]> git.ipfire.org Git - thirdparty/kernel/stable.git/blame - drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500
[thirdparty/kernel/stable.git] / drivers / video / fbdev / mb862xx / mb862xxfb_accel.c
CommitLineData
d2912cb1 1// SPDX-License-Identifier: GPL-2.0-only
2ec509b9
VS
2/*
3 * drivers/mb862xx/mb862xxfb_accel.c
4 *
5 * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver acceleration support
6 *
7 * (C) 2007 Alexander Shishkin <virtuoso@slind.org>
da258016 8 * (C) 2009 Valentin Sitdikov <v.sitdikov@gmail.com>
2ec509b9 9 * (C) 2009 Siemens AG
2ec509b9
VS
10 */
11#include <linux/fb.h>
12#include <linux/delay.h>
13#include <linux/init.h>
14#include <linux/interrupt.h>
a71dc148 15#include <linux/module.h>
2ec509b9 16#include <linux/pci.h>
5a0e3ad6 17#include <linux/slab.h>
2ec509b9
VS
18#if defined(CONFIG_OF)
19#include <linux/of_platform.h>
20#endif
21#include "mb862xxfb.h"
22#include "mb862xx_reg.h"
23#include "mb862xxfb_accel.h"
24
25static void mb862xxfb_write_fifo(u32 count, u32 *data, struct fb_info *info)
26{
27 struct mb862xxfb_par *par = info->par;
28 static u32 free;
29
30 u32 total = 0;
31 while (total < count) {
32 if (free) {
33 outreg(geo, GDC_GEO_REG_INPUT_FIFO, data[total]);
34 total++;
35 free--;
36 } else {
37 free = (u32) inreg(draw, GDC_REG_FIFO_COUNT);
38 }
39 }
40}
41
42static void mb86290fb_copyarea(struct fb_info *info,
43 const struct fb_copyarea *area)
44{
45 __u32 cmd[6];
46
47 cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
48 /* Set raster operation */
49 cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
50 cmd[2] = GDC_TYPE_BLTCOPYP << 24;
51
52 if (area->sx >= area->dx && area->sy >= area->dy)
53 cmd[2] |= GDC_CMD_BLTCOPY_TOP_LEFT << 16;
54 else if (area->sx >= area->dx && area->sy <= area->dy)
55 cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_LEFT << 16;
56 else if (area->sx <= area->dx && area->sy >= area->dy)
57 cmd[2] |= GDC_CMD_BLTCOPY_TOP_RIGHT << 16;
58 else
59 cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_RIGHT << 16;
60
61 cmd[3] = (area->sy << 16) | area->sx;
62 cmd[4] = (area->dy << 16) | area->dx;
63 cmd[5] = (area->height << 16) | area->width;
64 mb862xxfb_write_fifo(6, cmd, info);
65}
66
67/*
68 * Fill in the cmd array /GDC FIFO commands/ to draw a 1bit image.
69 * Make sure cmd has enough room!
70 */
71static void mb86290fb_imageblit1(u32 *cmd, u16 step, u16 dx, u16 dy,
72 u16 width, u16 height, u32 fgcolor,
73 u32 bgcolor, const struct fb_image *image,
74 struct fb_info *info)
75{
76 int i;
77 unsigned const char *line;
78 u16 bytes;
79
80 /* set colors and raster operation regs */
81 cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
82 /* Set raster operation */
83 cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
84 cmd[2] =
85 (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
86 cmd[3] = fgcolor;
87 cmd[4] =
88 (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_BACK_COLOR << 16);
89 cmd[5] = bgcolor;
90
91 i = 0;
92 line = image->data;
93 bytes = (image->width + 7) >> 3;
94
95 /* and the image */
96 cmd[6] = (GDC_TYPE_DRAWBITMAPP << 24) |
97 (GDC_CMD_BITMAP << 16) | (2 + (step * height));
98 cmd[7] = (dy << 16) | dx;
99 cmd[8] = (height << 16) | width;
100
101 while (i < height) {
102 memcpy(&cmd[9 + i * step], line, step << 2);
103#ifdef __LITTLE_ENDIAN
104 {
105 int k = 0;
106 for (k = 0; k < step; k++)
107 cmd[9 + i * step + k] =
108 cpu_to_be32(cmd[9 + i * step + k]);
109 }
110#endif
111 line += bytes;
112 i++;
113 }
114}
115
116/*
117 * Fill in the cmd array /GDC FIFO commands/ to draw a 8bit image.
118 * Make sure cmd has enough room!
119 */
120static void mb86290fb_imageblit8(u32 *cmd, u16 step, u16 dx, u16 dy,
121 u16 width, u16 height, u32 fgcolor,
122 u32 bgcolor, const struct fb_image *image,
123 struct fb_info *info)
124{
125 int i, j;
126 unsigned const char *line, *ptr;
127 u16 bytes;
128
129 cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
130 (GDC_CMD_BLT_DRAW << 16) | (2 + (height * step));
131 cmd[1] = (dy << 16) | dx;
132 cmd[2] = (height << 16) | width;
133
134 i = 0;
135 line = ptr = image->data;
136 bytes = image->width;
137
138 while (i < height) {
139 ptr = line;
140 for (j = 0; j < step; j++) {
141 cmd[3 + i * step + j] =
142 (((u32 *) (info->pseudo_palette))[*ptr]) & 0xffff;
143 ptr++;
144 cmd[3 + i * step + j] |=
145 ((((u32 *) (info->
146 pseudo_palette))[*ptr]) & 0xffff) << 16;
147 ptr++;
148 }
149
150 line += bytes;
151 i++;
152 }
153}
154
155/*
156 * Fill in the cmd array /GDC FIFO commands/ to draw a 16bit image.
157 * Make sure cmd has enough room!
158 */
159static void mb86290fb_imageblit16(u32 *cmd, u16 step, u16 dx, u16 dy,
160 u16 width, u16 height, u32 fgcolor,
161 u32 bgcolor, const struct fb_image *image,
162 struct fb_info *info)
163{
164 int i;
165 unsigned const char *line;
166 u16 bytes;
167
168 i = 0;
169 line = image->data;
170 bytes = image->width << 1;
171
172 cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
173 (GDC_CMD_BLT_DRAW << 16) | (2 + step * height);
174 cmd[1] = (dy << 16) | dx;
175 cmd[2] = (height << 16) | width;
176
177 while (i < height) {
178 memcpy(&cmd[3 + i * step], line, step);
179 line += bytes;
180 i++;
181 }
182}
183
184static void mb86290fb_imageblit(struct fb_info *info,
185 const struct fb_image *image)
186{
187 int mdr;
188 u32 *cmd = NULL;
189 void (*cmdfn) (u32 *, u16, u16, u16, u16, u16, u32, u32,
190 const struct fb_image *, struct fb_info *) = NULL;
191 u32 cmdlen;
192 u32 fgcolor = 0, bgcolor = 0;
193 u16 step;
194
195 u16 width = image->width, height = image->height;
196 u16 dx = image->dx, dy = image->dy;
197 int x2, y2, vxres, vyres;
198
199 mdr = (GDC_ROP_COPY << 9);
200 x2 = image->dx + image->width;
201 y2 = image->dy + image->height;
202 vxres = info->var.xres_virtual;
203 vyres = info->var.yres_virtual;
204 x2 = min(x2, vxres);
205 y2 = min(y2, vyres);
206 width = x2 - dx;
207 height = y2 - dy;
208
209 switch (image->depth) {
210 case 1:
211 step = (width + 31) >> 5;
212 cmdlen = 9 + height * step;
213 cmdfn = mb86290fb_imageblit1;
214 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
215 info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
216 fgcolor =
217 ((u32 *) (info->pseudo_palette))[image->fg_color];
218 bgcolor =
219 ((u32 *) (info->pseudo_palette))[image->bg_color];
220 } else {
221 fgcolor = image->fg_color;
222 bgcolor = image->bg_color;
223 }
224
225 break;
226
227 case 8:
228 step = (width + 1) >> 1;
229 cmdlen = 3 + height * step;
230 cmdfn = mb86290fb_imageblit8;
231 break;
232
233 case 16:
234 step = (width + 1) >> 1;
235 cmdlen = 3 + height * step;
236 cmdfn = mb86290fb_imageblit16;
237 break;
238
239 default:
240 cfb_imageblit(info, image);
241 return;
242 }
243
6da2ec56 244 cmd = kmalloc_array(cmdlen, 4, GFP_DMA);
2ec509b9
VS
245 if (!cmd)
246 return cfb_imageblit(info, image);
247 cmdfn(cmd, step, dx, dy, width, height, fgcolor, bgcolor, image, info);
248 mb862xxfb_write_fifo(cmdlen, cmd, info);
249 kfree(cmd);
250}
251
252static void mb86290fb_fillrect(struct fb_info *info,
253 const struct fb_fillrect *rect)
254{
255
256 u32 x2, y2, vxres, vyres, height, width, fg;
257 u32 cmd[7];
258
259 vxres = info->var.xres_virtual;
260 vyres = info->var.yres_virtual;
261
262 if (!rect->width || !rect->height || rect->dx > vxres
263 || rect->dy > vyres)
264 return;
265
266 /* We could use hardware clipping but on many cards you get around
267 * hardware clipping by writing to framebuffer directly. */
268 x2 = rect->dx + rect->width;
269 y2 = rect->dy + rect->height;
270 x2 = min(x2, vxres);
271 y2 = min(y2, vyres);
272 width = x2 - rect->dx;
273 height = y2 - rect->dy;
274 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
275 info->fix.visual == FB_VISUAL_DIRECTCOLOR)
276 fg = ((u32 *) (info->pseudo_palette))[rect->color];
277 else
278 fg = rect->color;
279
280 switch (rect->rop) {
281
282 case ROP_XOR:
283 /* Set raster operation */
284 cmd[1] = (2 << 7) | (GDC_ROP_XOR << 9);
285 break;
286
287 case ROP_COPY:
288 /* Set raster operation */
289 cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
290 break;
291
292 }
293
294 cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
295 /* cmd[1] set earlier */
296 cmd[2] =
297 (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
298 cmd[3] = fg;
299 cmd[4] = (GDC_TYPE_DRAWRECTP << 24) | (GDC_CMD_BLT_FILL << 16);
300 cmd[5] = (rect->dy << 16) | (rect->dx);
301 cmd[6] = (height << 16) | width;
302
303 mb862xxfb_write_fifo(7, cmd, info);
304}
305
306void mb862xxfb_init_accel(struct fb_info *info, int xres)
307{
308 struct mb862xxfb_par *par = info->par;
309
310 if (info->var.bits_per_pixel == 32) {
311 info->fbops->fb_fillrect = cfb_fillrect;
312 info->fbops->fb_copyarea = cfb_copyarea;
313 info->fbops->fb_imageblit = cfb_imageblit;
314 } else {
315 outreg(disp, GC_L0EM, 3);
316 info->fbops->fb_fillrect = mb86290fb_fillrect;
317 info->fbops->fb_copyarea = mb86290fb_copyarea;
318 info->fbops->fb_imageblit = mb86290fb_imageblit;
319 }
320 outreg(draw, GDC_REG_DRAW_BASE, 0);
321 outreg(draw, GDC_REG_MODE_MISC, 0x8000);
322 outreg(draw, GDC_REG_X_RESOLUTION, xres);
323
324 info->flags |=
325 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
326 FBINFO_HWACCEL_IMAGEBLIT;
327 info->fix.accel = 0xff; /*FIXME: add right define */
328}
329EXPORT_SYMBOL(mb862xxfb_init_accel);
a71dc148
RD
330
331MODULE_LICENSE("GPL v2");