]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/video/smiLynxEM.c
Merge branch 'u-boot/master' into u-boot-arm/master
[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 #ifdef CONFIG_HMI1001
135         0x62, 0x74, /* Memory type is not configured by pins on HMI1001 */
136 #endif
137 };
138
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,
142 };
143
144
145 /*******************************************************************************
146  *
147  * Write SMI ISA register
148  */
149 static void smiWrite (unsigned short index, char reg, char val)
150 {
151         register GraphicDevice *pGD = (GraphicDevice *)&smi;
152
153         out8 ((pGD->isaBase + index), reg);
154         out8 ((pGD->isaBase + index + 1), val);
155 }
156
157 /*******************************************************************************
158  *
159  * Write a table of SMI ISA register
160  */
161 static void smiLoadRegs (
162         unsigned int iReg,
163         unsigned int dReg,
164         char         *regTab,
165         unsigned int tabSize
166         )
167 {
168         register GraphicDevice *pGD  = (GraphicDevice *)&smi;
169         register int i;
170
171         for (i=0; i<tabSize; i+=2) {
172                 if (iReg == SMI_INDX_ATTR) {
173                         /* Reset the Flip Flop */
174                         in8 (SMI_ISR1);
175                         out8 (iReg, regTab[i]);
176                         out8 (iReg, regTab[i+1]);
177                 } else {
178                         out8 (iReg, regTab[i]);
179                         out8 (dReg, regTab[i+1]);
180                 }
181         }
182 }
183
184 /*******************************************************************************
185  *
186  * Init capture port registers
187  */
188 static void smiInitCapturePort (void)
189 {
190         SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
191         register GraphicDevice *pGD  = (GraphicDevice *)&smi;
192         register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
193
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);
201 }
202
203
204 /*******************************************************************************
205  *
206  * Init video processor registers
207  */
208 static void smiInitVideoProcessor (void)
209 {
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;
215
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;
221
222         /* color key */
223         out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
224
225         /* color key mask */
226         out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
227
228         /* data src start adrs */
229         out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
230
231         /* data width and offset */
232         out32r ((pGD->vprBase + 0x0010),
233                 ((pVP->offset   / 8 * pGD->gdfBytesPP) << 16) |
234                 (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
235
236         /* video window 1 */
237         out32r ((pGD->vprBase + 0x0014),
238                 ((pVWin->top << 16) | pVWin->left));
239
240         out32r ((pGD->vprBase + 0x0018),
241                 ((pVWin->bottom << 16) | pVWin->right));
242
243         out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
244
245         out32r ((pGD->vprBase + 0x0020),
246                 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
247
248         out32r ((pGD->vprBase + 0x0024),
249                 (((pVWin->hStretch) << 8) | pVWin->vStretch));
250
251         /* video window 2 */
252         out32r ((pGD->vprBase + 0x0028),
253                 ((pVWin->top << 16) | pVWin->left));
254
255         out32r ((pGD->vprBase + 0x002c),
256                 ((pVWin->bottom << 16) | pVWin->right));
257
258         out32r ((pGD->vprBase + 0x0030),
259                 pVWin->srcStart / 8);
260
261         out32r ((pGD->vprBase + 0x0034),
262                 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
263
264         out32r ((pGD->vprBase + 0x0038),
265                 (((pVWin->hStretch) << 8) | pVWin->vStretch));
266
267         /* fifo prio control */
268         out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
269
270         /* fifo empty request levell */
271         out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
272
273         /* conversion constant */
274         out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
275
276         /* vpr control word */
277         out32r ((pGD->vprBase + 0x0000), pVP->control);
278 }
279
280 /******************************************************************************
281  *
282  * Init drawing engine registers
283  */
284 static void smiInitDrawingEngine (void)
285 {
286         GraphicDevice *pGD = (GraphicDevice *)&smi;
287         unsigned int val;
288
289         /* don't start now */
290         out32r ((pGD->dprBase + 0x000c), 0x000f0000);
291
292         /* set rop2 to copypen */
293         val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
294         out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
295
296         /* set clip rect */
297         out32r ((pGD->dprBase + 0x002c), 0);
298         out32r ((pGD->dprBase + 0x0030),
299                 ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
300
301         /* src row pitch */
302         val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
303         out32r ((pGD->dprBase + 0x0010),
304                 (val | pGD->plnSizeX * pGD->gdfBytesPP));
305
306         /* dst row pitch */
307         val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
308         out32r ((pGD->dprBase + 0x0010),
309                 (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
310
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);
316
317         /* src base adrs */
318         out32r ((pGD->dprBase + 0x0040),
319                 (((pGD->frameAdrs/8) & 0x000fffff)));
320
321         /* dst base adrs */
322         out32r ((pGD->dprBase + 0x0044),
323                 (((pGD->frameAdrs/8) & 0x000fffff)));
324
325         /* foreground color */
326         out32r ((pGD->dprBase + 0x0014), pGD->fg);
327
328         /* background color */
329         out32r ((pGD->dprBase + 0x0018), pGD->bg);
330
331         /* xcolor */
332         out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
333
334         /* xcolor mask */
335         out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
336
337         /* bit mask */
338         out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
339
340         /* load mono pattern */
341         out32r ((pGD->dprBase + 0x0034), 0);
342         out32r ((pGD->dprBase + 0x0038), 0);
343 }
344
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 },
349         { }
350 };
351
352 /*****************************************************************************/
353 static void smiLoadMsr (struct ctfb_res_modes *mode)
354 {
355         unsigned char h_synch_high, v_synch_high;
356         register GraphicDevice *pGD  = (GraphicDevice *)&smi;
357
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
367          */
368 }
369 /*****************************************************************************/
370 static void smiLoadCrt (struct ctfb_res_modes *var, int bits_per_pixel)
371 {
372         unsigned char cr[0x7a];
373         int i;
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;
377
378         const int LineCompare = 0x3ff;
379         unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor   */
380         register GraphicDevice *pGD  = (GraphicDevice *)&smi;
381
382         /* Horizontal */
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  */
387         /* Blank */
388         hbs = hd;
389         hbe = 0; /* Blank end at 0 */
390
391         /* Vertical */
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  */
396         vbs = vd;
397         vbe = 0;
398
399         bpp = bits_per_pixel;
400         dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
401         interlaced = var->vmode & FB_VMODE_INTERLACED;
402
403
404         if (bpp == 15)
405                 bpp = 16;
406         wd = var->xres * bpp / 64;      /* double words per line */
407         if (interlaced) {       /* we divide all vertical timings, exept vd */
408                 vs >>= 1;
409                 vbs >>= 1;
410                 ve >>= 1;
411                 vt >>= 1;
412         }
413
414         memset (cr, 0, sizeof (cr));
415         cr[0x00] = ht - 5;
416         cr[0x01] = hd - 1;
417         cr[0x02] = hbs - 1;
418         cr[0x03] = (hbe & 0x1F);
419         cr[0x04] = hs;
420         cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
421
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);
431
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;
437
438
439         cr[0x08] = 0x00;
440         cr[0x09] = (dblscan << 7)
441                 | ((LineCompare & 0x200) >> 3)
442                 | (((vbs - 1) & 0x200) >> 4)
443                 | (TextScanLines - 1);
444
445         cr[0x10] = vs & 0xff;   /* VSyncPulseStart */
446         cr[0x11] = (ve & 0x0f);
447         cr[0x12] = (vd - 1) & 0xff;     /* LineCount  */
448         cr[0x13] = wd & 0xff;
449         cr[0x14] = 0x40;
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? */
455
456
457         /* now set the registers */
458         for (i = 0; i <= 0x18; i++) {   /*CR00 .. CR18 */
459                 smiWrite (SMI_INDX_D4, i, cr[i]);
460         }
461         i = 0x22;               /*CR22 */
462         smiWrite (SMI_INDX_D4, i, cr[i]);
463         i = 0x30;               /*CR30 */
464         smiWrite (SMI_INDX_D4, i, cr[i]);
465 }
466
467 /*****************************************************************************/
468 #define REF_FREQ        14318180
469 #define PMIN            1
470 #define PMAX            255
471 #define QMIN            1
472 #define QMAX            63
473
474 static unsigned int FindPQ (unsigned int freq, unsigned int *pp, unsigned int *pq)
475 {
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;
479
480         for (n = QMIN; n <= QMAX; n++) {
481                 m = PMIN;       /* p/q ~ freq/ref -> p*ref-freq*q ~ 0 */
482                 L = P * n - m * Q;
483                 while (L > 0 && m < PMAX) {
484                         L -= REF_FREQ;  /* difference is greater as 0 subtract fref */
485                         m++;    /* and increment m */
486                 }
487                 /* difference is less or equal than 0 or m > maximum */
488                 if (m > PMAX)
489                         break;  /* no solution: if we increase n we get the same situation */
490                 /* L is <= 0 now */
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 */
494                 }
495                 L = (L < 0) ? -L : +L;  /* absolute value */
496                 if (D < L)      /* if last difference was better take next n */
497                         continue;
498                 D = L;
499                 *pp = m;
500                 *pq = n;        /*  keep improved data */
501                 if (D == 0)
502                         break;  /* best result we can get */
503         }
504         return (unsigned int) (0xffffffff & D);
505 }
506
507 /*****************************************************************************/
508 static void smiLoadCcr (struct ctfb_res_modes *var, unsigned short device_id)
509 {
510         unsigned int p = 0;
511         unsigned int q = 0;
512         long long freq;
513         register GraphicDevice *pGD  = (GraphicDevice *)&smi;
514
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);
520         } else {
521                 smiWrite (SMI_INDX_C4, 0x69, 0x0);
522         }
523
524         /* Memory clock */
525         switch (device_id) {
526         case PCI_DEVICE_ID_SMI_710 :
527                 smiWrite (SMI_INDX_C4, 0x6a, 0x75);
528                 break;
529         case PCI_DEVICE_ID_SMI_712 :
530                 smiWrite (SMI_INDX_C4, 0x6a, 0x80);
531                 break;
532         default :
533                 smiWrite (SMI_INDX_C4, 0x6a, 0x53);
534                 break;
535         }
536         smiWrite (SMI_INDX_C4, 0x6b, 0x15);
537
538         /* VCLK */
539         freq = 1000000000000LL / var -> pixclock;
540
541         FindPQ ((unsigned int)freq, &p, &q);
542
543         smiWrite (SMI_INDX_C4, 0x6c, p);
544         smiWrite (SMI_INDX_C4, 0x6d, q);
545
546 }
547
548 /*******************************************************************************
549  *
550  * Init video chip with common Linux graphic modes (lilo)
551  */
552 void *video_hw_init (void)
553 {
554         GraphicDevice *pGD = (GraphicDevice *)&smi;
555         unsigned short device_id;
556         pci_dev_t devbusfn;
557         int videomode;
558         unsigned long t1, hsynch, vsynch;
559         unsigned int pci_mem_base, *vm;
560         char *penv;
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;
565
566         /* Search for video chip */
567         printf("Video: ");
568
569         if ((devbusfn = pci_find_devices(supported, 0)) < 0)
570         {
571                 printf ("Controller not found !\n");
572                 return (NULL);
573         }
574
575         /* PCI setup */
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);
580
581         tmp = 0;
582
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);
589                         tmp = 1;
590                 }
591         } else {
592                 tmp = 1;
593         }
594         if (tmp) {
595                 /* parameter are vesa modes */
596                 /* search params */
597                 for (i = 0; i < VESA_MODES_COUNT; i++) {
598                         if (vesa_modes[i].vesanr == videomode)
599                                 break;
600                 }
601                 if (i == VESA_MODES_COUNT) {
602                         printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE);
603                         i = 0;
604                 }
605                 res_mode =
606                         (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
607                                                                  resindex];
608                 bits_per_pixel = vesa_modes[i].bits_per_pixel;
609         } else {
610
611                 res_mode = (struct ctfb_res_modes *) &var_mode;
612                 bits_per_pixel = video_get_params (res_mode, penv);
613         }
614
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;
618         t1 *= 8;
619         t1 *= res_mode->pixclock;
620         t1 /= 1000;
621         hsynch = 1000000000L / t1;
622         t1 *=
623                 (res_mode->upper_margin + res_mode->yres +
624                  res_mode->lower_margin + res_mode->vsync_len);
625         t1 /= 1000;
626         vsynch = 1000000000L / t1;
627
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),
631                  (vsynch / 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) {
638         case 8:
639                 pGD->gdfBytesPP = 1;
640                 pGD->gdfIndex = GDF__8BIT_INDEX;
641                 break;
642         case 15:
643                 pGD->gdfBytesPP = 2;
644                 pGD->gdfIndex = GDF_15BIT_555RGB;
645                 break;
646         case 16:
647                 pGD->gdfBytesPP = 2;
648                 pGD->gdfIndex = GDF_16BIT_565RGB;
649                 break;
650         case 24:
651                 pGD->gdfBytesPP = 3;
652                 pGD->gdfIndex = GDF_24BIT_888RGB;
653                 break;
654         }
655
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;
663
664         /* Set up hardware : select color mode,
665            set Register base to isa 3dx for 3?x regs*/
666         out8 (SMI_MISC_REG, 0x01);
667
668         /* Turn off display */
669         smiWrite (SMI_INDX_C4, 0x01, 0x20);
670
671         /* Unlock ext. crt regs */
672         out8 (SMI_LOCK_REG, 0x40);
673
674         /* Unlock crt regs 0-7 */
675         smiWrite (SMI_INDX_D4, 0x11, 0x0e);
676
677         /* Sytem Control Register */
678         smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SCR, sizeof(SMI_SCR));
679
680         /* extented CRT Register */
681         smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, SMI_EXT_CRT, sizeof(SMI_EXT_CRT));
682
683         /* Attributes controller registers */
684         smiLoadRegs (SMI_INDX_ATTR, SMI_INDX_ATTR, SMI_ATTR, sizeof(SMI_ATTR));
685
686         /* Graphics Controller Register */
687         smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF, SMI_GCR, sizeof(SMI_GCR));
688
689         /* Sequencer Register */
690         smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SEQR, sizeof(SMI_SEQR));
691
692         /* Power Control Register */
693         smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_PCR, sizeof(SMI_PCR));
694
695         /* Memory Control Register */
696         /* Register MSR62 is a power on configurable register. We don't */
697         /* modify it */
698         smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_MCR, sizeof(SMI_MCR));
699
700         /* Set misc output register */
701         smiLoadMsr (res_mode);
702
703         /* Set CRT and Clock control registers */
704         smiLoadCrt (res_mode, bits_per_pixel);
705
706         smiLoadCcr (res_mode, device_id);
707
708         /* Hardware Cusor Register */
709         smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_HCR, sizeof(SMI_HCR));
710
711         /* Enable  Display  */
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);
716         }
717         smiWrite (SMI_INDX_C4, 0x31, videoout);
718
719         /* Video processor default setup */
720         smiInitVideoProcessor ();
721
722         /* Capture port default setup */
723         smiInitCapturePort ();
724
725         /* Drawing engine default setup */
726         smiInitDrawingEngine ();
727
728         /* Turn on display */
729         smiWrite (0x3c4, 0x01, 0x01);
730
731         /* Clear video memory */
732         i = pGD->memSize/4;
733         vm = (unsigned int *)pGD->pciBase;
734         while(i--)
735                 *vm++ = 0;
736         return ((void*)&smi);
737 }
738
739 /*******************************************************************************
740  *
741  * Drawing engine fill on screen region
742  */
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 */
750         )
751 {
752         register GraphicDevice *pGD = (GraphicDevice *)&smi;
753         register unsigned int control;
754
755         dim_x *= bpp;
756
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));
760
761         control = 0x0000ffff &  in32r ((pGD->dprBase + 0x000c));
762
763         control |= 0x80010000;
764
765         out32r ((pGD->dprBase + 0x000c),  control);
766
767         /* Wait for drawing processor */
768         do
769         {
770                 out8 ((pGD->isaBase + 0x3c4), 0x16);
771         } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
772 }
773
774 /*******************************************************************************
775  *
776  * Drawing engine bitblt with screen region
777  */
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 */
786         )
787 {
788         register GraphicDevice *pGD = (GraphicDevice *)&smi;
789         register unsigned int control;
790
791         dim_x *= bpp;
792
793         if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x)))
794         {
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;
798         } else {
799                 out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y));
800                 out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
801                 control = 0x80000000;
802         }
803
804         out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
805         control |= (0x0000ffff &  in32r ((pGD->dprBase + 0x000c)));
806         out32r ((pGD->dprBase + 0x000c), control);
807
808         /* Wait for drawing processor */
809         do
810         {
811                 out8 ((pGD->isaBase + 0x3c4), 0x16);
812         } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
813 }
814
815 /*******************************************************************************
816  *
817  * Set a RGB color in the LUT (8 bit index)
818  */
819 void video_set_lut (
820         unsigned int index,           /* color number */
821         unsigned char r,              /* red */
822         unsigned char g,              /* green */
823         unsigned char b               /* blue */
824         )
825 {
826         register GraphicDevice *pGD = (GraphicDevice *)&smi;
827
828         out8 (SMI_LUT_MASK,  0xff);
829
830         out8 (SMI_LUT_START, (char)index);
831
832         out8 (SMI_LUT_RGB, r>>2);    /* red */
833         udelay (10);
834         out8 (SMI_LUT_RGB, g>>2);    /* green */
835         udelay (10);
836         out8 (SMI_LUT_RGB, b>>2);    /* blue */
837         udelay (10);
838 }