allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / drivers / video / smivgxfb.c
blobc521069c905b4252109b8144478b4381c0ccdb7f
1 /***************************************************************************
2 * Silicon Motion VoyagerGX framebuffer driver
4 * ported to 2.6 by Embedded Alley Solutions, Inc
5 * Copyright (C) 2005 Embedded Alley Solutions, Inc
7 * based on
8 copyright : (C) 2001 by Szu-Tao Huang
9 email : johuang@siliconmotion.com
10 Updated to SM501 by Eric.Devolder@amd.com and dan@embeddededge.com
11 for the AMD Mirage Portable Tablet. 20 Oct 2003
12 ***************************************************************************/
14 /***************************************************************************
15 * *
16 * This program is free software; you can redistribute it and/or modify *
17 * it under the terms of the GNU General Public License as published by *
18 * the Free Software Foundation; either version 2 of the License, or *
19 * (at your option) any later version. *
20 * *
21 ***************************************************************************/
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/string.h>
27 #include <linux/mm.h>
28 #include <linux/tty.h>
29 #include <linux/slab.h>
30 #include <linux/delay.h>
31 #include <linux/fb.h>
32 #include <linux/pci.h>
33 #include <linux/init.h>
35 #include <asm/io.h>
36 #include <asm/irq.h>
37 #include <asm/pgtable.h>
38 #include <asm/system.h>
39 #include <asm/uaccess.h>
41 static char __iomem *SMIRegs; // point to virtual Memory Map IO starting address
42 static char __iomem *SMILFB; // point to virtual video memory starting address
44 static struct fb_fix_screeninfo smifb_fix __devinitdata = {
45 .id = "smivgx",
46 .type = FB_TYPE_PACKED_PIXELS,
47 .visual = FB_VISUAL_TRUECOLOR,
48 .ywrapstep = 0,
49 .line_length = 1024 * 2, /* (bbp * xres)/8 */
50 .accel = FB_ACCEL_NONE,
53 static struct fb_var_screeninfo smifb_var __devinitdata = {
54 .xres = 1024,
55 .yres = 768,
56 .xres_virtual = 1024,
57 .yres_virtual = 768,
58 .bits_per_pixel = 16,
59 .red = { 11, 5, 0 },
60 .green = { 5, 6, 0 },
61 .blue = { 0, 5, 0 },
62 .activate = FB_ACTIVATE_NOW,
63 .height = -1,
64 .width = -1,
65 .vmode = FB_VMODE_NONINTERLACED,
69 static struct fb_info info;
71 #define smi_mmiowb(dat,reg) writeb(dat, (SMIRegs + reg))
72 #define smi_mmioww(dat,reg) writew(dat, (SMIRegs + reg))
73 #define smi_mmiowl(dat,reg) writel(dat, (SMIRegs + reg))
75 #define smi_mmiorb(reg) readb(SMIRegs + reg)
76 #define smi_mmiorw(reg) readw(SMIRegs + reg)
77 #define smi_mmiorl(reg) readl(SMIRegs + reg)
79 /* Address space offsets for various control/status registers.
81 #define MISC_CTRL 0x000004
82 #define GPIO_LO_CTRL 0x000008
83 #define GPIO_HI_CTRL 0x00000c
84 #define DRAM_CTRL 0x000010
85 #define CURRENT_POWER_GATE 0x000038
86 #define CURRENT_POWER_CLOCK 0x00003C
87 #define POWER_MODE1_GATE 0x000048
88 #define POWER_MODE1_CLOCK 0x00004C
89 #define POWER_MODE_CTRL 0x000054
91 #define GPIO_DATA_LO 0x010000
92 #define GPIO_DATA_HI 0x010004
93 #define GPIO_DATA_DIR_LO 0x010008
94 #define GPIO_DATA_DIR_HI 0x01000c
95 #define I2C_BYTE_COUNT 0x010040
96 #define I2C_CONTROL 0x010041
97 #define I2C_STATUS_RESET 0x010042
98 #define I2C_SLAVE_ADDRESS 0x010043
99 #define I2C_DATA 0x010044
101 #define DE_COLOR_COMPARE 0x100020
102 #define DE_COLOR_COMPARE_MASK 0x100024
103 #define DE_MASKS 0x100028
104 #define DE_WRAP 0x10004C
106 #define PANEL_DISPLAY_CTRL 0x080000
107 #define PANEL_PAN_CTRL 0x080004
108 #define PANEL_COLOR_KEY 0x080008
109 #define PANEL_FB_ADDRESS 0x08000C
110 #define PANEL_FB_WIDTH 0x080010
111 #define PANEL_WINDOW_WIDTH 0x080014
112 #define PANEL_WINDOW_HEIGHT 0x080018
113 #define PANEL_PLANE_TL 0x08001C
114 #define PANEL_PLANE_BR 0x080020
115 #define PANEL_HORIZONTAL_TOTAL 0x080024
116 #define PANEL_HORIZONTAL_SYNC 0x080028
117 #define PANEL_VERTICAL_TOTAL 0x08002C
118 #define PANEL_VERTICAL_SYNC 0x080030
119 #define PANEL_CURRENT_LINE 0x080034
120 #define VIDEO_DISPLAY_CTRL 0x080040
121 #define VIDEO_DISPLAY_FB0 0x080044
122 #define VIDEO_DISPLAY_FBWIDTH 0x080048
123 #define VIDEO_DISPLAY_FB0LAST 0x08004C
124 #define VIDEO_DISPLAY_TL 0x080050
125 #define VIDEO_DISPLAY_BR 0x080054
126 #define VIDEO_SCALE 0x080058
127 #define VIDEO_INITIAL_SCALE 0x08005C
128 #define VIDEO_YUV_CONSTANTS 0x080060
129 #define VIDEO_DISPLAY_FB1 0x080064
130 #define VIDEO_DISPLAY_FB1LAST 0x080068
131 #define VIDEO_ALPHA_CTRL 0x080080
132 #define PANEL_HWC_ADDRESS 0x0800F0
133 #define CRT_DISPLAY_CTRL 0x080200
134 #define CRT_FB_ADDRESS 0x080204
135 #define CRT_FB_WIDTH 0x080208
136 #define CRT_HORIZONTAL_TOTAL 0x08020c
137 #define CRT_HORIZONTAL_SYNC 0x080210
138 #define CRT_VERTICAL_TOTAL 0x080214
139 #define CRT_VERTICAL_SYNC 0x080218
140 #define CRT_HWC_ADDRESS 0x080230
141 #define CRT_HWC_LOCATION 0x080234
143 #define ZV_CAPTURE_CTRL 0x090000
144 #define ZV_CAPTURE_CLIP 0x090004
145 #define ZV_CAPTURE_SIZE 0x090008
146 #define ZV_CAPTURE_BUF0 0x09000c
147 #define ZV_CAPTURE_BUF1 0x090010
148 #define ZV_CAPTURE_OFFSET 0x090014
149 #define ZV_FIFO_CTRL 0x090018
151 #define waitforvsync() udelay(400)
153 static int initdone = 0;
154 static int crt_out = 1;
157 static int
158 smi_setcolreg(unsigned regno, unsigned red, unsigned green,
159 unsigned blue, unsigned transp,
160 struct fb_info *info)
162 if (regno > 255)
163 return 1;
165 ((u32 *)(info->pseudo_palette))[regno] =
166 ((red & 0xf800) >> 0) |
167 ((green & 0xfc00) >> 5) |
168 ((blue & 0xf800) >> 11);
170 return 0;
173 /* This function still needs lots of work to generically support
174 * different output devices (CRT or LCD) and resolutions.
175 * Currently hard-coded for 1024x768 LCD panel.
177 static void smi_setmode(void)
179 if (initdone)
180 return;
182 initdone = 1;
184 /* Just blast in some control values based upon the chip
185 * documentation. We use the internal memory, I don't know
186 * how to determine the amount available yet.
188 smi_mmiowl(0x07F127C2, DRAM_CTRL);
189 smi_mmiowl(0x02000020, PANEL_HWC_ADDRESS);
190 smi_mmiowl(0x007FF800, PANEL_HWC_ADDRESS);
191 smi_mmiowl(0x00021827, POWER_MODE1_GATE);
192 smi_mmiowl(0x011A0A09, POWER_MODE1_CLOCK);
193 smi_mmiowl(0x00000001, POWER_MODE_CTRL);
194 smi_mmiowl(0x80000000, PANEL_FB_ADDRESS);
195 smi_mmiowl(0x08000800, PANEL_FB_WIDTH);
196 smi_mmiowl(0x04000000, PANEL_WINDOW_WIDTH);
197 smi_mmiowl(0x03000000, PANEL_WINDOW_HEIGHT);
198 smi_mmiowl(0x00000000, PANEL_PLANE_TL);
199 smi_mmiowl(0x02FF03FF, PANEL_PLANE_BR);
200 smi_mmiowl(0x05D003FF, PANEL_HORIZONTAL_TOTAL);
201 smi_mmiowl(0x00C80424, PANEL_HORIZONTAL_SYNC);
202 smi_mmiowl(0x032502FF, PANEL_VERTICAL_TOTAL);
203 smi_mmiowl(0x00060302, PANEL_VERTICAL_SYNC);
204 smi_mmiowl(0x00013905, PANEL_DISPLAY_CTRL);
205 smi_mmiowl(0x01013105, PANEL_DISPLAY_CTRL);
206 waitforvsync();
207 smi_mmiowl(0x03013905, PANEL_DISPLAY_CTRL);
208 waitforvsync();
209 smi_mmiowl(0x07013905, PANEL_DISPLAY_CTRL);
210 waitforvsync();
211 smi_mmiowl(0x0F013905, PANEL_DISPLAY_CTRL);
212 smi_mmiowl(0x0002187F, POWER_MODE1_GATE);
213 smi_mmiowl(0x01011801, POWER_MODE1_CLOCK);
214 smi_mmiowl(0x00000001, POWER_MODE_CTRL);
216 smi_mmiowl(0x80000000, PANEL_FB_ADDRESS);
217 smi_mmiowl(0x00000000, PANEL_PAN_CTRL);
218 smi_mmiowl(0x00000000, PANEL_COLOR_KEY);
220 if (crt_out) {
221 /* Just sent the panel out to the CRT for now.
223 smi_mmiowl(0x80000000, CRT_FB_ADDRESS);
224 smi_mmiowl(0x08000800, CRT_FB_WIDTH);
225 smi_mmiowl(0x05D003FF, CRT_HORIZONTAL_TOTAL);
226 smi_mmiowl(0x00C80424, CRT_HORIZONTAL_SYNC);
227 smi_mmiowl(0x032502FF, CRT_VERTICAL_TOTAL);
228 smi_mmiowl(0x00060302, CRT_VERTICAL_SYNC);
229 smi_mmiowl(0x007FF800, CRT_HWC_ADDRESS);
230 smi_mmiowl(0x00010305, CRT_DISPLAY_CTRL);
231 smi_mmiowl(0x00000001, MISC_CTRL);
236 * Unmap in the memory mapped IO registers
240 static void __devinit smi_unmap_mmio(void)
242 if (SMIRegs) {
243 iounmap(SMIRegs);
244 SMIRegs = NULL;
250 * Unmap in the screen memory
253 static void __devinit smi_unmap_smem(void)
255 if (SMILFB) {
256 iounmap(SMILFB);
257 SMILFB = NULL;
261 static void vgxfb_setup(char *options)
264 if (!options || !*options)
265 return;
267 /* The only thing I'm looking for right now is to disable a
268 * CRT output that mirrors the panel display.
270 if (strcmp(options, "no_crt") == 0)
271 crt_out = 0;
273 return;
276 static struct fb_ops smifb_ops = {
277 .owner = THIS_MODULE,
278 .fb_setcolreg = smi_setcolreg,
279 .fb_fillrect = cfb_fillrect,
280 .fb_copyarea = cfb_copyarea,
281 .fb_imageblit = cfb_imageblit,
284 static int __devinit vgx_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
286 int err;
288 /* Enable the chip.
290 err = pci_enable_device(dev);
291 if (err)
292 return err;
295 /* Set up MMIO space.
297 smifb_fix.mmio_start = pci_resource_start(dev,1);
298 smifb_fix.mmio_len = 0x00200000;
299 SMIRegs = ioremap(smifb_fix.mmio_start, smifb_fix.mmio_len);
301 /* Set up framebuffer. It's a 64M space, various amount of
302 * internal memory. I don't know how to determine the real
303 * amount of memory (yet).
305 smifb_fix.smem_start = pci_resource_start(dev,0);
306 smifb_fix.smem_len = 0x00800000;
307 SMILFB = ioremap(smifb_fix.smem_start, smifb_fix.smem_len);
309 memset_io(SMILFB, 0, smifb_fix.smem_len);
311 info.screen_base = SMILFB;
312 info.fbops = &smifb_ops;
313 info.fix = smifb_fix;
315 info.flags = FBINFO_FLAG_DEFAULT;
317 info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
318 if (!info.pseudo_palette) {
319 return -ENOMEM;
321 memset(info.pseudo_palette, 0, sizeof(u32) *16);
323 fb_alloc_cmap(&info.cmap,256,0);
325 smi_setmode();
327 info.var = smifb_var;
329 if (register_framebuffer(&info) < 0)
330 goto failed;
332 return 0;
334 failed:
335 smi_unmap_smem();
336 smi_unmap_mmio();
338 return err;
341 static void __devexit vgx_pci_remove(struct pci_dev *dev)
343 unregister_framebuffer(&info);
344 smi_unmap_smem();
345 smi_unmap_mmio();
348 static struct pci_device_id vgx_devices[] = {
349 {PCI_VENDOR_ID_SILICON_MOTION, PCI_DEVICE_ID_SM501_VOYAGER_GX_REV_AA,
350 PCI_ANY_ID, PCI_ANY_ID},
351 {PCI_VENDOR_ID_SILICON_MOTION, PCI_DEVICE_ID_SM501_VOYAGER_GX_REV_B,
352 PCI_ANY_ID, PCI_ANY_ID},
356 MODULE_DEVICE_TABLE(pci, vgx_devices);
358 static struct pci_driver vgxfb_pci_driver = {
359 .name = "vgxfb",
360 .id_table= vgx_devices,
361 .probe = vgx_pci_probe,
362 .remove = __devexit_p(vgx_pci_remove),
365 static int __init vgxfb_init(void)
367 char *option = NULL;
369 if (fb_get_options("vgxfb", &option))
370 return -ENODEV;
371 vgxfb_setup(option);
373 printk("Silicon Motion Inc. VOYAGER Init complete.\n");
374 return pci_module_init(&vgxfb_pci_driver);
377 static void __exit vgxfb_exit(void)
379 pci_unregister_driver(&vgxfb_pci_driver);
382 module_init(vgxfb_init);
383 module_exit(vgxfb_exit);
385 MODULE_AUTHOR("");
386 MODULE_DESCRIPTION("Framebuffer driver for SMI Voyager");
387 MODULE_LICENSE("GPL");