tgafb accelerated code
authorJames Simmons <jsimmons@infradead.org>
Tue, 8 May 2007 07:37:50 +0000 (00:37 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 8 May 2007 18:15:27 +0000 (11:15 -0700)
Add accelerated panning and accelerated color and mono image drawing.
Please apply.

Signed-off-by: James Simmons <jsimmons@infradead.org>
Acked-by: Maciej W. Rozycki <macro@linux-mips.org> (tested, too!)
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/video/tgafb.c

index 5345fe03cdfe14f93b5f2e38aa619daea9e069a0..f0fde6ea7c36e252f5f6dec8d205664d5ce8b023 100644 (file)
@@ -59,6 +59,7 @@ static void tgafb_init_fix(struct fb_info *);
 static void tgafb_imageblit(struct fb_info *, const struct fb_image *);
 static void tgafb_fillrect(struct fb_info *, const struct fb_fillrect *);
 static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *);
+static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
 
 static int __devinit tgafb_register(struct device *dev);
 static void __devexit tgafb_unregister(struct device *dev);
@@ -81,6 +82,7 @@ static struct fb_ops tgafb_ops = {
        .fb_set_par             = tgafb_set_par,
        .fb_setcolreg           = tgafb_setcolreg,
        .fb_blank               = tgafb_blank,
+       .fb_pan_display         = tgafb_pan_display,
        .fb_fillrect            = tgafb_fillrect,
        .fb_copyarea            = tgafb_copyarea,
        .fb_imageblit           = tgafb_imageblit,
@@ -319,21 +321,7 @@ tgafb_set_par(struct fb_info *info)
                BT485_WRITE(par, 0x00, BT485_ADDR_PAL_WRITE);
                TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
 
-#ifdef CONFIG_HW_CONSOLE
-               for (i = 0; i < 16; i++) {
-                       int j = color_table[i];
-
-                       TGA_WRITE_REG(par, default_red[j]|(BT485_DATA_PAL<<8),
-                                     TGA_RAMDAC_REG);
-                       TGA_WRITE_REG(par, default_grn[j]|(BT485_DATA_PAL<<8),
-                                     TGA_RAMDAC_REG);
-                       TGA_WRITE_REG(par, default_blu[j]|(BT485_DATA_PAL<<8),
-                                     TGA_RAMDAC_REG);
-               }
-               for (i = 0; i < 240 * 3; i += 4) {
-#else
                for (i = 0; i < 256 * 3; i += 4) {
-#endif
                        TGA_WRITE_REG(par, 0x55 | (BT485_DATA_PAL << 8),
                                      TGA_RAMDAC_REG);
                        TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
@@ -358,18 +346,7 @@ tgafb_set_par(struct fb_info *info)
                BT459_LOAD_ADDR(par, 0x0000);
                TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
 
-#ifdef CONFIG_HW_CONSOLE
-               for (i = 0; i < 16; i++) {
-                       int j = color_table[i];
-
-                       TGA_WRITE_REG(par, default_red[j], TGA_RAMDAC_REG);
-                       TGA_WRITE_REG(par, default_grn[j], TGA_RAMDAC_REG);
-                       TGA_WRITE_REG(par, default_blu[j], TGA_RAMDAC_REG);
-               }
-               for (i = 0; i < 240 * 3; i += 4) {
-#else
                for (i = 0; i < 256 * 3; i += 4) {
-#endif
                        TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG);
                        TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
                        TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
@@ -646,16 +623,8 @@ tgafb_blank(int blank, struct fb_info *info)
  *  Acceleration.
  */
 
-/**
- *      tgafb_imageblit - REQUIRED function. Can use generic routines if
- *                        non acclerated hardware and packed pixel based.
- *                        Copies a image from system memory to the screen. 
- *
- *      @info: frame buffer structure that represents a single frame buffer
- *      @image: structure defining the image.
- */
 static void
-tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
+tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image)
 {
        struct tga_par *par = (struct tga_par *) info->par;
        u32 fgcolor, bgcolor, dx, dy, width, height, vxres, vyres, pixelmask;
@@ -665,6 +634,17 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
        void __iomem *regs_base;
        void __iomem *fb_base;
 
+       is8bpp = info->var.bits_per_pixel == 8;
+
+       /* For copies that aren't pixel expansion, there's little we
+          can do better than the generic code.  */
+       /* ??? There is a DMA write mode; I wonder if that could be
+          made to pull the data from the image buffer...  */
+       if (image->depth > 1) {
+               cfb_imageblit(info, image);
+               return;
+       }
+
        dx = image->dx;
        dy = image->dy;
        width = image->width;
@@ -682,18 +662,8 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
        if (dy + height > vyres)
                height = vyres - dy;
 
-       /* For copies that aren't pixel expansion, there's little we
-          can do better than the generic code.  */
-       /* ??? There is a DMA write mode; I wonder if that could be
-          made to pull the data from the image buffer...  */
-       if (image->depth > 1) {
-               cfb_imageblit(info, image);
-               return;
-       }
-
        regs_base = par->tga_regs_base;
        fb_base = par->tga_fb_base;
-       is8bpp = info->var.bits_per_pixel == 8;
 
        /* Expand the color values to fill 32-bits.  */
        /* ??? Would be nice to notice colour changes elsewhere, so
@@ -871,6 +841,85 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
                     regs_base + TGA_MODE_REG);
 }
 
+static void
+tgafb_clut_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       struct tga_par *par = (struct tga_par *) info->par;
+       u32 color, dx, dy, width, height, vxres, vyres;
+       u32 *palette = ((u32 *)info->pseudo_palette);
+       unsigned long pos, line_length, i, j;
+       const unsigned char *data;
+       void *regs_base, *fb_base;
+
+       dx = image->dx;
+       dy = image->dy;
+       width = image->width;
+       height = image->height;
+       vxres = info->var.xres_virtual;
+       vyres = info->var.yres_virtual;
+       line_length = info->fix.line_length;
+
+       /* Crop the image to the screen.  */
+       if (dx > vxres || dy > vyres)
+               return;
+       if (dx + width > vxres)
+               width = vxres - dx;
+       if (dy + height > vyres)
+               height = vyres - dy;
+
+       regs_base = par->tga_regs_base;
+       fb_base = par->tga_fb_base;
+
+       pos = dy * line_length + (dx * 4);
+       data = image->data;
+
+       /* Now copy the image, color_expanding via the palette. */
+       for (i = 0; i < height; i++) {
+               for (j = 0; j < width; j++) {
+                       color = palette[*data++];
+                       __raw_writel(color, fb_base + pos + j*4);
+               }
+               pos += line_length;
+       }
+}
+
+/**
+ *      tgafb_imageblit - REQUIRED function. Can use generic routines if
+ *                        non acclerated hardware and packed pixel based.
+ *                        Copies a image from system memory to the screen.
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *      @image: structure defining the image.
+ */
+static void
+tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       unsigned int is8bpp = info->var.bits_per_pixel == 8;
+
+       /* If a mono image, regardless of FB depth, go do it. */
+       if (image->depth == 1) {
+               tgafb_mono_imageblit(info, image);
+               return;
+       }
+
+       /* For copies that aren't pixel expansion, there's little we
+          can do better than the generic code.  */
+       /* ??? There is a DMA write mode; I wonder if that could be
+          made to pull the data from the image buffer...  */
+       if (image->depth == info->var.bits_per_pixel) {
+               cfb_imageblit(info, image);
+               return;
+       }
+
+       /* If 24-plane FB and the image is 8-plane with CLUT, we can do it. */
+       if (!is8bpp && image->depth == 8) {
+               tgafb_clut_imageblit(info, image);
+               return;
+       }
+
+       /* Silently return... */
+}
+
 /**
  *      tgafb_fillrect - REQUIRED function. Can use generic routines if 
  *                       non acclerated hardware and packed pixel based.
@@ -1480,6 +1529,26 @@ tgafb_init_fix(struct fb_info *info)
        info->fix.ywrapstep = 0;
 
        info->fix.accel = FB_ACCEL_DEC_TGA;
+
+       /*
+        * These are needed by fb_set_logo_truepalette(), so we
+        * set them here for 24-plane cards.
+        */
+       if (tga_type != TGA_TYPE_8PLANE) {
+               info->var.red.length = 8;
+               info->var.green.length = 8;
+               info->var.blue.length = 8;
+               info->var.red.offset = 16;
+               info->var.green.offset = 8;
+               info->var.blue.offset = 0;
+       }
+}
+
+static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       /* We just use this to catch switches out of graphics mode. */
+       tgafb_set_par(info); /* A bit of overkill for BASE_ADDR reset. */
+       return 0;
 }
 
 static int __devinit