]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/video/smiLynxEM.c
Convert CONFIG_VIDEO_CT69000 to Kconfig
[people/ms/u-boot.git] / drivers / video / smiLynxEM.c
CommitLineData
c609719b
WD
1/*
2 * (C) Copyright 1997-2002 ELTEC Elektronik AG
3 * Frank Gottschling <fgottschling@eltec.de>
4 *
1a459660 5 * SPDX-License-Identifier: GPL-2.0+
c609719b
WD
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 *
eeb1b77b
WD
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>
c609719b
WD
23 */
24
25#include <common.h>
26
c609719b
WD
27#include <pci.h>
28#include <video_fb.h>
eeb1b77b 29#include "videomodes.h"
c609719b
WD
30/*
31 * Export Graphic Device
32 */
33GraphicDevice smi;
34
35/*
36 * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
37 */
eeb1b77b 38#define VIDEO_MEM_SIZE 0x400000
c609719b
WD
39
40
41/*
42 * ISA mapped regs
43 */
eeb1b77b
WD
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 */
c609719b
WD
57
58/*
59 * Video processor control
eeb1b77b 60 */
c609719b 61typedef struct {
eeb1b77b
WD
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;
c609719b
WD
71} SmiVideoProc;
72
73/*
74 * Video window control
75 */
76typedef struct {
eeb1b77b
WD
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;
c609719b
WD
86} SmiVideoWin;
87
88/*
89 * Capture port control
90 */
91typedef struct {
eeb1b77b
WD
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;
c609719b
WD
101} SmiCapturePort;
102
103
c609719b
WD
104/*
105 * Register values for common video modes
106 */
eeb1b77b
WD
107static char SMI_SCR[] = {
108 /* all modes */
109 0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x15, 0x90,
110 0x17, 0x20, 0x18, 0xb1, 0x19, 0x00,
c609719b 111};
eeb1b77b
WD
112static char SMI_EXT_CRT[] = {
113 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
ccd9d3d6 114 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00,
c609719b 115};
eeb1b77b
WD
116static 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,
c609719b 121};
eeb1b77b
WD
122static char SMI_GCR[18] = {
123 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
ccd9d3d6 124 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff,
c609719b 125};
eeb1b77b 126static char SMI_SEQR[] = {
ccd9d3d6 127 0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03,
c609719b 128};
eeb1b77b 129static char SMI_PCR [] = {
ccd9d3d6 130 0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00,
c609719b 131};
eeb1b77b 132static char SMI_MCR[] = {
b79a11cc 133 0x60, 0x01, 0x61, 0x00,
c609719b
WD
134};
135
eeb1b77b
WD
136static char SMI_HCR[] = {
137 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
ccd9d3d6 138 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00,
c609719b
WD
139};
140
c609719b
WD
141
142/*******************************************************************************
eeb1b77b
WD
143 *
144 * Write SMI ISA register
145 */
c609719b
WD
146static void smiWrite (unsigned short index, char reg, char val)
147{
eeb1b77b 148 register GraphicDevice *pGD = (GraphicDevice *)&smi;
c609719b 149
eeb1b77b
WD
150 out8 ((pGD->isaBase + index), reg);
151 out8 ((pGD->isaBase + index + 1), val);
c609719b
WD
152}
153
154/*******************************************************************************
eeb1b77b
WD
155 *
156 * Write a table of SMI ISA register
157 */
c609719b 158static void smiLoadRegs (
eeb1b77b
WD
159 unsigned int iReg,
160 unsigned int dReg,
161 char *regTab,
162 unsigned int tabSize
163 )
c609719b 164{
eeb1b77b
WD
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 }
c609719b
WD
179}
180
181/*******************************************************************************
eeb1b77b
WD
182 *
183 * Init capture port registers
184 */
c609719b
WD
185static void smiInitCapturePort (void)
186{
eeb1b77b
WD
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);
c609719b
WD
198}
199
200
201/*******************************************************************************
eeb1b77b
WD
202 *
203 * Init video processor registers
204 */
c609719b
WD
205static void smiInitVideoProcessor (void)
206{
eeb1b77b
WD
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;
c609719b 212
eeb1b77b
WD
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;
c609719b 218
eeb1b77b
WD
219 /* color key */
220 out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
c609719b 221
eeb1b77b
WD
222 /* color key mask */
223 out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
c609719b 224
eeb1b77b
WD
225 /* data src start adrs */
226 out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
c609719b 227
eeb1b77b
WD
228 /* data width and offset */
229 out32r ((pGD->vprBase + 0x0010),
230 ((pVP->offset / 8 * pGD->gdfBytesPP) << 16) |
231 (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
c609719b 232
eeb1b77b
WD
233 /* video window 1 */
234 out32r ((pGD->vprBase + 0x0014),
235 ((pVWin->top << 16) | pVWin->left));
c609719b 236
eeb1b77b
WD
237 out32r ((pGD->vprBase + 0x0018),
238 ((pVWin->bottom << 16) | pVWin->right));
c609719b 239
eeb1b77b 240 out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
c609719b 241
eeb1b77b
WD
242 out32r ((pGD->vprBase + 0x0020),
243 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
c609719b 244
eeb1b77b
WD
245 out32r ((pGD->vprBase + 0x0024),
246 (((pVWin->hStretch) << 8) | pVWin->vStretch));
c609719b 247
eeb1b77b
WD
248 /* video window 2 */
249 out32r ((pGD->vprBase + 0x0028),
250 ((pVWin->top << 16) | pVWin->left));
c609719b 251
eeb1b77b
WD
252 out32r ((pGD->vprBase + 0x002c),
253 ((pVWin->bottom << 16) | pVWin->right));
c609719b 254
eeb1b77b
WD
255 out32r ((pGD->vprBase + 0x0030),
256 pVWin->srcStart / 8);
c609719b 257
eeb1b77b
WD
258 out32r ((pGD->vprBase + 0x0034),
259 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
c609719b 260
eeb1b77b
WD
261 out32r ((pGD->vprBase + 0x0038),
262 (((pVWin->hStretch) << 8) | pVWin->vStretch));
c609719b 263
eeb1b77b
WD
264 /* fifo prio control */
265 out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
c609719b 266
eeb1b77b
WD
267 /* fifo empty request levell */
268 out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
c609719b 269
eeb1b77b
WD
270 /* conversion constant */
271 out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
c609719b 272
eeb1b77b
WD
273 /* vpr control word */
274 out32r ((pGD->vprBase + 0x0000), pVP->control);
c609719b
WD
275}
276
277/******************************************************************************
278 *
279 * Init drawing engine registers
280 */
281static void smiInitDrawingEngine (void)
282{
eeb1b77b
WD
283 GraphicDevice *pGD = (GraphicDevice *)&smi;
284 unsigned int val;
c609719b 285
eeb1b77b
WD
286 /* don't start now */
287 out32r ((pGD->dprBase + 0x000c), 0x000f0000);
c609719b 288
eeb1b77b
WD
289 /* set rop2 to copypen */
290 val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
291 out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
c609719b 292
eeb1b77b
WD
293 /* set clip rect */
294 out32r ((pGD->dprBase + 0x002c), 0);
295 out32r ((pGD->dprBase + 0x0030),
296 ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
c609719b 297
eeb1b77b
WD
298 /* src row pitch */
299 val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
300 out32r ((pGD->dprBase + 0x0010),
301 (val | pGD->plnSizeX * pGD->gdfBytesPP));
c609719b 302
eeb1b77b
WD
303 /* dst row pitch */
304 val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
305 out32r ((pGD->dprBase + 0x0010),
306 (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
c609719b 307
eeb1b77b
WD
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);
c609719b 313
eeb1b77b
WD
314 /* src base adrs */
315 out32r ((pGD->dprBase + 0x0040),
316 (((pGD->frameAdrs/8) & 0x000fffff)));
c609719b 317
eeb1b77b
WD
318 /* dst base adrs */
319 out32r ((pGD->dprBase + 0x0044),
320 (((pGD->frameAdrs/8) & 0x000fffff)));
c609719b 321
eeb1b77b
WD
322 /* foreground color */
323 out32r ((pGD->dprBase + 0x0014), pGD->fg);
c609719b 324
eeb1b77b
WD
325 /* background color */
326 out32r ((pGD->dprBase + 0x0018), pGD->bg);
c609719b 327
eeb1b77b
WD
328 /* xcolor */
329 out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
c609719b 330
eeb1b77b
WD
331 /* xcolor mask */
332 out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
c609719b 333
eeb1b77b
WD
334 /* bit mask */
335 out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
c609719b 336
eeb1b77b
WD
337 /* load mono pattern */
338 out32r ((pGD->dprBase + 0x0034), 0);
339 out32r ((pGD->dprBase + 0x0038), 0);
c609719b
WD
340}
341
342static struct pci_device_id supported[] = {
eeb1b77b
WD
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 { }
c609719b
WD
347};
348
eeb1b77b
WD
349/*****************************************************************************/
350static 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/*****************************************************************************/
367static 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 */
b79a11cc 385 hbs = hd;
eeb1b77b
WD
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;
b79a11cc 395
eeb1b77b
WD
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);
b79a11cc 418
eeb1b77b
WD
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;
b79a11cc 434
eeb1b77b
WD
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 */
b79a11cc 443 cr[0x11] = (ve & 0x0f);
eeb1b77b
WD
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
471static 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 */
b79a11cc 479 L = P * n - m * Q;
eeb1b77b
WD
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/*****************************************************************************/
505static void smiLoadCcr (struct ctfb_res_modes *var, unsigned short device_id)
506{
77ddac94
WD
507 unsigned int p = 0;
508 unsigned int q = 0;
eeb1b77b
WD
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);
b79a11cc 534
eeb1b77b 535 /* VCLK */
eedcd078 536 freq = 1000000000000LL / var -> pixclock;
b79a11cc 537
eeb1b77b 538 FindPQ ((unsigned int)freq, &p, &q);
b79a11cc 539
eeb1b77b
WD
540 smiWrite (SMI_INDX_C4, 0x6c, p);
541 smiWrite (SMI_INDX_C4, 0x6d, q);
542
543}
c609719b
WD
544
545/*******************************************************************************
eeb1b77b
WD
546 *
547 * Init video chip with common Linux graphic modes (lilo)
548 */
c609719b
WD
549void *video_hw_init (void)
550{
eeb1b77b
WD
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;
b79a11cc 562
eeb1b77b
WD
563 /* Search for video chip */
564 printf("Video: ");
565
566 if ((devbusfn = pci_find_devices(supported, 0)) < 0)
8bde7f77 567 {
eeb1b77b
WD
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;
b79a11cc 579
6d0f6bcf 580 videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE;
eeb1b77b
WD
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) {
6d0f6bcf 599 printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE);
eeb1b77b
WD
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 {
b79a11cc 607
eeb1b77b
WD
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;
b79a11cc 624
eeb1b77b
WD
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;
8bde7f77 651 }
eeb1b77b 652
6d0f6bcf 653 pGD->isaBase = CONFIG_SYS_ISA_IO;
eeb1b77b
WD
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));
b79a11cc 682
eeb1b77b
WD
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);
b79a11cc 699
eeb1b77b
WD
700 /* Set CRT and Clock control registers */
701 smiLoadCrt (res_mode, bits_per_pixel);
b79a11cc 702
eeb1b77b
WD
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);
c609719b
WD
734}
735
736/*******************************************************************************
eeb1b77b
WD
737 *
738 * Drawing engine fill on screen region
739 */
c609719b 740void video_hw_rectfill (
eeb1b77b
WD
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 )
c609719b 748{
eeb1b77b
WD
749 register GraphicDevice *pGD = (GraphicDevice *)&smi;
750 register unsigned int control;
c609719b 751
eeb1b77b 752 dim_x *= bpp;
c609719b 753
eeb1b77b
WD
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));
c609719b 757
eeb1b77b 758 control = 0x0000ffff & in32r ((pGD->dprBase + 0x000c));
c609719b 759
eeb1b77b 760 control |= 0x80010000;
c609719b 761
eeb1b77b 762 out32r ((pGD->dprBase + 0x000c), control);
c609719b 763
eeb1b77b
WD
764 /* Wait for drawing processor */
765 do
766 {
767 out8 ((pGD->isaBase + 0x3c4), 0x16);
768 } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
c609719b
WD
769}
770
771/*******************************************************************************
eeb1b77b
WD
772 *
773 * Drawing engine bitblt with screen region
774 */
c609719b 775void video_hw_bitblt (
eeb1b77b
WD
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 )
c609719b 784{
eeb1b77b
WD
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);
c609719b
WD
810}
811
812/*******************************************************************************
eeb1b77b
WD
813 *
814 * Set a RGB color in the LUT (8 bit index)
815 */
c609719b 816void video_set_lut (
eeb1b77b
WD
817 unsigned int index, /* color number */
818 unsigned char r, /* red */
819 unsigned char g, /* green */
820 unsigned char b /* blue */
821 )
c609719b 822{
eeb1b77b 823 register GraphicDevice *pGD = (GraphicDevice *)&smi;
c609719b 824
eeb1b77b 825 out8 (SMI_LUT_MASK, 0xff);
c609719b 826
eeb1b77b 827 out8 (SMI_LUT_START, (char)index);
c609719b 828
eeb1b77b
WD
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);
c609719b 835}