2 * Silicon Motion SM7XX frame buffer device
4 * Copyright (C) 2006 Silicon Motion Technology Corp.
5 * Authors: Ge Wang, gewang@siliconmotion.com
6 * Boyod boyod.yang@siliconmotion.com.cn
8 * Copyright (C) 2009 Lemote, Inc.
9 * Author: Wu Zhangjin, wuzhangjin@gmail.com
11 * Copyright (C) 2011 Igalia, S.L.
12 * Author: Javier M. Mellid <jmunhoz@igalia.com>
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
18 * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips
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>
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 */
59 void __iomem
*smtc_regbaseaddress
; /* Memory Map IO starting address */
61 static struct fb_var_screeninfo smtcfb_var
= {
70 .activate
= FB_ACTIVATE_NOW
,
73 .vmode
= FB_VMODE_NONINTERLACED
,
75 .accel_flags
= FB_ACCELF_TEXT
,
78 static struct fb_fix_screeninfo smtcfb_fix
= {
80 .type
= FB_TYPE_PACKED_PIXELS
,
81 .visual
= FB_VISUAL_TRUECOLOR
,
82 .line_length
= 800 * 3,
83 .accel
= FB_ACCEL_SMI_LYNX
,
97 static const struct vesa_mode vesa_mode_table
[] = {
98 {"0x301", 640, 480, 8},
99 {"0x303", 800, 600, 8},
100 {"0x305", 1024, 768, 8},
101 {"0x307", 1280, 1024, 8},
103 {"0x311", 640, 480, 16},
104 {"0x314", 800, 600, 16},
105 {"0x317", 1024, 768, 16},
106 {"0x31A", 1280, 1024, 16},
108 {"0x312", 640, 480, 24},
109 {"0x315", 800, 600, 24},
110 {"0x318", 1024, 768, 24},
111 {"0x31B", 1280, 1024, 24},
114 /**********************************************************************
116 **********************************************************************/
117 static const struct modeinit vgamode
[] = {
119 /* mode#0: 640 x 480 16Bpp 60Hz */
124 0x03, 0x01, 0x0F, 0x00, 0x0E,
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,
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,
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,
147 { /* Init_SRA0_SRAF */
148 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
149 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
151 { /* Init_GR00_GR08 */
152 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
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,
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,
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,
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,
179 /* mode#1: 640 x 480 24Bpp 60Hz */
184 0x03, 0x01, 0x0F, 0x00, 0x0E,
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,
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,
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,
207 { /* Init_SRA0_SRAF */
208 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
209 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
211 { /* Init_GR00_GR08 */
212 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
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,
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,
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,
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,
239 /* mode#0: 640 x 480 32Bpp 60Hz */
244 0x03, 0x01, 0x0F, 0x00, 0x0E,
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,
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,
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,
267 { /* Init_SRA0_SRAF */
268 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
269 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
271 { /* Init_GR00_GR08 */
272 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
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,
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,
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,
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,
299 { /* mode#2: 800 x 600 16Bpp 60Hz */
304 0x03, 0x01, 0x0F, 0x03, 0x0E,
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,
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,
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,
327 { /* Init_SRA0_SRAF */
328 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
329 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
331 { /* Init_GR00_GR08 */
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
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,
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,
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,
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,
358 { /* mode#3: 800 x 600 24Bpp 60Hz */
362 0x03, 0x01, 0x0F, 0x03, 0x0E,
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,
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,
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,
385 { /* Init_SRA0_SRAF */
386 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
387 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
389 { /* Init_GR00_GR08 */
390 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
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,
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,
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,
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,
416 { /* mode#7: 800 x 600 32Bpp 60Hz */
421 0x03, 0x01, 0x0F, 0x03, 0x0E,
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,
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,
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,
444 { /* Init_SRA0_SRAF */
445 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
446 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
448 { /* Init_GR00_GR08 */
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
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,
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,
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,
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,
475 /* We use 1024x768 table to light 1024x600 panel for lemote */
476 { /* mode#4: 1024 x 600 16Bpp 60Hz */
481 0x03, 0x01, 0x0F, 0x00, 0x0E,
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,
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,
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,
504 { /* Init_SRA0_SRAF */
505 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
506 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
508 { /* Init_GR00_GR08 */
509 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
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,
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,
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,
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,
535 { /* mode#5: 1024 x 768 24Bpp 60Hz */
540 0x03, 0x01, 0x0F, 0x03, 0x0E,
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,
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,
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,
563 { /* Init_SRA0_SRAF */
564 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
565 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
567 { /* Init_GR00_GR08 */
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
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,
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,
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,
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,
594 { /* mode#4: 1024 x 768 32Bpp 60Hz */
599 0x03, 0x01, 0x0F, 0x03, 0x0E,
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,
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,
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,
622 { /* Init_SRA0_SRAF */
623 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
624 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
626 { /* Init_GR00_GR08 */
627 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
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,
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,
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,
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,
653 { /* mode#6: 320 x 240 16Bpp 60Hz */
658 0x03, 0x01, 0x0F, 0x03, 0x0E,
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,
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,
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,
681 { /* Init_SRA0_SRAF */
682 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
683 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
685 { /* Init_GR00_GR08 */
686 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
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,
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,
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,
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,
713 { /* mode#8: 320 x 240 32Bpp 60Hz */
718 0x03, 0x01, 0x0F, 0x03, 0x0E,
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,
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,
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,
741 { /* Init_SRA0_SRAF */
742 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
743 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
745 { /* Init_GR00_GR08 */
746 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
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,
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,
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,
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,
774 static struct screen_info smtc_scr_info
;
776 static char *mode_option
;
778 /* process command line options, get vga parameter */
779 static void __init
sm7xx_vga_setup(char *options
)
783 if (!options
|| !*options
)
786 smtc_scr_info
.lfb_width
= 0;
787 smtc_scr_info
.lfb_height
= 0;
788 smtc_scr_info
.lfb_depth
= 0;
790 pr_debug("sm7xx_vga_setup = %s\n", options
);
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
;
803 static void sm712_setpalette(int regno
, unsigned red
, unsigned green
,
804 unsigned blue
, struct fb_info
*info
)
806 /* set bit 5:4 = 01 (write LCD RAM only) */
807 smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10);
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
);
817 * convert a colour value into a field position
822 static inline unsigned int chan_to_field(unsigned int chan
,
823 struct fb_bitfield
*bf
)
826 chan
>>= 16 - bf
->length
;
827 return chan
<< bf
->offset
;
830 static int smtc_blank(int blank_mode
, struct fb_info
*info
)
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));
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));
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));
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));
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));
901 static int smtc_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
902 unsigned blue
, unsigned trans
, struct fb_info
*info
)
904 struct smtcfb_info
*sfb
;
912 switch (sfb
->fb
->fix
.visual
) {
913 case FB_VISUAL_DIRECTCOLOR
:
914 case FB_VISUAL_TRUECOLOR
:
916 * 16/32 bit true-colour, use pseudo-palette for 16 base color
920 if (sfb
->fb
->var
.bits_per_pixel
== 16) {
921 u32
*pal
= sfb
->fb
->pseudo_palette
;
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
);
926 pal
[regno
] = pal_rgb(red
, green
, blue
, val
);
928 u32
*pal
= sfb
->fb
->pseudo_palette
;
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
);
933 pal
[regno
] = big_swap(val
);
937 case FB_VISUAL_PSEUDOCOLOR
:
938 /* color depth 8 bit */
939 sm712_setpalette(regno
, red
, green
, blue
, info
);
943 return 1; /* unknown type */
949 static ssize_t
smtcfb_read(struct fb_info
*info
, char __user
*buf
,
950 size_t count
, loff_t
*ppos
)
952 unsigned long p
= *ppos
;
956 int c
, i
, cnt
= 0, err
= 0;
957 unsigned long total_size
;
959 if (!info
|| !info
->screen_base
)
962 if (info
->state
!= FBINFO_STATE_RUNNING
)
965 total_size
= info
->screen_size
;
968 total_size
= info
->fix
.smem_len
;
973 if (count
>= total_size
)
976 if (count
+ p
> total_size
)
977 count
= total_size
- p
;
979 buffer
= kmalloc((count
> PAGE_SIZE
) ? PAGE_SIZE
: count
, GFP_KERNEL
);
983 src
= (u32 __iomem
*)(info
->screen_base
+ p
);
985 if (info
->fbops
->fb_sync
)
986 info
->fbops
->fb_sync(info
);
989 c
= (count
> PAGE_SIZE
) ? PAGE_SIZE
: count
;
991 for (i
= c
>> 2; i
--;) {
992 *dst
= fb_readl(src
++);
993 *dst
= big_swap(*dst
);
997 u8
*dst8
= (u8
*)dst
;
998 u8 __iomem
*src8
= (u8 __iomem
*)src
;
1000 for (i
= c
& 3; i
--;) {
1002 *dst8
++ = fb_readb(++src8
);
1004 *dst8
++ = fb_readb(--src8
);
1008 src
= (u32 __iomem
*)src8
;
1011 if (copy_to_user(buf
, buffer
, c
)) {
1023 return (err
) ? err
: cnt
;
1026 static ssize_t
smtcfb_write(struct fb_info
*info
, const char __user
*buf
,
1027 size_t count
, loff_t
*ppos
)
1029 unsigned long p
= *ppos
;
1033 int c
, i
, cnt
= 0, err
= 0;
1034 unsigned long total_size
;
1036 if (!info
|| !info
->screen_base
)
1039 if (info
->state
!= FBINFO_STATE_RUNNING
)
1042 total_size
= info
->screen_size
;
1044 if (total_size
== 0)
1045 total_size
= info
->fix
.smem_len
;
1050 if (count
> total_size
) {
1055 if (count
+ p
> total_size
) {
1059 count
= total_size
- p
;
1062 buffer
= kmalloc((count
> PAGE_SIZE
) ? PAGE_SIZE
: count
, GFP_KERNEL
);
1066 dst
= (u32 __iomem
*)(info
->screen_base
+ p
);
1068 if (info
->fbops
->fb_sync
)
1069 info
->fbops
->fb_sync(info
);
1072 c
= (count
> PAGE_SIZE
) ? PAGE_SIZE
: count
;
1075 if (copy_from_user(src
, buf
, c
)) {
1080 for (i
= c
>> 2; i
--;) {
1081 fb_writel(big_swap(*src
), dst
++);
1085 u8
*src8
= (u8
*)src
;
1086 u8 __iomem
*dst8
= (u8 __iomem
*)dst
;
1088 for (i
= c
& 3; i
--;) {
1090 fb_writeb(*src8
++, ++dst8
);
1092 fb_writeb(*src8
++, --dst8
);
1096 dst
= (u32 __iomem
*)dst8
;
1107 return (cnt
) ? cnt
: err
;
1110 static void sm7xx_set_timing(struct smtcfb_info
*sfb
)
1113 u32 m_nscreenstride
;
1115 dev_dbg(&sfb
->pdev
->dev
,
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
);
1119 for (j
= 0; j
< ARRAY_SIZE(vgamode
); j
++) {
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
)
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
);
1131 dev_dbg(&sfb
->pdev
->dev
, "vgamode index=%d\n", j
);
1133 smtc_mmiowb(0x0, 0x3c6);
1137 smtc_mmiowb(vgamode
[j
].init_misc
, 0x3c2);
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
]);
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
]);
1147 /* init SEQ register SR30 - SR75 */
1148 for (i
= 0; i
< SIZE_SR30_SR75
; i
++)
1149 if ((i
+ 0x30) != 0x62 && (i
+ 0x30) != 0x6a &&
1152 vgamode
[j
].init_sr30_sr75
[i
]);
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
]);
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
]);
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
]);
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
]);
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
]);
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
]);
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
]);
1182 smtc_mmiowb(0x67, 0x3c2);
1184 /* set VPR registers */
1185 writel(0x0, sfb
->vp_regs
+ 0x0C);
1186 writel(0x0, sfb
->vp_regs
+ 0x40);
1188 /* set data width */
1189 m_nscreenstride
= (sfb
->width
* sfb
->fb
->var
.bits_per_pixel
) / 64;
1190 switch (sfb
->fb
->var
.bits_per_pixel
) {
1192 writel(0x0, sfb
->vp_regs
+ 0x0);
1195 writel(0x00020000, sfb
->vp_regs
+ 0x0);
1198 writel(0x00040000, sfb
->vp_regs
+ 0x0);
1201 writel(0x00030000, sfb
->vp_regs
+ 0x0);
1204 writel((u32
)(((m_nscreenstride
+ 2) << 16) | m_nscreenstride
),
1205 sfb
->vp_regs
+ 0x10);
1208 static void smtc_set_timing(struct smtcfb_info
*sfb
)
1210 switch (sfb
->chip_id
) {
1214 sm7xx_set_timing(sfb
);
1219 static void smtcfb_setmode(struct smtcfb_info
*sfb
)
1221 switch (sfb
->fb
->var
.bits_per_pixel
) {
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;
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;
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;
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;
1265 sfb
->width
= sfb
->fb
->var
.xres
;
1266 sfb
->height
= sfb
->fb
->var
.yres
;
1268 smtc_set_timing(sfb
);
1271 static int smtc_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
1274 if (var
->xres_virtual
< var
->xres
)
1275 var
->xres_virtual
= var
->xres
;
1277 if (var
->yres_virtual
< var
->yres
)
1278 var
->yres_virtual
= var
->yres
;
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;
1288 static int smtc_set_par(struct fb_info
*info
)
1290 smtcfb_setmode(info
->par
);
1295 static 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
,
1304 .fb_read
= smtcfb_read
,
1305 .fb_write
= smtcfb_write
,
1309 * Unmap in the memory mapped IO registers
1312 static void smtc_unmap_mmio(struct smtcfb_info
*sfb
)
1314 if (sfb
&& smtc_regbaseaddress
)
1315 smtc_regbaseaddress
= NULL
;
1319 * Map in the screen memory
1322 static int smtc_map_smem(struct smtcfb_info
*sfb
,
1323 struct pci_dev
*pdev
, u_long smem_len
)
1325 sfb
->fb
->fix
.smem_start
= pci_resource_start(pdev
, 0);
1327 if (sfb
->fb
->var
.bits_per_pixel
== 32)
1328 sfb
->fb
->fix
.smem_start
+= big_addr
;
1330 sfb
->fb
->fix
.smem_len
= smem_len
;
1332 sfb
->fb
->screen_base
= sfb
->lfb
;
1334 if (!sfb
->fb
->screen_base
) {
1336 "%s: unable to map screen memory\n", sfb
->fb
->fix
.id
);
1344 * Unmap in the screen memory
1347 static void smtc_unmap_smem(struct smtcfb_info
*sfb
)
1349 if (sfb
&& sfb
->fb
->screen_base
) {
1350 iounmap(sfb
->fb
->screen_base
);
1351 sfb
->fb
->screen_base
= NULL
;
1356 * We need to wake up the device and make sure its in linear memory mode.
1358 static inline void sm7xx_init_hw(void)
1360 outb_p(0x18, 0x3c4);
1361 outb_p(0x11, 0x3c5);
1364 static int smtcfb_pci_probe(struct pci_dev
*pdev
,
1365 const struct pci_device_id
*ent
)
1367 struct smtcfb_info
*sfb
;
1368 struct fb_info
*info
;
1369 u_long smem_size
= 0x00800000; /* default 8MB */
1371 unsigned long mmio_base
;
1373 dev_info(&pdev
->dev
, "Silicon Motion display driver.\n");
1375 err
= pci_enable_device(pdev
); /* enable SMTC chip */
1379 err
= pci_request_region(pdev
, 0, "sm7xxfb");
1381 dev_err(&pdev
->dev
, "cannot reserve framebuffer region\n");
1382 goto failed_regions
;
1385 sprintf(smtcfb_fix
.id
, "sm%Xfb", ent
->device
);
1387 info
= framebuffer_alloc(sizeof(*sfb
), &pdev
->dev
);
1389 dev_err(&pdev
->dev
, "framebuffer_alloc failed\n");
1396 sfb
->chip_id
= ent
->device
;
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
;
1405 pci_set_drvdata(pdev
, sfb
);
1409 /* get mode parameter from smtc_scr_info */
1410 if (smtc_scr_info
.lfb_width
!= 0) {
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
;
1415 /* default resolution 1024x600 16bit mode */
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
;
1421 big_pixel_depth(sfb
->fb
->var
.bits_per_pixel
, smtc_scr_info
.lfb_depth
);
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
);
1426 switch (sfb
->chip_id
) {
1429 sfb
->fb
->fix
.mmio_start
= mmio_base
+ 0x00400000;
1430 sfb
->fb
->fix
.mmio_len
= 0x00400000;
1431 smem_size
= SM712_VIDEOMEMORYSIZE
;
1432 sfb
->lfb
= ioremap(mmio_base
, mmio_addr
);
1435 "%s: unable to map memory mapped IO!\n",
1441 sfb
->mmio
= (smtc_regbaseaddress
=
1442 sfb
->lfb
+ 0x00700000);
1443 sfb
->dp_regs
= sfb
->lfb
+ 0x00408000;
1444 sfb
->vp_regs
= sfb
->lfb
+ 0x0040c000;
1445 if (sfb
->fb
->var
.bits_per_pixel
== 32) {
1446 sfb
->lfb
+= big_addr
;
1447 dev_info(&pdev
->dev
, "sfb->lfb=%p\n", sfb
->lfb
);
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 */
1457 if (sfb
->fb
->var
.bits_per_pixel
== 32)
1461 sfb
->fb
->fix
.mmio_start
= mmio_base
;
1462 sfb
->fb
->fix
.mmio_len
= 0x00200000;
1463 smem_size
= SM722_VIDEOMEMORYSIZE
;
1464 sfb
->dp_regs
= ioremap(mmio_base
, 0x00a00000);
1465 sfb
->lfb
= sfb
->dp_regs
+ 0x00200000;
1466 sfb
->mmio
= (smtc_regbaseaddress
=
1467 sfb
->dp_regs
+ 0x000c0000);
1468 sfb
->vp_regs
= sfb
->dp_regs
+ 0x800;
1470 smtc_seqw(0x62, 0xff);
1471 smtc_seqw(0x6a, 0x0d);
1472 smtc_seqw(0x6b, 0x02);
1476 "No valid Silicon Motion display chip was detected!\n");
1481 /* can support 32 bpp */
1482 if (15 == sfb
->fb
->var
.bits_per_pixel
)
1483 sfb
->fb
->var
.bits_per_pixel
= 16;
1485 sfb
->fb
->var
.xres_virtual
= sfb
->fb
->var
.xres
;
1486 sfb
->fb
->var
.yres_virtual
= sfb
->fb
->var
.yres
;
1487 err
= smtc_map_smem(sfb
, pdev
, smem_size
);
1491 smtcfb_setmode(sfb
);
1493 err
= register_framebuffer(info
);
1497 dev_info(&pdev
->dev
,
1498 "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.\n",
1499 sfb
->chip_id
, sfb
->chip_rev_id
, sfb
->fb
->var
.xres
,
1500 sfb
->fb
->var
.yres
, sfb
->fb
->var
.bits_per_pixel
);
1505 dev_err(&pdev
->dev
, "Silicon Motion, Inc. primary display init fail.\n");
1507 smtc_unmap_smem(sfb
);
1508 smtc_unmap_mmio(sfb
);
1510 framebuffer_release(info
);
1513 pci_release_region(pdev
, 0);
1516 pci_disable_device(pdev
);
1524 * 0x720 (Lynx3DM, Lynx3DM+)
1526 static const struct pci_device_id smtcfb_pci_table
[] = {
1527 { PCI_DEVICE(0x126f, 0x710), },
1528 { PCI_DEVICE(0x126f, 0x712), },
1529 { PCI_DEVICE(0x126f, 0x720), },
1533 MODULE_DEVICE_TABLE(pci
, smtcfb_pci_table
);
1535 static void smtcfb_pci_remove(struct pci_dev
*pdev
)
1537 struct smtcfb_info
*sfb
;
1539 sfb
= pci_get_drvdata(pdev
);
1540 smtc_unmap_smem(sfb
);
1541 smtc_unmap_mmio(sfb
);
1542 unregister_framebuffer(sfb
->fb
);
1543 framebuffer_release(sfb
->fb
);
1544 pci_release_region(pdev
, 0);
1545 pci_disable_device(pdev
);
1549 static int smtcfb_pci_suspend(struct device
*device
)
1551 struct pci_dev
*pdev
= to_pci_dev(device
);
1552 struct smtcfb_info
*sfb
;
1554 sfb
= pci_get_drvdata(pdev
);
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
1559 smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0));
1560 smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7));
1563 fb_set_suspend(sfb
->fb
, 1);
1566 /* additionally turn off all function blocks including internal PLLs */
1567 smtc_seqw(0x21, 0xff);
1572 static int smtcfb_pci_resume(struct device
*device
)
1574 struct pci_dev
*pdev
= to_pci_dev(device
);
1575 struct smtcfb_info
*sfb
;
1577 sfb
= pci_get_drvdata(pdev
);
1579 /* reinit hardware */
1581 switch (sfb
->chip_id
) {
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);
1590 if (sfb
->fb
->var
.bits_per_pixel
== 32)
1594 smtc_seqw(0x62, 0xff);
1595 smtc_seqw(0x6a, 0x0d);
1596 smtc_seqw(0x6b, 0x02);
1600 smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0));
1601 smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb));
1603 smtcfb_setmode(sfb
);
1606 fb_set_suspend(sfb
->fb
, 0);
1612 static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops
, smtcfb_pci_suspend
, smtcfb_pci_resume
);
1613 #define SM7XX_PM_OPS (&sm7xx_pm_ops)
1615 #else /* !CONFIG_PM */
1617 #define SM7XX_PM_OPS NULL
1619 #endif /* !CONFIG_PM */
1621 static struct pci_driver smtcfb_driver
= {
1623 .id_table
= smtcfb_pci_table
,
1624 .probe
= smtcfb_pci_probe
,
1625 .remove
= smtcfb_pci_remove
,
1626 .driver
.pm
= SM7XX_PM_OPS
,
1629 static int __init
sm712fb_init(void)
1631 char *option
= NULL
;
1633 if (fb_get_options("sm712fb", &option
))
1635 if (option
&& *option
)
1636 mode_option
= option
;
1637 sm7xx_vga_setup(mode_option
);
1639 return pci_register_driver(&smtcfb_driver
);
1642 module_init(sm712fb_init
);
1644 static void __exit
sm712fb_exit(void)
1646 pci_unregister_driver(&smtcfb_driver
);
1649 module_exit(sm712fb_exit
);
1651 MODULE_AUTHOR("Siliconmotion ");
1652 MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
1653 MODULE_LICENSE("GPL");