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