aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/cirrusfb.c
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2009-03-31 18:25:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-01 11:59:28 -0400
commit78d780e07247d52d3943b019bf9459bc9e95de1e (patch)
tree87e7f4f973fe7cf4ab2332afb354cbc9135c58a5 /drivers/video/cirrusfb.c
parent99a4584752bb41330342a427d014482525de7433 (diff)
cirrusfb: various Laguna fixes
- The Laguna GD5465 (AGP) has one register more than non-AGP chips. Recognize the AGP version and write a tile control register only on the AGP version. Tested only on an AGP card. - Bump up RAMDAC frequencies after X11 code. This allow to drive a flat panel resolution 1680x1050 at 16bpp from the 4MB card. - Fix screen start address overflow bits on Laguna cards (CRT1D register). - Fix exit path in the cirrusfb_pci_register() in case of error. 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/cirrusfb.c')
-rw-r--r--drivers/video/cirrusfb.c84
1 files changed, 57 insertions, 27 deletions
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index bab713b63a0c..cac4e2b0cbae 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -102,7 +102,8 @@ enum cirrus_board {
102 BT_PICASSO4, /* GD5446 */ 102 BT_PICASSO4, /* GD5446 */
103 BT_ALPINE, /* GD543x/4x */ 103 BT_ALPINE, /* GD543x/4x */
104 BT_GD5480, 104 BT_GD5480,
105 BT_LAGUNA, /* GD546x */ 105 BT_LAGUNA, /* GD5462/64 */
106 BT_LAGUNAB, /* GD5465 */
106}; 107};
107 108
108/* 109/*
@@ -234,8 +235,18 @@ static const struct cirrusfb_board_info_rec {
234 [BT_LAGUNA] = { 235 [BT_LAGUNA] = {
235 .name = "CL Laguna", 236 .name = "CL Laguna",
236 .maxclock = { 237 .maxclock = {
237 /* guess */ 238 /* taken from X11 code */
238 135100, 135100, 135100, 135100, 135100, 239 170000, 170000, 170000, 170000, 135100,
240 },
241 .init_sr07 = false,
242 .init_sr1f = false,
243 .scrn_start_bit19 = true,
244 },
245 [BT_LAGUNAB] = {
246 .name = "CL Laguna AGP",
247 .maxclock = {
248 /* taken from X11 code */
249 170000, 250000, 170000, 170000, 135100,
239 }, 250 },
240 .init_sr07 = false, 251 .init_sr07 = false,
241 .init_sr1f = false, 252 .init_sr1f = false,
@@ -258,7 +269,7 @@ static struct pci_device_id cirrusfb_pci_table[] = {
258 CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */ 269 CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */
259 CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */ 270 CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */
260 CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */ 271 CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */
261 CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA), /* CL Laguna 3DA*/ 272 CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNAB), /* CL Laguna 3DA*/
262 { 0, } 273 { 0, }
263}; 274};
264MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table); 275MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
@@ -385,6 +396,11 @@ static void cirrusfb_dbg_print_regs(struct fb_info *info,
385/*****************************************************************************/ 396/*****************************************************************************/
386/*** BEGIN Interface Used by the World ***************************************/ 397/*** BEGIN Interface Used by the World ***************************************/
387 398
399static inline int is_laguna(const struct cirrusfb_info *cinfo)
400{
401 return cinfo->btype == BT_LAGUNA || cinfo->btype == BT_LAGUNAB;
402}
403
388static int opencount; 404static int opencount;
389 405
390/*--- Open /dev/fbx ---------------------------------------------------------*/ 406/*--- Open /dev/fbx ---------------------------------------------------------*/
@@ -814,13 +830,16 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
814 cirrusfb_set_mclk_as_source(info, divMCLK); 830 cirrusfb_set_mclk_as_source(info, divMCLK);
815 } 831 }
816 } 832 }
817 if (cinfo->btype == BT_LAGUNA) { 833 if (is_laguna(cinfo)) {
818 long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc); 834 long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc);
819 unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407); 835 unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407);
820 unsigned short tile_control; 836 unsigned short tile_control;
821 837
822 tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4); 838 if (cinfo->btype == BT_LAGUNAB) {
823 fb_writew(tile_control & ~0x80, cinfo->laguna_mmio + 0x2c4); 839 tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4);
840 tile_control &= ~0x80;
841 fb_writew(tile_control, cinfo->laguna_mmio + 0x2c4);
842 }
824 843
825 fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc); 844 fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc);
826 fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407); 845 fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407);
@@ -842,7 +861,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
842 861
843 dev_dbg(info->device, "CL_SEQR1B: %d\n", (int) tmp); 862 dev_dbg(info->device, "CL_SEQR1B: %d\n", (int) tmp);
844 /* Laguna chipset has reversed clock registers */ 863 /* Laguna chipset has reversed clock registers */
845 if (cinfo->btype == BT_LAGUNA) { 864 if (is_laguna(cinfo)) {
846 vga_wseq(regbase, CL_SEQRE, tmp); 865 vga_wseq(regbase, CL_SEQRE, tmp);
847 vga_wseq(regbase, CL_SEQR1E, nom); 866 vga_wseq(regbase, CL_SEQR1E, nom);
848 } else { 867 } else {
@@ -873,7 +892,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
873 tmp |= 0x40; 892 tmp |= 0x40;
874 if (var->sync & FB_SYNC_VERT_HIGH_ACT) 893 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
875 tmp |= 0x80; 894 tmp |= 0x80;
876 if (cinfo->btype == BT_LAGUNA) 895 if (is_laguna(cinfo))
877 tmp |= 0xc; 896 tmp |= 0xc;
878 WGen(cinfo, VGA_MIS_W, tmp); 897 WGen(cinfo, VGA_MIS_W, tmp);
879 898
@@ -908,6 +927,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
908 break; 927 break;
909 928
910 case BT_LAGUNA: 929 case BT_LAGUNA:
930 case BT_LAGUNAB:
911 vga_wseq(regbase, CL_SEQR7, 931 vga_wseq(regbase, CL_SEQR7,
912 vga_rseq(regbase, CL_SEQR7) & ~0x01); 932 vga_rseq(regbase, CL_SEQR7) & ~0x01);
913 break; 933 break;
@@ -947,6 +967,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
947 case BT_ALPINE: 967 case BT_ALPINE:
948 case BT_GD5480: 968 case BT_GD5480:
949 case BT_LAGUNA: 969 case BT_LAGUNA:
970 case BT_LAGUNAB:
950 /* do nothing */ 971 /* do nothing */
951 break; 972 break;
952 973
@@ -991,6 +1012,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
991 break; 1012 break;
992 1013
993 case BT_LAGUNA: 1014 case BT_LAGUNA:
1015 case BT_LAGUNAB:
994 vga_wseq(regbase, CL_SEQR7, 1016 vga_wseq(regbase, CL_SEQR7,
995 vga_rseq(regbase, CL_SEQR7) | 0x01); 1017 vga_rseq(regbase, CL_SEQR7) | 0x01);
996 threshold |= 0x10; 1018 threshold |= 0x10;
@@ -1030,6 +1052,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
1030 1052
1031 case BT_GD5480: 1053 case BT_GD5480:
1032 case BT_LAGUNA: 1054 case BT_LAGUNA:
1055 case BT_LAGUNAB:
1033 /* do nothing */ 1056 /* do nothing */
1034 break; 1057 break;
1035 1058
@@ -1096,6 +1119,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
1096 break; 1119 break;
1097 1120
1098 case BT_LAGUNA: 1121 case BT_LAGUNA:
1122 case BT_LAGUNAB:
1099 vga_wseq(regbase, CL_SEQR7, 1123 vga_wseq(regbase, CL_SEQR7,
1100 vga_rseq(regbase, CL_SEQR7) & ~0x01); 1124 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1101 control |= 0x2000; 1125 control |= 0x2000;
@@ -1166,6 +1190,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
1166 break; 1190 break;
1167 1191
1168 case BT_LAGUNA: 1192 case BT_LAGUNA:
1193 case BT_LAGUNAB:
1169 vga_wseq(regbase, CL_SEQR7, 1194 vga_wseq(regbase, CL_SEQR7,
1170 vga_rseq(regbase, CL_SEQR7) & ~0x01); 1195 vga_rseq(regbase, CL_SEQR7) & ~0x01);
1171 control |= 0x6000; 1196 control |= 0x6000;
@@ -1208,7 +1233,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
1208 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) 1233 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
1209 vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1); 1234 vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1);
1210 1235
1211 if (cinfo->btype == BT_LAGUNA) { 1236 if (is_laguna(cinfo)) {
1212 tmp = 0; 1237 tmp = 0;
1213 if ((htotal + 5) & 256) 1238 if ((htotal + 5) & 256)
1214 tmp |= 128; 1239 tmp |= 128;
@@ -1234,7 +1259,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
1234 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */ 1259 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1235 AttrOn(cinfo); 1260 AttrOn(cinfo);
1236 1261
1237 if (cinfo->btype == BT_LAGUNA) { 1262 if (is_laguna(cinfo)) {
1238 /* no tiles */ 1263 /* no tiles */
1239 fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402); 1264 fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402);
1240 fb_writew(format, cinfo->laguna_mmio + 0xc0); 1265 fb_writew(format, cinfo->laguna_mmio + 0xc0);
@@ -1332,7 +1357,7 @@ static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1332 xpix = (unsigned char) ((xoffset % 4) * 2); 1357 xpix = (unsigned char) ((xoffset % 4) * 2);
1333 } 1358 }
1334 1359
1335 if (cinfo->btype != BT_LAGUNA) 1360 if (!is_laguna(cinfo))
1336 cirrusfb_WaitBLT(cinfo->regbase); 1361 cirrusfb_WaitBLT(cinfo->regbase);
1337 1362
1338 /* lower 8 + 8 bits of screen start address */ 1363 /* lower 8 + 8 bits of screen start address */
@@ -1353,8 +1378,11 @@ static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1353 1378
1354 /* construct bit 19 of screen start address */ 1379 /* construct bit 19 of screen start address */
1355 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) { 1380 if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
1356 tmp = vga_rcrt(cinfo->regbase, CL_CRT1D) & ~0x80; 1381 tmp = vga_rcrt(cinfo->regbase, CL_CRT1D);
1357 tmp |= (base >> 12) & 0x80; 1382 if (is_laguna(cinfo))
1383 tmp = (tmp & ~0x18) | ((base >> 16) & 0x18);
1384 else
1385 tmp = (tmp & ~0x80) | ((base >> 12) & 0x80);
1358 vga_wcrt(cinfo->regbase, CL_CRT1D, tmp); 1386 vga_wcrt(cinfo->regbase, CL_CRT1D, tmp);
1359 } 1387 }
1360 1388
@@ -1365,7 +1393,7 @@ static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1365 if (info->var.bits_per_pixel == 1) 1393 if (info->var.bits_per_pixel == 1)
1366 vga_wattr(cinfo->regbase, CL_AR33, xpix); 1394 vga_wattr(cinfo->regbase, CL_AR33, xpix);
1367 1395
1368 if (cinfo->btype != BT_LAGUNA) 1396 if (!is_laguna(cinfo))
1369 cirrusfb_WaitBLT(cinfo->regbase); 1397 cirrusfb_WaitBLT(cinfo->regbase);
1370 1398
1371 return 0; 1399 return 0;
@@ -1486,6 +1514,7 @@ static void init_vgachip(struct fb_info *info)
1486 break; 1514 break;
1487 1515
1488 case BT_LAGUNA: 1516 case BT_LAGUNA:
1517 case BT_LAGUNAB:
1489 case BT_ALPINE: 1518 case BT_ALPINE:
1490 /* Nothing to do to reset the board. */ 1519 /* Nothing to do to reset the board. */
1491 break; 1520 break;
@@ -1530,6 +1559,7 @@ static void init_vgachip(struct fb_info *info)
1530 break; 1559 break;
1531 case BT_ALPINE: 1560 case BT_ALPINE:
1532 case BT_LAGUNA: 1561 case BT_LAGUNA:
1562 case BT_LAGUNAB:
1533 break; 1563 break;
1534 case BT_SD64: 1564 case BT_SD64:
1535 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8); 1565 vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
@@ -1611,7 +1641,7 @@ static void init_vgachip(struct fb_info *info)
1611 /* Bit Mask: no mask at all */ 1641 /* Bit Mask: no mask at all */
1612 vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff); 1642 vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
1613 1643
1614 if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_LAGUNA) 1644 if (cinfo->btype == BT_ALPINE || is_laguna(cinfo))
1615 /* (5434 can't have bit 3 set for bitblt) */ 1645 /* (5434 can't have bit 3 set for bitblt) */
1616 vga_wgfx(cinfo->regbase, CL_GRB, 0x20); 1646 vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
1617 else 1647 else
@@ -1802,7 +1832,7 @@ static void cirrusfb_imageblit(struct fb_info *info,
1802{ 1832{
1803 struct cirrusfb_info *cinfo = info->par; 1833 struct cirrusfb_info *cinfo = info->par;
1804 1834
1805 if (cinfo->btype != BT_LAGUNA) 1835 if (!is_laguna(cinfo))
1806 cirrusfb_WaitBLT(cinfo->regbase); 1836 cirrusfb_WaitBLT(cinfo->regbase);
1807 cfb_imageblit(info, image); 1837 cfb_imageblit(info, image);
1808} 1838}
@@ -1831,7 +1861,7 @@ static unsigned int __devinit cirrusfb_get_memsize(struct fb_info *info,
1831 unsigned long mem; 1861 unsigned long mem;
1832 struct cirrusfb_info *cinfo = info->par; 1862 struct cirrusfb_info *cinfo = info->par;
1833 1863
1834 if (cinfo->btype == BT_LAGUNA) { 1864 if (is_laguna(cinfo)) {
1835 unsigned char SR14 = vga_rseq(regbase, CL_SEQR14); 1865 unsigned char SR14 = vga_rseq(regbase, CL_SEQR14);
1836 1866
1837 mem = ((SR14 & 7) + 1) << 20; 1867 mem = ((SR14 & 7) + 1) << 20;
@@ -1950,7 +1980,7 @@ static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
1950 | FBINFO_HWACCEL_YPAN 1980 | FBINFO_HWACCEL_YPAN
1951 | FBINFO_HWACCEL_FILLRECT 1981 | FBINFO_HWACCEL_FILLRECT
1952 | FBINFO_HWACCEL_COPYAREA; 1982 | FBINFO_HWACCEL_COPYAREA;
1953 if (noaccel || cinfo->btype == BT_LAGUNA) 1983 if (noaccel || is_laguna(cinfo))
1954 info->flags |= FBINFO_HWACCEL_DISABLED; 1984 info->flags |= FBINFO_HWACCEL_DISABLED;
1955 info->fbops = &cirrusfb_ops; 1985 info->fbops = &cirrusfb_ops;
1956 if (cinfo->btype == BT_GD5480) { 1986 if (cinfo->btype == BT_GD5480) {
@@ -2060,7 +2090,7 @@ static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
2060 if (!info) { 2090 if (!info) {
2061 printk(KERN_ERR "cirrusfb: could not allocate memory\n"); 2091 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2062 ret = -ENOMEM; 2092 ret = -ENOMEM;
2063 goto err_disable; 2093 goto err_out;
2064 } 2094 }
2065 2095
2066 cinfo = info->par; 2096 cinfo = info->par;
@@ -2127,10 +2157,11 @@ static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
2127 pci_set_drvdata(pdev, info); 2157 pci_set_drvdata(pdev, info);
2128 2158
2129 ret = cirrusfb_register(info); 2159 ret = cirrusfb_register(info);
2130 if (ret) 2160 if (!ret)
2131 iounmap(info->screen_base); 2161 return 0;
2132 return ret;
2133 2162
2163 pci_set_drvdata(pdev, NULL);
2164 iounmap(info->screen_base);
2134err_release_legacy: 2165err_release_legacy:
2135 if (release_io_ports) 2166 if (release_io_ports)
2136 release_region(0x3C0, 32); 2167 release_region(0x3C0, 32);
@@ -2140,10 +2171,9 @@ err_release_regions:
2140#endif 2171#endif
2141 pci_release_regions(pdev); 2172 pci_release_regions(pdev);
2142err_release_fb: 2173err_release_fb:
2143 if (cinfo->laguna_mmio == NULL) 2174 if (cinfo->laguna_mmio != NULL)
2144 iounmap(cinfo->laguna_mmio); 2175 iounmap(cinfo->laguna_mmio);
2145 framebuffer_release(info); 2176 framebuffer_release(info);
2146err_disable:
2147err_out: 2177err_out:
2148 return ret; 2178 return ret;
2149} 2179}
@@ -2439,7 +2469,7 @@ static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
2439{ 2469{
2440 unsigned char dummy; 2470 unsigned char dummy;
2441 2471
2442 if (cinfo->btype == BT_LAGUNA) 2472 if (is_laguna(cinfo))
2443 return; 2473 return;
2444 if (cinfo->btype == BT_PICASSO) { 2474 if (cinfo->btype == BT_PICASSO) {
2445 /* Klaus' hint for correct access to HDR on some boards */ 2475 /* Klaus' hint for correct access to HDR on some boards */
@@ -2509,7 +2539,7 @@ static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned ch
2509 2539
2510 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 || 2540 if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2511 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480 || 2541 cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480 ||
2512 cinfo->btype == BT_LAGUNA) { 2542 is_laguna(cinfo)) {
2513 /* but DAC data register IS, at least for Picasso II */ 2543 /* but DAC data register IS, at least for Picasso II */
2514 if (cinfo->btype == BT_PICASSO) 2544 if (cinfo->btype == BT_PICASSO)
2515 data += 0xfff; 2545 data += 0xfff;