diff options
Diffstat (limited to 'drivers/video/tridentfb.c')
-rw-r--r-- | drivers/video/tridentfb.c | 135 |
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 | |||
498 | static 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 | |||
540 | static 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 | |||
551 | static 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 | ||
1256 | static int __devinit trident_pci_probe(struct pci_dev *dev, | 1362 | static 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); |