blob: 614bcb3c92c2948f47184640d08d285d0148f181 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
2 * (C) Copyright 1997-2002 ELTEC Elektronik AG
3 * Frank Gottschling <fgottschling@eltec.de>
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenkc6097192002-11-03 00:24:07 +00006 */
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 *
wdenkeeb1b772004-03-23 22:53:55 +000017 * 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>
wdenkc6097192002-11-03 00:24:07 +000023 */
24
25#include <common.h>
26
wdenkc6097192002-11-03 00:24:07 +000027#include <pci.h>
28#include <video_fb.h>
wdenkeeb1b772004-03-23 22:53:55 +000029#include "videomodes.h"
wdenkc6097192002-11-03 00:24:07 +000030/*
31 * Export Graphic Device
32 */
33GraphicDevice smi;
34
35/*
36 * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
37 */
wdenkeeb1b772004-03-23 22:53:55 +000038#define VIDEO_MEM_SIZE 0x400000
wdenkc6097192002-11-03 00:24:07 +000039
40
41/*
42 * ISA mapped regs
43 */
wdenkeeb1b772004-03-23 22:53:55 +000044#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 */
wdenkc6097192002-11-03 00:24:07 +000057
58/*
59 * Video processor control
wdenkeeb1b772004-03-23 22:53:55 +000060 */
wdenkc6097192002-11-03 00:24:07 +000061typedef struct {
wdenkeeb1b772004-03-23 22:53:55 +000062 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;
wdenkc6097192002-11-03 00:24:07 +000071} SmiVideoProc;
72
73/*
74 * Video window control
75 */
76typedef struct {
wdenkeeb1b772004-03-23 22:53:55 +000077 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;
wdenkc6097192002-11-03 00:24:07 +000086} SmiVideoWin;
87
88/*
89 * Capture port control
90 */
91typedef struct {
wdenkeeb1b772004-03-23 22:53:55 +000092 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;
wdenkc6097192002-11-03 00:24:07 +0000101} SmiCapturePort;
102
103
wdenkc6097192002-11-03 00:24:07 +0000104/*
105 * Register values for common video modes
106 */
wdenkeeb1b772004-03-23 22:53:55 +0000107static char SMI_SCR[] = {
108 /* all modes */
109 0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x15, 0x90,
110 0x17, 0x20, 0x18, 0xb1, 0x19, 0x00,
wdenkc6097192002-11-03 00:24:07 +0000111};
wdenkeeb1b772004-03-23 22:53:55 +0000112static char SMI_EXT_CRT[] = {
113 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
Wolfgang Denkccd9d3d2005-09-03 01:21:50 +0200114 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00,
wdenkc6097192002-11-03 00:24:07 +0000115};
wdenkeeb1b772004-03-23 22:53:55 +0000116static 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,
wdenkc6097192002-11-03 00:24:07 +0000121};
wdenkc6097192002-11-03 00:24:07 +0000122static char SMI_GCR[18] = {
wdenkeeb1b772004-03-23 22:53:55 +0000123 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
Wolfgang Denkccd9d3d2005-09-03 01:21:50 +0200124 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff,
wdenkeeb1b772004-03-23 22:53:55 +0000125};
126static char SMI_SEQR[] = {
Wolfgang Denkccd9d3d2005-09-03 01:21:50 +0200127 0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03,
wdenkeeb1b772004-03-23 22:53:55 +0000128};
129static char SMI_PCR [] = {
Wolfgang Denkccd9d3d2005-09-03 01:21:50 +0200130 0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00,
wdenkeeb1b772004-03-23 22:53:55 +0000131};
132static char SMI_MCR[] = {
wdenkb79a11c2004-03-25 15:14:43 +0000133 0x60, 0x01, 0x61, 0x00,
Wolfgang Denkccd9d3d2005-09-03 01:21:50 +0200134#ifdef CONFIG_HMI1001
135 0x62, 0x74, /* Memory type is not configured by pins on HMI1001 */
136#endif
wdenkc6097192002-11-03 00:24:07 +0000137};
138
wdenkeeb1b772004-03-23 22:53:55 +0000139static char SMI_HCR[] = {
140 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
Wolfgang Denkccd9d3d2005-09-03 01:21:50 +0200141 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00,
wdenkeeb1b772004-03-23 22:53:55 +0000142};
wdenkc6097192002-11-03 00:24:07 +0000143
wdenkc6097192002-11-03 00:24:07 +0000144
145/*******************************************************************************
wdenkeeb1b772004-03-23 22:53:55 +0000146 *
147 * Write SMI ISA register
148 */
wdenkc6097192002-11-03 00:24:07 +0000149static void smiWrite (unsigned short index, char reg, char val)
150{
wdenkeeb1b772004-03-23 22:53:55 +0000151 register GraphicDevice *pGD = (GraphicDevice *)&smi;
wdenkc6097192002-11-03 00:24:07 +0000152
wdenkeeb1b772004-03-23 22:53:55 +0000153 out8 ((pGD->isaBase + index), reg);
154 out8 ((pGD->isaBase + index + 1), val);
wdenkc6097192002-11-03 00:24:07 +0000155}
156
157/*******************************************************************************
wdenkeeb1b772004-03-23 22:53:55 +0000158 *
159 * Write a table of SMI ISA register
160 */
wdenkc6097192002-11-03 00:24:07 +0000161static void smiLoadRegs (
wdenkeeb1b772004-03-23 22:53:55 +0000162 unsigned int iReg,
163 unsigned int dReg,
164 char *regTab,
165 unsigned int tabSize
166 )
wdenkc6097192002-11-03 00:24:07 +0000167{
wdenkeeb1b772004-03-23 22:53:55 +0000168 register GraphicDevice *pGD = (GraphicDevice *)&smi;
169 register int i;
wdenkc6097192002-11-03 00:24:07 +0000170
wdenkeeb1b772004-03-23 22:53:55 +0000171 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 }
wdenkc6097192002-11-03 00:24:07 +0000182}
183
184/*******************************************************************************
wdenkeeb1b772004-03-23 22:53:55 +0000185 *
186 * Init capture port registers
187 */
wdenkc6097192002-11-03 00:24:07 +0000188static void smiInitCapturePort (void)
189{
wdenkeeb1b772004-03-23 22:53:55 +0000190 SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
191 register GraphicDevice *pGD = (GraphicDevice *)&smi;
192 register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
wdenkc6097192002-11-03 00:24:07 +0000193
wdenkeeb1b772004-03-23 22:53:55 +0000194 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);
wdenkc6097192002-11-03 00:24:07 +0000201}
202
203
204/*******************************************************************************
wdenkeeb1b772004-03-23 22:53:55 +0000205 *
206 * Init video processor registers
207 */
wdenkc6097192002-11-03 00:24:07 +0000208static void smiInitVideoProcessor (void)
209{
wdenkeeb1b772004-03-23 22:53:55 +0000210 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;
wdenkc6097192002-11-03 00:24:07 +0000215
wdenkeeb1b772004-03-23 22:53:55 +0000216 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;
wdenkc6097192002-11-03 00:24:07 +0000221
wdenkeeb1b772004-03-23 22:53:55 +0000222 /* color key */
223 out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
wdenkc6097192002-11-03 00:24:07 +0000224
wdenkeeb1b772004-03-23 22:53:55 +0000225 /* color key mask */
226 out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
wdenkc6097192002-11-03 00:24:07 +0000227
wdenkeeb1b772004-03-23 22:53:55 +0000228 /* data src start adrs */
229 out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
wdenkc6097192002-11-03 00:24:07 +0000230
wdenkeeb1b772004-03-23 22:53:55 +0000231 /* data width and offset */
232 out32r ((pGD->vprBase + 0x0010),
233 ((pVP->offset / 8 * pGD->gdfBytesPP) << 16) |
234 (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
wdenkc6097192002-11-03 00:24:07 +0000235
wdenkeeb1b772004-03-23 22:53:55 +0000236 /* video window 1 */
237 out32r ((pGD->vprBase + 0x0014),
238 ((pVWin->top << 16) | pVWin->left));
wdenkc6097192002-11-03 00:24:07 +0000239
wdenkeeb1b772004-03-23 22:53:55 +0000240 out32r ((pGD->vprBase + 0x0018),
241 ((pVWin->bottom << 16) | pVWin->right));
wdenkc6097192002-11-03 00:24:07 +0000242
wdenkeeb1b772004-03-23 22:53:55 +0000243 out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
wdenkc6097192002-11-03 00:24:07 +0000244
wdenkeeb1b772004-03-23 22:53:55 +0000245 out32r ((pGD->vprBase + 0x0020),
246 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
wdenkc6097192002-11-03 00:24:07 +0000247
wdenkeeb1b772004-03-23 22:53:55 +0000248 out32r ((pGD->vprBase + 0x0024),
249 (((pVWin->hStretch) << 8) | pVWin->vStretch));
wdenkc6097192002-11-03 00:24:07 +0000250
wdenkeeb1b772004-03-23 22:53:55 +0000251 /* video window 2 */
252 out32r ((pGD->vprBase + 0x0028),
253 ((pVWin->top << 16) | pVWin->left));
wdenkc6097192002-11-03 00:24:07 +0000254
wdenkeeb1b772004-03-23 22:53:55 +0000255 out32r ((pGD->vprBase + 0x002c),
256 ((pVWin->bottom << 16) | pVWin->right));
wdenkc6097192002-11-03 00:24:07 +0000257
wdenkeeb1b772004-03-23 22:53:55 +0000258 out32r ((pGD->vprBase + 0x0030),
259 pVWin->srcStart / 8);
wdenkc6097192002-11-03 00:24:07 +0000260
wdenkeeb1b772004-03-23 22:53:55 +0000261 out32r ((pGD->vprBase + 0x0034),
262 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
wdenkc6097192002-11-03 00:24:07 +0000263
wdenkeeb1b772004-03-23 22:53:55 +0000264 out32r ((pGD->vprBase + 0x0038),
265 (((pVWin->hStretch) << 8) | pVWin->vStretch));
wdenkc6097192002-11-03 00:24:07 +0000266
wdenkeeb1b772004-03-23 22:53:55 +0000267 /* fifo prio control */
268 out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
wdenkc6097192002-11-03 00:24:07 +0000269
wdenkeeb1b772004-03-23 22:53:55 +0000270 /* fifo empty request levell */
271 out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
wdenkc6097192002-11-03 00:24:07 +0000272
wdenkeeb1b772004-03-23 22:53:55 +0000273 /* conversion constant */
274 out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
wdenkc6097192002-11-03 00:24:07 +0000275
wdenkeeb1b772004-03-23 22:53:55 +0000276 /* vpr control word */
277 out32r ((pGD->vprBase + 0x0000), pVP->control);
wdenkc6097192002-11-03 00:24:07 +0000278}
279
280/******************************************************************************
281 *
282 * Init drawing engine registers
283 */
284static void smiInitDrawingEngine (void)
285{
wdenkeeb1b772004-03-23 22:53:55 +0000286 GraphicDevice *pGD = (GraphicDevice *)&smi;
287 unsigned int val;
wdenkc6097192002-11-03 00:24:07 +0000288
wdenkeeb1b772004-03-23 22:53:55 +0000289 /* don't start now */
290 out32r ((pGD->dprBase + 0x000c), 0x000f0000);
wdenkc6097192002-11-03 00:24:07 +0000291
wdenkeeb1b772004-03-23 22:53:55 +0000292 /* set rop2 to copypen */
293 val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
294 out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
wdenkc6097192002-11-03 00:24:07 +0000295
wdenkeeb1b772004-03-23 22:53:55 +0000296 /* set clip rect */
297 out32r ((pGD->dprBase + 0x002c), 0);
298 out32r ((pGD->dprBase + 0x0030),
299 ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
wdenkc6097192002-11-03 00:24:07 +0000300
wdenkeeb1b772004-03-23 22:53:55 +0000301 /* src row pitch */
302 val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
303 out32r ((pGD->dprBase + 0x0010),
304 (val | pGD->plnSizeX * pGD->gdfBytesPP));
wdenkc6097192002-11-03 00:24:07 +0000305
wdenkeeb1b772004-03-23 22:53:55 +0000306 /* dst row pitch */
307 val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
308 out32r ((pGD->dprBase + 0x0010),
309 (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
wdenkc6097192002-11-03 00:24:07 +0000310
wdenkeeb1b772004-03-23 22:53:55 +0000311 /* 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);
wdenkc6097192002-11-03 00:24:07 +0000316
wdenkeeb1b772004-03-23 22:53:55 +0000317 /* src base adrs */
318 out32r ((pGD->dprBase + 0x0040),
319 (((pGD->frameAdrs/8) & 0x000fffff)));
wdenkc6097192002-11-03 00:24:07 +0000320
wdenkeeb1b772004-03-23 22:53:55 +0000321 /* dst base adrs */
322 out32r ((pGD->dprBase + 0x0044),
323 (((pGD->frameAdrs/8) & 0x000fffff)));
wdenkc6097192002-11-03 00:24:07 +0000324
wdenkeeb1b772004-03-23 22:53:55 +0000325 /* foreground color */
326 out32r ((pGD->dprBase + 0x0014), pGD->fg);
wdenkc6097192002-11-03 00:24:07 +0000327
wdenkeeb1b772004-03-23 22:53:55 +0000328 /* background color */
329 out32r ((pGD->dprBase + 0x0018), pGD->bg);
wdenkc6097192002-11-03 00:24:07 +0000330
wdenkeeb1b772004-03-23 22:53:55 +0000331 /* xcolor */
332 out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
wdenkc6097192002-11-03 00:24:07 +0000333
wdenkeeb1b772004-03-23 22:53:55 +0000334 /* xcolor mask */
335 out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
wdenkc6097192002-11-03 00:24:07 +0000336
wdenkeeb1b772004-03-23 22:53:55 +0000337 /* bit mask */
338 out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
wdenkc6097192002-11-03 00:24:07 +0000339
wdenkeeb1b772004-03-23 22:53:55 +0000340 /* load mono pattern */
341 out32r ((pGD->dprBase + 0x0034), 0);
342 out32r ((pGD->dprBase + 0x0038), 0);
wdenkc6097192002-11-03 00:24:07 +0000343}
344
345static struct pci_device_id supported[] = {
wdenkeeb1b772004-03-23 22:53:55 +0000346 { 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 { }
wdenkc6097192002-11-03 00:24:07 +0000350};
351
wdenkeeb1b772004-03-23 22:53:55 +0000352/*****************************************************************************/
353static 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/*****************************************************************************/
370static 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 */
wdenkb79a11c2004-03-25 15:14:43 +0000388 hbs = hd;
wdenkeeb1b772004-03-23 22:53:55 +0000389 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;
wdenkb79a11c2004-03-25 15:14:43 +0000398
wdenkeeb1b772004-03-23 22:53:55 +0000399 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);
wdenkb79a11c2004-03-25 15:14:43 +0000421
wdenkeeb1b772004-03-23 22:53:55 +0000422 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;
wdenkb79a11c2004-03-25 15:14:43 +0000437
wdenkeeb1b772004-03-23 22:53:55 +0000438
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 */
wdenkb79a11c2004-03-25 15:14:43 +0000446 cr[0x11] = (ve & 0x0f);
wdenkeeb1b772004-03-23 22:53:55 +0000447 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
474static 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 */
wdenkb79a11c2004-03-25 15:14:43 +0000482 L = P * n - m * Q;
wdenkeeb1b772004-03-23 22:53:55 +0000483 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/*****************************************************************************/
508static void smiLoadCcr (struct ctfb_res_modes *var, unsigned short device_id)
509{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200510 unsigned int p = 0;
511 unsigned int q = 0;
wdenkeeb1b772004-03-23 22:53:55 +0000512 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);
wdenkb79a11c2004-03-25 15:14:43 +0000537
wdenkeeb1b772004-03-23 22:53:55 +0000538 /* VCLK */
wdenkeedcd072004-09-08 22:03:11 +0000539 freq = 1000000000000LL / var -> pixclock;
wdenkb79a11c2004-03-25 15:14:43 +0000540
wdenkeeb1b772004-03-23 22:53:55 +0000541 FindPQ ((unsigned int)freq, &p, &q);
wdenkb79a11c2004-03-25 15:14:43 +0000542
wdenkeeb1b772004-03-23 22:53:55 +0000543 smiWrite (SMI_INDX_C4, 0x6c, p);
544 smiWrite (SMI_INDX_C4, 0x6d, q);
545
546}
wdenkc6097192002-11-03 00:24:07 +0000547
548/*******************************************************************************
wdenkeeb1b772004-03-23 22:53:55 +0000549 *
550 * Init video chip with common Linux graphic modes (lilo)
551 */
wdenkc6097192002-11-03 00:24:07 +0000552void *video_hw_init (void)
553{
wdenkeeb1b772004-03-23 22:53:55 +0000554 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;
wdenkb79a11c2004-03-25 15:14:43 +0000565
wdenkeeb1b772004-03-23 22:53:55 +0000566 /* Search for video chip */
567 printf("Video: ");
wdenkc6097192002-11-03 00:24:07 +0000568
wdenkeeb1b772004-03-23 22:53:55 +0000569 if ((devbusfn = pci_find_devices(supported, 0)) < 0)
wdenk8bde7f72003-06-27 21:31:46 +0000570 {
wdenkeeb1b772004-03-23 22:53:55 +0000571 printf ("Controller not found !\n");
572 return (NULL);
wdenk8bde7f72003-06-27 21:31:46 +0000573 }
wdenkc6097192002-11-03 00:24:07 +0000574
wdenkeeb1b772004-03-23 22:53:55 +0000575 /* 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);
wdenkc6097192002-11-03 00:24:07 +0000580
wdenkeeb1b772004-03-23 22:53:55 +0000581 tmp = 0;
wdenkb79a11c2004-03-25 15:14:43 +0000582
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200583 videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE;
wdenkeeb1b772004-03-23 22:53:55 +0000584 /* 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) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200602 printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE);
wdenkeeb1b772004-03-23 22:53:55 +0000603 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 {
wdenkb79a11c2004-03-25 15:14:43 +0000610
wdenkeeb1b772004-03-23 22:53:55 +0000611 res_mode = (struct ctfb_res_modes *) &var_mode;
612 bits_per_pixel = video_get_params (res_mode, penv);
613 }
wdenkc6097192002-11-03 00:24:07 +0000614
wdenkeeb1b772004-03-23 22:53:55 +0000615 /* 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;
wdenkb79a11c2004-03-25 15:14:43 +0000627
wdenkeeb1b772004-03-23 22:53:55 +0000628 /* 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 }
wdenkc6097192002-11-03 00:24:07 +0000655
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200656 pGD->isaBase = CONFIG_SYS_ISA_IO;
wdenkeeb1b772004-03-23 22:53:55 +0000657 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;
wdenkc6097192002-11-03 00:24:07 +0000663
wdenkeeb1b772004-03-23 22:53:55 +0000664 /* Set up hardware : select color mode,
665 set Register base to isa 3dx for 3?x regs*/
666 out8 (SMI_MISC_REG, 0x01);
wdenkc6097192002-11-03 00:24:07 +0000667
wdenkeeb1b772004-03-23 22:53:55 +0000668 /* Turn off display */
669 smiWrite (SMI_INDX_C4, 0x01, 0x20);
wdenkc6097192002-11-03 00:24:07 +0000670
wdenkeeb1b772004-03-23 22:53:55 +0000671 /* Unlock ext. crt regs */
672 out8 (SMI_LOCK_REG, 0x40);
wdenkc6097192002-11-03 00:24:07 +0000673
wdenkeeb1b772004-03-23 22:53:55 +0000674 /* Unlock crt regs 0-7 */
675 smiWrite (SMI_INDX_D4, 0x11, 0x0e);
wdenkc6097192002-11-03 00:24:07 +0000676
wdenkeeb1b772004-03-23 22:53:55 +0000677 /* Sytem Control Register */
678 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SCR, sizeof(SMI_SCR));
wdenkc6097192002-11-03 00:24:07 +0000679
wdenkeeb1b772004-03-23 22:53:55 +0000680 /* extented CRT Register */
681 smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, SMI_EXT_CRT, sizeof(SMI_EXT_CRT));
wdenkc6097192002-11-03 00:24:07 +0000682
wdenkeeb1b772004-03-23 22:53:55 +0000683 /* Attributes controller registers */
684 smiLoadRegs (SMI_INDX_ATTR, SMI_INDX_ATTR, SMI_ATTR, sizeof(SMI_ATTR));
wdenkb79a11c2004-03-25 15:14:43 +0000685
wdenkeeb1b772004-03-23 22:53:55 +0000686 /* Graphics Controller Register */
687 smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF, SMI_GCR, sizeof(SMI_GCR));
wdenkc6097192002-11-03 00:24:07 +0000688
wdenkeeb1b772004-03-23 22:53:55 +0000689 /* Sequencer Register */
690 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SEQR, sizeof(SMI_SEQR));
wdenkc6097192002-11-03 00:24:07 +0000691
wdenkeeb1b772004-03-23 22:53:55 +0000692 /* Power Control Register */
693 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_PCR, sizeof(SMI_PCR));
wdenkc6097192002-11-03 00:24:07 +0000694
wdenkeeb1b772004-03-23 22:53:55 +0000695 /* 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));
wdenkc6097192002-11-03 00:24:07 +0000699
wdenkeeb1b772004-03-23 22:53:55 +0000700 /* Set misc output register */
701 smiLoadMsr (res_mode);
wdenkb79a11c2004-03-25 15:14:43 +0000702
wdenkeeb1b772004-03-23 22:53:55 +0000703 /* Set CRT and Clock control registers */
704 smiLoadCrt (res_mode, bits_per_pixel);
wdenkb79a11c2004-03-25 15:14:43 +0000705
wdenkeeb1b772004-03-23 22:53:55 +0000706 smiLoadCcr (res_mode, device_id);
wdenkc6097192002-11-03 00:24:07 +0000707
wdenkeeb1b772004-03-23 22:53:55 +0000708 /* Hardware Cusor Register */
709 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_HCR, sizeof(SMI_HCR));
wdenkc6097192002-11-03 00:24:07 +0000710
wdenkeeb1b772004-03-23 22:53:55 +0000711 /* 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);
wdenkc6097192002-11-03 00:24:07 +0000718
wdenkeeb1b772004-03-23 22:53:55 +0000719 /* Video processor default setup */
720 smiInitVideoProcessor ();
wdenkc6097192002-11-03 00:24:07 +0000721
wdenkeeb1b772004-03-23 22:53:55 +0000722 /* Capture port default setup */
723 smiInitCapturePort ();
wdenkc6097192002-11-03 00:24:07 +0000724
wdenkeeb1b772004-03-23 22:53:55 +0000725 /* Drawing engine default setup */
726 smiInitDrawingEngine ();
wdenkc6097192002-11-03 00:24:07 +0000727
wdenkeeb1b772004-03-23 22:53:55 +0000728 /* Turn on display */
729 smiWrite (0x3c4, 0x01, 0x01);
wdenkc6097192002-11-03 00:24:07 +0000730
wdenkeeb1b772004-03-23 22:53:55 +0000731 /* Clear video memory */
732 i = pGD->memSize/4;
733 vm = (unsigned int *)pGD->pciBase;
734 while(i--)
735 *vm++ = 0;
736 return ((void*)&smi);
wdenkc6097192002-11-03 00:24:07 +0000737}
738
739/*******************************************************************************
wdenkeeb1b772004-03-23 22:53:55 +0000740 *
741 * Drawing engine fill on screen region
742 */
wdenkc6097192002-11-03 00:24:07 +0000743void video_hw_rectfill (
wdenkeeb1b772004-03-23 22:53:55 +0000744 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 )
wdenkc6097192002-11-03 00:24:07 +0000751{
wdenkeeb1b772004-03-23 22:53:55 +0000752 register GraphicDevice *pGD = (GraphicDevice *)&smi;
753 register unsigned int control;
wdenkc6097192002-11-03 00:24:07 +0000754
wdenkeeb1b772004-03-23 22:53:55 +0000755 dim_x *= bpp;
wdenkc6097192002-11-03 00:24:07 +0000756
wdenkeeb1b772004-03-23 22:53:55 +0000757 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));
wdenkc6097192002-11-03 00:24:07 +0000760
wdenkeeb1b772004-03-23 22:53:55 +0000761 control = 0x0000ffff & in32r ((pGD->dprBase + 0x000c));
wdenkc6097192002-11-03 00:24:07 +0000762
wdenkeeb1b772004-03-23 22:53:55 +0000763 control |= 0x80010000;
wdenkc6097192002-11-03 00:24:07 +0000764
wdenkeeb1b772004-03-23 22:53:55 +0000765 out32r ((pGD->dprBase + 0x000c), control);
wdenkc6097192002-11-03 00:24:07 +0000766
wdenkeeb1b772004-03-23 22:53:55 +0000767 /* Wait for drawing processor */
768 do
769 {
770 out8 ((pGD->isaBase + 0x3c4), 0x16);
771 } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
wdenkc6097192002-11-03 00:24:07 +0000772}
773
774/*******************************************************************************
wdenkeeb1b772004-03-23 22:53:55 +0000775 *
776 * Drawing engine bitblt with screen region
777 */
wdenkc6097192002-11-03 00:24:07 +0000778void video_hw_bitblt (
wdenkeeb1b772004-03-23 22:53:55 +0000779 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 )
wdenkc6097192002-11-03 00:24:07 +0000787{
wdenkeeb1b772004-03-23 22:53:55 +0000788 register GraphicDevice *pGD = (GraphicDevice *)&smi;
789 register unsigned int control;
wdenkc6097192002-11-03 00:24:07 +0000790
wdenkeeb1b772004-03-23 22:53:55 +0000791 dim_x *= bpp;
wdenkc6097192002-11-03 00:24:07 +0000792
wdenkeeb1b772004-03-23 22:53:55 +0000793 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 }
wdenkc6097192002-11-03 00:24:07 +0000803
wdenkeeb1b772004-03-23 22:53:55 +0000804 out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
805 control |= (0x0000ffff & in32r ((pGD->dprBase + 0x000c)));
806 out32r ((pGD->dprBase + 0x000c), control);
wdenkc6097192002-11-03 00:24:07 +0000807
wdenkeeb1b772004-03-23 22:53:55 +0000808 /* Wait for drawing processor */
809 do
810 {
811 out8 ((pGD->isaBase + 0x3c4), 0x16);
812 } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
wdenkc6097192002-11-03 00:24:07 +0000813}
814
815/*******************************************************************************
wdenkeeb1b772004-03-23 22:53:55 +0000816 *
817 * Set a RGB color in the LUT (8 bit index)
818 */
wdenkc6097192002-11-03 00:24:07 +0000819void video_set_lut (
wdenkeeb1b772004-03-23 22:53:55 +0000820 unsigned int index, /* color number */
821 unsigned char r, /* red */
822 unsigned char g, /* green */
823 unsigned char b /* blue */
824 )
wdenkc6097192002-11-03 00:24:07 +0000825{
wdenkeeb1b772004-03-23 22:53:55 +0000826 register GraphicDevice *pGD = (GraphicDevice *)&smi;
wdenkc6097192002-11-03 00:24:07 +0000827
wdenkeeb1b772004-03-23 22:53:55 +0000828 out8 (SMI_LUT_MASK, 0xff);
wdenkc6097192002-11-03 00:24:07 +0000829
wdenkeeb1b772004-03-23 22:53:55 +0000830 out8 (SMI_LUT_START, (char)index);
wdenkc6097192002-11-03 00:24:07 +0000831
wdenkeeb1b772004-03-23 22:53:55 +0000832 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);
wdenkc6097192002-11-03 00:24:07 +0000838}