aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/tridentfb.c
diff options
context:
space:
mode:
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);