aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/tridentfb.c
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2008-07-24 00:31:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:36 -0400
commitbcac2d5fe36238dcfc955b49f9db10ad3ae3e53c (patch)
tree3cb0092505c4b7c39b9e4a26c14e42e322eb843a /drivers/video/tridentfb.c
parent54f019e54244fef0ad927ce5501927d9033492de (diff)
tridentfb: add acceleration for TGUI families
This patch adds acceleration for TGUI 9440 and 96xx chips. These chips requires line length to be power of 2, so this is also changed. It also moves the troubling enable_mmio() function to its final destination. 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>
Diffstat (limited to 'drivers/video/tridentfb.c')
-rw-r--r--drivers/video/tridentfb.c135
1 files changed, 123 insertions, 12 deletions
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index ed1b32a1cef5..9b87c08e517d 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -492,6 +492,95 @@ static void image_copy_rect(struct tridentfb_par *par,
492} 492}
493 493
494/* 494/*
495 * TGUI 9440/96XX acceleration
496 */
497
498static void tgui_init_accel(struct tridentfb_par *par, int pitch, int bpp)
499{
500 unsigned char x = 0;
501
502 /* disable clipping */
503 writemmr(par, 0x2148, 0);
504 writemmr(par, 0x214C, point(4095, 2047));
505
506 switch (bpp) {
507 case 8:
508 x = 0;
509 break;
510 case 16:
511 x = 1;
512 break;
513 case 24:
514 x = 3;
515 break;
516 case 32:
517 x = 2;
518 break;
519 }
520
521 switch ((pitch * bpp) / 8) {
522 case 8192:
523 case 512:
524 x |= 0x00;
525 break;
526 case 1024:
527 x |= 0x04;
528 break;
529 case 2048:
530 x |= 0x08;
531 break;
532 case 4096:
533 x |= 0x0C;
534 break;
535 }
536
537 fb_writew(x, par->io_virt + 0x2122);
538}
539
540static void tgui_fill_rect(struct tridentfb_par *par,
541 u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
542{
543 t_outb(par, ROP_P, 0x2127);
544 writemmr(par, 0x212c, c);
545 writemmr(par, 0x2128, 0x4020);
546 writemmr(par, 0x2140, point(w - 1, h - 1));
547 writemmr(par, 0x2138, point(x, y));
548 t_outb(par, 1, 0x2124);
549}
550
551static void tgui_copy_rect(struct tridentfb_par *par,
552 u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
553{
554 int flags = 0;
555 u16 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
556
557 if ((x1 < x2) && (y1 == y2)) {
558 flags |= 0x0200;
559 x1_tmp = x1 + w - 1;
560 x2_tmp = x2 + w - 1;
561 } else {
562 x1_tmp = x1;
563 x2_tmp = x2;
564 }
565
566 if (y1 < y2) {
567 flags |= 0x0100;
568 y1_tmp = y1 + h - 1;
569 y2_tmp = y2 + h - 1;
570 } else {
571 y1_tmp = y1;
572 y2_tmp = y2;
573 }
574
575 writemmr(par, 0x2128, 0x4 | flags);
576 t_outb(par, ROP_S, 0x2127);
577 writemmr(par, 0x213C, point(x1_tmp, y1_tmp));
578 writemmr(par, 0x2138, point(x2_tmp, y2_tmp));
579 writemmr(par, 0x2140, point(w - 1, h - 1));
580 t_outb(par, 1, 0x2124);
581}
582
583/*
495 * Accel functions called by the upper layers 584 * Accel functions called by the upper layers
496 */ 585 */
497#ifdef CONFIG_FB_TRIDENT_ACCEL 586#ifdef CONFIG_FB_TRIDENT_ACCEL
@@ -530,12 +619,8 @@ static void tridentfb_copyarea(struct fb_info *info,
530 ca->width, ca->height); 619 ca->width, ca->height);
531 par->wait_engine(par); 620 par->wait_engine(par);
532} 621}
533#else /* !CONFIG_FB_TRIDENT_ACCEL */
534#define tridentfb_fillrect cfb_fillrect
535#define tridentfb_copyarea cfb_copyarea
536#endif /* CONFIG_FB_TRIDENT_ACCEL */ 622#endif /* CONFIG_FB_TRIDENT_ACCEL */
537 623
538
539/* 624/*
540 * Hardware access functions 625 * Hardware access functions
541 */ 626 */
@@ -829,6 +914,7 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var,
829{ 914{
830 struct tridentfb_par *par = info->par; 915 struct tridentfb_par *par = info->par;
831 int bpp = var->bits_per_pixel; 916 int bpp = var->bits_per_pixel;
917 int line_length;
832 int ramdac = 230000; /* 230MHz for most 3D chips */ 918 int ramdac = 230000; /* 230MHz for most 3D chips */
833 debug("enter\n"); 919 debug("enter\n");
834 920
@@ -844,9 +930,27 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var,
844 var->xres = (var->xres + 7) & ~0x7; 930 var->xres = (var->xres + 7) & ~0x7;
845 if (var->xres != var->xres_virtual) 931 if (var->xres != var->xres_virtual)
846 var->xres_virtual = var->xres; 932 var->xres_virtual = var->xres;
933 line_length = var->xres_virtual * bpp / 8;
934#ifdef CONFIG_FB_TRIDENT_ACCEL
935 if (!is3Dchip(par->chip_id)) {
936 /* acceleration requires line length to be power of 2 */
937 if (line_length <= 512)
938 var->xres_virtual = 512 * 8 / bpp;
939 else if (line_length <= 1024)
940 var->xres_virtual = 1024 * 8 / bpp;
941 else if (line_length <= 2048)
942 var->xres_virtual = 2048 * 8 / bpp;
943 else if (line_length <= 4096)
944 var->xres_virtual = 4096 * 8 / bpp;
945 else if (line_length <= 8192)
946 var->xres_virtual = 8192 * 8 / bpp;
947
948 line_length = var->xres_virtual * bpp / 8;
949 }
950#endif
847 if (var->yres > var->yres_virtual) 951 if (var->yres > var->yres_virtual)
848 var->yres_virtual = var->yres; 952 var->yres_virtual = var->yres;
849 if (var->xres * var->yres_virtual * bpp / 8 > info->fix.smem_len) 953 if (line_length * var->yres_virtual > info->fix.smem_len)
850 return -EINVAL; 954 return -EINVAL;
851 955
852 switch (bpp) { 956 switch (bpp) {
@@ -918,7 +1022,7 @@ static int tridentfb_pan_display(struct fb_var_screeninfo *var,
918 unsigned int offset; 1022 unsigned int offset;
919 1023
920 debug("enter\n"); 1024 debug("enter\n");
921 offset = (var->xoffset + (var->yoffset * var->xres)) 1025 offset = (var->xoffset + (var->yoffset * var->xres_virtual))
922 * var->bits_per_pixel / 32; 1026 * var->bits_per_pixel / 32;
923 info->var.xoffset = var->xoffset; 1027 info->var.xoffset = var->xoffset;
924 info->var.yoffset = var->yoffset; 1028 info->var.yoffset = var->yoffset;
@@ -1049,7 +1153,7 @@ static int tridentfb_set_par(struct fb_info *info)
1049 write3X4(par, GraphEngReg, 0x80); 1153 write3X4(par, GraphEngReg, 0x80);
1050 1154
1051#ifdef CONFIG_FB_TRIDENT_ACCEL 1155#ifdef CONFIG_FB_TRIDENT_ACCEL
1052 par->init_accel(par, info->var.xres, bpp); 1156 par->init_accel(par, info->var.xres_virtual, bpp);
1053#endif 1157#endif
1054 1158
1055 switch (bpp) { 1159 switch (bpp) {
@@ -1147,9 +1251,9 @@ static int tridentfb_set_par(struct fb_info *info)
1147 1251
1148 if (par->flatpanel) 1252 if (par->flatpanel)
1149 set_number_of_lines(par, info->var.yres); 1253 set_number_of_lines(par, info->var.yres);
1150 set_lwidth(par, info->var.xres * bpp / (4 * 16)); 1254 info->fix.line_length = info->var.xres_virtual * bpp / 8;
1255 set_lwidth(par, info->fix.line_length / 8);
1151 info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 1256 info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1152 info->fix.line_length = info->var.xres * (bpp >> 3);
1153 info->cmap.len = (bpp == 8) ? 256 : 16; 1257 info->cmap.len = (bpp == 8) ? 256 : 16;
1154 debug("exit\n"); 1258 debug("exit\n");
1155 return 0; 1259 return 0;
@@ -1248,9 +1352,11 @@ static struct fb_ops tridentfb_ops = {
1248 .fb_blank = tridentfb_blank, 1352 .fb_blank = tridentfb_blank,
1249 .fb_check_var = tridentfb_check_var, 1353 .fb_check_var = tridentfb_check_var,
1250 .fb_set_par = tridentfb_set_par, 1354 .fb_set_par = tridentfb_set_par,
1355#ifdef CONFIG_FB_TRIDENT_ACCEL
1251 .fb_fillrect = tridentfb_fillrect, 1356 .fb_fillrect = tridentfb_fillrect,
1252 .fb_copyarea = tridentfb_copyarea, 1357 .fb_copyarea = tridentfb_copyarea,
1253 .fb_imageblit = cfb_imageblit, 1358 .fb_imageblit = cfb_imageblit,
1359#endif
1254}; 1360};
1255 1361
1256static int __devinit trident_pci_probe(struct pci_dev *dev, 1362static int __devinit trident_pci_probe(struct pci_dev *dev,
@@ -1328,11 +1434,16 @@ static int __devinit trident_pci_probe(struct pci_dev *dev,
1328 default_par->wait_engine = blade_wait_engine; 1434 default_par->wait_engine = blade_wait_engine;
1329 default_par->fill_rect = blade_fill_rect; 1435 default_par->fill_rect = blade_fill_rect;
1330 default_par->copy_rect = blade_copy_rect; 1436 default_par->copy_rect = blade_copy_rect;
1331 } else { 1437 } else if (chip3D) { /* 3DImage family left */
1332 default_par->init_accel = image_init_accel; 1438 default_par->init_accel = image_init_accel;
1333 default_par->wait_engine = image_wait_engine; 1439 default_par->wait_engine = image_wait_engine;
1334 default_par->fill_rect = image_fill_rect; 1440 default_par->fill_rect = image_fill_rect;
1335 default_par->copy_rect = image_copy_rect; 1441 default_par->copy_rect = image_copy_rect;
1442 } else { /* TGUI 9440/96XX family */
1443 default_par->init_accel = tgui_init_accel;
1444 default_par->wait_engine = xp_wait_engine;
1445 default_par->fill_rect = tgui_fill_rect;
1446 default_par->copy_rect = tgui_copy_rect;
1336 } 1447 }
1337 1448
1338 default_par->chip_id = chip_id; 1449 default_par->chip_id = chip_id;
@@ -1359,12 +1470,12 @@ static int __devinit trident_pci_probe(struct pci_dev *dev,
1359 goto out_unmap1; 1470 goto out_unmap1;
1360 } 1471 }
1361 1472
1473 enable_mmio();
1474
1362 /* setup framebuffer memory */ 1475 /* setup framebuffer memory */
1363 tridentfb_fix.smem_start = pci_resource_start(dev, 0); 1476 tridentfb_fix.smem_start = pci_resource_start(dev, 0);
1364 tridentfb_fix.smem_len = get_memsize(default_par); 1477 tridentfb_fix.smem_len = get_memsize(default_par);
1365 1478
1366 enable_mmio();
1367
1368 if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) { 1479 if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) {
1369 debug("request_mem_region failed!\n"); 1480 debug("request_mem_region failed!\n");
1370 disable_mmio(info->par); 1481 disable_mmio(info->par);