2 * (C) Copyright 1997-2002 ELTEC Elektronik AG
3 * Frank Gottschling <fgottschling@eltec.de>
5 * SPDX-License-Identifier: GPL-2.0+
11 * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator
13 * modification history
14 * --------------------
15 * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>.
17 * 18-03-2004 - Unify videomodes handling with the ct69000
18 * - The video output can be set via the variable "videoout"
20 * videoout=1 output on LCD
21 * videoout=2 output on CRT (default value)
22 * <p.aubert@staubli.com>
29 #include "videomodes.h"
31 * Export Graphic Device
36 * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
38 #define VIDEO_MEM_SIZE 0x400000
44 #define SMI_INDX_C4 (pGD->isaBase + 0x03c4) /* index reg */
45 #define SMI_DATA_C5 (pGD->isaBase + 0x03c5) /* data reg */
46 #define SMI_INDX_D4 (pGD->isaBase + 0x03d4) /* index reg */
47 #define SMI_DATA_D5 (pGD->isaBase + 0x03d5) /* data reg */
48 #define SMI_ISR1 (pGD->isaBase + 0x03ca)
49 #define SMI_INDX_CE (pGD->isaBase + 0x03ce) /* index reg */
50 #define SMI_DATA_CF (pGD->isaBase + 0x03cf) /* data reg */
51 #define SMI_LOCK_REG (pGD->isaBase + 0x03c3) /* unlock/lock ext crt reg */
52 #define SMI_MISC_REG (pGD->isaBase + 0x03c2) /* misc reg */
53 #define SMI_LUT_MASK (pGD->isaBase + 0x03c6) /* lut mask reg */
54 #define SMI_LUT_START (pGD->isaBase + 0x03c8) /* lut start index */
55 #define SMI_LUT_RGB (pGD->isaBase + 0x03c9) /* lut colors auto incr.*/
56 #define SMI_INDX_ATTR (pGD->isaBase + 0x03c0) /* attributes index reg */
59 * Video processor control
63 unsigned int colorKey;
64 unsigned int colorKeyMask;
66 unsigned short offset;
68 unsigned int fifoPrio;
70 unsigned int YUVtoRGB;
74 * Video window control
79 unsigned short bottom;
81 unsigned int srcStart;
83 unsigned short offset;
84 unsigned char hStretch;
85 unsigned char vStretch;
89 * Capture port control
93 unsigned short topClip;
94 unsigned short leftClip;
95 unsigned short srcHeight;
96 unsigned short srcWidth;
97 unsigned int srcBufStart1;
98 unsigned int srcBufStart2;
99 unsigned short srcOffset;
100 unsigned short fifoControl;
105 * Register values for common video modes
107 static char SMI_SCR[] = {
109 0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x15, 0x90,
110 0x17, 0x20, 0x18, 0xb1, 0x19, 0x00,
112 static char SMI_EXT_CRT[] = {
113 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
114 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00,
116 static char SMI_ATTR [] = {
117 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05,
118 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b,
119 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x41, 0x11, 0x00,
120 0x12, 0x0f, 0x13, 0x00, 0x14, 0x00,
122 static char SMI_GCR[18] = {
123 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
124 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff,
126 static char SMI_SEQR[] = {
127 0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03,
129 static char SMI_PCR [] = {
130 0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00,
132 static char SMI_MCR[] = {
133 0x60, 0x01, 0x61, 0x00,
134 #ifdef CONFIG_HMI1001
135 0x62, 0x74, /* Memory type is not configured by pins on HMI1001 */
139 static char SMI_HCR[] = {
140 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
141 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00,
145 /*******************************************************************************
147 * Write SMI ISA register
149 static void smiWrite (unsigned short index, char reg, char val)
151 register GraphicDevice *pGD = (GraphicDevice *)&smi;
153 out8 ((pGD->isaBase + index), reg);
154 out8 ((pGD->isaBase + index + 1), val);
157 /*******************************************************************************
159 * Write a table of SMI ISA register
161 static void smiLoadRegs (
168 register GraphicDevice *pGD = (GraphicDevice *)&smi;
171 for (i=0; i<tabSize; i+=2) {
172 if (iReg == SMI_INDX_ATTR) {
173 /* Reset the Flip Flop */
175 out8 (iReg, regTab[i]);
176 out8 (iReg, regTab[i+1]);
178 out8 (iReg, regTab[i]);
179 out8 (dReg, regTab[i+1]);
184 /*******************************************************************************
186 * Init capture port registers
188 static void smiInitCapturePort (void)
190 SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
191 register GraphicDevice *pGD = (GraphicDevice *)&smi;
192 register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
194 out32r ((pGD->cprBase + 0x0004), ((pCP->topClip<<16) | pCP->leftClip));
195 out32r ((pGD->cprBase + 0x0008), ((pCP->srcHeight<<16) | pCP->srcWidth));
196 out32r ((pGD->cprBase + 0x000c), pCP->srcBufStart1/8);
197 out32r ((pGD->cprBase + 0x0010), pCP->srcBufStart2/8);
198 out32r ((pGD->cprBase + 0x0014), pCP->srcOffset/8);
199 out32r ((pGD->cprBase + 0x0018), pCP->fifoControl);
200 out32r ((pGD->cprBase + 0x0000), pCP->control);
204 /*******************************************************************************
206 * Init video processor registers
208 static void smiInitVideoProcessor (void)
210 SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed };
211 SmiVideoWin smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 };
212 register GraphicDevice *pGD = (GraphicDevice *)&smi;
213 register SmiVideoProc *pVP = (SmiVideoProc *)&smiVP;
214 register SmiVideoWin *pVWin = (SmiVideoWin *)&smiVW;
216 pVP->width = pGD->plnSizeX * pGD->gdfBytesPP;
217 pVP->control |= pGD->gdfIndex << 16;
218 pVWin->bottom = pGD->winSizeY - 1;
219 pVWin->right = pGD->winSizeX - 1;
220 pVWin->width = pVP->width;
223 out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
226 out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
228 /* data src start adrs */
229 out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
231 /* data width and offset */
232 out32r ((pGD->vprBase + 0x0010),
233 ((pVP->offset / 8 * pGD->gdfBytesPP) << 16) |
234 (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
237 out32r ((pGD->vprBase + 0x0014),
238 ((pVWin->top << 16) | pVWin->left));
240 out32r ((pGD->vprBase + 0x0018),
241 ((pVWin->bottom << 16) | pVWin->right));
243 out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
245 out32r ((pGD->vprBase + 0x0020),
246 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
248 out32r ((pGD->vprBase + 0x0024),
249 (((pVWin->hStretch) << 8) | pVWin->vStretch));
252 out32r ((pGD->vprBase + 0x0028),
253 ((pVWin->top << 16) | pVWin->left));
255 out32r ((pGD->vprBase + 0x002c),
256 ((pVWin->bottom << 16) | pVWin->right));
258 out32r ((pGD->vprBase + 0x0030),
259 pVWin->srcStart / 8);
261 out32r ((pGD->vprBase + 0x0034),
262 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
264 out32r ((pGD->vprBase + 0x0038),
265 (((pVWin->hStretch) << 8) | pVWin->vStretch));
267 /* fifo prio control */
268 out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
270 /* fifo empty request levell */
271 out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
273 /* conversion constant */
274 out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
276 /* vpr control word */
277 out32r ((pGD->vprBase + 0x0000), pVP->control);
280 /******************************************************************************
282 * Init drawing engine registers
284 static void smiInitDrawingEngine (void)
286 GraphicDevice *pGD = (GraphicDevice *)&smi;
289 /* don't start now */
290 out32r ((pGD->dprBase + 0x000c), 0x000f0000);
292 /* set rop2 to copypen */
293 val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
294 out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
297 out32r ((pGD->dprBase + 0x002c), 0);
298 out32r ((pGD->dprBase + 0x0030),
299 ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
302 val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
303 out32r ((pGD->dprBase + 0x0010),
304 (val | pGD->plnSizeX * pGD->gdfBytesPP));
307 val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
308 out32r ((pGD->dprBase + 0x0010),
309 (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
311 /* window width src/dst */
312 out32r ((pGD->dprBase + 0x003c),
313 (((pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)<<16) |
314 (pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)));
315 out16r ((pGD->dprBase + 0x001e), 0x0000);
318 out32r ((pGD->dprBase + 0x0040),
319 (((pGD->frameAdrs/8) & 0x000fffff)));
322 out32r ((pGD->dprBase + 0x0044),
323 (((pGD->frameAdrs/8) & 0x000fffff)));
325 /* foreground color */
326 out32r ((pGD->dprBase + 0x0014), pGD->fg);
328 /* background color */
329 out32r ((pGD->dprBase + 0x0018), pGD->bg);
332 out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
335 out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
338 out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
340 /* load mono pattern */
341 out32r ((pGD->dprBase + 0x0034), 0);
342 out32r ((pGD->dprBase + 0x0038), 0);
345 static struct pci_device_id supported[] = {
346 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_710 },
347 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_712 },
348 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_810 },
352 /*****************************************************************************/
353 static void smiLoadMsr (struct ctfb_res_modes *mode)
355 unsigned char h_synch_high, v_synch_high;
356 register GraphicDevice *pGD = (GraphicDevice *)&smi;
358 h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40; /* horizontal Synch High active */
359 v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */
360 out8 (SMI_MISC_REG, (h_synch_high | v_synch_high | 0x29));
361 /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
362 * Selects the upper 64KB page.Bit5=1
363 * CLK2 (left reserved in standard VGA) Bit3|2=1|0
364 * Disables CPU access to frame buffer. Bit1=0
365 * Sets the I/O address decode for ST01, FCR, and all CR registers
366 * to the 3Dx I/O address range (CGA emulation). Bit0=1
369 /*****************************************************************************/
370 static void smiLoadCrt (struct ctfb_res_modes *var, int bits_per_pixel)
372 unsigned char cr[0x7a];
374 unsigned int hd, hs, he, ht, hbs, hbe; /* Horizontal. */
375 unsigned int vd, vs, ve, vt, vbs, vbe; /* vertical */
376 unsigned int bpp, wd, dblscan, interlaced;
378 const int LineCompare = 0x3ff;
379 unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor */
380 register GraphicDevice *pGD = (GraphicDevice *)&smi;
383 hd = (var->xres) / 8; /* HDisp. */
384 hs = (var->xres + var->right_margin) / 8; /* HsStrt */
385 he = (var->xres + var->right_margin + var->hsync_len) / 8; /* HsEnd */
386 ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8; /* HTotal */
389 hbe = 0; /* Blank end at 0 */
392 vd = var->yres; /* VDisplay */
393 vs = var->yres + var->lower_margin; /* VSyncStart */
394 ve = var->yres + var->lower_margin + var->vsync_len; /* VSyncEnd */
395 vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; /* VTotal */
399 bpp = bits_per_pixel;
400 dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
401 interlaced = var->vmode & FB_VMODE_INTERLACED;
406 wd = var->xres * bpp / 64; /* double words per line */
407 if (interlaced) { /* we divide all vertical timings, exept vd */
414 memset (cr, 0, sizeof (cr));
418 cr[0x03] = (hbe & 0x1F);
420 cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
422 cr[0x06] = (vt - 2) & 0xFF;
423 cr[0x07] = (((vt - 2) & 0x100) >> 8)
424 | (((vd - 1) & 0x100) >> 7)
425 | ((vs & 0x100) >> 6)
426 | (((vbs - 1) & 0x100) >> 5)
427 | ((LineCompare & 0x100) >> 4)
428 | (((vt - 2) & 0x200) >> 4)
429 | (((vd - 1) & 0x200) >> 3)
430 | ((vs & 0x200) >> 2);
432 cr[0x30] = ((vt - 2) & 0x400) >> 7
433 | (((vd - 1) & 0x400) >> 8)
434 | (((vbs - 1) & 0x400) >> 9)
435 | ((vs & 0x400) >> 10)
436 | (interlaced) ? 0x80 : 0;
440 cr[0x09] = (dblscan << 7)
441 | ((LineCompare & 0x200) >> 3)
442 | (((vbs - 1) & 0x200) >> 4)
443 | (TextScanLines - 1);
445 cr[0x10] = vs & 0xff; /* VSyncPulseStart */
446 cr[0x11] = (ve & 0x0f);
447 cr[0x12] = (vd - 1) & 0xff; /* LineCount */
448 cr[0x13] = wd & 0xff;
450 cr[0x15] = (vbs - 1) & 0xff;
451 cr[0x16] = vbe & 0xff;
452 cr[0x17] = 0xe3; /* but it does not work */
453 cr[0x18] = 0xff & LineCompare;
454 cr[0x22] = 0x00; /* todo? */
457 /* now set the registers */
458 for (i = 0; i <= 0x18; i++) { /*CR00 .. CR18 */
459 smiWrite (SMI_INDX_D4, i, cr[i]);
462 smiWrite (SMI_INDX_D4, i, cr[i]);
464 smiWrite (SMI_INDX_D4, i, cr[i]);
467 /*****************************************************************************/
468 #define REF_FREQ 14318180
474 static unsigned int FindPQ (unsigned int freq, unsigned int *pp, unsigned int *pq)
476 unsigned int n = QMIN, m = 0;
477 long long int L = 0, P = freq, Q = REF_FREQ, H = P >> 1;
478 long long int D = 0x7ffffffffffffffLL;
480 for (n = QMIN; n <= QMAX; n++) {
481 m = PMIN; /* p/q ~ freq/ref -> p*ref-freq*q ~ 0 */
483 while (L > 0 && m < PMAX) {
484 L -= REF_FREQ; /* difference is greater as 0 subtract fref */
485 m++; /* and increment m */
487 /* difference is less or equal than 0 or m > maximum */
489 break; /* no solution: if we increase n we get the same situation */
491 if (-L > H && m > PMIN) { /* if difference > the half fref */
492 L += REF_FREQ; /* we take the situation before */
493 m--; /* because its closer to 0 */
495 L = (L < 0) ? -L : +L; /* absolute value */
496 if (D < L) /* if last difference was better take next n */
500 *pq = n; /* keep improved data */
502 break; /* best result we can get */
504 return (unsigned int) (0xffffffff & D);
507 /*****************************************************************************/
508 static void smiLoadCcr (struct ctfb_res_modes *var, unsigned short device_id)
513 register GraphicDevice *pGD = (GraphicDevice *)&smi;
515 smiWrite (SMI_INDX_C4, 0x65, 0);
516 smiWrite (SMI_INDX_C4, 0x66, 0);
517 smiWrite (SMI_INDX_C4, 0x68, 0x50);
518 if (device_id == PCI_DEVICE_ID_SMI_810) {
519 smiWrite (SMI_INDX_C4, 0x69, 0x3);
521 smiWrite (SMI_INDX_C4, 0x69, 0x0);
526 case PCI_DEVICE_ID_SMI_710 :
527 smiWrite (SMI_INDX_C4, 0x6a, 0x75);
529 case PCI_DEVICE_ID_SMI_712 :
530 smiWrite (SMI_INDX_C4, 0x6a, 0x80);
533 smiWrite (SMI_INDX_C4, 0x6a, 0x53);
536 smiWrite (SMI_INDX_C4, 0x6b, 0x15);
539 freq = 1000000000000LL / var -> pixclock;
541 FindPQ ((unsigned int)freq, &p, &q);
543 smiWrite (SMI_INDX_C4, 0x6c, p);
544 smiWrite (SMI_INDX_C4, 0x6d, q);
548 /*******************************************************************************
550 * Init video chip with common Linux graphic modes (lilo)
552 void *video_hw_init (void)
554 GraphicDevice *pGD = (GraphicDevice *)&smi;
555 unsigned short device_id;
558 unsigned long t1, hsynch, vsynch;
559 unsigned int pci_mem_base, *vm;
561 int tmp, i, bits_per_pixel;
562 struct ctfb_res_modes *res_mode;
563 struct ctfb_res_modes var_mode;
564 unsigned char videoout;
566 /* Search for video chip */
569 if ((devbusfn = pci_find_devices(supported, 0)) < 0)
571 printf ("Controller not found !\n");
576 pci_write_config_dword (devbusfn, PCI_COMMAND, (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
577 pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
578 pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
579 pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
583 videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE;
584 /* get video mode via environment */
585 if ((penv = getenv ("videomode")) != NULL) {
586 /* deceide if it is a string */
587 if (penv[0] <= '9') {
588 videomode = (int) simple_strtoul (penv, NULL, 16);
595 /* parameter are vesa modes */
597 for (i = 0; i < VESA_MODES_COUNT; i++) {
598 if (vesa_modes[i].vesanr == videomode)
601 if (i == VESA_MODES_COUNT) {
602 printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE);
606 (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
608 bits_per_pixel = vesa_modes[i].bits_per_pixel;
611 res_mode = (struct ctfb_res_modes *) &var_mode;
612 bits_per_pixel = video_get_params (res_mode, penv);
615 /* calculate hsynch and vsynch freq (info only) */
616 t1 = (res_mode->left_margin + res_mode->xres +
617 res_mode->right_margin + res_mode->hsync_len) / 8;
619 t1 *= res_mode->pixclock;
621 hsynch = 1000000000L / t1;
623 (res_mode->upper_margin + res_mode->yres +
624 res_mode->lower_margin + res_mode->vsync_len);
626 vsynch = 1000000000L / t1;
628 /* fill in Graphic device struct */
629 sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
630 res_mode->yres, bits_per_pixel, (hsynch / 1000),
632 printf ("%s\n", pGD->modeIdent);
633 pGD->winSizeX = res_mode->xres;
634 pGD->winSizeY = res_mode->yres;
635 pGD->plnSizeX = res_mode->xres;
636 pGD->plnSizeY = res_mode->yres;
637 switch (bits_per_pixel) {
640 pGD->gdfIndex = GDF__8BIT_INDEX;
644 pGD->gdfIndex = GDF_15BIT_555RGB;
648 pGD->gdfIndex = GDF_16BIT_565RGB;
652 pGD->gdfIndex = GDF_24BIT_888RGB;
656 pGD->isaBase = CONFIG_SYS_ISA_IO;
657 pGD->pciBase = pci_mem_base;
658 pGD->dprBase = (pci_mem_base + 0x400000 + 0x8000);
659 pGD->vprBase = (pci_mem_base + 0x400000 + 0xc000);
660 pGD->cprBase = (pci_mem_base + 0x400000 + 0xe000);
661 pGD->frameAdrs = pci_mem_base;
662 pGD->memSize = VIDEO_MEM_SIZE;
664 /* Set up hardware : select color mode,
665 set Register base to isa 3dx for 3?x regs*/
666 out8 (SMI_MISC_REG, 0x01);
668 /* Turn off display */
669 smiWrite (SMI_INDX_C4, 0x01, 0x20);
671 /* Unlock ext. crt regs */
672 out8 (SMI_LOCK_REG, 0x40);
674 /* Unlock crt regs 0-7 */
675 smiWrite (SMI_INDX_D4, 0x11, 0x0e);
677 /* Sytem Control Register */
678 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SCR, sizeof(SMI_SCR));
680 /* extented CRT Register */
681 smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, SMI_EXT_CRT, sizeof(SMI_EXT_CRT));
683 /* Attributes controller registers */
684 smiLoadRegs (SMI_INDX_ATTR, SMI_INDX_ATTR, SMI_ATTR, sizeof(SMI_ATTR));
686 /* Graphics Controller Register */
687 smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF, SMI_GCR, sizeof(SMI_GCR));
689 /* Sequencer Register */
690 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SEQR, sizeof(SMI_SEQR));
692 /* Power Control Register */
693 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_PCR, sizeof(SMI_PCR));
695 /* Memory Control Register */
696 /* Register MSR62 is a power on configurable register. We don't */
698 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_MCR, sizeof(SMI_MCR));
700 /* Set misc output register */
701 smiLoadMsr (res_mode);
703 /* Set CRT and Clock control registers */
704 smiLoadCrt (res_mode, bits_per_pixel);
706 smiLoadCcr (res_mode, device_id);
708 /* Hardware Cusor Register */
709 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_HCR, sizeof(SMI_HCR));
712 videoout = 2; /* Default output is CRT */
713 if ((penv = getenv ("videoout")) != NULL) {
714 /* deceide if it is a string */
715 videoout = (int) simple_strtoul (penv, NULL, 16);
717 smiWrite (SMI_INDX_C4, 0x31, videoout);
719 /* Video processor default setup */
720 smiInitVideoProcessor ();
722 /* Capture port default setup */
723 smiInitCapturePort ();
725 /* Drawing engine default setup */
726 smiInitDrawingEngine ();
728 /* Turn on display */
729 smiWrite (0x3c4, 0x01, 0x01);
731 /* Clear video memory */
733 vm = (unsigned int *)pGD->pciBase;
736 return ((void*)&smi);
739 /*******************************************************************************
741 * Drawing engine fill on screen region
743 void video_hw_rectfill (
744 unsigned int bpp, /* bytes per pixel */
745 unsigned int dst_x, /* dest pos x */
746 unsigned int dst_y, /* dest pos y */
747 unsigned int dim_x, /* frame width */
748 unsigned int dim_y, /* frame height */
749 unsigned int color /* fill color */
752 register GraphicDevice *pGD = (GraphicDevice *)&smi;
753 register unsigned int control;
757 out32r ((pGD->dprBase + 0x0014), color);
758 out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
759 out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
761 control = 0x0000ffff & in32r ((pGD->dprBase + 0x000c));
763 control |= 0x80010000;
765 out32r ((pGD->dprBase + 0x000c), control);
767 /* Wait for drawing processor */
770 out8 ((pGD->isaBase + 0x3c4), 0x16);
771 } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
774 /*******************************************************************************
776 * Drawing engine bitblt with screen region
778 void video_hw_bitblt (
779 unsigned int bpp, /* bytes per pixel */
780 unsigned int src_x, /* source pos x */
781 unsigned int src_y, /* source pos y */
782 unsigned int dst_x, /* dest pos x */
783 unsigned int dst_y, /* dest pos y */
784 unsigned int dim_x, /* frame width */
785 unsigned int dim_y /* frame height */
788 register GraphicDevice *pGD = (GraphicDevice *)&smi;
789 register unsigned int control;
793 if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x)))
795 out32r ((pGD->dprBase + 0x0000), (((src_x+dim_x-1)<<16) | (src_y+dim_y-1)));
796 out32r ((pGD->dprBase + 0x0004), (((dst_x+dim_x-1)<<16) | (dst_y+dim_y-1)));
797 control = 0x88000000;
799 out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y));
800 out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
801 control = 0x80000000;
804 out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
805 control |= (0x0000ffff & in32r ((pGD->dprBase + 0x000c)));
806 out32r ((pGD->dprBase + 0x000c), control);
808 /* Wait for drawing processor */
811 out8 ((pGD->isaBase + 0x3c4), 0x16);
812 } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
815 /*******************************************************************************
817 * Set a RGB color in the LUT (8 bit index)
820 unsigned int index, /* color number */
821 unsigned char r, /* red */
822 unsigned char g, /* green */
823 unsigned char b /* blue */
826 register GraphicDevice *pGD = (GraphicDevice *)&smi;
828 out8 (SMI_LUT_MASK, 0xff);
830 out8 (SMI_LUT_START, (char)index);
832 out8 (SMI_LUT_RGB, r>>2); /* red */
834 out8 (SMI_LUT_RGB, g>>2); /* green */
836 out8 (SMI_LUT_RGB, b>>2); /* blue */