blob: 2001e9caac27a453298eefe8a23678813721cc73 [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
Jerry Van Baren5afb2fe2009-02-05 22:18:02 -050015 * 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
wdenkc6097192002-11-03 00:24:07 +000043#include <pci.h>
44#include <video_fb.h>
wdenkaea86e42004-03-23 22:53:55 +000045#include "videomodes.h"
wdenkc6097192002-11-03 00:24:07 +000046/*
47 * Export Graphic Device
48 */
49GraphicDevice smi;
50
51/*
52 * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
53 */
wdenkaea86e42004-03-23 22:53:55 +000054#define VIDEO_MEM_SIZE 0x400000
wdenkc6097192002-11-03 00:24:07 +000055
wdenkc6097192002-11-03 00:24:07 +000056
57/*
58 * ISA mapped regs
59 */
wdenkaea86e42004-03-23 22:53:55 +000060#define SMI_INDX_C4 (pGD->isaBase + 0x03c4) /* index reg */
61#define SMI_DATA_C5 (pGD->isaBase + 0x03c5) /* data reg */
62#define SMI_INDX_D4 (pGD->isaBase + 0x03d4) /* index reg */
63#define SMI_DATA_D5 (pGD->isaBase + 0x03d5) /* data reg */
64#define SMI_ISR1 (pGD->isaBase + 0x03ca)
65#define SMI_INDX_CE (pGD->isaBase + 0x03ce) /* index reg */
66#define SMI_DATA_CF (pGD->isaBase + 0x03cf) /* data reg */
67#define SMI_LOCK_REG (pGD->isaBase + 0x03c3) /* unlock/lock ext crt reg */
68#define SMI_MISC_REG (pGD->isaBase + 0x03c2) /* misc reg */
69#define SMI_LUT_MASK (pGD->isaBase + 0x03c6) /* lut mask reg */
70#define SMI_LUT_START (pGD->isaBase + 0x03c8) /* lut start index */
71#define SMI_LUT_RGB (pGD->isaBase + 0x03c9) /* lut colors auto incr.*/
72#define SMI_INDX_ATTR (pGD->isaBase + 0x03c0) /* attributes index reg */
wdenkc6097192002-11-03 00:24:07 +000073
74/*
75 * Video processor control
wdenkaea86e42004-03-23 22:53:55 +000076 */
wdenkc6097192002-11-03 00:24:07 +000077typedef struct {
wdenkaea86e42004-03-23 22:53:55 +000078 unsigned int control;
79 unsigned int colorKey;
80 unsigned int colorKeyMask;
81 unsigned int start;
82 unsigned short offset;
83 unsigned short width;
84 unsigned int fifoPrio;
85 unsigned int fifoERL;
86 unsigned int YUVtoRGB;
wdenkc6097192002-11-03 00:24:07 +000087} SmiVideoProc;
88
89/*
90 * Video window control
91 */
92typedef struct {
wdenkaea86e42004-03-23 22:53:55 +000093 unsigned short top;
94 unsigned short left;
95 unsigned short bottom;
96 unsigned short right;
97 unsigned int srcStart;
98 unsigned short width;
99 unsigned short offset;
100 unsigned char hStretch;
101 unsigned char vStretch;
wdenkc6097192002-11-03 00:24:07 +0000102} SmiVideoWin;
103
104/*
105 * Capture port control
106 */
107typedef struct {
wdenkaea86e42004-03-23 22:53:55 +0000108 unsigned int control;
109 unsigned short topClip;
110 unsigned short leftClip;
111 unsigned short srcHeight;
112 unsigned short srcWidth;
113 unsigned int srcBufStart1;
114 unsigned int srcBufStart2;
115 unsigned short srcOffset;
116 unsigned short fifoControl;
wdenkc6097192002-11-03 00:24:07 +0000117} SmiCapturePort;
118
119
wdenkc6097192002-11-03 00:24:07 +0000120/*
121 * Register values for common video modes
122 */
wdenkaea86e42004-03-23 22:53:55 +0000123static char SMI_SCR[] = {
124 /* all modes */
125 0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x15, 0x90,
126 0x17, 0x20, 0x18, 0xb1, 0x19, 0x00,
wdenkc6097192002-11-03 00:24:07 +0000127};
wdenkaea86e42004-03-23 22:53:55 +0000128static char SMI_EXT_CRT[] = {
129 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
Wolfgang Denkc6b0fb82005-09-03 01:21:50 +0200130 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00,
wdenkc6097192002-11-03 00:24:07 +0000131};
wdenkaea86e42004-03-23 22:53:55 +0000132static char SMI_ATTR [] = {
133 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05,
134 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b,
135 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x41, 0x11, 0x00,
136 0x12, 0x0f, 0x13, 0x00, 0x14, 0x00,
wdenkc6097192002-11-03 00:24:07 +0000137};
wdenkaea86e42004-03-23 22:53:55 +0000138static char SMI_GCR[18] = {
139 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
Wolfgang Denkc6b0fb82005-09-03 01:21:50 +0200140 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff,
wdenkc6097192002-11-03 00:24:07 +0000141};
wdenkaea86e42004-03-23 22:53:55 +0000142static char SMI_SEQR[] = {
Wolfgang Denkc6b0fb82005-09-03 01:21:50 +0200143 0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03,
wdenkc6097192002-11-03 00:24:07 +0000144};
wdenkaea86e42004-03-23 22:53:55 +0000145static char SMI_PCR [] = {
Wolfgang Denkc6b0fb82005-09-03 01:21:50 +0200146 0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00,
wdenkc6097192002-11-03 00:24:07 +0000147};
wdenkaea86e42004-03-23 22:53:55 +0000148static char SMI_MCR[] = {
wdenkd3602132004-03-25 15:14:43 +0000149 0x60, 0x01, 0x61, 0x00,
Wolfgang Denkc6b0fb82005-09-03 01:21:50 +0200150#ifdef CONFIG_HMI1001
151 0x62, 0x74, /* Memory type is not configured by pins on HMI1001 */
152#endif
wdenkc6097192002-11-03 00:24:07 +0000153};
154
wdenkaea86e42004-03-23 22:53:55 +0000155static char SMI_HCR[] = {
156 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
Wolfgang Denkc6b0fb82005-09-03 01:21:50 +0200157 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00,
wdenkc6097192002-11-03 00:24:07 +0000158};
159
wdenkc6097192002-11-03 00:24:07 +0000160
161/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000162 *
163 * Write SMI ISA register
164 */
wdenkc6097192002-11-03 00:24:07 +0000165static void smiWrite (unsigned short index, char reg, char val)
166{
wdenkaea86e42004-03-23 22:53:55 +0000167 register GraphicDevice *pGD = (GraphicDevice *)&smi;
wdenkc6097192002-11-03 00:24:07 +0000168
wdenkaea86e42004-03-23 22:53:55 +0000169 out8 ((pGD->isaBase + index), reg);
170 out8 ((pGD->isaBase + index + 1), val);
wdenkc6097192002-11-03 00:24:07 +0000171}
172
173/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000174 *
175 * Write a table of SMI ISA register
176 */
wdenkc6097192002-11-03 00:24:07 +0000177static void smiLoadRegs (
wdenkaea86e42004-03-23 22:53:55 +0000178 unsigned int iReg,
179 unsigned int dReg,
180 char *regTab,
181 unsigned int tabSize
182 )
wdenkc6097192002-11-03 00:24:07 +0000183{
wdenkaea86e42004-03-23 22:53:55 +0000184 register GraphicDevice *pGD = (GraphicDevice *)&smi;
185 register int i;
wdenkc6097192002-11-03 00:24:07 +0000186
wdenkaea86e42004-03-23 22:53:55 +0000187 for (i=0; i<tabSize; i+=2) {
188 if (iReg == SMI_INDX_ATTR) {
189 /* Reset the Flip Flop */
190 in8 (SMI_ISR1);
191 out8 (iReg, regTab[i]);
192 out8 (iReg, regTab[i+1]);
193 } else {
194 out8 (iReg, regTab[i]);
195 out8 (dReg, regTab[i+1]);
196 }
197 }
wdenkc6097192002-11-03 00:24:07 +0000198}
199
200/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000201 *
202 * Init capture port registers
203 */
wdenkc6097192002-11-03 00:24:07 +0000204static void smiInitCapturePort (void)
205{
wdenkaea86e42004-03-23 22:53:55 +0000206 SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
207 register GraphicDevice *pGD = (GraphicDevice *)&smi;
208 register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
wdenkc6097192002-11-03 00:24:07 +0000209
wdenkaea86e42004-03-23 22:53:55 +0000210 out32r ((pGD->cprBase + 0x0004), ((pCP->topClip<<16) | pCP->leftClip));
211 out32r ((pGD->cprBase + 0x0008), ((pCP->srcHeight<<16) | pCP->srcWidth));
212 out32r ((pGD->cprBase + 0x000c), pCP->srcBufStart1/8);
213 out32r ((pGD->cprBase + 0x0010), pCP->srcBufStart2/8);
214 out32r ((pGD->cprBase + 0x0014), pCP->srcOffset/8);
215 out32r ((pGD->cprBase + 0x0018), pCP->fifoControl);
216 out32r ((pGD->cprBase + 0x0000), pCP->control);
wdenkc6097192002-11-03 00:24:07 +0000217}
218
219
220/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000221 *
222 * Init video processor registers
223 */
wdenkc6097192002-11-03 00:24:07 +0000224static void smiInitVideoProcessor (void)
225{
wdenkaea86e42004-03-23 22:53:55 +0000226 SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed };
227 SmiVideoWin smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 };
228 register GraphicDevice *pGD = (GraphicDevice *)&smi;
229 register SmiVideoProc *pVP = (SmiVideoProc *)&smiVP;
230 register SmiVideoWin *pVWin = (SmiVideoWin *)&smiVW;
wdenkc6097192002-11-03 00:24:07 +0000231
wdenkaea86e42004-03-23 22:53:55 +0000232 pVP->width = pGD->plnSizeX * pGD->gdfBytesPP;
233 pVP->control |= pGD->gdfIndex << 16;
234 pVWin->bottom = pGD->winSizeY - 1;
235 pVWin->right = pGD->winSizeX - 1;
236 pVWin->width = pVP->width;
wdenkc6097192002-11-03 00:24:07 +0000237
wdenkaea86e42004-03-23 22:53:55 +0000238 /* color key */
239 out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
wdenkc6097192002-11-03 00:24:07 +0000240
wdenkaea86e42004-03-23 22:53:55 +0000241 /* color key mask */
242 out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
wdenkc6097192002-11-03 00:24:07 +0000243
wdenkaea86e42004-03-23 22:53:55 +0000244 /* data src start adrs */
245 out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
wdenkc6097192002-11-03 00:24:07 +0000246
wdenkaea86e42004-03-23 22:53:55 +0000247 /* data width and offset */
248 out32r ((pGD->vprBase + 0x0010),
249 ((pVP->offset / 8 * pGD->gdfBytesPP) << 16) |
250 (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
wdenkc6097192002-11-03 00:24:07 +0000251
wdenkaea86e42004-03-23 22:53:55 +0000252 /* video window 1 */
253 out32r ((pGD->vprBase + 0x0014),
254 ((pVWin->top << 16) | pVWin->left));
wdenkc6097192002-11-03 00:24:07 +0000255
wdenkaea86e42004-03-23 22:53:55 +0000256 out32r ((pGD->vprBase + 0x0018),
257 ((pVWin->bottom << 16) | pVWin->right));
wdenkc6097192002-11-03 00:24:07 +0000258
wdenkaea86e42004-03-23 22:53:55 +0000259 out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
wdenkc6097192002-11-03 00:24:07 +0000260
wdenkaea86e42004-03-23 22:53:55 +0000261 out32r ((pGD->vprBase + 0x0020),
262 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
wdenkc6097192002-11-03 00:24:07 +0000263
wdenkaea86e42004-03-23 22:53:55 +0000264 out32r ((pGD->vprBase + 0x0024),
265 (((pVWin->hStretch) << 8) | pVWin->vStretch));
wdenkc6097192002-11-03 00:24:07 +0000266
wdenkaea86e42004-03-23 22:53:55 +0000267 /* video window 2 */
268 out32r ((pGD->vprBase + 0x0028),
269 ((pVWin->top << 16) | pVWin->left));
wdenkc6097192002-11-03 00:24:07 +0000270
wdenkaea86e42004-03-23 22:53:55 +0000271 out32r ((pGD->vprBase + 0x002c),
272 ((pVWin->bottom << 16) | pVWin->right));
wdenkc6097192002-11-03 00:24:07 +0000273
wdenkaea86e42004-03-23 22:53:55 +0000274 out32r ((pGD->vprBase + 0x0030),
275 pVWin->srcStart / 8);
wdenkc6097192002-11-03 00:24:07 +0000276
wdenkaea86e42004-03-23 22:53:55 +0000277 out32r ((pGD->vprBase + 0x0034),
278 (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
wdenkc6097192002-11-03 00:24:07 +0000279
wdenkaea86e42004-03-23 22:53:55 +0000280 out32r ((pGD->vprBase + 0x0038),
281 (((pVWin->hStretch) << 8) | pVWin->vStretch));
wdenkc6097192002-11-03 00:24:07 +0000282
wdenkaea86e42004-03-23 22:53:55 +0000283 /* fifo prio control */
284 out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
wdenkc6097192002-11-03 00:24:07 +0000285
wdenkaea86e42004-03-23 22:53:55 +0000286 /* fifo empty request levell */
287 out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
wdenkc6097192002-11-03 00:24:07 +0000288
wdenkaea86e42004-03-23 22:53:55 +0000289 /* conversion constant */
290 out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
wdenkc6097192002-11-03 00:24:07 +0000291
wdenkaea86e42004-03-23 22:53:55 +0000292 /* vpr control word */
293 out32r ((pGD->vprBase + 0x0000), pVP->control);
wdenkc6097192002-11-03 00:24:07 +0000294}
295
296/******************************************************************************
297 *
298 * Init drawing engine registers
299 */
300static void smiInitDrawingEngine (void)
301{
wdenkaea86e42004-03-23 22:53:55 +0000302 GraphicDevice *pGD = (GraphicDevice *)&smi;
303 unsigned int val;
wdenkc6097192002-11-03 00:24:07 +0000304
wdenkaea86e42004-03-23 22:53:55 +0000305 /* don't start now */
306 out32r ((pGD->dprBase + 0x000c), 0x000f0000);
wdenkc6097192002-11-03 00:24:07 +0000307
wdenkaea86e42004-03-23 22:53:55 +0000308 /* set rop2 to copypen */
309 val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
310 out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
wdenkc6097192002-11-03 00:24:07 +0000311
wdenkaea86e42004-03-23 22:53:55 +0000312 /* set clip rect */
313 out32r ((pGD->dprBase + 0x002c), 0);
314 out32r ((pGD->dprBase + 0x0030),
315 ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
wdenkc6097192002-11-03 00:24:07 +0000316
wdenkaea86e42004-03-23 22:53:55 +0000317 /* src row pitch */
318 val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
319 out32r ((pGD->dprBase + 0x0010),
320 (val | pGD->plnSizeX * pGD->gdfBytesPP));
wdenkc6097192002-11-03 00:24:07 +0000321
wdenkaea86e42004-03-23 22:53:55 +0000322 /* dst row pitch */
323 val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
324 out32r ((pGD->dprBase + 0x0010),
325 (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
wdenkc6097192002-11-03 00:24:07 +0000326
wdenkaea86e42004-03-23 22:53:55 +0000327 /* window width src/dst */
328 out32r ((pGD->dprBase + 0x003c),
329 (((pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)<<16) |
330 (pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)));
331 out16r ((pGD->dprBase + 0x001e), 0x0000);
wdenkc6097192002-11-03 00:24:07 +0000332
wdenkaea86e42004-03-23 22:53:55 +0000333 /* src base adrs */
334 out32r ((pGD->dprBase + 0x0040),
335 (((pGD->frameAdrs/8) & 0x000fffff)));
wdenkc6097192002-11-03 00:24:07 +0000336
wdenkaea86e42004-03-23 22:53:55 +0000337 /* dst base adrs */
338 out32r ((pGD->dprBase + 0x0044),
339 (((pGD->frameAdrs/8) & 0x000fffff)));
wdenkc6097192002-11-03 00:24:07 +0000340
wdenkaea86e42004-03-23 22:53:55 +0000341 /* foreground color */
342 out32r ((pGD->dprBase + 0x0014), pGD->fg);
wdenkc6097192002-11-03 00:24:07 +0000343
wdenkaea86e42004-03-23 22:53:55 +0000344 /* background color */
345 out32r ((pGD->dprBase + 0x0018), pGD->bg);
wdenkc6097192002-11-03 00:24:07 +0000346
wdenkaea86e42004-03-23 22:53:55 +0000347 /* xcolor */
348 out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
wdenkc6097192002-11-03 00:24:07 +0000349
wdenkaea86e42004-03-23 22:53:55 +0000350 /* xcolor mask */
351 out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
wdenkc6097192002-11-03 00:24:07 +0000352
wdenkaea86e42004-03-23 22:53:55 +0000353 /* bit mask */
354 out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
wdenkc6097192002-11-03 00:24:07 +0000355
wdenkaea86e42004-03-23 22:53:55 +0000356 /* load mono pattern */
357 out32r ((pGD->dprBase + 0x0034), 0);
358 out32r ((pGD->dprBase + 0x0038), 0);
wdenkc6097192002-11-03 00:24:07 +0000359}
360
361static struct pci_device_id supported[] = {
wdenkaea86e42004-03-23 22:53:55 +0000362 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_710 },
363 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_712 },
364 { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_810 },
365 { }
wdenkc6097192002-11-03 00:24:07 +0000366};
367
wdenkaea86e42004-03-23 22:53:55 +0000368/*****************************************************************************/
369static void smiLoadMsr (struct ctfb_res_modes *mode)
370{
371 unsigned char h_synch_high, v_synch_high;
372 register GraphicDevice *pGD = (GraphicDevice *)&smi;
wdenkc6097192002-11-03 00:24:07 +0000373
wdenkaea86e42004-03-23 22:53:55 +0000374 h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40; /* horizontal Synch High active */
375 v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */
376 out8 (SMI_MISC_REG, (h_synch_high | v_synch_high | 0x29));
377 /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
378 * Selects the upper 64KB page.Bit5=1
379 * CLK2 (left reserved in standard VGA) Bit3|2=1|0
380 * Disables CPU access to frame buffer. Bit1=0
381 * Sets the I/O address decode for ST01, FCR, and all CR registers
382 * to the 3Dx I/O address range (CGA emulation). Bit0=1
383 */
384}
385/*****************************************************************************/
386static void smiLoadCrt (struct ctfb_res_modes *var, int bits_per_pixel)
wdenkc6097192002-11-03 00:24:07 +0000387{
wdenkaea86e42004-03-23 22:53:55 +0000388 unsigned char cr[0x7a];
389 int i;
390 unsigned int hd, hs, he, ht, hbs, hbe; /* Horizontal. */
391 unsigned int vd, vs, ve, vt, vbs, vbe; /* vertical */
392 unsigned int bpp, wd, dblscan, interlaced;
wdenkc6097192002-11-03 00:24:07 +0000393
wdenkaea86e42004-03-23 22:53:55 +0000394 const int LineCompare = 0x3ff;
395 unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor */
396 register GraphicDevice *pGD = (GraphicDevice *)&smi;
wdenkc6097192002-11-03 00:24:07 +0000397
wdenkaea86e42004-03-23 22:53:55 +0000398 /* Horizontal */
399 hd = (var->xres) / 8; /* HDisp. */
400 hs = (var->xres + var->right_margin) / 8; /* HsStrt */
401 he = (var->xres + var->right_margin + var->hsync_len) / 8; /* HsEnd */
402 ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8; /* HTotal */
403 /* Blank */
wdenkd3602132004-03-25 15:14:43 +0000404 hbs = hd;
wdenkaea86e42004-03-23 22:53:55 +0000405 hbe = 0; /* Blank end at 0 */
wdenkc6097192002-11-03 00:24:07 +0000406
wdenkaea86e42004-03-23 22:53:55 +0000407 /* Vertical */
408 vd = var->yres; /* VDisplay */
409 vs = var->yres + var->lower_margin; /* VSyncStart */
410 ve = var->yres + var->lower_margin + var->vsync_len; /* VSyncEnd */
411 vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; /* VTotal */
412 vbs = vd;
413 vbe = 0;
wdenkd3602132004-03-25 15:14:43 +0000414
wdenkaea86e42004-03-23 22:53:55 +0000415 bpp = bits_per_pixel;
416 dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
417 interlaced = var->vmode & FB_VMODE_INTERLACED;
wdenkc6097192002-11-03 00:24:07 +0000418
wdenkc6097192002-11-03 00:24:07 +0000419
wdenkaea86e42004-03-23 22:53:55 +0000420 if (bpp == 15)
421 bpp = 16;
422 wd = var->xres * bpp / 64; /* double words per line */
423 if (interlaced) { /* we divide all vertical timings, exept vd */
424 vs >>= 1;
425 vbs >>= 1;
426 ve >>= 1;
427 vt >>= 1;
wdenk57b2d802003-06-27 21:31:46 +0000428 }
wdenkc6097192002-11-03 00:24:07 +0000429
wdenkaea86e42004-03-23 22:53:55 +0000430 memset (cr, 0, sizeof (cr));
431 cr[0x00] = ht - 5;
432 cr[0x01] = hd - 1;
433 cr[0x02] = hbs - 1;
434 cr[0x03] = (hbe & 0x1F);
435 cr[0x04] = hs;
436 cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
wdenkd3602132004-03-25 15:14:43 +0000437
wdenkaea86e42004-03-23 22:53:55 +0000438 cr[0x06] = (vt - 2) & 0xFF;
439 cr[0x07] = (((vt - 2) & 0x100) >> 8)
440 | (((vd - 1) & 0x100) >> 7)
441 | ((vs & 0x100) >> 6)
442 | (((vbs - 1) & 0x100) >> 5)
443 | ((LineCompare & 0x100) >> 4)
444 | (((vt - 2) & 0x200) >> 4)
445 | (((vd - 1) & 0x200) >> 3)
446 | ((vs & 0x200) >> 2);
wdenkc6097192002-11-03 00:24:07 +0000447
wdenkaea86e42004-03-23 22:53:55 +0000448 cr[0x30] = ((vt - 2) & 0x400) >> 7
449 | (((vd - 1) & 0x400) >> 8)
450 | (((vbs - 1) & 0x400) >> 9)
451 | ((vs & 0x400) >> 10)
452 | (interlaced) ? 0x80 : 0;
wdenkd3602132004-03-25 15:14:43 +0000453
wdenkc6097192002-11-03 00:24:07 +0000454
wdenkaea86e42004-03-23 22:53:55 +0000455 cr[0x08] = 0x00;
456 cr[0x09] = (dblscan << 7)
457 | ((LineCompare & 0x200) >> 3)
458 | (((vbs - 1) & 0x200) >> 4)
459 | (TextScanLines - 1);
wdenkc6097192002-11-03 00:24:07 +0000460
wdenkaea86e42004-03-23 22:53:55 +0000461 cr[0x10] = vs & 0xff; /* VSyncPulseStart */
wdenkd3602132004-03-25 15:14:43 +0000462 cr[0x11] = (ve & 0x0f);
wdenkaea86e42004-03-23 22:53:55 +0000463 cr[0x12] = (vd - 1) & 0xff; /* LineCount */
464 cr[0x13] = wd & 0xff;
465 cr[0x14] = 0x40;
466 cr[0x15] = (vbs - 1) & 0xff;
467 cr[0x16] = vbe & 0xff;
468 cr[0x17] = 0xe3; /* but it does not work */
469 cr[0x18] = 0xff & LineCompare;
470 cr[0x22] = 0x00; /* todo? */
wdenkc6097192002-11-03 00:24:07 +0000471
wdenkc6097192002-11-03 00:24:07 +0000472
wdenkaea86e42004-03-23 22:53:55 +0000473 /* now set the registers */
474 for (i = 0; i <= 0x18; i++) { /*CR00 .. CR18 */
475 smiWrite (SMI_INDX_D4, i, cr[i]);
476 }
477 i = 0x22; /*CR22 */
478 smiWrite (SMI_INDX_D4, i, cr[i]);
479 i = 0x30; /*CR30 */
480 smiWrite (SMI_INDX_D4, i, cr[i]);
481}
wdenkc6097192002-11-03 00:24:07 +0000482
wdenkaea86e42004-03-23 22:53:55 +0000483/*****************************************************************************/
484#define REF_FREQ 14318180
485#define PMIN 1
486#define PMAX 255
487#define QMIN 1
488#define QMAX 63
wdenkc6097192002-11-03 00:24:07 +0000489
wdenkaea86e42004-03-23 22:53:55 +0000490static unsigned int FindPQ (unsigned int freq, unsigned int *pp, unsigned int *pq)
491{
492 unsigned int n = QMIN, m = 0;
493 long long int L = 0, P = freq, Q = REF_FREQ, H = P >> 1;
494 long long int D = 0x7ffffffffffffffLL;
wdenkc6097192002-11-03 00:24:07 +0000495
wdenkaea86e42004-03-23 22:53:55 +0000496 for (n = QMIN; n <= QMAX; n++) {
497 m = PMIN; /* p/q ~ freq/ref -> p*ref-freq*q ~ 0 */
wdenkd3602132004-03-25 15:14:43 +0000498 L = P * n - m * Q;
wdenkaea86e42004-03-23 22:53:55 +0000499 while (L > 0 && m < PMAX) {
500 L -= REF_FREQ; /* difference is greater as 0 subtract fref */
501 m++; /* and increment m */
502 }
503 /* difference is less or equal than 0 or m > maximum */
504 if (m > PMAX)
505 break; /* no solution: if we increase n we get the same situation */
506 /* L is <= 0 now */
507 if (-L > H && m > PMIN) { /* if difference > the half fref */
508 L += REF_FREQ; /* we take the situation before */
509 m--; /* because its closer to 0 */
510 }
511 L = (L < 0) ? -L : +L; /* absolute value */
512 if (D < L) /* if last difference was better take next n */
513 continue;
514 D = L;
515 *pp = m;
516 *pq = n; /* keep improved data */
517 if (D == 0)
518 break; /* best result we can get */
519 }
520 return (unsigned int) (0xffffffff & D);
521}
wdenkc6097192002-11-03 00:24:07 +0000522
wdenkaea86e42004-03-23 22:53:55 +0000523/*****************************************************************************/
524static void smiLoadCcr (struct ctfb_res_modes *var, unsigned short device_id)
525{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200526 unsigned int p = 0;
527 unsigned int q = 0;
wdenkaea86e42004-03-23 22:53:55 +0000528 long long freq;
529 register GraphicDevice *pGD = (GraphicDevice *)&smi;
wdenkc6097192002-11-03 00:24:07 +0000530
wdenkaea86e42004-03-23 22:53:55 +0000531 smiWrite (SMI_INDX_C4, 0x65, 0);
532 smiWrite (SMI_INDX_C4, 0x66, 0);
533 smiWrite (SMI_INDX_C4, 0x68, 0x50);
534 if (device_id == PCI_DEVICE_ID_SMI_810) {
535 smiWrite (SMI_INDX_C4, 0x69, 0x3);
536 } else {
537 smiWrite (SMI_INDX_C4, 0x69, 0x0);
538 }
wdenkc6097192002-11-03 00:24:07 +0000539
wdenkaea86e42004-03-23 22:53:55 +0000540 /* Memory clock */
541 switch (device_id) {
542 case PCI_DEVICE_ID_SMI_710 :
543 smiWrite (SMI_INDX_C4, 0x6a, 0x75);
544 break;
545 case PCI_DEVICE_ID_SMI_712 :
546 smiWrite (SMI_INDX_C4, 0x6a, 0x80);
547 break;
548 default :
549 smiWrite (SMI_INDX_C4, 0x6a, 0x53);
550 break;
551 }
552 smiWrite (SMI_INDX_C4, 0x6b, 0x15);
wdenkd3602132004-03-25 15:14:43 +0000553
wdenkaea86e42004-03-23 22:53:55 +0000554 /* VCLK */
wdenka0ebde52004-09-08 22:03:11 +0000555 freq = 1000000000000LL / var -> pixclock;
wdenkd3602132004-03-25 15:14:43 +0000556
wdenkaea86e42004-03-23 22:53:55 +0000557 FindPQ ((unsigned int)freq, &p, &q);
wdenkd3602132004-03-25 15:14:43 +0000558
wdenkaea86e42004-03-23 22:53:55 +0000559 smiWrite (SMI_INDX_C4, 0x6c, p);
560 smiWrite (SMI_INDX_C4, 0x6d, q);
wdenkc6097192002-11-03 00:24:07 +0000561
wdenkaea86e42004-03-23 22:53:55 +0000562}
wdenkc6097192002-11-03 00:24:07 +0000563
wdenkaea86e42004-03-23 22:53:55 +0000564/*******************************************************************************
565 *
566 * Init video chip with common Linux graphic modes (lilo)
567 */
568void *video_hw_init (void)
569{
570 GraphicDevice *pGD = (GraphicDevice *)&smi;
571 unsigned short device_id;
572 pci_dev_t devbusfn;
573 int videomode;
574 unsigned long t1, hsynch, vsynch;
575 unsigned int pci_mem_base, *vm;
576 char *penv;
577 int tmp, i, bits_per_pixel;
578 struct ctfb_res_modes *res_mode;
579 struct ctfb_res_modes var_mode;
580 unsigned char videoout;
wdenkd3602132004-03-25 15:14:43 +0000581
wdenkaea86e42004-03-23 22:53:55 +0000582 /* Search for video chip */
583 printf("Video: ");
wdenkc6097192002-11-03 00:24:07 +0000584
wdenkaea86e42004-03-23 22:53:55 +0000585 if ((devbusfn = pci_find_devices(supported, 0)) < 0)
586 {
587 printf ("Controller not found !\n");
588 return (NULL);
589 }
wdenkc6097192002-11-03 00:24:07 +0000590
wdenkaea86e42004-03-23 22:53:55 +0000591 /* PCI setup */
592 pci_write_config_dword (devbusfn, PCI_COMMAND, (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
593 pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
594 pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
595 pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
wdenkc6097192002-11-03 00:24:07 +0000596
wdenkaea86e42004-03-23 22:53:55 +0000597 tmp = 0;
wdenkd3602132004-03-25 15:14:43 +0000598
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200599 videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE;
wdenkaea86e42004-03-23 22:53:55 +0000600 /* get video mode via environment */
601 if ((penv = getenv ("videomode")) != NULL) {
602 /* deceide if it is a string */
603 if (penv[0] <= '9') {
604 videomode = (int) simple_strtoul (penv, NULL, 16);
605 tmp = 1;
606 }
607 } else {
608 tmp = 1;
609 }
610 if (tmp) {
611 /* parameter are vesa modes */
612 /* search params */
613 for (i = 0; i < VESA_MODES_COUNT; i++) {
614 if (vesa_modes[i].vesanr == videomode)
615 break;
616 }
617 if (i == VESA_MODES_COUNT) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200618 printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE);
wdenkaea86e42004-03-23 22:53:55 +0000619 i = 0;
620 }
621 res_mode =
622 (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
623 resindex];
624 bits_per_pixel = vesa_modes[i].bits_per_pixel;
625 } else {
wdenkd3602132004-03-25 15:14:43 +0000626
wdenkaea86e42004-03-23 22:53:55 +0000627 res_mode = (struct ctfb_res_modes *) &var_mode;
628 bits_per_pixel = video_get_params (res_mode, penv);
629 }
wdenkc6097192002-11-03 00:24:07 +0000630
wdenkaea86e42004-03-23 22:53:55 +0000631 /* calculate hsynch and vsynch freq (info only) */
632 t1 = (res_mode->left_margin + res_mode->xres +
633 res_mode->right_margin + res_mode->hsync_len) / 8;
634 t1 *= 8;
635 t1 *= res_mode->pixclock;
636 t1 /= 1000;
637 hsynch = 1000000000L / t1;
638 t1 *=
639 (res_mode->upper_margin + res_mode->yres +
640 res_mode->lower_margin + res_mode->vsync_len);
641 t1 /= 1000;
642 vsynch = 1000000000L / t1;
wdenkd3602132004-03-25 15:14:43 +0000643
wdenkaea86e42004-03-23 22:53:55 +0000644 /* fill in Graphic device struct */
645 sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
646 res_mode->yres, bits_per_pixel, (hsynch / 1000),
647 (vsynch / 1000));
648 printf ("%s\n", pGD->modeIdent);
649 pGD->winSizeX = res_mode->xres;
650 pGD->winSizeY = res_mode->yres;
651 pGD->plnSizeX = res_mode->xres;
652 pGD->plnSizeY = res_mode->yres;
653 switch (bits_per_pixel) {
654 case 8:
655 pGD->gdfBytesPP = 1;
656 pGD->gdfIndex = GDF__8BIT_INDEX;
657 break;
658 case 15:
659 pGD->gdfBytesPP = 2;
660 pGD->gdfIndex = GDF_15BIT_555RGB;
661 break;
662 case 16:
663 pGD->gdfBytesPP = 2;
664 pGD->gdfIndex = GDF_16BIT_565RGB;
665 break;
666 case 24:
667 pGD->gdfBytesPP = 3;
668 pGD->gdfIndex = GDF_24BIT_888RGB;
669 break;
670 }
wdenkc6097192002-11-03 00:24:07 +0000671
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200672 pGD->isaBase = CONFIG_SYS_ISA_IO;
wdenkaea86e42004-03-23 22:53:55 +0000673 pGD->pciBase = pci_mem_base;
674 pGD->dprBase = (pci_mem_base + 0x400000 + 0x8000);
675 pGD->vprBase = (pci_mem_base + 0x400000 + 0xc000);
676 pGD->cprBase = (pci_mem_base + 0x400000 + 0xe000);
677 pGD->frameAdrs = pci_mem_base;
678 pGD->memSize = VIDEO_MEM_SIZE;
wdenkc6097192002-11-03 00:24:07 +0000679
wdenkaea86e42004-03-23 22:53:55 +0000680 /* Set up hardware : select color mode,
681 set Register base to isa 3dx for 3?x regs*/
682 out8 (SMI_MISC_REG, 0x01);
wdenkc6097192002-11-03 00:24:07 +0000683
wdenkaea86e42004-03-23 22:53:55 +0000684 /* Turn off display */
685 smiWrite (SMI_INDX_C4, 0x01, 0x20);
wdenkc6097192002-11-03 00:24:07 +0000686
wdenkaea86e42004-03-23 22:53:55 +0000687 /* Unlock ext. crt regs */
688 out8 (SMI_LOCK_REG, 0x40);
wdenkc6097192002-11-03 00:24:07 +0000689
wdenkaea86e42004-03-23 22:53:55 +0000690 /* Unlock crt regs 0-7 */
691 smiWrite (SMI_INDX_D4, 0x11, 0x0e);
wdenkc6097192002-11-03 00:24:07 +0000692
wdenkaea86e42004-03-23 22:53:55 +0000693 /* Sytem Control Register */
694 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SCR, sizeof(SMI_SCR));
wdenkc6097192002-11-03 00:24:07 +0000695
wdenkaea86e42004-03-23 22:53:55 +0000696 /* extented CRT Register */
697 smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, SMI_EXT_CRT, sizeof(SMI_EXT_CRT));
wdenkc6097192002-11-03 00:24:07 +0000698
wdenkaea86e42004-03-23 22:53:55 +0000699 /* Attributes controller registers */
700 smiLoadRegs (SMI_INDX_ATTR, SMI_INDX_ATTR, SMI_ATTR, sizeof(SMI_ATTR));
wdenkd3602132004-03-25 15:14:43 +0000701
wdenkaea86e42004-03-23 22:53:55 +0000702 /* Graphics Controller Register */
703 smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF, SMI_GCR, sizeof(SMI_GCR));
wdenkc6097192002-11-03 00:24:07 +0000704
wdenkaea86e42004-03-23 22:53:55 +0000705 /* Sequencer Register */
706 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SEQR, sizeof(SMI_SEQR));
wdenkc6097192002-11-03 00:24:07 +0000707
wdenkaea86e42004-03-23 22:53:55 +0000708 /* Power Control Register */
709 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_PCR, sizeof(SMI_PCR));
wdenkc6097192002-11-03 00:24:07 +0000710
wdenkaea86e42004-03-23 22:53:55 +0000711 /* Memory Control Register */
712 /* Register MSR62 is a power on configurable register. We don't */
713 /* modify it */
714 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_MCR, sizeof(SMI_MCR));
wdenkc6097192002-11-03 00:24:07 +0000715
wdenkaea86e42004-03-23 22:53:55 +0000716 /* Set misc output register */
717 smiLoadMsr (res_mode);
wdenkd3602132004-03-25 15:14:43 +0000718
wdenkaea86e42004-03-23 22:53:55 +0000719 /* Set CRT and Clock control registers */
720 smiLoadCrt (res_mode, bits_per_pixel);
wdenkd3602132004-03-25 15:14:43 +0000721
wdenkaea86e42004-03-23 22:53:55 +0000722 smiLoadCcr (res_mode, device_id);
wdenkc6097192002-11-03 00:24:07 +0000723
wdenkaea86e42004-03-23 22:53:55 +0000724 /* Hardware Cusor Register */
725 smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_HCR, sizeof(SMI_HCR));
wdenkc6097192002-11-03 00:24:07 +0000726
wdenkaea86e42004-03-23 22:53:55 +0000727 /* Enable Display */
728 videoout = 2; /* Default output is CRT */
729 if ((penv = getenv ("videoout")) != NULL) {
730 /* deceide if it is a string */
731 videoout = (int) simple_strtoul (penv, NULL, 16);
732 }
733 smiWrite (SMI_INDX_C4, 0x31, videoout);
wdenkc6097192002-11-03 00:24:07 +0000734
wdenkaea86e42004-03-23 22:53:55 +0000735 /* Video processor default setup */
736 smiInitVideoProcessor ();
wdenkc6097192002-11-03 00:24:07 +0000737
wdenkaea86e42004-03-23 22:53:55 +0000738 /* Capture port default setup */
739 smiInitCapturePort ();
740
741 /* Drawing engine default setup */
742 smiInitDrawingEngine ();
743
744 /* Turn on display */
745 smiWrite (0x3c4, 0x01, 0x01);
746
747 /* Clear video memory */
748 i = pGD->memSize/4;
749 vm = (unsigned int *)pGD->pciBase;
750 while(i--)
751 *vm++ = 0;
752 return ((void*)&smi);
wdenkc6097192002-11-03 00:24:07 +0000753}
754
755/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000756 *
757 * Drawing engine fill on screen region
758 */
wdenkc6097192002-11-03 00:24:07 +0000759void video_hw_rectfill (
wdenkaea86e42004-03-23 22:53:55 +0000760 unsigned int bpp, /* bytes per pixel */
761 unsigned int dst_x, /* dest pos x */
762 unsigned int dst_y, /* dest pos y */
763 unsigned int dim_x, /* frame width */
764 unsigned int dim_y, /* frame height */
765 unsigned int color /* fill color */
766 )
wdenkc6097192002-11-03 00:24:07 +0000767{
wdenkaea86e42004-03-23 22:53:55 +0000768 register GraphicDevice *pGD = (GraphicDevice *)&smi;
769 register unsigned int control;
wdenkc6097192002-11-03 00:24:07 +0000770
wdenkaea86e42004-03-23 22:53:55 +0000771 dim_x *= bpp;
wdenkc6097192002-11-03 00:24:07 +0000772
wdenkaea86e42004-03-23 22:53:55 +0000773 out32r ((pGD->dprBase + 0x0014), color);
774 out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
775 out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
wdenkc6097192002-11-03 00:24:07 +0000776
wdenkaea86e42004-03-23 22:53:55 +0000777 control = 0x0000ffff & in32r ((pGD->dprBase + 0x000c));
wdenkc6097192002-11-03 00:24:07 +0000778
wdenkaea86e42004-03-23 22:53:55 +0000779 control |= 0x80010000;
wdenkc6097192002-11-03 00:24:07 +0000780
wdenkaea86e42004-03-23 22:53:55 +0000781 out32r ((pGD->dprBase + 0x000c), control);
wdenkc6097192002-11-03 00:24:07 +0000782
wdenkaea86e42004-03-23 22:53:55 +0000783 /* Wait for drawing processor */
784 do
785 {
786 out8 ((pGD->isaBase + 0x3c4), 0x16);
787 } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
wdenkc6097192002-11-03 00:24:07 +0000788}
789
790/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000791 *
792 * Drawing engine bitblt with screen region
793 */
wdenkc6097192002-11-03 00:24:07 +0000794void video_hw_bitblt (
wdenkaea86e42004-03-23 22:53:55 +0000795 unsigned int bpp, /* bytes per pixel */
796 unsigned int src_x, /* source pos x */
797 unsigned int src_y, /* source pos y */
798 unsigned int dst_x, /* dest pos x */
799 unsigned int dst_y, /* dest pos y */
800 unsigned int dim_x, /* frame width */
801 unsigned int dim_y /* frame height */
802 )
wdenkc6097192002-11-03 00:24:07 +0000803{
wdenkaea86e42004-03-23 22:53:55 +0000804 register GraphicDevice *pGD = (GraphicDevice *)&smi;
805 register unsigned int control;
wdenkc6097192002-11-03 00:24:07 +0000806
wdenkaea86e42004-03-23 22:53:55 +0000807 dim_x *= bpp;
wdenkc6097192002-11-03 00:24:07 +0000808
wdenkaea86e42004-03-23 22:53:55 +0000809 if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x)))
810 {
811 out32r ((pGD->dprBase + 0x0000), (((src_x+dim_x-1)<<16) | (src_y+dim_y-1)));
812 out32r ((pGD->dprBase + 0x0004), (((dst_x+dim_x-1)<<16) | (dst_y+dim_y-1)));
813 control = 0x88000000;
814 } else {
815 out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y));
816 out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
817 control = 0x80000000;
818 }
wdenkc6097192002-11-03 00:24:07 +0000819
wdenkaea86e42004-03-23 22:53:55 +0000820 out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
821 control |= (0x0000ffff & in32r ((pGD->dprBase + 0x000c)));
822 out32r ((pGD->dprBase + 0x000c), control);
wdenkc6097192002-11-03 00:24:07 +0000823
wdenkaea86e42004-03-23 22:53:55 +0000824 /* Wait for drawing processor */
825 do
826 {
827 out8 ((pGD->isaBase + 0x3c4), 0x16);
828 } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
wdenkc6097192002-11-03 00:24:07 +0000829}
830
831/*******************************************************************************
wdenkaea86e42004-03-23 22:53:55 +0000832 *
833 * Set a RGB color in the LUT (8 bit index)
834 */
wdenkc6097192002-11-03 00:24:07 +0000835void video_set_lut (
wdenkaea86e42004-03-23 22:53:55 +0000836 unsigned int index, /* color number */
837 unsigned char r, /* red */
838 unsigned char g, /* green */
839 unsigned char b /* blue */
840 )
wdenkc6097192002-11-03 00:24:07 +0000841{
wdenkaea86e42004-03-23 22:53:55 +0000842 register GraphicDevice *pGD = (GraphicDevice *)&smi;
wdenkc6097192002-11-03 00:24:07 +0000843
wdenkaea86e42004-03-23 22:53:55 +0000844 out8 (SMI_LUT_MASK, 0xff);
wdenkc6097192002-11-03 00:24:07 +0000845
wdenkaea86e42004-03-23 22:53:55 +0000846 out8 (SMI_LUT_START, (char)index);
wdenkc6097192002-11-03 00:24:07 +0000847
wdenkaea86e42004-03-23 22:53:55 +0000848 out8 (SMI_LUT_RGB, r>>2); /* red */
849 udelay (10);
850 out8 (SMI_LUT_RGB, g>>2); /* green */
851 udelay (10);
852 out8 (SMI_LUT_RGB, b>>2); /* blue */
853 udelay (10);
wdenkc6097192002-11-03 00:24:07 +0000854}