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