2 * (C) Copyright 1997-2002 ELTEC Elektronik AG
3 * Frank Gottschling <fgottschling@eltec.de>
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator
29 * modification history
30 * --------------------
31 * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>.
33 * 18-03-2004 - Unify videomodes handling with the ct69000
34 * - The video output can be set via the variable "videoout"
36 * videoout=1 output on LCD
37 * videoout=2 output on CRT (default value)
38 * <p.aubert@staubli.com>
45 #include "videomodes.h"
47 * Export Graphic Device
52 * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
54 #define VIDEO_MEM_SIZE 0x400000
60 #define SMI_INDX_C4 (pGD->isaBase + 0x03c4) /* index reg */
61 #define SMI_DATA_C5 (pGD->isaBase + 0x03c5) /* data reg */
62 #define SMI_INDX_D4 (pGD->isaBase + 0x03d4) /* index reg */
63 #define SMI_DATA_D5 (pGD->isaBase + 0x03d5) /* data reg */
64 #define SMI_ISR1 (pGD->isaBase + 0x03ca)
65 #define SMI_INDX_CE (pGD->isaBase + 0x03ce) /* index reg */
66 #define SMI_DATA_CF (pGD->isaBase + 0x03cf) /* data reg */
67 #define SMI_LOCK_REG (pGD->isaBase + 0x03c3) /* unlock/lock ext crt reg */
68 #define SMI_MISC_REG (pGD->isaBase + 0x03c2) /* misc reg */
69 #define SMI_LUT_MASK (pGD->isaBase + 0x03c6) /* lut mask reg */
70 #define SMI_LUT_START (pGD->isaBase + 0x03c8) /* lut start index */
71 #define SMI_LUT_RGB (pGD->isaBase + 0x03c9) /* lut colors auto incr.*/
72 #define SMI_INDX_ATTR (pGD->isaBase + 0x03c0) /* attributes index reg */
75 * Video processor control
79 unsigned int colorKey
;
80 unsigned int colorKeyMask
;
82 unsigned short offset
;
84 unsigned int fifoPrio
;
86 unsigned int YUVtoRGB
;
90 * Video window control
95 unsigned short bottom
;
97 unsigned int srcStart
;
99 unsigned short offset
;
100 unsigned char hStretch
;
101 unsigned char vStretch
;
105 * Capture port control
108 unsigned int control
;
109 unsigned short topClip
;
110 unsigned short leftClip
;
111 unsigned short srcHeight
;
112 unsigned short srcWidth
;
113 unsigned int srcBufStart1
;
114 unsigned int srcBufStart2
;
115 unsigned short srcOffset
;
116 unsigned short fifoControl
;
121 * Register values for common video modes
123 static char SMI_SCR
[] = {
125 0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x15, 0x90,
126 0x17, 0x20, 0x18, 0xb1, 0x19, 0x00,
128 static char SMI_EXT_CRT
[] = {
129 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
130 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00,
132 static char SMI_ATTR
[] = {
133 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05,
134 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b,
135 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x41, 0x11, 0x00,
136 0x12, 0x0f, 0x13, 0x00, 0x14, 0x00,
138 static char SMI_GCR
[18] = {
139 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
140 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff,
142 static char SMI_SEQR
[] = {
143 0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03,
145 static char SMI_PCR
[] = {
146 0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00,
148 static char SMI_MCR
[] = {
149 0x60, 0x01, 0x61, 0x00,
150 #ifdef CONFIG_HMI1001
151 0x62, 0x74, /* Memory type is not configured by pins on HMI1001 */
155 static char SMI_HCR
[] = {
156 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
157 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00,
161 /*******************************************************************************
163 * Write SMI ISA register
165 static void smiWrite (unsigned short index
, char reg
, char val
)
167 register GraphicDevice
*pGD
= (GraphicDevice
*)&smi
;
169 out8 ((pGD
->isaBase
+ index
), reg
);
170 out8 ((pGD
->isaBase
+ index
+ 1), val
);
173 /*******************************************************************************
175 * Write a table of SMI ISA register
177 static void smiLoadRegs (
184 register GraphicDevice
*pGD
= (GraphicDevice
*)&smi
;
187 for (i
=0; i
<tabSize
; i
+=2) {
188 if (iReg
== SMI_INDX_ATTR
) {
189 /* Reset the Flip Flop */
191 out8 (iReg
, regTab
[i
]);
192 out8 (iReg
, regTab
[i
+1]);
194 out8 (iReg
, regTab
[i
]);
195 out8 (dReg
, regTab
[i
+1]);
200 /*******************************************************************************
202 * Init capture port registers
204 static void smiInitCapturePort (void)
206 SmiCapturePort smiCP
= { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
207 register GraphicDevice
*pGD
= (GraphicDevice
*)&smi
;
208 register SmiCapturePort
*pCP
= (SmiCapturePort
*)&smiCP
;
210 out32r ((pGD
->cprBase
+ 0x0004), ((pCP
->topClip
<<16) | pCP
->leftClip
));
211 out32r ((pGD
->cprBase
+ 0x0008), ((pCP
->srcHeight
<<16) | pCP
->srcWidth
));
212 out32r ((pGD
->cprBase
+ 0x000c), pCP
->srcBufStart1
/8);
213 out32r ((pGD
->cprBase
+ 0x0010), pCP
->srcBufStart2
/8);
214 out32r ((pGD
->cprBase
+ 0x0014), pCP
->srcOffset
/8);
215 out32r ((pGD
->cprBase
+ 0x0018), pCP
->fifoControl
);
216 out32r ((pGD
->cprBase
+ 0x0000), pCP
->control
);
220 /*******************************************************************************
222 * Init video processor registers
224 static void smiInitVideoProcessor (void)
226 SmiVideoProc smiVP
= { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed };
227 SmiVideoWin smiVW
= { 0, 0, 599, 799, 0, 1600, 0, 0, 0 };
228 register GraphicDevice
*pGD
= (GraphicDevice
*)&smi
;
229 register SmiVideoProc
*pVP
= (SmiVideoProc
*)&smiVP
;
230 register SmiVideoWin
*pVWin
= (SmiVideoWin
*)&smiVW
;
232 pVP
->width
= pGD
->plnSizeX
* pGD
->gdfBytesPP
;
233 pVP
->control
|= pGD
->gdfIndex
<< 16;
234 pVWin
->bottom
= pGD
->winSizeY
- 1;
235 pVWin
->right
= pGD
->winSizeX
- 1;
236 pVWin
->width
= pVP
->width
;
239 out32r ((pGD
->vprBase
+ 0x0004), pVP
->colorKey
);
242 out32r ((pGD
->vprBase
+ 0x0008), pVP
->colorKeyMask
);
244 /* data src start adrs */
245 out32r ((pGD
->vprBase
+ 0x000c), pVP
->start
/ 8);
247 /* data width and offset */
248 out32r ((pGD
->vprBase
+ 0x0010),
249 ((pVP
->offset
/ 8 * pGD
->gdfBytesPP
) << 16) |
250 (pGD
->plnSizeX
/ 8 * pGD
->gdfBytesPP
));
253 out32r ((pGD
->vprBase
+ 0x0014),
254 ((pVWin
->top
<< 16) | pVWin
->left
));
256 out32r ((pGD
->vprBase
+ 0x0018),
257 ((pVWin
->bottom
<< 16) | pVWin
->right
));
259 out32r ((pGD
->vprBase
+ 0x001c), pVWin
->srcStart
/ 8);
261 out32r ((pGD
->vprBase
+ 0x0020),
262 (((pVWin
->offset
/ 8) << 16) | (pVWin
->width
/ 8)));
264 out32r ((pGD
->vprBase
+ 0x0024),
265 (((pVWin
->hStretch
) << 8) | pVWin
->vStretch
));
268 out32r ((pGD
->vprBase
+ 0x0028),
269 ((pVWin
->top
<< 16) | pVWin
->left
));
271 out32r ((pGD
->vprBase
+ 0x002c),
272 ((pVWin
->bottom
<< 16) | pVWin
->right
));
274 out32r ((pGD
->vprBase
+ 0x0030),
275 pVWin
->srcStart
/ 8);
277 out32r ((pGD
->vprBase
+ 0x0034),
278 (((pVWin
->offset
/ 8) << 16) | (pVWin
->width
/ 8)));
280 out32r ((pGD
->vprBase
+ 0x0038),
281 (((pVWin
->hStretch
) << 8) | pVWin
->vStretch
));
283 /* fifo prio control */
284 out32r ((pGD
->vprBase
+ 0x0054), pVP
->fifoPrio
);
286 /* fifo empty request levell */
287 out32r ((pGD
->vprBase
+ 0x0058), pVP
->fifoERL
);
289 /* conversion constant */
290 out32r ((pGD
->vprBase
+ 0x005c), pVP
->YUVtoRGB
);
292 /* vpr control word */
293 out32r ((pGD
->vprBase
+ 0x0000), pVP
->control
);
296 /******************************************************************************
298 * Init drawing engine registers
300 static void smiInitDrawingEngine (void)
302 GraphicDevice
*pGD
= (GraphicDevice
*)&smi
;
305 /* don't start now */
306 out32r ((pGD
->dprBase
+ 0x000c), 0x000f0000);
308 /* set rop2 to copypen */
309 val
= 0xffff3ff0 & in32r ((pGD
->dprBase
+ 0x000c));
310 out32r ((pGD
->dprBase
+ 0x000c), (val
| 0x8000 | 0x0c));
313 out32r ((pGD
->dprBase
+ 0x002c), 0);
314 out32r ((pGD
->dprBase
+ 0x0030),
315 ((pGD
->winSizeY
<<16) | pGD
->winSizeX
* pGD
->gdfBytesPP
));
318 val
= 0xffff0000 & (in32r ((pGD
->dprBase
+ 0x0010)));
319 out32r ((pGD
->dprBase
+ 0x0010),
320 (val
| pGD
->plnSizeX
* pGD
->gdfBytesPP
));
323 val
= 0x0000ffff & (in32r ((pGD
->dprBase
+ 0x0010)));
324 out32r ((pGD
->dprBase
+ 0x0010),
325 (((pGD
->plnSizeX
* pGD
->gdfBytesPP
)<<16) | val
));
327 /* window width src/dst */
328 out32r ((pGD
->dprBase
+ 0x003c),
329 (((pGD
->plnSizeX
* pGD
->gdfBytesPP
& 0x0fff)<<16) |
330 (pGD
->plnSizeX
* pGD
->gdfBytesPP
& 0x0fff)));
331 out16r ((pGD
->dprBase
+ 0x001e), 0x0000);
334 out32r ((pGD
->dprBase
+ 0x0040),
335 (((pGD
->frameAdrs
/8) & 0x000fffff)));
338 out32r ((pGD
->dprBase
+ 0x0044),
339 (((pGD
->frameAdrs
/8) & 0x000fffff)));
341 /* foreground color */
342 out32r ((pGD
->dprBase
+ 0x0014), pGD
->fg
);
344 /* background color */
345 out32r ((pGD
->dprBase
+ 0x0018), pGD
->bg
);
348 out32r ((pGD
->dprBase
+ 0x0020), 0x00ffffff);
351 out32r ((pGD
->dprBase
+ 0x0024), 0x00ffffff);
354 out32r ((pGD
->dprBase
+ 0x0028), 0x00ffffff);
356 /* load mono pattern */
357 out32r ((pGD
->dprBase
+ 0x0034), 0);
358 out32r ((pGD
->dprBase
+ 0x0038), 0);
361 static struct pci_device_id supported
[] = {
362 { PCI_VENDOR_ID_SMI
, PCI_DEVICE_ID_SMI_710
},
363 { PCI_VENDOR_ID_SMI
, PCI_DEVICE_ID_SMI_712
},
364 { PCI_VENDOR_ID_SMI
, PCI_DEVICE_ID_SMI_810
},
368 /*****************************************************************************/
369 static void smiLoadMsr (struct ctfb_res_modes
*mode
)
371 unsigned char h_synch_high
, v_synch_high
;
372 register GraphicDevice
*pGD
= (GraphicDevice
*)&smi
;
374 h_synch_high
= (mode
->sync
& FB_SYNC_HOR_HIGH_ACT
) ? 0 : 0x40; /* horizontal Synch High active */
375 v_synch_high
= (mode
->sync
& FB_SYNC_VERT_HIGH_ACT
) ? 0 : 0x80; /* vertical Synch High active */
376 out8 (SMI_MISC_REG
, (h_synch_high
| v_synch_high
| 0x29));
377 /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
378 * Selects the upper 64KB page.Bit5=1
379 * CLK2 (left reserved in standard VGA) Bit3|2=1|0
380 * Disables CPU access to frame buffer. Bit1=0
381 * Sets the I/O address decode for ST01, FCR, and all CR registers
382 * to the 3Dx I/O address range (CGA emulation). Bit0=1
385 /*****************************************************************************/
386 static void smiLoadCrt (struct ctfb_res_modes
*var
, int bits_per_pixel
)
388 unsigned char cr
[0x7a];
390 unsigned int hd
, hs
, he
, ht
, hbs
, hbe
; /* Horizontal. */
391 unsigned int vd
, vs
, ve
, vt
, vbs
, vbe
; /* vertical */
392 unsigned int bpp
, wd
, dblscan
, interlaced
;
394 const int LineCompare
= 0x3ff;
395 unsigned int TextScanLines
= 1; /* this is in fact a vertical zoom factor */
396 register GraphicDevice
*pGD
= (GraphicDevice
*)&smi
;
399 hd
= (var
->xres
) / 8; /* HDisp. */
400 hs
= (var
->xres
+ var
->right_margin
) / 8; /* HsStrt */
401 he
= (var
->xres
+ var
->right_margin
+ var
->hsync_len
) / 8; /* HsEnd */
402 ht
= (var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
) / 8; /* HTotal */
405 hbe
= 0; /* Blank end at 0 */
408 vd
= var
->yres
; /* VDisplay */
409 vs
= var
->yres
+ var
->lower_margin
; /* VSyncStart */
410 ve
= var
->yres
+ var
->lower_margin
+ var
->vsync_len
; /* VSyncEnd */
411 vt
= var
->upper_margin
+ var
->yres
+ var
->lower_margin
+ var
->vsync_len
; /* VTotal */
415 bpp
= bits_per_pixel
;
416 dblscan
= (var
->vmode
& FB_VMODE_DOUBLE
) ? 1 : 0;
417 interlaced
= var
->vmode
& FB_VMODE_INTERLACED
;
422 wd
= var
->xres
* bpp
/ 64; /* double words per line */
423 if (interlaced
) { /* we divide all vertical timings, exept vd */
430 memset (cr
, 0, sizeof (cr
));
434 cr
[0x03] = (hbe
& 0x1F);
436 cr
[0x05] = ((hbe
& 0x20) << 2) | (he
& 0x1f);
438 cr
[0x06] = (vt
- 2) & 0xFF;
439 cr
[0x07] = (((vt
- 2) & 0x100) >> 8)
440 | (((vd
- 1) & 0x100) >> 7)
441 | ((vs
& 0x100) >> 6)
442 | (((vbs
- 1) & 0x100) >> 5)
443 | ((LineCompare
& 0x100) >> 4)
444 | (((vt
- 2) & 0x200) >> 4)
445 | (((vd
- 1) & 0x200) >> 3)
446 | ((vs
& 0x200) >> 2);
448 cr
[0x30] = ((vt
- 2) & 0x400) >> 7
449 | (((vd
- 1) & 0x400) >> 8)
450 | (((vbs
- 1) & 0x400) >> 9)
451 | ((vs
& 0x400) >> 10)
452 | (interlaced
) ? 0x80 : 0;
456 cr
[0x09] = (dblscan
<< 7)
457 | ((LineCompare
& 0x200) >> 3)
458 | (((vbs
- 1) & 0x200) >> 4)
459 | (TextScanLines
- 1);
461 cr
[0x10] = vs
& 0xff; /* VSyncPulseStart */
462 cr
[0x11] = (ve
& 0x0f);
463 cr
[0x12] = (vd
- 1) & 0xff; /* LineCount */
464 cr
[0x13] = wd
& 0xff;
466 cr
[0x15] = (vbs
- 1) & 0xff;
467 cr
[0x16] = vbe
& 0xff;
468 cr
[0x17] = 0xe3; /* but it does not work */
469 cr
[0x18] = 0xff & LineCompare
;
470 cr
[0x22] = 0x00; /* todo? */
473 /* now set the registers */
474 for (i
= 0; i
<= 0x18; i
++) { /*CR00 .. CR18 */
475 smiWrite (SMI_INDX_D4
, i
, cr
[i
]);
478 smiWrite (SMI_INDX_D4
, i
, cr
[i
]);
480 smiWrite (SMI_INDX_D4
, i
, cr
[i
]);
483 /*****************************************************************************/
484 #define REF_FREQ 14318180
490 static unsigned int FindPQ (unsigned int freq
, unsigned int *pp
, unsigned int *pq
)
492 unsigned int n
= QMIN
, m
= 0;
493 long long int L
= 0, P
= freq
, Q
= REF_FREQ
, H
= P
>> 1;
494 long long int D
= 0x7ffffffffffffffLL
;
496 for (n
= QMIN
; n
<= QMAX
; n
++) {
497 m
= PMIN
; /* p/q ~ freq/ref -> p*ref-freq*q ~ 0 */
499 while (L
> 0 && m
< PMAX
) {
500 L
-= REF_FREQ
; /* difference is greater as 0 subtract fref */
501 m
++; /* and increment m */
503 /* difference is less or equal than 0 or m > maximum */
505 break; /* no solution: if we increase n we get the same situation */
507 if (-L
> H
&& m
> PMIN
) { /* if difference > the half fref */
508 L
+= REF_FREQ
; /* we take the situation before */
509 m
--; /* because its closer to 0 */
511 L
= (L
< 0) ? -L
: +L
; /* absolute value */
512 if (D
< L
) /* if last difference was better take next n */
516 *pq
= n
; /* keep improved data */
518 break; /* best result we can get */
520 return (unsigned int) (0xffffffff & D
);
523 /*****************************************************************************/
524 static void smiLoadCcr (struct ctfb_res_modes
*var
, unsigned short device_id
)
529 register GraphicDevice
*pGD
= (GraphicDevice
*)&smi
;
531 smiWrite (SMI_INDX_C4
, 0x65, 0);
532 smiWrite (SMI_INDX_C4
, 0x66, 0);
533 smiWrite (SMI_INDX_C4
, 0x68, 0x50);
534 if (device_id
== PCI_DEVICE_ID_SMI_810
) {
535 smiWrite (SMI_INDX_C4
, 0x69, 0x3);
537 smiWrite (SMI_INDX_C4
, 0x69, 0x0);
542 case PCI_DEVICE_ID_SMI_710
:
543 smiWrite (SMI_INDX_C4
, 0x6a, 0x75);
545 case PCI_DEVICE_ID_SMI_712
:
546 smiWrite (SMI_INDX_C4
, 0x6a, 0x80);
549 smiWrite (SMI_INDX_C4
, 0x6a, 0x53);
552 smiWrite (SMI_INDX_C4
, 0x6b, 0x15);
555 freq
= 1000000000000LL / var
-> pixclock
;
557 FindPQ ((unsigned int)freq
, &p
, &q
);
559 smiWrite (SMI_INDX_C4
, 0x6c, p
);
560 smiWrite (SMI_INDX_C4
, 0x6d, q
);
564 /*******************************************************************************
566 * Init video chip with common Linux graphic modes (lilo)
568 void *video_hw_init (void)
570 GraphicDevice
*pGD
= (GraphicDevice
*)&smi
;
571 unsigned short device_id
;
574 unsigned long t1
, hsynch
, vsynch
;
575 unsigned int pci_mem_base
, *vm
;
577 int tmp
, i
, bits_per_pixel
;
578 struct ctfb_res_modes
*res_mode
;
579 struct ctfb_res_modes var_mode
;
580 unsigned char videoout
;
582 /* Search for video chip */
585 if ((devbusfn
= pci_find_devices(supported
, 0)) < 0)
587 printf ("Controller not found !\n");
592 pci_write_config_dword (devbusfn
, PCI_COMMAND
, (PCI_COMMAND_MEMORY
| PCI_COMMAND_IO
));
593 pci_read_config_word (devbusfn
, PCI_DEVICE_ID
, &device_id
);
594 pci_read_config_dword (devbusfn
, PCI_BASE_ADDRESS_0
, &pci_mem_base
);
595 pci_mem_base
= pci_mem_to_phys (devbusfn
, pci_mem_base
);
599 videomode
= CONFIG_SYS_DEFAULT_VIDEO_MODE
;
600 /* get video mode via environment */
601 if ((penv
= getenv ("videomode")) != NULL
) {
602 /* deceide if it is a string */
603 if (penv
[0] <= '9') {
604 videomode
= (int) simple_strtoul (penv
, NULL
, 16);
611 /* parameter are vesa modes */
613 for (i
= 0; i
< VESA_MODES_COUNT
; i
++) {
614 if (vesa_modes
[i
].vesanr
== videomode
)
617 if (i
== VESA_MODES_COUNT
) {
618 printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE
);
622 (struct ctfb_res_modes
*) &res_mode_init
[vesa_modes
[i
].
624 bits_per_pixel
= vesa_modes
[i
].bits_per_pixel
;
627 res_mode
= (struct ctfb_res_modes
*) &var_mode
;
628 bits_per_pixel
= video_get_params (res_mode
, penv
);
631 /* calculate hsynch and vsynch freq (info only) */
632 t1
= (res_mode
->left_margin
+ res_mode
->xres
+
633 res_mode
->right_margin
+ res_mode
->hsync_len
) / 8;
635 t1
*= res_mode
->pixclock
;
637 hsynch
= 1000000000L / t1
;
639 (res_mode
->upper_margin
+ res_mode
->yres
+
640 res_mode
->lower_margin
+ res_mode
->vsync_len
);
642 vsynch
= 1000000000L / t1
;
644 /* fill in Graphic device struct */
645 sprintf (pGD
->modeIdent
, "%dx%dx%d %ldkHz %ldHz", res_mode
->xres
,
646 res_mode
->yres
, bits_per_pixel
, (hsynch
/ 1000),
648 printf ("%s\n", pGD
->modeIdent
);
649 pGD
->winSizeX
= res_mode
->xres
;
650 pGD
->winSizeY
= res_mode
->yres
;
651 pGD
->plnSizeX
= res_mode
->xres
;
652 pGD
->plnSizeY
= res_mode
->yres
;
653 switch (bits_per_pixel
) {
656 pGD
->gdfIndex
= GDF__8BIT_INDEX
;
660 pGD
->gdfIndex
= GDF_15BIT_555RGB
;
664 pGD
->gdfIndex
= GDF_16BIT_565RGB
;
668 pGD
->gdfIndex
= GDF_24BIT_888RGB
;
672 pGD
->isaBase
= CONFIG_SYS_ISA_IO
;
673 pGD
->pciBase
= pci_mem_base
;
674 pGD
->dprBase
= (pci_mem_base
+ 0x400000 + 0x8000);
675 pGD
->vprBase
= (pci_mem_base
+ 0x400000 + 0xc000);
676 pGD
->cprBase
= (pci_mem_base
+ 0x400000 + 0xe000);
677 pGD
->frameAdrs
= pci_mem_base
;
678 pGD
->memSize
= VIDEO_MEM_SIZE
;
680 /* Set up hardware : select color mode,
681 set Register base to isa 3dx for 3?x regs*/
682 out8 (SMI_MISC_REG
, 0x01);
684 /* Turn off display */
685 smiWrite (SMI_INDX_C4
, 0x01, 0x20);
687 /* Unlock ext. crt regs */
688 out8 (SMI_LOCK_REG
, 0x40);
690 /* Unlock crt regs 0-7 */
691 smiWrite (SMI_INDX_D4
, 0x11, 0x0e);
693 /* Sytem Control Register */
694 smiLoadRegs (SMI_INDX_C4
, SMI_DATA_C5
, SMI_SCR
, sizeof(SMI_SCR
));
696 /* extented CRT Register */
697 smiLoadRegs (SMI_INDX_D4
, SMI_DATA_D5
, SMI_EXT_CRT
, sizeof(SMI_EXT_CRT
));
699 /* Attributes controller registers */
700 smiLoadRegs (SMI_INDX_ATTR
, SMI_INDX_ATTR
, SMI_ATTR
, sizeof(SMI_ATTR
));
702 /* Graphics Controller Register */
703 smiLoadRegs (SMI_INDX_CE
, SMI_DATA_CF
, SMI_GCR
, sizeof(SMI_GCR
));
705 /* Sequencer Register */
706 smiLoadRegs (SMI_INDX_C4
, SMI_DATA_C5
, SMI_SEQR
, sizeof(SMI_SEQR
));
708 /* Power Control Register */
709 smiLoadRegs (SMI_INDX_C4
, SMI_DATA_C5
, SMI_PCR
, sizeof(SMI_PCR
));
711 /* Memory Control Register */
712 /* Register MSR62 is a power on configurable register. We don't */
714 smiLoadRegs (SMI_INDX_C4
, SMI_DATA_C5
, SMI_MCR
, sizeof(SMI_MCR
));
716 /* Set misc output register */
717 smiLoadMsr (res_mode
);
719 /* Set CRT and Clock control registers */
720 smiLoadCrt (res_mode
, bits_per_pixel
);
722 smiLoadCcr (res_mode
, device_id
);
724 /* Hardware Cusor Register */
725 smiLoadRegs (SMI_INDX_C4
, SMI_DATA_C5
, SMI_HCR
, sizeof(SMI_HCR
));
728 videoout
= 2; /* Default output is CRT */
729 if ((penv
= getenv ("videoout")) != NULL
) {
730 /* deceide if it is a string */
731 videoout
= (int) simple_strtoul (penv
, NULL
, 16);
733 smiWrite (SMI_INDX_C4
, 0x31, videoout
);
735 /* Video processor default setup */
736 smiInitVideoProcessor ();
738 /* Capture port default setup */
739 smiInitCapturePort ();
741 /* Drawing engine default setup */
742 smiInitDrawingEngine ();
744 /* Turn on display */
745 smiWrite (0x3c4, 0x01, 0x01);
747 /* Clear video memory */
749 vm
= (unsigned int *)pGD
->pciBase
;
752 return ((void*)&smi
);
755 /*******************************************************************************
757 * Drawing engine fill on screen region
759 void video_hw_rectfill (
760 unsigned int bpp
, /* bytes per pixel */
761 unsigned int dst_x
, /* dest pos x */
762 unsigned int dst_y
, /* dest pos y */
763 unsigned int dim_x
, /* frame width */
764 unsigned int dim_y
, /* frame height */
765 unsigned int color
/* fill color */
768 register GraphicDevice
*pGD
= (GraphicDevice
*)&smi
;
769 register unsigned int control
;
773 out32r ((pGD
->dprBase
+ 0x0014), color
);
774 out32r ((pGD
->dprBase
+ 0x0004), ((dst_x
<<16) | dst_y
));
775 out32r ((pGD
->dprBase
+ 0x0008), ((dim_x
<<16) | dim_y
));
777 control
= 0x0000ffff & in32r ((pGD
->dprBase
+ 0x000c));
779 control
|= 0x80010000;
781 out32r ((pGD
->dprBase
+ 0x000c), control
);
783 /* Wait for drawing processor */
786 out8 ((pGD
->isaBase
+ 0x3c4), 0x16);
787 } while (in8 (pGD
->isaBase
+ 0x3c5) & 0x08);
790 /*******************************************************************************
792 * Drawing engine bitblt with screen region
794 void video_hw_bitblt (
795 unsigned int bpp
, /* bytes per pixel */
796 unsigned int src_x
, /* source pos x */
797 unsigned int src_y
, /* source pos y */
798 unsigned int dst_x
, /* dest pos x */
799 unsigned int dst_y
, /* dest pos y */
800 unsigned int dim_x
, /* frame width */
801 unsigned int dim_y
/* frame height */
804 register GraphicDevice
*pGD
= (GraphicDevice
*)&smi
;
805 register unsigned int control
;
809 if ((src_y
<dst_y
) || ((src_y
==dst_y
) && (src_x
<dst_x
)))
811 out32r ((pGD
->dprBase
+ 0x0000), (((src_x
+dim_x
-1)<<16) | (src_y
+dim_y
-1)));
812 out32r ((pGD
->dprBase
+ 0x0004), (((dst_x
+dim_x
-1)<<16) | (dst_y
+dim_y
-1)));
813 control
= 0x88000000;
815 out32r ((pGD
->dprBase
+ 0x0000), ((src_x
<<16) | src_y
));
816 out32r ((pGD
->dprBase
+ 0x0004), ((dst_x
<<16) | dst_y
));
817 control
= 0x80000000;
820 out32r ((pGD
->dprBase
+ 0x0008), ((dim_x
<<16) | dim_y
));
821 control
|= (0x0000ffff & in32r ((pGD
->dprBase
+ 0x000c)));
822 out32r ((pGD
->dprBase
+ 0x000c), control
);
824 /* Wait for drawing processor */
827 out8 ((pGD
->isaBase
+ 0x3c4), 0x16);
828 } while (in8 (pGD
->isaBase
+ 0x3c5) & 0x08);
831 /*******************************************************************************
833 * Set a RGB color in the LUT (8 bit index)
836 unsigned int index
, /* color number */
837 unsigned char r
, /* red */
838 unsigned char g
, /* green */
839 unsigned char b
/* blue */
842 register GraphicDevice
*pGD
= (GraphicDevice
*)&smi
;
844 out8 (SMI_LUT_MASK
, 0xff);
846 out8 (SMI_LUT_START
, (char)index
);
848 out8 (SMI_LUT_RGB
, r
>>2); /* red */
850 out8 (SMI_LUT_RGB
, g
>>2); /* green */
852 out8 (SMI_LUT_RGB
, b
>>2); /* blue */