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