]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/smiLynxEM.c
Initial revision
[karo-tx-uboot.git] / drivers / smiLynxEM.c
1 /*
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
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * 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  *
33  */
34
35 #include <common.h>
36
37 #if defined(CONFIG_VIDEO_SMI_LYNXEM)
38
39 #include <pci.h>
40 #include <video_fb.h>
41
42 /*
43  * Export Graphic Device
44  */
45 GraphicDevice smi;
46
47 /*
48  * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
49  */
50 #define VIDEO_MEM_SIZE  0x400000
51
52 /*
53  * Supported video modes for SMI Lynx E/EM/EM+
54  */
55 #define VIDEO_MODES             7
56 #define DUAL_800_600            0   /* SMI710:VGA1:75Hz     (pitch=1600) */
57                                     /*        VGA2:60/120Hz (pitch=1600) */
58                                     /* SMI810:VGA1:75Hz     (pitch=1600) */
59                                     /*        VGA2:75Hz     (pitch=1600) */
60 #define DUAL_1024_768           1   /* VGA1:75Hz VGA2:73Hz (pitch=2048)  */
61 #define SINGLE_800_600          2   /* VGA1:75Hz (pitch=800)             */
62 #define SINGLE_1024_768         3   /* VGA1:75Hz (pitch=1024)            */
63 #define SINGLE_1280_1024        4   /* VGA1:75Hz (pitch=1280)            */
64 #define TV_MODE_CCIR            5   /* VGA1:50Hz (h=720;v=576;pitch=720) */
65 #define TV_MODE_EIA             6   /* VGA1:60Hz (h=720;v=484;pitch=720) */
66
67
68 /*
69  * ISA mapped regs
70  */
71 #define SMI_INDX_C4             (pGD->isaBase + 0x03c4)    /* index reg */
72 #define SMI_DATA_C5             (pGD->isaBase + 0x03c5)    /* data reg */
73 #define SMI_INDX_D4             (pGD->isaBase + 0x03d4)    /* index reg */
74 #define SMI_DATA_D5             (pGD->isaBase + 0x03d5)    /* data reg */
75 #define SMI_INDX_CE             (pGD->isaBase + 0x03ce)    /* index reg */
76 #define SMI_DATA_CF             (pGD->isaBase + 0x03cf)    /* data reg */
77 #define SMI_LOCK_REG            (pGD->isaBase + 0x03c3)    /* unlock/lock ext crt reg */
78 #define SMI_MISC_REG            (pGD->isaBase + 0x03c2)    /* misc reg */
79 #define SMI_LUT_MASK            (pGD->isaBase + 0x03c6)    /* lut mask reg */
80 #define SMI_LUT_START           (pGD->isaBase + 0x03c8)    /* lut start index */
81 #define SMI_LUT_RGB             (pGD->isaBase + 0x03c9)    /* lut colors auto incr.*/
82
83
84 /*
85  * Video processor control
86 */
87 typedef struct {
88     unsigned int   control;
89     unsigned int   colorKey;
90     unsigned int   colorKeyMask;
91     unsigned int   start;
92     unsigned short offset;
93     unsigned short width;
94     unsigned int   fifoPrio;
95     unsigned int   fifoERL;
96     unsigned int   YUVtoRGB;
97 } SmiVideoProc;
98
99 /*
100  * Video window control
101  */
102 typedef struct {
103     unsigned short top;
104     unsigned short left;
105     unsigned short bottom;
106     unsigned short right;
107     unsigned int   srcStart;
108     unsigned short width;
109     unsigned short offset;
110     unsigned char  hStretch;
111     unsigned char  vStretch;
112 } SmiVideoWin;
113
114 /*
115  * Capture port control
116  */
117 typedef struct {
118     unsigned int   control;
119     unsigned short topClip;
120     unsigned short leftClip;
121     unsigned short srcHeight;
122     unsigned short srcWidth;
123     unsigned int   srcBufStart1;
124     unsigned int   srcBufStart2;
125     unsigned short srcOffset;
126     unsigned short fifoControl;
127 } SmiCapturePort;
128
129
130
131 /*
132  * Register values for common video modes
133  */
134 static char SMI_SCR[22] = {
135     /* all modes */
136     0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x14, 0x00, 0x15, 0x90,
137     0x16, 0x10, 0x17, 0x2c, 0x18, 0xb1, 0x19, 0x20, 0x1a, 0x01
138 };
139
140 static char SMI_EXT_CRT[VIDEO_MODES][24] = {
141     { /* DUAL_800_600_8 */
142     0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
143     0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
144     },
145     { /* DUAL_1024_768_8 */
146     0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
147     0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
148     },
149     { /* SINGLE_800_600_8 */
150     0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
151     0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
152     },
153     { /* SINGLE_1024_768_8 */
154     0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
155     0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
156     },
157     { /* SINGLE_1280_1024_8 */
158     0x30, 0x09, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
159     0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
160     },
161     { /* TV_MODE_CCIR */
162     0x30, 0x80, 0x31, 0x2b, 0x32, 0x06, 0x33, 0x01, 0x34, 0x26, 0x35, 0x88,
163     0x36, 0x02, 0x38, 0x11, 0x39, 0x11, 0x3a, 0x20, 0x3e, 0xa3, 0x3f, 0x00
164     },
165     { /* TV_MODE_EIA */
166     0x30, 0x80, 0x31, 0x2b, 0x32, 0x06, 0x33, 0x00, 0x34, 0xf8, 0x35, 0x88,
167     0x36, 0x02, 0x38, 0x11, 0x39, 0x11, 0x3a, 0x20, 0x3e, 0xa3, 0x3f, 0x00
168     },
169 };
170
171 static char SMI_CRTCR[VIDEO_MODES][50] = {
172     { /* DUAL_800_600_8 */
173     0x00, 0x7f, 0x01, 0x63, 0x02, 0x63, 0x03, 0x00, 0x04, 0x68, 0x05, 0x12,
174     0x06, 0x6f, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
175     0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x59, 0x11, 0x2c,
176     0x12, 0x57, 0x13, 0x64, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3,
177     0x18, 0xff
178     },
179     { /* DUAL_1024_768_8 */
180     0x00, 0x9f, 0x01, 0x7f, 0x02, 0x7f, 0x03, 0x00, 0x04, 0x82, 0x05, 0x0e,
181     0x06, 0x1e, 0x07, 0xf5, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
182     0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x01, 0x11, 0x24,
183     0x12, 0xff, 0x13, 0x80, 0x14, 0x40, 0x15, 0xff, 0x16, 0x00, 0x17, 0xe3,
184     0x18, 0xff
185     },
186     { /* SINGLE_800_600_8 */
187     0x00, 0x7f, 0x01, 0x63, 0x02, 0x63, 0x03, 0x00, 0x04, 0x68, 0x05, 0x12,
188     0x06, 0x6f, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
189     0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x59, 0x11, 0x2c,
190     0x12, 0x57, 0x13, 0x32, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3,
191     0x18, 0xff
192     },
193     { /* SINGLE_1024_768_8 */
194     0x00, 0x9f, 0x01, 0x7f, 0x02, 0x7f, 0x03, 0x00, 0x04, 0x82, 0x05, 0x0e,
195     0x06, 0x1e, 0x07, 0xf5, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
196     0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x01, 0x11, 0x24,
197     0x12, 0xff, 0x13, 0x40, 0x14, 0x40, 0x15, 0xff, 0x16, 0x00, 0x17, 0xe3,
198     0x18, 0xff
199     },
200     { /* SINGLE_1280_1024_8 */
201     0x00, 0xce, 0x01, 0x9f, 0x02, 0x9f, 0x03, 0x00, 0x04, 0xa2, 0x05, 0x12,
202     0x06, 0x2a, 0x07, 0x5a, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
203     0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x01, 0x11, 0x23,
204     0x12, 0xff, 0x13, 0x50, 0x14, 0x40, 0x15, 0xff, 0x16, 0x00, 0x17, 0xe3,
205     0x18, 0xff
206     },
207     { /* TV_MODE_CCIR */
208     0x00, 0x00, 0x01, 0x59, 0x02, 0x63, 0x03, 0x00, 0x04, 0x69, 0x05, 0x10,
209     0x06, 0x72, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
210     0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x58, 0x11, 0x2c,
211     0x12, 0x57, 0x13, 0x2d, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3,
212     0x18, 0xff
213     },
214     { /* TV_MODE_EIA */
215     0x00, 0x00, 0x01, 0x59, 0x02, 0x63, 0x03, 0x00, 0x04, 0x69, 0x05, 0x10,
216     0x06, 0x72, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00,
217     0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x58, 0x11, 0x2c,
218     0x12, 0x57, 0x13, 0x2d, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3,
219     0x18, 0xff
220     },
221 };
222
223 static char SMI_SEQR[10] = {
224     0x00, 0x03, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e
225 };
226
227 static char SMI_PCR[VIDEO_MODES][8] = {
228     { /* DUAL_800_600_8 */
229     0x20, 0x04, 0x21, 0x20, 0x22, 0x00, 0x23, 0x00
230     },
231     { /* DUAL_1024_768_8 */
232     0x20, 0x04, 0x21, 0x20, 0x22, 0x00, 0x23, 0x00
233     },
234     { /* SINGLE_800_600_8 */
235     0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
236     },
237     { /* SINGLE_1024_768_8 */
238     0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
239     },
240     { /* SINGLE_1280_1024_8 */
241     0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
242     },
243     { /* TV_MODE_CCIR */
244     0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
245     },
246     { /* TV_MODE_EIA */
247     0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00
248     },
249 };
250
251 static char SMI_MCR[VIDEO_MODES][6] = {
252     { /* DUAL_800_600_8 */
253     0x60, 0x01, 0x61, 0x00, 0x62, 0x7a
254     },
255     { /* DUAL_1024_768_8 */
256     0x60, 0x01, 0x61, 0x00, 0x62, 0x7a
257     },
258     { /* SINGLE_800_600_8 */
259     0x60, 0x00, 0x61, 0x00, 0x62, 0x34
260     },
261     { /* SINGLE_1024_768_8 */
262     0x60, 0x00, 0x61, 0x00, 0x62, 0xfe
263     },
264     { /* SINGLE_1280_1024_8 */
265     0x60, 0x00, 0x61, 0x00, 0x62, 0xfe
266     },
267     { /* TV_MODE_CCIR */
268     0x60, 0x00, 0x61, 0x00, 0x62, 0x34
269     },
270     { /* TV_MODE_EIA */
271     0x60, 0x00, 0x61, 0x00, 0x62, 0x34
272     },
273 };
274
275 static char SMI_CCR[VIDEO_MODES][18] = {
276     { /* DUAL_800_600_8 */
277     0x65, 0x34, 0x68, 0x50, 0x69, 0x05, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15,
278     0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12
279     },
280     { /* DUAL_1024_768_8 */
281     0x65, 0x00, 0x68, 0x50, 0x69, 0x06, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x0b,
282     0x6d, 0x02, 0x6e, 0x0b, 0x6f, 0x02
283     },
284     { /* SINGLE_800_600_8 */
285     0x65, 0x34, 0x68, 0x40, 0x69, 0x03, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15,
286     0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12
287     },
288     { /* SINGLE_1024_768_8 */
289     0x65, 0x00, 0x68, 0x50, 0x69, 0x03, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x0b,
290     0x6d, 0x02, 0x6e, 0x0b, 0x6f, 0x02
291     },
292     { /* SINGLE_1280_1024_8 */
293     0x65, 0x00, 0x68, 0x50, 0x69, 0x03, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0xd9,
294     0x6d, 0x17, 0x6e, 0xd9, 0x6f, 0x17
295     },
296     { /* TV_MODE_CCIR */
297     0x65, 0x07, 0x68, 0xc0, 0x69, 0x81, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15,
298     0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12
299     },
300     { /* TV_MODE_EIA */
301     0x65, 0x07, 0x68, 0xc0, 0x69, 0x81, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15,
302     0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12
303     },
304 };
305
306 static char SMI_SHVGA[VIDEO_MODES][24] = {
307     { /* DUAL_800_600_8 */
308     0x40, 0x7f, 0x41, 0x63, 0x42, 0x00, 0x43, 0x68, 0x44, 0x12, 0x45, 0x6f,
309     0x46, 0x57, 0x47, 0x00, 0x48, 0x59, 0x49, 0x0c, 0x4a, 0xa0, 0x4b, 0x20,
310     },
311     { /* DUAL_1024_768_8 */
312     0x40, 0x9f, 0x41, 0x7f, 0x42, 0x00, 0x43, 0x82, 0x44, 0x0e, 0x45, 0x1e,
313     0x46, 0xff, 0x47, 0x00, 0x48, 0x00, 0x49, 0x03, 0x4a, 0xe5, 0x4b, 0x20,
314     },
315     { /* SINGLE_800_600_8 */
316     0x40, 0x7f, 0x41, 0x63, 0x42, 0x00, 0x43, 0x68, 0x44, 0x12, 0x45, 0x6f,
317     0x46, 0x57, 0x47, 0x00, 0x48, 0x59, 0x49, 0x0c, 0x4a, 0xa0, 0x4b, 0x20,
318     },
319     { /* SINGLE_1024_768_8 */
320     0x40, 0x9f, 0x41, 0x7f, 0x42, 0x00, 0x43, 0x82, 0x44, 0x0e, 0x45, 0x1e,
321     0x46, 0xff, 0x47, 0x00, 0x48, 0x01, 0x49, 0x04, 0x4a, 0xa5, 0x4b, 0x20,
322     },
323     { /* SINGLE_1280_1024_8 */
324     0x40, 0xce, 0x41, 0x9f, 0x42, 0x00, 0x43, 0xa2, 0x44, 0x12, 0x45, 0x2a,
325     0x46, 0xff, 0x47, 0x00, 0x48, 0x01, 0x49, 0x03, 0x4a, 0x4a, 0x4b, 0x20,
326     },
327     { /* TV_MODE_CCIR */
328     0x40, 0x6d, 0x41, 0x59, 0x42, 0x00, 0x43, 0x60, 0x44, 0x09, 0x45, 0x38,
329     0x46, 0x25, 0x47, 0x05, 0x48, 0x2a, 0x49, 0x00, 0x4a, 0x4d, 0x4b, 0x00,
330     },
331     { /* TV_MODE_EIA */
332     0x40, 0x6d, 0x41, 0x59, 0x42, 0x00, 0x43, 0x60, 0x44, 0x09, 0x45, 0x06,
333     0x46, 0xf7, 0x47, 0x05, 0x48, 0xfa, 0x49, 0x00, 0x4a, 0x41, 0x4b, 0x00,
334     },
335 };
336
337
338 static char SMI_GPR[VIDEO_MODES][12] = {
339     { /* DUAL_800_600_8 */
340     0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
341     },
342     { /* DUAL_1024_768_8 */
343     0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
344     },
345     { /* SINGLE_800_600_8 */
346     0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
347     },
348     { /* SINGLE_1024_768_8 */
349     0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
350     },
351     { /* SINGLE_1280_1024_8 */
352     0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00
353     },
354     { /* TV_MODE_CCIR */
355     0x70, 0x82, 0x71, 0x8d, 0x72, 0x0c, 0x73, 0x32, 0x74, 0x09, 0x75, 0x28
356     },
357     { /* TV_MODE_EIA */
358     0x70, 0x82, 0x71, 0x8d, 0x72, 0x0c, 0x73, 0x32, 0x74, 0x09, 0x75, 0x28
359     },
360 };
361
362 static char SMI_HCR[VIDEO_MODES][22] = {
363     { /* DUAL_800_600_8 */
364     0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
365     0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
366     },
367     { /* DUAL_1024_768_8 */
368     0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
369     0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
370     },
371     { /* SINGLE_800_600_8 */
372     0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
373     0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
374     },
375     { /* SINGLE_1024_768_8 */
376     0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
377     0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
378     },
379     { /* SINGLE_1280_1024_8 */
380     0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
381     0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
382     },
383     { /* TV_MODE_CCIR */
384     0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
385     0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
386     },
387     { /* TV_MODE_EIA */
388     0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
389     0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
390     },
391 };
392
393 static char SMI_FPR[VIDEO_MODES][88] = {
394     { /* DUAL_800_600_8 */
395     0x30, 0x36, 0x31, 0x83, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x03,
396     0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8,
397     0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x41,
398     0x4b, 0xa0, 0x4c, 0x00,
399     0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x67, 0x55, 0x71,
400     0x56, 0x57, 0x57, 0x59, 0x58, 0x03, 0x59, 0x00, 0x5a, 0x4a,
401     0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
402     0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
403     0xa0, 0x44
404     },
405     { /* DUAL_1024_768_8 */
406     0x30, 0x3a, 0x31, 0x83, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x00,
407     0x3f, 0x00, 0x40, 0x80, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00,
408     0x45, 0x42, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x41,
409     0x4b, 0xa0, 0x4c, 0x00,
410     0x50, 0x06, 0x51, 0x68, 0x52, 0xa7, 0x53, 0x7f, 0x54, 0x83, 0x55, 0x25,
411     0x56, 0xff, 0x57, 0x03, 0x58, 0x04, 0x59, 0x00, 0x5a, 0xc2,
412     0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
413     0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
414     0xa0, 0x44
415     },
416     { /* SINGLE_800_600_8 */
417     0x30, 0x36, 0x31, 0x82, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x03,
418     0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8,
419     0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x00,
420     0x4b, 0xa0, 0x4c, 0x00,
421     0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x67, 0x55, 0x71,
422     0x56, 0x57, 0x57, 0x59, 0x58, 0x03, 0x59, 0x00, 0x5a, 0x4a,
423     0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
424     0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
425     0xa0, 0x44
426     },
427     { /* SINGLE_1024_768_8 */
428     0x30, 0x3a, 0x31, 0x82, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x00,
429     0x3f, 0x00, 0x40, 0x80, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00,
430     0x45, 0x42, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x11,
431     0x4b, 0xa0, 0x4c, 0x00,
432     0x50, 0x06, 0x51, 0x68, 0x52, 0xa7, 0x53, 0x7f, 0x54, 0x83, 0x55, 0x24,
433     0x56, 0xff, 0x57, 0x03, 0x58, 0x04, 0x59, 0x00, 0x5a, 0xc2,
434     0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
435     0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
436     0xa0, 0x44
437     },
438     { /* SINGLE_1280_1024_8 */
439     0x30, 0x3e, 0x31, 0x82, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x00,
440     0x3f, 0x00, 0x40, 0xa0, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00,
441     0x45, 0x42, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x11,
442     0x4b, 0xa0, 0x4c, 0x00,
443     0x50, 0x08, 0x51, 0x88, 0x52, 0xd3, 0x53, 0x9f, 0x54, 0xa3, 0x55, 0x2a,
444     0x56, 0xff, 0x57, 0x04, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x63,
445     0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00,
446     0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00,
447     0xa0, 0x44
448     },
449     { /* TV_MODE_CCIR */
450     0x30, 0x24, 0x31, 0x84, 0x32, 0x20, 0x33, 0x09, 0x34, 0xf0, 0x3e, 0x03,
451     0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8,
452     0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x00,
453     0x4b, 0xa0, 0x4c, 0x00,
454     0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x68, 0x55, 0x73,
455     0x56, 0x57, 0x57, 0x58, 0x58, 0x04, 0x59, 0x57, 0x5a, 0x7b,
456     0xa1, 0x10, 0xa2, 0xab, 0xa3, 0x98, 0xa4, 0xc1, 0xa8, 0x8c, 0xa9, 0x05,
457     0xaa, 0x17, 0xab, 0x35, 0xac, 0x41, 0xad, 0x68, 0xae, 0x00, 0xaf, 0x00,
458     0xa0, 0x00
459     },
460     { /* TV_MODE_EIA */
461     0x30, 0x24, 0x31, 0x84, 0x32, 0x20, 0x33, 0x09, 0x34, 0xf0, 0x3e, 0x03,
462     0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8,
463     0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x00,
464     0x4b, 0xa0, 0x4c, 0x00,
465     0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x68, 0x55, 0x73,
466     0x56, 0x57, 0x57, 0x58, 0x58, 0x04, 0x59, 0x57, 0x5a, 0x7b,
467     0xa1, 0x10, 0xa2, 0xab, 0xa3, 0x98, 0xa4, 0xc1, 0xa8, 0x8c, 0xa9, 0x05,
468     0xaa, 0x17, 0xab, 0x35, 0xac, 0x41, 0xad, 0x68, 0xae, 0x00, 0xaf, 0x00,
469     0xa0, 0x00
470     },
471 };
472
473 static char SMI_GCR[18] = {
474     0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
475     0x06, 0x05, 0x07, 0x0f, 0x08, 0xff
476 };
477
478 /*******************************************************************************
479 *
480 * Read SMI ISA register
481 */
482 static char smiRead (unsigned short index, char reg)
483 {
484     register GraphicDevice *pGD = (GraphicDevice *)&smi;
485
486     out8 ((pGD->isaBase + index), reg);
487     return (in8 (pGD->isaBase + index + 1));
488 }
489
490 /*******************************************************************************
491 *
492 * Write SMI ISA register
493 */
494 static void smiWrite (unsigned short index, char reg, char val)
495 {
496     register GraphicDevice *pGD = (GraphicDevice *)&smi;
497
498     out8 ((pGD->isaBase + index), reg);
499     out8 ((pGD->isaBase + index + 1), val);
500 }
501
502 /*******************************************************************************
503 *
504 * Write a table of SMI ISA register
505 */
506 static void smiLoadRegs (
507     unsigned int iReg,
508     unsigned int dReg,
509     char         *regTab,
510     unsigned int tabSize
511     )
512 {
513     register int i;
514
515     for (i=0; i<tabSize; i+=2)
516     {
517         out8 (iReg, regTab[i]);
518         out8 (dReg, regTab[i+1]);
519     }
520 }
521
522 /*******************************************************************************
523 *
524 * Init capture port registers
525 */
526 static void smiInitCapturePort (void)
527 {
528     SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
529     register GraphicDevice *pGD  = (GraphicDevice *)&smi;
530     register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
531
532     out32r ((pGD->cprBase + 0x0004), ((pCP->topClip<<16)   | pCP->leftClip));
533     out32r ((pGD->cprBase + 0x0008), ((pCP->srcHeight<<16) | pCP->srcWidth));
534     out32r ((pGD->cprBase + 0x000c), pCP->srcBufStart1/8);
535     out32r ((pGD->cprBase + 0x0010), pCP->srcBufStart2/8);
536     out32r ((pGD->cprBase + 0x0014), pCP->srcOffset/8);
537     out32r ((pGD->cprBase + 0x0018), pCP->fifoControl);
538     out32r ((pGD->cprBase + 0x0000), pCP->control);
539 }
540
541
542 /*******************************************************************************
543 *
544 * Init video processor registers
545 */
546 static void smiInitVideoProcessor (void)
547 {
548     SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed };
549     SmiVideoWin  smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 };
550     register GraphicDevice *pGD = (GraphicDevice *)&smi;
551     register SmiVideoProc  *pVP = (SmiVideoProc *)&smiVP;
552     register SmiVideoWin *pVWin = (SmiVideoWin *)&smiVW;
553
554     pVP->width    = pGD->plnSizeX * pGD->gdfBytesPP;
555     pVP->control |= pGD->gdfIndex << 16;
556     pVWin->bottom = pGD->winSizeY - 1;
557     pVWin->right  = pGD->winSizeX - 1;
558     pVWin->width  = pVP->width;
559
560     /* color key */
561     out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
562
563      /* color key mask */
564     out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
565
566     /* data src start adrs */
567     out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
568
569     /* data width and offset */
570     out32r ((pGD->vprBase + 0x0010),
571         ((pVP->offset   / 8 * pGD->gdfBytesPP) << 16) |
572          (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
573
574     /* video window 1 */
575     out32r ((pGD->vprBase + 0x0014),
576         ((pVWin->top << 16) | pVWin->left));
577
578     out32r ((pGD->vprBase + 0x0018),
579         ((pVWin->bottom << 16) | pVWin->right));
580
581     out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
582
583     out32r ((pGD->vprBase + 0x0020),
584         (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
585
586     out32r ((pGD->vprBase + 0x0024),
587         (((pVWin->hStretch) << 8) | pVWin->vStretch));
588
589     /* video window 2 */
590     out32r ((pGD->vprBase + 0x0028),
591         ((pVWin->top << 16) | pVWin->left));
592
593     out32r ((pGD->vprBase + 0x002c),
594         ((pVWin->bottom << 16) | pVWin->right));
595
596     out32r ((pGD->vprBase + 0x0030),
597         pVWin->srcStart / 8);
598
599     out32r ((pGD->vprBase + 0x0034),
600         (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
601
602     out32r ((pGD->vprBase + 0x0038),
603         (((pVWin->hStretch) << 8) | pVWin->vStretch));
604
605     /* fifo prio control */
606     out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
607
608     /* fifo empty request levell */
609     out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
610
611     /* conversion constant */
612     out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
613
614     /* vpr control word */
615     out32r ((pGD->vprBase + 0x0000), pVP->control);
616 }
617
618 /******************************************************************************
619  *
620  * Init drawing engine registers
621  */
622 static void smiInitDrawingEngine (void)
623 {
624     GraphicDevice *pGD = (GraphicDevice *)&smi;
625     unsigned int val;
626
627     /* don't start now */
628     out32r ((pGD->dprBase + 0x000c), 0x000f0000);
629
630     /* set rop2 to copypen */
631     val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
632     out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
633
634     /* set clip rect */
635     out32r ((pGD->dprBase + 0x002c), 0);
636     out32r ((pGD->dprBase + 0x0030),
637         ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
638
639     /* src row pitch */
640     val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
641     out32r ((pGD->dprBase + 0x0010),
642         (val | pGD->plnSizeX * pGD->gdfBytesPP));
643
644     /* dst row pitch */
645     val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
646     out32r ((pGD->dprBase + 0x0010),
647         (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
648
649     /* window width src/dst */
650     out32r ((pGD->dprBase + 0x003c),
651         (((pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)<<16) |
652           (pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)));
653     out16r ((pGD->dprBase + 0x001e), 0x0000);
654
655     /* src base adrs */
656     out32r ((pGD->dprBase + 0x0040),
657         (((pGD->frameAdrs/8) & 0x000fffff)));
658
659     /* dst base adrs */
660     out32r ((pGD->dprBase + 0x0044),
661         (((pGD->frameAdrs/8) & 0x000fffff)));
662
663     /* foreground color */
664     out32r ((pGD->dprBase + 0x0014), pGD->fg);
665
666     /* background color */
667     out32r ((pGD->dprBase + 0x0018), pGD->bg);
668
669     /* xcolor */
670     out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
671
672     /* xcolor mask */
673     out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
674
675     /* bit mask */
676     out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
677
678     /* load mono pattern */
679     out32r ((pGD->dprBase + 0x0034), 0);
680     out32r ((pGD->dprBase + 0x0038), 0);
681 }
682
683 static struct pci_device_id supported[] = {
684     { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_710 },
685     { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_712 },
686     { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_810 },
687     { }
688 };
689
690
691 /*******************************************************************************
692 *
693 * Init video chip with common Linux graphic modes (lilo)
694 */
695 void *video_hw_init (void)
696 {
697     GraphicDevice *pGD = (GraphicDevice *)&smi;
698     unsigned short device_id;
699     pci_dev_t devbusfn;
700     int videomode;
701     unsigned int pci_mem_base, *vm, i;
702     unsigned int gdfTab[] = { 1, 2, 2, 4, 3, 1 };
703     char *penv;
704     char *gdfModes[] =
705             {
706             "8 Bit Index Color",
707             "15 Bit 5-5-5 RGB",
708             "16 Bit 5-6-5 RGB",
709             "32 Bit X-8-8-8 RGB",
710             "24 Bit 8-8-8 RGB",
711             "8 Bit 3-3-2 RGB"
712             };
713     int vgaModes[16][2] =
714             {
715             {769, -1}, {771, 0x00002}, {773, 0x00003}, {775, 0x00004},
716             {784, -1}, {787, 0x10002}, {790, 0x10003}, {793, 0x10004},
717             {785, -1}, {788, 0x20002}, {791, 0x20003}, {794, 0x20004},
718             {786, -1}, {789, 0x40002}, {792, 0x40003}, {795, 0x40004}
719             };
720
721     /* Search for video chip */
722     printf("Video: ");
723
724     if ((devbusfn = pci_find_devices(supported, 0)) < 0)
725     {
726         printf ("Controller not found !\n");
727         return (NULL);
728     }
729
730     /* PCI setup */
731     pci_write_config_dword (devbusfn, PCI_COMMAND, (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
732     pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
733     pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
734     pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
735
736     /* Initialize the video controller */
737     if ((penv = getenv ("videomode")) != NULL)
738         videomode = (int)simple_strtoul (penv, NULL, 16);
739     else
740         videomode = 0x303;                    /* Default 800x600 8 bit index color */
741
742     /* Compare with common vga mode numbers */
743     for (i=0; i<16; i++)
744     {
745         if (vgaModes[i][0] == videomode)
746         {
747             if (vgaModes[i][1] == -1)
748             {
749                 printf("Videomode not supported !\n");
750                 return (NULL);                /* mode not supported */
751             }
752             pGD->mode = vgaModes[i][1];        /* use driver int. mode number */
753             break;
754         }
755     }
756
757     /* Extract graphic data format */
758     pGD->gdfIndex = (pGD->mode & 0x00070000) >> 16;
759     if (pGD->gdfIndex > 5)
760         pGD->gdfIndex = 0;
761     pGD->gdfBytesPP = gdfTab[pGD->gdfIndex];
762
763     /* Extract graphic resolution */
764     pGD->mode &= 0xf;
765
766     /* Exit for not supported resolutions */
767     if (((pGD->mode==DUAL_800_600) || (pGD->mode==DUAL_1024_768)) && (pGD->gdfBytesPP > 1))
768     {
769         printf ("Dual screen for 1BPP only !\n");
770         return (NULL);
771     }
772
773     if ((pGD->mode==SINGLE_1280_1024) && (pGD->gdfBytesPP==4))
774     {
775         printf ("Out of memory !\n");
776         return (NULL);
777     }
778
779     /* Set graphic parameters */
780     switch (pGD->mode)
781     {
782     case DUAL_800_600:
783             pGD->winSizeX = 800;
784             pGD->winSizeY = 600;
785             pGD->plnSizeX = 1600;
786             pGD->plnSizeY = 600;
787             sprintf (pGD->modeIdent, "Dual Screen 800x600 with %s", gdfModes[pGD->gdfIndex]);
788             break;
789     case DUAL_1024_768:
790             pGD->winSizeX = 1024;
791             pGD->winSizeY = 768;
792             pGD->plnSizeX = 2048;
793             pGD->plnSizeY = 768;
794             sprintf (pGD->modeIdent, "Dual Screen 1024x768 with %s", gdfModes[pGD->gdfIndex]);
795             break;
796     case SINGLE_800_600:
797             pGD->winSizeX = 800;
798             pGD->winSizeY = 600;
799             pGD->plnSizeX = 800;
800             pGD->plnSizeY = 600;
801             sprintf (pGD->modeIdent, "Single Screen 800x600 with %s", gdfModes[pGD->gdfIndex]);
802             break;
803     case SINGLE_1024_768:
804             pGD->winSizeX = 1024;
805             pGD->winSizeY = 768;
806             pGD->plnSizeX = 1024;
807             pGD->plnSizeY = 768;
808             sprintf (pGD->modeIdent,"Single Screen 1024x768 with %s", gdfModes[pGD->gdfIndex]);
809             break;
810     case TV_MODE_CCIR:
811             pGD->winSizeX = 720;
812             pGD->winSizeY = 576;
813             pGD->plnSizeX = 720;
814             pGD->plnSizeY = 576;
815             sprintf (pGD->modeIdent, "TV Mode CCIR with %s", gdfModes[pGD->gdfIndex]);
816             break;
817     case TV_MODE_EIA:
818             pGD->winSizeX = 720;
819             pGD->winSizeY = 484;
820             pGD->plnSizeX = 720;
821             pGD->plnSizeY = 484;
822             sprintf (pGD->modeIdent, "TV Mode EIA with %s", gdfModes[pGD->gdfIndex]);
823             break;
824     case SINGLE_1280_1024:
825             pGD->winSizeX = 1280;
826             pGD->winSizeY = 1024;
827             pGD->plnSizeX = 1280;
828             pGD->plnSizeY = 1024;
829             sprintf (pGD->modeIdent, "Single Screen 1280x1024 with %s", gdfModes[pGD->gdfIndex]);
830             break;
831     default:
832             printf("Videomode not supported !\n");
833             return (NULL);
834     }
835
836
837     pGD->isaBase = CFG_ISA_IO;
838     pGD->pciBase = pci_mem_base;
839     pGD->dprBase = (pci_mem_base + 0x400000 + 0x8000);
840     pGD->vprBase = (pci_mem_base + 0x400000 + 0xc000);
841     pGD->cprBase = (pci_mem_base + 0x400000 + 0xe000);
842     pGD->frameAdrs = pci_mem_base;
843     pGD->memSize = VIDEO_MEM_SIZE;
844
845     /* Turn off display */
846     smiWrite (0x3c4, 0x01, 0x20);
847
848     /* Unlock ext. crt regs */
849     out8 (SMI_LOCK_REG, 0x40);
850
851     /* Set Register base to isa 3dx for 3?x regs (color mode) */
852     out8 (SMI_MISC_REG, 0x2b);
853
854     /* Unlock crt regs 0-7 */
855     smiWrite (0x3d4, 0x11, 0x0e);
856
857     /* Sytem Control Register */
858     smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
859          SMI_SCR, sizeof(SMI_SCR));
860
861     /* extented CRT Register */
862     smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5,
863          SMI_EXT_CRT[pGD->mode], sizeof(SMI_EXT_CRT)/VIDEO_MODES);
864
865     /* Sequencer Register */
866     smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
867          SMI_SEQR, sizeof(SMI_SEQR));
868
869     /* Power Control Register */
870     smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
871          SMI_PCR[pGD->mode], sizeof(SMI_PCR)/VIDEO_MODES);
872
873     /* Memory Control Register */
874     smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
875          SMI_MCR[pGD->mode], sizeof(SMI_MCR)/VIDEO_MODES);
876
877     /* Clock Control Register */
878     smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
879          SMI_CCR[pGD->mode], sizeof(SMI_CCR)/VIDEO_MODES);
880
881     /* Shadow VGA Register */
882     smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5,
883          SMI_SHVGA[pGD->mode], sizeof(SMI_SHVGA)/VIDEO_MODES);
884
885     /* General Purpose Register */
886     smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
887          SMI_GPR[pGD->mode], sizeof(SMI_GPR)/VIDEO_MODES);
888
889     /* Hardware Cusor Register */
890     smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
891          SMI_HCR[pGD->mode], sizeof(SMI_HCR)/VIDEO_MODES);
892
893     /* Flat Panel Register */
894     smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5,
895          SMI_FPR[pGD->mode], sizeof(SMI_FPR)/VIDEO_MODES);
896
897     /* CRTC Register */
898     smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5,
899          SMI_CRTCR[pGD->mode], sizeof(SMI_CRTCR)/VIDEO_MODES);
900
901     /* Graphics Controller Register */
902     smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF,
903          SMI_GCR, sizeof(SMI_GCR));
904
905     /* Patch memory and refresh settings for SMI710 */
906     if (device_id == PCI_DEVICE_ID_SMI_710)
907     {
908     unsigned char reg = smiRead (0x3c4, 0x62);
909
910     /* external memory disabled */
911     smiWrite (0x3c4, 0x62, (reg & 0xfb));
912     /* memory clock */
913     smiWrite (0x3c4, 0x6a, 0x75);
914     }
915
916     /* Patch memory and refresh settings for SMI712 */
917     if (device_id == PCI_DEVICE_ID_SMI_712)
918     {
919     unsigned char reg = smiRead (0x3c4, 0x62);
920
921     /* IL runs at MCLK; 64bit bus; external memory disabled */
922     smiWrite (0x3c4, 0x62, (reg | 0xc4));
923     /* memory clock */
924     smiWrite (0x3c4, 0x6a, 0x80);
925     }
926
927     /* Patch clock settings for SMI810 */
928     if (device_id == PCI_DEVICE_ID_SMI_810)
929     {
930     /* clock control */
931     smiWrite (0x3c4, 0x69, 0x03);
932     }
933
934     /* Video processor default setup */
935     smiInitVideoProcessor ();
936
937     /* Capture port default setup */
938     smiInitCapturePort ();
939
940     /* Drawing engine default setup */
941     smiInitDrawingEngine ();
942
943     /* Turn on display */
944     smiWrite (0x3c4, 0x01, 0x01);
945
946     /* Clear video memory */
947     i = pGD->memSize/4;
948     vm = (unsigned int *)pGD->pciBase;
949     while(i--)
950     *vm++ = 0;
951
952     printf("mode=%x - %s\n", videomode, pGD->modeIdent);
953     return ((void*)&smi);
954 }
955
956 /*******************************************************************************
957 *
958 * Drawing engine fill on screen region
959 */
960 void video_hw_rectfill (
961     unsigned int bpp,             /* bytes per pixel */
962     unsigned int dst_x,           /* dest pos x */
963     unsigned int dst_y,           /* dest pos y */
964     unsigned int dim_x,           /* frame width */
965     unsigned int dim_y,           /* frame height */
966     unsigned int color            /* fill color */
967      )
968 {
969     register GraphicDevice *pGD = (GraphicDevice *)&smi;
970     register unsigned int control;
971
972     dim_x *= bpp;
973
974     out32r ((pGD->dprBase + 0x0014), color);
975     out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
976     out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
977
978     control = 0x0000ffff &  in32r ((pGD->dprBase + 0x000c));
979
980     control |= 0x80010000;
981
982     out32r ((pGD->dprBase + 0x000c),  control);
983
984     /* Wait for drawing processor */
985     do
986     {
987     out8 ((pGD->isaBase + 0x3c4), 0x16);
988     } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
989 }
990
991 /*******************************************************************************
992 *
993 * Drawing engine bitblt with screen region
994 */
995 void video_hw_bitblt (
996     unsigned int bpp,             /* bytes per pixel */
997     unsigned int src_x,           /* source pos x */
998     unsigned int src_y,           /* source pos y */
999     unsigned int dst_x,           /* dest pos x */
1000     unsigned int dst_y,           /* dest pos y */
1001     unsigned int dim_x,           /* frame width */
1002     unsigned int dim_y            /* frame height */
1003     )
1004 {
1005     register GraphicDevice *pGD = (GraphicDevice *)&smi;
1006     register unsigned int control;
1007
1008     dim_x *= bpp;
1009
1010     if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x)))
1011     {
1012     out32r ((pGD->dprBase + 0x0000), (((src_x+dim_x-1)<<16) | (src_y+dim_y-1)));
1013     out32r ((pGD->dprBase + 0x0004), (((dst_x+dim_x-1)<<16) | (dst_y+dim_y-1)));
1014     control = 0x88000000;
1015     }
1016     else
1017     {
1018     out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y));
1019     out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
1020     control = 0x80000000;
1021     }
1022
1023     out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
1024     control |= (0x0000ffff &  in32r ((pGD->dprBase + 0x000c)));
1025     out32r ((pGD->dprBase + 0x000c), control);
1026
1027     /* Wait for drawing processor */
1028     do
1029     {
1030     out8 ((pGD->isaBase + 0x3c4), 0x16);
1031     } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
1032 }
1033
1034 /*******************************************************************************
1035 *
1036 * Set a RGB color in the LUT (8 bit index)
1037 */
1038 void video_set_lut (
1039     unsigned int index,           /* color number */
1040     unsigned char r,              /* red */
1041     unsigned char g,              /* green */
1042     unsigned char b               /* blue */
1043     )
1044 {
1045     register GraphicDevice *pGD = (GraphicDevice *)&smi;
1046
1047     out8 (SMI_LUT_MASK,  0xff);
1048
1049     out8 (SMI_LUT_START, (char)index);
1050
1051     out8 (SMI_LUT_RGB, r>>2);    /* red */
1052     udelay (10);
1053     out8 (SMI_LUT_RGB, g>>2);    /* green */
1054     udelay (10);
1055     out8 (SMI_LUT_RGB, b>>2);    /* blue */
1056     udelay (10);
1057 }
1058
1059 #endif /* CONFIG_VIDEO_SMI_LYNXEM */