]> git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/video/smiLynxEM.c
pxa_lcd: invert colors for Zipit Z2 to get white on black palette
[people/ms/u-boot.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 }