summaryrefslogtreecommitdiff
path: root/drivers/video/wmt_ge_rops.c
diff options
context:
space:
mode:
authorAlexey Charkov <alchark@gmail.com>2010-11-09 02:42:39 +0300
committerPaul Mundt <lethal@linux-sh.org>2010-11-09 18:52:07 +0900
commitd6ff7d0fe22cdf3ea41c48b50da9a9181500d1bf (patch)
treef14609b2e10c9b381c1905a3a895729293119929 /drivers/video/wmt_ge_rops.c
parenta7bcf21e60c73cb7f7c13fad928967d7e47c3cac (diff)
ARM: Add support for the display controllers in VT8500 and WM8505
This adds drivers for the LCD controller found in VIA VT8500 SoC, GOVR display controller found in WonderMedia WM8505 SoC and for the Graphics Engine present in both of them that provides hardware accelerated raster operations (used for copyarea and fillrect). Signed-off-by: Alexey Charkov <alchark@gmail.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/video/wmt_ge_rops.c')
-rw-r--r--drivers/video/wmt_ge_rops.c192
1 files changed, 192 insertions, 0 deletions
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 @@
+/*
+ * linux/drivers/video/wmt_ge_rops.c
+ *
+ * Accelerators for raster operations using WonderMedia Graphics Engine
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/platform_device.h>
+#include "fb_draw.h"
+
+#define GE_COMMAND_OFF 0x00
+#define GE_DEPTH_OFF 0x04
+#define GE_HIGHCOLOR_OFF 0x08
+#define GE_ROPCODE_OFF 0x14
+#define GE_FIRE_OFF 0x18
+#define GE_SRCBASE_OFF 0x20
+#define GE_SRCDISPW_OFF 0x24
+#define GE_SRCDISPH_OFF 0x28
+#define GE_SRCAREAX_OFF 0x2c
+#define GE_SRCAREAY_OFF 0x30
+#define GE_SRCAREAW_OFF 0x34
+#define GE_SRCAREAH_OFF 0x38
+#define GE_DESTBASE_OFF 0x3c
+#define GE_DESTDISPW_OFF 0x40
+#define GE_DESTDISPH_OFF 0x44
+#define GE_DESTAREAX_OFF 0x48
+#define GE_DESTAREAY_OFF 0x4c
+#define GE_DESTAREAW_OFF 0x50
+#define GE_DESTAREAH_OFF 0x54
+#define GE_PAT0C_OFF 0x88 /* Pattern 0 color */
+#define GE_ENABLE_OFF 0xec
+#define GE_INTEN_OFF 0xf0
+#define GE_STATUS_OFF 0xf8
+
+static void __iomem *regbase;
+
+void wmt_ge_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+ unsigned long fg, pat;
+
+ if (p->state != FBINFO_STATE_RUNNING)
+ return;
+
+ if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+ p->fix.visual == FB_VISUAL_DIRECTCOLOR)
+ fg = ((u32 *) (p->pseudo_palette))[rect->color];
+ else
+ fg = rect->color;
+
+ pat = pixel_to_pat(p->var.bits_per_pixel, fg);
+
+ if (p->fbops->fb_sync)
+ p->fbops->fb_sync(p);
+
+ writel(p->var.bits_per_pixel == 32 ? 3 :
+ (p->var.bits_per_pixel == 8 ? 0 : 1), regbase + GE_DEPTH_OFF);
+ writel(p->var.bits_per_pixel == 15 ? 1 : 0, regbase + GE_HIGHCOLOR_OFF);
+ writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
+ writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
+ writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
+ writel(rect->dx, regbase + GE_DESTAREAX_OFF);
+ writel(rect->dy, regbase + GE_DESTAREAY_OFF);
+ writel(rect->width - 1, regbase + GE_DESTAREAW_OFF);
+ writel(rect->height - 1, regbase + GE_DESTAREAH_OFF);
+
+ writel(pat, regbase + GE_PAT0C_OFF);
+ writel(1, regbase + GE_COMMAND_OFF);
+ writel(rect->rop == ROP_XOR ? 0x5a : 0xf0, regbase + GE_ROPCODE_OFF);
+ writel(1, regbase + GE_FIRE_OFF);
+}
+EXPORT_SYMBOL_GPL(wmt_ge_fillrect);
+
+void wmt_ge_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+ if (p->state != FBINFO_STATE_RUNNING)
+ return;
+
+ if (p->fbops->fb_sync)
+ p->fbops->fb_sync(p);
+
+ writel(p->var.bits_per_pixel > 16 ? 3 :
+ (p->var.bits_per_pixel > 8 ? 1 : 0), regbase + GE_DEPTH_OFF);
+
+ writel(p->fix.smem_start, regbase + GE_SRCBASE_OFF);
+ writel(p->var.xres_virtual - 1, regbase + GE_SRCDISPW_OFF);
+ writel(p->var.yres_virtual - 1, regbase + GE_SRCDISPH_OFF);
+ writel(area->sx, regbase + GE_SRCAREAX_OFF);
+ writel(area->sy, regbase + GE_SRCAREAY_OFF);
+ writel(area->width - 1, regbase + GE_SRCAREAW_OFF);
+ writel(area->height - 1, regbase + GE_SRCAREAH_OFF);
+
+ writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
+ writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
+ writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
+ writel(area->dx, regbase + GE_DESTAREAX_OFF);
+ writel(area->dy, regbase + GE_DESTAREAY_OFF);
+ writel(area->width - 1, regbase + GE_DESTAREAW_OFF);
+ writel(area->height - 1, regbase + GE_DESTAREAH_OFF);
+
+ writel(0xcc, regbase + GE_ROPCODE_OFF);
+ writel(1, regbase + GE_COMMAND_OFF);
+ writel(1, regbase + GE_FIRE_OFF);
+}
+EXPORT_SYMBOL_GPL(wmt_ge_copyarea);
+
+int wmt_ge_sync(struct fb_info *p)
+{
+ int loops = 5000000;
+ while ((readl(regbase + GE_STATUS_OFF) & 4) && --loops)
+ cpu_relax();
+ return loops > 0 ? 0 : -EBUSY;
+}
+EXPORT_SYMBOL_GPL(wmt_ge_sync);
+
+static int __devinit wmt_ge_rops_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "no I/O memory resource defined\n");
+ ret = -ENODEV;
+ goto error;
+ }
+
+ /* Only one ROP engine is presently supported. */
+ if (unlikely(regbase)) {
+ WARN_ON(1);
+ return -EBUSY;
+ }
+
+ regbase = ioremap(res->start, resource_size(res));
+ if (regbase == NULL) {
+ dev_err(&pdev->dev, "failed to map I/O memory\n");
+ ret = -EBUSY;
+ goto error;
+ }
+
+ writel(1, regbase + GE_ENABLE_OFF);
+ printk(KERN_INFO "Enabled support for WMT GE raster acceleration\n");
+
+ return 0;
+
+error:
+ return ret;
+}
+
+static int __devexit wmt_ge_rops_remove(struct platform_device *pdev)
+{
+ iounmap(regbase);
+ return 0;
+}
+
+static struct platform_driver wmt_ge_rops_driver = {
+ .probe = wmt_ge_rops_probe,
+ .remove = __devexit_p(wmt_ge_rops_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "wmt_ge_rops",
+ },
+};
+
+static int __init wmt_ge_rops_init(void)
+{
+ return platform_driver_register(&wmt_ge_rops_driver);
+}
+
+static void __exit wmt_ge_rops_exit(void)
+{
+ platform_driver_unregister(&wmt_ge_rops_driver);
+}
+
+module_init(wmt_ge_rops_init);
+module_exit(wmt_ge_rops_exit);
+
+MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com");
+MODULE_DESCRIPTION("Accelerators for raster operations using "
+ "WonderMedia Graphics Engine");
+MODULE_LICENSE("GPL");