aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/cyber2000fb.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-08-02 04:57:07 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-02-11 05:16:05 -0500
commitb7ca01a9b20e3fdd11745227905e9ad8a99e0123 (patch)
tree6d4157e1253e074343044566092bb3de3c950234 /drivers/video/cyber2000fb.c
parent052a7f5c496b7d2966edea0f576ec39f41703992 (diff)
VIDEO: cyberpro: add support for video capture I2C
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/video/cyber2000fb.c')
-rw-r--r--drivers/video/cyber2000fb.c122
1 files changed, 108 insertions, 14 deletions
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index eeccdb8f4848..27cb3b23c3da 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -47,7 +47,6 @@
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
51#include <linux/i2c.h> 50#include <linux/i2c.h>
52#include <linux/i2c-algo-bit.h> 51#include <linux/i2c-algo-bit.h>
53 52
@@ -99,6 +98,11 @@ struct cfb_info {
99 struct i2c_adapter ddc_adapter; 98 struct i2c_adapter ddc_adapter;
100 struct i2c_algo_bit_data ddc_algo; 99 struct i2c_algo_bit_data ddc_algo;
101#endif 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
102}; 106};
103 107
104static char *default_font = "Acorn8x8"; 108static char *default_font = "Acorn8x8";
@@ -1131,6 +1135,11 @@ int cyber2000fb_attach(struct cyberpro_info *info, int idx)
1131{ 1135{
1132 if (int_cfb_info != NULL) { 1136 if (int_cfb_info != NULL) {
1133 info->dev = int_cfb_info->dev; 1137 info->dev = int_cfb_info->dev;
1138#ifdef CONFIG_FB_CYBER2000_I2C
1139 info->i2c = &int_cfb_info->i2c_adapter;
1140#else
1141 info->i2c = NULL;
1142#endif
1134 info->regs = int_cfb_info->regs; 1143 info->regs = int_cfb_info->regs;
1135 info->fb = int_cfb_info->fb.screen_base; 1144 info->fb = int_cfb_info->fb.screen_base;
1136 info->fb_size = int_cfb_info->fb.fix.smem_len; 1145 info->fb_size = int_cfb_info->fb.fix.smem_len;
@@ -1251,6 +1260,86 @@ static int __devinit cyber2000fb_setup_ddc_bus(struct cfb_info *cfb)
1251} 1260}
1252#endif /* CONFIG_FB_CYBER2000_DDC */ 1261#endif /* CONFIG_FB_CYBER2000_DDC */
1253 1262
1263#ifdef CONFIG_FB_CYBER2000_I2C
1264static void cyber2000fb_i2c_setsda(void *data, int state)
1265{
1266 struct cfb_info *cfb = data;
1267 unsigned int latch2;
1268
1269 spin_lock(&cfb->reg_b0_lock);
1270 latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
1271 latch2 &= EXT_LATCH2_I2C_CLKEN;
1272 if (state)
1273 latch2 |= EXT_LATCH2_I2C_DATEN;
1274 cyber2000_grphw(EXT_LATCH2, latch2, cfb);
1275 spin_unlock(&cfb->reg_b0_lock);
1276}
1277
1278static void cyber2000fb_i2c_setscl(void *data, int state)
1279{
1280 struct cfb_info *cfb = data;
1281 unsigned int latch2;
1282
1283 spin_lock(&cfb->reg_b0_lock);
1284 latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
1285 latch2 &= EXT_LATCH2_I2C_DATEN;
1286 if (state)
1287 latch2 |= EXT_LATCH2_I2C_CLKEN;
1288 cyber2000_grphw(EXT_LATCH2, latch2, cfb);
1289 spin_unlock(&cfb->reg_b0_lock);
1290}
1291
1292static int cyber2000fb_i2c_getsda(void *data)
1293{
1294 struct cfb_info *cfb = data;
1295 int ret;
1296
1297 spin_lock(&cfb->reg_b0_lock);
1298 ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_DAT);
1299 spin_unlock(&cfb->reg_b0_lock);
1300
1301 return ret;
1302}
1303
1304static int cyber2000fb_i2c_getscl(void *data)
1305{
1306 struct cfb_info *cfb = data;
1307 int ret;
1308
1309 spin_lock(&cfb->reg_b0_lock);
1310 ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_CLK);
1311 spin_unlock(&cfb->reg_b0_lock);
1312
1313 return ret;
1314}
1315
1316static int __devinit cyber2000fb_i2c_register(struct cfb_info *cfb)
1317{
1318 strlcpy(cfb->i2c_adapter.name, cfb->fb.fix.id,
1319 sizeof(cfb->i2c_adapter.name));
1320 cfb->i2c_adapter.owner = THIS_MODULE;
1321 cfb->i2c_adapter.algo_data = &cfb->i2c_algo;
1322 cfb->i2c_adapter.dev.parent = &cfb->dev->dev;
1323 cfb->i2c_algo.setsda = cyber2000fb_i2c_setsda;
1324 cfb->i2c_algo.setscl = cyber2000fb_i2c_setscl;
1325 cfb->i2c_algo.getsda = cyber2000fb_i2c_getsda;
1326 cfb->i2c_algo.getscl = cyber2000fb_i2c_getscl;
1327 cfb->i2c_algo.udelay = 5;
1328 cfb->i2c_algo.timeout = msecs_to_jiffies(100);
1329 cfb->i2c_algo.data = cfb;
1330
1331 return i2c_bit_add_bus(&cfb->i2c_adapter);
1332}
1333
1334static void cyber2000fb_i2c_unregister(struct cfb_info *cfb)
1335{
1336 i2c_del_adapter(&cfb->i2c_adapter);
1337}
1338#else
1339#define cyber2000fb_i2c_register(cfb) (0)
1340#define cyber2000fb_i2c_unregister(cfb) do { } while (0)
1341#endif
1342
1254/* 1343/*
1255 * These parameters give 1344 * These parameters give
1256 * 640x480, hsync 31.5kHz, vsync 60Hz 1345 * 640x480, hsync 31.5kHz, vsync 60Hz
@@ -1520,7 +1609,14 @@ static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
1520 1609
1521 if (cfb->dev) 1610 if (cfb->dev)
1522 cfb->fb.device = &cfb->dev->dev; 1611 cfb->fb.device = &cfb->dev->dev;
1612
1613 err = cyber2000fb_i2c_register(cfb);
1614 if (err)
1615 goto failed;
1616
1523 err = register_framebuffer(&cfb->fb); 1617 err = register_framebuffer(&cfb->fb);
1618 if (err)
1619 cyber2000fb_i2c_unregister(cfb);
1524 1620
1525failed: 1621failed:
1526#ifdef CONFIG_FB_CYBER2000_DDC 1622#ifdef CONFIG_FB_CYBER2000_DDC
@@ -1530,6 +1626,16 @@ failed:
1530 return err; 1626 return err;
1531} 1627}
1532 1628
1629static void __devexit cyberpro_common_remove(struct cfb_info *cfb)
1630{
1631 unregister_framebuffer(&cfb->fb);
1632#ifdef CONFIG_FB_CYBER2000_DDC
1633 if (cfb->ddc_registered)
1634 i2c_del_adapter(&cfb->ddc_adapter);
1635#endif
1636 cyber2000fb_i2c_unregister(cfb);
1637}
1638
1533static void cyberpro_common_resume(struct cfb_info *cfb) 1639static void cyberpro_common_resume(struct cfb_info *cfb)
1534{ 1640{
1535 cyberpro_init_hw(cfb); 1641 cyberpro_init_hw(cfb);
@@ -1769,19 +1875,7 @@ static void __devexit cyberpro_pci_remove(struct pci_dev *dev)
1769 struct cfb_info *cfb = pci_get_drvdata(dev); 1875 struct cfb_info *cfb = pci_get_drvdata(dev);
1770 1876
1771 if (cfb) { 1877 if (cfb) {
1772 /* 1878 cyberpro_common_remove(cfb);
1773 * If unregister_framebuffer fails, then
1774 * we will be leaving hooks that could cause
1775 * oopsen laying around.
1776 */
1777 if (unregister_framebuffer(&cfb->fb))
1778 printk(KERN_WARNING "%s: danger Will Robinson, "
1779 "danger danger! Oopsen imminent!\n",
1780 cfb->fb.fix.id);
1781#ifdef CONFIG_FB_CYBER2000_DDC
1782 if (cfb->ddc_registered)
1783 i2c_del_adapter(&cfb->ddc_adapter);
1784#endif
1785 iounmap(cfb->region); 1879 iounmap(cfb->region);
1786 cyberpro_free_fb_info(cfb); 1880 cyberpro_free_fb_info(cfb);
1787 1881