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>
19 #include "mb862xxfb.h"
20 #include "mb862xx_reg.h"
21 #include "mb862xxfb_accel.h"
23 static void mb862xxfb_write_fifo(u32 count
, u32
*data
, struct fb_info
*info
)
25 struct mb862xxfb_par
*par
= info
->par
;
29 while (total
< count
) {
31 outreg(geo
, GDC_GEO_REG_INPUT_FIFO
, data
[total
]);
35 free
= (u32
) inreg(draw
, GDC_REG_FIFO_COUNT
);
40 static void mb86290fb_copyarea(struct fb_info
*info
,
41 const struct fb_copyarea
*area
)
45 cmd
[0] = (GDC_TYPE_SETREGISTER
<< 24) | (1 << 16) | GDC_REG_MODE_BITMAP
;
46 /* Set raster operation */
47 cmd
[1] = (2 << 7) | (GDC_ROP_COPY
<< 9);
48 cmd
[2] = GDC_TYPE_BLTCOPYP
<< 24;
50 if (area
->sx
>= area
->dx
&& area
->sy
>= area
->dy
)
51 cmd
[2] |= GDC_CMD_BLTCOPY_TOP_LEFT
<< 16;
52 else if (area
->sx
>= area
->dx
&& area
->sy
<= area
->dy
)
53 cmd
[2] |= GDC_CMD_BLTCOPY_BOTTOM_LEFT
<< 16;
54 else if (area
->sx
<= area
->dx
&& area
->sy
>= area
->dy
)
55 cmd
[2] |= GDC_CMD_BLTCOPY_TOP_RIGHT
<< 16;
57 cmd
[2] |= GDC_CMD_BLTCOPY_BOTTOM_RIGHT
<< 16;
59 cmd
[3] = (area
->sy
<< 16) | area
->sx
;
60 cmd
[4] = (area
->dy
<< 16) | area
->dx
;
61 cmd
[5] = (area
->height
<< 16) | area
->width
;
62 mb862xxfb_write_fifo(6, cmd
, info
);
66 * Fill in the cmd array /GDC FIFO commands/ to draw a 1bit image.
67 * Make sure cmd has enough room!
69 static void mb86290fb_imageblit1(u32
*cmd
, u16 step
, u16 dx
, u16 dy
,
70 u16 width
, u16 height
, u32 fgcolor
,
71 u32 bgcolor
, const struct fb_image
*image
,
75 unsigned const char *line
;
78 /* set colors and raster operation regs */
79 cmd
[0] = (GDC_TYPE_SETREGISTER
<< 24) | (1 << 16) | GDC_REG_MODE_BITMAP
;
80 /* Set raster operation */
81 cmd
[1] = (2 << 7) | (GDC_ROP_COPY
<< 9);
83 (GDC_TYPE_SETCOLORREGISTER
<< 24) | (GDC_CMD_BODY_FORE_COLOR
<< 16);
86 (GDC_TYPE_SETCOLORREGISTER
<< 24) | (GDC_CMD_BODY_BACK_COLOR
<< 16);
91 bytes
= (image
->width
+ 7) >> 3;
94 cmd
[6] = (GDC_TYPE_DRAWBITMAPP
<< 24) |
95 (GDC_CMD_BITMAP
<< 16) | (2 + (step
* height
));
96 cmd
[7] = (dy
<< 16) | dx
;
97 cmd
[8] = (height
<< 16) | width
;
100 memcpy(&cmd
[9 + i
* step
], line
, step
<< 2);
101 #ifdef __LITTLE_ENDIAN
104 for (k
= 0; k
< step
; k
++)
105 cmd
[9 + i
* step
+ k
] =
106 cpu_to_be32(cmd
[9 + i
* step
+ k
]);
115 * Fill in the cmd array /GDC FIFO commands/ to draw a 8bit image.
116 * Make sure cmd has enough room!
118 static void mb86290fb_imageblit8(u32
*cmd
, u16 step
, u16 dx
, u16 dy
,
119 u16 width
, u16 height
, u32 fgcolor
,
120 u32 bgcolor
, const struct fb_image
*image
,
121 struct fb_info
*info
)
124 unsigned const char *line
, *ptr
;
127 cmd
[0] = (GDC_TYPE_DRAWBITMAPP
<< 24) |
128 (GDC_CMD_BLT_DRAW
<< 16) | (2 + (height
* step
));
129 cmd
[1] = (dy
<< 16) | dx
;
130 cmd
[2] = (height
<< 16) | width
;
134 bytes
= image
->width
;
138 for (j
= 0; j
< step
; j
++) {
139 cmd
[3 + i
* step
+ j
] =
140 (((u32
*) (info
->pseudo_palette
))[*ptr
]) & 0xffff;
142 cmd
[3 + i
* step
+ j
] |=
144 pseudo_palette
))[*ptr
]) & 0xffff) << 16;
154 * Fill in the cmd array /GDC FIFO commands/ to draw a 16bit image.
155 * Make sure cmd has enough room!
157 static void mb86290fb_imageblit16(u32
*cmd
, u16 step
, u16 dx
, u16 dy
,
158 u16 width
, u16 height
, u32 fgcolor
,
159 u32 bgcolor
, const struct fb_image
*image
,
160 struct fb_info
*info
)
163 unsigned const char *line
;
168 bytes
= image
->width
<< 1;
170 cmd
[0] = (GDC_TYPE_DRAWBITMAPP
<< 24) |
171 (GDC_CMD_BLT_DRAW
<< 16) | (2 + step
* height
);
172 cmd
[1] = (dy
<< 16) | dx
;
173 cmd
[2] = (height
<< 16) | width
;
176 memcpy(&cmd
[3 + i
* step
], line
, step
);
182 static void mb86290fb_imageblit(struct fb_info
*info
,
183 const struct fb_image
*image
)
186 void (*cmdfn
) (u32
*, u16
, u16
, u16
, u16
, u16
, u32
, u32
,
187 const struct fb_image
*, struct fb_info
*) = NULL
;
189 u32 fgcolor
= 0, bgcolor
= 0;
192 u16 width
= image
->width
, height
= image
->height
;
193 u16 dx
= image
->dx
, dy
= image
->dy
;
194 int x2
, y2
, vxres
, vyres
;
196 x2
= image
->dx
+ image
->width
;
197 y2
= image
->dy
+ image
->height
;
198 vxres
= info
->var
.xres_virtual
;
199 vyres
= info
->var
.yres_virtual
;
205 switch (image
->depth
) {
207 step
= (width
+ 31) >> 5;
208 cmdlen
= 9 + height
* step
;
209 cmdfn
= mb86290fb_imageblit1
;
210 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
211 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
) {
213 ((u32
*) (info
->pseudo_palette
))[image
->fg_color
];
215 ((u32
*) (info
->pseudo_palette
))[image
->bg_color
];
217 fgcolor
= image
->fg_color
;
218 bgcolor
= image
->bg_color
;
224 step
= (width
+ 1) >> 1;
225 cmdlen
= 3 + height
* step
;
226 cmdfn
= mb86290fb_imageblit8
;
230 step
= (width
+ 1) >> 1;
231 cmdlen
= 3 + height
* step
;
232 cmdfn
= mb86290fb_imageblit16
;
236 cfb_imageblit(info
, image
);
240 cmd
= kmalloc_array(cmdlen
, 4, GFP_DMA
);
242 return cfb_imageblit(info
, image
);
243 cmdfn(cmd
, step
, dx
, dy
, width
, height
, fgcolor
, bgcolor
, image
, info
);
244 mb862xxfb_write_fifo(cmdlen
, cmd
, info
);
248 static void mb86290fb_fillrect(struct fb_info
*info
,
249 const struct fb_fillrect
*rect
)
252 u32 x2
, y2
, vxres
, vyres
, height
, width
, fg
;
255 vxres
= info
->var
.xres_virtual
;
256 vyres
= info
->var
.yres_virtual
;
258 if (!rect
->width
|| !rect
->height
|| rect
->dx
> vxres
262 /* We could use hardware clipping but on many cards you get around
263 * hardware clipping by writing to framebuffer directly. */
264 x2
= rect
->dx
+ rect
->width
;
265 y2
= rect
->dy
+ rect
->height
;
268 width
= x2
- rect
->dx
;
269 height
= y2
- rect
->dy
;
270 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
271 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
272 fg
= ((u32
*) (info
->pseudo_palette
))[rect
->color
];
279 /* Set raster operation */
280 cmd
[1] = (2 << 7) | (GDC_ROP_XOR
<< 9);
284 /* Set raster operation */
285 cmd
[1] = (2 << 7) | (GDC_ROP_COPY
<< 9);
290 cmd
[0] = (GDC_TYPE_SETREGISTER
<< 24) | (1 << 16) | GDC_REG_MODE_BITMAP
;
291 /* cmd[1] set earlier */
293 (GDC_TYPE_SETCOLORREGISTER
<< 24) | (GDC_CMD_BODY_FORE_COLOR
<< 16);
295 cmd
[4] = (GDC_TYPE_DRAWRECTP
<< 24) | (GDC_CMD_BLT_FILL
<< 16);
296 cmd
[5] = (rect
->dy
<< 16) | (rect
->dx
);
297 cmd
[6] = (height
<< 16) | width
;
299 mb862xxfb_write_fifo(7, cmd
, info
);
302 void mb862xxfb_init_accel(struct fb_info
*info
, struct fb_ops
*fbops
, int xres
)
304 struct mb862xxfb_par
*par
= info
->par
;
306 if (info
->var
.bits_per_pixel
== 32) {
307 fbops
->fb_fillrect
= cfb_fillrect
;
308 fbops
->fb_copyarea
= cfb_copyarea
;
309 fbops
->fb_imageblit
= cfb_imageblit
;
311 outreg(disp
, GC_L0EM
, 3);
312 fbops
->fb_fillrect
= mb86290fb_fillrect
;
313 fbops
->fb_copyarea
= mb86290fb_copyarea
;
314 fbops
->fb_imageblit
= mb86290fb_imageblit
;
316 outreg(draw
, GDC_REG_DRAW_BASE
, 0);
317 outreg(draw
, GDC_REG_MODE_MISC
, 0x8000);
318 outreg(draw
, GDC_REG_X_RESOLUTION
, xres
);
321 FBINFO_HWACCEL_COPYAREA
| FBINFO_HWACCEL_FILLRECT
|
322 FBINFO_HWACCEL_IMAGEBLIT
;
323 info
->fix
.accel
= 0xff; /*FIXME: add right define */
326 MODULE_LICENSE("GPL v2");