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