Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e7f76df9 authored by Krzysztof Helt's avatar Krzysztof Helt Committed by Linus Torvalds
Browse files

pm3fb: copyarea and partial imageblit suppor



This patch adds accelerated copyarea and partially accelerated imageblit
functions. There is also fixed one register address in the pm3fb.h file.

Signed-off-by: default avatarKrzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: default avatarAntonino Daplas <adaplas@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 0a0b53f6
Loading
Loading
Loading
Loading
+169 −11
Original line number Diff line number Diff line
@@ -276,15 +276,22 @@ static void pm3fb_init_engine(struct fb_info *info)

	PM3_WAIT(par, 2);
	{
		unsigned long rm = 1;
		/* invert bits in bitmask */
		unsigned long rm = 1 | (3 << 7);
		switch (info->var.bits_per_pixel) {
		case 8:
			PM3_WRITE_REG(par, PM3PixelSize,
					   PM3PixelSize_GLOBAL_8BIT);
#ifdef __BIG_ENDIAN
			rm |= 3 << 15;
#endif
			break;
		case 16:
			PM3_WRITE_REG(par, PM3PixelSize,
					   PM3PixelSize_GLOBAL_16BIT);
#ifdef __BIG_ENDIAN
			rm |= 2 << 15;
#endif
			break;
		case 32:
			PM3_WRITE_REG(par, PM3PixelSize,
@@ -394,11 +401,11 @@ static void pm3fb_fillrect (struct fb_info *info,
		color |= color << 16;

	PM3_WAIT(par, 4);

	/* ROP Ox3 is GXcopy */
	PM3_WRITE_REG(par, PM3Config2D,
			PM3Config2D_UseConstantSource |
			PM3Config2D_ForegroundROPEnable |
				  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
			(PM3Config2D_ForegroundROP(0x3)) |
			PM3Config2D_FBWriteEnable);

	PM3_WRITE_REG(par, PM3ForegroundColor, color);
@@ -415,6 +422,154 @@ static void pm3fb_fillrect (struct fb_info *info,
		      (PM3Render2D_Width(modded.width)) |
		      (PM3Render2D_Height(modded.height)));
}

static void pm3fb_copyarea(struct fb_info *info,
				const struct fb_copyarea *area)
{
	struct pm3_par *par = info->par;
	struct fb_copyarea modded;
	u32 vxres, vyres;
	int x_align, o_x, o_y;

	if (info->state != FBINFO_STATE_RUNNING)
		return;
	if (info->flags & FBINFO_HWACCEL_DISABLED) {
		cfb_copyarea(info, area);
		return;
	}

	memcpy(&modded, area, sizeof(struct fb_copyarea));

	vxres = info->var.xres_virtual;
	vyres = info->var.yres_virtual;

	if(!modded.width || !modded.height ||
	   modded.sx >= vxres || modded.sy >= vyres ||
	   modded.dx >= vxres || modded.dy >= vyres)
		return;

	if(modded.sx + modded.width > vxres)
		modded.width = vxres - modded.sx;
	if(modded.dx + modded.width > vxres)
		modded.width = vxres - modded.dx;
	if(modded.sy + modded.height > vyres)
		modded.height = vyres - modded.sy;
	if(modded.dy + modded.height > vyres)
		modded.height = vyres - modded.dy;

	o_x = modded.sx - modded.dx;	/*(sx > dx ) ? (sx - dx) : (dx - sx); */
	o_y = modded.sy - modded.dy;	/*(sy > dy ) ? (sy - dy) : (dy - sy); */

	x_align = (modded.sx & 0x1f);

	PM3_WAIT(par, 6);

	PM3_WRITE_REG(par, PM3Config2D,
			PM3Config2D_UserScissorEnable |
			PM3Config2D_ForegroundROPEnable |
			PM3Config2D_Blocking |
			(PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
			PM3Config2D_FBWriteEnable);

	PM3_WRITE_REG(par, PM3ScissorMinXY,
			((modded.dy & 0x0fff) << 16) | (modded.dx & 0x0fff));
	PM3_WRITE_REG(par, PM3ScissorMaxXY,
			(((modded.dy + modded.height) & 0x0fff) << 16) |
			((modded.dx + modded.width) & 0x0fff));

	PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset,
			PM3FBSourceReadBufferOffset_XOffset(o_x) |
			PM3FBSourceReadBufferOffset_YOffset(o_y));

	PM3_WRITE_REG(par, PM3RectanglePosition,
			(PM3RectanglePosition_XOffset(modded.dx - x_align)) |
			(PM3RectanglePosition_YOffset(modded.dy)));

	PM3_WRITE_REG(par, PM3Render2D,
			((modded.sx > modded.dx) ? PM3Render2D_XPositive : 0) |
			((modded.sy > modded.dy) ? PM3Render2D_YPositive : 0) |
			PM3Render2D_Operation_Normal |
			PM3Render2D_SpanOperation |
			PM3Render2D_FBSourceReadEnable |
			(PM3Render2D_Width(modded.width + x_align)) |
			(PM3Render2D_Height(modded.height)));
}

static void pm3fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
	struct pm3_par *par = info->par;
	u32 height = image->height;
	u32 fgx, bgx;
	const u32 *src = (const u32*)image->data;

	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 (image->depth != 1 || (image->width & 0x1f)) {
		return cfb_imageblit(info, image);
	}
	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;
	}

	PM3_WAIT(par, 5);

	PM3_WRITE_REG(par, PM3ForegroundColor, fgx);
	PM3_WRITE_REG(par, PM3BackgroundColor, bgx);

	/* ROP Ox3 is GXcopy */
	PM3_WRITE_REG(par, PM3Config2D,
			PM3Config2D_UseConstantSource |
			PM3Config2D_ForegroundROPEnable |
			(PM3Config2D_ForegroundROP(0x3)) |
			PM3Config2D_OpaqueSpan |
			PM3Config2D_FBWriteEnable);
	PM3_WRITE_REG(par, PM3RectanglePosition,
			(PM3RectanglePosition_XOffset(image->dx)) |
			(PM3RectanglePosition_YOffset(image->dy)));
	PM3_WRITE_REG(par, PM3Render2D,
			PM3Render2D_XPositive |
			PM3Render2D_YPositive |
			PM3Render2D_Operation_SyncOnBitMask |
			PM3Render2D_SpanOperation |
			(PM3Render2D_Width(image->width)) |
			(PM3Render2D_Height(image->height)));


	while (height--) {
		u32 width = (image->width + 31) >> 5;

		while (width >= PM3_FIFO_SIZE) {
			int i = PM3_FIFO_SIZE - 1;

			PM3_WAIT(par, PM3_FIFO_SIZE);
			while (i--) {
				PM3_WRITE_REG(par, PM3BitMaskPattern, *src);
				src++;
			}
			width -= PM3_FIFO_SIZE - 1;
		}

		PM3_WAIT(par, width + 1);
		while (width--) {
			PM3_WRITE_REG(par, PM3BitMaskPattern, *src);
			src++;
		}
	}
}
/* end of acceleration functions */

/* write the mode to registers */
@@ -907,8 +1062,8 @@ static struct fb_ops pm3fb_ops = {
	.fb_setcolreg	= pm3fb_setcolreg,
	.fb_pan_display	= pm3fb_pan_display,
	.fb_fillrect	= pm3fb_fillrect,
	.fb_copyarea	= cfb_copyarea,
	.fb_imageblit	= cfb_imageblit,
	.fb_copyarea	= pm3fb_copyarea,
	.fb_imageblit	= pm3fb_imageblit,
	.fb_blank	= pm3fb_blank,
	.fb_sync	= pm3fb_sync,
};
@@ -1080,7 +1235,10 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
	info->fix = pm3fb_fix;
	info->pseudo_palette = par->palette;
	info->flags = FBINFO_DEFAULT |
			FBINFO_HWACCEL_FILLRECT;/* | FBINFO_HWACCEL_YPAN;*/
/*			FBINFO_HWACCEL_YPAN |*/
			FBINFO_HWACCEL_COPYAREA |
			FBINFO_HWACCEL_IMAGEBLIT |
			FBINFO_HWACCEL_FILLRECT;

	/*
	 * This should give a reasonable default video mode. The following is
+4 −1
Original line number Diff line number Diff line
@@ -849,7 +849,7 @@
	#define PM3Render_FBSourceRead_Enable			(1<<27)
#define PM3RasterizerMode					0x80a0
#define PM3RasterizerModeAnd					0xaba0
#define PM3RasterizerModeOr					0xabb8
#define PM3RasterizerModeOr					0xaba8
#define PM3RectangleHeight					0x94e0
#define PM3Render						0x8038
#define PM3RepeatLine						0x9328
@@ -1116,6 +1116,9 @@
/* ***** pm3fb useful define and macro ***** */
/* ***************************************** */

/* fifo size in chip */
#define PM3_FIFO_SIZE 120

/* max size of options */
#define PM3_OPTIONS_SIZE 256