pm2fb: accelerated imageblit

This patch adds accelerated imageblit function.

Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Antonino Daplas <adaplas@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Krzysztof Helt 2007-10-16 01:28:34 -07:00 committed by Linus Torvalds
parent d5383fcc4c
commit 91b3a6f4cd
2 changed files with 127 additions and 3 deletions

View file

@ -60,6 +60,8 @@
#define DPRINTK(a,b...)
#endif
#define PM2_PIXMAP_SIZE (1600 * 4)
/*
* Driver data
*/
@ -1166,6 +1168,104 @@ static void pm2fb_copyarea(struct fb_info *info,
modded.width, modded.height, 0);
}
static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct pm2fb_par *par = info->par;
u32 height = image->height;
u32 fgx, bgx;
const u32 *src = (const u32*)image->data;
u32 xres = (info->var.xres + 31) & ~31;
if (info->state != FBINFO_STATE_RUNNING)
return;
if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1) {
cfb_imageblit(info, image);
return;
}
switch (info->fix.visual) {
case FB_VISUAL_PSEUDOCOLOR:
fgx = image->fg_color;
bgx = image->bg_color;
break;
case FB_VISUAL_TRUECOLOR:
default:
fgx = par->palette[image->fg_color];
bgx = par->palette[image->bg_color];
break;
}
if (info->var.bits_per_pixel == 8) {
fgx |= fgx << 8;
bgx |= bgx << 8;
}
if (info->var.bits_per_pixel <= 16) {
fgx |= fgx << 16;
bgx |= bgx << 16;
}
WAIT_FIFO(par, 13);
pm2_WR(par, PM2R_FB_READ_MODE, partprod(xres));
pm2_WR(par, PM2R_SCISSOR_MIN_XY,
((image->dy & 0xfff) << 16) | (image->dx & 0x0fff));
pm2_WR(par, PM2R_SCISSOR_MAX_XY,
(((image->dy + image->height) & 0x0fff) << 16) |
((image->dx + image->width) & 0x0fff));
pm2_WR(par, PM2R_SCISSOR_MODE, 1);
/* GXcopy & UNIT_ENABLE */
pm2_WR(par, PM2R_LOGICAL_OP_MODE, (0x3 << 1) | 1 );
pm2_WR(par, PM2R_RECTANGLE_ORIGIN,
((image->dy & 0xfff) << 16) | (image->dx & 0x0fff));
pm2_WR(par, PM2R_RECTANGLE_SIZE,
((image->height & 0x0fff) << 16) |
((image->width) & 0x0fff));
if (info->var.bits_per_pixel == 24) {
pm2_WR(par, PM2R_COLOR_DDA_MODE, 1);
/* clear area */
pm2_WR(par, PM2R_CONSTANT_COLOR, bgx);
pm2_WR(par, PM2R_RENDER,
PM2F_RENDER_RECTANGLE |
PM2F_INCREASE_X | PM2F_INCREASE_Y );
/* BitMapPackEachScanline & invert bits and byte order*/
/* force background */
pm2_WR(par, PM2R_RASTERIZER_MODE, (1<<9) | 1 | (3<<7));
pm2_WR(par, PM2R_CONSTANT_COLOR, fgx);
pm2_WR(par, PM2R_RENDER,
PM2F_RENDER_RECTANGLE |
PM2F_INCREASE_X | PM2F_INCREASE_Y |
PM2F_RENDER_SYNC_ON_BIT_MASK);
} else {
pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
/* clear area */
pm2_WR(par, PM2R_FB_BLOCK_COLOR, bgx);
pm2_WR(par, PM2R_RENDER,
PM2F_RENDER_RECTANGLE |
PM2F_RENDER_FASTFILL |
PM2F_INCREASE_X | PM2F_INCREASE_Y );
/* invert bits and byte order*/
pm2_WR(par, PM2R_RASTERIZER_MODE, 1 | (3<<7) );
pm2_WR(par, PM2R_FB_BLOCK_COLOR, fgx);
pm2_WR(par, PM2R_RENDER,
PM2F_RENDER_RECTANGLE |
PM2F_INCREASE_X | PM2F_INCREASE_Y |
PM2F_RENDER_FASTFILL |
PM2F_RENDER_SYNC_ON_BIT_MASK);
}
while (height--) {
int width = ((image->width + 7) >> 3)
+ info->pixmap.scan_align - 1;
width >>= 2;
WAIT_FIFO(par, width);
while (width--) {
pm2_WR(par, PM2R_BIT_MASK_PATTERN, *src);
src++;
}
}
WAIT_FIFO(par, 3);
pm2_WR(par, PM2R_RASTERIZER_MODE, 0);
pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
pm2_WR(par, PM2R_SCISSOR_MODE, 0);
}
/* ------------ Hardware Independent Functions ------------ */
/*
@ -1181,7 +1281,7 @@ static struct fb_ops pm2fb_ops = {
.fb_pan_display = pm2fb_pan_display,
.fb_fillrect = pm2fb_fillrect,
.fb_copyarea = pm2fb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_imageblit = pm2fb_imageblit,
.fb_sync = pm2fb_sync,
};
@ -1340,11 +1440,24 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
info->flags = FBINFO_DEFAULT |
FBINFO_HWACCEL_YPAN |
FBINFO_HWACCEL_COPYAREA |
FBINFO_HWACCEL_IMAGEBLIT |
FBINFO_HWACCEL_FILLRECT;
info->pixmap.addr = kmalloc(PM2_PIXMAP_SIZE, GFP_KERNEL);
if (!info->pixmap.addr) {
err_retval = -ENOMEM;
goto err_exit_pixmap;
}
info->pixmap.size = PM2_PIXMAP_SIZE;
info->pixmap.buf_align = 4;
info->pixmap.scan_align = 4;
info->pixmap.access_align = 32;
info->pixmap.flags = FB_PIXMAP_SYSTEM;
if (noaccel) {
printk(KERN_DEBUG "disabling acceleration\n");
info->flags |= FBINFO_HWACCEL_DISABLED;
printk(KERN_DEBUG "disabling acceleration\n");
info->flags |= FBINFO_HWACCEL_DISABLED;
info->pixmap.scan_align = 1;
}
if (!mode)
@ -1373,6 +1486,8 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
err_exit_all:
fb_dealloc_cmap(&info->cmap);
err_exit_both:
kfree(info->pixmap.addr);
err_exit_pixmap:
iounmap(info->screen_base);
release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
err_exit_mmio:
@ -1409,6 +1524,8 @@ static void __devexit pm2fb_remove(struct pci_dev *pdev)
release_mem_region(fix->mmio_start, fix->mmio_len);
pci_set_drvdata(pdev, NULL);
if (info->pixmap.addr)
kfree(info->pixmap.addr);
kfree(info);
}

View file

@ -68,11 +68,14 @@
#define PM2R_D_Y 0x8028
#define PM2R_COUNT 0x8030
#define PM2R_RENDER 0x8038
#define PM2R_BIT_MASK_PATTERN 0x8068
#define PM2R_RASTERIZER_MODE 0x80a0
#define PM2R_RECTANGLE_ORIGIN 0x80d0
#define PM2R_RECTANGLE_SIZE 0x80d8
#define PM2R_PACKED_DATA_LIMITS 0x8150
#define PM2R_SCISSOR_MODE 0x8180
#define PM2R_SCISSOR_MIN_XY 0x8188
#define PM2R_SCISSOR_MAX_XY 0x8190
#define PM2R_SCREEN_SIZE 0x8198
#define PM2R_AREA_STIPPLE_MODE 0x81a0
#define PM2R_WINDOW_ORIGIN 0x81c8
@ -83,7 +86,9 @@
#define PM2R_TEXEL_LUT_MODE 0x8678
#define PM2R_TEXTURE_COLOR_MODE 0x8680
#define PM2R_FOG_MODE 0x8690
#define PM2R_TEXEL0 0x8760
#define PM2R_COLOR_DDA_MODE 0x87e0
#define PM2R_CONSTANT_COLOR 0x87e8
#define PM2R_ALPHA_BLEND_MODE 0x8810
#define PM2R_DITHER_MODE 0x8818
#define PM2R_FB_SOFT_WRITE_MASK 0x8820
@ -169,6 +174,8 @@
#define PM2F_RENDER_TRAPEZOID (1L<<6)
#define PM2F_RENDER_POINT (2L<<6)
#define PM2F_RENDER_RECTANGLE (3L<<6)
#define PM2F_RENDER_SYNC_ON_BIT_MASK (1L<<11)
#define PM2F_RENDER_TEXTURE_ENABLE (1L<<13)
#define PM2F_SYNCHRONIZATION (1L<<10)
#define PM2F_PLL_LOCKED 0x10
#define PM2F_BEING_RESET (1L<<31)