aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/cyber2000fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/cyber2000fb.c')
-rw-r--r--drivers/video/cyber2000fb.c263
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
93static char *default_font = "Acorn8x8"; 108static 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}
1106EXPORT_SYMBOL(cyber2000fb_disable_extregs); 1123EXPORT_SYMBOL(cyber2000fb_disable_extregs);
1107 1124
1108void 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}
1112EXPORT_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 */
1117int cyber2000fb_attach(struct cyberpro_info *info, int idx) 1128int 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}
1142EXPORT_SYMBOL(cyber2000fb_detach); 1157EXPORT_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
1167static void cyber2000fb_enable_ddc(struct cfb_info *cfb)
1168{
1169 spin_lock(&cfb->reg_b0_lock);
1170 cyber2000fb_writew(0x1bf, 0x3ce, cfb);
1171}
1172
1173static 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
1180static 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
1195static 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
1210static 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
1222static 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
1234static 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
1257static 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
1271static 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
1285static 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
1297static 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
1309static 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
1327static 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
1408failed: 1611failed:
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
1619static 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
1412static void cyberpro_common_resume(struct cfb_info *cfb) 1629static 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