leon: R.I.P.
[openwrt.git] / target / linux / coldfire / patches / 038-Add-PCI-Framebuffer-support-for-Silicon-Motion-s-Lyn.patch
1 From d984818481320cf4a1b44cefbc99448205cc7673 Mon Sep 17 00:00:00 2001
2 From: Jingchang Lu <b35083@freescale.com>
3 Date: Thu, 4 Aug 2011 09:59:48 +0800
4 Subject: [PATCH 38/52] Add PCI Framebuffer support for Silicon Motion's Lynx family
5
6 The driver may support SM710, SM712, SM720, and the SM712
7 has been tested on ColdFire M547X_8XEVB.
8
9 Signed-off-by: Alison Wang <b18965@freescale.com>
10 Signed-off-by: Jingchang Lu <b35083@freescale.com>
11 ---
12  drivers/video/Kconfig           |   15 +
13  drivers/video/Makefile          |    1 +
14  drivers/video/console/bitblit.c |   12 +
15  drivers/video/console/fbcon.c   |    4 +
16  drivers/video/fbmem.c           |    2 +-
17  drivers/video/smifb.c           |  963 +++++++++++++++++++++++++++++++++++++++
18  drivers/video/smifb.h           |  150 ++++++
19  include/linux/fb.h              |   18 +-
20  8 files changed, 1163 insertions(+), 2 deletions(-)
21  create mode 100644 drivers/video/smifb.c
22  create mode 100644 drivers/video/smifb.h
23
24 --- a/drivers/video/Kconfig
25 +++ b/drivers/video/Kconfig
26 @@ -204,6 +204,7 @@ config FB_WMT_GE_ROPS
27  config FB_DEFERRED_IO
28         bool
29         depends on FB
30 +       default y
31  
32  config FB_HECUBA
33         tristate
34 @@ -262,6 +263,20 @@ config FB_TILEBLITTING
35  comment "Frame buffer hardware drivers"
36         depends on FB
37  
38 +config FB_SMI
39 +       tristate "Silicon Motion Lynx support"
40 +       depends on FB && PCI
41 +       select FB_CFB_FILLRECT
42 +       select FB_CFB_COPYAREA
43 +       select FB_CFB_IMAGEBLIT
44 +       ---help---
45 +         This enables support for the Silicon Motion Lynx family of graphic
46 +         chips.
47 +
48 +         The SM712 has been tested on ColdFire M547X_8Xevb.
49 +
50 +         If unsure, say N.
51 +
52  config FB_CIRRUS
53         tristate "Cirrus Logic support"
54         depends on FB && (ZORRO || PCI)
55 --- a/drivers/video/Makefile
56 +++ b/drivers/video/Makefile
57 @@ -29,6 +29,7 @@ obj-$(CONFIG_FB_DEFERRED_IO)   += fb_def
58  obj-$(CONFIG_FB_WMT_GE_ROPS)   += wmt_ge_rops.o
59  
60  # Hardware specific drivers go first
61 +obj-$(CONFIG_FB_SMI)              += smifb.o
62  obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p_planar.o
63  obj-$(CONFIG_FB_ARC)              += arcfb.o
64  obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
65 --- a/drivers/video/console/bitblit.c
66 +++ b/drivers/video/console/bitblit.c
67 @@ -79,7 +79,11 @@ static inline void bit_putcs_aligned(str
68                                      u32 d_pitch, u32 s_pitch, u32 cellsize,
69                                      struct fb_image *image, u8 *buf, u8 *dst)
70  {
71 +#ifndef CONFIG_COLDFIRE
72         u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
73 +#else
74 +       u32 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
75 +#endif
76         u32 idx = vc->vc_font.width >> 3;
77         u8 *src;
78  
79 @@ -112,7 +116,11 @@ static inline void bit_putcs_unaligned(s
80                                        struct fb_image *image, u8 *buf,
81                                        u8 *dst)
82  {
83 +#ifndef CONFIG_COLDFIRE
84         u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
85 +#else
86 +       u32 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
87 +#endif
88         u32 shift_low = 0, mod = vc->vc_font.width % 8;
89         u32 shift_high = 8;
90         u32 idx = vc->vc_font.width >> 3;
91 @@ -239,7 +247,11 @@ static void bit_cursor(struct vc_data *v
92  {
93         struct fb_cursor cursor;
94         struct fbcon_ops *ops = info->fbcon_par;
95 +#ifndef CONFIG_COLDFIRE
96         unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
97 +#else
98 +       unsigned long charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
99 +#endif
100         int w = DIV_ROUND_UP(vc->vc_font.width, 8), c;
101         int y = real_y(ops->p, vc->vc_y);
102         int attribute, use_sw = (vc->vc_cursor_type & 0x10);
103 --- a/drivers/video/console/fbcon.c
104 +++ b/drivers/video/console/fbcon.c
105 @@ -2636,7 +2636,11 @@ static int fbcon_set_palette(struct vc_d
106  {
107         struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
108         int i, j, k, depth;
109 +#ifndef CONFIG_COLDFIRE
110         u8 val;
111 +#else
112 +       u32 val;
113 +#endif
114  
115         if (fbcon_is_inactive(vc, info))
116                 return -EINVAL;
117 --- a/drivers/video/fbmem.c
118 +++ b/drivers/video/fbmem.c
119 @@ -1433,7 +1433,7 @@ static int fb_check_foreignness(struct f
120  
121         fi->flags &= ~FBINFO_FOREIGN_ENDIAN;
122  
123 -#ifdef __BIG_ENDIAN
124 +#if defined(__BIG_ENDIAN) && !defined(CONFIG_COLDFIRE)
125         fi->flags |= foreign_endian ? 0 : FBINFO_BE_MATH;
126  #else
127         fi->flags |= foreign_endian ? FBINFO_BE_MATH : 0;
128 --- /dev/null
129 +++ b/drivers/video/smifb.c
130 @@ -0,0 +1,963 @@
131 +/***************************************************************************
132 +       smifb.c  -  Silicon Motion, Inc. LynxEM+ frame buffer device
133 +                       -------------------
134 +    begin                : Thu Aug 9 2001
135 +    copyright            : (C) 2001 by Szu-Tao Huang
136 +    email                : johuang@siliconmotion.com
137 + ***************************************************************************/
138 +/* Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.*/
139 +/***************************************************************************
140 + *                                                                         *
141 + *   This program is free software; you can redistribute it and/or modify  *
142 + *   it under the terms of the GNU General Public License as published by  *
143 + *   the Free Software Foundation; either version 2 of the License, or     *
144 + *   (at your option) any later version.                                   *
145 + *                                                                         *
146 + ***************************************************************************/
147 +
148 +#include <linux/module.h>
149 +#include <linux/kernel.h>
150 +#include <linux/errno.h>
151 +#include <linux/string.h>
152 +#include <linux/mm.h>
153 +#include <linux/tty.h>
154 +#include <linux/slab.h>
155 +#include <linux/delay.h>
156 +#include <linux/fb.h>
157 +#include <linux/pci.h>
158 +#include <linux/init.h>
159 +
160 +#include <linux/io.h>
161 +#include <asm/irq.h>
162 +#include <asm/pgtable.h>
163 +#include <asm/system.h>
164 +#include <linux/uaccess.h>
165 +
166 +#include "console/fbcon.h"
167 +
168 +/*
169 +#include <video/fbcon.h>
170 +#include <video/fbcon-cfb8.h>
171 +#include <video/fbcon-cfb16.h>
172 +#include <video/fbcon-cfb24.h>
173 +*/
174 +
175 +#include <linux/fb.h>
176 +/*point to virtual Memory Map IO starting address*/
177 +static char *SMIRegs;
178 +/*point to virtual video memory starting address*/
179 +static char *SMILFB;
180 +/*used to record hardware information*/
181 +static struct par_info hw;
182 +#ifdef DEBUG_FB
183 +#define debug_printk(x...) printk(x)
184 +#else
185 +#define debug_printk(x...)
186 +#endif
187 +#include "smifb.h"
188 +
189 +struct ModeInit VGAMode[numVGAModes] = {
190 +       {
191 +               /*  mode#0: 640 x 480  8Bpp  60Hz */
192 +               640, 480, 8, 60,
193 +               /*  Init_MISC */
194 +               0xE3,
195 +               {   /*  Init_SR0_SR4 */
196 +                       0x03, 0x01, 0x0F, 0x00, 0x0E,
197 +               },
198 +               {   /*  Init_SR10_SR24 */
199 +                       0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
200 +                       0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 +                       0xC4, 0x30, 0x02, 0x01, 0x01,
202 +               },
203 +               {   /*  Init_SR30_SR75 */
204 +                       0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
205 +                       0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
206 +                       0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
207 +                       0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
208 +                       0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
209 +                       0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
210 +                       0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
211 +                       0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
212 +                       0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
213 +               },
214 +               {   /*  Init_SR80_SR93 */
215 +                       0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
216 +                       0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
217 +                       0x00, 0x00, 0x00, 0x00,
218 +               },
219 +               {   /*  Init_SRA0_SRAF */
220 +                       0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
221 +                       0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
222 +               },
223 +               {   /*  Init_GR00_GR08 */
224 +                       0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
225 +                       0xFF,
226 +               },
227 +               {   /*  Init_AR00_AR14 */
228 +                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
229 +                       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
230 +                       0x41, 0x00, 0x0F, 0x00, 0x00,
231 +               },
232 +               {   /*  Init_CR00_CR18 */
233 +                       0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
234 +                       0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 +                       0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
236 +                       0xFF,
237 +               },
238 +               {   /*  Init_CR30_CR4D */
239 +                       0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
240 +                       0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
241 +                       0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
242 +                       0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
243 +               },
244 +               {   /*  Init_CR90_CRA7 */
245 +                       0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
246 +                       0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
247 +                       0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
248 +               },
249 +       },
250 +       {
251 +               /*  mode#1: 640 x 480  16Bpp  60Hz */
252 +               640, 480, 16, 60,
253 +               /*  Init_MISC */
254 +               0xE3,
255 +               {   /*  Init_SR0_SR4 */
256 +                       0x03, 0x01, 0x0F, 0x00, 0x0E,
257 +               },
258 +               {   /*  Init_SR10_SR24 */
259 +                       0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
260 +                       0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261 +                       0xC4, 0x30, 0x02, 0x01, 0x01,
262 +               },
263 +               {   /*  Init_SR30_SR75 */
264 +                       0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
265 +                       0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
266 +                       0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
267 +                       0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
268 +                       0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
269 +                       0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
270 +                       0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
271 +                       0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
272 +                       0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
273 +               },
274 +               {   /*  Init_SR80_SR93 */
275 +                       0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
276 +                       0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
277 +                       0x00, 0x00, 0x00, 0x00,
278 +               },
279 +               {   /*  Init_SRA0_SRAF */
280 +                       0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
281 +                       0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
282 +               },
283 +               {   /*  Init_GR00_GR08 */
284 +                       0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
285 +                       0xFF,
286 +               },
287 +               {   /*  Init_AR00_AR14 */
288 +                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
289 +                       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
290 +                       0x41, 0x00, 0x0F, 0x00, 0x00,
291 +               },
292 +               {   /*  Init_CR00_CR18 */
293 +                       0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
294 +                       0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 +                       0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
296 +                       0xFF,
297 +               },
298 +               {   /*  Init_CR30_CR4D */
299 +                       0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
300 +                       0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
301 +                       0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
302 +                       0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
303 +               },
304 +               {   /*  Init_CR90_CRA7 */
305 +                       0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
306 +                       0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
307 +                       0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
308 +               },
309 +       },
310 +       {
311 +               /*  mode#2: 640 x 480  24Bpp  60Hz */
312 +               640, 480, 24, 60,
313 +               /*  Init_MISC */
314 +               0xE3,
315 +               {   /*  Init_SR0_SR4 */
316 +                       0x03, 0x01, 0x0F, 0x00, 0x0E,
317 +               },
318 +               {   /*  Init_SR10_SR24 */
319 +                       0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
320 +                       0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 +                       0xC4, 0x30, 0x02, 0x01, 0x01,
322 +               },
323 +               {   /*  Init_SR30_SR75 */
324 +                       0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
325 +                       0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
326 +                       0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
327 +                       0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
328 +                       0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
329 +                       0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
330 +                       0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
331 +                       0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
332 +                       0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
333 +               },
334 +               {   /*  Init_SR80_SR93 */
335 +                       0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
336 +                       0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
337 +                       0x00, 0x00, 0x00, 0x00,
338 +               },
339 +               {   /*  Init_SRA0_SRAF */
340 +                       0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
341 +                       0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
342 +               },
343 +               {   /*  Init_GR00_GR08 */
344 +                       0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
345 +                       0xFF,
346 +               },
347 +               {   /*  Init_AR00_AR14 */
348 +                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
349 +                       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
350 +                       0x41, 0x00, 0x0F, 0x00, 0x00,
351 +               },
352 +               {   /*  Init_CR00_CR18 */
353 +                       0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
354 +                       0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355 +                       0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
356 +                       0xFF,
357 +               },
358 +               {   /*  Init_CR30_CR4D */
359 +                       0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
360 +                       0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
361 +                       0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
362 +                       0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
363 +               },
364 +               {   /*  Init_CR90_CRA7 */
365 +                       0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
366 +                       0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
367 +                       0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
368 +               },
369 +       },
370 +       {/*  mode#3: 800 x 600  8Bpp  60Hz */
371 +               800, 600, 8, 60,
372 +               0x2B,   /*  Init_MISC */
373 +               {       /*  Init_SR0_SR4 */
374 +                       0x03, 0x01, 0x0F, 0x03, 0x0E,
375 +               },
376 +               {   /*  Init_SR10_SR24 */
377 +                       0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
378 +                       0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
379 +                       0xC4, 0x30, 0x02, 0x01, 0x01,
380 +               },
381 +               {   /*  Init_SR30_SR75 */
382 +                       0x24, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
383 +                       0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
384 +                       0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
385 +                       0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
386 +                       0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
387 +                       0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
388 +                       0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
389 +                       0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
390 +                       0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
391 +               },
392 +               {   /*  Init_SR80_SR93 */
393 +                       0xFF, 0x87, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
394 +                       0x90, 0x01, 0x2C, 0x01, 0xFF, 0x00, 0x24, 0x24,
395 +                       0x00, 0x00, 0x00, 0x00,
396 +               },
397 +               {   /*  Init_SRA0_SRAF */
398 +                       0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
399 +                       0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
400 +               },
401 +               {   /*  Init_GR00_GR08 */
402 +                       0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
403 +                       0xFF,
404 +               },
405 +               {   /*  Init_AR00_AR14 */
406 +                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
407 +                       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
408 +                       0x41, 0x00, 0x0F, 0x00, 0x00,
409 +               },
410 +               {   /*  Init_CR00_CR18 */
411 +                       0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
412 +                       0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413 +                       0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
414 +                       0xFF,
415 +               },
416 +               {   /*  Init_CR30_CR4D */
417 +                       0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
418 +                       0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
419 +                       0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
420 +                       0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
421 +               },
422 +               {   /*  Init_CR90_CRA7 */
423 +                       0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
424 +                       0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
425 +                       0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
426 +               },
427 +       },
428 +       {/*  mode#4: 800 x 600  16Bpp  60Hz */
429 +               800, 600, 16, 60,
430 +               /*  Init_MISC */
431 +               0x2B,
432 +               {   /*  Init_SR0_SR4 */
433 +                       0x03, 0x01, 0x0F, 0x03, 0x0E,
434 +               },
435 +               {   /*  Init_SR10_SR24 */
436 +                       0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
437 +                       0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
438 +                       0xC4, 0x30, 0x02, 0x01, 0x01,
439 +               },
440 +               {   /*  Init_SR30_SR75 */
441 +                       0x24, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
442 +                       0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
443 +                       0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
444 +                       0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
445 +                       0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
446 +                       0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
447 +                       0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
448 +                       0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
449 +                       0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
450 +               },
451 +               {   /*  Init_SR80_SR93 */
452 +                       0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
453 +                       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
454 +                       0x00, 0x00, 0x00, 0x00,
455 +               },
456 +               {   /*  Init_SRA0_SRAF */
457 +                       0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
458 +                       0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
459 +               },
460 +               {   /*  Init_GR00_GR08 */
461 +                       0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
462 +                       0xFF,
463 +               },
464 +               {   /*  Init_AR00_AR14 */
465 +                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
466 +                       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
467 +                       0x41, 0x00, 0x0F, 0x00, 0x00,
468 +               },
469 +               {   /*  Init_CR00_CR18 */
470 +                       0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
471 +                       0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 +                       0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
473 +                       0xFF,
474 +               },
475 +               {   /*  Init_CR30_CR4D */
476 +                       0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
477 +                       0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
478 +                       0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
479 +                       0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
480 +               },
481 +               {   /*  Init_CR90_CRA7 */
482 +                       0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
483 +                       0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
484 +                       0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
485 +               },
486 +       },
487 +               {/*  mode#5: 800 x 600  24Bpp  60Hz */
488 +               800, 600, 24, 60,
489 +               0x2B,
490 +               {   /*  Init_SR0_SR4 */
491 +                       0x03, 0x01, 0x0F, 0x03, 0x0E,
492 +               },
493 +               {   /*  Init_SR10_SR24 */
494 +                       0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
495 +                       0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
496 +                       0xC4, 0x30, 0x02, 0x01, 0x01,
497 +               },
498 +               {   /*  Init_SR30_SR75 */
499 +                       0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
500 +                       0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
501 +                       0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
502 +                       0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
503 +                       0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
504 +                       0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
505 +                       0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
506 +                       0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
507 +                       0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
508 +               },
509 +               {   /*  Init_SR80_SR93 */
510 +                       0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
511 +                       0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
512 +                       0x00, 0x00, 0x00, 0x00,
513 +               },
514 +               {   /*  Init_SRA0_SRAF */
515 +                       0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
516 +                       0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
517 +               },
518 +               {   /*  Init_GR00_GR08 */
519 +                       0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
520 +                       0xFF,
521 +               },
522 +               {   /*  Init_AR00_AR14 */
523 +                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
524 +                       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
525 +                       0x41, 0x00, 0x0F, 0x00, 0x00,
526 +               },
527 +               {   /*  Init_CR00_CR18 */
528 +                       0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
529 +                       0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 +                       0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
531 +                       0xFF,
532 +               },
533 +               {   /*  Init_CR30_CR4D */
534 +                       0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
535 +                       0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
536 +                       0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
537 +                       0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
538 +               },
539 +               {   /*  Init_CR90_CRA7 */
540 +                       0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
541 +                       0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
542 +                       0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
543 +               },
544 +       },
545 +};
546 +
547 +static void smi_set_timing(struct smifb_info *sfb, struct par_info *hw)
548 +{
549 +       int i = 0, j = 0;
550 +       u32 m_nScreenStride;
551 +       debug_printk("set timing:hw->width %x,hw->height %x,bpp %x\n",
552 +                       hw->width, hw->height, sfb->fb.var.bits_per_pixel);
553 +
554 +       for (j = 0; j < numVGAModes; j++) {
555 +               if (VGAMode[j].mmSizeX == hw->width &&
556 +                       VGAMode[j].mmSizeY == hw->height &&
557 +                       VGAMode[j].bpp == sfb->fb.var.bits_per_pixel &&
558 +                       VGAMode[j].hz == hw->hz) {
559 +                       debug_printk("VGAMode[%d]\n", j);
560 +                       smi_mmiowb(0x0, 0x3c6);
561 +
562 +                       smi_seqw(0, 0x1);
563 +
564 +                       smi_mmiowb(VGAMode[j].Init_MISC, 0x3c2);
565 +
566 +                       for (i = 0; i < SIZE_SR00_SR04; i++) {
567 +                               /* init SEQ register SR00 - SR04 */
568 +                               smi_seqw(i,
569 +                                       VGAMode[j].Init_SR00_SR04[i]);
570 +                       }
571 +
572 +                       for (i = 0; i < SIZE_SR10_SR24; i++) {
573 +                               /* init SEQ register SR10 - SR24*/
574 +                               smi_seqw(i + 0x10,
575 +                                       VGAMode[j].Init_SR10_SR24[i]);
576 +                       }
577 +
578 +                       for (i = 0; i < SIZE_SR30_SR75; i++) {
579 +                               /* init SEQ register SR30 - SR75*/
580 +                               if (((i + 0x30) != 0x62) &&
581 +                                       ((i + 0x30) != 0x6a) &&
582 +                                       ((i + 0x30) != 0x6b))
583 +                                       smi_seqw(i + 0x30,
584 +                                               VGAMode[j].Init_SR30_SR75[i]);
585 +                       }
586 +                       for (i = 0; i < SIZE_SR80_SR93; i++) {
587 +                               /* init SEQ register SR80 - SR93*/
588 +                               smi_seqw(i + 0x80,
589 +                                       VGAMode[j].Init_SR80_SR93[i]);
590 +                       }
591 +                       for (i = 0; i < SIZE_SRA0_SRAF; i++) {
592 +                               /* init SEQ register SRA0 - SRAF */
593 +                               smi_seqw(i + 0xa0,
594 +                                       VGAMode[j].Init_SRA0_SRAF[i]);
595 +                       }
596 +
597 +                       for (i = 0; i < SIZE_GR00_GR08; i++) {
598 +                               /* init Graphic register GR00 - GR08*/
599 +                               smi_grphw(i,
600 +                                       VGAMode[j].Init_GR00_GR08[i]);
601 +                       }
602 +
603 +                       for (i = 0; i < SIZE_AR00_AR14; i++) {
604 +                               /* init Attribute register AR00 - AR14*/
605 +                               smi_attrw(i,
606 +                                       VGAMode[j].Init_AR00_AR14[i]);
607 +                       }
608 +
609 +                       for (i = 0; i < SIZE_CR00_CR18; i++) {
610 +                               /* init CRTC register CR00 - CR18 */
611 +                               smi_crtcw(i,
612 +                                       VGAMode[j].Init_CR00_CR18[i]);
613 +                       }
614 +
615 +                       for (i = 0; i < SIZE_CR30_CR4D; i++) {
616 +                               /* init CRTC register CR30 - CR4D*/
617 +                               smi_crtcw(i + 0x30,
618 +                                       VGAMode[j].Init_CR30_CR4D[i]);
619 +                       }
620 +
621 +                       for (i = 0; i < SIZE_CR90_CRA7; i++) {
622 +                               /*init CRTC register CR90 - CRA7*/
623 +                               smi_crtcw(i + 0x90,
624 +                                       VGAMode[j].Init_CR90_CRA7[i]);
625 +                       }
626 +               }
627 +       }
628 +       smi_mmiowb(0x67, 0x3c2);
629 +       /* set VPR registers */
630 +       writel(0x0, hw->m_pVPR+0x0C);
631 +       writel(0x0, hw->m_pVPR+0x40);
632 +       /* set data width */
633 +       m_nScreenStride = (hw->width * sfb->fb.var.bits_per_pixel) / 64;
634 +       switch (sfb->fb.var.bits_per_pixel) {
635 +       case 8:
636 +               writel(0x0, hw->m_pVPR+0x0);
637 +               break;
638 +       case 16:
639 +               writel(0x00020000, hw->m_pVPR+0x0);
640 +               break;
641 +       case 24:
642 +               writel(0x00040000, hw->m_pVPR+0x0);
643 +               break;
644 +       }
645 +       writel((u32)(((m_nScreenStride + 2) << 16) |
646 +                       m_nScreenStride), hw->m_pVPR+0x10);
647 +}
648 +
649 +/*
650 + * Set the color palette
651 + */
652 +static int
653 +smifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
654 +                  u_int trans, struct fb_info *info)
655 +{
656 +       struct smifb_info *sfb = (struct smifb_info *)info;
657 +       u32 *pal;
658 +
659 +       switch (sfb->fb.fix.visual) {
660 +       case FB_VISUAL_TRUECOLOR:               /* RGB 5:6:5 True Colour */
661 +               pal = sfb->fb.pseudo_palette;
662 +               /* System has 16 default color */
663 +               if (regno >= 16)
664 +                       return 1;
665 +
666 +               pal[regno] = (red & 0xf800) |
667 +                   ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
668 +               break;
669 +       }
670 +
671 +       return 0;
672 +}
673 +
674 +/*
675 + *  smifb_decode_var():
676 + *    Get the video params out of 'var'. If a value doesn't fit, round it up,
677 + *    if it's too big, return -EINVAL.
678 + *
679 + *    Suggestion: Round up in the following order: bits_per_pixel, xres,
680 + *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
681 + *    bitfields, horizontal timing, vertical timing.
682 + */
683 +static int smifb_decode_var(struct fb_var_screeninfo *var,
684 +               struct smifb_info *sfb, struct par_info *hw)
685 +{
686 +       hw->width = var->xres;
687 +       hw->height = var->yres;
688 +       hw->hz = 60;
689 +
690 +       return 0;
691 +}
692 +
693 +static int smifb_set_par(struct fb_info *info)
694 +{
695 +       struct smifb_info *sfb = (struct smifb_info *)info;
696 +       int err, chgvar = 0;
697 +       struct fb_var_screeninfo *var = &info->var;
698 +       struct fb_cmap *cmap;
699 +
700 +
701 +       /*
702 +        * Decode var contents into a par structure, adjusting any
703 +        * out of range values.
704 +        */
705 +       err = smifb_decode_var(var, sfb, &hw);
706 +       if (err)
707 +               return err;
708 +
709 +       if (hw.width != var->xres)
710 +               chgvar = 1;
711 +       if (hw.height != var->yres)
712 +               chgvar = 1;
713 +
714 +       var->activate           &= ~FB_ACTIVATE_ALL;
715 +
716 +       smi_set_timing(sfb, &hw);
717 +
718 +       sfb->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
719 +       cmap = (struct fb_cmap *)fb_default_cmap(sfb->palette_size);
720 +       fb_set_cmap(cmap, &sfb->fb);
721 +
722 +       return 0;
723 +}
724 +
725 +static int smifb_check_var(struct fb_var_screeninfo *var,
726 +                               struct fb_info *info)
727 +{
728 +       var->bits_per_pixel += 7;
729 +       var->bits_per_pixel &= ~7;
730 +
731 +       var->xres_virtual =
732 +           var->xres_virtual < var->xres ? var->xres : var->xres_virtual;
733 +       var->yres_virtual =
734 +           var->yres_virtual < var->yres ? var->yres : var->yres_virtual;
735 +       debug_printk("var->bits_per_pixel %x\n", var->bits_per_pixel);
736 +       switch (var->bits_per_pixel) {
737 +       case 8:
738 +       case 16:                /* RGB 565 */
739 +       case 24:
740 +               break;
741 +       default:
742 +               return -EINVAL;
743 +       }
744 +
745 +       switch (var->bits_per_pixel) {
746 +       case 16:
747 +               var->red.offset = 11;
748 +               var->red.length = 5;
749 +               var->green.offset       = 5;
750 +               var->green.length       = 6;
751 +               var->blue.offset        = 0;
752 +               var->blue.length        = 5;
753 +
754 +               info->fix.visual        = FB_VISUAL_TRUECOLOR;
755 +               info->fix.line_length = var->xres * 2;
756 +
757 +               break;
758 +       default:
759 +               return -EINVAL;
760 +               /* We don't support anything other than 16bpp for now. --NL */
761 +               break;
762 +       }
763 +       return 0;
764 +
765 +       /*smifb_set_color_bitfields(var);*/
766 +
767 +       return 0;
768 +}
769 +
770 +/*
771 + * Formal definition of the VESA spec:
772 + *  On
773 + *     This refers to the state of the display when it is in full operation
774 + *  Stand-By
775 + *     This defines an optional operating state of minimal power reduction with
776 + *     the shortest recovery time
777 + *  Suspend
778 + *     This refers to a level of power management in which substantial power
779 + *     reduction is achieved by the display.  The display can have a longer
780 + *     recovery time from this state than from the Stand-by state
781 + *  Off
782 + *     This indicates that the display is consuming the lowest level of power
783 + *     and is non-operational. Recovery from this state may optionally require
784 + *     the user to manually power on the monitor
785 + *
786 + *  Now, the fbdev driver adds an additional state, (blank), where they
787 + *  turn off the video (maybe by colormap tricks), but don't mess with the
788 + *  video itself: think of it semantically between on and Stand-By.
789 + *
790 + *  So here's what we should do in our fbdev blank routine:
791 + *
792 + *     VESA_NO_BLANKING (mode 0)       Video on,  front/back light on
793 + *     VESA_VSYNC_SUSPEND (mode 1)     Video on,  front/back light off
794 + *     VESA_HSYNC_SUSPEND (mode 2)     Video on,  front/back light off
795 + *     VESA_POWERDOWN (mode 3)         Video off, front/back light off
796 + *
797 + *  This will match the matrox implementation.
798 + */
799 +/*
800 + * smifb_blank():
801 + *     Blank the display by setting all palette values to zero.  Note, the
802 + *     12 and 16 bpp modes don't really use the palette, so this will not
803 + *     blank the display in all modes.
804 + */
805 +static int smifb_blank(int blank, struct fb_info *info)
806 +{
807 +/* struct smifb_info *sfb = (struct smifb_info *)info; */
808 +#if 0
809 +       switch (blank) {
810 +       case VESA_POWERDOWN:
811 +       case VESA_VSYNC_SUSPEND:
812 +       case VESA_HSYNC_SUSPEND:
813 +       case VESA_NO_BLANKING:
814 +       }
815 +#endif
816 +       return 1;
817 +}
818 +
819 +static struct fb_ops smifb_ops = {
820 +       .owner          = THIS_MODULE,
821 +       .fb_check_var   = smifb_check_var,
822 +       .fb_set_par     = smifb_set_par,
823 +       .fb_setcolreg   = smifb_setcolreg,
824 +       .fb_blank       = smifb_blank,
825 +
826 +       /* Accelerated functions, using softversions, per se */
827 +       .fb_fillrect    = cfb_fillrect,
828 +       .fb_copyarea    = cfb_copyarea,
829 +       .fb_imageblit   = cfb_imageblit,
830 +       .fb_cursor      = soft_cursor,
831 +};
832 +
833 +/*
834 + * Alloc struct smifb_info and assign the default value
835 + */
836 +static struct smifb_info * __devinit
837 +smi_alloc_fb_info(struct pci_dev *dev, char *name)
838 +{
839 +       struct smifb_info *sfb;
840 +
841 +       sfb = kmalloc(sizeof(struct smifb_info) + sizeof(u32) * 16, GFP_KERNEL);
842 +
843 +       if (!sfb)
844 +               return NULL;
845 +
846 +       memset(sfb, 0, sizeof(struct smifb_info));
847 +
848 +       sfb->currcon        = -1;
849 +       sfb->dev            = dev;
850 +
851 +       strcpy(sfb->fb.fix.id, name);
852 +
853 +       sfb->fb.fix.type                = FB_TYPE_PACKED_PIXELS;
854 +       sfb->fb.fix.type_aux    = 0;
855 +       sfb->fb.fix.xpanstep    = 0;
856 +       sfb->fb.fix.ypanstep    = 0;
857 +       sfb->fb.fix.ywrapstep   = 0;
858 +       sfb->fb.fix.accel               = FB_ACCEL_NONE;
859 +
860 +       sfb->fb.var.nonstd              = 0;
861 +       sfb->fb.var.activate    = FB_ACTIVATE_NOW;
862 +       sfb->fb.var.height              = -1;
863 +       sfb->fb.var.width               = -1;
864 +       sfb->fb.var.accel_flags = 0;
865 +       sfb->fb.var.vmode               = FB_VMODE_NONINTERLACED;
866 +
867 +       sfb->fb.fbops           = &smifb_ops;
868 +       sfb->fb.flags           = FBINFO_FLAG_DEFAULT;
869 +       sfb->fb.node            = -1;
870 +       sfb->fb.pseudo_palette  = (void *)(&sfb->palette_size + 1);
871 +
872 +       return sfb;
873 +}
874 +
875 +/*
876 + * Unmap in the memory mapped IO registers
877 + *
878 + */
879 +
880 +static void __devinit
881 +smi_unmap_mmio(struct smifb_info *sfb)
882 +{
883 +       if (sfb && SMILFB) {
884 +               iounmap(SMILFB);
885 +               SMIRegs = NULL;
886 +       }
887 +}
888 +
889 +/*
890 + * Map in the screen memory
891 + *
892 + */
893 +static int __devinit
894 +smi_map_smem(struct smifb_info *sfb, struct pci_dev *dev, u_long smem_len)
895 +{
896 +       sfb->fb.fix.smem_start = pci_resource_start(dev, 0);
897 +       sfb->fb.fix.smem_len  = smem_len;
898 +
899 +       debug_printk("%s:smem %x,len %x\n", __func__,
900 +               sfb->fb.fix.smem_start,
901 +               sfb->fb.fix.smem_len);
902 +
903 +       sfb->fb.screen_base = SMILFB;
904 +
905 +       if (!sfb->fb.screen_base) {
906 +               printk("%s: unable to map screen memory\n", sfb->fb.fix.id);
907 +               return -ENOMEM;
908 +       }
909 +
910 +       return 0;
911 +}
912 +
913 +
914 +/*
915 + * Unmap in the screen memory
916 + *
917 + */
918 +static void __devinit
919 +smi_unmap_smem(struct smifb_info *sfb)
920 +{
921 +       if (sfb && sfb->fb.screen_base) {
922 +               iounmap(sfb->fb.screen_base);
923 +               sfb->fb.screen_base = NULL;
924 +       }
925 +}
926 +
927 +/*
928 + * We need to wake up the LynxEM+, and make sure its in linear memory mode.
929 + */
930 +static inline void __devinit
931 +smi_init_hw(void)
932 +{
933 +       /* The delays prevent the ColdFire PCI host from locking up. :/ --NL */
934 +       udelay(1000);
935 +       outb(0x18, 0x3c4);
936 +
937 +       udelay(1000);
938 +       outb(0x11, 0x3c5);
939 +       udelay(1000);
940 +
941 +       debug_printk("%s: 0x3c4 =%x 0x3c5 %x\n",
942 +                       __func__, inw(0x3c4), inw(0x3c5));
943 +}
944 +
945 +static void __devinit
946 +smi_free_fb_info(struct smifb_info *sfb)
947 +{
948 +       if (sfb) {
949 +               fb_alloc_cmap(&sfb->fb.cmap, 0, 0);
950 +               kfree(sfb);
951 +       }
952 +}
953 +
954 +
955 +u16 SMI_ChipIDs[numChipIDs] = {0x710, 0x712, 0x720};
956 +
957 +int __devinit smifb_init(struct pci_dev *pdev, const struct pci_device_id *ent)
958 +{
959 +       struct smifb_info *sfb;
960 +       unsigned long smem_size;
961 +       char name[16];
962 +       int err;
963 +       char *m_pLAW;
964 +       unsigned long m_pLAWPhysical;
965 +
966 +       debug_printk("%s start\n", __func__);
967 +       sprintf(name, "smifb");
968 +       hw.chipID = pdev->device;
969 +       err = -ENOMEM;
970 +       sfb = smi_alloc_fb_info(pdev, name);
971 +       if (!sfb)
972 +               goto failed;
973 +
974 +       smi_init_hw();
975 +
976 +       /* Map address and memory detection */
977 +       m_pLAWPhysical = pci_resource_start(pdev, 0);
978 +       printk(KERN_INFO "%s:Physical addr %x,hw.chipID %x\n",
979 +                       __func__, (unsigned int)m_pLAWPhysical,
980 +                       (unsigned int)hw.chipID);
981 +       switch (hw.chipID) {
982 +       case 0x710:
983 +       case 0x712:
984 +               sfb->fb.fix.mmio_start = m_pLAWPhysical + 0x00700000;
985 +               sfb->fb.fix.mmio_len   = 0x00100000;
986 +
987 +               hw.m_pLFB = SMILFB =
988 +                       ioremap(m_pLAWPhysical, 0x00800000);
989 +               debug_printk("%s:SMILFB%x\n", __func__, SMILFB);
990 +               hw.m_pMMIO = SMIRegs = SMILFB + 0x00700000;
991 +               hw.m_pDPR = hw.m_pLFB + 0x00408000;
992 +               hw.m_pVPR = hw.m_pLFB + 0x0040c000;
993 +
994 +               if (!SMIRegs) {
995 +                       printk(KERN_ERR "%s: unable to map "
996 +                               "memory mapped IO\n", sfb->fb.fix.id);
997 +                       return -ENOMEM;
998 +               }
999 +
1000 +               smi_seqw(0x62, 0x7A);
1001 +               smi_seqw(0x6a, 0x0c);
1002 +               smi_seqw(0x6b, 0x02);
1003 +               smem_size = 0x00400000;
1004 +
1005 +               /* LynxEM+ memory dection */
1006 +               *(u32 *)(SMILFB + 4) = 0xAA551133;
1007 +               if (*(u32 *)(SMILFB + 4) != 0xAA551133) {
1008 +                       smem_size = 0x00200000;
1009 +                       /* Program the MCLK to 130 MHz */
1010 +                       smi_seqw(0x6a, 0x12);
1011 +                       smi_seqw(0x6b, 0x02);
1012 +                       smi_seqw(0x62, 0x3e);
1013 +               }
1014 +               break;
1015 +       case 0x720:
1016 +               sfb->fb.fix.mmio_start = m_pLAWPhysical + 0x000c0000;
1017 +               sfb->fb.fix.mmio_len   = 0x00040000;
1018 +
1019 +               m_pLAW = ioremap(m_pLAWPhysical, 0x00a00000);
1020 +               hw.m_pLFB = SMILFB = m_pLAW + 0x00200000;
1021 +               hw.m_pMMIO = SMIRegs = m_pLAW + 0x000c0000;
1022 +               hw.m_pDPR = m_pLAW;
1023 +               hw.m_pVPR = m_pLAW + 0x800;
1024 +
1025 +               smi_seqw(0x62, 0xff);
1026 +               smi_seqw(0x6a, 0x0d);
1027 +               smi_seqw(0x6b, 0x02);
1028 +               smem_size = 0x00400000;
1029 +
1030 +               break;
1031 +       }
1032 +
1033 +       sfb->fb.var.xres = 640;
1034 +       sfb->fb.var.yres = 480;
1035 +       sfb->fb.var.bits_per_pixel = 16;
1036 +
1037 +       sfb->fb.var.xres_virtual = sfb->fb.var.xres;
1038 +
1039 +       sfb->fb.var.yres_virtual = sfb->fb.var.yres;
1040 +
1041 +       sfb->fb.flags = FBINFO_FLAG_DEFAULT;
1042 +
1043 +       debug_printk("%s:smem_size %x\n", __func__, smem_size);
1044 +       err = smi_map_smem(sfb, pdev, smem_size);
1045 +       debug_printk("%s:smi_map_smem error %x\n", __func__, err);
1046 +       if (err)
1047 +               goto failed;
1048 +
1049 +       fb_set_var(&sfb->fb, &sfb->fb.var);
1050 +       smifb_check_var(&sfb->fb.var, &sfb->fb);
1051 +       smifb_set_par((struct fb_info *)sfb);
1052 +       debug_printk("%s:register_framebuffer\n", __func__);
1053 +       err = register_framebuffer(&sfb->fb);
1054 +       if (err < 0)
1055 +               goto failed;
1056 +
1057 +       printk(KERN_INFO "Silicon Motion, Inc. "
1058 +                       "LynxEM+ Init complete.\n");
1059 +       return 0;
1060 +
1061 +failed:
1062 +       smi_unmap_smem(sfb);
1063 +       smi_unmap_mmio(sfb);
1064 +       smi_free_fb_info(sfb);
1065 +       printk(KERN_INFO "Silicon Motion, Inc. "
1066 +                       "LynxEM+ Init FAILED.n");
1067 +
1068 +       return err;
1069 +}
1070 +
1071 +static DEFINE_PCI_DEVICE_TABLE(smifb_pci_tbl) = {
1072 +       { 0x126f, 0x710, PCI_ANY_ID, PCI_ANY_ID },
1073 +       { 0x126f, 0x712, PCI_ANY_ID, PCI_ANY_ID },
1074 +       { 0x126f, 0x720, PCI_ANY_ID, PCI_ANY_ID },
1075 +       { 0 }
1076 +};
1077 +
1078 +MODULE_DEVICE_TABLE(pci, smifb_pci_tbl);
1079 +
1080 +struct pci_driver smifb_driver = {
1081 +       .name =         "smifb",
1082 +       .id_table =     smifb_pci_tbl,
1083 +       .probe =        smifb_init,
1084 +};
1085 +
1086 +int __init smi_init(void)
1087 +{
1088 +       /*return pci_module_init(&smifb_driver);*/
1089 +       return pci_register_driver(&smifb_driver);
1090 +}
1091 +
1092 +module_init(smi_init);
1093 +MODULE_LICENSE("GPL");
1094 --- /dev/null
1095 +++ b/drivers/video/smifb.h
1096 @@ -0,0 +1,150 @@
1097 +/***************************************************************************
1098 +                       smifb.h  -  SiliconMotion LynxEM+ frame buffer device
1099 +                       -------------------
1100 +    begin                : Thu Aug 9 2001
1101 +    copyright            : (C) 2001 by Szu-Tao Huang
1102 +    email                : johuang@siliconmotion.com
1103 + ***************************************************************************/
1104 +/* Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.*/
1105 +/***************************************************************************
1106 + *                                                                         *
1107 + *   This program is free software; you can redistribute it and/or modify  *
1108 + *   it under the terms of the GNU General Public License as published by  *
1109 + *   the Free Software Foundation; either version 2 of the License, or     *
1110 + *   (at your option) any later version.                                   *
1111 + *                                                                         *
1112 + ***************************************************************************/
1113 +
1114 +#define smi_mmiowb(dat, reg)   writeb(dat, SMIRegs + reg)
1115 +#define smi_mmioww(dat, reg)   writew(dat, SMIRegs + reg)
1116 +#define smi_mmiowl(dat, reg)   writel(dat, SMIRegs + reg)
1117 +
1118 +#define smi_mmiorb(reg)                readb(SMIRegs + reg)
1119 +#define smi_mmiorw(reg)                readw(SMIRegs + reg)
1120 +#define smi_mmiorl(reg)                readl(SMIRegs + reg)
1121 +
1122 +#define SIZE_SR00_SR04      (0x04 - 0x00 + 1)
1123 +#define SIZE_SR10_SR24      (0x24 - 0x10 + 1)
1124 +#define SIZE_SR30_SR75      (0x75 - 0x30 + 1)
1125 +#define SIZE_SR80_SR93      (0x93 - 0x80 + 1)
1126 +#define SIZE_SRA0_SRAF      (0xAF - 0xA0 + 1)
1127 +#define SIZE_GR00_GR08      (0x08 - 0x00 + 1)
1128 +#define SIZE_AR00_AR14      (0x14 - 0x00 + 1)
1129 +#define SIZE_CR00_CR18      (0x18 - 0x00 + 1)
1130 +#define SIZE_CR30_CR4D      (0x4D - 0x30 + 1)
1131 +#define SIZE_CR90_CRA7      (0xA7 - 0x90 + 1)
1132 +#define SIZE_VPR                        (0x6C + 1)
1133 +#define SIZE_DPR                       (0x44 + 1)
1134 +
1135 +#define numVGAModes                    6
1136 +#define numChipIDs                     3
1137 +
1138 +#define NR_PALETTE     256
1139 +#define NR_RGB          2
1140 +
1141 +/*
1142 + * Minimum X and Y resolutions
1143 + */
1144 +#define MIN_XRES       640
1145 +#define MIN_YRES       480
1146 +
1147 +static inline void smi_crtcw(int reg, int val)
1148 +{
1149 +       smi_mmiowb(reg, 0x3d4);
1150 +       smi_mmiowb(val, 0x3d5);
1151 +}
1152 +
1153 +static inline unsigned int smi_crtcr(int reg)
1154 +{
1155 +       smi_mmiowb(reg, 0x3d4);
1156 +       return smi_mmiorb(0x3d5);
1157 +}
1158 +
1159 +static inline void smi_grphw(int reg, int val)
1160 +{
1161 +       smi_mmiowb(reg, 0x3ce);
1162 +       smi_mmiowb(val, 0x3cf);
1163 +}
1164 +
1165 +static inline unsigned int smi_grphr(int reg)
1166 +{
1167 +       smi_mmiowb(reg, 0x3ce);
1168 +       return smi_mmiorb(0x3cf);
1169 +}
1170 +
1171 +static inline void smi_attrw(int reg, int val)
1172 +{
1173 +       smi_mmiorb(0x3da);
1174 +       smi_mmiowb(reg, 0x3c0);
1175 +       smi_mmiorb(0x3c1);
1176 +       smi_mmiowb(val, 0x3c0);
1177 +}
1178 +
1179 +static inline void smi_seqw(int reg, int val)
1180 +{
1181 +       smi_mmiowb(reg, 0x3c4);
1182 +       smi_mmiowb(val, 0x3c5);
1183 +}
1184 +
1185 +static inline unsigned int smi_seqr(int reg)
1186 +{
1187 +       smi_mmiowb(reg, 0x3c4);
1188 +       return smi_mmiorb(0x3c5);
1189 +}
1190 +/*
1191 +* Private structure
1192 +*/
1193 +struct smifb_info {
1194 +       /*
1195 +       * The following is a pointer to be passed into the
1196 +       * functions below.  The modules outside the main
1197 +       * smifb.c driver have no knowledge as to what
1198 +       * is within this structure.
1199 +       */
1200 +       struct fb_info          fb;
1201 +       struct display_switch   *dispsw;
1202 +       struct pci_dev          *dev;
1203 +       signed int              currcon;
1204 +
1205 +       struct {
1206 +               u8 red, green, blue;
1207 +       } palette[NR_RGB];
1208 +
1209 +       u_int                   palette_size;
1210 +};
1211 +
1212 +struct par_info {
1213 +       /*
1214 +        * Hardware
1215 +        */
1216 +       u16             chipID;
1217 +       char    *m_pLFB;
1218 +       char    *m_pMMIO;
1219 +       char    *m_pDPR;
1220 +       char    *m_pVPR;
1221 +
1222 +       u_int   width;
1223 +       u_int   height;
1224 +       u_int   hz;
1225 +};
1226 +
1227 +/*The next structure holds all information relevant for
1228 + *a specific video mode.
1229 + */
1230 +struct ModeInit {
1231 +       int                       mmSizeX;
1232 +       int                       mmSizeY;
1233 +       int                       bpp;
1234 +       int                       hz;
1235 +       unsigned char Init_MISC;
1236 +       unsigned char Init_SR00_SR04[SIZE_SR00_SR04];
1237 +       unsigned char Init_SR10_SR24[SIZE_SR10_SR24];
1238 +       unsigned char Init_SR30_SR75[SIZE_SR30_SR75];
1239 +       unsigned char Init_SR80_SR93[SIZE_SR80_SR93];
1240 +       unsigned char Init_SRA0_SRAF[SIZE_SRA0_SRAF];
1241 +       unsigned char Init_GR00_GR08[SIZE_GR00_GR08];
1242 +       unsigned char Init_AR00_AR14[SIZE_AR00_AR14];
1243 +       unsigned char Init_CR00_CR18[SIZE_CR00_CR18];
1244 +       unsigned char Init_CR30_CR4D[SIZE_CR30_CR4D];
1245 +       unsigned char Init_CR90_CRA7[SIZE_CR90_CRA7];
1246 +};
1247 --- a/include/linux/fb.h
1248 +++ b/include/linux/fb.h
1249 @@ -935,6 +935,19 @@ static inline struct apertures_struct *a
1250  #define fb_memcpy_fromfb sbus_memcpy_fromio
1251  #define fb_memcpy_tofb sbus_memcpy_toio
1252  
1253 +#elif defined(CONFIG_COLDFIRE)
1254 +#define fb_readb readb
1255 +#define fb_readw readw
1256 +#define fb_readl readl
1257 +#define fb_readq readq
1258 +#define fb_writeb writeb
1259 +#define fb_writew writew
1260 +#define fb_writel writel
1261 +#define fb_writeq writeq
1262 +#define fb_memset memset_io
1263 +#define fb_memcpy_fromfb memcpy_fromio
1264 +#define fb_memcpy_tofb memcpy_toio
1265 +
1266  #elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) || defined(__sh__) || defined(__powerpc__) || defined(__avr32__) || defined(__bfin__)
1267  
1268  #define fb_readb __raw_readb
1269 @@ -1045,6 +1058,9 @@ extern int fb_deferred_io_fsync(struct f
1270  
1271  static inline bool fb_be_math(struct fb_info *info)
1272  {
1273 +#if defined(CONFIG_COLDFIRE)
1274 +       return false;
1275 +#endif
1276  #ifdef CONFIG_FB_FOREIGN_ENDIAN
1277  #if defined(CONFIG_FB_BOTH_ENDIAN)
1278         return info->flags & FBINFO_BE_MATH;
1279 @@ -1054,7 +1070,7 @@ static inline bool fb_be_math(struct fb_
1280         return false;
1281  #endif /* CONFIG_FB_BOTH_ENDIAN */
1282  #else
1283 -#ifdef __BIG_ENDIAN
1284 +#if defined(__BIG_ENDIAN) && !defined(CONFIG_COLDFIRE)
1285         return true;
1286  #else
1287         return false;