staging: sm7xxfb: fix camelcase
[linux-2.6-block.git] / drivers / staging / sm7xxfb / sm7xxfb.c
1 /*
2  * Silicon Motion SM7XX frame buffer device
3  *
4  * Copyright (C) 2006 Silicon Motion Technology Corp.
5  * Authors:  Ge Wang, gewang@siliconmotion.com
6  *           Boyod boyod.yang@siliconmotion.com.cn
7  *
8  * Copyright (C) 2009 Lemote, Inc.
9  * Author:   Wu Zhangjin, wuzhangjin@gmail.com
10  *
11  * Copyright (C) 2011 Igalia, S.L.
12  * Author:   Javier M. Mellid <jmunhoz@igalia.com>
13  *
14  * This file is subject to the terms and conditions of the GNU General Public
15  * License. See the file COPYING in the main directory of this archive for
16  * more details.
17  *
18  * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips
19  */
20
21 #include <linux/io.h>
22 #include <linux/fb.h>
23 #include <linux/pci.h>
24 #include <linux/init.h>
25 #include <linux/slab.h>
26 #include <linux/uaccess.h>
27 #include <linux/module.h>
28 #include <linux/console.h>
29 #include <linux/screen_info.h>
30
31 #ifdef CONFIG_PM
32 #include <linux/pm.h>
33 #endif
34
35 #include "sm7xx.h"
36
37 /*
38 * Private structure
39 */
40 struct smtcfb_info {
41         struct pci_dev *pdev;
42         struct fb_info *fb;
43         u16 chip_id;
44         u8  chip_rev_id;
45
46         void __iomem *lfb;      /* linear frame buffer */
47         void __iomem *dp_regs;  /* drawing processor control regs */
48         void __iomem *vp_regs;  /* video processor control regs */
49         void __iomem *cp_regs;  /* capture processor control regs */
50         void __iomem *mmio;     /* memory map IO port */
51
52         u_int width;
53         u_int height;
54         u_int hz;
55
56         u32 colreg[17];
57 };
58
59 void __iomem *smtc_regbaseaddress;      /* Memory Map IO starting address */
60
61 static struct fb_var_screeninfo smtcfb_var = {
62         .xres           = 1024,
63         .yres           = 600,
64         .xres_virtual   = 1024,
65         .yres_virtual   = 600,
66         .bits_per_pixel = 16,
67         .red            = {16, 8, 0},
68         .green          = {8, 8, 0},
69         .blue           = {0, 8, 0},
70         .activate       = FB_ACTIVATE_NOW,
71         .height         = -1,
72         .width          = -1,
73         .vmode          = FB_VMODE_NONINTERLACED,
74         .nonstd         = 0,
75         .accel_flags    = FB_ACCELF_TEXT,
76 };
77
78 static struct fb_fix_screeninfo smtcfb_fix = {
79         .id             = "smXXXfb",
80         .type           = FB_TYPE_PACKED_PIXELS,
81         .visual         = FB_VISUAL_TRUECOLOR,
82         .line_length    = 800 * 3,
83         .accel          = FB_ACCEL_SMI_LYNX,
84         .type_aux       = 0,
85         .xpanstep       = 0,
86         .ypanstep       = 0,
87         .ywrapstep      = 0,
88 };
89
90 struct vesa_mode {
91         char index[6];
92         u16  lfb_width;
93         u16  lfb_height;
94         u16  lfb_depth;
95 };
96
97 static const struct vesa_mode vesa_mode_table[] = {
98         {"0x301", 640,  480,  8},
99         {"0x303", 800,  600,  8},
100         {"0x305", 1024, 768,  8},
101         {"0x307", 1280, 1024, 8},
102
103         {"0x311", 640,  480,  16},
104         {"0x314", 800,  600,  16},
105         {"0x317", 1024, 768,  16},
106         {"0x31A", 1280, 1024, 16},
107
108         {"0x312", 640,  480,  24},
109         {"0x315", 800,  600,  24},
110         {"0x318", 1024, 768,  24},
111         {"0x31B", 1280, 1024, 24},
112 };
113
114 /**********************************************************************
115                          SM712 Mode table.
116  **********************************************************************/
117 static const struct modeinit vgamode[] = {
118         {
119                 /*  mode#0: 640 x 480  16Bpp  60Hz */
120                 640, 480, 16, 60,
121                 /*  Init_MISC */
122                 0xE3,
123                 {       /*  Init_SR0_SR4 */
124                         0x03, 0x01, 0x0F, 0x00, 0x0E,
125                 },
126                 {       /*  Init_SR10_SR24 */
127                         0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
128                         0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129                         0xC4, 0x30, 0x02, 0x01, 0x01,
130                 },
131                 {       /*  Init_SR30_SR75 */
132                         0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
133                         0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
134                         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
135                         0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
136                         0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
137                         0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
138                         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
139                         0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
140                         0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
141                 },
142                 {       /*  Init_SR80_SR93 */
143                         0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
144                         0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
145                         0x00, 0x00, 0x00, 0x00,
146                 },
147                 {       /*  Init_SRA0_SRAF */
148                         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
149                         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
150                 },
151                 {       /*  Init_GR00_GR08 */
152                         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
153                         0xFF,
154                 },
155                 {       /*  Init_AR00_AR14 */
156                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
157                         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
158                         0x41, 0x00, 0x0F, 0x00, 0x00,
159                 },
160                 {       /*  Init_CR00_CR18 */
161                         0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
162                         0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163                         0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
164                         0xFF,
165                 },
166                 {       /*  Init_CR30_CR4D */
167                         0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
168                         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
169                         0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
170                         0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
171                 },
172                 {       /*  Init_CR90_CRA7 */
173                         0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
174                         0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
175                         0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
176                 },
177         },
178         {
179                 /*  mode#1: 640 x 480  24Bpp  60Hz */
180                 640, 480, 24, 60,
181                 /*  Init_MISC */
182                 0xE3,
183                 {       /*  Init_SR0_SR4 */
184                         0x03, 0x01, 0x0F, 0x00, 0x0E,
185                 },
186                 {       /*  Init_SR10_SR24 */
187                         0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
188                         0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189                         0xC4, 0x30, 0x02, 0x01, 0x01,
190                 },
191                 {       /*  Init_SR30_SR75 */
192                         0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
193                         0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
194                         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
195                         0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
196                         0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
197                         0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
198                         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
199                         0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
200                         0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
201                 },
202                 {       /*  Init_SR80_SR93 */
203                         0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
204                         0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
205                         0x00, 0x00, 0x00, 0x00,
206                 },
207                 {       /*  Init_SRA0_SRAF */
208                         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
209                         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
210                 },
211                 {       /*  Init_GR00_GR08 */
212                         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
213                         0xFF,
214                 },
215                 {       /*  Init_AR00_AR14 */
216                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
217                         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
218                         0x41, 0x00, 0x0F, 0x00, 0x00,
219                 },
220                 {       /*  Init_CR00_CR18 */
221                         0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
222                         0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223                         0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
224                         0xFF,
225                 },
226                 {       /*  Init_CR30_CR4D */
227                         0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
228                         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
229                         0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
230                         0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
231                 },
232                 {       /*  Init_CR90_CRA7 */
233                         0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
234                         0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
235                         0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
236                 },
237         },
238         {
239                 /*  mode#0: 640 x 480  32Bpp  60Hz */
240                 640, 480, 32, 60,
241                 /*  Init_MISC */
242                 0xE3,
243                 {       /*  Init_SR0_SR4 */
244                         0x03, 0x01, 0x0F, 0x00, 0x0E,
245                 },
246                 {       /*  Init_SR10_SR24 */
247                         0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
248                         0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249                         0xC4, 0x30, 0x02, 0x01, 0x01,
250                 },
251                 {       /*  Init_SR30_SR75 */
252                         0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
253                         0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
254                         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
255                         0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
256                         0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
257                         0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
258                         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
259                         0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
260                         0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
261                 },
262                 {       /*  Init_SR80_SR93 */
263                         0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
264                         0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
265                         0x00, 0x00, 0x00, 0x00,
266                 },
267                 {       /*  Init_SRA0_SRAF */
268                         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
269                         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
270                 },
271                 {       /*  Init_GR00_GR08 */
272                         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
273                         0xFF,
274                 },
275                 {       /*  Init_AR00_AR14 */
276                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
277                         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
278                         0x41, 0x00, 0x0F, 0x00, 0x00,
279                 },
280                 {       /*  Init_CR00_CR18 */
281                         0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
282                         0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283                         0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
284                         0xFF,
285                 },
286                 {       /*  Init_CR30_CR4D */
287                         0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
288                         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
289                         0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
290                         0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
291                 },
292                 {       /*  Init_CR90_CRA7 */
293                         0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
294                         0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
295                         0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
296                 },
297         },
298
299         {       /*  mode#2: 800 x 600  16Bpp  60Hz */
300                 800, 600, 16, 60,
301                 /*  Init_MISC */
302                 0x2B,
303                 {       /*  Init_SR0_SR4 */
304                         0x03, 0x01, 0x0F, 0x03, 0x0E,
305                 },
306                 {       /*  Init_SR10_SR24 */
307                         0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
308                         0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
309                         0xC4, 0x30, 0x02, 0x01, 0x01,
310                 },
311                 {       /*  Init_SR30_SR75 */
312                         0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
313                         0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
314                         0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
315                         0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
316                         0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
317                         0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
318                         0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
319                         0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
320                         0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
321                 },
322                 {       /*  Init_SR80_SR93 */
323                         0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
324                         0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
325                         0x00, 0x00, 0x00, 0x00,
326                 },
327                 {       /*  Init_SRA0_SRAF */
328                         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
329                         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
330                 },
331                 {       /*  Init_GR00_GR08 */
332                         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
333                         0xFF,
334                 },
335                 {       /*  Init_AR00_AR14 */
336                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
337                         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
338                         0x41, 0x00, 0x0F, 0x00, 0x00,
339                 },
340                 {       /*  Init_CR00_CR18 */
341                         0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
342                         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
343                         0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
344                         0xFF,
345                 },
346                 {       /*  Init_CR30_CR4D */
347                         0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
348                         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
349                         0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
350                         0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
351                 },
352                 {       /*  Init_CR90_CRA7 */
353                         0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
354                         0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
355                         0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
356                 },
357         },
358         {       /*  mode#3: 800 x 600  24Bpp  60Hz */
359                 800, 600, 24, 60,
360                 0x2B,
361                 {       /*  Init_SR0_SR4 */
362                         0x03, 0x01, 0x0F, 0x03, 0x0E,
363                 },
364                 {       /*  Init_SR10_SR24 */
365                         0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
366                         0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367                         0xC4, 0x30, 0x02, 0x01, 0x01,
368                 },
369                 {       /*  Init_SR30_SR75 */
370                         0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
371                         0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
372                         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
373                         0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
374                         0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
375                         0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
376                         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
377                         0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
378                         0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
379                 },
380                 {       /*  Init_SR80_SR93 */
381                         0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
382                         0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
383                         0x00, 0x00, 0x00, 0x00,
384                 },
385                 {       /*  Init_SRA0_SRAF */
386                         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
387                         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
388                 },
389                 {       /*  Init_GR00_GR08 */
390                         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
391                         0xFF,
392                 },
393                 {       /*  Init_AR00_AR14 */
394                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
395                         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
396                         0x41, 0x00, 0x0F, 0x00, 0x00,
397                 },
398                 {       /*  Init_CR00_CR18 */
399                         0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
400                         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401                         0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
402                         0xFF,
403                 },
404                 {       /*  Init_CR30_CR4D */
405                         0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
406                         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
407                         0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
408                         0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
409                 },
410                 {       /*  Init_CR90_CRA7 */
411                         0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
412                         0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
413                         0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
414                 },
415         },
416         {       /*  mode#7: 800 x 600  32Bpp  60Hz */
417                 800, 600, 32, 60,
418                 /*  Init_MISC */
419                 0x2B,
420                 {       /*  Init_SR0_SR4 */
421                         0x03, 0x01, 0x0F, 0x03, 0x0E,
422                 },
423                 {       /*  Init_SR10_SR24 */
424                         0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
425                         0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
426                         0xC4, 0x30, 0x02, 0x01, 0x01,
427                 },
428                 {       /*  Init_SR30_SR75 */
429                         0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
430                         0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
431                         0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
432                         0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
433                         0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
434                         0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
435                         0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
436                         0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
437                         0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
438                 },
439                 {       /*  Init_SR80_SR93 */
440                         0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
441                         0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
442                         0x00, 0x00, 0x00, 0x00,
443                 },
444                 {       /*  Init_SRA0_SRAF */
445                         0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
446                         0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
447                 },
448                 {       /*  Init_GR00_GR08 */
449                         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
450                         0xFF,
451                 },
452                 {       /*  Init_AR00_AR14 */
453                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
454                         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
455                         0x41, 0x00, 0x0F, 0x00, 0x00,
456                 },
457                 {       /*  Init_CR00_CR18 */
458                         0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
459                         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460                         0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
461                         0xFF,
462                 },
463                 {       /*  Init_CR30_CR4D */
464                         0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
465                         0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
466                         0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
467                         0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
468                 },
469                 {       /*  Init_CR90_CRA7 */
470                         0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
471                         0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
472                         0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
473                 },
474         },
475         /* We use 1024x768 table to light 1024x600 panel for lemote */
476         {       /*  mode#4: 1024 x 600  16Bpp  60Hz  */
477                 1024, 600, 16, 60,
478                 /*  Init_MISC */
479                 0xEB,
480                 {       /*  Init_SR0_SR4 */
481                         0x03, 0x01, 0x0F, 0x00, 0x0E,
482                 },
483                 {       /*  Init_SR10_SR24 */
484                         0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20,
485                         0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
486                         0xC4, 0x30, 0x02, 0x00, 0x01,
487                 },
488                 {       /*  Init_SR30_SR75 */
489                         0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22,
490                         0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF,
491                         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
492                         0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22,
493                         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
494                         0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22,
495                         0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
496                         0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02,
497                         0x04, 0x45, 0x3F, 0x30, 0x40, 0x20,
498                 },
499                 {       /*  Init_SR80_SR93 */
500                         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
501                         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
502                         0x00, 0x00, 0x00, 0x00,
503                 },
504                 {       /*  Init_SRA0_SRAF */
505                         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
506                         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
507                 },
508                 {       /*  Init_GR00_GR08 */
509                         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
510                         0xFF,
511                 },
512                 {       /*  Init_AR00_AR14 */
513                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
514                         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
515                         0x41, 0x00, 0x0F, 0x00, 0x00,
516                 },
517                 {       /*  Init_CR00_CR18 */
518                         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
519                         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520                         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
521                         0xFF,
522                 },
523                 {       /*  Init_CR30_CR4D */
524                         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
525                         0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
526                         0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00,
527                         0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57,
528                 },
529                 {       /*  Init_CR90_CRA7 */
530                         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
531                         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
532                         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
533                 },
534         },
535         {       /*  mode#5: 1024 x 768  24Bpp  60Hz */
536                 1024, 768, 24, 60,
537                 /*  Init_MISC */
538                 0xEB,
539                 {       /*  Init_SR0_SR4 */
540                         0x03, 0x01, 0x0F, 0x03, 0x0E,
541                 },
542                 {       /*  Init_SR10_SR24 */
543                         0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
544                         0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
545                         0xC4, 0x30, 0x02, 0x01, 0x01,
546                 },
547                 {       /*  Init_SR30_SR75 */
548                         0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
549                         0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
550                         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
551                         0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
552                         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
553                         0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
554                         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
555                         0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
556                         0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
557                 },
558                 {       /*  Init_SR80_SR93 */
559                         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
560                         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
561                         0x00, 0x00, 0x00, 0x00,
562                 },
563                 {       /*  Init_SRA0_SRAF */
564                         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
565                         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
566                 },
567                 {       /*  Init_GR00_GR08 */
568                         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
569                         0xFF,
570                 },
571                 {       /*  Init_AR00_AR14 */
572                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
573                         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
574                         0x41, 0x00, 0x0F, 0x00, 0x00,
575                 },
576                 {       /*  Init_CR00_CR18 */
577                         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
578                         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579                         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
580                         0xFF,
581                 },
582                 {       /*  Init_CR30_CR4D */
583                         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
584                         0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
585                         0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
586                         0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
587                 },
588                 {       /*  Init_CR90_CRA7 */
589                         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
590                         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
591                         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
592                 },
593         },
594         {       /*  mode#4: 1024 x 768  32Bpp  60Hz */
595                 1024, 768, 32, 60,
596                 /*  Init_MISC */
597                 0xEB,
598                 {       /*  Init_SR0_SR4 */
599                         0x03, 0x01, 0x0F, 0x03, 0x0E,
600                 },
601                 {       /*  Init_SR10_SR24 */
602                         0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
603                         0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
604                         0xC4, 0x32, 0x02, 0x01, 0x01,
605                 },
606                 {       /*  Init_SR30_SR75 */
607                         0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
608                         0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
609                         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
610                         0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
611                         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
612                         0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
613                         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
614                         0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
615                         0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
616                 },
617                 {       /*  Init_SR80_SR93 */
618                         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
619                         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
620                         0x00, 0x00, 0x00, 0x00,
621                 },
622                 {       /*  Init_SRA0_SRAF */
623                         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
624                         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
625                 },
626                 {       /*  Init_GR00_GR08 */
627                         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
628                         0xFF,
629                 },
630                 {       /*  Init_AR00_AR14 */
631                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
632                         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
633                         0x41, 0x00, 0x0F, 0x00, 0x00,
634                 },
635                 {       /*  Init_CR00_CR18 */
636                         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
637                         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638                         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
639                         0xFF,
640                 },
641                 {       /*  Init_CR30_CR4D */
642                         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
643                         0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
644                         0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
645                         0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
646                 },
647                 {       /*  Init_CR90_CRA7 */
648                         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
649                         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
650                         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
651                 },
652         },
653         {       /*  mode#6: 320 x 240  16Bpp  60Hz */
654                 320, 240, 16, 60,
655                 /*  Init_MISC */
656                 0xEB,
657                 {       /*  Init_SR0_SR4 */
658                         0x03, 0x01, 0x0F, 0x03, 0x0E,
659                 },
660                 {       /*  Init_SR10_SR24 */
661                         0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
662                         0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
663                         0xC4, 0x32, 0x02, 0x01, 0x01,
664                 },
665                 {       /*  Init_SR30_SR75 */
666                         0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
667                         0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
668                         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
669                         0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
670                         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
671                         0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
672                         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
673                         0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
674                         0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
675                 },
676                 {       /*  Init_SR80_SR93 */
677                         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
678                         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
679                         0x00, 0x00, 0x00, 0x00,
680                 },
681                 {       /*  Init_SRA0_SRAF */
682                         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
683                         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
684                 },
685                 {       /*  Init_GR00_GR08 */
686                         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
687                         0xFF,
688                 },
689                 {       /*  Init_AR00_AR14 */
690                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
691                         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
692                         0x41, 0x00, 0x0F, 0x00, 0x00,
693                 },
694                 {       /*  Init_CR00_CR18 */
695                         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
696                         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
697                         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
698                         0xFF,
699                 },
700                 {       /*  Init_CR30_CR4D */
701                         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
702                         0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
703                         0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
704                         0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
705                 },
706                 {       /*  Init_CR90_CRA7 */
707                         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
708                         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
709                         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
710                 },
711         },
712
713         {       /*  mode#8: 320 x 240  32Bpp  60Hz */
714                 320, 240, 32, 60,
715                 /*  Init_MISC */
716                 0xEB,
717                 {       /*  Init_SR0_SR4 */
718                         0x03, 0x01, 0x0F, 0x03, 0x0E,
719                 },
720                 {       /*  Init_SR10_SR24 */
721                         0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
722                         0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
723                         0xC4, 0x32, 0x02, 0x01, 0x01,
724                 },
725                 {       /*  Init_SR30_SR75 */
726                         0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
727                         0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
728                         0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
729                         0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
730                         0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
731                         0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
732                         0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
733                         0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
734                         0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
735                 },
736                 {       /*  Init_SR80_SR93 */
737                         0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
738                         0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
739                         0x00, 0x00, 0x00, 0x00,
740                 },
741                 {       /*  Init_SRA0_SRAF */
742                         0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
743                         0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
744                 },
745                 {       /*  Init_GR00_GR08 */
746                         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
747                         0xFF,
748                 },
749                 {       /*  Init_AR00_AR14 */
750                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
751                         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
752                         0x41, 0x00, 0x0F, 0x00, 0x00,
753                 },
754                 {       /*  Init_CR00_CR18 */
755                         0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
756                         0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
757                         0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
758                         0xFF,
759                 },
760                 {       /*  Init_CR30_CR4D */
761                         0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
762                         0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
763                         0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
764                         0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
765                 },
766                 {       /*  Init_CR90_CRA7 */
767                         0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
768                         0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
769                         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
770                 },
771         },
772 };
773
774 static struct screen_info smtc_scr_info;
775
776 static char *mode_option;
777
778 /* process command line options, get vga parameter */
779 static void __init sm7xx_vga_setup(char *options)
780 {
781         int i;
782
783         if (!options || !*options)
784                 return;
785
786         smtc_scr_info.lfb_width = 0;
787         smtc_scr_info.lfb_height = 0;
788         smtc_scr_info.lfb_depth = 0;
789
790         pr_debug("sm7xx_vga_setup = %s\n", options);
791
792         for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) {
793                 if (strstr(options, vesa_mode_table[i].index)) {
794                         smtc_scr_info.lfb_width  = vesa_mode_table[i].lfb_width;
795                         smtc_scr_info.lfb_height =
796                                                 vesa_mode_table[i].lfb_height;
797                         smtc_scr_info.lfb_depth  = vesa_mode_table[i].lfb_depth;
798                         return;
799                 }
800         }
801 }
802
803 static void sm712_setpalette(int regno, unsigned red, unsigned green,
804                              unsigned blue, struct fb_info *info)
805 {
806         /* set bit 5:4 = 01 (write LCD RAM only) */
807         smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10);
808
809         smtc_mmiowb(regno, dac_reg);
810         smtc_mmiowb(red >> 10, dac_val);
811         smtc_mmiowb(green >> 10, dac_val);
812         smtc_mmiowb(blue >> 10, dac_val);
813 }
814
815 /* chan_to_field
816  *
817  * convert a colour value into a field position
818  *
819  * from pxafb.c
820  */
821
822 static inline unsigned int chan_to_field(unsigned int chan,
823                                          struct fb_bitfield *bf)
824 {
825         chan &= 0xffff;
826         chan >>= 16 - bf->length;
827         return chan << bf->offset;
828 }
829
830 static int smtc_blank(int blank_mode, struct fb_info *info)
831 {
832         /* clear DPMS setting */
833         switch (blank_mode) {
834         case FB_BLANK_UNBLANK:
835                 /* Screen On: HSync: On, VSync : On */
836                 smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
837                 smtc_seqw(0x6a, 0x16);
838                 smtc_seqw(0x6b, 0x02);
839                 smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
840                 smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
841                 smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
842                 smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
843                 smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
844                 break;
845         case FB_BLANK_NORMAL:
846                 /* Screen Off: HSync: On, VSync : On   Soft blank */
847                 smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
848                 smtc_seqw(0x6a, 0x16);
849                 smtc_seqw(0x6b, 0x02);
850                 smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
851                 smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
852                 smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
853                 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
854                 break;
855         case FB_BLANK_VSYNC_SUSPEND:
856                 /* Screen On: HSync: On, VSync : Off */
857                 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
858                 smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
859                 smtc_seqw(0x6a, 0x0c);
860                 smtc_seqw(0x6b, 0x02);
861                 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
862                 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
863                 smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
864                 smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
865                 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
866                 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
867                 break;
868         case FB_BLANK_HSYNC_SUSPEND:
869                 /* Screen On: HSync: Off, VSync : On */
870                 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
871                 smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
872                 smtc_seqw(0x6a, 0x0c);
873                 smtc_seqw(0x6b, 0x02);
874                 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
875                 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
876                 smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
877                 smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
878                 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
879                 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
880                 break;
881         case FB_BLANK_POWERDOWN:
882                 /* Screen On: HSync: Off, VSync : Off */
883                 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
884                 smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
885                 smtc_seqw(0x6a, 0x0c);
886                 smtc_seqw(0x6b, 0x02);
887                 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
888                 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
889                 smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
890                 smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
891                 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
892                 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
893                 break;
894         default:
895                 return -EINVAL;
896         }
897
898         return 0;
899 }
900
901 static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green,
902                           unsigned blue, unsigned trans, struct fb_info *info)
903 {
904         struct smtcfb_info *sfb;
905         u32 val;
906
907         sfb = info->par;
908
909         if (regno > 255)
910                 return 1;
911
912         switch (sfb->fb->fix.visual) {
913         case FB_VISUAL_DIRECTCOLOR:
914         case FB_VISUAL_TRUECOLOR:
915                 /*
916                  * 16/32 bit true-colour, use pseudo-palette for 16 base color
917                  */
918                 if (regno >= 16)
919                         break;
920                 if (sfb->fb->var.bits_per_pixel == 16) {
921                         u32 *pal = sfb->fb->pseudo_palette;
922
923                         val = chan_to_field(red, &sfb->fb->var.red);
924                         val |= chan_to_field(green, &sfb->fb->var.green);
925                         val |= chan_to_field(blue, &sfb->fb->var.blue);
926 #ifdef __BIG_ENDIAN
927                         pal[regno] = ((red & 0xf800) >> 8) |
928                                      ((green & 0xe000) >> 13) |
929                                      ((green & 0x1c00) << 3) |
930                                      ((blue & 0xf800) >> 3);
931 #else
932                         pal[regno] = val;
933 #endif
934                 } else {
935                         u32 *pal = sfb->fb->pseudo_palette;
936
937                         val = chan_to_field(red, &sfb->fb->var.red);
938                         val |= chan_to_field(green, &sfb->fb->var.green);
939                         val |= chan_to_field(blue, &sfb->fb->var.blue);
940 #ifdef __BIG_ENDIAN
941                         val = (val & 0xff00ff00 >> 8) |
942                               (val & 0x00ff00ff << 8);
943 #endif
944                         pal[regno] = val;
945                 }
946                 break;
947
948         case FB_VISUAL_PSEUDOCOLOR:
949                 /* color depth 8 bit */
950                 sm712_setpalette(regno, red, green, blue, info);
951                 break;
952
953         default:
954                 return 1;       /* unknown type */
955         }
956
957         return 0;
958 }
959
960 #ifdef __BIG_ENDIAN
961 static ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
962                            size_t count, loff_t *ppos)
963 {
964         unsigned long p = *ppos;
965
966         u32 *buffer, *dst;
967         u32 __iomem *src;
968         int c, i, cnt = 0, err = 0;
969         unsigned long total_size;
970
971         if (!info || !info->screen_base)
972                 return -ENODEV;
973
974         if (info->state != FBINFO_STATE_RUNNING)
975                 return -EPERM;
976
977         total_size = info->screen_size;
978
979         if (total_size == 0)
980                 total_size = info->fix.smem_len;
981
982         if (p >= total_size)
983                 return 0;
984
985         if (count >= total_size)
986                 count = total_size;
987
988         if (count + p > total_size)
989                 count = total_size - p;
990
991         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
992         if (!buffer)
993                 return -ENOMEM;
994
995         src = (u32 __iomem *)(info->screen_base + p);
996
997         if (info->fbops->fb_sync)
998                 info->fbops->fb_sync(info);
999
1000         while (count) {
1001                 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
1002                 dst = buffer;
1003                 for (i = c >> 2; i--;) {
1004                         *dst = fb_readl(src++);
1005                         *dst = (*dst & 0xff00ff00 >> 8) |
1006                                (*dst & 0x00ff00ff << 8);
1007                         dst++;
1008                 }
1009                 if (c & 3) {
1010                         u8 *dst8 = (u8 *)dst;
1011                         u8 __iomem *src8 = (u8 __iomem *)src;
1012
1013                         for (i = c & 3; i--;) {
1014                                 if (i & 1) {
1015                                         *dst8++ = fb_readb(++src8);
1016                                 } else {
1017                                         *dst8++ = fb_readb(--src8);
1018                                         src8 += 2;
1019                                 }
1020                         }
1021                         src = (u32 __iomem *)src8;
1022                 }
1023
1024                 if (copy_to_user(buf, buffer, c)) {
1025                         err = -EFAULT;
1026                         break;
1027                 }
1028                 *ppos += c;
1029                 buf += c;
1030                 cnt += c;
1031                 count -= c;
1032         }
1033
1034         kfree(buffer);
1035
1036         return (err) ? err : cnt;
1037 }
1038
1039 static ssize_t smtcfb_write(struct fb_info *info, const char __user *buf,
1040                             size_t count, loff_t *ppos)
1041 {
1042         unsigned long p = *ppos;
1043
1044         u32 *buffer, *src;
1045         u32 __iomem *dst;
1046         int c, i, cnt = 0, err = 0;
1047         unsigned long total_size;
1048
1049         if (!info || !info->screen_base)
1050                 return -ENODEV;
1051
1052         if (info->state != FBINFO_STATE_RUNNING)
1053                 return -EPERM;
1054
1055         total_size = info->screen_size;
1056
1057         if (total_size == 0)
1058                 total_size = info->fix.smem_len;
1059
1060         if (p > total_size)
1061                 return -EFBIG;
1062
1063         if (count > total_size) {
1064                 err = -EFBIG;
1065                 count = total_size;
1066         }
1067
1068         if (count + p > total_size) {
1069                 if (!err)
1070                         err = -ENOSPC;
1071
1072                 count = total_size - p;
1073         }
1074
1075         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
1076         if (!buffer)
1077                 return -ENOMEM;
1078
1079         dst = (u32 __iomem *)(info->screen_base + p);
1080
1081         if (info->fbops->fb_sync)
1082                 info->fbops->fb_sync(info);
1083
1084         while (count) {
1085                 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
1086                 src = buffer;
1087
1088                 if (copy_from_user(src, buf, c)) {
1089                         err = -EFAULT;
1090                         break;
1091                 }
1092
1093                 for (i = c >> 2; i--;) {
1094                         fb_writel((*src & 0xff00ff00 >> 8) |
1095                                   (*src & 0x00ff00ff << 8), dst++);
1096                         src++;
1097                 }
1098                 if (c & 3) {
1099                         u8 *src8 = (u8 *)src;
1100                         u8 __iomem *dst8 = (u8 __iomem *)dst;
1101
1102                         for (i = c & 3; i--;) {
1103                                 if (i & 1) {
1104                                         fb_writeb(*src8++, ++dst8);
1105                                 } else {
1106                                         fb_writeb(*src8++, --dst8);
1107                                         dst8 += 2;
1108                                 }
1109                         }
1110                         dst = (u32 __iomem *)dst8;
1111                 }
1112
1113                 *ppos += c;
1114                 buf += c;
1115                 cnt += c;
1116                 count -= c;
1117         }
1118
1119         kfree(buffer);
1120
1121         return (cnt) ? cnt : err;
1122 }
1123 #endif  /* ! __BIG_ENDIAN */
1124
1125 static void sm7xx_set_timing(struct smtcfb_info *sfb)
1126 {
1127         int i = 0, j = 0;
1128         u32 m_nscreenstride;
1129
1130         dev_dbg(&sfb->pdev->dev,
1131                 "sfb->width=%d sfb->height=%d sfb->fb->var.bits_per_pixel=%d sfb->hz=%d\n",
1132                 sfb->width, sfb->height, sfb->fb->var.bits_per_pixel, sfb->hz);
1133
1134         for (j = 0; j < ARRAY_SIZE(vgamode); j++) {
1135                 if (vgamode[j].mmsizex != sfb->width ||
1136                     vgamode[j].mmsizey != sfb->height ||
1137                     vgamode[j].bpp != sfb->fb->var.bits_per_pixel ||
1138                     vgamode[j].hz != sfb->hz)
1139                         continue;
1140
1141                 dev_dbg(&sfb->pdev->dev,
1142                         "vgamode[j].mmsizex=%d vgamode[j].mmSizeY=%d vgamode[j].bpp=%d vgamode[j].hz=%d\n",
1143                         vgamode[j].mmsizex, vgamode[j].mmsizey,
1144                         vgamode[j].bpp, vgamode[j].hz);
1145
1146                 dev_dbg(&sfb->pdev->dev, "vgamode index=%d\n", j);
1147
1148                 smtc_mmiowb(0x0, 0x3c6);
1149
1150                 smtc_seqw(0, 0x1);
1151
1152                 smtc_mmiowb(vgamode[j].init_misc, 0x3c2);
1153
1154                 /* init SEQ register SR00 - SR04 */
1155                 for (i = 0; i < SIZE_SR00_SR04; i++)
1156                         smtc_seqw(i, vgamode[j].init_sr00_sr04[i]);
1157
1158                 /* init SEQ register SR10 - SR24 */
1159                 for (i = 0; i < SIZE_SR10_SR24; i++)
1160                         smtc_seqw(i + 0x10, vgamode[j].init_sr10_sr24[i]);
1161
1162                 /* init SEQ register SR30 - SR75 */
1163                 for (i = 0; i < SIZE_SR30_SR75; i++)
1164                         if ((i + 0x30) != 0x62 && (i + 0x30) != 0x6a &&
1165                             (i + 0x30) != 0x6b)
1166                                 smtc_seqw(i + 0x30,
1167                                           vgamode[j].init_sr30_sr75[i]);
1168
1169                 /* init SEQ register SR80 - SR93 */
1170                 for (i = 0; i < SIZE_SR80_SR93; i++)
1171                         smtc_seqw(i + 0x80, vgamode[j].init_sr80_sr93[i]);
1172
1173                 /* init SEQ register SRA0 - SRAF */
1174                 for (i = 0; i < SIZE_SRA0_SRAF; i++)
1175                         smtc_seqw(i + 0xa0, vgamode[j].init_sra0_sraf[i]);
1176
1177                 /* init Graphic register GR00 - GR08 */
1178                 for (i = 0; i < SIZE_GR00_GR08; i++)
1179                         smtc_grphw(i, vgamode[j].init_gr00_gr08[i]);
1180
1181                 /* init Attribute register AR00 - AR14 */
1182                 for (i = 0; i < SIZE_AR00_AR14; i++)
1183                         smtc_attrw(i, vgamode[j].init_ar00_ar14[i]);
1184
1185                 /* init CRTC register CR00 - CR18 */
1186                 for (i = 0; i < SIZE_CR00_CR18; i++)
1187                         smtc_crtcw(i, vgamode[j].init_cr00_cr18[i]);
1188
1189                 /* init CRTC register CR30 - CR4D */
1190                 for (i = 0; i < SIZE_CR30_CR4D; i++)
1191                         smtc_crtcw(i + 0x30, vgamode[j].init_cr30_cr4d[i]);
1192
1193                 /* init CRTC register CR90 - CRA7 */
1194                 for (i = 0; i < SIZE_CR90_CRA7; i++)
1195                         smtc_crtcw(i + 0x90, vgamode[j].init_cr90_cra7[i]);
1196         }
1197         smtc_mmiowb(0x67, 0x3c2);
1198
1199         /* set VPR registers */
1200         writel(0x0, sfb->vp_regs + 0x0C);
1201         writel(0x0, sfb->vp_regs + 0x40);
1202
1203         /* set data width */
1204         m_nscreenstride = (sfb->width * sfb->fb->var.bits_per_pixel) / 64;
1205         switch (sfb->fb->var.bits_per_pixel) {
1206         case 8:
1207                 writel(0x0, sfb->vp_regs + 0x0);
1208                 break;
1209         case 16:
1210                 writel(0x00020000, sfb->vp_regs + 0x0);
1211                 break;
1212         case 24:
1213                 writel(0x00040000, sfb->vp_regs + 0x0);
1214                 break;
1215         case 32:
1216                 writel(0x00030000, sfb->vp_regs + 0x0);
1217                 break;
1218         }
1219         writel((u32)(((m_nscreenstride + 2) << 16) | m_nscreenstride),
1220                sfb->vp_regs + 0x10);
1221 }
1222
1223 static void smtc_set_timing(struct smtcfb_info *sfb)
1224 {
1225         switch (sfb->chip_id) {
1226         case 0x710:
1227         case 0x712:
1228         case 0x720:
1229                 sm7xx_set_timing(sfb);
1230                 break;
1231         }
1232 }
1233
1234 static void smtcfb_setmode(struct smtcfb_info *sfb)
1235 {
1236         switch (sfb->fb->var.bits_per_pixel) {
1237         case 32:
1238                 sfb->fb->fix.visual       = FB_VISUAL_TRUECOLOR;
1239                 sfb->fb->fix.line_length  = sfb->fb->var.xres * 4;
1240                 sfb->fb->var.red.length   = 8;
1241                 sfb->fb->var.green.length = 8;
1242                 sfb->fb->var.blue.length  = 8;
1243                 sfb->fb->var.red.offset   = 16;
1244                 sfb->fb->var.green.offset = 8;
1245                 sfb->fb->var.blue.offset  = 0;
1246                 break;
1247         case 24:
1248                 sfb->fb->fix.visual       = FB_VISUAL_TRUECOLOR;
1249                 sfb->fb->fix.line_length  = sfb->fb->var.xres * 3;
1250                 sfb->fb->var.red.length   = 8;
1251                 sfb->fb->var.green.length = 8;
1252                 sfb->fb->var.blue.length  = 8;
1253                 sfb->fb->var.red.offset   = 16;
1254                 sfb->fb->var.green.offset = 8;
1255                 sfb->fb->var.blue.offset  = 0;
1256                 break;
1257         case 8:
1258                 sfb->fb->fix.visual       = FB_VISUAL_PSEUDOCOLOR;
1259                 sfb->fb->fix.line_length  = sfb->fb->var.xres;
1260                 sfb->fb->var.red.length   = 3;
1261                 sfb->fb->var.green.length = 3;
1262                 sfb->fb->var.blue.length  = 2;
1263                 sfb->fb->var.red.offset   = 5;
1264                 sfb->fb->var.green.offset = 2;
1265                 sfb->fb->var.blue.offset  = 0;
1266                 break;
1267         case 16:
1268         default:
1269                 sfb->fb->fix.visual       = FB_VISUAL_TRUECOLOR;
1270                 sfb->fb->fix.line_length  = sfb->fb->var.xres * 2;
1271                 sfb->fb->var.red.length   = 5;
1272                 sfb->fb->var.green.length = 6;
1273                 sfb->fb->var.blue.length  = 5;
1274                 sfb->fb->var.red.offset   = 11;
1275                 sfb->fb->var.green.offset = 5;
1276                 sfb->fb->var.blue.offset  = 0;
1277                 break;
1278         }
1279
1280         sfb->width  = sfb->fb->var.xres;
1281         sfb->height = sfb->fb->var.yres;
1282         sfb->hz = 60;
1283         smtc_set_timing(sfb);
1284 }
1285
1286 static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1287 {
1288         /* sanity checks */
1289         if (var->xres_virtual < var->xres)
1290                 var->xres_virtual = var->xres;
1291
1292         if (var->yres_virtual < var->yres)
1293                 var->yres_virtual = var->yres;
1294
1295         /* set valid default bpp */
1296         if ((var->bits_per_pixel != 8)  && (var->bits_per_pixel != 16) &&
1297             (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32))
1298                 var->bits_per_pixel = 16;
1299
1300         return 0;
1301 }
1302
1303 static int smtc_set_par(struct fb_info *info)
1304 {
1305         smtcfb_setmode(info->par);
1306
1307         return 0;
1308 }
1309
1310 static struct fb_ops smtcfb_ops = {
1311         .owner        = THIS_MODULE,
1312         .fb_check_var = smtc_check_var,
1313         .fb_set_par   = smtc_set_par,
1314         .fb_setcolreg = smtc_setcolreg,
1315         .fb_blank     = smtc_blank,
1316         .fb_fillrect  = cfb_fillrect,
1317         .fb_imageblit = cfb_imageblit,
1318         .fb_copyarea  = cfb_copyarea,
1319 #ifdef __BIG_ENDIAN
1320         .fb_read      = smtcfb_read,
1321         .fb_write     = smtcfb_write,
1322 #endif
1323 };
1324
1325 /*
1326  * Unmap in the memory mapped IO registers
1327  */
1328
1329 static void smtc_unmap_mmio(struct smtcfb_info *sfb)
1330 {
1331         if (sfb && smtc_regbaseaddress)
1332                 smtc_regbaseaddress = NULL;
1333 }
1334
1335 /*
1336  * Map in the screen memory
1337  */
1338
1339 static int smtc_map_smem(struct smtcfb_info *sfb,
1340                          struct pci_dev *pdev, u_long smem_len)
1341 {
1342         sfb->fb->fix.smem_start = pci_resource_start(pdev, 0);
1343
1344 #ifdef __BIG_ENDIAN
1345         if (sfb->fb->var.bits_per_pixel == 32)
1346                 sfb->fb->fix.smem_start += 0x800000;
1347 #endif
1348
1349         sfb->fb->fix.smem_len = smem_len;
1350
1351         sfb->fb->screen_base = sfb->lfb;
1352
1353         if (!sfb->fb->screen_base) {
1354                 dev_err(&pdev->dev,
1355                         "%s: unable to map screen memory\n", sfb->fb->fix.id);
1356                 return -ENOMEM;
1357         }
1358
1359         return 0;
1360 }
1361
1362 /*
1363  * Unmap in the screen memory
1364  *
1365  */
1366 static void smtc_unmap_smem(struct smtcfb_info *sfb)
1367 {
1368         if (sfb && sfb->fb->screen_base) {
1369                 iounmap(sfb->fb->screen_base);
1370                 sfb->fb->screen_base = NULL;
1371         }
1372 }
1373
1374 /*
1375  * We need to wake up the device and make sure its in linear memory mode.
1376  */
1377 static inline void sm7xx_init_hw(void)
1378 {
1379         outb_p(0x18, 0x3c4);
1380         outb_p(0x11, 0x3c5);
1381 }
1382
1383 static int smtcfb_pci_probe(struct pci_dev *pdev,
1384                             const struct pci_device_id *ent)
1385 {
1386         struct smtcfb_info *sfb;
1387         struct fb_info *info;
1388         u_long smem_size = 0x00800000;  /* default 8MB */
1389         int err;
1390         unsigned long mmio_base;
1391
1392         dev_info(&pdev->dev, "Silicon Motion display driver.\n");
1393
1394         err = pci_enable_device(pdev);  /* enable SMTC chip */
1395         if (err)
1396                 return err;
1397
1398         err = pci_request_region(pdev, 0, "sm7xxfb");
1399         if (err < 0) {
1400                 dev_err(&pdev->dev, "cannot reserve framebuffer region\n");
1401                 goto failed_regions;
1402         }
1403
1404         sprintf(smtcfb_fix.id, "sm%Xfb", ent->device);
1405
1406         info = framebuffer_alloc(sizeof(*sfb), &pdev->dev);
1407         if (!info) {
1408                 dev_err(&pdev->dev, "framebuffer_alloc failed\n");
1409                 err = -ENOMEM;
1410                 goto failed_free;
1411         }
1412
1413         sfb = info->par;
1414         sfb->fb = info;
1415         sfb->chip_id = ent->device;
1416         sfb->pdev = pdev;
1417         info->flags = FBINFO_FLAG_DEFAULT;
1418         info->fbops = &smtcfb_ops;
1419         info->fix = smtcfb_fix;
1420         info->var = smtcfb_var;
1421         info->pseudo_palette = sfb->colreg;
1422         info->par = sfb;
1423
1424         pci_set_drvdata(pdev, sfb);
1425
1426         sm7xx_init_hw();
1427
1428         /* get mode parameter from smtc_scr_info */
1429         if (smtc_scr_info.lfb_width != 0) {
1430                 sfb->fb->var.xres = smtc_scr_info.lfb_width;
1431                 sfb->fb->var.yres = smtc_scr_info.lfb_height;
1432                 sfb->fb->var.bits_per_pixel = smtc_scr_info.lfb_depth;
1433         } else {
1434                 /* default resolution 1024x600 16bit mode */
1435                 sfb->fb->var.xres = SCREEN_X_RES;
1436                 sfb->fb->var.yres = SCREEN_Y_RES;
1437                 sfb->fb->var.bits_per_pixel = SCREEN_BPP;
1438         }
1439
1440 #ifdef __BIG_ENDIAN
1441         if (sfb->fb->var.bits_per_pixel == 24)
1442                 sfb->fb->var.bits_per_pixel = (smtc_scr_info.lfb_depth = 32);
1443 #endif
1444         /* Map address and memory detection */
1445         mmio_base = pci_resource_start(pdev, 0);
1446         pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
1447
1448         switch (sfb->chip_id) {
1449         case 0x710:
1450         case 0x712:
1451                 sfb->fb->fix.mmio_start = mmio_base + 0x00400000;
1452                 sfb->fb->fix.mmio_len = 0x00400000;
1453                 smem_size = SM712_VIDEOMEMORYSIZE;
1454 #ifdef __BIG_ENDIAN
1455                 sfb->lfb = ioremap(mmio_base, 0x00c00000);
1456 #else
1457                 sfb->lfb = ioremap(mmio_base, 0x00800000);
1458 #endif
1459                 sfb->mmio = (smtc_regbaseaddress =
1460                     sfb->lfb + 0x00700000);
1461                 sfb->dp_regs = sfb->lfb + 0x00408000;
1462                 sfb->vp_regs = sfb->lfb + 0x0040c000;
1463 #ifdef __BIG_ENDIAN
1464                 if (sfb->fb->var.bits_per_pixel == 32) {
1465                         sfb->lfb += 0x800000;
1466                         dev_info(&pdev->dev, "sfb->lfb=%p\n", sfb->lfb);
1467                 }
1468 #endif
1469                 if (!smtc_regbaseaddress) {
1470                         dev_err(&pdev->dev,
1471                                 "%s: unable to map memory mapped IO!\n",
1472                                 sfb->fb->fix.id);
1473                         err = -ENOMEM;
1474                         goto failed_fb;
1475                 }
1476
1477                 /* set MCLK = 14.31818 * (0x16 / 0x2) */
1478                 smtc_seqw(0x6a, 0x16);
1479                 smtc_seqw(0x6b, 0x02);
1480                 smtc_seqw(0x62, 0x3e);
1481                 /* enable PCI burst */
1482                 smtc_seqw(0x17, 0x20);
1483                 /* enable word swap */
1484 #ifdef __BIG_ENDIAN
1485                 if (sfb->fb->var.bits_per_pixel == 32)
1486                         smtc_seqw(0x17, 0x30);
1487 #endif
1488                 break;
1489         case 0x720:
1490                 sfb->fb->fix.mmio_start = mmio_base;
1491                 sfb->fb->fix.mmio_len = 0x00200000;
1492                 smem_size = SM722_VIDEOMEMORYSIZE;
1493                 sfb->dp_regs = ioremap(mmio_base, 0x00a00000);
1494                 sfb->lfb = sfb->dp_regs + 0x00200000;
1495                 sfb->mmio = (smtc_regbaseaddress =
1496                     sfb->dp_regs + 0x000c0000);
1497                 sfb->vp_regs = sfb->dp_regs + 0x800;
1498
1499                 smtc_seqw(0x62, 0xff);
1500                 smtc_seqw(0x6a, 0x0d);
1501                 smtc_seqw(0x6b, 0x02);
1502                 break;
1503         default:
1504                 dev_err(&pdev->dev,
1505                         "No valid Silicon Motion display chip was detected!\n");
1506
1507                 goto failed_fb;
1508         }
1509
1510         /* can support 32 bpp */
1511         if (15 == sfb->fb->var.bits_per_pixel)
1512                 sfb->fb->var.bits_per_pixel = 16;
1513
1514         sfb->fb->var.xres_virtual = sfb->fb->var.xres;
1515         sfb->fb->var.yres_virtual = sfb->fb->var.yres;
1516         err = smtc_map_smem(sfb, pdev, smem_size);
1517         if (err)
1518                 goto failed;
1519
1520         smtcfb_setmode(sfb);
1521
1522         err = register_framebuffer(info);
1523         if (err < 0)
1524                 goto failed;
1525
1526         dev_info(&pdev->dev,
1527                  "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.\n",
1528                  sfb->chip_id, sfb->chip_rev_id, sfb->fb->var.xres,
1529                  sfb->fb->var.yres, sfb->fb->var.bits_per_pixel);
1530
1531         return 0;
1532
1533 failed:
1534         dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail.\n");
1535
1536         smtc_unmap_smem(sfb);
1537         smtc_unmap_mmio(sfb);
1538 failed_fb:
1539         framebuffer_release(info);
1540
1541 failed_free:
1542         pci_release_region(pdev, 0);
1543
1544 failed_regions:
1545         pci_disable_device(pdev);
1546
1547         return err;
1548 }
1549
1550 /*
1551  * 0x710 (LynxEM)
1552  * 0x712 (LynxEM+)
1553  * 0x720 (Lynx3DM, Lynx3DM+)
1554  */
1555 static const struct pci_device_id smtcfb_pci_table[] = {
1556         { PCI_DEVICE(0x126f, 0x710), },
1557         { PCI_DEVICE(0x126f, 0x712), },
1558         { PCI_DEVICE(0x126f, 0x720), },
1559         {0,}
1560 };
1561
1562 MODULE_DEVICE_TABLE(pci, smtcfb_pci_table);
1563
1564 static void smtcfb_pci_remove(struct pci_dev *pdev)
1565 {
1566         struct smtcfb_info *sfb;
1567
1568         sfb = pci_get_drvdata(pdev);
1569         smtc_unmap_smem(sfb);
1570         smtc_unmap_mmio(sfb);
1571         unregister_framebuffer(sfb->fb);
1572         framebuffer_release(sfb->fb);
1573         pci_release_region(pdev, 0);
1574         pci_disable_device(pdev);
1575 }
1576
1577 #ifdef CONFIG_PM
1578 static int smtcfb_pci_suspend(struct device *device)
1579 {
1580         struct pci_dev *pdev = to_pci_dev(device);
1581         struct smtcfb_info *sfb;
1582
1583         sfb = pci_get_drvdata(pdev);
1584
1585         /* set the hw in sleep mode use external clock and self memory refresh
1586          * so that we can turn off internal PLLs later on
1587          */
1588         smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0));
1589         smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7));
1590
1591         console_lock();
1592         fb_set_suspend(sfb->fb, 1);
1593         console_unlock();
1594
1595         /* additionally turn off all function blocks including internal PLLs */
1596         smtc_seqw(0x21, 0xff);
1597
1598         return 0;
1599 }
1600
1601 static int smtcfb_pci_resume(struct device *device)
1602 {
1603         struct pci_dev *pdev = to_pci_dev(device);
1604         struct smtcfb_info *sfb;
1605
1606         sfb = pci_get_drvdata(pdev);
1607
1608         /* reinit hardware */
1609         sm7xx_init_hw();
1610         switch (sfb->chip_id) {
1611         case 0x710:
1612         case 0x712:
1613                 /* set MCLK = 14.31818 *  (0x16 / 0x2) */
1614                 smtc_seqw(0x6a, 0x16);
1615                 smtc_seqw(0x6b, 0x02);
1616                 smtc_seqw(0x62, 0x3e);
1617                 /* enable PCI burst */
1618                 smtc_seqw(0x17, 0x20);
1619 #ifdef __BIG_ENDIAN
1620                 if (sfb->fb->var.bits_per_pixel == 32)
1621                         smtc_seqw(0x17, 0x30);
1622 #endif
1623                 break;
1624         case 0x720:
1625                 smtc_seqw(0x62, 0xff);
1626                 smtc_seqw(0x6a, 0x0d);
1627                 smtc_seqw(0x6b, 0x02);
1628                 break;
1629         }
1630
1631         smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0));
1632         smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb));
1633
1634         smtcfb_setmode(sfb);
1635
1636         console_lock();
1637         fb_set_suspend(sfb->fb, 0);
1638         console_unlock();
1639
1640         return 0;
1641 }
1642
1643 static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume);
1644 #define SM7XX_PM_OPS (&sm7xx_pm_ops)
1645
1646 #else  /* !CONFIG_PM */
1647
1648 #define SM7XX_PM_OPS NULL
1649
1650 #endif /* !CONFIG_PM */
1651
1652 static struct pci_driver smtcfb_driver = {
1653         .name = "smtcfb",
1654         .id_table = smtcfb_pci_table,
1655         .probe = smtcfb_pci_probe,
1656         .remove = smtcfb_pci_remove,
1657         .driver.pm  = SM7XX_PM_OPS,
1658 };
1659
1660 static int __init sm712fb_init(void)
1661 {
1662 #ifndef MODULE
1663         char *option = NULL;
1664
1665         if (fb_get_options("sm712fb", &option))
1666                 return -ENODEV;
1667         if (option && *option)
1668                 mode_option = option;
1669 #endif
1670         sm7xx_vga_setup(mode_option);
1671
1672         return pci_register_driver(&smtcfb_driver);
1673 }
1674
1675 module_init(sm712fb_init);
1676
1677 static void __exit sm712fb_exit(void)
1678 {
1679         pci_unregister_driver(&smtcfb_driver);
1680 }
1681
1682 module_exit(sm712fb_exit);
1683
1684 MODULE_AUTHOR("Siliconmotion ");
1685 MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
1686 MODULE_LICENSE("GPL");