2 * (C) Copyright 1997-2002 ELTEC Elektronik AG
3 * Frank Gottschling <fgottschling@eltec.de>
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator
29 * modification history
30 * --------------------
31 * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>.
33 * 18-03-2004 - Unify videomodes handling with the ct69000
34 * - The video output can be set via the variable "videoout"
36 * videoout=1 output on LCD
37 * videoout=2 output on CRT (default value)
38 * <p.aubert@staubli.com>
43 #if defined(CONFIG_VIDEO_SMI_LYNXEM)
47 #include "videomodes.h"
49 * Export Graphic Device
54 * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
56 #define VIDEO_MEM_SIZE 0x400000
62 #define SMI_INDX_C4 (pGD->isaBase + 0x03c4) /* index reg */
63 #define SMI_DATA_C5 (pGD->isaBase + 0x03c5) /* data reg */
64 #define SMI_INDX_D4 (pGD->isaBase + 0x03d4) /* index reg */
65 #define SMI_DATA_D5 (pGD->isaBase + 0x03d5) /* data reg */
66 #define SMI_ISR1 (pGD->isaBase + 0x03ca)
67 #define SMI_INDX_CE (pGD->isaBase + 0x03ce) /* index reg */
68 #define SMI_DATA_CF (pGD->isaBase + 0x03cf) /* data reg */
69 #define SMI_LOCK_REG (pGD->isaBase + 0x03c3) /* unlock/lock ext crt reg */
70 #define SMI_MISC_REG (pGD->isaBase + 0x03c2) /* misc reg */
71 #define SMI_LUT_MASK (pGD->isaBase + 0x03c6) /* lut mask reg */
72 #define SMI_LUT_START (pGD->isaBase + 0x03c8) /* lut start index */
73 #define SMI_LUT_RGB (pGD->isaBase + 0x03c9) /* lut colors auto incr.*/
74 #define SMI_INDX_ATTR (pGD->isaBase + 0x03c0) /* attributes index reg */
77 * Video processor control
81 unsigned int colorKey;
82 unsigned int colorKeyMask;
84 unsigned short offset;
86 unsigned int fifoPrio;
88 unsigned int YUVtoRGB;
92 * Video window control
97 unsigned short bottom;
99 unsigned int srcStart;
100 unsigned short width;
101 unsigned short offset;
102 unsigned char hStretch;
103 unsigned char vStretch;
107 * Capture port control
110 unsigned int control;
111 unsigned short topClip;
112 unsigned short leftClip;
113 unsigned short srcHeight;
114 unsigned short srcWidth;
115 unsigned int srcBufStart1;
116 unsigned int srcBufStart2;
117 unsigned short srcOffset;
118 unsigned short fifoControl;
123 * Register values for common video modes
125 static char SMI_SCR[] = {
127 0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x15, 0x90,
128 0x17, 0x20, 0x18, 0xb1, 0x19, 0x00,
130 static char SMI_EXT_CRT[] = {
131 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
132 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
134 static char SMI_ATTR [] = {
135 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05,
136 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b,
137 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x41, 0x11, 0x00,
138 0x12, 0x0f, 0x13, 0x00, 0x14, 0x00,
140 static char SMI_GCR[18] = {
141 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
142 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff
144 static char SMI_SEQR[] = {
145 0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03
147 static char SMI_PCR [] = {
148 0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00
150 static char SMI_MCR[] = {
151 0x60, 0x01, 0x61, 0x00,
154 static char SMI_HCR[] = {
155 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
156 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
160 /*******************************************************************************
162 * Write SMI ISA register
164 static void smiWrite (unsigned short index, char reg, char val)
166 register GraphicDevice *pGD = (GraphicDevice *)&smi;
168 out8 ((pGD->isaBase + index), reg);
169 out8 ((pGD->isaBase + index + 1), val);
172 /*******************************************************************************
174 * Write a table of SMI ISA register
176 static void smiLoadRegs (
183 register GraphicDevice *pGD = (GraphicDevice *)&smi;
186 for (i=0; i<tabSize; i+=2) {
187 if (iReg == SMI_INDX_ATTR) {
188 /* Reset the Flip Flop */
190 out8 (iReg, regTab[i]);
191 out8 (iReg, regTab[i+1]);
193 out8 (iReg, regTab[i]);
194 out8 (dReg, regTab[i+1]);
199 /*******************************************************************************
201 * Init capture port registers
203 static void smiInitCapturePort (void)
205 SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
206 register GraphicDevice *pGD = (GraphicDevice *)&smi;
207 register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
209 out32r ((pGD->cprBase + 0x0004), ((pCP->topClip<<16) | pCP->leftClip));
210 out32r ((pGD->cprBase + 0x0008), ((pCP->srcHeight<<16) | pCP->srcWidth));
211 out32r ((pGD->cprBase + 0x000c), pCP->srcBufStart1/8);
212 out32r ((pGD->cprBase + 0x0010), pCP->srcBufStart2/8);
213 out32r ((pGD->cprBase + 0x0014), pCP->srcOffset/8);
214 out32r ((pGD->cprBase + 0x0018), pCP->fifoControl);
215 out32r ((pGD->cprBase + 0x0000), pCP->control);
219 /*******************************************************************************
221 * Init video processor registers
223 static void smiInitVideoProcessor (void)
225 SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed };
226 SmiVideoWin smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 };
227 register GraphicDevice *pGD = (GraphicDevice *)&smi;
228 register SmiVideoProc *pVP = (SmiVideoProc *)&smiVP;
229 register SmiVideoWin *pVWin = (SmiVideoWin *)&smiVW;
231 pVP->width = pGD->plnSizeX * pGD->gdfBytesPP;
232 pVP->control |= pGD->gdfIndex << 16;
233 pVWin->bottom = pGD->winSizeY - 1;
234 pVWin->right = pGD->winSizeX - 1;
235 pVWin->width = pVP->width;
238 out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
241 out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
243 /* data src start adrs */
244 out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
246 /* data width and offset */
247 out32r ((pGD->vprBase + 0x0010),
248 ((pVP->offset / 8 * pGD->gdfBytesPP) << 16) |
249 (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
252 out32r ((pGD->vprBase + 0x0014),
253 ((pVWin->top << 16) | pVWin->left));
255 out32r ((pGD->vprBase + 0x0018),
256 ((pVWin->bottom << 16) | pVWin->right));
258 out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
260 out32r ((pGD->vprBase + 0x0020),
261 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
263 out32r ((pGD->vprBase + 0x0024),
264 (((pVWin->hStretch) << 8) | pVWin->vStretch));
267 out32r ((pGD->vprBase + 0x0028),
268 ((pVWin->top << 16) | pVWin->left));
270 out32r ((pGD->vprBase + 0x002c),
271 ((pVWin->bottom << 16) | pVWin->right));
273 out32r ((pGD->vprBase + 0x0030),
274 pVWin->srcStart / 8);
276 out32r ((pGD->vprBase + 0x0034),
277 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
279 out32r ((pGD->vprBase + 0x0038),
280 (((pVWin->hStretch) << 8) | pVWin->vStretch));
282 /* fifo prio control */
283 out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
285 /* fifo empty request levell */
286 out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
288 /* conversion constant */
289 out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
291 /* vpr control word */
292 out32r ((pGD->vprBase + 0x0000), pVP->control);
295 /******************************************************************************
297 * Init drawing engine registers
299 static void smiInitDrawingEngine (void)
301 GraphicDevice *pGD = (GraphicDevice *)&smi;
304 /* don't start now */
305 out32r ((pGD->dprBase + 0x000c), 0x000f0000);
307 /* set rop2 to copypen */
308 val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
309 out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
312 out32r ((pGD->dprBase + 0x002c), 0);
313 out32r ((pGD->dprBase + 0x0030),
314 ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
317 val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
318 out32r ((pGD->dprBase + 0x0010),
319 (val | pGD->plnSizeX * pGD->gdfBytesPP));
322 val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
323 out32r ((pGD->dprBase + 0x0010),
324 (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
326 /* window width src/dst */
327 out32r ((pGD->dprBase + 0x003c),
328 (((pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)<<16) |
329 (pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)));
330 out16r ((pGD->dprBase + 0x001e), 0x0000);
333 out32r ((pGD->dprBase + 0x0040),
334 (((pGD->frameAdrs/8) & 0x000fffff)));
337 out32r ((pGD->dprBase + 0x0044),
338 (((pGD->frameAdrs/8) & 0x000fffff)));
340 /* foreground color */
341 out32r ((pGD->dprBase + 0x0014), pGD->fg);
343 /* background color */
344 out32r ((pGD->dprBase + 0x0018), pGD->bg);
347 out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
350 out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
353 out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
355 /* load mono pattern */
356 out32r ((pGD->dprBase + 0x0034), 0);
357 out32r ((pGD->dprBase + 0x0038), 0);
360 static struct pci_device_id supported[] = {
361 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_710 },
362 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_712 },
363 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_810 },
367 /*****************************************************************************/
368 static void smiLoadMsr (struct ctfb_res_modes *mode)
370 unsigned char h_synch_high, v_synch_high;
371 register GraphicDevice *pGD = (GraphicDevice *)&smi;
373 h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40; /* horizontal Synch High active */
374 v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */
375 out8 (SMI_MISC_REG, (h_synch_high | v_synch_high | 0x29));
376 /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
377 * Selects the upper 64KB page.Bit5=1
378 * CLK2 (left reserved in standard VGA) Bit3|2=1|0
379 * Disables CPU access to frame buffer. Bit1=0
380 * Sets the I/O address decode for ST01, FCR, and all CR registers
381 * to the 3Dx I/O address range (CGA emulation). Bit0=1
384 /*****************************************************************************/
385 static void smiLoadCrt (struct ctfb_res_modes *var, int bits_per_pixel)
387 unsigned char cr[0x7a];
389 unsigned int hd, hs, he, ht, hbs, hbe; /* Horizontal. */
390 unsigned int vd, vs, ve, vt, vbs, vbe; /* vertical */
391 unsigned int bpp, wd, dblscan, interlaced;
393 const int LineCompare = 0x3ff;
394 unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor */
395 register GraphicDevice *pGD = (GraphicDevice *)&smi;
398 hd = (var->xres) / 8; /* HDisp. */
399 hs = (var->xres + var->right_margin) / 8; /* HsStrt */
400 he = (var->xres + var->right_margin + var->hsync_len) / 8; /* HsEnd */
401 ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8; /* HTotal */
404 hbe = 0; /* Blank end at 0 */
407 vd = var->yres; /* VDisplay */
408 vs = var->yres + var->lower_margin; /* VSyncStart */
409 ve = var->yres + var->lower_margin + var->vsync_len; /* VSyncEnd */
410 vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; /* VTotal */
414 bpp = bits_per_pixel;
415 dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
416 interlaced = var->vmode & FB_VMODE_INTERLACED;
421 wd = var->xres * bpp / 64; /* double words per line */
422 if (interlaced) { /* we divide all vertical timings, exept vd */
429 memset (cr, 0, sizeof (cr));
433 cr[0x03] = (hbe & 0x1F);
435 cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
437 cr[0x06] = (vt - 2) & 0xFF;
438 cr[0x07] = (((vt - 2) & 0x100) >> 8)
439 | (((vd - 1) & 0x100) >> 7)
440 | ((vs & 0x100) >> 6)
441 | (((vbs - 1) & 0x100) >> 5)
442 | ((LineCompare & 0x100) >> 4)
443 | (((vt - 2) & 0x200) >> 4)
444 | (((vd - 1) & 0x200) >> 3)
445 | ((vs & 0x200) >> 2);
447 cr[0x30] = ((vt - 2) & 0x400) >> 7
448 | (((vd - 1) & 0x400) >> 8)
449 | (((vbs - 1) & 0x400) >> 9)
450 | ((vs & 0x400) >> 10)
451 | (interlaced) ? 0x80 : 0;
455 cr[0x09] = (dblscan << 7)
456 | ((LineCompare & 0x200) >> 3)
457 | (((vbs - 1) & 0x200) >> 4)
458 | (TextScanLines - 1);
460 cr[0x10] = vs & 0xff; /* VSyncPulseStart */
461 cr[0x11] = (ve & 0x0f);
462 cr[0x12] = (vd - 1) & 0xff; /* LineCount */
463 cr[0x13] = wd & 0xff;
465 cr[0x15] = (vbs - 1) & 0xff;
466 cr[0x16] = vbe & 0xff;
467 cr[0x17] = 0xe3; /* but it does not work */
468 cr[0x18] = 0xff & LineCompare;
469 cr[0x22] = 0x00; /* todo? */
472 /* now set the registers */
473 for (i = 0; i <= 0x18; i++) { /*CR00 .. CR18 */
474 smiWrite (SMI_INDX_D4, i, cr[i]);
477 smiWrite (SMI_INDX_D4, i, cr[i]);
479 smiWrite (SMI_INDX_D4, i, cr[i]);
482 /*****************************************************************************/
483 #define REF_FREQ 14318180
489 static unsigned int FindPQ (unsigned int freq, unsigned int *pp, unsigned int *pq)
491 unsigned int n = QMIN, m = 0;
492 long long int L = 0, P = freq, Q = REF_FREQ, H = P >> 1;
493 long long int D = 0x7ffffffffffffffLL;
495 for (n = QMIN; n <= QMAX; n++) {
496 m = PMIN; /* p/q ~ freq/ref -> p*ref-freq*q ~ 0 */
498 while (L > 0 && m < PMAX) {
499 L -= REF_FREQ; /* difference is greater as 0 subtract fref */
500 m++; /* and increment m */
502 /* difference is less or equal than 0 or m > maximum */
504 break; /* no solution: if we increase n we get the same situation */
506 if (-L > H && m > PMIN) { /* if difference > the half fref */
507 L += REF_FREQ; /* we take the situation before */
508 m--; /* because its closer to 0 */
510 L = (L < 0) ? -L : +L; /* absolute value */
511 if (D < L) /* if last difference was better take next n */
515 *pq = n; /* keep improved data */
517 break; /* best result we can get */
519 return (unsigned int) (0xffffffff & D);
522 /*****************************************************************************/
523 static void smiLoadCcr (struct ctfb_res_modes *var, unsigned short device_id)
527 register GraphicDevice *pGD = (GraphicDevice *)&smi;
529 smiWrite (SMI_INDX_C4, 0x65, 0);
530 smiWrite (SMI_INDX_C4, 0x66, 0);
531 smiWrite (SMI_INDX_C4, 0x68, 0x50);
532 if (device_id == PCI_DEVICE_ID_SMI_810) {
533 smiWrite (SMI_INDX_C4, 0x69, 0x3);
535 smiWrite (SMI_INDX_C4, 0x69, 0x0);
540 case PCI_DEVICE_ID_SMI_710 :
541 smiWrite (SMI_INDX_C4, 0x6a, 0x75);
543 case PCI_DEVICE_ID_SMI_712 :
544 smiWrite (SMI_INDX_C4, 0x6a, 0x80);
547 smiWrite (SMI_INDX_C4, 0x6a, 0x53);
550 smiWrite (SMI_INDX_C4, 0x6b, 0x15);
553 freq = 1000000000000LL / var -> pixclock;
555 FindPQ ((unsigned int)freq, &p, &q);
557 smiWrite (SMI_INDX_C4, 0x6c, p);
558 smiWrite (SMI_INDX_C4, 0x6d, q);
562 /*******************************************************************************
564 * Init video chip with common Linux graphic modes (lilo)
566 void *video_hw_init (void)
568 GraphicDevice *pGD = (GraphicDevice *)&smi;
569 unsigned short device_id;
572 unsigned long t1, hsynch, vsynch;
573 unsigned int pci_mem_base, *vm;
575 int tmp, i, bits_per_pixel;
576 struct ctfb_res_modes *res_mode;
577 struct ctfb_res_modes var_mode;
578 unsigned char videoout;
580 /* Search for video chip */
583 if ((devbusfn = pci_find_devices(supported, 0)) < 0)
585 printf ("Controller not found !\n");
590 pci_write_config_dword (devbusfn, PCI_COMMAND, (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
591 pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
592 pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
593 pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
597 videomode = CFG_DEFAULT_VIDEO_MODE;
598 /* get video mode via environment */
599 if ((penv = getenv ("videomode")) != NULL) {
600 /* deceide if it is a string */
601 if (penv[0] <= '9') {
602 videomode = (int) simple_strtoul (penv, NULL, 16);
609 /* parameter are vesa modes */
611 for (i = 0; i < VESA_MODES_COUNT; i++) {
612 if (vesa_modes[i].vesanr == videomode)
615 if (i == VESA_MODES_COUNT) {
616 printf ("no VESA Mode found, switching to mode 0x%x ", CFG_DEFAULT_VIDEO_MODE);
620 (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
622 bits_per_pixel = vesa_modes[i].bits_per_pixel;
625 res_mode = (struct ctfb_res_modes *) &var_mode;
626 bits_per_pixel = video_get_params (res_mode, penv);
629 /* calculate hsynch and vsynch freq (info only) */
630 t1 = (res_mode->left_margin + res_mode->xres +
631 res_mode->right_margin + res_mode->hsync_len) / 8;
633 t1 *= res_mode->pixclock;
635 hsynch = 1000000000L / t1;
637 (res_mode->upper_margin + res_mode->yres +
638 res_mode->lower_margin + res_mode->vsync_len);
640 vsynch = 1000000000L / t1;
642 /* fill in Graphic device struct */
643 sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
644 res_mode->yres, bits_per_pixel, (hsynch / 1000),
646 printf ("%s\n", pGD->modeIdent);
647 pGD->winSizeX = res_mode->xres;
648 pGD->winSizeY = res_mode->yres;
649 pGD->plnSizeX = res_mode->xres;
650 pGD->plnSizeY = res_mode->yres;
651 switch (bits_per_pixel) {
654 pGD->gdfIndex = GDF__8BIT_INDEX;
658 pGD->gdfIndex = GDF_15BIT_555RGB;
662 pGD->gdfIndex = GDF_16BIT_565RGB;
666 pGD->gdfIndex = GDF_24BIT_888RGB;
670 pGD->isaBase = CFG_ISA_IO;
671 pGD->pciBase = pci_mem_base;
672 pGD->dprBase = (pci_mem_base + 0x400000 + 0x8000);
673 pGD->vprBase = (pci_mem_base + 0x400000 + 0xc000);
674 pGD->cprBase = (pci_mem_base + 0x400000 + 0xe000);
675 pGD->frameAdrs = pci_mem_base;
676 pGD->memSize = VIDEO_MEM_SIZE;
678 /* Set up hardware : select color mode,
679 set Register base to isa 3dx for 3?x regs*/
680 out8 (SMI_MISC_REG, 0x01);
682 /* Turn off display */
683 smiWrite (SMI_INDX_C4, 0x01, 0x20);
685 /* Unlock ext. crt regs */
686 out8 (SMI_LOCK_REG, 0x40);
688 /* Unlock crt regs 0-7 */
689 smiWrite (SMI_INDX_D4, 0x11, 0x0e);
691 /* Sytem Control Register */
692 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SCR, sizeof(SMI_SCR));
694 /* extented CRT Register */
695 smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, SMI_EXT_CRT, sizeof(SMI_EXT_CRT));
697 /* Attributes controller registers */
698 smiLoadRegs (SMI_INDX_ATTR, SMI_INDX_ATTR, SMI_ATTR, sizeof(SMI_ATTR));
700 /* Graphics Controller Register */
701 smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF, SMI_GCR, sizeof(SMI_GCR));
703 /* Sequencer Register */
704 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SEQR, sizeof(SMI_SEQR));
706 /* Power Control Register */
707 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_PCR, sizeof(SMI_PCR));
709 /* Memory Control Register */
710 /* Register MSR62 is a power on configurable register. We don't */
712 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_MCR, sizeof(SMI_MCR));
714 /* Set misc output register */
715 smiLoadMsr (res_mode);
717 /* Set CRT and Clock control registers */
718 smiLoadCrt (res_mode, bits_per_pixel);
720 smiLoadCcr (res_mode, device_id);
722 /* Hardware Cusor Register */
723 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_HCR, sizeof(SMI_HCR));
726 videoout = 2; /* Default output is CRT */
727 if ((penv = getenv ("videoout")) != NULL) {
728 /* deceide if it is a string */
729 videoout = (int) simple_strtoul (penv, NULL, 16);
731 smiWrite (SMI_INDX_C4, 0x31, videoout);
733 /* Video processor default setup */
734 smiInitVideoProcessor ();
736 /* Capture port default setup */
737 smiInitCapturePort ();
739 /* Drawing engine default setup */
740 smiInitDrawingEngine ();
742 /* Turn on display */
743 smiWrite (0x3c4, 0x01, 0x01);
745 /* Clear video memory */
747 vm = (unsigned int *)pGD->pciBase;
750 return ((void*)&smi);
753 /*******************************************************************************
755 * Drawing engine fill on screen region
757 void video_hw_rectfill (
758 unsigned int bpp, /* bytes per pixel */
759 unsigned int dst_x, /* dest pos x */
760 unsigned int dst_y, /* dest pos y */
761 unsigned int dim_x, /* frame width */
762 unsigned int dim_y, /* frame height */
763 unsigned int color /* fill color */
766 register GraphicDevice *pGD = (GraphicDevice *)&smi;
767 register unsigned int control;
771 out32r ((pGD->dprBase + 0x0014), color);
772 out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
773 out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
775 control = 0x0000ffff & in32r ((pGD->dprBase + 0x000c));
777 control |= 0x80010000;
779 out32r ((pGD->dprBase + 0x000c), control);
781 /* Wait for drawing processor */
784 out8 ((pGD->isaBase + 0x3c4), 0x16);
785 } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
788 /*******************************************************************************
790 * Drawing engine bitblt with screen region
792 void video_hw_bitblt (
793 unsigned int bpp, /* bytes per pixel */
794 unsigned int src_x, /* source pos x */
795 unsigned int src_y, /* source pos y */
796 unsigned int dst_x, /* dest pos x */
797 unsigned int dst_y, /* dest pos y */
798 unsigned int dim_x, /* frame width */
799 unsigned int dim_y /* frame height */
802 register GraphicDevice *pGD = (GraphicDevice *)&smi;
803 register unsigned int control;
807 if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x)))
809 out32r ((pGD->dprBase + 0x0000), (((src_x+dim_x-1)<<16) | (src_y+dim_y-1)));
810 out32r ((pGD->dprBase + 0x0004), (((dst_x+dim_x-1)<<16) | (dst_y+dim_y-1)));
811 control = 0x88000000;
813 out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y));
814 out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
815 control = 0x80000000;
818 out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
819 control |= (0x0000ffff & in32r ((pGD->dprBase + 0x000c)));
820 out32r ((pGD->dprBase + 0x000c), control);
822 /* Wait for drawing processor */
825 out8 ((pGD->isaBase + 0x3c4), 0x16);
826 } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
829 /*******************************************************************************
831 * Set a RGB color in the LUT (8 bit index)
834 unsigned int index, /* color number */
835 unsigned char r, /* red */
836 unsigned char g, /* green */
837 unsigned char b /* blue */
840 register GraphicDevice *pGD = (GraphicDevice *)&smi;
842 out8 (SMI_LUT_MASK, 0xff);
844 out8 (SMI_LUT_START, (char)index);
846 out8 (SMI_LUT_RGB, r>>2); /* red */
848 out8 (SMI_LUT_RGB, g>>2); /* green */
850 out8 (SMI_LUT_RGB, b>>2); /* blue */
854 #endif /* CONFIG_VIDEO_SMI_LYNXEM */