]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/video/smiLynxEM.c
karo: fdt: fix panel-dpi support
[karo-tx-uboot.git] / drivers / video / smiLynxEM.c
1 /*
2  * (C) Copyright 1997-2002 ELTEC Elektronik AG
3  * Frank Gottschling <fgottschling@eltec.de>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 /*
9  * smiLynxEM.c
10  *
11  * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator
12  *
13  * modification history
14  * --------------------
15  * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>.
16  *
17  * 18-03-2004 - Unify videomodes handling with the ct69000
18  *            - The video output can be set via the variable "videoout"
19  *              in the environment.
20  *              videoout=1 output on LCD
21  *              videoout=2 output on CRT (default value)
22  *                      <p.aubert@staubli.com>
23  */
24
25 #include <common.h>
26
27 #include <pci.h>
28 #include <video_fb.h>
29 #include "videomodes.h"
30 /*
31  * Export Graphic Device
32  */
33 GraphicDevice smi;
34
35 /*
36  * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
37  */
38 #define VIDEO_MEM_SIZE  0x400000
39
40
41 /*
42  * ISA mapped regs
43  */
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 */
57
58 /*
59  * Video processor control
60  */
61 typedef struct {
62         unsigned int   control;
63         unsigned int   colorKey;
64         unsigned int   colorKeyMask;
65         unsigned int   start;
66         unsigned short offset;
67         unsigned short width;
68         unsigned int   fifoPrio;
69         unsigned int   fifoERL;
70         unsigned int   YUVtoRGB;
71 } SmiVideoProc;
72
73 /*
74  * Video window control
75  */
76 typedef struct {
77         unsigned short top;
78         unsigned short left;
79         unsigned short bottom;
80         unsigned short right;
81         unsigned int   srcStart;
82         unsigned short width;
83         unsigned short offset;
84         unsigned char  hStretch;
85         unsigned char  vStretch;
86 } SmiVideoWin;
87
88 /*
89  * Capture port control
90  */
91 typedef struct {
92         unsigned int   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;
101 } SmiCapturePort;
102
103
104 /*
105  * Register values for common video modes
106  */
107 static char SMI_SCR[] = {
108         /* all modes */
109         0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x15, 0x90,
110         0x17, 0x20, 0x18, 0xb1, 0x19, 0x00,
111 };
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,
115 };
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,
121 };
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,
125 };
126 static char SMI_SEQR[] = {
127         0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03,
128 };
129 static char SMI_PCR [] = {
130         0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00,
131 };
132 static char SMI_MCR[] = {
133         0x60, 0x01, 0x61, 0x00,
134 };
135
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,
139 };
140
141
142 /*******************************************************************************
143  *
144  * Write SMI ISA register
145  */
146 static void smiWrite (unsigned short index, char reg, char val)
147 {
148         register GraphicDevice *pGD = (GraphicDevice *)&smi;
149
150         out8 ((pGD->isaBase + index), reg);
151         out8 ((pGD->isaBase + index + 1), val);
152 }
153
154 /*******************************************************************************
155  *
156  * Write a table of SMI ISA register
157  */
158 static void smiLoadRegs (
159         unsigned int iReg,
160         unsigned int dReg,
161         char         *regTab,
162         unsigned int tabSize
163         )
164 {
165         register GraphicDevice *pGD  = (GraphicDevice *)&smi;
166         register int i;
167
168         for (i=0; i<tabSize; i+=2) {
169                 if (iReg == SMI_INDX_ATTR) {
170                         /* Reset the Flip Flop */
171                         in8 (SMI_ISR1);
172                         out8 (iReg, regTab[i]);
173                         out8 (iReg, regTab[i+1]);
174                 } else {
175                         out8 (iReg, regTab[i]);
176                         out8 (dReg, regTab[i+1]);
177                 }
178         }
179 }
180
181 /*******************************************************************************
182  *
183  * Init capture port registers
184  */
185 static void smiInitCapturePort (void)
186 {
187         SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
188         register GraphicDevice *pGD  = (GraphicDevice *)&smi;
189         register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
190
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);
198 }
199
200
201 /*******************************************************************************
202  *
203  * Init video processor registers
204  */
205 static void smiInitVideoProcessor (void)
206 {
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;
212
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;
218
219         /* color key */
220         out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
221
222         /* color key mask */
223         out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
224
225         /* data src start adrs */
226         out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
227
228         /* data width and offset */
229         out32r ((pGD->vprBase + 0x0010),
230                 ((pVP->offset   / 8 * pGD->gdfBytesPP) << 16) |
231                 (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
232
233         /* video window 1 */
234         out32r ((pGD->vprBase + 0x0014),
235                 ((pVWin->top << 16) | pVWin->left));
236
237         out32r ((pGD->vprBase + 0x0018),
238                 ((pVWin->bottom << 16) | pVWin->right));
239
240         out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
241
242         out32r ((pGD->vprBase + 0x0020),
243                 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
244
245         out32r ((pGD->vprBase + 0x0024),
246                 (((pVWin->hStretch) << 8) | pVWin->vStretch));
247
248         /* video window 2 */
249         out32r ((pGD->vprBase + 0x0028),
250                 ((pVWin->top << 16) | pVWin->left));
251
252         out32r ((pGD->vprBase + 0x002c),
253                 ((pVWin->bottom << 16) | pVWin->right));
254
255         out32r ((pGD->vprBase + 0x0030),
256                 pVWin->srcStart / 8);
257
258         out32r ((pGD->vprBase + 0x0034),
259                 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
260
261         out32r ((pGD->vprBase + 0x0038),
262                 (((pVWin->hStretch) << 8) | pVWin->vStretch));
263
264         /* fifo prio control */
265         out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
266
267         /* fifo empty request levell */
268         out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
269
270         /* conversion constant */
271         out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
272
273         /* vpr control word */
274         out32r ((pGD->vprBase + 0x0000), pVP->control);
275 }
276
277 /******************************************************************************
278  *
279  * Init drawing engine registers
280  */
281 static void smiInitDrawingEngine (void)
282 {
283         GraphicDevice *pGD = (GraphicDevice *)&smi;
284         unsigned int val;
285
286         /* don't start now */
287         out32r ((pGD->dprBase + 0x000c), 0x000f0000);
288
289         /* set rop2 to copypen */
290         val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
291         out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
292
293         /* set clip rect */
294         out32r ((pGD->dprBase + 0x002c), 0);
295         out32r ((pGD->dprBase + 0x0030),
296                 ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
297
298         /* src row pitch */
299         val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
300         out32r ((pGD->dprBase + 0x0010),
301                 (val | pGD->plnSizeX * pGD->gdfBytesPP));
302
303         /* dst row pitch */
304         val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
305         out32r ((pGD->dprBase + 0x0010),
306                 (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
307
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);
313
314         /* src base adrs */
315         out32r ((pGD->dprBase + 0x0040),
316                 (((pGD->frameAdrs/8) & 0x000fffff)));
317
318         /* dst base adrs */
319         out32r ((pGD->dprBase + 0x0044),
320                 (((pGD->frameAdrs/8) & 0x000fffff)));
321
322         /* foreground color */
323         out32r ((pGD->dprBase + 0x0014), pGD->fg);
324
325         /* background color */
326         out32r ((pGD->dprBase + 0x0018), pGD->bg);
327
328         /* xcolor */
329         out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
330
331         /* xcolor mask */
332         out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
333
334         /* bit mask */
335         out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
336
337         /* load mono pattern */
338         out32r ((pGD->dprBase + 0x0034), 0);
339         out32r ((pGD->dprBase + 0x0038), 0);
340 }
341
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 },
346         { }
347 };
348
349 /*****************************************************************************/
350 static void smiLoadMsr (struct ctfb_res_modes *mode)
351 {
352         unsigned char h_synch_high, v_synch_high;
353         register GraphicDevice *pGD  = (GraphicDevice *)&smi;
354
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
364          */
365 }
366 /*****************************************************************************/
367 static void smiLoadCrt (struct ctfb_res_modes *var, int bits_per_pixel)
368 {
369         unsigned char cr[0x7a];
370         int i;
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;
374
375         const int LineCompare = 0x3ff;
376         unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor   */
377         register GraphicDevice *pGD  = (GraphicDevice *)&smi;
378
379         /* Horizontal */
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  */
384         /* Blank */
385         hbs = hd;
386         hbe = 0; /* Blank end at 0 */
387
388         /* Vertical */
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  */
393         vbs = vd;
394         vbe = 0;
395
396         bpp = bits_per_pixel;
397         dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
398         interlaced = var->vmode & FB_VMODE_INTERLACED;
399
400
401         if (bpp == 15)
402                 bpp = 16;
403         wd = var->xres * bpp / 64;      /* double words per line */
404         if (interlaced) {       /* we divide all vertical timings, exept vd */
405                 vs >>= 1;
406                 vbs >>= 1;
407                 ve >>= 1;
408                 vt >>= 1;
409         }
410
411         memset (cr, 0, sizeof (cr));
412         cr[0x00] = ht - 5;
413         cr[0x01] = hd - 1;
414         cr[0x02] = hbs - 1;
415         cr[0x03] = (hbe & 0x1F);
416         cr[0x04] = hs;
417         cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
418
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);
428
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;
434
435
436         cr[0x08] = 0x00;
437         cr[0x09] = (dblscan << 7)
438                 | ((LineCompare & 0x200) >> 3)
439                 | (((vbs - 1) & 0x200) >> 4)
440                 | (TextScanLines - 1);
441
442         cr[0x10] = vs & 0xff;   /* VSyncPulseStart */
443         cr[0x11] = (ve & 0x0f);
444         cr[0x12] = (vd - 1) & 0xff;     /* LineCount  */
445         cr[0x13] = wd & 0xff;
446         cr[0x14] = 0x40;
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? */
452
453
454         /* now set the registers */
455         for (i = 0; i <= 0x18; i++) {   /*CR00 .. CR18 */
456                 smiWrite (SMI_INDX_D4, i, cr[i]);
457         }
458         i = 0x22;               /*CR22 */
459         smiWrite (SMI_INDX_D4, i, cr[i]);
460         i = 0x30;               /*CR30 */
461         smiWrite (SMI_INDX_D4, i, cr[i]);
462 }
463
464 /*****************************************************************************/
465 #define REF_FREQ        14318180
466 #define PMIN            1
467 #define PMAX            255
468 #define QMIN            1
469 #define QMAX            63
470
471 static unsigned int FindPQ (unsigned int freq, unsigned int *pp, unsigned int *pq)
472 {
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;
476
477         for (n = QMIN; n <= QMAX; n++) {
478                 m = PMIN;       /* p/q ~ freq/ref -> p*ref-freq*q ~ 0 */
479                 L = P * n - m * Q;
480                 while (L > 0 && m < PMAX) {
481                         L -= REF_FREQ;  /* difference is greater as 0 subtract fref */
482                         m++;    /* and increment m */
483                 }
484                 /* difference is less or equal than 0 or m > maximum */
485                 if (m > PMAX)
486                         break;  /* no solution: if we increase n we get the same situation */
487                 /* L is <= 0 now */
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 */
491                 }
492                 L = (L < 0) ? -L : +L;  /* absolute value */
493                 if (D < L)      /* if last difference was better take next n */
494                         continue;
495                 D = L;
496                 *pp = m;
497                 *pq = n;        /*  keep improved data */
498                 if (D == 0)
499                         break;  /* best result we can get */
500         }
501         return (unsigned int) (0xffffffff & D);
502 }
503
504 /*****************************************************************************/
505 static void smiLoadCcr (struct ctfb_res_modes *var, unsigned short device_id)
506 {
507         unsigned int p = 0;
508         unsigned int q = 0;
509         long long freq;
510         register GraphicDevice *pGD  = (GraphicDevice *)&smi;
511
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);
517         } else {
518                 smiWrite (SMI_INDX_C4, 0x69, 0x0);
519         }
520
521         /* Memory clock */
522         switch (device_id) {
523         case PCI_DEVICE_ID_SMI_710 :
524                 smiWrite (SMI_INDX_C4, 0x6a, 0x75);
525                 break;
526         case PCI_DEVICE_ID_SMI_712 :
527                 smiWrite (SMI_INDX_C4, 0x6a, 0x80);
528                 break;
529         default :
530                 smiWrite (SMI_INDX_C4, 0x6a, 0x53);
531                 break;
532         }
533         smiWrite (SMI_INDX_C4, 0x6b, 0x15);
534
535         /* VCLK */
536         freq = 1000000000000LL / var -> pixclock;
537
538         FindPQ ((unsigned int)freq, &p, &q);
539
540         smiWrite (SMI_INDX_C4, 0x6c, p);
541         smiWrite (SMI_INDX_C4, 0x6d, q);
542
543 }
544
545 /*******************************************************************************
546  *
547  * Init video chip with common Linux graphic modes (lilo)
548  */
549 void *video_hw_init (void)
550 {
551         GraphicDevice *pGD = (GraphicDevice *)&smi;
552         unsigned short device_id;
553         pci_dev_t devbusfn;
554         int videomode;
555         unsigned long t1, hsynch, vsynch;
556         unsigned int pci_mem_base, *vm;
557         char *penv;
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;
562
563         /* Search for video chip */
564         printf("Video: ");
565
566         if ((devbusfn = pci_find_devices(supported, 0)) < 0)
567         {
568                 printf ("Controller not found !\n");
569                 return (NULL);
570         }
571
572         /* PCI setup */
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);
577
578         tmp = 0;
579
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);
586                         tmp = 1;
587                 }
588         } else {
589                 tmp = 1;
590         }
591         if (tmp) {
592                 /* parameter are vesa modes */
593                 /* search params */
594                 for (i = 0; i < VESA_MODES_COUNT; i++) {
595                         if (vesa_modes[i].vesanr == videomode)
596                                 break;
597                 }
598                 if (i == VESA_MODES_COUNT) {
599                         printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE);
600                         i = 0;
601                 }
602                 res_mode =
603                         (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
604                                                                  resindex];
605                 bits_per_pixel = vesa_modes[i].bits_per_pixel;
606         } else {
607
608                 res_mode = (struct ctfb_res_modes *) &var_mode;
609                 bits_per_pixel = video_get_params (res_mode, penv);
610         }
611
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;
615         t1 *= 8;
616         t1 *= res_mode->pixclock;
617         t1 /= 1000;
618         hsynch = 1000000000L / t1;
619         t1 *=
620                 (res_mode->upper_margin + res_mode->yres +
621                  res_mode->lower_margin + res_mode->vsync_len);
622         t1 /= 1000;
623         vsynch = 1000000000L / t1;
624
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),
628                  (vsynch / 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) {
635         case 8:
636                 pGD->gdfBytesPP = 1;
637                 pGD->gdfIndex = GDF__8BIT_INDEX;
638                 break;
639         case 15:
640                 pGD->gdfBytesPP = 2;
641                 pGD->gdfIndex = GDF_15BIT_555RGB;
642                 break;
643         case 16:
644                 pGD->gdfBytesPP = 2;
645                 pGD->gdfIndex = GDF_16BIT_565RGB;
646                 break;
647         case 24:
648                 pGD->gdfBytesPP = 3;
649                 pGD->gdfIndex = GDF_24BIT_888RGB;
650                 break;
651         }
652
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;
660
661         /* Set up hardware : select color mode,
662            set Register base to isa 3dx for 3?x regs*/
663         out8 (SMI_MISC_REG, 0x01);
664
665         /* Turn off display */
666         smiWrite (SMI_INDX_C4, 0x01, 0x20);
667
668         /* Unlock ext. crt regs */
669         out8 (SMI_LOCK_REG, 0x40);
670
671         /* Unlock crt regs 0-7 */
672         smiWrite (SMI_INDX_D4, 0x11, 0x0e);
673
674         /* Sytem Control Register */
675         smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SCR, sizeof(SMI_SCR));
676
677         /* extented CRT Register */
678         smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, SMI_EXT_CRT, sizeof(SMI_EXT_CRT));
679
680         /* Attributes controller registers */
681         smiLoadRegs (SMI_INDX_ATTR, SMI_INDX_ATTR, SMI_ATTR, sizeof(SMI_ATTR));
682
683         /* Graphics Controller Register */
684         smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF, SMI_GCR, sizeof(SMI_GCR));
685
686         /* Sequencer Register */
687         smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SEQR, sizeof(SMI_SEQR));
688
689         /* Power Control Register */
690         smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_PCR, sizeof(SMI_PCR));
691
692         /* Memory Control Register */
693         /* Register MSR62 is a power on configurable register. We don't */
694         /* modify it */
695         smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_MCR, sizeof(SMI_MCR));
696
697         /* Set misc output register */
698         smiLoadMsr (res_mode);
699
700         /* Set CRT and Clock control registers */
701         smiLoadCrt (res_mode, bits_per_pixel);
702
703         smiLoadCcr (res_mode, device_id);
704
705         /* Hardware Cusor Register */
706         smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_HCR, sizeof(SMI_HCR));
707
708         /* Enable  Display  */
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);
713         }
714         smiWrite (SMI_INDX_C4, 0x31, videoout);
715
716         /* Video processor default setup */
717         smiInitVideoProcessor ();
718
719         /* Capture port default setup */
720         smiInitCapturePort ();
721
722         /* Drawing engine default setup */
723         smiInitDrawingEngine ();
724
725         /* Turn on display */
726         smiWrite (0x3c4, 0x01, 0x01);
727
728         /* Clear video memory */
729         i = pGD->memSize/4;
730         vm = (unsigned int *)pGD->pciBase;
731         while(i--)
732                 *vm++ = 0;
733         return ((void*)&smi);
734 }
735
736 /*******************************************************************************
737  *
738  * Drawing engine fill on screen region
739  */
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 */
747         )
748 {
749         register GraphicDevice *pGD = (GraphicDevice *)&smi;
750         register unsigned int control;
751
752         dim_x *= bpp;
753
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));
757
758         control = 0x0000ffff &  in32r ((pGD->dprBase + 0x000c));
759
760         control |= 0x80010000;
761
762         out32r ((pGD->dprBase + 0x000c),  control);
763
764         /* Wait for drawing processor */
765         do
766         {
767                 out8 ((pGD->isaBase + 0x3c4), 0x16);
768         } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
769 }
770
771 /*******************************************************************************
772  *
773  * Drawing engine bitblt with screen region
774  */
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 */
783         )
784 {
785         register GraphicDevice *pGD = (GraphicDevice *)&smi;
786         register unsigned int control;
787
788         dim_x *= bpp;
789
790         if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x)))
791         {
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;
795         } else {
796                 out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y));
797                 out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
798                 control = 0x80000000;
799         }
800
801         out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
802         control |= (0x0000ffff &  in32r ((pGD->dprBase + 0x000c)));
803         out32r ((pGD->dprBase + 0x000c), control);
804
805         /* Wait for drawing processor */
806         do
807         {
808                 out8 ((pGD->isaBase + 0x3c4), 0x16);
809         } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
810 }
811
812 /*******************************************************************************
813  *
814  * Set a RGB color in the LUT (8 bit index)
815  */
816 void video_set_lut (
817         unsigned int index,           /* color number */
818         unsigned char r,              /* red */
819         unsigned char g,              /* green */
820         unsigned char b               /* blue */
821         )
822 {
823         register GraphicDevice *pGD = (GraphicDevice *)&smi;
824
825         out8 (SMI_LUT_MASK,  0xff);
826
827         out8 (SMI_LUT_START, (char)index);
828
829         out8 (SMI_LUT_RGB, r>>2);    /* red */
830         udelay (10);
831         out8 (SMI_LUT_RGB, g>>2);    /* green */
832         udelay (10);
833         out8 (SMI_LUT_RGB, b>>2);    /* blue */
834         udelay (10);
835 }