aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2007-10-16 04:28:45 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:15 -0400
commit92744dd517258181af0637105eed5f72d95e05e7 (patch)
tree5917dfd6b65813e6d2901f99265ee7e5f3f08052 /drivers
parent8af1d50f7f679375f579782f2d5eb5e2a1508df8 (diff)
tdfxfb: 3 fixes
This patch fixes 3 issues: - transparency handling in tdfxfb - panning with more than 4096 virtual height and acceleration (acceleration with x & y > 4096) - exit paths on errors in tdfxfb_probe() Additionally it sets a FBINFO_READS_FAST flag to use smart blitter scrolling (speed up on tdfxfb). Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Antonino Daplas <adaplas@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/tdfxfb.c172
1 files changed, 108 insertions, 64 deletions
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index e6aced9df52d..2566683cbfef 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -502,6 +502,8 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
502 return -EINVAL; 502 return -EINVAL;
503 } 503 }
504 504
505 var->transp.offset = 0;
506 var->transp.length = 0;
505 switch (var->bits_per_pixel) { 507 switch (var->bits_per_pixel) {
506 case 8: 508 case 8:
507 var->red.length = var->green.length = var->blue.length = 8; 509 var->red.length = var->green.length = var->blue.length = 8;
@@ -515,10 +517,12 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
515 var->blue.length = 5; 517 var->blue.length = 5;
516 break; 518 break;
517 case 32: 519 case 32:
520 var->transp.offset = 24;
521 var->transp.length = 8;
518 case 24: 522 case 24:
519 var->red.offset=16; 523 var->red.offset = 16;
520 var->green.offset=8; 524 var->green.offset = 8;
521 var->blue.offset=0; 525 var->blue.offset = 0;
522 var->red.length = var->green.length = var->blue.length = 8; 526 var->red.length = var->green.length = var->blue.length = 8;
523 break; 527 break;
524 } 528 }
@@ -874,13 +878,26 @@ static void tdfxfb_fillrect(struct fb_info *info,
874 u32 stride = info->fix.line_length; 878 u32 stride = info->fix.line_length;
875 u32 fmt= stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13); 879 u32 fmt= stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
876 int tdfx_rop; 880 int tdfx_rop;
881 u32 dx = rect->dx;
882 u32 dy = rect->dy;
883 u32 dstbase = 0;
877 884
878 if (rect->rop == ROP_COPY) 885 if (rect->rop == ROP_COPY)
879 tdfx_rop = TDFX_ROP_COPY; 886 tdfx_rop = TDFX_ROP_COPY;
880 else 887 else
881 tdfx_rop = TDFX_ROP_XOR; 888 tdfx_rop = TDFX_ROP_XOR;
882 889
883 banshee_make_room(par, 5); 890 /* asume always rect->height < 4096 */
891 if (dy + rect->height > 4095) {
892 dstbase = stride * dy;
893 dy = 0;
894 }
895 /* asume always rect->width < 4096 */
896 if (dx + rect->width > 4095) {
897 dstbase += dx * bpp >> 3;
898 dx = 0;
899 }
900 banshee_make_room(par, 6);
884 tdfx_outl(par, DSTFORMAT, fmt); 901 tdfx_outl(par, DSTFORMAT, fmt);
885 if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { 902 if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
886 tdfx_outl(par, COLORFORE, rect->color); 903 tdfx_outl(par, COLORFORE, rect->color);
@@ -888,8 +905,9 @@ static void tdfxfb_fillrect(struct fb_info *info,
888 tdfx_outl(par, COLORFORE, par->palette[rect->color]); 905 tdfx_outl(par, COLORFORE, par->palette[rect->color]);
889 } 906 }
890 tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24)); 907 tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
908 tdfx_outl(par, DSTBASE, dstbase);
891 tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16)); 909 tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16));
892 tdfx_outl(par, LAUNCH_2D, rect->dx | (rect->dy << 16)); 910 tdfx_outl(par, LAUNCH_2D, dx | (dy << 16));
893} 911}
894 912
895/* 913/*
@@ -904,6 +922,30 @@ static void tdfxfb_copyarea(struct fb_info *info,
904 u32 stride = info->fix.line_length; 922 u32 stride = info->fix.line_length;
905 u32 blitcmd = COMMAND_2D_S2S_BITBLT | (TDFX_ROP_COPY << 24); 923 u32 blitcmd = COMMAND_2D_S2S_BITBLT | (TDFX_ROP_COPY << 24);
906 u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13); 924 u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
925 u32 dstbase = 0;
926 u32 srcbase = 0;
927
928 /* asume always area->height < 4096 */
929 if (sy + area->height > 4095) {
930 srcbase = stride * sy;
931 sy = 0;
932 }
933 /* asume always area->width < 4096 */
934 if (sx + area->width > 4095) {
935 srcbase += sx * bpp >> 3;
936 sx = 0;
937 }
938 /* asume always area->height < 4096 */
939 if (dy + area->height > 4095) {
940 dstbase = stride * dy;
941 dy = 0;
942 }
943 /* asume always area->width < 4096 */
944 if (dx + area->width > 4095) {
945 dstbase += dx * bpp >> 3;
946 dx = 0;
947 }
948
907 949
908 if (area->sx <= area->dx) { 950 if (area->sx <= area->dx) {
909 //-X 951 //-X
@@ -918,13 +960,15 @@ static void tdfxfb_copyarea(struct fb_info *info,
918 dy += area->height - 1; 960 dy += area->height - 1;
919 } 961 }
920 962
921 banshee_make_room(par, 6); 963 banshee_make_room(par, 8);
922 964
923 tdfx_outl(par, SRCFORMAT, fmt); 965 tdfx_outl(par, SRCFORMAT, fmt);
924 tdfx_outl(par, DSTFORMAT, fmt); 966 tdfx_outl(par, DSTFORMAT, fmt);
925 tdfx_outl(par, COMMAND_2D, blitcmd); 967 tdfx_outl(par, COMMAND_2D, blitcmd);
926 tdfx_outl(par, DSTSIZE, area->width | (area->height << 16)); 968 tdfx_outl(par, DSTSIZE, area->width | (area->height << 16));
927 tdfx_outl(par, DSTXY, dx | (dy << 16)); 969 tdfx_outl(par, DSTXY, dx | (dy << 16));
970 tdfx_outl(par, SRCBASE, srcbase);
971 tdfx_outl(par, DSTBASE, dstbase);
928 tdfx_outl(par, LAUNCH_2D, sx | (sy << 16)); 972 tdfx_outl(par, LAUNCH_2D, sx | (sy << 16));
929} 973}
930 974
@@ -938,35 +982,48 @@ static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
938 u32 dstfmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13); 982 u32 dstfmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
939 u8 *chardata = (u8 *) image->data; 983 u8 *chardata = (u8 *) image->data;
940 u32 srcfmt; 984 u32 srcfmt;
985 u32 dx = image->dx;
986 u32 dy = image->dy;
987 u32 dstbase = 0;
941 988
942 if (image->depth != 1) { 989 if (image->depth != 1) {
943 //banshee_make_room(par, 6 + ((size + 3) >> 2)); 990 //banshee_make_room(par, 6 + ((size + 3) >> 2));
944 //srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000; 991 //srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000;
945 cfb_imageblit(info, image); 992 cfb_imageblit(info, image);
946 return; 993 return;
947 } else { 994 }
948 banshee_make_room(par, 8); 995 banshee_make_room(par, 9);
949 switch (info->fix.visual) { 996 switch (info->fix.visual) {
950 case FB_VISUAL_PSEUDOCOLOR: 997 case FB_VISUAL_PSEUDOCOLOR:
951 tdfx_outl(par, COLORFORE, image->fg_color); 998 tdfx_outl(par, COLORFORE, image->fg_color);
952 tdfx_outl(par, COLORBACK, image->bg_color); 999 tdfx_outl(par, COLORBACK, image->bg_color);
953 break; 1000 break;
954 case FB_VISUAL_TRUECOLOR: 1001 case FB_VISUAL_TRUECOLOR:
955 default: 1002 default:
956 tdfx_outl(par, COLORFORE, 1003 tdfx_outl(par, COLORFORE,
957 par->palette[image->fg_color]); 1004 par->palette[image->fg_color]);
958 tdfx_outl(par, COLORBACK, 1005 tdfx_outl(par, COLORBACK,
959 par->palette[image->bg_color]); 1006 par->palette[image->bg_color]);
960 } 1007 }
961#ifdef __BIG_ENDIAN 1008#ifdef __BIG_ENDIAN
962 srcfmt = 0x400000 | BIT(20); 1009 srcfmt = 0x400000 | BIT(20);
963#else 1010#else
964 srcfmt = 0x400000; 1011 srcfmt = 0x400000;
965#endif 1012#endif
1013 /* asume always image->height < 4096 */
1014 if (dy + image->height > 4095) {
1015 dstbase = stride * dy;
1016 dy = 0;
1017 }
1018 /* asume always image->width < 4096 */
1019 if (dx + image->width > 4095) {
1020 dstbase += dx * bpp >> 3;
1021 dx = 0;
966 } 1022 }
967 1023
1024 tdfx_outl(par, DSTBASE, dstbase);
968 tdfx_outl(par, SRCXY, 0); 1025 tdfx_outl(par, SRCXY, 0);
969 tdfx_outl(par, DSTXY, image->dx | (image->dy << 16)); 1026 tdfx_outl(par, DSTXY, dx | (dy << 16));
970 tdfx_outl(par, COMMAND_2D, COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24)); 1027 tdfx_outl(par, COMMAND_2D, COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24));
971 tdfx_outl(par, SRCFORMAT, srcfmt); 1028 tdfx_outl(par, SRCFORMAT, srcfmt);
972 tdfx_outl(par, DSTFORMAT, dstfmt); 1029 tdfx_outl(par, DSTFORMAT, dstfmt);
@@ -1211,44 +1268,36 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1211 1268
1212 tdfx_fix.mmio_start = pci_resource_start(pdev, 0); 1269 tdfx_fix.mmio_start = pci_resource_start(pdev, 0);
1213 tdfx_fix.mmio_len = pci_resource_len(pdev, 0); 1270 tdfx_fix.mmio_len = pci_resource_len(pdev, 0);
1271 if (!request_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len,
1272 "tdfx regbase")) {
1273 printk(KERN_WARNING "tdfxfb: Can't reserve regbase\n");
1274 goto out_err;
1275 }
1276
1214 default_par->regbase_virt = 1277 default_par->regbase_virt =
1215 ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len); 1278 ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len);
1216 if (!default_par->regbase_virt) { 1279 if (!default_par->regbase_virt) {
1217 printk("fb: Can't remap %s register area.\n", tdfx_fix.id); 1280 printk("fb: Can't remap %s register area.\n", tdfx_fix.id);
1218 goto out_err; 1281 goto out_err_regbase;
1219 }
1220
1221 if (!request_mem_region(pci_resource_start(pdev, 0),
1222 pci_resource_len(pdev, 0), "tdfx regbase")) {
1223 printk(KERN_WARNING "tdfxfb: Can't reserve regbase\n");
1224 goto out_err;
1225 } 1282 }
1226 1283
1227 tdfx_fix.smem_start = pci_resource_start(pdev, 1); 1284 tdfx_fix.smem_start = pci_resource_start(pdev, 1);
1228 if (!(tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device))) { 1285 if (!(tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device))) {
1229 printk("fb: Can't count %s memory.\n", tdfx_fix.id); 1286 printk("fb: Can't count %s memory.\n", tdfx_fix.id);
1230 release_mem_region(pci_resource_start(pdev, 0), 1287 goto out_err_regbase;
1231 pci_resource_len(pdev, 0));
1232 goto out_err;
1233 } 1288 }
1234 1289
1235 if (!request_mem_region(pci_resource_start(pdev, 1), 1290 if (!request_mem_region(tdfx_fix.smem_start,
1236 pci_resource_len(pdev, 1), "tdfx smem")) { 1291 pci_resource_len(pdev, 1), "tdfx smem")) {
1237 printk(KERN_WARNING "tdfxfb: Can't reserve smem\n"); 1292 printk(KERN_WARNING "tdfxfb: Can't reserve smem\n");
1238 release_mem_region(pci_resource_start(pdev, 0), 1293 goto out_err_regbase;
1239 pci_resource_len(pdev, 0));
1240 goto out_err;
1241 } 1294 }
1242 1295
1243 info->screen_base = ioremap_nocache(tdfx_fix.smem_start, 1296 info->screen_base = ioremap_nocache(tdfx_fix.smem_start,
1244 tdfx_fix.smem_len); 1297 tdfx_fix.smem_len);
1245 if (!info->screen_base) { 1298 if (!info->screen_base) {
1246 printk("fb: Can't remap %s framebuffer.\n", tdfx_fix.id); 1299 printk("fb: Can't remap %s framebuffer.\n", tdfx_fix.id);
1247 release_mem_region(pci_resource_start(pdev, 1), 1300 goto out_err_screenbase;
1248 pci_resource_len(pdev, 1));
1249 release_mem_region(pci_resource_start(pdev, 0),
1250 pci_resource_len(pdev, 0));
1251 goto out_err;
1252 } 1301 }
1253 1302
1254 default_par->iobase = pci_resource_start(pdev, 2); 1303 default_par->iobase = pci_resource_start(pdev, 2);
@@ -1256,11 +1305,7 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1256 if (!request_region(pci_resource_start(pdev, 2), 1305 if (!request_region(pci_resource_start(pdev, 2),
1257 pci_resource_len(pdev, 2), "tdfx iobase")) { 1306 pci_resource_len(pdev, 2), "tdfx iobase")) {
1258 printk(KERN_WARNING "tdfxfb: Can't reserve iobase\n"); 1307 printk(KERN_WARNING "tdfxfb: Can't reserve iobase\n");
1259 release_mem_region(pci_resource_start(pdev, 1), 1308 goto out_err_screenbase;
1260 pci_resource_len(pdev, 1));
1261 release_mem_region(pci_resource_start(pdev, 0),
1262 pci_resource_len(pdev, 0));
1263 goto out_err;
1264 } 1309 }
1265 1310
1266 printk("fb: %s memory = %dK\n", tdfx_fix.id, tdfx_fix.smem_len >> 10); 1311 printk("fb: %s memory = %dK\n", tdfx_fix.id, tdfx_fix.smem_len >> 10);
@@ -1274,7 +1319,9 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1274 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 1319 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1275#ifdef CONFIG_FB_3DFX_ACCEL 1320#ifdef CONFIG_FB_3DFX_ACCEL
1276 info->flags |= FBINFO_HWACCEL_FILLRECT | 1321 info->flags |= FBINFO_HWACCEL_FILLRECT |
1277 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_IMAGEBLIT; 1322 FBINFO_HWACCEL_COPYAREA |
1323 FBINFO_HWACCEL_IMAGEBLIT |
1324 FBINFO_READS_FAST;
1278#endif 1325#endif
1279 1326
1280 if (!mode_option) 1327 if (!mode_option)
@@ -1288,27 +1335,17 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1288 lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3); 1335 lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3);
1289 info->var.yres_virtual = info->fix.smem_len / lpitch; 1336 info->var.yres_virtual = info->fix.smem_len / lpitch;
1290 if (info->var.yres_virtual < info->var.yres) 1337 if (info->var.yres_virtual < info->var.yres)
1291 goto out_err; 1338 goto out_err_iobase;
1292
1293#ifdef CONFIG_FB_3DFX_ACCEL
1294 /*
1295 * FIXME: Limit var->yres_virtual to 4096 because of screen artifacts
1296 * during scrolling. This is only present if 2D acceleration is
1297 * enabled.
1298 */
1299 if (info->var.yres_virtual > 4096)
1300 info->var.yres_virtual = 4096;
1301#endif /* CONFIG_FB_3DFX_ACCEL */
1302 1339
1303 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { 1340 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
1304 printk(KERN_WARNING "tdfxfb: Can't allocate color map\n"); 1341 printk(KERN_WARNING "tdfxfb: Can't allocate color map\n");
1305 goto out_err; 1342 goto out_err_iobase;
1306 } 1343 }
1307 1344
1308 if (register_framebuffer(info) < 0) { 1345 if (register_framebuffer(info) < 0) {
1309 printk("tdfxfb: can't register framebuffer\n"); 1346 printk("tdfxfb: can't register framebuffer\n");
1310 fb_dealloc_cmap(&info->cmap); 1347 fb_dealloc_cmap(&info->cmap);
1311 goto out_err; 1348 goto out_err_iobase;
1312 } 1349 }
1313 /* 1350 /*
1314 * Our driver data 1351 * Our driver data
@@ -1316,14 +1353,21 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1316 pci_set_drvdata(pdev, info); 1353 pci_set_drvdata(pdev, info);
1317 return 0; 1354 return 0;
1318 1355
1319out_err: 1356out_err_iobase:
1357 release_mem_region(pci_resource_start(pdev, 2),
1358 pci_resource_len(pdev, 2));
1359out_err_screenbase:
1360 if (info->screen_base)
1361 iounmap(info->screen_base);
1362 release_mem_region(tdfx_fix.smem_start, pci_resource_len(pdev, 1));
1363out_err_regbase:
1320 /* 1364 /*
1321 * Cleanup after anything that was remapped/allocated. 1365 * Cleanup after anything that was remapped/allocated.
1322 */ 1366 */
1323 if (default_par->regbase_virt) 1367 if (default_par->regbase_virt)
1324 iounmap(default_par->regbase_virt); 1368 iounmap(default_par->regbase_virt);
1325 if (info->screen_base) 1369 release_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len);
1326 iounmap(info->screen_base); 1370out_err:
1327 framebuffer_release(info); 1371 framebuffer_release(info);
1328 return -ENXIO; 1372 return -ENXIO;
1329} 1373}