aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/Kconfig26
-rw-r--r--drivers/video/Makefile3
-rw-r--r--drivers/video/vt8500lcdfb.c447
-rw-r--r--drivers/video/vt8500lcdfb.h34
-rw-r--r--drivers/video/wm8505fb.c422
-rw-r--r--drivers/video/wm8505fb_regs.h76
-rw-r--r--drivers/video/wmt_ge_rops.c192
-rw-r--r--drivers/video/wmt_ge_rops.h5
8 files changed, 1205 insertions, 0 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 27c1fb4b1e0d..954f6e9d8d5a 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -186,6 +186,14 @@ config FB_SYS_FOPS
186 depends on FB 186 depends on FB
187 default n 187 default n
188 188
189config FB_WMT_GE_ROPS
190 tristate
191 depends on FB
192 default n
193 ---help---
194 Include functions for accelerated rectangle filling and area
195 copying using WonderMedia Graphics Engine operations.
196
189config FB_DEFERRED_IO 197config FB_DEFERRED_IO
190 bool 198 bool
191 depends on FB 199 depends on FB
@@ -1722,6 +1730,24 @@ config FB_AU1200
1722 various panels and CRTs by passing in kernel cmd line option 1730 various panels and CRTs by passing in kernel cmd line option
1723 au1200fb:panel=<name>. 1731 au1200fb:panel=<name>.
1724 1732
1733config FB_VT8500
1734 bool "VT8500 LCD Driver"
1735 depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_VT8500
1736 select FB_WMT_GE_ROPS
1737 select FB_SYS_IMAGEBLIT
1738 help
1739 This is the framebuffer driver for VIA VT8500 integrated LCD
1740 controller.
1741
1742config FB_WM8505
1743 bool "WM8505 frame buffer support"
1744 depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_WM8505
1745 select FB_WMT_GE_ROPS
1746 select FB_SYS_IMAGEBLIT
1747 help
1748 This is the framebuffer driver for WonderMedia WM8505
1749 integrated LCD controller.
1750
1725source "drivers/video/geode/Kconfig" 1751source "drivers/video/geode/Kconfig"
1726 1752
1727config FB_HIT 1753config FB_HIT
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 485e8ed1318c..8d916dcb379f 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_FB_SVGALIB) += svgalib.o
26obj-$(CONFIG_FB_MACMODES) += macmodes.o 26obj-$(CONFIG_FB_MACMODES) += macmodes.o
27obj-$(CONFIG_FB_DDC) += fb_ddc.o 27obj-$(CONFIG_FB_DDC) += fb_ddc.o
28obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o 28obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
29obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
29 30
30# Hardware specific drivers go first 31# Hardware specific drivers go first
31obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o 32obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
@@ -104,6 +105,8 @@ obj-$(CONFIG_FB_W100) += w100fb.o
104obj-$(CONFIG_FB_TMIO) += tmiofb.o 105obj-$(CONFIG_FB_TMIO) += tmiofb.o
105obj-$(CONFIG_FB_AU1100) += au1100fb.o 106obj-$(CONFIG_FB_AU1100) += au1100fb.o
106obj-$(CONFIG_FB_AU1200) += au1200fb.o 107obj-$(CONFIG_FB_AU1200) += au1200fb.o
108obj-$(CONFIG_FB_VT8500) += vt8500lcdfb.o
109obj-$(CONFIG_FB_WM8505) += wm8505fb.o
107obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o 110obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o
108obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o 111obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o
109obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o 112obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
new file mode 100644
index 000000000000..7617f12e4fd7
--- /dev/null
+++ b/drivers/video/vt8500lcdfb.c
@@ -0,0 +1,447 @@
1/*
2 * linux/drivers/video/vt8500lcdfb.c
3 *
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 *
6 * Based on skeletonfb.c and pxafb.c
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/string.h>
22#include <linux/mm.h>
23#include <linux/slab.h>
24#include <linux/delay.h>
25#include <linux/fb.h>
26#include <linux/init.h>
27#include <linux/interrupt.h>
28#include <linux/io.h>
29#include <linux/dma-mapping.h>
30#include <linux/platform_device.h>
31#include <linux/wait.h>
32
33#include <mach/vt8500fb.h>
34
35#include "vt8500lcdfb.h"
36#include "wmt_ge_rops.h"
37
38#define to_vt8500lcd_info(__info) container_of(__info, \
39 struct vt8500lcd_info, fb)
40
41static int vt8500lcd_set_par(struct fb_info *info)
42{
43 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
44 int reg_bpp = 5; /* 16bpp */
45 int i;
46 unsigned long control0;
47
48 if (!fbi)
49 return -EINVAL;
50
51 if (info->var.bits_per_pixel <= 8) {
52 /* palettized */
53 info->var.red.offset = 0;
54 info->var.red.length = info->var.bits_per_pixel;
55 info->var.red.msb_right = 0;
56
57 info->var.green.offset = 0;
58 info->var.green.length = info->var.bits_per_pixel;
59 info->var.green.msb_right = 0;
60
61 info->var.blue.offset = 0;
62 info->var.blue.length = info->var.bits_per_pixel;
63 info->var.blue.msb_right = 0;
64
65 info->var.transp.offset = 0;
66 info->var.transp.length = 0;
67 info->var.transp.msb_right = 0;
68
69 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
70 info->fix.line_length = info->var.xres_virtual /
71 (8/info->var.bits_per_pixel);
72 } else {
73 /* non-palettized */
74 info->var.transp.offset = 0;
75 info->var.transp.length = 0;
76 info->var.transp.msb_right = 0;
77
78 if (info->var.bits_per_pixel == 16) {
79 /* RGB565 */
80 info->var.red.offset = 11;
81 info->var.red.length = 5;
82 info->var.red.msb_right = 0;
83 info->var.green.offset = 5;
84 info->var.green.length = 6;
85 info->var.green.msb_right = 0;
86 info->var.blue.offset = 0;
87 info->var.blue.length = 5;
88 info->var.blue.msb_right = 0;
89 } else {
90 /* Equal depths per channel */
91 info->var.red.offset = info->var.bits_per_pixel
92 * 2 / 3;
93 info->var.red.length = info->var.bits_per_pixel / 3;
94 info->var.red.msb_right = 0;
95 info->var.green.offset = info->var.bits_per_pixel / 3;
96 info->var.green.length = info->var.bits_per_pixel / 3;
97 info->var.green.msb_right = 0;
98 info->var.blue.offset = 0;
99 info->var.blue.length = info->var.bits_per_pixel / 3;
100 info->var.blue.msb_right = 0;
101 }
102
103 info->fix.visual = FB_VISUAL_TRUECOLOR;
104 info->fix.line_length = info->var.bits_per_pixel > 16 ?
105 info->var.xres_virtual << 2 :
106 info->var.xres_virtual << 1;
107 }
108
109 for (i = 0; i < 8; i++) {
110 if (bpp_values[i] == info->var.bits_per_pixel) {
111 reg_bpp = i;
112 continue;
113 }
114 }
115
116 control0 = readl(fbi->regbase) & ~0xf;
117 writel(0, fbi->regbase);
118 while (readl(fbi->regbase + 0x38) & 0x10)
119 /* wait */;
120 writel((((info->var.hsync_len - 1) & 0x3f) << 26)
121 | ((info->var.left_margin & 0xff) << 18)
122 | (((info->var.xres - 1) & 0x3ff) << 8)
123 | (info->var.right_margin & 0xff), fbi->regbase + 0x4);
124 writel((((info->var.vsync_len - 1) & 0x3f) << 26)
125 | ((info->var.upper_margin & 0xff) << 18)
126 | (((info->var.yres - 1) & 0x3ff) << 8)
127 | (info->var.lower_margin & 0xff), fbi->regbase + 0x8);
128 writel((((info->var.yres - 1) & 0x400) << 2)
129 | ((info->var.xres - 1) & 0x400), fbi->regbase + 0x10);
130 writel(0x80000000, fbi->regbase + 0x20);
131 writel(control0 | (reg_bpp << 1) | 0x100, fbi->regbase);
132
133 return 0;
134}
135
136static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
137{
138 chan &= 0xffff;
139 chan >>= 16 - bf->length;
140 return chan << bf->offset;
141}
142
143static int vt8500lcd_setcolreg(unsigned regno, unsigned red, unsigned green,
144 unsigned blue, unsigned transp,
145 struct fb_info *info) {
146 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
147 int ret = 1;
148 unsigned int val;
149 if (regno >= 256)
150 return -EINVAL;
151
152 if (info->var.grayscale)
153 red = green = blue =
154 (19595 * red + 38470 * green + 7471 * blue) >> 16;
155
156 switch (fbi->fb.fix.visual) {
157 case FB_VISUAL_TRUECOLOR:
158 if (regno < 16) {
159 u32 *pal = fbi->fb.pseudo_palette;
160
161 val = chan_to_field(red, &fbi->fb.var.red);
162 val |= chan_to_field(green, &fbi->fb.var.green);
163 val |= chan_to_field(blue, &fbi->fb.var.blue);
164
165 pal[regno] = val;
166 ret = 0;
167 }
168 break;
169
170 case FB_VISUAL_STATIC_PSEUDOCOLOR:
171 case FB_VISUAL_PSEUDOCOLOR:
172 writew((red & 0xf800)
173 | ((green >> 5) & 0x7e0)
174 | ((blue >> 11) & 0x1f),
175 fbi->palette_cpu + sizeof(u16) * regno);
176 break;
177 }
178
179 return ret;
180}
181
182static int vt8500lcd_ioctl(struct fb_info *info, unsigned int cmd,
183 unsigned long arg)
184{
185 int ret = 0;
186 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
187
188 if (cmd == FBIO_WAITFORVSYNC) {
189 /* Unmask End of Frame interrupt */
190 writel(0xffffffff ^ (1 << 3), fbi->regbase + 0x3c);
191 ret = wait_event_interruptible_timeout(fbi->wait,
192 readl(fbi->regbase + 0x38) & (1 << 3), HZ / 10);
193 /* Mask back to reduce unwanted interrupt traffic */
194 writel(0xffffffff, fbi->regbase + 0x3c);
195 if (ret < 0)
196 return ret;
197 if (ret == 0)
198 return -ETIMEDOUT;
199 }
200
201 return ret;
202}
203
204static int vt8500lcd_pan_display(struct fb_var_screeninfo *var,
205 struct fb_info *info)
206{
207 unsigned pixlen = info->fix.line_length / info->var.xres_virtual;
208 unsigned off = pixlen * var->xoffset
209 + info->fix.line_length * var->yoffset;
210 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
211
212 writel((1 << 31)
213 | (((var->xres_virtual - var->xres) * pixlen / 4) << 20)
214 | (off >> 2), fbi->regbase + 0x20);
215 return 0;
216}
217
218static struct fb_ops vt8500lcd_ops = {
219 .owner = THIS_MODULE,
220 .fb_set_par = vt8500lcd_set_par,
221 .fb_setcolreg = vt8500lcd_setcolreg,
222 .fb_fillrect = wmt_ge_fillrect,
223 .fb_copyarea = wmt_ge_copyarea,
224 .fb_imageblit = sys_imageblit,
225 .fb_sync = wmt_ge_sync,
226 .fb_ioctl = vt8500lcd_ioctl,
227 .fb_pan_display = vt8500lcd_pan_display,
228};
229
230static irqreturn_t vt8500lcd_handle_irq(int irq, void *dev_id)
231{
232 struct vt8500lcd_info *fbi = dev_id;
233
234 if (readl(fbi->regbase + 0x38) & (1 << 3))
235 wake_up_interruptible(&fbi->wait);
236
237 writel(0xffffffff, fbi->regbase + 0x38);
238 return IRQ_HANDLED;
239}
240
241static int __devinit vt8500lcd_probe(struct platform_device *pdev)
242{
243 struct vt8500lcd_info *fbi;
244 struct resource *res;
245 struct vt8500fb_platform_data *pdata = pdev->dev.platform_data;
246 void *addr;
247 int irq, ret;
248
249 ret = -ENOMEM;
250 fbi = NULL;
251
252 fbi = kzalloc(sizeof(struct vt8500lcd_info) + sizeof(u32) * 16,
253 GFP_KERNEL);
254 if (!fbi) {
255 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
256 ret = -ENOMEM;
257 goto failed;
258 }
259
260 strcpy(fbi->fb.fix.id, "VT8500 LCD");
261
262 fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
263 fbi->fb.fix.xpanstep = 0;
264 fbi->fb.fix.ypanstep = 1;
265 fbi->fb.fix.ywrapstep = 0;
266 fbi->fb.fix.accel = FB_ACCEL_NONE;
267
268 fbi->fb.var.nonstd = 0;
269 fbi->fb.var.activate = FB_ACTIVATE_NOW;
270 fbi->fb.var.height = -1;
271 fbi->fb.var.width = -1;
272 fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
273
274 fbi->fb.fbops = &vt8500lcd_ops;
275 fbi->fb.flags = FBINFO_DEFAULT
276 | FBINFO_HWACCEL_COPYAREA
277 | FBINFO_HWACCEL_FILLRECT
278 | FBINFO_HWACCEL_YPAN
279 | FBINFO_VIRTFB
280 | FBINFO_PARTIAL_PAN_OK;
281 fbi->fb.node = -1;
282
283 addr = fbi;
284 addr = addr + sizeof(struct vt8500lcd_info);
285 fbi->fb.pseudo_palette = addr;
286
287 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
288 if (res == NULL) {
289 dev_err(&pdev->dev, "no I/O memory resource defined\n");
290 ret = -ENODEV;
291 goto failed_fbi;
292 }
293
294 res = request_mem_region(res->start, resource_size(res), "vt8500lcd");
295 if (res == NULL) {
296 dev_err(&pdev->dev, "failed to request I/O memory\n");
297 ret = -EBUSY;
298 goto failed_fbi;
299 }
300
301 fbi->regbase = ioremap(res->start, resource_size(res));
302 if (fbi->regbase == NULL) {
303 dev_err(&pdev->dev, "failed to map I/O memory\n");
304 ret = -EBUSY;
305 goto failed_free_res;
306 }
307
308 fbi->fb.fix.smem_start = pdata->video_mem_phys;
309 fbi->fb.fix.smem_len = pdata->video_mem_len;
310 fbi->fb.screen_base = pdata->video_mem_virt;
311
312 fbi->palette_size = PAGE_ALIGN(512);
313 fbi->palette_cpu = dma_alloc_coherent(&pdev->dev,
314 fbi->palette_size,
315 &fbi->palette_phys,
316 GFP_KERNEL);
317 if (fbi->palette_cpu == NULL) {
318 dev_err(&pdev->dev, "Failed to allocate palette buffer\n");
319 ret = -ENOMEM;
320 goto failed_free_io;
321 }
322
323 irq = platform_get_irq(pdev, 0);
324 if (irq < 0) {
325 dev_err(&pdev->dev, "no IRQ defined\n");
326 ret = -ENODEV;
327 goto failed_free_palette;
328 }
329
330 ret = request_irq(irq, vt8500lcd_handle_irq, IRQF_DISABLED, "LCD", fbi);
331 if (ret) {
332 dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
333 ret = -EBUSY;
334 goto failed_free_palette;
335 }
336
337 init_waitqueue_head(&fbi->wait);
338
339 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
340 dev_err(&pdev->dev, "Failed to allocate color map\n");
341 ret = -ENOMEM;
342 goto failed_free_irq;
343 }
344
345 fb_videomode_to_var(&fbi->fb.var, &pdata->mode);
346 fbi->fb.var.bits_per_pixel = pdata->bpp;
347 fbi->fb.var.xres_virtual = pdata->xres_virtual;
348 fbi->fb.var.yres_virtual = pdata->yres_virtual;
349
350 ret = vt8500lcd_set_par(&fbi->fb);
351 if (ret) {
352 dev_err(&pdev->dev, "Failed to set parameters\n");
353 goto failed_free_cmap;
354 }
355
356 writel(fbi->fb.fix.smem_start >> 22, fbi->regbase + 0x1c);
357 writel((fbi->palette_phys & 0xfffffe00) | 1, fbi->regbase + 0x18);
358
359 platform_set_drvdata(pdev, fbi);
360
361 ret = register_framebuffer(&fbi->fb);
362 if (ret < 0) {
363 dev_err(&pdev->dev,
364 "Failed to register framebuffer device: %d\n", ret);
365 goto failed_free_cmap;
366 }
367
368 /*
369 * Ok, now enable the LCD controller
370 */
371 writel(readl(fbi->regbase) | 1, fbi->regbase);
372
373 return 0;
374
375failed_free_cmap:
376 if (fbi->fb.cmap.len)
377 fb_dealloc_cmap(&fbi->fb.cmap);
378failed_free_irq:
379 free_irq(irq, fbi);
380failed_free_palette:
381 dma_free_coherent(&pdev->dev, fbi->palette_size,
382 fbi->palette_cpu, fbi->palette_phys);
383failed_free_io:
384 iounmap(fbi->regbase);
385failed_free_res:
386 release_mem_region(res->start, resource_size(res));
387failed_fbi:
388 platform_set_drvdata(pdev, NULL);
389 kfree(fbi);
390failed:
391 return ret;
392}
393
394static int __devexit vt8500lcd_remove(struct platform_device *pdev)
395{
396 struct vt8500lcd_info *fbi = platform_get_drvdata(pdev);
397 struct resource *res;
398 int irq;
399
400 unregister_framebuffer(&fbi->fb);
401
402 writel(0, fbi->regbase);
403
404 if (fbi->fb.cmap.len)
405 fb_dealloc_cmap(&fbi->fb.cmap);
406
407 irq = platform_get_irq(pdev, 0);
408 free_irq(irq, fbi);
409
410 dma_free_coherent(&pdev->dev, fbi->palette_size,
411 fbi->palette_cpu, fbi->palette_phys);
412
413 iounmap(fbi->regbase);
414
415 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
416 release_mem_region(res->start, resource_size(res));
417
418 kfree(fbi);
419
420 return 0;
421}
422
423static struct platform_driver vt8500lcd_driver = {
424 .probe = vt8500lcd_probe,
425 .remove = __devexit_p(vt8500lcd_remove),
426 .driver = {
427 .owner = THIS_MODULE,
428 .name = "vt8500-lcd",
429 },
430};
431
432static int __init vt8500lcd_init(void)
433{
434 return platform_driver_register(&vt8500lcd_driver);
435}
436
437static void __exit vt8500lcd_exit(void)
438{
439 platform_driver_unregister(&vt8500lcd_driver);
440}
441
442module_init(vt8500lcd_init);
443module_exit(vt8500lcd_exit);
444
445MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
446MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
447MODULE_LICENSE("GPL");
diff --git a/drivers/video/vt8500lcdfb.h b/drivers/video/vt8500lcdfb.h
new file mode 100644
index 000000000000..36ca3ca09d83
--- /dev/null
+++ b/drivers/video/vt8500lcdfb.h
@@ -0,0 +1,34 @@
1/*
2 * linux/drivers/video/vt8500lcdfb.h
3 *
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16struct vt8500lcd_info {
17 struct fb_info fb;
18 void __iomem *regbase;
19 void __iomem *palette_cpu;
20 dma_addr_t palette_phys;
21 size_t palette_size;
22 wait_queue_head_t wait;
23};
24
25static int bpp_values[] = {
26 1,
27 2,
28 4,
29 8,
30 12,
31 16,
32 18,
33 24,
34};
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
new file mode 100644
index 000000000000..e37251b792c9
--- /dev/null
+++ b/drivers/video/wm8505fb.c
@@ -0,0 +1,422 @@
1/*
2 * WonderMedia WM8505 Frame Buffer device driver
3 *
4 * Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
5 * Based on vt8500lcdfb.c
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/errno.h>
20#include <linux/string.h>
21#include <linux/mm.h>
22#include <linux/slab.h>
23#include <linux/delay.h>
24#include <linux/fb.h>
25#include <linux/init.h>
26#include <linux/interrupt.h>
27#include <linux/io.h>
28#include <linux/dma-mapping.h>
29#include <linux/platform_device.h>
30#include <linux/wait.h>
31
32#include <mach/vt8500fb.h>
33
34#include "wm8505fb_regs.h"
35#include "wmt_ge_rops.h"
36
37#define DRIVER_NAME "wm8505-fb"
38
39#define to_wm8505fb_info(__info) container_of(__info, \
40 struct wm8505fb_info, fb)
41struct wm8505fb_info {
42 struct fb_info fb;
43 void __iomem *regbase;
44 unsigned int contrast;
45};
46
47
48static int wm8505fb_init_hw(struct fb_info *info)
49{
50 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
51
52 int i;
53
54 /* I know the purpose only of few registers, so clear unknown */
55 for (i = 0; i < 0x200; i += 4)
56 writel(0, fbi->regbase + i);
57
58 /* Set frame buffer address */
59 writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR);
60 writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR1);
61
62 /* Set in-memory picture format to RGB 32bpp */
63 writel(0x1c, fbi->regbase + WMT_GOVR_COLORSPACE);
64 writel(1, fbi->regbase + WMT_GOVR_COLORSPACE1);
65
66 /* Virtual buffer size */
67 writel(info->var.xres, fbi->regbase + WMT_GOVR_XRES);
68 writel(info->var.xres_virtual, fbi->regbase + WMT_GOVR_XRES_VIRTUAL);
69
70 /* black magic ;) */
71 writel(0xf, fbi->regbase + WMT_GOVR_FHI);
72 writel(4, fbi->regbase + WMT_GOVR_DVO_SET);
73 writel(1, fbi->regbase + WMT_GOVR_MIF_ENABLE);
74 writel(1, fbi->regbase + WMT_GOVR_REG_UPDATE);
75
76 return 0;
77}
78
79static int wm8505fb_set_timing(struct fb_info *info)
80{
81 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
82
83 int h_start = info->var.left_margin;
84 int h_end = h_start + info->var.xres;
85 int h_all = h_end + info->var.right_margin;
86 int h_sync = info->var.hsync_len;
87
88 int v_start = info->var.upper_margin;
89 int v_end = v_start + info->var.yres;
90 int v_all = v_end + info->var.lower_margin;
91 int v_sync = info->var.vsync_len + 1;
92
93 writel(0, fbi->regbase + WMT_GOVR_TG);
94
95 writel(h_start, fbi->regbase + WMT_GOVR_TIMING_H_START);
96 writel(h_end, fbi->regbase + WMT_GOVR_TIMING_H_END);
97 writel(h_all, fbi->regbase + WMT_GOVR_TIMING_H_ALL);
98 writel(h_sync, fbi->regbase + WMT_GOVR_TIMING_H_SYNC);
99
100 writel(v_start, fbi->regbase + WMT_GOVR_TIMING_V_START);
101 writel(v_end, fbi->regbase + WMT_GOVR_TIMING_V_END);
102 writel(v_all, fbi->regbase + WMT_GOVR_TIMING_V_ALL);
103 writel(v_sync, fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
104
105 writel(1, fbi->regbase + WMT_GOVR_TG);
106
107 return 0;
108}
109
110
111static int wm8505fb_set_par(struct fb_info *info)
112{
113 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
114
115 if (!fbi)
116 return -EINVAL;
117
118 if (info->var.bits_per_pixel == 32) {
119 info->var.red.offset = 16;
120 info->var.red.length = 8;
121 info->var.red.msb_right = 0;
122 info->var.green.offset = 8;
123 info->var.green.length = 8;
124 info->var.green.msb_right = 0;
125 info->var.blue.offset = 0;
126 info->var.blue.length = 8;
127 info->var.blue.msb_right = 0;
128 info->fix.visual = FB_VISUAL_TRUECOLOR;
129 info->fix.line_length = info->var.xres_virtual << 2;
130 }
131
132 wm8505fb_set_timing(info);
133
134 writel(fbi->contrast<<16 | fbi->contrast<<8 | fbi->contrast,
135 fbi->regbase + WMT_GOVR_CONTRAST);
136
137 return 0;
138}
139
140static ssize_t contrast_show(struct device *dev,
141 struct device_attribute *attr, char *buf)
142{
143 struct fb_info *info = dev_get_drvdata(dev);
144 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
145
146 return sprintf(buf, "%d\n", fbi->contrast);
147}
148
149static ssize_t contrast_store(struct device *dev,
150 struct device_attribute *attr,
151 const char *buf, size_t count)
152{
153 struct fb_info *info = dev_get_drvdata(dev);
154 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
155 unsigned long tmp;
156
157 if (strict_strtoul(buf, 10, &tmp) || (tmp > 0xff))
158 return -EINVAL;
159 fbi->contrast = tmp;
160
161 wm8505fb_set_par(info);
162
163 return count;
164}
165
166static DEVICE_ATTR(contrast, 0644, contrast_show, contrast_store);
167
168static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
169{
170 chan &= 0xffff;
171 chan >>= 16 - bf->length;
172 return chan << bf->offset;
173}
174
175static int wm8505fb_setcolreg(unsigned regno, unsigned red, unsigned green,
176 unsigned blue, unsigned transp,
177 struct fb_info *info) {
178 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
179 int ret = 1;
180 unsigned int val;
181 if (regno >= 256)
182 return -EINVAL;
183
184 if (info->var.grayscale)
185 red = green = blue =
186 (19595 * red + 38470 * green + 7471 * blue) >> 16;
187
188 switch (fbi->fb.fix.visual) {
189 case FB_VISUAL_TRUECOLOR:
190 if (regno < 16) {
191 u32 *pal = info->pseudo_palette;
192
193 val = chan_to_field(red, &fbi->fb.var.red);
194 val |= chan_to_field(green, &fbi->fb.var.green);
195 val |= chan_to_field(blue, &fbi->fb.var.blue);
196
197 pal[regno] = val;
198 ret = 0;
199 }
200 break;
201 }
202
203 return ret;
204}
205
206static int wm8505fb_pan_display(struct fb_var_screeninfo *var,
207 struct fb_info *info)
208{
209 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
210
211 writel(var->xoffset, fbi->regbase + WMT_GOVR_XPAN);
212 writel(var->yoffset, fbi->regbase + WMT_GOVR_YPAN);
213 return 0;
214}
215
216static int wm8505fb_blank(int blank, struct fb_info *info)
217{
218 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
219
220 switch (blank) {
221 case FB_BLANK_UNBLANK:
222 wm8505fb_set_timing(info);
223 break;
224 default:
225 writel(0, fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
226 break;
227 }
228
229 return 0;
230}
231
232static struct fb_ops wm8505fb_ops = {
233 .owner = THIS_MODULE,
234 .fb_set_par = wm8505fb_set_par,
235 .fb_setcolreg = wm8505fb_setcolreg,
236 .fb_fillrect = wmt_ge_fillrect,
237 .fb_copyarea = wmt_ge_copyarea,
238 .fb_imageblit = sys_imageblit,
239 .fb_sync = wmt_ge_sync,
240 .fb_pan_display = wm8505fb_pan_display,
241 .fb_blank = wm8505fb_blank,
242};
243
244static int __devinit wm8505fb_probe(struct platform_device *pdev)
245{
246 struct wm8505fb_info *fbi;
247 struct resource *res;
248 void *addr;
249 struct vt8500fb_platform_data *pdata;
250 int ret;
251
252 pdata = pdev->dev.platform_data;
253
254 ret = -ENOMEM;
255 fbi = NULL;
256
257 fbi = kzalloc(sizeof(struct wm8505fb_info) + sizeof(u32) * 16,
258 GFP_KERNEL);
259 if (!fbi) {
260 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
261 ret = -ENOMEM;
262 goto failed;
263 }
264
265 strcpy(fbi->fb.fix.id, DRIVER_NAME);
266
267 fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
268 fbi->fb.fix.xpanstep = 1;
269 fbi->fb.fix.ypanstep = 1;
270 fbi->fb.fix.ywrapstep = 0;
271 fbi->fb.fix.accel = FB_ACCEL_NONE;
272
273 fbi->fb.fbops = &wm8505fb_ops;
274 fbi->fb.flags = FBINFO_DEFAULT
275 | FBINFO_HWACCEL_COPYAREA
276 | FBINFO_HWACCEL_FILLRECT
277 | FBINFO_HWACCEL_XPAN
278 | FBINFO_HWACCEL_YPAN
279 | FBINFO_VIRTFB
280 | FBINFO_PARTIAL_PAN_OK;
281 fbi->fb.node = -1;
282
283 addr = fbi;
284 addr = addr + sizeof(struct wm8505fb_info);
285 fbi->fb.pseudo_palette = addr;
286
287 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
288 if (res == NULL) {
289 dev_err(&pdev->dev, "no I/O memory resource defined\n");
290 ret = -ENODEV;
291 goto failed_fbi;
292 }
293
294 res = request_mem_region(res->start, resource_size(res), "wm8505fb");
295 if (res == NULL) {
296 dev_err(&pdev->dev, "failed to request I/O memory\n");
297 ret = -EBUSY;
298 goto failed_fbi;
299 }
300
301 fbi->regbase = ioremap(res->start, resource_size(res));
302 if (fbi->regbase == NULL) {
303 dev_err(&pdev->dev, "failed to map I/O memory\n");
304 ret = -EBUSY;
305 goto failed_free_res;
306 }
307
308 fb_videomode_to_var(&fbi->fb.var, &pdata->mode);
309
310 fbi->fb.var.nonstd = 0;
311 fbi->fb.var.activate = FB_ACTIVATE_NOW;
312
313 fbi->fb.var.height = -1;
314 fbi->fb.var.width = -1;
315 fbi->fb.var.xres_virtual = pdata->xres_virtual;
316 fbi->fb.var.yres_virtual = pdata->yres_virtual;
317 fbi->fb.var.bits_per_pixel = pdata->bpp;
318
319 fbi->fb.fix.smem_start = pdata->video_mem_phys;
320 fbi->fb.fix.smem_len = pdata->video_mem_len;
321 fbi->fb.screen_base = pdata->video_mem_virt;
322 fbi->fb.screen_size = pdata->video_mem_len;
323
324 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
325 dev_err(&pdev->dev, "Failed to allocate color map\n");
326 ret = -ENOMEM;
327 goto failed_free_io;
328 }
329
330 wm8505fb_init_hw(&fbi->fb);
331
332 fbi->contrast = 0x80;
333 ret = wm8505fb_set_par(&fbi->fb);
334 if (ret) {
335 dev_err(&pdev->dev, "Failed to set parameters\n");
336 goto failed_free_cmap;
337 }
338
339 platform_set_drvdata(pdev, fbi);
340
341 ret = register_framebuffer(&fbi->fb);
342 if (ret < 0) {
343 dev_err(&pdev->dev,
344 "Failed to register framebuffer device: %d\n", ret);
345 goto failed_free_cmap;
346 }
347
348 ret = device_create_file(&pdev->dev, &dev_attr_contrast);
349 if (ret < 0) {
350 printk(KERN_WARNING "fb%d: failed to register attributes (%d)\n",
351 fbi->fb.node, ret);
352 }
353
354 printk(KERN_INFO "fb%d: %s frame buffer at 0x%lx-0x%lx\n",
355 fbi->fb.node, fbi->fb.fix.id, fbi->fb.fix.smem_start,
356 fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
357
358 return 0;
359
360failed_free_cmap:
361 if (fbi->fb.cmap.len)
362 fb_dealloc_cmap(&fbi->fb.cmap);
363failed_free_io:
364 iounmap(fbi->regbase);
365failed_free_res:
366 release_mem_region(res->start, resource_size(res));
367failed_fbi:
368 platform_set_drvdata(pdev, NULL);
369 kfree(fbi);
370failed:
371 return ret;
372}
373
374static int __devexit wm8505fb_remove(struct platform_device *pdev)
375{
376 struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
377 struct resource *res;
378
379 device_remove_file(&pdev->dev, &dev_attr_contrast);
380
381 unregister_framebuffer(&fbi->fb);
382
383 writel(0, fbi->regbase);
384
385 if (fbi->fb.cmap.len)
386 fb_dealloc_cmap(&fbi->fb.cmap);
387
388 iounmap(fbi->regbase);
389
390 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
391 release_mem_region(res->start, resource_size(res));
392
393 kfree(fbi);
394
395 return 0;
396}
397
398static struct platform_driver wm8505fb_driver = {
399 .probe = wm8505fb_probe,
400 .remove = __devexit_p(wm8505fb_remove),
401 .driver = {
402 .owner = THIS_MODULE,
403 .name = DRIVER_NAME,
404 },
405};
406
407static int __init wm8505fb_init(void)
408{
409 return platform_driver_register(&wm8505fb_driver);
410}
411
412static void __exit wm8505fb_exit(void)
413{
414 platform_driver_unregister(&wm8505fb_driver);
415}
416
417module_init(wm8505fb_init);
418module_exit(wm8505fb_exit);
419
420MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>");
421MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
422MODULE_LICENSE("GPL");
diff --git a/drivers/video/wm8505fb_regs.h b/drivers/video/wm8505fb_regs.h
new file mode 100644
index 000000000000..4dd41668c6d1
--- /dev/null
+++ b/drivers/video/wm8505fb_regs.h
@@ -0,0 +1,76 @@
1/*
2 * GOVR registers list for WM8505 chips
3 *
4 * Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
5 * Based on VIA/WonderMedia wm8510-govrh-reg.h
6 * http://github.com/projectgus/kernel_wm8505/blob/wm8505_2.6.29/
7 * drivers/video/wmt/register/wm8510/wm8510-govrh-reg.h
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#ifndef _WM8505FB_REGS_H
20#define _WM8505FB_REGS_H
21
22/*
23 * Color space select register, default value 0x1c
24 * BIT0 GOVRH_DVO_YUV2RGB_ENABLE
25 * BIT1 GOVRH_VGA_YUV2RGB_ENABLE
26 * BIT2 GOVRH_RGB_MODE
27 * BIT3 GOVRH_DAC_CLKINV
28 * BIT4 GOVRH_BLANK_ZERO
29 */
30#define WMT_GOVR_COLORSPACE 0x1e4
31/*
32 * Another colorspace select register, default value 1
33 * BIT0 GOVRH_DVO_RGB
34 * BIT1 GOVRH_DVO_YUV422
35 */
36#define WMT_GOVR_COLORSPACE1 0x30
37
38#define WMT_GOVR_CONTRAST 0x1b8
39#define WMT_GOVR_BRGHTNESS 0x1bc /* incompatible with RGB? */
40
41/* Framubeffer address */
42#define WMT_GOVR_FBADDR 0x90
43#define WMT_GOVR_FBADDR1 0x94 /* UV offset in YUV mode */
44
45/* Offset of visible window */
46#define WMT_GOVR_XPAN 0xa4
47#define WMT_GOVR_YPAN 0xa0
48
49#define WMT_GOVR_XRES 0x98
50#define WMT_GOVR_XRES_VIRTUAL 0x9c
51
52#define WMT_GOVR_MIF_ENABLE 0x80
53#define WMT_GOVR_FHI 0xa8
54#define WMT_GOVR_REG_UPDATE 0xe4
55
56/*
57 * BIT0 GOVRH_DVO_OUTWIDTH
58 * BIT1 GOVRH_DVO_SYNC_POLAR
59 * BIT2 GOVRH_DVO_ENABLE
60 */
61#define WMT_GOVR_DVO_SET 0x148
62
63/* Timing generator? */
64#define WMT_GOVR_TG 0x100
65
66/* Timings */
67#define WMT_GOVR_TIMING_H_ALL 0x108
68#define WMT_GOVR_TIMING_V_ALL 0x10c
69#define WMT_GOVR_TIMING_V_START 0x110
70#define WMT_GOVR_TIMING_V_END 0x114
71#define WMT_GOVR_TIMING_H_START 0x118
72#define WMT_GOVR_TIMING_H_END 0x11c
73#define WMT_GOVR_TIMING_V_SYNC 0x128
74#define WMT_GOVR_TIMING_H_SYNC 0x12c
75
76#endif /* _WM8505FB_REGS_H */
diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/wmt_ge_rops.c
new file mode 100644
index 000000000000..f31883f8eaf7
--- /dev/null
+++ b/drivers/video/wmt_ge_rops.c
@@ -0,0 +1,192 @@
1/*
2 * linux/drivers/video/wmt_ge_rops.c
3 *
4 * Accelerators for raster operations using WonderMedia Graphics Engine
5 *
6 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/fb.h>
20#include <linux/platform_device.h>
21#include "fb_draw.h"
22
23#define GE_COMMAND_OFF 0x00
24#define GE_DEPTH_OFF 0x04
25#define GE_HIGHCOLOR_OFF 0x08
26#define GE_ROPCODE_OFF 0x14
27#define GE_FIRE_OFF 0x18
28#define GE_SRCBASE_OFF 0x20
29#define GE_SRCDISPW_OFF 0x24
30#define GE_SRCDISPH_OFF 0x28
31#define GE_SRCAREAX_OFF 0x2c
32#define GE_SRCAREAY_OFF 0x30
33#define GE_SRCAREAW_OFF 0x34
34#define GE_SRCAREAH_OFF 0x38
35#define GE_DESTBASE_OFF 0x3c
36#define GE_DESTDISPW_OFF 0x40
37#define GE_DESTDISPH_OFF 0x44
38#define GE_DESTAREAX_OFF 0x48
39#define GE_DESTAREAY_OFF 0x4c
40#define GE_DESTAREAW_OFF 0x50
41#define GE_DESTAREAH_OFF 0x54
42#define GE_PAT0C_OFF 0x88 /* Pattern 0 color */
43#define GE_ENABLE_OFF 0xec
44#define GE_INTEN_OFF 0xf0
45#define GE_STATUS_OFF 0xf8
46
47static void __iomem *regbase;
48
49void wmt_ge_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
50{
51 unsigned long fg, pat;
52
53 if (p->state != FBINFO_STATE_RUNNING)
54 return;
55
56 if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
57 p->fix.visual == FB_VISUAL_DIRECTCOLOR)
58 fg = ((u32 *) (p->pseudo_palette))[rect->color];
59 else
60 fg = rect->color;
61
62 pat = pixel_to_pat(p->var.bits_per_pixel, fg);
63
64 if (p->fbops->fb_sync)
65 p->fbops->fb_sync(p);
66
67 writel(p->var.bits_per_pixel == 32 ? 3 :
68 (p->var.bits_per_pixel == 8 ? 0 : 1), regbase + GE_DEPTH_OFF);
69 writel(p->var.bits_per_pixel == 15 ? 1 : 0, regbase + GE_HIGHCOLOR_OFF);
70 writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
71 writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
72 writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
73 writel(rect->dx, regbase + GE_DESTAREAX_OFF);
74 writel(rect->dy, regbase + GE_DESTAREAY_OFF);
75 writel(rect->width - 1, regbase + GE_DESTAREAW_OFF);
76 writel(rect->height - 1, regbase + GE_DESTAREAH_OFF);
77
78 writel(pat, regbase + GE_PAT0C_OFF);
79 writel(1, regbase + GE_COMMAND_OFF);
80 writel(rect->rop == ROP_XOR ? 0x5a : 0xf0, regbase + GE_ROPCODE_OFF);
81 writel(1, regbase + GE_FIRE_OFF);
82}
83EXPORT_SYMBOL_GPL(wmt_ge_fillrect);
84
85void wmt_ge_copyarea(struct fb_info *p, const struct fb_copyarea *area)
86{
87 if (p->state != FBINFO_STATE_RUNNING)
88 return;
89
90 if (p->fbops->fb_sync)
91 p->fbops->fb_sync(p);
92
93 writel(p->var.bits_per_pixel > 16 ? 3 :
94 (p->var.bits_per_pixel > 8 ? 1 : 0), regbase + GE_DEPTH_OFF);
95
96 writel(p->fix.smem_start, regbase + GE_SRCBASE_OFF);
97 writel(p->var.xres_virtual - 1, regbase + GE_SRCDISPW_OFF);
98 writel(p->var.yres_virtual - 1, regbase + GE_SRCDISPH_OFF);
99 writel(area->sx, regbase + GE_SRCAREAX_OFF);
100 writel(area->sy, regbase + GE_SRCAREAY_OFF);
101 writel(area->width - 1, regbase + GE_SRCAREAW_OFF);
102 writel(area->height - 1, regbase + GE_SRCAREAH_OFF);
103
104 writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
105 writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
106 writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
107 writel(area->dx, regbase + GE_DESTAREAX_OFF);
108 writel(area->dy, regbase + GE_DESTAREAY_OFF);
109 writel(area->width - 1, regbase + GE_DESTAREAW_OFF);
110 writel(area->height - 1, regbase + GE_DESTAREAH_OFF);
111
112 writel(0xcc, regbase + GE_ROPCODE_OFF);
113 writel(1, regbase + GE_COMMAND_OFF);
114 writel(1, regbase + GE_FIRE_OFF);
115}
116EXPORT_SYMBOL_GPL(wmt_ge_copyarea);
117
118int wmt_ge_sync(struct fb_info *p)
119{
120 int loops = 5000000;
121 while ((readl(regbase + GE_STATUS_OFF) & 4) && --loops)
122 cpu_relax();
123 return loops > 0 ? 0 : -EBUSY;
124}
125EXPORT_SYMBOL_GPL(wmt_ge_sync);
126
127static int __devinit wmt_ge_rops_probe(struct platform_device *pdev)
128{
129 struct resource *res;
130 int ret;
131
132 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
133 if (res == NULL) {
134 dev_err(&pdev->dev, "no I/O memory resource defined\n");
135 ret = -ENODEV;
136 goto error;
137 }
138
139 /* Only one ROP engine is presently supported. */
140 if (unlikely(regbase)) {
141 WARN_ON(1);
142 return -EBUSY;
143 }
144
145 regbase = ioremap(res->start, resource_size(res));
146 if (regbase == NULL) {
147 dev_err(&pdev->dev, "failed to map I/O memory\n");
148 ret = -EBUSY;
149 goto error;
150 }
151
152 writel(1, regbase + GE_ENABLE_OFF);
153 printk(KERN_INFO "Enabled support for WMT GE raster acceleration\n");
154
155 return 0;
156
157error:
158 return ret;
159}
160
161static int __devexit wmt_ge_rops_remove(struct platform_device *pdev)
162{
163 iounmap(regbase);
164 return 0;
165}
166
167static struct platform_driver wmt_ge_rops_driver = {
168 .probe = wmt_ge_rops_probe,
169 .remove = __devexit_p(wmt_ge_rops_remove),
170 .driver = {
171 .owner = THIS_MODULE,
172 .name = "wmt_ge_rops",
173 },
174};
175
176static int __init wmt_ge_rops_init(void)
177{
178 return platform_driver_register(&wmt_ge_rops_driver);
179}
180
181static void __exit wmt_ge_rops_exit(void)
182{
183 platform_driver_unregister(&wmt_ge_rops_driver);
184}
185
186module_init(wmt_ge_rops_init);
187module_exit(wmt_ge_rops_exit);
188
189MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com");
190MODULE_DESCRIPTION("Accelerators for raster operations using "
191 "WonderMedia Graphics Engine");
192MODULE_LICENSE("GPL");
diff --git a/drivers/video/wmt_ge_rops.h b/drivers/video/wmt_ge_rops.h
new file mode 100644
index 000000000000..87380751a443
--- /dev/null
+++ b/drivers/video/wmt_ge_rops.h
@@ -0,0 +1,5 @@
1extern void wmt_ge_fillrect(struct fb_info *info,
2 const struct fb_fillrect *rect);
3extern void wmt_ge_copyarea(struct fb_info *info,
4 const struct fb_copyarea *area);
5extern int wmt_ge_sync(struct fb_info *info);