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