hc
2023-12-06 d38611ca164021d018c1b23eee65bbebc09c63e0
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
// SPDX-License-Identifier: GPL-2.0-only
/*
 *  linux/drivers/video/wmt_ge_rops.c
 *
 *  Accelerators for raster operations using WonderMedia Graphics Engine
 *
 *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
 */
 
#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);