video/rockchip: rga2: use axi safe reset
[firefly-linux-kernel-4.4.55.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/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 "sm712.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                         pal[regno] = pal_rgb(red, green, blue, val);
927                 } else {
928                         u32 *pal = sfb->fb->pseudo_palette;
929
930                         val = chan_to_field(red, &sfb->fb->var.red);
931                         val |= chan_to_field(green, &sfb->fb->var.green);
932                         val |= chan_to_field(blue, &sfb->fb->var.blue);
933                         pal[regno] = big_swap(val);
934                 }
935                 break;
936
937         case FB_VISUAL_PSEUDOCOLOR:
938                 /* color depth 8 bit */
939                 sm712_setpalette(regno, red, green, blue, info);
940                 break;
941
942         default:
943                 return 1;       /* unknown type */
944         }
945
946         return 0;
947 }
948
949 static ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
950                            size_t count, loff_t *ppos)
951 {
952         unsigned long p = *ppos;
953
954         u32 *buffer, *dst;
955         u32 __iomem *src;
956         int c, i, cnt = 0, err = 0;
957         unsigned long total_size;
958
959         if (!info || !info->screen_base)
960                 return -ENODEV;
961
962         if (info->state != FBINFO_STATE_RUNNING)
963                 return -EPERM;
964
965         total_size = info->screen_size;
966
967         if (total_size == 0)
968                 total_size = info->fix.smem_len;
969
970         if (p >= total_size)
971                 return 0;
972
973         if (count >= total_size)
974                 count = total_size;
975
976         if (count + p > total_size)
977                 count = total_size - p;
978
979         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
980         if (!buffer)
981                 return -ENOMEM;
982
983         src = (u32 __iomem *)(info->screen_base + p);
984
985         if (info->fbops->fb_sync)
986                 info->fbops->fb_sync(info);
987
988         while (count) {
989                 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
990                 dst = buffer;
991                 for (i = c >> 2; i--;) {
992                         *dst = fb_readl(src++);
993                         *dst = big_swap(*dst);
994                         dst++;
995                 }
996                 if (c & 3) {
997                         u8 *dst8 = (u8 *)dst;
998                         u8 __iomem *src8 = (u8 __iomem *)src;
999
1000                         for (i = c & 3; i--;) {
1001                                 if (i & 1) {
1002                                         *dst8++ = fb_readb(++src8);
1003                                 } else {
1004                                         *dst8++ = fb_readb(--src8);
1005                                         src8 += 2;
1006                                 }
1007                         }
1008                         src = (u32 __iomem *)src8;
1009                 }
1010
1011                 if (copy_to_user(buf, buffer, c)) {
1012                         err = -EFAULT;
1013                         break;
1014                 }
1015                 *ppos += c;
1016                 buf += c;
1017                 cnt += c;
1018                 count -= c;
1019         }
1020
1021         kfree(buffer);
1022
1023         return (err) ? err : cnt;
1024 }
1025
1026 static ssize_t smtcfb_write(struct fb_info *info, const char __user *buf,
1027                             size_t count, loff_t *ppos)
1028 {
1029         unsigned long p = *ppos;
1030
1031         u32 *buffer, *src;
1032         u32 __iomem *dst;
1033         int c, i, cnt = 0, err = 0;
1034         unsigned long total_size;
1035
1036         if (!info || !info->screen_base)
1037                 return -ENODEV;
1038
1039         if (info->state != FBINFO_STATE_RUNNING)
1040                 return -EPERM;
1041
1042         total_size = info->screen_size;
1043
1044         if (total_size == 0)
1045                 total_size = info->fix.smem_len;
1046
1047         if (p > total_size)
1048                 return -EFBIG;
1049
1050         if (count > total_size) {
1051                 err = -EFBIG;
1052                 count = total_size;
1053         }
1054
1055         if (count + p > total_size) {
1056                 if (!err)
1057                         err = -ENOSPC;
1058
1059                 count = total_size - p;
1060         }
1061
1062         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
1063         if (!buffer)
1064                 return -ENOMEM;
1065
1066         dst = (u32 __iomem *)(info->screen_base + p);
1067
1068         if (info->fbops->fb_sync)
1069                 info->fbops->fb_sync(info);
1070
1071         while (count) {
1072                 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
1073                 src = buffer;
1074
1075                 if (copy_from_user(src, buf, c)) {
1076                         err = -EFAULT;
1077                         break;
1078                 }
1079
1080                 for (i = c >> 2; i--;) {
1081                         fb_writel(big_swap(*src), dst++);
1082                         src++;
1083                 }
1084                 if (c & 3) {
1085                         u8 *src8 = (u8 *)src;
1086                         u8 __iomem *dst8 = (u8 __iomem *)dst;
1087
1088                         for (i = c & 3; i--;) {
1089                                 if (i & 1) {
1090                                         fb_writeb(*src8++, ++dst8);
1091                                 } else {
1092                                         fb_writeb(*src8++, --dst8);
1093                                         dst8 += 2;
1094                                 }
1095                         }
1096                         dst = (u32 __iomem *)dst8;
1097                 }
1098
1099                 *ppos += c;
1100                 buf += c;
1101                 cnt += c;
1102                 count -= c;
1103         }
1104
1105         kfree(buffer);
1106
1107         return (cnt) ? cnt : err;
1108 }
1109
1110 static void sm7xx_set_timing(struct smtcfb_info *sfb)
1111 {
1112         int i = 0, j = 0;
1113         u32 m_nscreenstride;
1114
1115         dev_dbg(&sfb->pdev->dev,
1116                 "sfb->width=%d sfb->height=%d sfb->fb->var.bits_per_pixel=%d sfb->hz=%d\n",
1117                 sfb->width, sfb->height, sfb->fb->var.bits_per_pixel, sfb->hz);
1118
1119         for (j = 0; j < ARRAY_SIZE(vgamode); j++) {
1120                 if (vgamode[j].mmsizex != sfb->width ||
1121                     vgamode[j].mmsizey != sfb->height ||
1122                     vgamode[j].bpp != sfb->fb->var.bits_per_pixel ||
1123                     vgamode[j].hz != sfb->hz)
1124                         continue;
1125
1126                 dev_dbg(&sfb->pdev->dev,
1127                         "vgamode[j].mmsizex=%d vgamode[j].mmSizeY=%d vgamode[j].bpp=%d vgamode[j].hz=%d\n",
1128                         vgamode[j].mmsizex, vgamode[j].mmsizey,
1129                         vgamode[j].bpp, vgamode[j].hz);
1130
1131                 dev_dbg(&sfb->pdev->dev, "vgamode index=%d\n", j);
1132
1133                 smtc_mmiowb(0x0, 0x3c6);
1134
1135                 smtc_seqw(0, 0x1);
1136
1137                 smtc_mmiowb(vgamode[j].init_misc, 0x3c2);
1138
1139                 /* init SEQ register SR00 - SR04 */
1140                 for (i = 0; i < SIZE_SR00_SR04; i++)
1141                         smtc_seqw(i, vgamode[j].init_sr00_sr04[i]);
1142
1143                 /* init SEQ register SR10 - SR24 */
1144                 for (i = 0; i < SIZE_SR10_SR24; i++)
1145                         smtc_seqw(i + 0x10, vgamode[j].init_sr10_sr24[i]);
1146
1147                 /* init SEQ register SR30 - SR75 */
1148                 for (i = 0; i < SIZE_SR30_SR75; i++)
1149                         if ((i + 0x30) != 0x62 && (i + 0x30) != 0x6a &&
1150                             (i + 0x30) != 0x6b)
1151                                 smtc_seqw(i + 0x30,
1152                                           vgamode[j].init_sr30_sr75[i]);
1153
1154                 /* init SEQ register SR80 - SR93 */
1155                 for (i = 0; i < SIZE_SR80_SR93; i++)
1156                         smtc_seqw(i + 0x80, vgamode[j].init_sr80_sr93[i]);
1157
1158                 /* init SEQ register SRA0 - SRAF */
1159                 for (i = 0; i < SIZE_SRA0_SRAF; i++)
1160                         smtc_seqw(i + 0xa0, vgamode[j].init_sra0_sraf[i]);
1161
1162                 /* init Graphic register GR00 - GR08 */
1163                 for (i = 0; i < SIZE_GR00_GR08; i++)
1164                         smtc_grphw(i, vgamode[j].init_gr00_gr08[i]);
1165
1166                 /* init Attribute register AR00 - AR14 */
1167                 for (i = 0; i < SIZE_AR00_AR14; i++)
1168                         smtc_attrw(i, vgamode[j].init_ar00_ar14[i]);
1169
1170                 /* init CRTC register CR00 - CR18 */
1171                 for (i = 0; i < SIZE_CR00_CR18; i++)
1172                         smtc_crtcw(i, vgamode[j].init_cr00_cr18[i]);
1173
1174                 /* init CRTC register CR30 - CR4D */
1175                 for (i = 0; i < SIZE_CR30_CR4D; i++)
1176                         smtc_crtcw(i + 0x30, vgamode[j].init_cr30_cr4d[i]);
1177
1178                 /* init CRTC register CR90 - CRA7 */
1179                 for (i = 0; i < SIZE_CR90_CRA7; i++)
1180                         smtc_crtcw(i + 0x90, vgamode[j].init_cr90_cra7[i]);
1181         }
1182         smtc_mmiowb(0x67, 0x3c2);
1183
1184         /* set VPR registers */
1185         writel(0x0, sfb->vp_regs + 0x0C);
1186         writel(0x0, sfb->vp_regs + 0x40);
1187
1188         /* set data width */
1189         m_nscreenstride = (sfb->width * sfb->fb->var.bits_per_pixel) / 64;
1190         switch (sfb->fb->var.bits_per_pixel) {
1191         case 8:
1192                 writel(0x0, sfb->vp_regs + 0x0);
1193                 break;
1194         case 16:
1195                 writel(0x00020000, sfb->vp_regs + 0x0);
1196                 break;
1197         case 24:
1198                 writel(0x00040000, sfb->vp_regs + 0x0);
1199                 break;
1200         case 32:
1201                 writel(0x00030000, sfb->vp_regs + 0x0);
1202                 break;
1203         }
1204         writel((u32)(((m_nscreenstride + 2) << 16) | m_nscreenstride),
1205                sfb->vp_regs + 0x10);
1206 }
1207
1208 static void smtc_set_timing(struct smtcfb_info *sfb)
1209 {
1210         switch (sfb->chip_id) {
1211         case 0x710:
1212         case 0x712:
1213         case 0x720:
1214                 sm7xx_set_timing(sfb);
1215                 break;
1216         }
1217 }
1218
1219 static void smtcfb_setmode(struct smtcfb_info *sfb)
1220 {
1221         switch (sfb->fb->var.bits_per_pixel) {
1222         case 32:
1223                 sfb->fb->fix.visual       = FB_VISUAL_TRUECOLOR;
1224                 sfb->fb->fix.line_length  = sfb->fb->var.xres * 4;
1225                 sfb->fb->var.red.length   = 8;
1226                 sfb->fb->var.green.length = 8;
1227                 sfb->fb->var.blue.length  = 8;
1228                 sfb->fb->var.red.offset   = 16;
1229                 sfb->fb->var.green.offset = 8;
1230                 sfb->fb->var.blue.offset  = 0;
1231                 break;
1232         case 24:
1233                 sfb->fb->fix.visual       = FB_VISUAL_TRUECOLOR;
1234                 sfb->fb->fix.line_length  = sfb->fb->var.xres * 3;
1235                 sfb->fb->var.red.length   = 8;
1236                 sfb->fb->var.green.length = 8;
1237                 sfb->fb->var.blue.length  = 8;
1238                 sfb->fb->var.red.offset   = 16;
1239                 sfb->fb->var.green.offset = 8;
1240                 sfb->fb->var.blue.offset  = 0;
1241                 break;
1242         case 8:
1243                 sfb->fb->fix.visual       = FB_VISUAL_PSEUDOCOLOR;
1244                 sfb->fb->fix.line_length  = sfb->fb->var.xres;
1245                 sfb->fb->var.red.length   = 3;
1246                 sfb->fb->var.green.length = 3;
1247                 sfb->fb->var.blue.length  = 2;
1248                 sfb->fb->var.red.offset   = 5;
1249                 sfb->fb->var.green.offset = 2;
1250                 sfb->fb->var.blue.offset  = 0;
1251                 break;
1252         case 16:
1253         default:
1254                 sfb->fb->fix.visual       = FB_VISUAL_TRUECOLOR;
1255                 sfb->fb->fix.line_length  = sfb->fb->var.xres * 2;
1256                 sfb->fb->var.red.length   = 5;
1257                 sfb->fb->var.green.length = 6;
1258                 sfb->fb->var.blue.length  = 5;
1259                 sfb->fb->var.red.offset   = 11;
1260                 sfb->fb->var.green.offset = 5;
1261                 sfb->fb->var.blue.offset  = 0;
1262                 break;
1263         }
1264
1265         sfb->width  = sfb->fb->var.xres;
1266         sfb->height = sfb->fb->var.yres;
1267         sfb->hz = 60;
1268         smtc_set_timing(sfb);
1269 }
1270
1271 static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1272 {
1273         /* sanity checks */
1274         if (var->xres_virtual < var->xres)
1275                 var->xres_virtual = var->xres;
1276
1277         if (var->yres_virtual < var->yres)
1278                 var->yres_virtual = var->yres;
1279
1280         /* set valid default bpp */
1281         if ((var->bits_per_pixel != 8)  && (var->bits_per_pixel != 16) &&
1282             (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32))
1283                 var->bits_per_pixel = 16;
1284
1285         return 0;
1286 }
1287
1288 static int smtc_set_par(struct fb_info *info)
1289 {
1290         smtcfb_setmode(info->par);
1291
1292         return 0;
1293 }
1294
1295 static struct fb_ops smtcfb_ops = {
1296         .owner        = THIS_MODULE,
1297         .fb_check_var = smtc_check_var,
1298         .fb_set_par   = smtc_set_par,
1299         .fb_setcolreg = smtc_setcolreg,
1300         .fb_blank     = smtc_blank,
1301         .fb_fillrect  = cfb_fillrect,
1302         .fb_imageblit = cfb_imageblit,
1303         .fb_copyarea  = cfb_copyarea,
1304         .fb_read      = smtcfb_read,
1305         .fb_write     = smtcfb_write,
1306 };
1307
1308 /*
1309  * Unmap in the memory mapped IO registers
1310  */
1311
1312 static void smtc_unmap_mmio(struct smtcfb_info *sfb)
1313 {
1314         if (sfb && smtc_regbaseaddress)
1315                 smtc_regbaseaddress = NULL;
1316 }
1317
1318 /*
1319  * Map in the screen memory
1320  */
1321
1322 static int smtc_map_smem(struct smtcfb_info *sfb,
1323                          struct pci_dev *pdev, u_long smem_len)
1324 {
1325         sfb->fb->fix.smem_start = pci_resource_start(pdev, 0);
1326
1327         if (sfb->fb->var.bits_per_pixel == 32)
1328                 sfb->fb->fix.smem_start += big_addr;
1329
1330         sfb->fb->fix.smem_len = smem_len;
1331
1332         sfb->fb->screen_base = sfb->lfb;
1333
1334         if (!sfb->fb->screen_base) {
1335                 dev_err(&pdev->dev,
1336                         "%s: unable to map screen memory\n", sfb->fb->fix.id);
1337                 return -ENOMEM;
1338         }
1339
1340         return 0;
1341 }
1342
1343 /*
1344  * Unmap in the screen memory
1345  *
1346  */
1347 static void smtc_unmap_smem(struct smtcfb_info *sfb)
1348 {
1349         if (sfb && sfb->fb->screen_base) {
1350                 iounmap(sfb->fb->screen_base);
1351                 sfb->fb->screen_base = NULL;
1352         }
1353 }
1354
1355 /*
1356  * We need to wake up the device and make sure its in linear memory mode.
1357  */
1358 static inline void sm7xx_init_hw(void)
1359 {
1360         outb_p(0x18, 0x3c4);
1361         outb_p(0x11, 0x3c5);
1362 }
1363
1364 static int smtcfb_pci_probe(struct pci_dev *pdev,
1365                             const struct pci_device_id *ent)
1366 {
1367         struct smtcfb_info *sfb;
1368         struct fb_info *info;
1369         u_long smem_size = 0x00800000;  /* default 8MB */
1370         int err;
1371         unsigned long mmio_base;
1372
1373         dev_info(&pdev->dev, "Silicon Motion display driver.\n");
1374
1375         err = pci_enable_device(pdev);  /* enable SMTC chip */
1376         if (err)
1377                 return err;
1378
1379         err = pci_request_region(pdev, 0, "sm7xxfb");
1380         if (err < 0) {
1381                 dev_err(&pdev->dev, "cannot reserve framebuffer region\n");
1382                 goto failed_regions;
1383         }
1384
1385         sprintf(smtcfb_fix.id, "sm%Xfb", ent->device);
1386
1387         info = framebuffer_alloc(sizeof(*sfb), &pdev->dev);
1388         if (!info) {
1389                 dev_err(&pdev->dev, "framebuffer_alloc failed\n");
1390                 err = -ENOMEM;
1391                 goto failed_free;
1392         }
1393
1394         sfb = info->par;
1395         sfb->fb = info;
1396         sfb->chip_id = ent->device;
1397         sfb->pdev = pdev;
1398         info->flags = FBINFO_FLAG_DEFAULT;
1399         info->fbops = &smtcfb_ops;
1400         info->fix = smtcfb_fix;
1401         info->var = smtcfb_var;
1402         info->pseudo_palette = sfb->colreg;
1403         info->par = sfb;
1404
1405         pci_set_drvdata(pdev, sfb);
1406
1407         sm7xx_init_hw();
1408
1409         /* get mode parameter from smtc_scr_info */
1410         if (smtc_scr_info.lfb_width != 0) {
1411                 sfb->fb->var.xres = smtc_scr_info.lfb_width;
1412                 sfb->fb->var.yres = smtc_scr_info.lfb_height;
1413                 sfb->fb->var.bits_per_pixel = smtc_scr_info.lfb_depth;
1414         } else {
1415                 /* default resolution 1024x600 16bit mode */
1416                 sfb->fb->var.xres = SCREEN_X_RES;
1417                 sfb->fb->var.yres = SCREEN_Y_RES;
1418                 sfb->fb->var.bits_per_pixel = SCREEN_BPP;
1419         }
1420
1421         big_pixel_depth(sfb->fb->var.bits_per_pixel, smtc_scr_info.lfb_depth);
1422         /* Map address and memory detection */
1423         mmio_base = pci_resource_start(pdev, 0);
1424         pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
1425
1426         switch (sfb->chip_id) {
1427         case 0x710:
1428         case 0x712:
1429                 sfb->fb->fix.mmio_start = mmio_base + 0x00400000;
1430                 sfb->fb->fix.mmio_len = 0x00400000;
1431                 smem_size = SM712_VIDEOMEMORYSIZE;
1432                 sfb->lfb = ioremap(mmio_base, mmio_addr);
1433                 if (!sfb->lfb) {
1434                         dev_err(&pdev->dev,
1435                                 "%s: unable to map memory mapped IO!\n",
1436                                 sfb->fb->fix.id);
1437                         err = -ENOMEM;
1438                         goto failed_fb;
1439                 }
1440
1441                 sfb->mmio = (smtc_regbaseaddress =
1442                     sfb->lfb + 0x00700000);
1443                 sfb->dp_regs = sfb->lfb + 0x00408000;
1444                 sfb->vp_regs = sfb->lfb + 0x0040c000;
1445                 if (sfb->fb->var.bits_per_pixel == 32) {
1446                         sfb->lfb += big_addr;
1447                         dev_info(&pdev->dev, "sfb->lfb=%p\n", sfb->lfb);
1448                 }
1449
1450                 /* set MCLK = 14.31818 * (0x16 / 0x2) */
1451                 smtc_seqw(0x6a, 0x16);
1452                 smtc_seqw(0x6b, 0x02);
1453                 smtc_seqw(0x62, 0x3e);
1454                 /* enable PCI burst */
1455                 smtc_seqw(0x17, 0x20);
1456                 /* enable word swap */
1457                 if (sfb->fb->var.bits_per_pixel == 32)
1458                         seqw17();
1459                 break;
1460         case 0x720:
1461                 sfb->fb->fix.mmio_start = mmio_base;
1462                 sfb->fb->fix.mmio_len = 0x00200000;
1463                 smem_size = SM722_VIDEOMEMORYSIZE;
1464                 sfb->dp_regs = ioremap(mmio_base, 0x00a00000);
1465                 sfb->lfb = sfb->dp_regs + 0x00200000;
1466                 sfb->mmio = (smtc_regbaseaddress =
1467                     sfb->dp_regs + 0x000c0000);
1468                 sfb->vp_regs = sfb->dp_regs + 0x800;
1469
1470                 smtc_seqw(0x62, 0xff);
1471                 smtc_seqw(0x6a, 0x0d);
1472                 smtc_seqw(0x6b, 0x02);
1473                 break;
1474         default:
1475                 dev_err(&pdev->dev,
1476                         "No valid Silicon Motion display chip was detected!\n");
1477
1478                 goto failed_fb;
1479         }
1480
1481         /* can support 32 bpp */
1482         if (15 == sfb->fb->var.bits_per_pixel)
1483                 sfb->fb->var.bits_per_pixel = 16;
1484
1485         sfb->fb->var.xres_virtual = sfb->fb->var.xres;
1486         sfb->fb->var.yres_virtual = sfb->fb->var.yres;
1487         err = smtc_map_smem(sfb, pdev, smem_size);
1488         if (err)
1489                 goto failed;
1490
1491         smtcfb_setmode(sfb);
1492
1493         err = register_framebuffer(info);
1494         if (err < 0)
1495                 goto failed;
1496
1497         dev_info(&pdev->dev,
1498                  "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.\n",
1499                  sfb->chip_id, sfb->chip_rev_id, sfb->fb->var.xres,
1500                  sfb->fb->var.yres, sfb->fb->var.bits_per_pixel);
1501
1502         return 0;
1503
1504 failed:
1505         dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail.\n");
1506
1507         smtc_unmap_smem(sfb);
1508         smtc_unmap_mmio(sfb);
1509 failed_fb:
1510         framebuffer_release(info);
1511
1512 failed_free:
1513         pci_release_region(pdev, 0);
1514
1515 failed_regions:
1516         pci_disable_device(pdev);
1517
1518         return err;
1519 }
1520
1521 /*
1522  * 0x710 (LynxEM)
1523  * 0x712 (LynxEM+)
1524  * 0x720 (Lynx3DM, Lynx3DM+)
1525  */
1526 static const struct pci_device_id smtcfb_pci_table[] = {
1527         { PCI_DEVICE(0x126f, 0x710), },
1528         { PCI_DEVICE(0x126f, 0x712), },
1529         { PCI_DEVICE(0x126f, 0x720), },
1530         {0,}
1531 };
1532
1533 MODULE_DEVICE_TABLE(pci, smtcfb_pci_table);
1534
1535 static void smtcfb_pci_remove(struct pci_dev *pdev)
1536 {
1537         struct smtcfb_info *sfb;
1538
1539         sfb = pci_get_drvdata(pdev);
1540         smtc_unmap_smem(sfb);
1541         smtc_unmap_mmio(sfb);
1542         unregister_framebuffer(sfb->fb);
1543         framebuffer_release(sfb->fb);
1544         pci_release_region(pdev, 0);
1545         pci_disable_device(pdev);
1546 }
1547
1548 #ifdef CONFIG_PM
1549 static int smtcfb_pci_suspend(struct device *device)
1550 {
1551         struct pci_dev *pdev = to_pci_dev(device);
1552         struct smtcfb_info *sfb;
1553
1554         sfb = pci_get_drvdata(pdev);
1555
1556         /* set the hw in sleep mode use external clock and self memory refresh
1557          * so that we can turn off internal PLLs later on
1558          */
1559         smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0));
1560         smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7));
1561
1562         console_lock();
1563         fb_set_suspend(sfb->fb, 1);
1564         console_unlock();
1565
1566         /* additionally turn off all function blocks including internal PLLs */
1567         smtc_seqw(0x21, 0xff);
1568
1569         return 0;
1570 }
1571
1572 static int smtcfb_pci_resume(struct device *device)
1573 {
1574         struct pci_dev *pdev = to_pci_dev(device);
1575         struct smtcfb_info *sfb;
1576
1577         sfb = pci_get_drvdata(pdev);
1578
1579         /* reinit hardware */
1580         sm7xx_init_hw();
1581         switch (sfb->chip_id) {
1582         case 0x710:
1583         case 0x712:
1584                 /* set MCLK = 14.31818 *  (0x16 / 0x2) */
1585                 smtc_seqw(0x6a, 0x16);
1586                 smtc_seqw(0x6b, 0x02);
1587                 smtc_seqw(0x62, 0x3e);
1588                 /* enable PCI burst */
1589                 smtc_seqw(0x17, 0x20);
1590                 if (sfb->fb->var.bits_per_pixel == 32)
1591                         seqw17();
1592                 break;
1593         case 0x720:
1594                 smtc_seqw(0x62, 0xff);
1595                 smtc_seqw(0x6a, 0x0d);
1596                 smtc_seqw(0x6b, 0x02);
1597                 break;
1598         }
1599
1600         smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0));
1601         smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb));
1602
1603         smtcfb_setmode(sfb);
1604
1605         console_lock();
1606         fb_set_suspend(sfb->fb, 0);
1607         console_unlock();
1608
1609         return 0;
1610 }
1611
1612 static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume);
1613 #define SM7XX_PM_OPS (&sm7xx_pm_ops)
1614
1615 #else  /* !CONFIG_PM */
1616
1617 #define SM7XX_PM_OPS NULL
1618
1619 #endif /* !CONFIG_PM */
1620
1621 static struct pci_driver smtcfb_driver = {
1622         .name = "smtcfb",
1623         .id_table = smtcfb_pci_table,
1624         .probe = smtcfb_pci_probe,
1625         .remove = smtcfb_pci_remove,
1626         .driver.pm  = SM7XX_PM_OPS,
1627 };
1628
1629 static int __init sm712fb_init(void)
1630 {
1631         char *option = NULL;
1632
1633         if (fb_get_options("sm712fb", &option))
1634                 return -ENODEV;
1635         if (option && *option)
1636                 mode_option = option;
1637         sm7xx_vga_setup(mode_option);
1638
1639         return pci_register_driver(&smtcfb_driver);
1640 }
1641
1642 module_init(sm712fb_init);
1643
1644 static void __exit sm712fb_exit(void)
1645 {
1646         pci_unregister_driver(&smtcfb_driver);
1647 }
1648
1649 module_exit(sm712fb_exit);
1650
1651 MODULE_AUTHOR("Siliconmotion ");
1652 MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
1653 MODULE_LICENSE("GPL");