diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2008-07-24 00:31:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-24 13:47:36 -0400 |
commit | 0292be4a382957016e8b574dc292779cfb49e029 (patch) | |
tree | dc583df0ad19e5fc2f7cfa294cbd6ade9ad4a87b | |
parent | 6280fd4f9c2683a4d2f096320dd74ded4e5106ad (diff) |
tridentfb: add imageblit acceleration for Blade3D family
Add imageblit acceleration for the Blade3D family of cores. The code is
based on code from the cyblafb driver.
It is a step toward assimilating back the cyblafb driver into the
tridentfb driver. The cyblafb driver handles a subfamily of the Trident
Blade3d cores.
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/video/tridentfb.c | 79 | ||||
-rw-r--r-- | include/video/trident.h | 1 |
2 files changed, 77 insertions, 3 deletions
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index 854e2e5af582..b21f84239022 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c | |||
@@ -35,11 +35,12 @@ struct tridentfb_par { | |||
35 | (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32); | 35 | (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32); |
36 | void (*copy_rect) | 36 | void (*copy_rect) |
37 | (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32); | 37 | (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32); |
38 | void (*image_blit) | ||
39 | (struct tridentfb_par *par, const char*, | ||
40 | u32, u32, u32, u32, u32, u32); | ||
38 | unsigned char eng_oper; /* engine operation... */ | 41 | unsigned char eng_oper; /* engine operation... */ |
39 | }; | 42 | }; |
40 | 43 | ||
41 | static struct fb_ops tridentfb_ops; | ||
42 | |||
43 | static struct fb_fix_screeninfo tridentfb_fix = { | 44 | static struct fb_fix_screeninfo tridentfb_fix = { |
44 | .id = "Trident", | 45 | .id = "Trident", |
45 | .type = FB_TYPE_PACKED_PIXELS, | 46 | .type = FB_TYPE_PACKED_PIXELS, |
@@ -212,6 +213,21 @@ static void blade_fill_rect(struct tridentfb_par *par, | |||
212 | writemmr(par, DST2, point(x + w - 1, y + h - 1)); | 213 | writemmr(par, DST2, point(x + w - 1, y + h - 1)); |
213 | } | 214 | } |
214 | 215 | ||
216 | static void blade_image_blit(struct tridentfb_par *par, const char *data, | ||
217 | u32 x, u32 y, u32 w, u32 h, u32 c, u32 b) | ||
218 | { | ||
219 | unsigned size = ((w + 31) >> 5) * h; | ||
220 | |||
221 | writemmr(par, COLOR, c); | ||
222 | writemmr(par, BGCOLOR, b); | ||
223 | writemmr(par, CMD, 0xa0000000 | 3 << 19); | ||
224 | |||
225 | writemmr(par, DST1, point(x, y)); | ||
226 | writemmr(par, DST2, point(x + w - 1, y + h - 1)); | ||
227 | |||
228 | memcpy(par->io_virt + 0x10000, data, 4 * size); | ||
229 | } | ||
230 | |||
215 | static void blade_copy_rect(struct tridentfb_par *par, | 231 | static void blade_copy_rect(struct tridentfb_par *par, |
216 | u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) | 232 | u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) |
217 | { | 233 | { |
@@ -497,6 +513,36 @@ static void tridentfb_fillrect(struct fb_info *info, | |||
497 | fr->height, col, fr->rop); | 513 | fr->height, col, fr->rop); |
498 | } | 514 | } |
499 | 515 | ||
516 | static void tridentfb_imageblit(struct fb_info *info, | ||
517 | const struct fb_image *img) | ||
518 | { | ||
519 | struct tridentfb_par *par = info->par; | ||
520 | int col, bgcol; | ||
521 | |||
522 | if ((info->flags & FBINFO_HWACCEL_DISABLED) || img->depth != 1) { | ||
523 | cfb_imageblit(info, img); | ||
524 | return; | ||
525 | } | ||
526 | if (info->var.bits_per_pixel == 8) { | ||
527 | col = img->fg_color; | ||
528 | col |= col << 8; | ||
529 | col |= col << 16; | ||
530 | bgcol = img->bg_color; | ||
531 | bgcol |= bgcol << 8; | ||
532 | bgcol |= bgcol << 16; | ||
533 | } else { | ||
534 | col = ((u32 *)(info->pseudo_palette))[img->fg_color]; | ||
535 | bgcol = ((u32 *)(info->pseudo_palette))[img->bg_color]; | ||
536 | } | ||
537 | |||
538 | par->wait_engine(par); | ||
539 | if (par->image_blit) | ||
540 | par->image_blit(par, img->data, img->dx, img->dy, | ||
541 | img->width, img->height, col, bgcol); | ||
542 | else | ||
543 | cfb_imageblit(info, img); | ||
544 | } | ||
545 | |||
500 | static void tridentfb_copyarea(struct fb_info *info, | 546 | static void tridentfb_copyarea(struct fb_info *info, |
501 | const struct fb_copyarea *ca) | 547 | const struct fb_copyarea *ca) |
502 | { | 548 | { |
@@ -522,6 +568,7 @@ static int tridentfb_sync(struct fb_info *info) | |||
522 | #else | 568 | #else |
523 | #define tridentfb_fillrect cfb_fillrect | 569 | #define tridentfb_fillrect cfb_fillrect |
524 | #define tridentfb_copyarea cfb_copyarea | 570 | #define tridentfb_copyarea cfb_copyarea |
571 | #define tridentfb_imageblit cfb_imageblit | ||
525 | #endif /* CONFIG_FB_TRIDENT_ACCEL */ | 572 | #endif /* CONFIG_FB_TRIDENT_ACCEL */ |
526 | 573 | ||
527 | /* | 574 | /* |
@@ -1285,7 +1332,7 @@ static struct fb_ops tridentfb_ops = { | |||
1285 | .fb_set_par = tridentfb_set_par, | 1332 | .fb_set_par = tridentfb_set_par, |
1286 | .fb_fillrect = tridentfb_fillrect, | 1333 | .fb_fillrect = tridentfb_fillrect, |
1287 | .fb_copyarea = tridentfb_copyarea, | 1334 | .fb_copyarea = tridentfb_copyarea, |
1288 | .fb_imageblit = cfb_imageblit, | 1335 | .fb_imageblit = tridentfb_imageblit, |
1289 | #ifdef CONFIG_FB_TRIDENT_ACCEL | 1336 | #ifdef CONFIG_FB_TRIDENT_ACCEL |
1290 | .fb_sync = tridentfb_sync, | 1337 | .fb_sync = tridentfb_sync, |
1291 | #endif | 1338 | #endif |
@@ -1369,6 +1416,7 @@ static int __devinit trident_pci_probe(struct pci_dev *dev, | |||
1369 | default_par->wait_engine = blade_wait_engine; | 1416 | default_par->wait_engine = blade_wait_engine; |
1370 | default_par->fill_rect = blade_fill_rect; | 1417 | default_par->fill_rect = blade_fill_rect; |
1371 | default_par->copy_rect = blade_copy_rect; | 1418 | default_par->copy_rect = blade_copy_rect; |
1419 | default_par->image_blit = blade_image_blit; | ||
1372 | tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADE3D; | 1420 | tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADE3D; |
1373 | } else if (chip3D) { /* 3DImage family left */ | 1421 | } else if (chip3D) { /* 3DImage family left */ |
1374 | default_par->init_accel = image_init_accel; | 1422 | default_par->init_accel = image_init_accel; |
@@ -1446,6 +1494,29 @@ static int __devinit trident_pci_probe(struct pci_dev *dev, | |||
1446 | } else | 1494 | } else |
1447 | info->flags |= FBINFO_HWACCEL_DISABLED; | 1495 | info->flags |= FBINFO_HWACCEL_DISABLED; |
1448 | 1496 | ||
1497 | info->pixmap.addr = kmalloc(4096, GFP_KERNEL); | ||
1498 | if (!info->pixmap.addr) { | ||
1499 | err = -ENOMEM; | ||
1500 | goto out_unmap2; | ||
1501 | } | ||
1502 | |||
1503 | info->pixmap.size = 4096; | ||
1504 | info->pixmap.buf_align = 4; | ||
1505 | info->pixmap.scan_align = 1; | ||
1506 | info->pixmap.access_align = 32; | ||
1507 | info->pixmap.flags = FB_PIXMAP_SYSTEM; | ||
1508 | |||
1509 | if (default_par->image_blit) { | ||
1510 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT; | ||
1511 | info->pixmap.scan_align = 4; | ||
1512 | } | ||
1513 | |||
1514 | if (noaccel) { | ||
1515 | printk(KERN_DEBUG "disabling acceleration\n"); | ||
1516 | info->flags |= FBINFO_HWACCEL_DISABLED; | ||
1517 | info->pixmap.scan_align = 1; | ||
1518 | } | ||
1519 | |||
1449 | if (!fb_find_mode(&info->var, info, | 1520 | if (!fb_find_mode(&info->var, info, |
1450 | mode_option, NULL, 0, NULL, bpp)) { | 1521 | mode_option, NULL, 0, NULL, bpp)) { |
1451 | err = -EINVAL; | 1522 | err = -EINVAL; |
@@ -1471,6 +1542,7 @@ static int __devinit trident_pci_probe(struct pci_dev *dev, | |||
1471 | return 0; | 1542 | return 0; |
1472 | 1543 | ||
1473 | out_unmap2: | 1544 | out_unmap2: |
1545 | kfree(info->pixmap.addr); | ||
1474 | if (info->screen_base) | 1546 | if (info->screen_base) |
1475 | iounmap(info->screen_base); | 1547 | iounmap(info->screen_base); |
1476 | release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); | 1548 | release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); |
@@ -1494,6 +1566,7 @@ static void __devexit trident_pci_remove(struct pci_dev *dev) | |||
1494 | release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); | 1566 | release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); |
1495 | release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); | 1567 | release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); |
1496 | pci_set_drvdata(dev, NULL); | 1568 | pci_set_drvdata(dev, NULL); |
1569 | kfree(info->pixmap.addr); | ||
1497 | framebuffer_release(info); | 1570 | framebuffer_release(info); |
1498 | } | 1571 | } |
1499 | 1572 | ||
diff --git a/include/video/trident.h b/include/video/trident.h index 85ced9d91312..b6ce19d1b61b 100644 --- a/include/video/trident.h +++ b/include/video/trident.h | |||
@@ -135,6 +135,7 @@ | |||
135 | #define CMD 0x2144 | 135 | #define CMD 0x2144 |
136 | #define ROP 0x2148 | 136 | #define ROP 0x2148 |
137 | #define COLOR 0x2160 | 137 | #define COLOR 0x2160 |
138 | #define BGCOLOR 0x2164 | ||
138 | #define SRC1 0x2100 | 139 | #define SRC1 0x2100 |
139 | #define SRC2 0x2104 | 140 | #define SRC2 0x2104 |
140 | #define DST1 0x2108 | 141 | #define DST1 0x2108 |