1 // SPDX-License-Identifier: GPL-2.0-only
3 * drivers/mb862xx/mb862xxfb_accel.c
5 * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver acceleration support
7 * (C) 2007 Alexander Shishkin <virtuoso@slind.org>
8 * (C) 2009 Valentin Sitdikov <v.sitdikov@gmail.com>
12 #include <linux/delay.h>
13 #include <linux/init.h>
14 #include <linux/interrupt.h>
15 #include <linux/module.h>
16 #include <linux/pci.h>
17 #include <linux/slab.h>
18 #if defined(CONFIG_OF)
19 #include <linux/of_platform.h>
21 #include "mb862xxfb.h"
22 #include "mb862xx_reg.h"
23 #include "mb862xxfb_accel.h"
25 static void mb862xxfb_write_fifo(u32 count
, u32
*data
, struct fb_info
*info
)
27 struct mb862xxfb_par
*par
= info
->par
;
31 while (total
< count
) {
33 outreg(geo
, GDC_GEO_REG_INPUT_FIFO
, data
[total
]);
37 free
= (u32
) inreg(draw
, GDC_REG_FIFO_COUNT
);
42 static void mb86290fb_copyarea(struct fb_info
*info
,
43 const struct fb_copyarea
*area
)
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;
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;
59 cmd
[2] |= GDC_CMD_BLTCOPY_BOTTOM_RIGHT
<< 16;
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
);
68 * Fill in the cmd array /GDC FIFO commands/ to draw a 1bit image.
69 * Make sure cmd has enough room!
71 static 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
,
77 unsigned const char *line
;
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);
85 (GDC_TYPE_SETCOLORREGISTER
<< 24) | (GDC_CMD_BODY_FORE_COLOR
<< 16);
88 (GDC_TYPE_SETCOLORREGISTER
<< 24) | (GDC_CMD_BODY_BACK_COLOR
<< 16);
93 bytes
= (image
->width
+ 7) >> 3;
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
;
102 memcpy(&cmd
[9 + i
* step
], line
, step
<< 2);
103 #ifdef __LITTLE_ENDIAN
106 for (k
= 0; k
< step
; k
++)
107 cmd
[9 + i
* step
+ k
] =
108 cpu_to_be32(cmd
[9 + i
* step
+ k
]);
117 * Fill in the cmd array /GDC FIFO commands/ to draw a 8bit image.
118 * Make sure cmd has enough room!
120 static 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
)
126 unsigned const char *line
, *ptr
;
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
;
135 line
= ptr
= image
->data
;
136 bytes
= image
->width
;
140 for (j
= 0; j
< step
; j
++) {
141 cmd
[3 + i
* step
+ j
] =
142 (((u32
*) (info
->pseudo_palette
))[*ptr
]) & 0xffff;
144 cmd
[3 + i
* step
+ j
] |=
146 pseudo_palette
))[*ptr
]) & 0xffff) << 16;
156 * Fill in the cmd array /GDC FIFO commands/ to draw a 16bit image.
157 * Make sure cmd has enough room!
159 static 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
)
165 unsigned const char *line
;
170 bytes
= image
->width
<< 1;
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
;
178 memcpy(&cmd
[3 + i
* step
], line
, step
);
184 static void mb86290fb_imageblit(struct fb_info
*info
,
185 const struct fb_image
*image
)
188 void (*cmdfn
) (u32
*, u16
, u16
, u16
, u16
, u16
, u32
, u32
,
189 const struct fb_image
*, struct fb_info
*) = NULL
;
191 u32 fgcolor
= 0, bgcolor
= 0;
194 u16 width
= image
->width
, height
= image
->height
;
195 u16 dx
= image
->dx
, dy
= image
->dy
;
196 int x2
, y2
, vxres
, vyres
;
198 x2
= image
->dx
+ image
->width
;
199 y2
= image
->dy
+ image
->height
;
200 vxres
= info
->var
.xres_virtual
;
201 vyres
= info
->var
.yres_virtual
;
207 switch (image
->depth
) {
209 step
= (width
+ 31) >> 5;
210 cmdlen
= 9 + height
* step
;
211 cmdfn
= mb86290fb_imageblit1
;
212 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
213 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
) {
215 ((u32
*) (info
->pseudo_palette
))[image
->fg_color
];
217 ((u32
*) (info
->pseudo_palette
))[image
->bg_color
];
219 fgcolor
= image
->fg_color
;
220 bgcolor
= image
->bg_color
;
226 step
= (width
+ 1) >> 1;
227 cmdlen
= 3 + height
* step
;
228 cmdfn
= mb86290fb_imageblit8
;
232 step
= (width
+ 1) >> 1;
233 cmdlen
= 3 + height
* step
;
234 cmdfn
= mb86290fb_imageblit16
;
238 cfb_imageblit(info
, image
);
242 cmd
= kmalloc_array(cmdlen
, 4, GFP_DMA
);
244 return cfb_imageblit(info
, image
);
245 cmdfn(cmd
, step
, dx
, dy
, width
, height
, fgcolor
, bgcolor
, image
, info
);
246 mb862xxfb_write_fifo(cmdlen
, cmd
, info
);
250 static void mb86290fb_fillrect(struct fb_info
*info
,
251 const struct fb_fillrect
*rect
)
254 u32 x2
, y2
, vxres
, vyres
, height
, width
, fg
;
257 vxres
= info
->var
.xres_virtual
;
258 vyres
= info
->var
.yres_virtual
;
260 if (!rect
->width
|| !rect
->height
|| rect
->dx
> vxres
264 /* We could use hardware clipping but on many cards you get around
265 * hardware clipping by writing to framebuffer directly. */
266 x2
= rect
->dx
+ rect
->width
;
267 y2
= rect
->dy
+ rect
->height
;
270 width
= x2
- rect
->dx
;
271 height
= y2
- rect
->dy
;
272 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
273 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
274 fg
= ((u32
*) (info
->pseudo_palette
))[rect
->color
];
281 /* Set raster operation */
282 cmd
[1] = (2 << 7) | (GDC_ROP_XOR
<< 9);
286 /* Set raster operation */
287 cmd
[1] = (2 << 7) | (GDC_ROP_COPY
<< 9);
292 cmd
[0] = (GDC_TYPE_SETREGISTER
<< 24) | (1 << 16) | GDC_REG_MODE_BITMAP
;
293 /* cmd[1] set earlier */
295 (GDC_TYPE_SETCOLORREGISTER
<< 24) | (GDC_CMD_BODY_FORE_COLOR
<< 16);
297 cmd
[4] = (GDC_TYPE_DRAWRECTP
<< 24) | (GDC_CMD_BLT_FILL
<< 16);
298 cmd
[5] = (rect
->dy
<< 16) | (rect
->dx
);
299 cmd
[6] = (height
<< 16) | width
;
301 mb862xxfb_write_fifo(7, cmd
, info
);
304 void mb862xxfb_init_accel(struct fb_info
*info
, struct fb_ops
*fbops
, int xres
)
306 struct mb862xxfb_par
*par
= info
->par
;
308 if (info
->var
.bits_per_pixel
== 32) {
309 fbops
->fb_fillrect
= cfb_fillrect
;
310 fbops
->fb_copyarea
= cfb_copyarea
;
311 fbops
->fb_imageblit
= cfb_imageblit
;
313 outreg(disp
, GC_L0EM
, 3);
314 fbops
->fb_fillrect
= mb86290fb_fillrect
;
315 fbops
->fb_copyarea
= mb86290fb_copyarea
;
316 fbops
->fb_imageblit
= mb86290fb_imageblit
;
318 outreg(draw
, GDC_REG_DRAW_BASE
, 0);
319 outreg(draw
, GDC_REG_MODE_MISC
, 0x8000);
320 outreg(draw
, GDC_REG_X_RESOLUTION
, xres
);
323 FBINFO_HWACCEL_COPYAREA
| FBINFO_HWACCEL_FILLRECT
|
324 FBINFO_HWACCEL_IMAGEBLIT
;
325 info
->fix
.accel
= 0xff; /*FIXME: add right define */
328 MODULE_LICENSE("GPL v2");