blob: 26469e2a38aa5c3b0281aa435e41de54ee37ef7a [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 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
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.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
wdenkaea86e42004-03-23 22:53:55 +000015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
wdenkc6097192002-11-03 00:24:07 +000016 * GNU General Public License for more details.
17 *
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,
21 * MA 02111-1307 USA
22 */
23
24/*
25 * smiLynxEM.c
26 *
27 * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator
28 *
29 * modification history
30 * --------------------
31 * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>.
32 *
wdenkaea86e42004-03-23 22:53:55 +000033 * 18-03-2004 - Unify videomodes handling with the ct69000
34 * - The video output can be set via the variable "videoout"
35 * in the environment.
36 * videoout=1 output on LCD
37 * videoout=2 output on CRT (default value)
38 * <p.aubert@staubli.com>
wdenkc6097192002-11-03 00:24:07 +000039 */
40
41#include <common.h>
42
43#if defined(CONFIG_VIDEO_SMI_LYNXEM)
44
45#include <pci.h>
46#include <video_fb.h>
wdenkaea86e42004-03-23 22:53:55 +000047#include "videomodes.h"
wdenkc6097192002-11-03 00:24:07 +000048/*
49 * Export Graphic Device
50 */
51GraphicDevice smi;
52
53/*
54 * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
55 */
wdenkaea86e42004-03-23 22:53:55 +000056#define VIDEO_MEM_SIZE 0x400000
wdenkc6097192002-11-03 00:24:07 +000057
wdenkc6097192002-11-03 00:24:07 +000058
59/*
60 * ISA mapped regs
61 */
wdenkaea86e42004-03-23 22:53:55 +000062#define SMI_INDX_C4 (pGD->isaBase + 0x03c4) /* index reg */
63#define SMI_DATA_C5 (pGD->isaBase + 0x03c5) /* data reg */
64#define SMI_INDX_D4 (pGD->isaBase + 0x03d4) /* index reg */
65#define SMI_DATA_D5 (pGD->isaBase + 0x03d5) /* data reg */
66#define SMI_ISR1 (pGD->isaBase + 0x03ca)
67#define SMI_INDX_CE (pGD->isaBase + 0x03ce) /* index reg */
68#define SMI_DATA_CF (pGD->isaBase + 0x03cf) /* data reg */
69#define SMI_LOCK_REG (pGD->isaBase + 0x03c3) /* unlock/lock ext crt reg */
70#define SMI_MISC_REG (pGD->isaBase + 0x03c2) /* misc reg */
71#define SMI_LUT_MASK (pGD->isaBase + 0x03c6) /* lut mask reg */
72#define SMI_LUT_START (pGD->isaBase + 0x03c8) /* lut start index */
73#define SMI_LUT_RGB (pGD->isaBase + 0x03c9) /* lut colors auto incr.*/
74#define SMI_INDX_ATTR (pGD->isaBase + 0x03c0) /* attributes index reg */
wdenkc6097192002-11-03 00:24:07 +000075
76/*
77 * Video processor control
wdenkaea86e42004-03-23 22:53:55 +000078 */
wdenkc6097192002-11-03 00:24:07 +000079typedef struct {
wdenkaea86e42004-03-23 22:53:55 +000080 unsigned int control;
81 unsigned int colorKey;
82 unsigned int colorKeyMask;
83 unsigned int start;
84 unsigned short offset;
85 unsigned short width;
86 unsigned int fifoPrio;
87 unsigned int fifoERL;
88 unsigned int YUVtoRGB;
wdenkc6097192002-11-03 00:24:07 +000089} SmiVideoProc;
90
91/*
92 * Video window control
93 */
94typedef struct {
wdenkaea86e42004-03-23 22:53:55 +000095 unsigned short top;
96 unsigned short left;
97 unsigned short bottom;
98 unsigned short right;
99 unsigned int srcStart;
100 unsigned short width;
101 unsigned short offset;
102 unsigned char hStretch;
103 unsigned char vStretch;
wdenkc6097192002-11-03 00:24:07 +0000104} SmiVideoWin;
105
106/*
107 * Capture port control
108 */
109typedef struct {
wdenkaea86e42004-03-23 22:53:55 +0000110 unsigned int control;
111 unsigned short topClip;
112 unsigned short leftClip;
113 unsigned short srcHeight;
114 unsigned short srcWidth;
115 unsigned int srcBufStart1;
116 unsigned int srcBufStart2;
117 unsigned short srcOffset;
118 unsigned short fifoControl;
wdenkc6097192002-11-03 00:24:07 +0000119} SmiCapturePort;
120
121
wdenkc6097192002-11-03 00:24:07 +0000122/*
123 * Register values for common video modes
124 */
wdenkaea86e42004-03-23 22:53:55 +0000125static char SMI_SCR[] = {
126 /* all modes */
127 0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x15, 0x90,
128 0x17, 0x20, 0x18, 0xb1, 0x19, 0x00,
wdenkc6097192002-11-03 00:24:07 +0000129};
wdenkaea86e42004-03-23 22:53:55 +0000130static char SMI_EXT_CRT[] = {
131 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
132 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
wdenkc6097192002-11-03 00:24:07 +0000133};
wdenkaea86e42004-03-23 22:53:55 +0000134static char SMI_ATTR [] = {
135 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05,
136 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b,
137 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x41, 0x11, 0x00,
138 0x12, 0x0f, 0x13, 0x00, 0x14, 0x00,
wdenkc6097192002-11-03 00:24:07 +0000139};
wdenkaea86e42004-03-23 22:53:55 +0000140static char SMI_GCR[18] = {
141 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
142 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff
wdenkc6097192002-11-03 00:24:07 +0000143};
wdenkaea86e42004-03-23 22:53:55 +0000144static char SMI_SEQR[] = {
145 0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03
wdenkc6097192002-11-03 00:24:07 +0000146};
wdenkaea86e42004-03-23 22:53:55 +0000147static char SMI_PCR [] = {
148 0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00
wdenkc6097192002-11-03 00:24:07 +0000149};
wdenkaea86e42004-03-23 22:53:55 +0000150static char SMI_MCR[] = {
wdenkd3602132004-03-25 15:14:43 +0000151 0x60, 0x01, 0x61, 0x00,
wdenkc6097192002-11-03 00:24:07 +0000152};
153
wdenkaea86e42004-03-23 22:53:55 +0000154static char SMI_HCR[] = {
155 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
156 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
wdenkc6097192002-11-03 00:24:07 +0000157};
158
wdenkc6097192002-11-03 00:24:07 +0000159
160/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000161 *
162 * Write SMI ISA register
163 */
wdenkc6097192002-11-03 00:24:07 +0000164static void smiWrite (unsigned short index, char reg, char val)
165{
wdenkaea86e42004-03-23 22:53:55 +0000166 register GraphicDevice *pGD = (GraphicDevice *)&smi;
wdenkc6097192002-11-03 00:24:07 +0000167
wdenkaea86e42004-03-23 22:53:55 +0000168 out8 ((pGD->isaBase + index), reg);
169 out8 ((pGD->isaBase + index + 1), val);
wdenkc6097192002-11-03 00:24:07 +0000170}
171
172/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000173 *
174 * Write a table of SMI ISA register
175 */
wdenkc6097192002-11-03 00:24:07 +0000176static void smiLoadRegs (
wdenkaea86e42004-03-23 22:53:55 +0000177 unsigned int iReg,
178 unsigned int dReg,
179 char *regTab,
180 unsigned int tabSize
181 )
wdenkc6097192002-11-03 00:24:07 +0000182{
wdenkaea86e42004-03-23 22:53:55 +0000183 register GraphicDevice *pGD = (GraphicDevice *)&smi;
184 register int i;
wdenkc6097192002-11-03 00:24:07 +0000185
wdenkaea86e42004-03-23 22:53:55 +0000186 for (i=0; i<tabSize; i+=2) {
187 if (iReg == SMI_INDX_ATTR) {
188 /* Reset the Flip Flop */
189 in8 (SMI_ISR1);
190 out8 (iReg, regTab[i]);
191 out8 (iReg, regTab[i+1]);
192 } else {
193 out8 (iReg, regTab[i]);
194 out8 (dReg, regTab[i+1]);
195 }
196 }
wdenkc6097192002-11-03 00:24:07 +0000197}
198
199/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000200 *
201 * Init capture port registers
202 */
wdenkc6097192002-11-03 00:24:07 +0000203static void smiInitCapturePort (void)
204{
wdenkaea86e42004-03-23 22:53:55 +0000205 SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
206 register GraphicDevice *pGD = (GraphicDevice *)&smi;
207 register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
wdenkc6097192002-11-03 00:24:07 +0000208
wdenkaea86e42004-03-23 22:53:55 +0000209 out32r ((pGD->cprBase + 0x0004), ((pCP->topClip<<16) | pCP->leftClip));
210 out32r ((pGD->cprBase + 0x0008), ((pCP->srcHeight<<16) | pCP->srcWidth));
211 out32r ((pGD->cprBase + 0x000c), pCP->srcBufStart1/8);
212 out32r ((pGD->cprBase + 0x0010), pCP->srcBufStart2/8);
213 out32r ((pGD->cprBase + 0x0014), pCP->srcOffset/8);
214 out32r ((pGD->cprBase + 0x0018), pCP->fifoControl);
215 out32r ((pGD->cprBase + 0x0000), pCP->control);
wdenkc6097192002-11-03 00:24:07 +0000216}
217
218
219/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000220 *
221 * Init video processor registers
222 */
wdenkc6097192002-11-03 00:24:07 +0000223static void smiInitVideoProcessor (void)
224{
wdenkaea86e42004-03-23 22:53:55 +0000225 SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed };
226 SmiVideoWin smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 };
227 register GraphicDevice *pGD = (GraphicDevice *)&smi;
228 register SmiVideoProc *pVP = (SmiVideoProc *)&smiVP;
229 register SmiVideoWin *pVWin = (SmiVideoWin *)&smiVW;
wdenkc6097192002-11-03 00:24:07 +0000230
wdenkaea86e42004-03-23 22:53:55 +0000231 pVP->width = pGD->plnSizeX * pGD->gdfBytesPP;
232 pVP->control |= pGD->gdfIndex << 16;
233 pVWin->bottom = pGD->winSizeY - 1;
234 pVWin->right = pGD->winSizeX - 1;
235 pVWin->width = pVP->width;
wdenkc6097192002-11-03 00:24:07 +0000236
wdenkaea86e42004-03-23 22:53:55 +0000237 /* color key */
238 out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
wdenkc6097192002-11-03 00:24:07 +0000239
wdenkaea86e42004-03-23 22:53:55 +0000240 /* color key mask */
241 out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
wdenkc6097192002-11-03 00:24:07 +0000242
wdenkaea86e42004-03-23 22:53:55 +0000243 /* data src start adrs */
244 out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
wdenkc6097192002-11-03 00:24:07 +0000245
wdenkaea86e42004-03-23 22:53:55 +0000246 /* data width and offset */
247 out32r ((pGD->vprBase + 0x0010),
248 ((pVP->offset / 8 * pGD->gdfBytesPP) << 16) |
249 (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
wdenkc6097192002-11-03 00:24:07 +0000250
wdenkaea86e42004-03-23 22:53:55 +0000251 /* video window 1 */
252 out32r ((pGD->vprBase + 0x0014),
253 ((pVWin->top << 16) | pVWin->left));
wdenkc6097192002-11-03 00:24:07 +0000254
wdenkaea86e42004-03-23 22:53:55 +0000255 out32r ((pGD->vprBase + 0x0018),
256 ((pVWin->bottom << 16) | pVWin->right));
wdenkc6097192002-11-03 00:24:07 +0000257
wdenkaea86e42004-03-23 22:53:55 +0000258 out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
wdenkc6097192002-11-03 00:24:07 +0000259
wdenkaea86e42004-03-23 22:53:55 +0000260 out32r ((pGD->vprBase + 0x0020),
261 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
wdenkc6097192002-11-03 00:24:07 +0000262
wdenkaea86e42004-03-23 22:53:55 +0000263 out32r ((pGD->vprBase + 0x0024),
264 (((pVWin->hStretch) << 8) | pVWin->vStretch));
wdenkc6097192002-11-03 00:24:07 +0000265
wdenkaea86e42004-03-23 22:53:55 +0000266 /* video window 2 */
267 out32r ((pGD->vprBase + 0x0028),
268 ((pVWin->top << 16) | pVWin->left));
wdenkc6097192002-11-03 00:24:07 +0000269
wdenkaea86e42004-03-23 22:53:55 +0000270 out32r ((pGD->vprBase + 0x002c),
271 ((pVWin->bottom << 16) | pVWin->right));
wdenkc6097192002-11-03 00:24:07 +0000272
wdenkaea86e42004-03-23 22:53:55 +0000273 out32r ((pGD->vprBase + 0x0030),
274 pVWin->srcStart / 8);
wdenkc6097192002-11-03 00:24:07 +0000275
wdenkaea86e42004-03-23 22:53:55 +0000276 out32r ((pGD->vprBase + 0x0034),
277 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
wdenkc6097192002-11-03 00:24:07 +0000278
wdenkaea86e42004-03-23 22:53:55 +0000279 out32r ((pGD->vprBase + 0x0038),
280 (((pVWin->hStretch) << 8) | pVWin->vStretch));
wdenkc6097192002-11-03 00:24:07 +0000281
wdenkaea86e42004-03-23 22:53:55 +0000282 /* fifo prio control */
283 out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
wdenkc6097192002-11-03 00:24:07 +0000284
wdenkaea86e42004-03-23 22:53:55 +0000285 /* fifo empty request levell */
286 out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
wdenkc6097192002-11-03 00:24:07 +0000287
wdenkaea86e42004-03-23 22:53:55 +0000288 /* conversion constant */
289 out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
wdenkc6097192002-11-03 00:24:07 +0000290
wdenkaea86e42004-03-23 22:53:55 +0000291 /* vpr control word */
292 out32r ((pGD->vprBase + 0x0000), pVP->control);
wdenkc6097192002-11-03 00:24:07 +0000293}
294
295/******************************************************************************
296 *
297 * Init drawing engine registers
298 */
299static void smiInitDrawingEngine (void)
300{
wdenkaea86e42004-03-23 22:53:55 +0000301 GraphicDevice *pGD = (GraphicDevice *)&smi;
302 unsigned int val;
wdenkc6097192002-11-03 00:24:07 +0000303
wdenkaea86e42004-03-23 22:53:55 +0000304 /* don't start now */
305 out32r ((pGD->dprBase + 0x000c), 0x000f0000);
wdenkc6097192002-11-03 00:24:07 +0000306
wdenkaea86e42004-03-23 22:53:55 +0000307 /* set rop2 to copypen */
308 val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
309 out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
wdenkc6097192002-11-03 00:24:07 +0000310
wdenkaea86e42004-03-23 22:53:55 +0000311 /* set clip rect */
312 out32r ((pGD->dprBase + 0x002c), 0);
313 out32r ((pGD->dprBase + 0x0030),
314 ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
wdenkc6097192002-11-03 00:24:07 +0000315
wdenkaea86e42004-03-23 22:53:55 +0000316 /* src row pitch */
317 val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
318 out32r ((pGD->dprBase + 0x0010),
319 (val | pGD->plnSizeX * pGD->gdfBytesPP));
wdenkc6097192002-11-03 00:24:07 +0000320
wdenkaea86e42004-03-23 22:53:55 +0000321 /* dst row pitch */
322 val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
323 out32r ((pGD->dprBase + 0x0010),
324 (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
wdenkc6097192002-11-03 00:24:07 +0000325
wdenkaea86e42004-03-23 22:53:55 +0000326 /* window width src/dst */
327 out32r ((pGD->dprBase + 0x003c),
328 (((pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)<<16) |
329 (pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)));
330 out16r ((pGD->dprBase + 0x001e), 0x0000);
wdenkc6097192002-11-03 00:24:07 +0000331
wdenkaea86e42004-03-23 22:53:55 +0000332 /* src base adrs */
333 out32r ((pGD->dprBase + 0x0040),
334 (((pGD->frameAdrs/8) & 0x000fffff)));
wdenkc6097192002-11-03 00:24:07 +0000335
wdenkaea86e42004-03-23 22:53:55 +0000336 /* dst base adrs */
337 out32r ((pGD->dprBase + 0x0044),
338 (((pGD->frameAdrs/8) & 0x000fffff)));
wdenkc6097192002-11-03 00:24:07 +0000339
wdenkaea86e42004-03-23 22:53:55 +0000340 /* foreground color */
341 out32r ((pGD->dprBase + 0x0014), pGD->fg);
wdenkc6097192002-11-03 00:24:07 +0000342
wdenkaea86e42004-03-23 22:53:55 +0000343 /* background color */
344 out32r ((pGD->dprBase + 0x0018), pGD->bg);
wdenkc6097192002-11-03 00:24:07 +0000345
wdenkaea86e42004-03-23 22:53:55 +0000346 /* xcolor */
347 out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
wdenkc6097192002-11-03 00:24:07 +0000348
wdenkaea86e42004-03-23 22:53:55 +0000349 /* xcolor mask */
350 out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
wdenkc6097192002-11-03 00:24:07 +0000351
wdenkaea86e42004-03-23 22:53:55 +0000352 /* bit mask */
353 out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
wdenkc6097192002-11-03 00:24:07 +0000354
wdenkaea86e42004-03-23 22:53:55 +0000355 /* load mono pattern */
356 out32r ((pGD->dprBase + 0x0034), 0);
357 out32r ((pGD->dprBase + 0x0038), 0);
wdenkc6097192002-11-03 00:24:07 +0000358}
359
360static struct pci_device_id supported[] = {
wdenkaea86e42004-03-23 22:53:55 +0000361 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_710 },
362 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_712 },
363 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_810 },
364 { }
wdenkc6097192002-11-03 00:24:07 +0000365};
366
wdenkaea86e42004-03-23 22:53:55 +0000367/*****************************************************************************/
368static void smiLoadMsr (struct ctfb_res_modes *mode)
369{
370 unsigned char h_synch_high, v_synch_high;
371 register GraphicDevice *pGD = (GraphicDevice *)&smi;
wdenkc6097192002-11-03 00:24:07 +0000372
wdenkaea86e42004-03-23 22:53:55 +0000373 h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40; /* horizontal Synch High active */
374 v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */
375 out8 (SMI_MISC_REG, (h_synch_high | v_synch_high | 0x29));
376 /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
377 * Selects the upper 64KB page.Bit5=1
378 * CLK2 (left reserved in standard VGA) Bit3|2=1|0
379 * Disables CPU access to frame buffer. Bit1=0
380 * Sets the I/O address decode for ST01, FCR, and all CR registers
381 * to the 3Dx I/O address range (CGA emulation). Bit0=1
382 */
383}
384/*****************************************************************************/
385static void smiLoadCrt (struct ctfb_res_modes *var, int bits_per_pixel)
wdenkc6097192002-11-03 00:24:07 +0000386{
wdenkaea86e42004-03-23 22:53:55 +0000387 unsigned char cr[0x7a];
388 int i;
389 unsigned int hd, hs, he, ht, hbs, hbe; /* Horizontal. */
390 unsigned int vd, vs, ve, vt, vbs, vbe; /* vertical */
391 unsigned int bpp, wd, dblscan, interlaced;
wdenkc6097192002-11-03 00:24:07 +0000392
wdenkaea86e42004-03-23 22:53:55 +0000393 const int LineCompare = 0x3ff;
394 unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor */
395 register GraphicDevice *pGD = (GraphicDevice *)&smi;
wdenkc6097192002-11-03 00:24:07 +0000396
wdenkaea86e42004-03-23 22:53:55 +0000397 /* Horizontal */
398 hd = (var->xres) / 8; /* HDisp. */
399 hs = (var->xres + var->right_margin) / 8; /* HsStrt */
400 he = (var->xres + var->right_margin + var->hsync_len) / 8; /* HsEnd */
401 ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8; /* HTotal */
402 /* Blank */
wdenkd3602132004-03-25 15:14:43 +0000403 hbs = hd;
wdenkaea86e42004-03-23 22:53:55 +0000404 hbe = 0; /* Blank end at 0 */
wdenkc6097192002-11-03 00:24:07 +0000405
wdenkaea86e42004-03-23 22:53:55 +0000406 /* Vertical */
407 vd = var->yres; /* VDisplay */
408 vs = var->yres + var->lower_margin; /* VSyncStart */
409 ve = var->yres + var->lower_margin + var->vsync_len; /* VSyncEnd */
410 vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; /* VTotal */
411 vbs = vd;
412 vbe = 0;
wdenkd3602132004-03-25 15:14:43 +0000413
wdenkaea86e42004-03-23 22:53:55 +0000414 bpp = bits_per_pixel;
415 dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
416 interlaced = var->vmode & FB_VMODE_INTERLACED;
wdenkc6097192002-11-03 00:24:07 +0000417
wdenkc6097192002-11-03 00:24:07 +0000418
wdenkaea86e42004-03-23 22:53:55 +0000419 if (bpp == 15)
420 bpp = 16;
421 wd = var->xres * bpp / 64; /* double words per line */
422 if (interlaced) { /* we divide all vertical timings, exept vd */
423 vs >>= 1;
424 vbs >>= 1;
425 ve >>= 1;
426 vt >>= 1;
wdenk57b2d802003-06-27 21:31:46 +0000427 }
wdenkc6097192002-11-03 00:24:07 +0000428
wdenkaea86e42004-03-23 22:53:55 +0000429 memset (cr, 0, sizeof (cr));
430 cr[0x00] = ht - 5;
431 cr[0x01] = hd - 1;
432 cr[0x02] = hbs - 1;
433 cr[0x03] = (hbe & 0x1F);
434 cr[0x04] = hs;
435 cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
wdenkd3602132004-03-25 15:14:43 +0000436
wdenkaea86e42004-03-23 22:53:55 +0000437 cr[0x06] = (vt - 2) & 0xFF;
438 cr[0x07] = (((vt - 2) & 0x100) >> 8)
439 | (((vd - 1) & 0x100) >> 7)
440 | ((vs & 0x100) >> 6)
441 | (((vbs - 1) & 0x100) >> 5)
442 | ((LineCompare & 0x100) >> 4)
443 | (((vt - 2) & 0x200) >> 4)
444 | (((vd - 1) & 0x200) >> 3)
445 | ((vs & 0x200) >> 2);
wdenkc6097192002-11-03 00:24:07 +0000446
wdenkaea86e42004-03-23 22:53:55 +0000447 cr[0x30] = ((vt - 2) & 0x400) >> 7
448 | (((vd - 1) & 0x400) >> 8)
449 | (((vbs - 1) & 0x400) >> 9)
450 | ((vs & 0x400) >> 10)
451 | (interlaced) ? 0x80 : 0;
wdenkd3602132004-03-25 15:14:43 +0000452
wdenkc6097192002-11-03 00:24:07 +0000453
wdenkaea86e42004-03-23 22:53:55 +0000454 cr[0x08] = 0x00;
455 cr[0x09] = (dblscan << 7)
456 | ((LineCompare & 0x200) >> 3)
457 | (((vbs - 1) & 0x200) >> 4)
458 | (TextScanLines - 1);
wdenkc6097192002-11-03 00:24:07 +0000459
wdenkaea86e42004-03-23 22:53:55 +0000460 cr[0x10] = vs & 0xff; /* VSyncPulseStart */
wdenkd3602132004-03-25 15:14:43 +0000461 cr[0x11] = (ve & 0x0f);
wdenkaea86e42004-03-23 22:53:55 +0000462 cr[0x12] = (vd - 1) & 0xff; /* LineCount */
463 cr[0x13] = wd & 0xff;
464 cr[0x14] = 0x40;
465 cr[0x15] = (vbs - 1) & 0xff;
466 cr[0x16] = vbe & 0xff;
467 cr[0x17] = 0xe3; /* but it does not work */
468 cr[0x18] = 0xff & LineCompare;
469 cr[0x22] = 0x00; /* todo? */
wdenkc6097192002-11-03 00:24:07 +0000470
wdenkc6097192002-11-03 00:24:07 +0000471
wdenkaea86e42004-03-23 22:53:55 +0000472 /* now set the registers */
473 for (i = 0; i <= 0x18; i++) { /*CR00 .. CR18 */
474 smiWrite (SMI_INDX_D4, i, cr[i]);
475 }
476 i = 0x22; /*CR22 */
477 smiWrite (SMI_INDX_D4, i, cr[i]);
478 i = 0x30; /*CR30 */
479 smiWrite (SMI_INDX_D4, i, cr[i]);
480}
wdenkc6097192002-11-03 00:24:07 +0000481
wdenkaea86e42004-03-23 22:53:55 +0000482/*****************************************************************************/
483#define REF_FREQ 14318180
484#define PMIN 1
485#define PMAX 255
486#define QMIN 1
487#define QMAX 63
wdenkc6097192002-11-03 00:24:07 +0000488
wdenkaea86e42004-03-23 22:53:55 +0000489static unsigned int FindPQ (unsigned int freq, unsigned int *pp, unsigned int *pq)
490{
491 unsigned int n = QMIN, m = 0;
492 long long int L = 0, P = freq, Q = REF_FREQ, H = P >> 1;
493 long long int D = 0x7ffffffffffffffLL;
wdenkc6097192002-11-03 00:24:07 +0000494
wdenkaea86e42004-03-23 22:53:55 +0000495 for (n = QMIN; n <= QMAX; n++) {
496 m = PMIN; /* p/q ~ freq/ref -> p*ref-freq*q ~ 0 */
wdenkd3602132004-03-25 15:14:43 +0000497 L = P * n - m * Q;
wdenkaea86e42004-03-23 22:53:55 +0000498 while (L > 0 && m < PMAX) {
499 L -= REF_FREQ; /* difference is greater as 0 subtract fref */
500 m++; /* and increment m */
501 }
502 /* difference is less or equal than 0 or m > maximum */
503 if (m > PMAX)
504 break; /* no solution: if we increase n we get the same situation */
505 /* L is <= 0 now */
506 if (-L > H && m > PMIN) { /* if difference > the half fref */
507 L += REF_FREQ; /* we take the situation before */
508 m--; /* because its closer to 0 */
509 }
510 L = (L < 0) ? -L : +L; /* absolute value */
511 if (D < L) /* if last difference was better take next n */
512 continue;
513 D = L;
514 *pp = m;
515 *pq = n; /* keep improved data */
516 if (D == 0)
517 break; /* best result we can get */
518 }
519 return (unsigned int) (0xffffffff & D);
520}
wdenkc6097192002-11-03 00:24:07 +0000521
wdenkaea86e42004-03-23 22:53:55 +0000522/*****************************************************************************/
523static void smiLoadCcr (struct ctfb_res_modes *var, unsigned short device_id)
524{
525 unsigned int p, q;
526 long long freq;
527 register GraphicDevice *pGD = (GraphicDevice *)&smi;
wdenkc6097192002-11-03 00:24:07 +0000528
wdenkaea86e42004-03-23 22:53:55 +0000529 smiWrite (SMI_INDX_C4, 0x65, 0);
530 smiWrite (SMI_INDX_C4, 0x66, 0);
531 smiWrite (SMI_INDX_C4, 0x68, 0x50);
532 if (device_id == PCI_DEVICE_ID_SMI_810) {
533 smiWrite (SMI_INDX_C4, 0x69, 0x3);
534 } else {
535 smiWrite (SMI_INDX_C4, 0x69, 0x0);
536 }
wdenkc6097192002-11-03 00:24:07 +0000537
wdenkaea86e42004-03-23 22:53:55 +0000538 /* Memory clock */
539 switch (device_id) {
540 case PCI_DEVICE_ID_SMI_710 :
541 smiWrite (SMI_INDX_C4, 0x6a, 0x75);
542 break;
543 case PCI_DEVICE_ID_SMI_712 :
544 smiWrite (SMI_INDX_C4, 0x6a, 0x80);
545 break;
546 default :
547 smiWrite (SMI_INDX_C4, 0x6a, 0x53);
548 break;
549 }
550 smiWrite (SMI_INDX_C4, 0x6b, 0x15);
wdenkd3602132004-03-25 15:14:43 +0000551
wdenkaea86e42004-03-23 22:53:55 +0000552 /* VCLK */
553 freq = 1000000000000L / var -> pixclock;
wdenkd3602132004-03-25 15:14:43 +0000554
wdenkaea86e42004-03-23 22:53:55 +0000555 FindPQ ((unsigned int)freq, &p, &q);
wdenkd3602132004-03-25 15:14:43 +0000556
wdenkaea86e42004-03-23 22:53:55 +0000557 smiWrite (SMI_INDX_C4, 0x6c, p);
558 smiWrite (SMI_INDX_C4, 0x6d, q);
wdenkc6097192002-11-03 00:24:07 +0000559
wdenkaea86e42004-03-23 22:53:55 +0000560}
wdenkc6097192002-11-03 00:24:07 +0000561
wdenkaea86e42004-03-23 22:53:55 +0000562/*******************************************************************************
563 *
564 * Init video chip with common Linux graphic modes (lilo)
565 */
566void *video_hw_init (void)
567{
568 GraphicDevice *pGD = (GraphicDevice *)&smi;
569 unsigned short device_id;
570 pci_dev_t devbusfn;
571 int videomode;
572 unsigned long t1, hsynch, vsynch;
573 unsigned int pci_mem_base, *vm;
574 char *penv;
575 int tmp, i, bits_per_pixel;
576 struct ctfb_res_modes *res_mode;
577 struct ctfb_res_modes var_mode;
578 unsigned char videoout;
wdenkd3602132004-03-25 15:14:43 +0000579
wdenkaea86e42004-03-23 22:53:55 +0000580 /* Search for video chip */
581 printf("Video: ");
wdenkc6097192002-11-03 00:24:07 +0000582
wdenkaea86e42004-03-23 22:53:55 +0000583 if ((devbusfn = pci_find_devices(supported, 0)) < 0)
584 {
585 printf ("Controller not found !\n");
586 return (NULL);
587 }
wdenkc6097192002-11-03 00:24:07 +0000588
wdenkaea86e42004-03-23 22:53:55 +0000589 /* PCI setup */
590 pci_write_config_dword (devbusfn, PCI_COMMAND, (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
591 pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
592 pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
593 pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
wdenkc6097192002-11-03 00:24:07 +0000594
wdenkaea86e42004-03-23 22:53:55 +0000595 tmp = 0;
wdenkd3602132004-03-25 15:14:43 +0000596
wdenkaea86e42004-03-23 22:53:55 +0000597 videomode = CFG_DEFAULT_VIDEO_MODE;
598 /* get video mode via environment */
599 if ((penv = getenv ("videomode")) != NULL) {
600 /* deceide if it is a string */
601 if (penv[0] <= '9') {
602 videomode = (int) simple_strtoul (penv, NULL, 16);
603 tmp = 1;
604 }
605 } else {
606 tmp = 1;
607 }
608 if (tmp) {
609 /* parameter are vesa modes */
610 /* search params */
611 for (i = 0; i < VESA_MODES_COUNT; i++) {
612 if (vesa_modes[i].vesanr == videomode)
613 break;
614 }
615 if (i == VESA_MODES_COUNT) {
616 printf ("no VESA Mode found, switching to mode 0x%x ", CFG_DEFAULT_VIDEO_MODE);
617 i = 0;
618 }
619 res_mode =
620 (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
621 resindex];
622 bits_per_pixel = vesa_modes[i].bits_per_pixel;
623 } else {
wdenkd3602132004-03-25 15:14:43 +0000624
wdenkaea86e42004-03-23 22:53:55 +0000625 res_mode = (struct ctfb_res_modes *) &var_mode;
626 bits_per_pixel = video_get_params (res_mode, penv);
627 }
wdenkc6097192002-11-03 00:24:07 +0000628
wdenkaea86e42004-03-23 22:53:55 +0000629 /* calculate hsynch and vsynch freq (info only) */
630 t1 = (res_mode->left_margin + res_mode->xres +
631 res_mode->right_margin + res_mode->hsync_len) / 8;
632 t1 *= 8;
633 t1 *= res_mode->pixclock;
634 t1 /= 1000;
635 hsynch = 1000000000L / t1;
636 t1 *=
637 (res_mode->upper_margin + res_mode->yres +
638 res_mode->lower_margin + res_mode->vsync_len);
639 t1 /= 1000;
640 vsynch = 1000000000L / t1;
wdenkd3602132004-03-25 15:14:43 +0000641
wdenkaea86e42004-03-23 22:53:55 +0000642 /* fill in Graphic device struct */
643 sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
644 res_mode->yres, bits_per_pixel, (hsynch / 1000),
645 (vsynch / 1000));
646 printf ("%s\n", pGD->modeIdent);
647 pGD->winSizeX = res_mode->xres;
648 pGD->winSizeY = res_mode->yres;
649 pGD->plnSizeX = res_mode->xres;
650 pGD->plnSizeY = res_mode->yres;
651 switch (bits_per_pixel) {
652 case 8:
653 pGD->gdfBytesPP = 1;
654 pGD->gdfIndex = GDF__8BIT_INDEX;
655 break;
656 case 15:
657 pGD->gdfBytesPP = 2;
658 pGD->gdfIndex = GDF_15BIT_555RGB;
659 break;
660 case 16:
661 pGD->gdfBytesPP = 2;
662 pGD->gdfIndex = GDF_16BIT_565RGB;
663 break;
664 case 24:
665 pGD->gdfBytesPP = 3;
666 pGD->gdfIndex = GDF_24BIT_888RGB;
667 break;
668 }
wdenkc6097192002-11-03 00:24:07 +0000669
wdenkaea86e42004-03-23 22:53:55 +0000670 pGD->isaBase = CFG_ISA_IO;
671 pGD->pciBase = pci_mem_base;
672 pGD->dprBase = (pci_mem_base + 0x400000 + 0x8000);
673 pGD->vprBase = (pci_mem_base + 0x400000 + 0xc000);
674 pGD->cprBase = (pci_mem_base + 0x400000 + 0xe000);
675 pGD->frameAdrs = pci_mem_base;
676 pGD->memSize = VIDEO_MEM_SIZE;
wdenkc6097192002-11-03 00:24:07 +0000677
wdenkaea86e42004-03-23 22:53:55 +0000678 /* Set up hardware : select color mode,
679 set Register base to isa 3dx for 3?x regs*/
680 out8 (SMI_MISC_REG, 0x01);
wdenkc6097192002-11-03 00:24:07 +0000681
wdenkaea86e42004-03-23 22:53:55 +0000682 /* Turn off display */
683 smiWrite (SMI_INDX_C4, 0x01, 0x20);
wdenkc6097192002-11-03 00:24:07 +0000684
wdenkaea86e42004-03-23 22:53:55 +0000685 /* Unlock ext. crt regs */
686 out8 (SMI_LOCK_REG, 0x40);
wdenkc6097192002-11-03 00:24:07 +0000687
wdenkaea86e42004-03-23 22:53:55 +0000688 /* Unlock crt regs 0-7 */
689 smiWrite (SMI_INDX_D4, 0x11, 0x0e);
wdenkc6097192002-11-03 00:24:07 +0000690
wdenkaea86e42004-03-23 22:53:55 +0000691 /* Sytem Control Register */
692 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SCR, sizeof(SMI_SCR));
wdenkc6097192002-11-03 00:24:07 +0000693
wdenkaea86e42004-03-23 22:53:55 +0000694 /* extented CRT Register */
695 smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, SMI_EXT_CRT, sizeof(SMI_EXT_CRT));
wdenkc6097192002-11-03 00:24:07 +0000696
wdenkaea86e42004-03-23 22:53:55 +0000697 /* Attributes controller registers */
698 smiLoadRegs (SMI_INDX_ATTR, SMI_INDX_ATTR, SMI_ATTR, sizeof(SMI_ATTR));
wdenkd3602132004-03-25 15:14:43 +0000699
wdenkaea86e42004-03-23 22:53:55 +0000700 /* Graphics Controller Register */
701 smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF, SMI_GCR, sizeof(SMI_GCR));
wdenkc6097192002-11-03 00:24:07 +0000702
wdenkaea86e42004-03-23 22:53:55 +0000703 /* Sequencer Register */
704 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SEQR, sizeof(SMI_SEQR));
wdenkc6097192002-11-03 00:24:07 +0000705
wdenkaea86e42004-03-23 22:53:55 +0000706 /* Power Control Register */
707 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_PCR, sizeof(SMI_PCR));
wdenkc6097192002-11-03 00:24:07 +0000708
wdenkaea86e42004-03-23 22:53:55 +0000709 /* Memory Control Register */
710 /* Register MSR62 is a power on configurable register. We don't */
711 /* modify it */
712 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_MCR, sizeof(SMI_MCR));
wdenkc6097192002-11-03 00:24:07 +0000713
wdenkaea86e42004-03-23 22:53:55 +0000714 /* Set misc output register */
715 smiLoadMsr (res_mode);
wdenkd3602132004-03-25 15:14:43 +0000716
wdenkaea86e42004-03-23 22:53:55 +0000717 /* Set CRT and Clock control registers */
718 smiLoadCrt (res_mode, bits_per_pixel);
wdenkd3602132004-03-25 15:14:43 +0000719
wdenkaea86e42004-03-23 22:53:55 +0000720 smiLoadCcr (res_mode, device_id);
wdenkc6097192002-11-03 00:24:07 +0000721
wdenkaea86e42004-03-23 22:53:55 +0000722 /* Hardware Cusor Register */
723 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_HCR, sizeof(SMI_HCR));
wdenkc6097192002-11-03 00:24:07 +0000724
wdenkaea86e42004-03-23 22:53:55 +0000725 /* Enable Display */
726 videoout = 2; /* Default output is CRT */
727 if ((penv = getenv ("videoout")) != NULL) {
728 /* deceide if it is a string */
729 videoout = (int) simple_strtoul (penv, NULL, 16);
730 }
731 smiWrite (SMI_INDX_C4, 0x31, videoout);
wdenkc6097192002-11-03 00:24:07 +0000732
wdenkaea86e42004-03-23 22:53:55 +0000733 /* Video processor default setup */
734 smiInitVideoProcessor ();
wdenkc6097192002-11-03 00:24:07 +0000735
wdenkaea86e42004-03-23 22:53:55 +0000736 /* Capture port default setup */
737 smiInitCapturePort ();
738
739 /* Drawing engine default setup */
740 smiInitDrawingEngine ();
741
742 /* Turn on display */
743 smiWrite (0x3c4, 0x01, 0x01);
744
745 /* Clear video memory */
746 i = pGD->memSize/4;
747 vm = (unsigned int *)pGD->pciBase;
748 while(i--)
749 *vm++ = 0;
750 return ((void*)&smi);
wdenkc6097192002-11-03 00:24:07 +0000751}
752
753/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000754 *
755 * Drawing engine fill on screen region
756 */
wdenkc6097192002-11-03 00:24:07 +0000757void video_hw_rectfill (
wdenkaea86e42004-03-23 22:53:55 +0000758 unsigned int bpp, /* bytes per pixel */
759 unsigned int dst_x, /* dest pos x */
760 unsigned int dst_y, /* dest pos y */
761 unsigned int dim_x, /* frame width */
762 unsigned int dim_y, /* frame height */
763 unsigned int color /* fill color */
764 )
wdenkc6097192002-11-03 00:24:07 +0000765{
wdenkaea86e42004-03-23 22:53:55 +0000766 register GraphicDevice *pGD = (GraphicDevice *)&smi;
767 register unsigned int control;
wdenkc6097192002-11-03 00:24:07 +0000768
wdenkaea86e42004-03-23 22:53:55 +0000769 dim_x *= bpp;
wdenkc6097192002-11-03 00:24:07 +0000770
wdenkaea86e42004-03-23 22:53:55 +0000771 out32r ((pGD->dprBase + 0x0014), color);
772 out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
773 out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
wdenkc6097192002-11-03 00:24:07 +0000774
wdenkaea86e42004-03-23 22:53:55 +0000775 control = 0x0000ffff & in32r ((pGD->dprBase + 0x000c));
wdenkc6097192002-11-03 00:24:07 +0000776
wdenkaea86e42004-03-23 22:53:55 +0000777 control |= 0x80010000;
wdenkc6097192002-11-03 00:24:07 +0000778
wdenkaea86e42004-03-23 22:53:55 +0000779 out32r ((pGD->dprBase + 0x000c), control);
wdenkc6097192002-11-03 00:24:07 +0000780
wdenkaea86e42004-03-23 22:53:55 +0000781 /* Wait for drawing processor */
782 do
783 {
784 out8 ((pGD->isaBase + 0x3c4), 0x16);
785 } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
wdenkc6097192002-11-03 00:24:07 +0000786}
787
788/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000789 *
790 * Drawing engine bitblt with screen region
791 */
wdenkc6097192002-11-03 00:24:07 +0000792void video_hw_bitblt (
wdenkaea86e42004-03-23 22:53:55 +0000793 unsigned int bpp, /* bytes per pixel */
794 unsigned int src_x, /* source pos x */
795 unsigned int src_y, /* source pos y */
796 unsigned int dst_x, /* dest pos x */
797 unsigned int dst_y, /* dest pos y */
798 unsigned int dim_x, /* frame width */
799 unsigned int dim_y /* frame height */
800 )
wdenkc6097192002-11-03 00:24:07 +0000801{
wdenkaea86e42004-03-23 22:53:55 +0000802 register GraphicDevice *pGD = (GraphicDevice *)&smi;
803 register unsigned int control;
wdenkc6097192002-11-03 00:24:07 +0000804
wdenkaea86e42004-03-23 22:53:55 +0000805 dim_x *= bpp;
wdenkc6097192002-11-03 00:24:07 +0000806
wdenkaea86e42004-03-23 22:53:55 +0000807 if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x)))
808 {
809 out32r ((pGD->dprBase + 0x0000), (((src_x+dim_x-1)<<16) | (src_y+dim_y-1)));
810 out32r ((pGD->dprBase + 0x0004), (((dst_x+dim_x-1)<<16) | (dst_y+dim_y-1)));
811 control = 0x88000000;
812 } else {
813 out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y));
814 out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
815 control = 0x80000000;
816 }
wdenkc6097192002-11-03 00:24:07 +0000817
wdenkaea86e42004-03-23 22:53:55 +0000818 out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
819 control |= (0x0000ffff & in32r ((pGD->dprBase + 0x000c)));
820 out32r ((pGD->dprBase + 0x000c), control);
wdenkc6097192002-11-03 00:24:07 +0000821
wdenkaea86e42004-03-23 22:53:55 +0000822 /* Wait for drawing processor */
823 do
824 {
825 out8 ((pGD->isaBase + 0x3c4), 0x16);
826 } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
wdenkc6097192002-11-03 00:24:07 +0000827}
828
829/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000830 *
831 * Set a RGB color in the LUT (8 bit index)
832 */
wdenkc6097192002-11-03 00:24:07 +0000833void video_set_lut (
wdenkaea86e42004-03-23 22:53:55 +0000834 unsigned int index, /* color number */
835 unsigned char r, /* red */
836 unsigned char g, /* green */
837 unsigned char b /* blue */
838 )
wdenkc6097192002-11-03 00:24:07 +0000839{
wdenkaea86e42004-03-23 22:53:55 +0000840 register GraphicDevice *pGD = (GraphicDevice *)&smi;
wdenkc6097192002-11-03 00:24:07 +0000841
wdenkaea86e42004-03-23 22:53:55 +0000842 out8 (SMI_LUT_MASK, 0xff);
wdenkc6097192002-11-03 00:24:07 +0000843
wdenkaea86e42004-03-23 22:53:55 +0000844 out8 (SMI_LUT_START, (char)index);
wdenkc6097192002-11-03 00:24:07 +0000845
wdenkaea86e42004-03-23 22:53:55 +0000846 out8 (SMI_LUT_RGB, r>>2); /* red */
847 udelay (10);
848 out8 (SMI_LUT_RGB, g>>2); /* green */
849 udelay (10);
850 out8 (SMI_LUT_RGB, b>>2); /* blue */
851 udelay (10);
wdenkc6097192002-11-03 00:24:07 +0000852}
853
854#endif /* CONFIG_VIDEO_SMI_LYNXEM */