Commit 5b1d28d6 authored by Florian Tobias Schandinat's avatar Florian Tobias Schandinat Committed by James Toy

v2: - fix copyarea with overlapping areas

    - add raster operation code conversion and checking
Signed-off-by: default avatarFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Scott Fang <ScottFang@viatech.com.cn>
Cc: Joseph Chan <JosephChan@via.com.tw>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 1ea5fe32
...@@ -25,13 +25,40 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, ...@@ -25,13 +25,40 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height,
u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y, u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
u32 fg_color, u32 bg_color, u8 fill_rop) u32 fg_color, u32 bg_color, u8 fill_rop)
{ {
u32 tmp, i; u32 ge_cmd = 0, tmp, i;
if (!op || op > 3) { if (!op || op > 3) {
printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op); printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op);
return -EINVAL; return -EINVAL;
} }
if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
if (src_x < dst_x) {
ge_cmd |= 0x00008000;
src_x += width - 1;
dst_x += width - 1;
}
if (src_y < dst_y) {
ge_cmd |= 0x00004000;
src_y += height - 1;
dst_y += height - 1;
}
}
if (op == VIA_BITBLT_FILL) {
switch (fill_rop) {
case 0x00: /* blackness */
case 0x5A: /* pattern inversion */
case 0xF0: /* pattern copy */
case 0xFF: /* whiteness */
break;
default:
printk(KERN_WARNING "hw_bitblt_1: Invalid fill rop: "
"%u\n", fill_rop);
return -EINVAL;
}
}
switch (dst_bpp) { switch (dst_bpp) {
case 8: case 8:
tmp = 0x00000000; tmp = 0x00000000;
...@@ -113,19 +140,18 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, ...@@ -113,19 +140,18 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height,
tmp = (tmp >> 3) | (dst_pitch << (16 - 3)); tmp = (tmp >> 3) | (dst_pitch << (16 - 3));
writel(tmp, engine + 0x38); writel(tmp, engine + 0x38);
tmp = 0;
if (op == VIA_BITBLT_FILL) if (op == VIA_BITBLT_FILL)
tmp |= fill_rop << 24 | 0x00002000 | 0x00000001; ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
else { else {
tmp = 0xCC000000; /* ROP=SRCCOPY */ ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
if (src_mem) if (src_mem)
tmp |= 0x00000040; ge_cmd |= 0x00000040;
if (op == VIA_BITBLT_MONO) if (op == VIA_BITBLT_MONO)
tmp |= 0x00000002 | 0x00000100 | 0x00020000; ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
else else
tmp |= 0x00000001; ge_cmd |= 0x00000001;
} }
writel(tmp, engine); writel(ge_cmd, engine);
if (op == VIA_BITBLT_FILL || !src_mem) if (op == VIA_BITBLT_FILL || !src_mem)
return 0; return 0;
...@@ -144,13 +170,40 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height, ...@@ -144,13 +170,40 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y, u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
u32 fg_color, u32 bg_color, u8 fill_rop) u32 fg_color, u32 bg_color, u8 fill_rop)
{ {
u32 tmp, i; u32 ge_cmd = 0, tmp, i;
if (!op || op > 3) { if (!op || op > 3) {
printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op); printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op);
return -EINVAL; return -EINVAL;
} }
if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
if (src_x < dst_x) {
ge_cmd |= 0x00008000;
src_x += width - 1;
dst_x += width - 1;
}
if (src_y < dst_y) {
ge_cmd |= 0x00004000;
src_y += height - 1;
dst_y += height - 1;
}
}
if (op == VIA_BITBLT_FILL) {
switch (fill_rop) {
case 0x00: /* blackness */
case 0x5A: /* pattern inversion */
case 0xF0: /* pattern copy */
case 0xFF: /* whiteness */
break;
default:
printk(KERN_WARNING "hw_bitblt_2: Invalid fill rop: "
"%u\n", fill_rop);
return -EINVAL;
}
}
switch (dst_bpp) { switch (dst_bpp) {
case 8: case 8:
tmp = 0x00000000; tmp = 0x00000000;
...@@ -230,19 +283,18 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height, ...@@ -230,19 +283,18 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
if (op == VIA_BITBLT_MONO) if (op == VIA_BITBLT_MONO)
writel(bg_color, engine + 0x50); writel(bg_color, engine + 0x50);
tmp = 0;
if (op == VIA_BITBLT_FILL) if (op == VIA_BITBLT_FILL)
tmp |= fill_rop << 24 | 0x00002000 | 0x00000001; ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
else { else {
tmp = 0xCC000000; /* ROP=SRCCOPY */ ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
if (src_mem) if (src_mem)
tmp |= 0x00000040; ge_cmd |= 0x00000040;
if (op == VIA_BITBLT_MONO) if (op == VIA_BITBLT_MONO)
tmp |= 0x00000002 | 0x00000100 | 0x00020000; ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
else else
tmp |= 0x00000001; ge_cmd |= 0x00000001;
} }
writel(tmp, engine); writel(ge_cmd, engine);
if (op == VIA_BITBLT_FILL || !src_mem) if (op == VIA_BITBLT_FILL || !src_mem)
return 0; return 0;
......
...@@ -768,6 +768,7 @@ static void viafb_fillrect(struct fb_info *info, ...@@ -768,6 +768,7 @@ static void viafb_fillrect(struct fb_info *info,
{ {
struct viafb_par *viapar = info->par; struct viafb_par *viapar = info->par;
u32 fg_color; u32 fg_color;
u8 rop;
if (!viapar->shared->hw_bitblt) { if (!viapar->shared->hw_bitblt) {
cfb_fillrect(info, rect); cfb_fillrect(info, rect);
...@@ -782,11 +783,16 @@ static void viafb_fillrect(struct fb_info *info, ...@@ -782,11 +783,16 @@ static void viafb_fillrect(struct fb_info *info,
else else
fg_color = rect->color; fg_color = rect->color;
if (rect->rop == ROP_XOR)
rop = 0x5A;
else
rop = 0xF0;
DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n"); DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n");
if (viapar->shared->hw_bitblt(viapar->io_virt, VIA_BITBLT_FILL, if (viapar->shared->hw_bitblt(viapar->io_virt, VIA_BITBLT_FILL,
rect->width, rect->height, info->var.bits_per_pixel, rect->width, rect->height, info->var.bits_per_pixel,
viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy, viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy,
NULL, 0, 0, 0, 0, fg_color, 0, rect->rop)) NULL, 0, 0, 0, 0, fg_color, 0, rop))
cfb_fillrect(info, rect); cfb_fillrect(info, rect);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment