diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/cirrusfb.c | 84 |
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 | }; |
264 | MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table); | 275 | MODULE_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 | ||
399 | static inline int is_laguna(const struct cirrusfb_info *cinfo) | ||
400 | { | ||
401 | return cinfo->btype == BT_LAGUNA || cinfo->btype == BT_LAGUNAB; | ||
402 | } | ||
403 | |||
388 | static int opencount; | 404 | static 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); | ||
2134 | err_release_legacy: | 2165 | err_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); |
2142 | err_release_fb: | 2173 | err_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); |
2146 | err_disable: | ||
2147 | err_out: | 2177 | err_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; |