]> git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/video/smiLynxEM.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[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 #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 }