Root/target/linux/coldfire/patches/038-Add-PCI-Framebuffer-support-for-Silicon-Motion-s-Lyn.patch

1From d984818481320cf4a1b44cefbc99448205cc7673 Mon Sep 17 00:00:00 2001
2From: Jingchang Lu <b35083@freescale.com>
3Date: Thu, 4 Aug 2011 09:59:48 +0800
4Subject: [PATCH 38/52] Add PCI Framebuffer support for Silicon Motion's Lynx family
5
6The driver may support SM710, SM712, SM720, and the SM712
7has been tested on ColdFire M547X_8XEVB.
8
9Signed-off-by: Alison Wang <b18965@freescale.com>
10Signed-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;
1288

Archive Download this file



interactive