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,
136 static char SMI_HCR[] = {
137 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
138 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00,
142 /*******************************************************************************
144 * Write SMI ISA register
146 static void smiWrite (unsigned short index, char reg, char val)
148 register GraphicDevice *pGD = (GraphicDevice *)&smi;
150 out8 ((pGD->isaBase + index), reg);
151 out8 ((pGD->isaBase + index + 1), val);
154 /*******************************************************************************
156 * Write a table of SMI ISA register
158 static void smiLoadRegs (
165 register GraphicDevice *pGD = (GraphicDevice *)&smi;
168 for (i=0; i<tabSize; i+=2) {
169 if (iReg == SMI_INDX_ATTR) {
170 /* Reset the Flip Flop */
172 out8 (iReg, regTab[i]);
173 out8 (iReg, regTab[i+1]);
175 out8 (iReg, regTab[i]);
176 out8 (dReg, regTab[i+1]);
181 /*******************************************************************************
183 * Init capture port registers
185 static void smiInitCapturePort (void)
187 SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
188 register GraphicDevice *pGD = (GraphicDevice *)&smi;
189 register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
191 out32r ((pGD->cprBase + 0x0004), ((pCP->topClip<<16) | pCP->leftClip));
192 out32r ((pGD->cprBase + 0x0008), ((pCP->srcHeight<<16) | pCP->srcWidth));
193 out32r ((pGD->cprBase + 0x000c), pCP->srcBufStart1/8);
194 out32r ((pGD->cprBase + 0x0010), pCP->srcBufStart2/8);
195 out32r ((pGD->cprBase + 0x0014), pCP->srcOffset/8);
196 out32r ((pGD->cprBase + 0x0018), pCP->fifoControl);
197 out32r ((pGD->cprBase + 0x0000), pCP->control);
201 /*******************************************************************************
203 * Init video processor registers
205 static void smiInitVideoProcessor (void)
207 SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed };
208 SmiVideoWin smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 };
209 register GraphicDevice *pGD = (GraphicDevice *)&smi;
210 register SmiVideoProc *pVP = (SmiVideoProc *)&smiVP;
211 register SmiVideoWin *pVWin = (SmiVideoWin *)&smiVW;
213 pVP->width = pGD->plnSizeX * pGD->gdfBytesPP;
214 pVP->control |= pGD->gdfIndex << 16;
215 pVWin->bottom = pGD->winSizeY - 1;
216 pVWin->right = pGD->winSizeX - 1;
217 pVWin->width = pVP->width;
220 out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
223 out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
225 /* data src start adrs */
226 out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
228 /* data width and offset */
229 out32r ((pGD->vprBase + 0x0010),
230 ((pVP->offset / 8 * pGD->gdfBytesPP) << 16) |
231 (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
234 out32r ((pGD->vprBase + 0x0014),
235 ((pVWin->top << 16) | pVWin->left));
237 out32r ((pGD->vprBase + 0x0018),
238 ((pVWin->bottom << 16) | pVWin->right));
240 out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
242 out32r ((pGD->vprBase + 0x0020),
243 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
245 out32r ((pGD->vprBase + 0x0024),
246 (((pVWin->hStretch) << 8) | pVWin->vStretch));
249 out32r ((pGD->vprBase + 0x0028),
250 ((pVWin->top << 16) | pVWin->left));
252 out32r ((pGD->vprBase + 0x002c),
253 ((pVWin->bottom << 16) | pVWin->right));
255 out32r ((pGD->vprBase + 0x0030),
256 pVWin->srcStart / 8);
258 out32r ((pGD->vprBase + 0x0034),
259 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
261 out32r ((pGD->vprBase + 0x0038),
262 (((pVWin->hStretch) << 8) | pVWin->vStretch));
264 /* fifo prio control */
265 out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
267 /* fifo empty request levell */
268 out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
270 /* conversion constant */
271 out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
273 /* vpr control word */
274 out32r ((pGD->vprBase + 0x0000), pVP->control);
277 /******************************************************************************
279 * Init drawing engine registers
281 static void smiInitDrawingEngine (void)
283 GraphicDevice *pGD = (GraphicDevice *)&smi;
286 /* don't start now */
287 out32r ((pGD->dprBase + 0x000c), 0x000f0000);
289 /* set rop2 to copypen */
290 val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
291 out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
294 out32r ((pGD->dprBase + 0x002c), 0);
295 out32r ((pGD->dprBase + 0x0030),
296 ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
299 val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
300 out32r ((pGD->dprBase + 0x0010),
301 (val | pGD->plnSizeX * pGD->gdfBytesPP));
304 val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
305 out32r ((pGD->dprBase + 0x0010),
306 (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
308 /* window width src/dst */
309 out32r ((pGD->dprBase + 0x003c),
310 (((pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)<<16) |
311 (pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)));
312 out16r ((pGD->dprBase + 0x001e), 0x0000);
315 out32r ((pGD->dprBase + 0x0040),
316 (((pGD->frameAdrs/8) & 0x000fffff)));
319 out32r ((pGD->dprBase + 0x0044),
320 (((pGD->frameAdrs/8) & 0x000fffff)));
322 /* foreground color */
323 out32r ((pGD->dprBase + 0x0014), pGD->fg);
325 /* background color */
326 out32r ((pGD->dprBase + 0x0018), pGD->bg);
329 out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
332 out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
335 out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
337 /* load mono pattern */
338 out32r ((pGD->dprBase + 0x0034), 0);
339 out32r ((pGD->dprBase + 0x0038), 0);
342 static struct pci_device_id supported[] = {
343 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_710 },
344 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_712 },
345 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_810 },
349 /*****************************************************************************/
350 static void smiLoadMsr (struct ctfb_res_modes *mode)
352 unsigned char h_synch_high, v_synch_high;
353 register GraphicDevice *pGD = (GraphicDevice *)&smi;
355 h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40; /* horizontal Synch High active */
356 v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */
357 out8 (SMI_MISC_REG, (h_synch_high | v_synch_high | 0x29));
358 /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
359 * Selects the upper 64KB page.Bit5=1
360 * CLK2 (left reserved in standard VGA) Bit3|2=1|0
361 * Disables CPU access to frame buffer. Bit1=0
362 * Sets the I/O address decode for ST01, FCR, and all CR registers
363 * to the 3Dx I/O address range (CGA emulation). Bit0=1
366 /*****************************************************************************/
367 static void smiLoadCrt (struct ctfb_res_modes *var, int bits_per_pixel)
369 unsigned char cr[0x7a];
371 unsigned int hd, hs, he, ht, hbs, hbe; /* Horizontal. */
372 unsigned int vd, vs, ve, vt, vbs, vbe; /* vertical */
373 unsigned int bpp, wd, dblscan, interlaced;
375 const int LineCompare = 0x3ff;
376 unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor */
377 register GraphicDevice *pGD = (GraphicDevice *)&smi;
380 hd = (var->xres) / 8; /* HDisp. */
381 hs = (var->xres + var->right_margin) / 8; /* HsStrt */
382 he = (var->xres + var->right_margin + var->hsync_len) / 8; /* HsEnd */
383 ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8; /* HTotal */
386 hbe = 0; /* Blank end at 0 */
389 vd = var->yres; /* VDisplay */
390 vs = var->yres + var->lower_margin; /* VSyncStart */
391 ve = var->yres + var->lower_margin + var->vsync_len; /* VSyncEnd */
392 vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; /* VTotal */
396 bpp = bits_per_pixel;
397 dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
398 interlaced = var->vmode & FB_VMODE_INTERLACED;
403 wd = var->xres * bpp / 64; /* double words per line */
404 if (interlaced) { /* we divide all vertical timings, exept vd */
411 memset (cr, 0, sizeof (cr));
415 cr[0x03] = (hbe & 0x1F);
417 cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
419 cr[0x06] = (vt - 2) & 0xFF;
420 cr[0x07] = (((vt - 2) & 0x100) >> 8)
421 | (((vd - 1) & 0x100) >> 7)
422 | ((vs & 0x100) >> 6)
423 | (((vbs - 1) & 0x100) >> 5)
424 | ((LineCompare & 0x100) >> 4)
425 | (((vt - 2) & 0x200) >> 4)
426 | (((vd - 1) & 0x200) >> 3)
427 | ((vs & 0x200) >> 2);
429 cr[0x30] = ((vt - 2) & 0x400) >> 7
430 | (((vd - 1) & 0x400) >> 8)
431 | (((vbs - 1) & 0x400) >> 9)
432 | ((vs & 0x400) >> 10)
433 | (interlaced) ? 0x80 : 0;
437 cr[0x09] = (dblscan << 7)
438 | ((LineCompare & 0x200) >> 3)
439 | (((vbs - 1) & 0x200) >> 4)
440 | (TextScanLines - 1);
442 cr[0x10] = vs & 0xff; /* VSyncPulseStart */
443 cr[0x11] = (ve & 0x0f);
444 cr[0x12] = (vd - 1) & 0xff; /* LineCount */
445 cr[0x13] = wd & 0xff;
447 cr[0x15] = (vbs - 1) & 0xff;
448 cr[0x16] = vbe & 0xff;
449 cr[0x17] = 0xe3; /* but it does not work */
450 cr[0x18] = 0xff & LineCompare;
451 cr[0x22] = 0x00; /* todo? */
454 /* now set the registers */
455 for (i = 0; i <= 0x18; i++) { /*CR00 .. CR18 */
456 smiWrite (SMI_INDX_D4, i, cr[i]);
459 smiWrite (SMI_INDX_D4, i, cr[i]);
461 smiWrite (SMI_INDX_D4, i, cr[i]);
464 /*****************************************************************************/
465 #define REF_FREQ 14318180
471 static unsigned int FindPQ (unsigned int freq, unsigned int *pp, unsigned int *pq)
473 unsigned int n = QMIN, m = 0;
474 long long int L = 0, P = freq, Q = REF_FREQ, H = P >> 1;
475 long long int D = 0x7ffffffffffffffLL;
477 for (n = QMIN; n <= QMAX; n++) {
478 m = PMIN; /* p/q ~ freq/ref -> p*ref-freq*q ~ 0 */
480 while (L > 0 && m < PMAX) {
481 L -= REF_FREQ; /* difference is greater as 0 subtract fref */
482 m++; /* and increment m */
484 /* difference is less or equal than 0 or m > maximum */
486 break; /* no solution: if we increase n we get the same situation */
488 if (-L > H && m > PMIN) { /* if difference > the half fref */
489 L += REF_FREQ; /* we take the situation before */
490 m--; /* because its closer to 0 */
492 L = (L < 0) ? -L : +L; /* absolute value */
493 if (D < L) /* if last difference was better take next n */
497 *pq = n; /* keep improved data */
499 break; /* best result we can get */
501 return (unsigned int) (0xffffffff & D);
504 /*****************************************************************************/
505 static void smiLoadCcr (struct ctfb_res_modes *var, unsigned short device_id)
510 register GraphicDevice *pGD = (GraphicDevice *)&smi;
512 smiWrite (SMI_INDX_C4, 0x65, 0);
513 smiWrite (SMI_INDX_C4, 0x66, 0);
514 smiWrite (SMI_INDX_C4, 0x68, 0x50);
515 if (device_id == PCI_DEVICE_ID_SMI_810) {
516 smiWrite (SMI_INDX_C4, 0x69, 0x3);
518 smiWrite (SMI_INDX_C4, 0x69, 0x0);
523 case PCI_DEVICE_ID_SMI_710 :
524 smiWrite (SMI_INDX_C4, 0x6a, 0x75);
526 case PCI_DEVICE_ID_SMI_712 :
527 smiWrite (SMI_INDX_C4, 0x6a, 0x80);
530 smiWrite (SMI_INDX_C4, 0x6a, 0x53);
533 smiWrite (SMI_INDX_C4, 0x6b, 0x15);
536 freq = 1000000000000LL / var -> pixclock;
538 FindPQ ((unsigned int)freq, &p, &q);
540 smiWrite (SMI_INDX_C4, 0x6c, p);
541 smiWrite (SMI_INDX_C4, 0x6d, q);
545 /*******************************************************************************
547 * Init video chip with common Linux graphic modes (lilo)
549 void *video_hw_init (void)
551 GraphicDevice *pGD = (GraphicDevice *)&smi;
552 unsigned short device_id;
555 unsigned long t1, hsynch, vsynch;
556 unsigned int pci_mem_base, *vm;
558 int tmp, i, bits_per_pixel;
559 struct ctfb_res_modes *res_mode;
560 struct ctfb_res_modes var_mode;
561 unsigned char videoout;
563 /* Search for video chip */
566 if ((devbusfn = pci_find_devices(supported, 0)) < 0)
568 printf ("Controller not found !\n");
573 pci_write_config_dword (devbusfn, PCI_COMMAND, (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
574 pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
575 pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
576 pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
580 videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE;
581 /* get video mode via environment */
582 if ((penv = getenv ("videomode")) != NULL) {
583 /* deceide if it is a string */
584 if (penv[0] <= '9') {
585 videomode = (int) simple_strtoul (penv, NULL, 16);
592 /* parameter are vesa modes */
594 for (i = 0; i < VESA_MODES_COUNT; i++) {
595 if (vesa_modes[i].vesanr == videomode)
598 if (i == VESA_MODES_COUNT) {
599 printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE);
603 (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
605 bits_per_pixel = vesa_modes[i].bits_per_pixel;
608 res_mode = (struct ctfb_res_modes *) &var_mode;
609 bits_per_pixel = video_get_params (res_mode, penv);
612 /* calculate hsynch and vsynch freq (info only) */
613 t1 = (res_mode->left_margin + res_mode->xres +
614 res_mode->right_margin + res_mode->hsync_len) / 8;
616 t1 *= res_mode->pixclock;
618 hsynch = 1000000000L / t1;
620 (res_mode->upper_margin + res_mode->yres +
621 res_mode->lower_margin + res_mode->vsync_len);
623 vsynch = 1000000000L / t1;
625 /* fill in Graphic device struct */
626 sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
627 res_mode->yres, bits_per_pixel, (hsynch / 1000),
629 printf ("%s\n", pGD->modeIdent);
630 pGD->winSizeX = res_mode->xres;
631 pGD->winSizeY = res_mode->yres;
632 pGD->plnSizeX = res_mode->xres;
633 pGD->plnSizeY = res_mode->yres;
634 switch (bits_per_pixel) {
637 pGD->gdfIndex = GDF__8BIT_INDEX;
641 pGD->gdfIndex = GDF_15BIT_555RGB;
645 pGD->gdfIndex = GDF_16BIT_565RGB;
649 pGD->gdfIndex = GDF_24BIT_888RGB;
653 pGD->isaBase = CONFIG_SYS_ISA_IO;
654 pGD->pciBase = pci_mem_base;
655 pGD->dprBase = (pci_mem_base + 0x400000 + 0x8000);
656 pGD->vprBase = (pci_mem_base + 0x400000 + 0xc000);
657 pGD->cprBase = (pci_mem_base + 0x400000 + 0xe000);
658 pGD->frameAdrs = pci_mem_base;
659 pGD->memSize = VIDEO_MEM_SIZE;
661 /* Set up hardware : select color mode,
662 set Register base to isa 3dx for 3?x regs*/
663 out8 (SMI_MISC_REG, 0x01);
665 /* Turn off display */
666 smiWrite (SMI_INDX_C4, 0x01, 0x20);
668 /* Unlock ext. crt regs */
669 out8 (SMI_LOCK_REG, 0x40);
671 /* Unlock crt regs 0-7 */
672 smiWrite (SMI_INDX_D4, 0x11, 0x0e);
674 /* Sytem Control Register */
675 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SCR, sizeof(SMI_SCR));
677 /* extented CRT Register */
678 smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, SMI_EXT_CRT, sizeof(SMI_EXT_CRT));
680 /* Attributes controller registers */
681 smiLoadRegs (SMI_INDX_ATTR, SMI_INDX_ATTR, SMI_ATTR, sizeof(SMI_ATTR));
683 /* Graphics Controller Register */
684 smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF, SMI_GCR, sizeof(SMI_GCR));
686 /* Sequencer Register */
687 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SEQR, sizeof(SMI_SEQR));
689 /* Power Control Register */
690 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_PCR, sizeof(SMI_PCR));
692 /* Memory Control Register */
693 /* Register MSR62 is a power on configurable register. We don't */
695 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_MCR, sizeof(SMI_MCR));
697 /* Set misc output register */
698 smiLoadMsr (res_mode);
700 /* Set CRT and Clock control registers */
701 smiLoadCrt (res_mode, bits_per_pixel);
703 smiLoadCcr (res_mode, device_id);
705 /* Hardware Cusor Register */
706 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_HCR, sizeof(SMI_HCR));
709 videoout = 2; /* Default output is CRT */
710 if ((penv = getenv ("videoout")) != NULL) {
711 /* deceide if it is a string */
712 videoout = (int) simple_strtoul (penv, NULL, 16);
714 smiWrite (SMI_INDX_C4, 0x31, videoout);
716 /* Video processor default setup */
717 smiInitVideoProcessor ();
719 /* Capture port default setup */
720 smiInitCapturePort ();
722 /* Drawing engine default setup */
723 smiInitDrawingEngine ();
725 /* Turn on display */
726 smiWrite (0x3c4, 0x01, 0x01);
728 /* Clear video memory */
730 vm = (unsigned int *)pGD->pciBase;
733 return ((void*)&smi);
736 /*******************************************************************************
738 * Drawing engine fill on screen region
740 void video_hw_rectfill (
741 unsigned int bpp, /* bytes per pixel */
742 unsigned int dst_x, /* dest pos x */
743 unsigned int dst_y, /* dest pos y */
744 unsigned int dim_x, /* frame width */
745 unsigned int dim_y, /* frame height */
746 unsigned int color /* fill color */
749 register GraphicDevice *pGD = (GraphicDevice *)&smi;
750 register unsigned int control;
754 out32r ((pGD->dprBase + 0x0014), color);
755 out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
756 out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
758 control = 0x0000ffff & in32r ((pGD->dprBase + 0x000c));
760 control |= 0x80010000;
762 out32r ((pGD->dprBase + 0x000c), control);
764 /* Wait for drawing processor */
767 out8 ((pGD->isaBase + 0x3c4), 0x16);
768 } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
771 /*******************************************************************************
773 * Drawing engine bitblt with screen region
775 void video_hw_bitblt (
776 unsigned int bpp, /* bytes per pixel */
777 unsigned int src_x, /* source pos x */
778 unsigned int src_y, /* source pos y */
779 unsigned int dst_x, /* dest pos x */
780 unsigned int dst_y, /* dest pos y */
781 unsigned int dim_x, /* frame width */
782 unsigned int dim_y /* frame height */
785 register GraphicDevice *pGD = (GraphicDevice *)&smi;
786 register unsigned int control;
790 if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x)))
792 out32r ((pGD->dprBase + 0x0000), (((src_x+dim_x-1)<<16) | (src_y+dim_y-1)));
793 out32r ((pGD->dprBase + 0x0004), (((dst_x+dim_x-1)<<16) | (dst_y+dim_y-1)));
794 control = 0x88000000;
796 out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y));
797 out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
798 control = 0x80000000;
801 out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
802 control |= (0x0000ffff & in32r ((pGD->dprBase + 0x000c)));
803 out32r ((pGD->dprBase + 0x000c), control);
805 /* Wait for drawing processor */
808 out8 ((pGD->isaBase + 0x3c4), 0x16);
809 } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
812 /*******************************************************************************
814 * Set a RGB color in the LUT (8 bit index)
817 unsigned int index, /* color number */
818 unsigned char r, /* red */
819 unsigned char g, /* green */
820 unsigned char b /* blue */
823 register GraphicDevice *pGD = (GraphicDevice *)&smi;
825 out8 (SMI_LUT_MASK, 0xff);
827 out8 (SMI_LUT_START, (char)index);
829 out8 (SMI_LUT_RGB, r>>2); /* red */
831 out8 (SMI_LUT_RGB, g>>2); /* green */
833 out8 (SMI_LUT_RGB, b>>2); /* blue */