diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2007-05-08 03:37:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:15:27 -0400 |
commit | 86c6f7d08b2868ba7cc1ef509c76ee9e9266af40 (patch) | |
tree | 0054449648223eada54e451f4e29dd8d09e9fd6c /drivers/video/tgafb.c | |
parent | 9a268a629be4c15ed85c88a61d712d92aa943847 (diff) |
tgafb: TURBOchannel support
This is support for the TC variations of the TGA boards (properly known as
SFB+ or Smart Frame Buffer Plus boards). The 8-plane SFB+ board uses the
Bt459 RAMDAC (unlike its PCI TGA counterpart, which uses the Bt485), so
bits have been added to support this chip as well.
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Cc: James Simmons <jsimmons@infradead.org>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/tgafb.c')
-rw-r--r-- | drivers/video/tgafb.c | 290 |
1 files changed, 239 insertions, 51 deletions
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 7478d0e3e211..5345fe03cdfe 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c | |||
@@ -5,27 +5,45 @@ | |||
5 | * Copyright (C) 1997 Geert Uytterhoeven | 5 | * Copyright (C) 1997 Geert Uytterhoeven |
6 | * Copyright (C) 1999,2000 Martin Lucina, Tom Zerucha | 6 | * Copyright (C) 1999,2000 Martin Lucina, Tom Zerucha |
7 | * Copyright (C) 2002 Richard Henderson | 7 | * Copyright (C) 2002 Richard Henderson |
8 | * Copyright (C) 2006 Maciej W. Rozycki | ||
8 | * | 9 | * |
9 | * This file is subject to the terms and conditions of the GNU General Public | 10 | * This file is subject to the terms and conditions of the GNU General Public |
10 | * License. See the file COPYING in the main directory of this archive for | 11 | * License. See the file COPYING in the main directory of this archive for |
11 | * more details. | 12 | * more details. |
12 | */ | 13 | */ |
13 | 14 | ||
14 | #include <linux/module.h> | 15 | #include <linux/bitrev.h> |
15 | #include <linux/kernel.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/mm.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
21 | #include <linux/init.h> | 17 | #include <linux/device.h> |
18 | #include <linux/errno.h> | ||
22 | #include <linux/fb.h> | 19 | #include <linux/fb.h> |
20 | #include <linux/init.h> | ||
21 | #include <linux/ioport.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/mm.h> | ||
24 | #include <linux/module.h> | ||
23 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
24 | #include <linux/selection.h> | 26 | #include <linux/selection.h> |
25 | #include <linux/bitrev.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/string.h> | ||
29 | #include <linux/tc.h> | ||
30 | |||
26 | #include <asm/io.h> | 31 | #include <asm/io.h> |
32 | |||
27 | #include <video/tgafb.h> | 33 | #include <video/tgafb.h> |
28 | 34 | ||
35 | #ifdef CONFIG_PCI | ||
36 | #define TGA_BUS_PCI(dev) (dev->bus == &pci_bus_type) | ||
37 | #else | ||
38 | #define TGA_BUS_PCI(dev) 0 | ||
39 | #endif | ||
40 | |||
41 | #ifdef CONFIG_TC | ||
42 | #define TGA_BUS_TC(dev) (dev->bus == &tc_bus_type) | ||
43 | #else | ||
44 | #define TGA_BUS_TC(dev) 0 | ||
45 | #endif | ||
46 | |||
29 | /* | 47 | /* |
30 | * Local functions. | 48 | * Local functions. |
31 | */ | 49 | */ |
@@ -42,12 +60,16 @@ static void tgafb_imageblit(struct fb_info *, const struct fb_image *); | |||
42 | static void tgafb_fillrect(struct fb_info *, const struct fb_fillrect *); | 60 | static void tgafb_fillrect(struct fb_info *, const struct fb_fillrect *); |
43 | static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *); | 61 | static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *); |
44 | 62 | ||
45 | static int __devinit tgafb_pci_register(struct pci_dev *, | 63 | static int __devinit tgafb_register(struct device *dev); |
46 | const struct pci_device_id *); | 64 | static void __devexit tgafb_unregister(struct device *dev); |
47 | static void __devexit tgafb_pci_unregister(struct pci_dev *); | 65 | |
66 | static const char *mode_option; | ||
67 | static const char *mode_option_pci = "640x480@60"; | ||
68 | static const char *mode_option_tc = "1280x1024@72"; | ||
48 | 69 | ||
49 | static const char *mode_option = "640x480@60"; | ||
50 | 70 | ||
71 | static struct pci_driver tgafb_pci_driver; | ||
72 | static struct tc_driver tgafb_tc_driver; | ||
51 | 73 | ||
52 | /* | 74 | /* |
53 | * Frame buffer operations | 75 | * Frame buffer operations |
@@ -65,9 +87,13 @@ static struct fb_ops tgafb_ops = { | |||
65 | }; | 87 | }; |
66 | 88 | ||
67 | 89 | ||
90 | #ifdef CONFIG_PCI | ||
68 | /* | 91 | /* |
69 | * PCI registration operations | 92 | * PCI registration operations |
70 | */ | 93 | */ |
94 | static int __devinit tgafb_pci_register(struct pci_dev *, | ||
95 | const struct pci_device_id *); | ||
96 | static void __devexit tgafb_pci_unregister(struct pci_dev *); | ||
71 | 97 | ||
72 | static struct pci_device_id const tgafb_pci_table[] = { | 98 | static struct pci_device_id const tgafb_pci_table[] = { |
73 | { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA) }, | 99 | { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA) }, |
@@ -75,13 +101,68 @@ static struct pci_device_id const tgafb_pci_table[] = { | |||
75 | }; | 101 | }; |
76 | MODULE_DEVICE_TABLE(pci, tgafb_pci_table); | 102 | MODULE_DEVICE_TABLE(pci, tgafb_pci_table); |
77 | 103 | ||
78 | static struct pci_driver tgafb_driver = { | 104 | static struct pci_driver tgafb_pci_driver = { |
79 | .name = "tgafb", | 105 | .name = "tgafb", |
80 | .id_table = tgafb_pci_table, | 106 | .id_table = tgafb_pci_table, |
81 | .probe = tgafb_pci_register, | 107 | .probe = tgafb_pci_register, |
82 | .remove = __devexit_p(tgafb_pci_unregister), | 108 | .remove = __devexit_p(tgafb_pci_unregister), |
83 | }; | 109 | }; |
84 | 110 | ||
111 | static int __devinit | ||
112 | tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) | ||
113 | { | ||
114 | return tgafb_register(&pdev->dev); | ||
115 | } | ||
116 | |||
117 | static void __devexit | ||
118 | tgafb_pci_unregister(struct pci_dev *pdev) | ||
119 | { | ||
120 | tgafb_unregister(&pdev->dev); | ||
121 | } | ||
122 | #endif /* CONFIG_PCI */ | ||
123 | |||
124 | #ifdef CONFIG_TC | ||
125 | /* | ||
126 | * TC registration operations | ||
127 | */ | ||
128 | static int __devinit tgafb_tc_register(struct device *); | ||
129 | static int __devexit tgafb_tc_unregister(struct device *); | ||
130 | |||
131 | static struct tc_device_id const tgafb_tc_table[] = { | ||
132 | { "DEC ", "PMAGD-AA" }, | ||
133 | { "DEC ", "PMAGD " }, | ||
134 | { } | ||
135 | }; | ||
136 | MODULE_DEVICE_TABLE(tc, tgafb_tc_table); | ||
137 | |||
138 | static struct tc_driver tgafb_tc_driver = { | ||
139 | .id_table = tgafb_tc_table, | ||
140 | .driver = { | ||
141 | .name = "tgafb", | ||
142 | .bus = &tc_bus_type, | ||
143 | .probe = tgafb_tc_register, | ||
144 | .remove = __devexit_p(tgafb_tc_unregister), | ||
145 | }, | ||
146 | }; | ||
147 | |||
148 | static int __devinit | ||
149 | tgafb_tc_register(struct device *dev) | ||
150 | { | ||
151 | int status = tgafb_register(dev); | ||
152 | if (!status) | ||
153 | get_device(dev); | ||
154 | return status; | ||
155 | } | ||
156 | |||
157 | static int __devexit | ||
158 | tgafb_tc_unregister(struct device *dev) | ||
159 | { | ||
160 | put_device(dev); | ||
161 | tgafb_unregister(dev); | ||
162 | return 0; | ||
163 | } | ||
164 | #endif /* CONFIG_TC */ | ||
165 | |||
85 | 166 | ||
86 | /** | 167 | /** |
87 | * tgafb_check_var - Optional function. Validates a var passed in. | 168 | * tgafb_check_var - Optional function. Validates a var passed in. |
@@ -132,10 +213,10 @@ static int | |||
132 | tgafb_set_par(struct fb_info *info) | 213 | tgafb_set_par(struct fb_info *info) |
133 | { | 214 | { |
134 | static unsigned int const deep_presets[4] = { | 215 | static unsigned int const deep_presets[4] = { |
135 | 0x00014000, | 216 | 0x00004000, |
136 | 0x0001440d, | 217 | 0x0000440d, |
137 | 0xffffffff, | 218 | 0xffffffff, |
138 | 0x0001441d | 219 | 0x0000441d |
139 | }; | 220 | }; |
140 | static unsigned int const rasterop_presets[4] = { | 221 | static unsigned int const rasterop_presets[4] = { |
141 | 0x00000003, | 222 | 0x00000003, |
@@ -157,6 +238,8 @@ tgafb_set_par(struct fb_info *info) | |||
157 | }; | 238 | }; |
158 | 239 | ||
159 | struct tga_par *par = (struct tga_par *) info->par; | 240 | struct tga_par *par = (struct tga_par *) info->par; |
241 | int tga_bus_pci = TGA_BUS_PCI(par->dev); | ||
242 | int tga_bus_tc = TGA_BUS_TC(par->dev); | ||
160 | u32 htimings, vtimings, pll_freq; | 243 | u32 htimings, vtimings, pll_freq; |
161 | u8 tga_type; | 244 | u8 tga_type; |
162 | int i; | 245 | int i; |
@@ -221,7 +304,7 @@ tgafb_set_par(struct fb_info *info) | |||
221 | TGA_WRITE_REG(par, vtimings, TGA_VERT_REG); | 304 | TGA_WRITE_REG(par, vtimings, TGA_VERT_REG); |
222 | 305 | ||
223 | /* Initalise RAMDAC. */ | 306 | /* Initalise RAMDAC. */ |
224 | if (tga_type == TGA_TYPE_8PLANE) { | 307 | if (tga_type == TGA_TYPE_8PLANE && tga_bus_pci) { |
225 | 308 | ||
226 | /* Init BT485 RAMDAC registers. */ | 309 | /* Init BT485 RAMDAC registers. */ |
227 | BT485_WRITE(par, 0xa2 | (par->sync_on_green ? 0x8 : 0x0), | 310 | BT485_WRITE(par, 0xa2 | (par->sync_on_green ? 0x8 : 0x0), |
@@ -261,6 +344,38 @@ tgafb_set_par(struct fb_info *info) | |||
261 | TGA_RAMDAC_REG); | 344 | TGA_RAMDAC_REG); |
262 | } | 345 | } |
263 | 346 | ||
347 | } else if (tga_type == TGA_TYPE_8PLANE && tga_bus_tc) { | ||
348 | |||
349 | /* Init BT459 RAMDAC registers. */ | ||
350 | BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_0, 0x40); | ||
351 | BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_1, 0x00); | ||
352 | BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_2, | ||
353 | (par->sync_on_green ? 0xc0 : 0x40)); | ||
354 | |||
355 | BT459_WRITE(par, BT459_REG_ACC, BT459_CUR_CMD_REG, 0x00); | ||
356 | |||
357 | /* Fill the palette. */ | ||
358 | BT459_LOAD_ADDR(par, 0x0000); | ||
359 | TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG); | ||
360 | |||
361 | #ifdef CONFIG_HW_CONSOLE | ||
362 | for (i = 0; i < 16; i++) { | ||
363 | int j = color_table[i]; | ||
364 | |||
365 | TGA_WRITE_REG(par, default_red[j], TGA_RAMDAC_REG); | ||
366 | TGA_WRITE_REG(par, default_grn[j], TGA_RAMDAC_REG); | ||
367 | TGA_WRITE_REG(par, default_blu[j], TGA_RAMDAC_REG); | ||
368 | } | ||
369 | for (i = 0; i < 240 * 3; i += 4) { | ||
370 | #else | ||
371 | for (i = 0; i < 256 * 3; i += 4) { | ||
372 | #endif | ||
373 | TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG); | ||
374 | TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG); | ||
375 | TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG); | ||
376 | TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG); | ||
377 | } | ||
378 | |||
264 | } else { /* 24-plane or 24plusZ */ | 379 | } else { /* 24-plane or 24plusZ */ |
265 | 380 | ||
266 | /* Init BT463 RAMDAC registers. */ | 381 | /* Init BT463 RAMDAC registers. */ |
@@ -431,6 +546,8 @@ tgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, | |||
431 | unsigned transp, struct fb_info *info) | 546 | unsigned transp, struct fb_info *info) |
432 | { | 547 | { |
433 | struct tga_par *par = (struct tga_par *) info->par; | 548 | struct tga_par *par = (struct tga_par *) info->par; |
549 | int tga_bus_pci = TGA_BUS_PCI(par->dev); | ||
550 | int tga_bus_tc = TGA_BUS_TC(par->dev); | ||
434 | 551 | ||
435 | if (regno > 255) | 552 | if (regno > 255) |
436 | return 1; | 553 | return 1; |
@@ -438,12 +555,18 @@ tgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, | |||
438 | green >>= 8; | 555 | green >>= 8; |
439 | blue >>= 8; | 556 | blue >>= 8; |
440 | 557 | ||
441 | if (par->tga_type == TGA_TYPE_8PLANE) { | 558 | if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_pci) { |
442 | BT485_WRITE(par, regno, BT485_ADDR_PAL_WRITE); | 559 | BT485_WRITE(par, regno, BT485_ADDR_PAL_WRITE); |
443 | TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG); | 560 | TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG); |
444 | TGA_WRITE_REG(par, red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG); | 561 | TGA_WRITE_REG(par, red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG); |
445 | TGA_WRITE_REG(par, green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG); | 562 | TGA_WRITE_REG(par, green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG); |
446 | TGA_WRITE_REG(par, blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG); | 563 | TGA_WRITE_REG(par, blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG); |
564 | } else if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_tc) { | ||
565 | BT459_LOAD_ADDR(par, regno); | ||
566 | TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG); | ||
567 | TGA_WRITE_REG(par, red, TGA_RAMDAC_REG); | ||
568 | TGA_WRITE_REG(par, green, TGA_RAMDAC_REG); | ||
569 | TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG); | ||
447 | } else { | 570 | } else { |
448 | if (regno < 16) { | 571 | if (regno < 16) { |
449 | u32 value = (regno << 16) | (regno << 8) | regno; | 572 | u32 value = (regno << 16) | (regno << 8) | regno; |
@@ -1309,18 +1432,29 @@ static void | |||
1309 | tgafb_init_fix(struct fb_info *info) | 1432 | tgafb_init_fix(struct fb_info *info) |
1310 | { | 1433 | { |
1311 | struct tga_par *par = (struct tga_par *)info->par; | 1434 | struct tga_par *par = (struct tga_par *)info->par; |
1435 | int tga_bus_pci = TGA_BUS_PCI(par->dev); | ||
1436 | int tga_bus_tc = TGA_BUS_TC(par->dev); | ||
1312 | u8 tga_type = par->tga_type; | 1437 | u8 tga_type = par->tga_type; |
1313 | const char *tga_type_name; | 1438 | const char *tga_type_name = NULL; |
1314 | 1439 | ||
1315 | switch (tga_type) { | 1440 | switch (tga_type) { |
1316 | case TGA_TYPE_8PLANE: | 1441 | case TGA_TYPE_8PLANE: |
1317 | tga_type_name = "Digital ZLXp-E1"; | 1442 | if (tga_bus_pci) |
1443 | tga_type_name = "Digital ZLXp-E1"; | ||
1444 | if (tga_bus_tc) | ||
1445 | tga_type_name = "Digital ZLX-E1"; | ||
1318 | break; | 1446 | break; |
1319 | case TGA_TYPE_24PLANE: | 1447 | case TGA_TYPE_24PLANE: |
1320 | tga_type_name = "Digital ZLXp-E2"; | 1448 | if (tga_bus_pci) |
1449 | tga_type_name = "Digital ZLXp-E2"; | ||
1450 | if (tga_bus_tc) | ||
1451 | tga_type_name = "Digital ZLX-E2"; | ||
1321 | break; | 1452 | break; |
1322 | case TGA_TYPE_24PLUSZ: | 1453 | case TGA_TYPE_24PLUSZ: |
1323 | tga_type_name = "Digital ZLXp-E3"; | 1454 | if (tga_bus_pci) |
1455 | tga_type_name = "Digital ZLXp-E3"; | ||
1456 | if (tga_bus_tc) | ||
1457 | tga_type_name = "Digital ZLX-E3"; | ||
1324 | break; | 1458 | break; |
1325 | default: | 1459 | default: |
1326 | tga_type_name = "Unknown"; | 1460 | tga_type_name = "Unknown"; |
@@ -1348,9 +1482,15 @@ tgafb_init_fix(struct fb_info *info) | |||
1348 | info->fix.accel = FB_ACCEL_DEC_TGA; | 1482 | info->fix.accel = FB_ACCEL_DEC_TGA; |
1349 | } | 1483 | } |
1350 | 1484 | ||
1351 | static __devinit int | 1485 | static int __devinit |
1352 | tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) | 1486 | tgafb_register(struct device *dev) |
1353 | { | 1487 | { |
1488 | static const struct fb_videomode modedb_tc = { | ||
1489 | /* 1280x1024 @ 72 Hz, 76.8 kHz hsync */ | ||
1490 | "1280x1024@72", 0, 1280, 1024, 7645, 224, 28, 33, 3, 160, 3, | ||
1491 | FB_SYNC_ON_GREEN, FB_VMODE_NONINTERLACED | ||
1492 | }; | ||
1493 | |||
1354 | static unsigned int const fb_offset_presets[4] = { | 1494 | static unsigned int const fb_offset_presets[4] = { |
1355 | TGA_8PLANE_FB_OFFSET, | 1495 | TGA_8PLANE_FB_OFFSET, |
1356 | TGA_24PLANE_FB_OFFSET, | 1496 | TGA_24PLANE_FB_OFFSET, |
@@ -1358,40 +1498,51 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1358 | TGA_24PLUSZ_FB_OFFSET | 1498 | TGA_24PLUSZ_FB_OFFSET |
1359 | }; | 1499 | }; |
1360 | 1500 | ||
1501 | const struct fb_videomode *modedb_tga = NULL; | ||
1502 | resource_size_t bar0_start = 0, bar0_len = 0; | ||
1503 | const char *mode_option_tga = NULL; | ||
1504 | int tga_bus_pci = TGA_BUS_PCI(dev); | ||
1505 | int tga_bus_tc = TGA_BUS_TC(dev); | ||
1506 | unsigned int modedbsize_tga = 0; | ||
1361 | void __iomem *mem_base; | 1507 | void __iomem *mem_base; |
1362 | unsigned long bar0_start, bar0_len; | ||
1363 | struct fb_info *info; | 1508 | struct fb_info *info; |
1364 | struct tga_par *par; | 1509 | struct tga_par *par; |
1365 | u8 tga_type; | 1510 | u8 tga_type; |
1366 | int ret; | 1511 | int ret = 0; |
1367 | 1512 | ||
1368 | /* Enable device in PCI config. */ | 1513 | /* Enable device in PCI config. */ |
1369 | if (pci_enable_device(pdev)) { | 1514 | if (tga_bus_pci && pci_enable_device(to_pci_dev(dev))) { |
1370 | printk(KERN_ERR "tgafb: Cannot enable PCI device\n"); | 1515 | printk(KERN_ERR "tgafb: Cannot enable PCI device\n"); |
1371 | return -ENODEV; | 1516 | return -ENODEV; |
1372 | } | 1517 | } |
1373 | 1518 | ||
1374 | /* Allocate the fb and par structures. */ | 1519 | /* Allocate the fb and par structures. */ |
1375 | info = framebuffer_alloc(sizeof(struct tga_par), &pdev->dev); | 1520 | info = framebuffer_alloc(sizeof(struct tga_par), dev); |
1376 | if (!info) { | 1521 | if (!info) { |
1377 | printk(KERN_ERR "tgafb: Cannot allocate memory\n"); | 1522 | printk(KERN_ERR "tgafb: Cannot allocate memory\n"); |
1378 | return -ENOMEM; | 1523 | return -ENOMEM; |
1379 | } | 1524 | } |
1380 | 1525 | ||
1381 | par = info->par; | 1526 | par = info->par; |
1382 | pci_set_drvdata(pdev, info); | 1527 | dev_set_drvdata(dev, info); |
1383 | 1528 | ||
1384 | /* Request the mem regions. */ | 1529 | /* Request the mem regions. */ |
1385 | bar0_start = pci_resource_start(pdev, 0); | ||
1386 | bar0_len = pci_resource_len(pdev, 0); | ||
1387 | ret = -ENODEV; | 1530 | ret = -ENODEV; |
1531 | if (tga_bus_pci) { | ||
1532 | bar0_start = pci_resource_start(to_pci_dev(dev), 0); | ||
1533 | bar0_len = pci_resource_len(to_pci_dev(dev), 0); | ||
1534 | } | ||
1535 | if (tga_bus_tc) { | ||
1536 | bar0_start = to_tc_dev(dev)->resource.start; | ||
1537 | bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1; | ||
1538 | } | ||
1388 | if (!request_mem_region (bar0_start, bar0_len, "tgafb")) { | 1539 | if (!request_mem_region (bar0_start, bar0_len, "tgafb")) { |
1389 | printk(KERN_ERR "tgafb: cannot reserve FB region\n"); | 1540 | printk(KERN_ERR "tgafb: cannot reserve FB region\n"); |
1390 | goto err0; | 1541 | goto err0; |
1391 | } | 1542 | } |
1392 | 1543 | ||
1393 | /* Map the framebuffer. */ | 1544 | /* Map the framebuffer. */ |
1394 | mem_base = ioremap(bar0_start, bar0_len); | 1545 | mem_base = ioremap_nocache(bar0_start, bar0_len); |
1395 | if (!mem_base) { | 1546 | if (!mem_base) { |
1396 | printk(KERN_ERR "tgafb: Cannot map MMIO\n"); | 1547 | printk(KERN_ERR "tgafb: Cannot map MMIO\n"); |
1397 | goto err1; | 1548 | goto err1; |
@@ -1399,12 +1550,16 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1399 | 1550 | ||
1400 | /* Grab info about the card. */ | 1551 | /* Grab info about the card. */ |
1401 | tga_type = (readl(mem_base) >> 12) & 0x0f; | 1552 | tga_type = (readl(mem_base) >> 12) & 0x0f; |
1402 | par->pdev = pdev; | 1553 | par->dev = dev; |
1403 | par->tga_mem_base = mem_base; | 1554 | par->tga_mem_base = mem_base; |
1404 | par->tga_fb_base = mem_base + fb_offset_presets[tga_type]; | 1555 | par->tga_fb_base = mem_base + fb_offset_presets[tga_type]; |
1405 | par->tga_regs_base = mem_base + TGA_REGS_OFFSET; | 1556 | par->tga_regs_base = mem_base + TGA_REGS_OFFSET; |
1406 | par->tga_type = tga_type; | 1557 | par->tga_type = tga_type; |
1407 | pci_read_config_byte(pdev, PCI_REVISION_ID, &par->tga_chip_rev); | 1558 | if (tga_bus_pci) |
1559 | pci_read_config_byte(to_pci_dev(dev), PCI_REVISION_ID, | ||
1560 | &par->tga_chip_rev); | ||
1561 | if (tga_bus_tc) | ||
1562 | par->tga_chip_rev = TGA_READ_REG(par, TGA_START_REG) & 0xff; | ||
1408 | 1563 | ||
1409 | /* Setup framebuffer. */ | 1564 | /* Setup framebuffer. */ |
1410 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | | 1565 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | |
@@ -1414,8 +1569,17 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1414 | info->pseudo_palette = (void *)(par + 1); | 1569 | info->pseudo_palette = (void *)(par + 1); |
1415 | 1570 | ||
1416 | /* This should give a reasonable default video mode. */ | 1571 | /* This should give a reasonable default video mode. */ |
1417 | 1572 | if (tga_bus_pci) { | |
1418 | ret = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, | 1573 | mode_option_tga = mode_option_pci; |
1574 | } | ||
1575 | if (tga_bus_tc) { | ||
1576 | mode_option_tga = mode_option_tc; | ||
1577 | modedb_tga = &modedb_tc; | ||
1578 | modedbsize_tga = 1; | ||
1579 | } | ||
1580 | ret = fb_find_mode(&info->var, info, | ||
1581 | mode_option ? mode_option : mode_option_tga, | ||
1582 | modedb_tga, modedbsize_tga, NULL, | ||
1419 | tga_type == TGA_TYPE_8PLANE ? 8 : 32); | 1583 | tga_type == TGA_TYPE_8PLANE ? 8 : 32); |
1420 | if (ret == 0 || ret == 4) { | 1584 | if (ret == 0 || ret == 4) { |
1421 | printk(KERN_ERR "tgafb: Could not find valid video mode\n"); | 1585 | printk(KERN_ERR "tgafb: Could not find valid video mode\n"); |
@@ -1438,13 +1602,19 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1438 | goto err1; | 1602 | goto err1; |
1439 | } | 1603 | } |
1440 | 1604 | ||
1441 | printk(KERN_INFO "tgafb: DC21030 [TGA] detected, rev=0x%02x\n", | 1605 | if (tga_bus_pci) { |
1442 | par->tga_chip_rev); | 1606 | pr_info("tgafb: DC21030 [TGA] detected, rev=0x%02x\n", |
1443 | printk(KERN_INFO "tgafb: at PCI bus %d, device %d, function %d\n", | 1607 | par->tga_chip_rev); |
1444 | pdev->bus->number, PCI_SLOT(pdev->devfn), | 1608 | pr_info("tgafb: at PCI bus %d, device %d, function %d\n", |
1445 | PCI_FUNC(pdev->devfn)); | 1609 | to_pci_dev(dev)->bus->number, |
1446 | printk(KERN_INFO "fb%d: %s frame buffer device at 0x%lx\n", | 1610 | PCI_SLOT(to_pci_dev(dev)->devfn), |
1447 | info->node, info->fix.id, bar0_start); | 1611 | PCI_FUNC(to_pci_dev(dev)->devfn)); |
1612 | } | ||
1613 | if (tga_bus_tc) | ||
1614 | pr_info("tgafb: SFB+ detected, rev=0x%02x\n", | ||
1615 | par->tga_chip_rev); | ||
1616 | pr_info("fb%d: %s frame buffer device at 0x%lx\n", | ||
1617 | info->node, info->fix.id, (long)bar0_start); | ||
1448 | 1618 | ||
1449 | return 0; | 1619 | return 0; |
1450 | 1620 | ||
@@ -1458,25 +1628,39 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1458 | } | 1628 | } |
1459 | 1629 | ||
1460 | static void __devexit | 1630 | static void __devexit |
1461 | tgafb_pci_unregister(struct pci_dev *pdev) | 1631 | tgafb_unregister(struct device *dev) |
1462 | { | 1632 | { |
1463 | struct fb_info *info = pci_get_drvdata(pdev); | 1633 | resource_size_t bar0_start = 0, bar0_len = 0; |
1464 | struct tga_par *par = info->par; | 1634 | int tga_bus_pci = TGA_BUS_PCI(dev); |
1635 | int tga_bus_tc = TGA_BUS_TC(dev); | ||
1636 | struct fb_info *info = NULL; | ||
1637 | struct tga_par *par; | ||
1465 | 1638 | ||
1639 | info = dev_get_drvdata(dev); | ||
1466 | if (!info) | 1640 | if (!info) |
1467 | return; | 1641 | return; |
1642 | |||
1643 | par = info->par; | ||
1468 | unregister_framebuffer(info); | 1644 | unregister_framebuffer(info); |
1469 | fb_dealloc_cmap(&info->cmap); | 1645 | fb_dealloc_cmap(&info->cmap); |
1470 | iounmap(par->tga_mem_base); | 1646 | iounmap(par->tga_mem_base); |
1471 | release_mem_region(pci_resource_start(pdev, 0), | 1647 | if (tga_bus_pci) { |
1472 | pci_resource_len(pdev, 0)); | 1648 | bar0_start = pci_resource_start(to_pci_dev(dev), 0); |
1649 | bar0_len = pci_resource_len(to_pci_dev(dev), 0); | ||
1650 | } | ||
1651 | if (tga_bus_tc) { | ||
1652 | bar0_start = to_tc_dev(dev)->resource.start; | ||
1653 | bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1; | ||
1654 | } | ||
1655 | release_mem_region(bar0_start, bar0_len); | ||
1473 | framebuffer_release(info); | 1656 | framebuffer_release(info); |
1474 | } | 1657 | } |
1475 | 1658 | ||
1476 | static void __devexit | 1659 | static void __devexit |
1477 | tgafb_exit(void) | 1660 | tgafb_exit(void) |
1478 | { | 1661 | { |
1479 | pci_unregister_driver(&tgafb_driver); | 1662 | tc_unregister_driver(&tgafb_tc_driver); |
1663 | pci_unregister_driver(&tgafb_pci_driver); | ||
1480 | } | 1664 | } |
1481 | 1665 | ||
1482 | #ifndef MODULE | 1666 | #ifndef MODULE |
@@ -1505,6 +1689,7 @@ tgafb_setup(char *arg) | |||
1505 | static int __devinit | 1689 | static int __devinit |
1506 | tgafb_init(void) | 1690 | tgafb_init(void) |
1507 | { | 1691 | { |
1692 | int status; | ||
1508 | #ifndef MODULE | 1693 | #ifndef MODULE |
1509 | char *option = NULL; | 1694 | char *option = NULL; |
1510 | 1695 | ||
@@ -1512,7 +1697,10 @@ tgafb_init(void) | |||
1512 | return -ENODEV; | 1697 | return -ENODEV; |
1513 | tgafb_setup(option); | 1698 | tgafb_setup(option); |
1514 | #endif | 1699 | #endif |
1515 | return pci_register_driver(&tgafb_driver); | 1700 | status = pci_register_driver(&tgafb_pci_driver); |
1701 | if (!status) | ||
1702 | status = tc_register_driver(&tgafb_tc_driver); | ||
1703 | return status; | ||
1516 | } | 1704 | } |
1517 | 1705 | ||
1518 | /* | 1706 | /* |
@@ -1522,5 +1710,5 @@ tgafb_init(void) | |||
1522 | module_init(tgafb_init); | 1710 | module_init(tgafb_init); |
1523 | module_exit(tgafb_exit); | 1711 | module_exit(tgafb_exit); |
1524 | 1712 | ||
1525 | MODULE_DESCRIPTION("framebuffer driver for TGA chipset"); | 1713 | MODULE_DESCRIPTION("Framebuffer driver for TGA/SFB+ chipset"); |
1526 | MODULE_LICENSE("GPL"); | 1714 | MODULE_LICENSE("GPL"); |