Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * drivers/mb862xx/mb862xxfb_accel.c
0004  *
0005  * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver acceleration support
0006  *
0007  * (C) 2007 Alexander Shishkin <virtuoso@slind.org>
0008  * (C) 2009 Valentin Sitdikov <v.sitdikov@gmail.com>
0009  * (C) 2009 Siemens AG
0010  */
0011 #include <linux/fb.h>
0012 #include <linux/delay.h>
0013 #include <linux/init.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/module.h>
0016 #include <linux/pci.h>
0017 #include <linux/slab.h>
0018 #if defined(CONFIG_OF)
0019 #include <linux/of_platform.h>
0020 #endif
0021 #include "mb862xxfb.h"
0022 #include "mb862xx_reg.h"
0023 #include "mb862xxfb_accel.h"
0024 
0025 static void mb862xxfb_write_fifo(u32 count, u32 *data, struct fb_info *info)
0026 {
0027     struct mb862xxfb_par *par = info->par;
0028     static u32 free;
0029 
0030     u32 total = 0;
0031     while (total < count) {
0032         if (free) {
0033             outreg(geo, GDC_GEO_REG_INPUT_FIFO, data[total]);
0034             total++;
0035             free--;
0036         } else {
0037             free = (u32) inreg(draw, GDC_REG_FIFO_COUNT);
0038         }
0039     }
0040 }
0041 
0042 static void mb86290fb_copyarea(struct fb_info *info,
0043                    const struct fb_copyarea *area)
0044 {
0045     __u32 cmd[6];
0046 
0047     cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
0048     /* Set raster operation */
0049     cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
0050     cmd[2] = GDC_TYPE_BLTCOPYP << 24;
0051 
0052     if (area->sx >= area->dx && area->sy >= area->dy)
0053         cmd[2] |= GDC_CMD_BLTCOPY_TOP_LEFT << 16;
0054     else if (area->sx >= area->dx && area->sy <= area->dy)
0055         cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_LEFT << 16;
0056     else if (area->sx <= area->dx && area->sy >= area->dy)
0057         cmd[2] |= GDC_CMD_BLTCOPY_TOP_RIGHT << 16;
0058     else
0059         cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_RIGHT << 16;
0060 
0061     cmd[3] = (area->sy << 16) | area->sx;
0062     cmd[4] = (area->dy << 16) | area->dx;
0063     cmd[5] = (area->height << 16) | area->width;
0064     mb862xxfb_write_fifo(6, cmd, info);
0065 }
0066 
0067 /*
0068  * Fill in the cmd array /GDC FIFO commands/ to draw a 1bit image.
0069  * Make sure cmd has enough room!
0070  */
0071 static void mb86290fb_imageblit1(u32 *cmd, u16 step, u16 dx, u16 dy,
0072                  u16 width, u16 height, u32 fgcolor,
0073                  u32 bgcolor, const struct fb_image *image,
0074                  struct fb_info *info)
0075 {
0076     int i;
0077     unsigned const char *line;
0078     u16 bytes;
0079 
0080     /* set colors and raster operation regs */
0081     cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
0082     /* Set raster operation */
0083     cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
0084     cmd[2] =
0085         (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
0086     cmd[3] = fgcolor;
0087     cmd[4] =
0088         (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_BACK_COLOR << 16);
0089     cmd[5] = bgcolor;
0090 
0091     i = 0;
0092     line = image->data;
0093     bytes = (image->width + 7) >> 3;
0094 
0095     /* and the image */
0096     cmd[6] = (GDC_TYPE_DRAWBITMAPP << 24) |
0097         (GDC_CMD_BITMAP << 16) | (2 + (step * height));
0098     cmd[7] = (dy << 16) | dx;
0099     cmd[8] = (height << 16) | width;
0100 
0101     while (i < height) {
0102         memcpy(&cmd[9 + i * step], line, step << 2);
0103 #ifdef __LITTLE_ENDIAN
0104         {
0105             int k = 0;
0106             for (k = 0; k < step; k++)
0107                 cmd[9 + i * step + k] =
0108                     cpu_to_be32(cmd[9 + i * step + k]);
0109         }
0110 #endif
0111         line += bytes;
0112         i++;
0113     }
0114 }
0115 
0116 /*
0117  * Fill in the cmd array /GDC FIFO commands/ to draw a 8bit image.
0118  * Make sure cmd has enough room!
0119  */
0120 static void mb86290fb_imageblit8(u32 *cmd, u16 step, u16 dx, u16 dy,
0121                  u16 width, u16 height, u32 fgcolor,
0122                  u32 bgcolor, const struct fb_image *image,
0123                  struct fb_info *info)
0124 {
0125     int i, j;
0126     unsigned const char *line, *ptr;
0127     u16 bytes;
0128 
0129     cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
0130         (GDC_CMD_BLT_DRAW << 16) | (2 + (height * step));
0131     cmd[1] = (dy << 16) | dx;
0132     cmd[2] = (height << 16) | width;
0133 
0134     i = 0;
0135     line = image->data;
0136     bytes = image->width;
0137 
0138     while (i < height) {
0139         ptr = line;
0140         for (j = 0; j < step; j++) {
0141             cmd[3 + i * step + j] =
0142                 (((u32 *) (info->pseudo_palette))[*ptr]) & 0xffff;
0143             ptr++;
0144             cmd[3 + i * step + j] |=
0145                 ((((u32 *) (info->
0146                     pseudo_palette))[*ptr]) & 0xffff) << 16;
0147             ptr++;
0148         }
0149 
0150         line += bytes;
0151         i++;
0152     }
0153 }
0154 
0155 /*
0156  * Fill in the cmd array /GDC FIFO commands/ to draw a 16bit image.
0157  * Make sure cmd has enough room!
0158  */
0159 static void mb86290fb_imageblit16(u32 *cmd, u16 step, u16 dx, u16 dy,
0160                   u16 width, u16 height, u32 fgcolor,
0161                   u32 bgcolor, const struct fb_image *image,
0162                   struct fb_info *info)
0163 {
0164     int i;
0165     unsigned const char *line;
0166     u16 bytes;
0167 
0168     i = 0;
0169     line = image->data;
0170     bytes = image->width << 1;
0171 
0172     cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
0173         (GDC_CMD_BLT_DRAW << 16) | (2 + step * height);
0174     cmd[1] = (dy << 16) | dx;
0175     cmd[2] = (height << 16) | width;
0176 
0177     while (i < height) {
0178         memcpy(&cmd[3 + i * step], line, step);
0179         line += bytes;
0180         i++;
0181     }
0182 }
0183 
0184 static void mb86290fb_imageblit(struct fb_info *info,
0185                 const struct fb_image *image)
0186 {
0187     u32 *cmd = NULL;
0188     void (*cmdfn) (u32 *, u16, u16, u16, u16, u16, u32, u32,
0189                const struct fb_image *, struct fb_info *) = NULL;
0190     u32 cmdlen;
0191     u32 fgcolor = 0, bgcolor = 0;
0192     u16 step;
0193 
0194     u16 width = image->width, height = image->height;
0195     u16 dx = image->dx, dy = image->dy;
0196     int x2, y2, vxres, vyres;
0197 
0198     x2 = image->dx + image->width;
0199     y2 = image->dy + image->height;
0200     vxres = info->var.xres_virtual;
0201     vyres = info->var.yres_virtual;
0202     x2 = min(x2, vxres);
0203     y2 = min(y2, vyres);
0204     width = x2 - dx;
0205     height = y2 - dy;
0206 
0207     switch (image->depth) {
0208     case 1:
0209         step = (width + 31) >> 5;
0210         cmdlen = 9 + height * step;
0211         cmdfn = mb86290fb_imageblit1;
0212         if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
0213             info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
0214             fgcolor =
0215                 ((u32 *) (info->pseudo_palette))[image->fg_color];
0216             bgcolor =
0217                 ((u32 *) (info->pseudo_palette))[image->bg_color];
0218         } else {
0219             fgcolor = image->fg_color;
0220             bgcolor = image->bg_color;
0221         }
0222 
0223         break;
0224 
0225     case 8:
0226         step = (width + 1) >> 1;
0227         cmdlen = 3 + height * step;
0228         cmdfn = mb86290fb_imageblit8;
0229         break;
0230 
0231     case 16:
0232         step = (width + 1) >> 1;
0233         cmdlen = 3 + height * step;
0234         cmdfn = mb86290fb_imageblit16;
0235         break;
0236 
0237     default:
0238         cfb_imageblit(info, image);
0239         return;
0240     }
0241 
0242     cmd = kmalloc_array(cmdlen, 4, GFP_DMA);
0243     if (!cmd)
0244         return cfb_imageblit(info, image);
0245     cmdfn(cmd, step, dx, dy, width, height, fgcolor, bgcolor, image, info);
0246     mb862xxfb_write_fifo(cmdlen, cmd, info);
0247     kfree(cmd);
0248 }
0249 
0250 static void mb86290fb_fillrect(struct fb_info *info,
0251                    const struct fb_fillrect *rect)
0252 {
0253 
0254     u32 x2, y2, vxres, vyres, height, width, fg;
0255     u32 cmd[7];
0256 
0257     vxres = info->var.xres_virtual;
0258     vyres = info->var.yres_virtual;
0259 
0260     if (!rect->width || !rect->height || rect->dx > vxres
0261         || rect->dy > vyres)
0262         return;
0263 
0264     /* We could use hardware clipping but on many cards you get around
0265      * hardware clipping by writing to framebuffer directly. */
0266     x2 = rect->dx + rect->width;
0267     y2 = rect->dy + rect->height;
0268     x2 = min(x2, vxres);
0269     y2 = min(y2, vyres);
0270     width = x2 - rect->dx;
0271     height = y2 - rect->dy;
0272     if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
0273         info->fix.visual == FB_VISUAL_DIRECTCOLOR)
0274         fg = ((u32 *) (info->pseudo_palette))[rect->color];
0275     else
0276         fg = rect->color;
0277 
0278     switch (rect->rop) {
0279 
0280     case ROP_XOR:
0281         /* Set raster operation */
0282         cmd[1] = (2 << 7) | (GDC_ROP_XOR << 9);
0283         break;
0284 
0285     case ROP_COPY:
0286         /* Set raster operation */
0287         cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
0288         break;
0289 
0290     }
0291 
0292     cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
0293     /* cmd[1] set earlier */
0294     cmd[2] =
0295         (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
0296     cmd[3] = fg;
0297     cmd[4] = (GDC_TYPE_DRAWRECTP << 24) | (GDC_CMD_BLT_FILL << 16);
0298     cmd[5] = (rect->dy << 16) | (rect->dx);
0299     cmd[6] = (height << 16) | width;
0300 
0301     mb862xxfb_write_fifo(7, cmd, info);
0302 }
0303 
0304 void mb862xxfb_init_accel(struct fb_info *info, struct fb_ops *fbops, int xres)
0305 {
0306     struct mb862xxfb_par *par = info->par;
0307 
0308     if (info->var.bits_per_pixel == 32) {
0309         fbops->fb_fillrect = cfb_fillrect;
0310         fbops->fb_copyarea = cfb_copyarea;
0311         fbops->fb_imageblit = cfb_imageblit;
0312     } else {
0313         outreg(disp, GC_L0EM, 3);
0314         fbops->fb_fillrect = mb86290fb_fillrect;
0315         fbops->fb_copyarea = mb86290fb_copyarea;
0316         fbops->fb_imageblit = mb86290fb_imageblit;
0317     }
0318     outreg(draw, GDC_REG_DRAW_BASE, 0);
0319     outreg(draw, GDC_REG_MODE_MISC, 0x8000);
0320     outreg(draw, GDC_REG_X_RESOLUTION, xres);
0321 
0322     info->flags |=
0323         FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
0324         FBINFO_HWACCEL_IMAGEBLIT;
0325     info->fix.accel = 0xff; /*FIXME: add right define */
0326 }
0327 
0328 MODULE_LICENSE("GPL v2");