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