aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/Kconfig9
-rw-r--r--drivers/video/cyber2000fb.c127
2 files changed, 136 insertions, 0 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6bafb51bb437..e0c7edf6c82b 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -439,6 +439,15 @@ config FB_CYBER2000
439 Say Y if you have a NetWinder or a graphics card containing this 439 Say Y if you have a NetWinder or a graphics card containing this
440 device, otherwise say N. 440 device, otherwise say N.
441 441
442config FB_CYBER2000_DDC
443 bool "DDC for CyberPro support"
444 depends on FB_CYBER2000
445 select FB_DDC
446 default y
447 help
448 Say Y here if you want DDC support for your CyberPro graphics
449 card. This is only I2C bus support, driver does not use EDID.
450
442config FB_APOLLO 451config FB_APOLLO
443 bool 452 bool
444 depends on (FB = y) && APOLLO 453 depends on (FB = y) && APOLLO
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index e946741ba2ed..87d2aafa92fe 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -48,6 +48,9 @@
48#include <linux/init.h> 48#include <linux/init.h>
49#include <linux/io.h> 49#include <linux/io.h>
50 50
51#include <linux/i2c.h>
52#include <linux/i2c-algo-bit.h>
53
51#include <asm/pgtable.h> 54#include <asm/pgtable.h>
52#include <asm/system.h> 55#include <asm/system.h>
53 56
@@ -88,6 +91,12 @@ struct cfb_info {
88 u_char ramdac_powerdown; 91 u_char ramdac_powerdown;
89 92
90 u32 pseudo_palette[16]; 93 u32 pseudo_palette[16];
94#ifdef CONFIG_FB_CYBER2000_DDC
95 bool ddc_registered;
96 struct i2c_adapter ddc_adapter;
97 struct i2c_algo_bit_data ddc_algo;
98 spinlock_t reg_b0_lock;
99#endif
91}; 100};
92 101
93static char *default_font = "Acorn8x8"; 102static char *default_font = "Acorn8x8";
@@ -494,6 +503,9 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
494 cyber2000_attrw(0x14, 0x00, cfb); 503 cyber2000_attrw(0x14, 0x00, cfb);
495 504
496 /* PLL registers */ 505 /* PLL registers */
506#ifdef CONFIG_FB_CYBER2000_DDC
507 spin_lock(&cfb->reg_b0_lock);
508#endif
497 cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb); 509 cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
498 cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb); 510 cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
499 cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb); 511 cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
@@ -501,6 +513,9 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
501 cyber2000_grphw(0x90, 0x01, cfb); 513 cyber2000_grphw(0x90, 0x01, cfb);
502 cyber2000_grphw(0xb9, 0x80, cfb); 514 cyber2000_grphw(0xb9, 0x80, cfb);
503 cyber2000_grphw(0xb9, 0x00, cfb); 515 cyber2000_grphw(0xb9, 0x00, cfb);
516#ifdef CONFIG_FB_CYBER2000_DDC
517 spin_unlock(&cfb->reg_b0_lock);
518#endif
504 519
505 cfb->ramdac_ctrl = hw->ramdac; 520 cfb->ramdac_ctrl = hw->ramdac;
506 cyber2000fb_write_ramdac_ctrl(cfb); 521 cyber2000fb_write_ramdac_ctrl(cfb);
@@ -1141,6 +1156,105 @@ 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 spin_lock_init(&cfb->reg_b0_lock);
1237
1238 strlcpy(cfb->ddc_adapter.name, cfb->fb.fix.id,
1239 sizeof(cfb->ddc_adapter.name));
1240 cfb->ddc_adapter.owner = THIS_MODULE;
1241 cfb->ddc_adapter.class = I2C_CLASS_DDC;
1242 cfb->ddc_adapter.algo_data = &cfb->ddc_algo;
1243 cfb->ddc_adapter.dev.parent = &cfb->dev->dev;
1244 cfb->ddc_algo.setsda = cyber2000fb_ddc_setsda;
1245 cfb->ddc_algo.setscl = cyber2000fb_ddc_setscl;
1246 cfb->ddc_algo.getsda = cyber2000fb_ddc_getsda;
1247 cfb->ddc_algo.getscl = cyber2000fb_ddc_getscl;
1248 cfb->ddc_algo.udelay = 10;
1249 cfb->ddc_algo.timeout = 20;
1250 cfb->ddc_algo.data = cfb;
1251
1252 i2c_set_adapdata(&cfb->ddc_adapter, cfb);
1253
1254 return i2c_bit_add_bus(&cfb->ddc_adapter);
1255}
1256#endif /* CONFIG_FB_CYBER2000_DDC */
1257
1144/* 1258/*
1145 * These parameters give 1259 * These parameters give
1146 * 640x480, hsync 31.5kHz, vsync 60Hz 1260 * 640x480, hsync 31.5kHz, vsync 60Hz
@@ -1369,6 +1483,11 @@ static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
1369 cfb->fb.fix.mmio_len = MMIO_SIZE; 1483 cfb->fb.fix.mmio_len = MMIO_SIZE;
1370 cfb->fb.screen_base = cfb->region; 1484 cfb->fb.screen_base = cfb->region;
1371 1485
1486#ifdef CONFIG_FB_CYBER2000_DDC
1487 if (cyber2000fb_setup_ddc_bus(cfb) == 0)
1488 cfb->ddc_registered = true;
1489#endif
1490
1372 err = -EINVAL; 1491 err = -EINVAL;
1373 if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0, 1492 if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
1374 &cyber2000fb_default_mode, 8)) { 1493 &cyber2000fb_default_mode, 8)) {
@@ -1406,6 +1525,10 @@ static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
1406 err = register_framebuffer(&cfb->fb); 1525 err = register_framebuffer(&cfb->fb);
1407 1526
1408failed: 1527failed:
1528#ifdef CONFIG_FB_CYBER2000_DDC
1529 if (err && cfb->ddc_registered)
1530 i2c_del_adapter(&cfb->ddc_adapter);
1531#endif
1409 return err; 1532 return err;
1410} 1533}
1411 1534
@@ -1657,6 +1780,10 @@ static void __devexit cyberpro_pci_remove(struct pci_dev *dev)
1657 printk(KERN_WARNING "%s: danger Will Robinson, " 1780 printk(KERN_WARNING "%s: danger Will Robinson, "
1658 "danger danger! Oopsen imminent!\n", 1781 "danger danger! Oopsen imminent!\n",
1659 cfb->fb.fix.id); 1782 cfb->fb.fix.id);
1783#ifdef CONFIG_FB_CYBER2000_DDC
1784 if (cfb->ddc_registered)
1785 i2c_del_adapter(&cfb->ddc_adapter);
1786#endif
1660 iounmap(cfb->region); 1787 iounmap(cfb->region);
1661 cyberpro_free_fb_info(cfb); 1788 cyberpro_free_fb_info(cfb);
1662 1789