1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
/*
* 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 "core/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 wmt_ge_rops_probe(struct platform_device *pdev)
{
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&pdev->dev, "no I/O memory resource defined\n");
return -ENODEV;
}
/* 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");
return -EBUSY;
}
writel(1, regbase + GE_ENABLE_OFF);
printk(KERN_INFO "Enabled support for WMT GE raster acceleration\n");
return 0;
}
static int wmt_ge_rops_remove(struct platform_device *pdev)
{
iounmap(regbase);
return 0;
}
static const struct of_device_id wmt_dt_ids[] = {
{ .compatible = "wm,prizm-ge-rops", },
{ /* sentinel */ }
};
static struct platform_driver wmt_ge_rops_driver = {
.probe = wmt_ge_rops_probe,
.remove = wmt_ge_rops_remove,
.driver = {
.name = "wmt_ge_rops",
.of_match_table = wmt_dt_ids,
},
};
module_platform_driver(wmt_ge_rops_driver);
MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
MODULE_DESCRIPTION("Accelerators for raster operations using "
"WonderMedia Graphics Engine");
MODULE_LICENSE("GPL v2");
MODULE_DEVICE_TABLE(of, wmt_dt_ids);
|