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