diff options
Diffstat (limited to 'drivers/video/cyber2000fb.c')
-rw-r--r-- | drivers/video/cyber2000fb.c | 263 |
1 files changed, 237 insertions, 26 deletions
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 0c1afd13ddd3..850380795b05 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c | |||
@@ -47,6 +47,8 @@ | |||
47 | #include <linux/pci.h> | 47 | #include <linux/pci.h> |
48 | #include <linux/init.h> | 48 | #include <linux/init.h> |
49 | #include <linux/io.h> | 49 | #include <linux/io.h> |
50 | #include <linux/i2c.h> | ||
51 | #include <linux/i2c-algo-bit.h> | ||
50 | 52 | ||
51 | #include <asm/pgtable.h> | 53 | #include <asm/pgtable.h> |
52 | #include <asm/system.h> | 54 | #include <asm/system.h> |
@@ -61,10 +63,10 @@ struct cfb_info { | |||
61 | struct fb_info fb; | 63 | struct fb_info fb; |
62 | struct display_switch *dispsw; | 64 | struct display_switch *dispsw; |
63 | struct display *display; | 65 | struct display *display; |
64 | struct pci_dev *dev; | ||
65 | unsigned char __iomem *region; | 66 | unsigned char __iomem *region; |
66 | unsigned char __iomem *regs; | 67 | unsigned char __iomem *regs; |
67 | u_int id; | 68 | u_int id; |
69 | u_int irq; | ||
68 | int func_use_count; | 70 | int func_use_count; |
69 | u_long ref_ps; | 71 | u_long ref_ps; |
70 | 72 | ||
@@ -88,6 +90,19 @@ struct cfb_info { | |||
88 | u_char ramdac_powerdown; | 90 | u_char ramdac_powerdown; |
89 | 91 | ||
90 | u32 pseudo_palette[16]; | 92 | u32 pseudo_palette[16]; |
93 | |||
94 | spinlock_t reg_b0_lock; | ||
95 | |||
96 | #ifdef CONFIG_FB_CYBER2000_DDC | ||
97 | bool ddc_registered; | ||
98 | struct i2c_adapter ddc_adapter; | ||
99 | struct i2c_algo_bit_data ddc_algo; | ||
100 | #endif | ||
101 | |||
102 | #ifdef CONFIG_FB_CYBER2000_I2C | ||
103 | struct i2c_adapter i2c_adapter; | ||
104 | struct i2c_algo_bit_data i2c_algo; | ||
105 | #endif | ||
91 | }; | 106 | }; |
92 | 107 | ||
93 | static char *default_font = "Acorn8x8"; | 108 | static char *default_font = "Acorn8x8"; |
@@ -494,6 +509,7 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw) | |||
494 | cyber2000_attrw(0x14, 0x00, cfb); | 509 | cyber2000_attrw(0x14, 0x00, cfb); |
495 | 510 | ||
496 | /* PLL registers */ | 511 | /* PLL registers */ |
512 | spin_lock(&cfb->reg_b0_lock); | ||
497 | cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb); | 513 | cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb); |
498 | cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb); | 514 | cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb); |
499 | cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb); | 515 | cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb); |
@@ -501,6 +517,7 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw) | |||
501 | cyber2000_grphw(0x90, 0x01, cfb); | 517 | cyber2000_grphw(0x90, 0x01, cfb); |
502 | cyber2000_grphw(0xb9, 0x80, cfb); | 518 | cyber2000_grphw(0xb9, 0x80, cfb); |
503 | cyber2000_grphw(0xb9, 0x00, cfb); | 519 | cyber2000_grphw(0xb9, 0x00, cfb); |
520 | spin_unlock(&cfb->reg_b0_lock); | ||
504 | 521 | ||
505 | cfb->ramdac_ctrl = hw->ramdac; | 522 | cfb->ramdac_ctrl = hw->ramdac; |
506 | cyber2000fb_write_ramdac_ctrl(cfb); | 523 | cyber2000fb_write_ramdac_ctrl(cfb); |
@@ -681,9 +698,9 @@ cyber2000fb_decode_clock(struct par_info *hw, struct cfb_info *cfb, | |||
681 | * pll_ps_calc = best_div1 / (ref_ps * best_mult) | 698 | * pll_ps_calc = best_div1 / (ref_ps * best_mult) |
682 | */ | 699 | */ |
683 | best_diff = 0x7fffffff; | 700 | best_diff = 0x7fffffff; |
684 | best_mult = 32; | 701 | best_mult = 2; |
685 | best_div1 = 255; | 702 | best_div1 = 32; |
686 | for (t_div1 = 32; t_div1 > 1; t_div1 -= 1) { | 703 | for (t_div1 = 2; t_div1 < 32; t_div1 += 1) { |
687 | u_int rr, t_mult, t_pll_ps; | 704 | u_int rr, t_mult, t_pll_ps; |
688 | int diff; | 705 | int diff; |
689 | 706 | ||
@@ -1105,24 +1122,22 @@ void cyber2000fb_disable_extregs(struct cfb_info *cfb) | |||
1105 | } | 1122 | } |
1106 | EXPORT_SYMBOL(cyber2000fb_disable_extregs); | 1123 | EXPORT_SYMBOL(cyber2000fb_disable_extregs); |
1107 | 1124 | ||
1108 | void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var) | ||
1109 | { | ||
1110 | memcpy(var, &cfb->fb.var, sizeof(struct fb_var_screeninfo)); | ||
1111 | } | ||
1112 | EXPORT_SYMBOL(cyber2000fb_get_fb_var); | ||
1113 | |||
1114 | /* | 1125 | /* |
1115 | * Attach a capture/tv driver to the core CyberX0X0 driver. | 1126 | * Attach a capture/tv driver to the core CyberX0X0 driver. |
1116 | */ | 1127 | */ |
1117 | int cyber2000fb_attach(struct cyberpro_info *info, int idx) | 1128 | int cyber2000fb_attach(struct cyberpro_info *info, int idx) |
1118 | { | 1129 | { |
1119 | if (int_cfb_info != NULL) { | 1130 | if (int_cfb_info != NULL) { |
1120 | info->dev = int_cfb_info->dev; | 1131 | info->dev = int_cfb_info->fb.device; |
1132 | #ifdef CONFIG_FB_CYBER2000_I2C | ||
1133 | info->i2c = &int_cfb_info->i2c_adapter; | ||
1134 | #else | ||
1135 | info->i2c = NULL; | ||
1136 | #endif | ||
1121 | info->regs = int_cfb_info->regs; | 1137 | info->regs = int_cfb_info->regs; |
1138 | info->irq = int_cfb_info->irq; | ||
1122 | info->fb = int_cfb_info->fb.screen_base; | 1139 | info->fb = int_cfb_info->fb.screen_base; |
1123 | info->fb_size = int_cfb_info->fb.fix.smem_len; | 1140 | info->fb_size = int_cfb_info->fb.fix.smem_len; |
1124 | info->enable_extregs = cyber2000fb_enable_extregs; | ||
1125 | info->disable_extregs = cyber2000fb_disable_extregs; | ||
1126 | info->info = int_cfb_info; | 1141 | info->info = int_cfb_info; |
1127 | 1142 | ||
1128 | strlcpy(info->dev_name, int_cfb_info->fb.fix.id, | 1143 | strlcpy(info->dev_name, int_cfb_info->fb.fix.id, |
@@ -1141,6 +1156,183 @@ void cyber2000fb_detach(int idx) | |||
1141 | } | 1156 | } |
1142 | EXPORT_SYMBOL(cyber2000fb_detach); | 1157 | EXPORT_SYMBOL(cyber2000fb_detach); |
1143 | 1158 | ||
1159 | #ifdef CONFIG_FB_CYBER2000_DDC | ||
1160 | |||
1161 | #define DDC_REG 0xb0 | ||
1162 | #define DDC_SCL_OUT (1 << 0) | ||
1163 | #define DDC_SDA_OUT (1 << 4) | ||
1164 | #define DDC_SCL_IN (1 << 2) | ||
1165 | #define DDC_SDA_IN (1 << 6) | ||
1166 | |||
1167 | static void cyber2000fb_enable_ddc(struct cfb_info *cfb) | ||
1168 | { | ||
1169 | spin_lock(&cfb->reg_b0_lock); | ||
1170 | cyber2000fb_writew(0x1bf, 0x3ce, cfb); | ||
1171 | } | ||
1172 | |||
1173 | static void cyber2000fb_disable_ddc(struct cfb_info *cfb) | ||
1174 | { | ||
1175 | cyber2000fb_writew(0x0bf, 0x3ce, cfb); | ||
1176 | spin_unlock(&cfb->reg_b0_lock); | ||
1177 | } | ||
1178 | |||
1179 | |||
1180 | static void cyber2000fb_ddc_setscl(void *data, int val) | ||
1181 | { | ||
1182 | struct cfb_info *cfb = data; | ||
1183 | unsigned char reg; | ||
1184 | |||
1185 | cyber2000fb_enable_ddc(cfb); | ||
1186 | reg = cyber2000_grphr(DDC_REG, cfb); | ||
1187 | if (!val) /* bit is inverted */ | ||
1188 | reg |= DDC_SCL_OUT; | ||
1189 | else | ||
1190 | reg &= ~DDC_SCL_OUT; | ||
1191 | cyber2000_grphw(DDC_REG, reg, cfb); | ||
1192 | cyber2000fb_disable_ddc(cfb); | ||
1193 | } | ||
1194 | |||
1195 | static void cyber2000fb_ddc_setsda(void *data, int val) | ||
1196 | { | ||
1197 | struct cfb_info *cfb = data; | ||
1198 | unsigned char reg; | ||
1199 | |||
1200 | cyber2000fb_enable_ddc(cfb); | ||
1201 | reg = cyber2000_grphr(DDC_REG, cfb); | ||
1202 | if (!val) /* bit is inverted */ | ||
1203 | reg |= DDC_SDA_OUT; | ||
1204 | else | ||
1205 | reg &= ~DDC_SDA_OUT; | ||
1206 | cyber2000_grphw(DDC_REG, reg, cfb); | ||
1207 | cyber2000fb_disable_ddc(cfb); | ||
1208 | } | ||
1209 | |||
1210 | static int cyber2000fb_ddc_getscl(void *data) | ||
1211 | { | ||
1212 | struct cfb_info *cfb = data; | ||
1213 | int retval; | ||
1214 | |||
1215 | cyber2000fb_enable_ddc(cfb); | ||
1216 | retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SCL_IN); | ||
1217 | cyber2000fb_disable_ddc(cfb); | ||
1218 | |||
1219 | return retval; | ||
1220 | } | ||
1221 | |||
1222 | static int cyber2000fb_ddc_getsda(void *data) | ||
1223 | { | ||
1224 | struct cfb_info *cfb = data; | ||
1225 | int retval; | ||
1226 | |||
1227 | cyber2000fb_enable_ddc(cfb); | ||
1228 | retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SDA_IN); | ||
1229 | cyber2000fb_disable_ddc(cfb); | ||
1230 | |||
1231 | return retval; | ||
1232 | } | ||
1233 | |||
1234 | static int __devinit cyber2000fb_setup_ddc_bus(struct cfb_info *cfb) | ||
1235 | { | ||
1236 | strlcpy(cfb->ddc_adapter.name, cfb->fb.fix.id, | ||
1237 | sizeof(cfb->ddc_adapter.name)); | ||
1238 | cfb->ddc_adapter.owner = THIS_MODULE; | ||
1239 | cfb->ddc_adapter.class = I2C_CLASS_DDC; | ||
1240 | cfb->ddc_adapter.algo_data = &cfb->ddc_algo; | ||
1241 | cfb->ddc_adapter.dev.parent = cfb->fb.device; | ||
1242 | cfb->ddc_algo.setsda = cyber2000fb_ddc_setsda; | ||
1243 | cfb->ddc_algo.setscl = cyber2000fb_ddc_setscl; | ||
1244 | cfb->ddc_algo.getsda = cyber2000fb_ddc_getsda; | ||
1245 | cfb->ddc_algo.getscl = cyber2000fb_ddc_getscl; | ||
1246 | cfb->ddc_algo.udelay = 10; | ||
1247 | cfb->ddc_algo.timeout = 20; | ||
1248 | cfb->ddc_algo.data = cfb; | ||
1249 | |||
1250 | i2c_set_adapdata(&cfb->ddc_adapter, cfb); | ||
1251 | |||
1252 | return i2c_bit_add_bus(&cfb->ddc_adapter); | ||
1253 | } | ||
1254 | #endif /* CONFIG_FB_CYBER2000_DDC */ | ||
1255 | |||
1256 | #ifdef CONFIG_FB_CYBER2000_I2C | ||
1257 | static void cyber2000fb_i2c_setsda(void *data, int state) | ||
1258 | { | ||
1259 | struct cfb_info *cfb = data; | ||
1260 | unsigned int latch2; | ||
1261 | |||
1262 | spin_lock(&cfb->reg_b0_lock); | ||
1263 | latch2 = cyber2000_grphr(EXT_LATCH2, cfb); | ||
1264 | latch2 &= EXT_LATCH2_I2C_CLKEN; | ||
1265 | if (state) | ||
1266 | latch2 |= EXT_LATCH2_I2C_DATEN; | ||
1267 | cyber2000_grphw(EXT_LATCH2, latch2, cfb); | ||
1268 | spin_unlock(&cfb->reg_b0_lock); | ||
1269 | } | ||
1270 | |||
1271 | static void cyber2000fb_i2c_setscl(void *data, int state) | ||
1272 | { | ||
1273 | struct cfb_info *cfb = data; | ||
1274 | unsigned int latch2; | ||
1275 | |||
1276 | spin_lock(&cfb->reg_b0_lock); | ||
1277 | latch2 = cyber2000_grphr(EXT_LATCH2, cfb); | ||
1278 | latch2 &= EXT_LATCH2_I2C_DATEN; | ||
1279 | if (state) | ||
1280 | latch2 |= EXT_LATCH2_I2C_CLKEN; | ||
1281 | cyber2000_grphw(EXT_LATCH2, latch2, cfb); | ||
1282 | spin_unlock(&cfb->reg_b0_lock); | ||
1283 | } | ||
1284 | |||
1285 | static int cyber2000fb_i2c_getsda(void *data) | ||
1286 | { | ||
1287 | struct cfb_info *cfb = data; | ||
1288 | int ret; | ||
1289 | |||
1290 | spin_lock(&cfb->reg_b0_lock); | ||
1291 | ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_DAT); | ||
1292 | spin_unlock(&cfb->reg_b0_lock); | ||
1293 | |||
1294 | return ret; | ||
1295 | } | ||
1296 | |||
1297 | static int cyber2000fb_i2c_getscl(void *data) | ||
1298 | { | ||
1299 | struct cfb_info *cfb = data; | ||
1300 | int ret; | ||
1301 | |||
1302 | spin_lock(&cfb->reg_b0_lock); | ||
1303 | ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_CLK); | ||
1304 | spin_unlock(&cfb->reg_b0_lock); | ||
1305 | |||
1306 | return ret; | ||
1307 | } | ||
1308 | |||
1309 | static int __devinit cyber2000fb_i2c_register(struct cfb_info *cfb) | ||
1310 | { | ||
1311 | strlcpy(cfb->i2c_adapter.name, cfb->fb.fix.id, | ||
1312 | sizeof(cfb->i2c_adapter.name)); | ||
1313 | cfb->i2c_adapter.owner = THIS_MODULE; | ||
1314 | cfb->i2c_adapter.algo_data = &cfb->i2c_algo; | ||
1315 | cfb->i2c_adapter.dev.parent = cfb->fb.device; | ||
1316 | cfb->i2c_algo.setsda = cyber2000fb_i2c_setsda; | ||
1317 | cfb->i2c_algo.setscl = cyber2000fb_i2c_setscl; | ||
1318 | cfb->i2c_algo.getsda = cyber2000fb_i2c_getsda; | ||
1319 | cfb->i2c_algo.getscl = cyber2000fb_i2c_getscl; | ||
1320 | cfb->i2c_algo.udelay = 5; | ||
1321 | cfb->i2c_algo.timeout = msecs_to_jiffies(100); | ||
1322 | cfb->i2c_algo.data = cfb; | ||
1323 | |||
1324 | return i2c_bit_add_bus(&cfb->i2c_adapter); | ||
1325 | } | ||
1326 | |||
1327 | static void cyber2000fb_i2c_unregister(struct cfb_info *cfb) | ||
1328 | { | ||
1329 | i2c_del_adapter(&cfb->i2c_adapter); | ||
1330 | } | ||
1331 | #else | ||
1332 | #define cyber2000fb_i2c_register(cfb) (0) | ||
1333 | #define cyber2000fb_i2c_unregister(cfb) do { } while (0) | ||
1334 | #endif | ||
1335 | |||
1144 | /* | 1336 | /* |
1145 | * These parameters give | 1337 | * These parameters give |
1146 | * 640x480, hsync 31.5kHz, vsync 60Hz | 1338 | * 640x480, hsync 31.5kHz, vsync 60Hz |
@@ -1275,6 +1467,8 @@ static struct cfb_info __devinit *cyberpro_alloc_fb_info(unsigned int id, | |||
1275 | cfb->fb.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; | 1467 | cfb->fb.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; |
1276 | cfb->fb.pseudo_palette = cfb->pseudo_palette; | 1468 | cfb->fb.pseudo_palette = cfb->pseudo_palette; |
1277 | 1469 | ||
1470 | spin_lock_init(&cfb->reg_b0_lock); | ||
1471 | |||
1278 | fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0); | 1472 | fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0); |
1279 | 1473 | ||
1280 | return cfb; | 1474 | return cfb; |
@@ -1369,6 +1563,11 @@ static int __devinit cyberpro_common_probe(struct cfb_info *cfb) | |||
1369 | cfb->fb.fix.mmio_len = MMIO_SIZE; | 1563 | cfb->fb.fix.mmio_len = MMIO_SIZE; |
1370 | cfb->fb.screen_base = cfb->region; | 1564 | cfb->fb.screen_base = cfb->region; |
1371 | 1565 | ||
1566 | #ifdef CONFIG_FB_CYBER2000_DDC | ||
1567 | if (cyber2000fb_setup_ddc_bus(cfb) == 0) | ||
1568 | cfb->ddc_registered = true; | ||
1569 | #endif | ||
1570 | |||
1372 | err = -EINVAL; | 1571 | err = -EINVAL; |
1373 | if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0, | 1572 | if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0, |
1374 | &cyber2000fb_default_mode, 8)) { | 1573 | &cyber2000fb_default_mode, 8)) { |
@@ -1401,14 +1600,32 @@ static int __devinit cyberpro_common_probe(struct cfb_info *cfb) | |||
1401 | cfb->fb.var.xres, cfb->fb.var.yres, | 1600 | cfb->fb.var.xres, cfb->fb.var.yres, |
1402 | h_sync / 1000, h_sync % 1000, v_sync); | 1601 | h_sync / 1000, h_sync % 1000, v_sync); |
1403 | 1602 | ||
1404 | if (cfb->dev) | 1603 | err = cyber2000fb_i2c_register(cfb); |
1405 | cfb->fb.device = &cfb->dev->dev; | 1604 | if (err) |
1605 | goto failed; | ||
1606 | |||
1406 | err = register_framebuffer(&cfb->fb); | 1607 | err = register_framebuffer(&cfb->fb); |
1608 | if (err) | ||
1609 | cyber2000fb_i2c_unregister(cfb); | ||
1407 | 1610 | ||
1408 | failed: | 1611 | failed: |
1612 | #ifdef CONFIG_FB_CYBER2000_DDC | ||
1613 | if (err && cfb->ddc_registered) | ||
1614 | i2c_del_adapter(&cfb->ddc_adapter); | ||
1615 | #endif | ||
1409 | return err; | 1616 | return err; |
1410 | } | 1617 | } |
1411 | 1618 | ||
1619 | static void __devexit cyberpro_common_remove(struct cfb_info *cfb) | ||
1620 | { | ||
1621 | unregister_framebuffer(&cfb->fb); | ||
1622 | #ifdef CONFIG_FB_CYBER2000_DDC | ||
1623 | if (cfb->ddc_registered) | ||
1624 | i2c_del_adapter(&cfb->ddc_adapter); | ||
1625 | #endif | ||
1626 | cyber2000fb_i2c_unregister(cfb); | ||
1627 | } | ||
1628 | |||
1412 | static void cyberpro_common_resume(struct cfb_info *cfb) | 1629 | static void cyberpro_common_resume(struct cfb_info *cfb) |
1413 | { | 1630 | { |
1414 | cyberpro_init_hw(cfb); | 1631 | cyberpro_init_hw(cfb); |
@@ -1442,12 +1659,13 @@ static int __devinit cyberpro_vl_probe(void) | |||
1442 | if (!cfb) | 1659 | if (!cfb) |
1443 | goto failed_release; | 1660 | goto failed_release; |
1444 | 1661 | ||
1445 | cfb->dev = NULL; | 1662 | cfb->irq = -1; |
1446 | cfb->region = ioremap(FB_START, FB_SIZE); | 1663 | cfb->region = ioremap(FB_START, FB_SIZE); |
1447 | if (!cfb->region) | 1664 | if (!cfb->region) |
1448 | goto failed_ioremap; | 1665 | goto failed_ioremap; |
1449 | 1666 | ||
1450 | cfb->regs = cfb->region + MMIO_OFFSET; | 1667 | cfb->regs = cfb->region + MMIO_OFFSET; |
1668 | cfb->fb.device = NULL; | ||
1451 | cfb->fb.fix.mmio_start = FB_START + MMIO_OFFSET; | 1669 | cfb->fb.fix.mmio_start = FB_START + MMIO_OFFSET; |
1452 | cfb->fb.fix.smem_start = FB_START; | 1670 | cfb->fb.fix.smem_start = FB_START; |
1453 | 1671 | ||
@@ -1585,12 +1803,13 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1585 | if (err) | 1803 | if (err) |
1586 | goto failed_regions; | 1804 | goto failed_regions; |
1587 | 1805 | ||
1588 | cfb->dev = dev; | 1806 | cfb->irq = dev->irq; |
1589 | cfb->region = pci_ioremap_bar(dev, 0); | 1807 | cfb->region = pci_ioremap_bar(dev, 0); |
1590 | if (!cfb->region) | 1808 | if (!cfb->region) |
1591 | goto failed_ioremap; | 1809 | goto failed_ioremap; |
1592 | 1810 | ||
1593 | cfb->regs = cfb->region + MMIO_OFFSET; | 1811 | cfb->regs = cfb->region + MMIO_OFFSET; |
1812 | cfb->fb.device = &dev->dev; | ||
1594 | cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET; | 1813 | cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET; |
1595 | cfb->fb.fix.smem_start = pci_resource_start(dev, 0); | 1814 | cfb->fb.fix.smem_start = pci_resource_start(dev, 0); |
1596 | 1815 | ||
@@ -1648,15 +1867,7 @@ static void __devexit cyberpro_pci_remove(struct pci_dev *dev) | |||
1648 | struct cfb_info *cfb = pci_get_drvdata(dev); | 1867 | struct cfb_info *cfb = pci_get_drvdata(dev); |
1649 | 1868 | ||
1650 | if (cfb) { | 1869 | if (cfb) { |
1651 | /* | 1870 | cyberpro_common_remove(cfb); |
1652 | * If unregister_framebuffer fails, then | ||
1653 | * we will be leaving hooks that could cause | ||
1654 | * oopsen laying around. | ||
1655 | */ | ||
1656 | if (unregister_framebuffer(&cfb->fb)) | ||
1657 | printk(KERN_WARNING "%s: danger Will Robinson, " | ||
1658 | "danger danger! Oopsen imminent!\n", | ||
1659 | cfb->fb.fix.id); | ||
1660 | iounmap(cfb->region); | 1871 | iounmap(cfb->region); |
1661 | cyberpro_free_fb_info(cfb); | 1872 | cyberpro_free_fb_info(cfb); |
1662 | 1873 | ||