From 596d92d5128d308b5a79f21c3e72c87f5fc7e58b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:24 -0800 Subject: [PATCH] v4l: 767: included support for em2800 - Included support for em2800. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-i2c.c | 182 ++++++++++++++++++++++++++++---- 1 file changed, 159 insertions(+), 23 deletions(-) (limited to 'drivers/media/video/em28xx/em28xx-i2c.c') diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 3065ddb4b36..b7360d579a8 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -1,5 +1,5 @@ /* - em2820-i2c.c - driver for Empia EM2820/2840 USB video capture devices + em2820-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger Ludovico Cavedon @@ -29,11 +29,6 @@ #include #include -/* To be moved to compat.h */ -#if !defined(I2C_HW_B_EM2820) -#define I2C_HW_B_EM2820 0x99 -#endif - #include "em2820.h" /* ----------------------------------------------------------- */ @@ -56,11 +51,132 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); printk(fmt , ##args); } while (0) /* - * i2c_send_bytes() + * em2800_i2c_send_max4() + * send up to 4 bytes to the i2c device + */ +static int em2800_i2c_send_max4(struct em2820 *dev, unsigned char addr, + char *buf, int len) +{ + int ret; + int write_timeout; + unsigned char b2[6]; + BUG_ON(len < 1 || len > 4); + b2[5] = 0x80 + len - 1; + b2[4] = addr; + b2[3] = buf[0]; + if (len > 1) + b2[2] = buf[1]; + if (len > 2) + b2[1] = buf[2]; + if (len > 3) + b2[0] = buf[3]; + + ret = dev->em2820_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); + if (ret != 2 + len) { + em2820_warn("writting to i2c device failed (error=%i)\n", ret); + return -EIO; + } + for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; + write_timeout -= 5) { + ret = dev->em2820_read_reg(dev, 0x05); + if (ret == 0x80 + len - 1) + return len; + mdelay(5); + } + em2820_warn("i2c write timed out\n"); + return -EIO; +} + +/* + * em2800_i2c_send_bytes() + */ +static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf, + short len) +{ + char *bufPtr = buf; + int ret; + int wrcount = 0; + int count; + int maxLen = 4; + struct em2820 *dev = (struct em2820 *)data; + while (len > 0) { + count = (len > maxLen) ? maxLen : len; + ret = em2800_i2c_send_max4(dev, addr, bufPtr, count); + if (ret > 0) { + len -= count; + bufPtr += count; + wrcount += count; + } else + return (ret < 0) ? ret : -EFAULT; + } + return wrcount; +} + +/* + * em2800_i2c_check_for_device() + * check if there is a i2c_device at the supplied address + */ +static int em2800_i2c_check_for_device(struct em2820 *dev, unsigned char addr) +{ + char msg; + int ret; + int write_timeout; + msg = addr; + ret = dev->em2820_write_regs(dev, 0x04, &msg, 1); + if (ret < 0) { + em2820_warn("setting i2c device address failed (error=%i)\n", + ret); + return ret; + } + msg = 0x84; + ret = dev->em2820_write_regs(dev, 0x05, &msg, 1); + if (ret < 0) { + em2820_warn("preparing i2c read failed (error=%i)\n", ret); + return ret; + } + for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; + write_timeout -= 5) { + unsigned msg = dev->em2820_read_reg(dev, 0x5); + if (msg == 0x94) + return -ENODEV; + else if (msg == 0x84) + return 0; + mdelay(5); + } + return -ENODEV; +} + +/* + * em2800_i2c_recv_bytes() + * read from the i2c device + */ +static int em2800_i2c_recv_bytes(struct em2820 *dev, unsigned char addr, + char *buf, int len) +{ + int ret; + /* check for the device and set i2c read address */ + ret = em2800_i2c_check_for_device(dev, addr); + if (ret) { + em2820_warn + ("preparing read at i2c address 0x%x failed (error=%i)\n", + addr, ret); + return ret; + } + ret = dev->em2820_read_reg_req_len(dev, 0x0, 0x3, buf, len); + if (ret < 0) { + em2820_warn("reading from i2c device at 0x%x failed (error=%i)", + addr, ret); + return ret; + } + return ret; +} + +/* + * em2820_i2c_send_bytes() * untested for more than 4 bytes */ -static int i2c_send_bytes(void *data, unsigned char addr, char *buf, short len, - int stop) +static int em2820_i2c_send_bytes(void *data, unsigned char addr, char *buf, + short len, int stop) { int wrcount = 0; struct em2820 *dev = (struct em2820 *)data; @@ -71,11 +187,11 @@ static int i2c_send_bytes(void *data, unsigned char addr, char *buf, short len, } /* - * i2c_recv_byte() + * em2820_i2c_recv_bytes() * read a byte from the i2c device */ -static int i2c_recv_bytes(struct em2820 *dev, unsigned char addr, char *buf, - int len) +static int em2820_i2c_recv_bytes(struct em2820 *dev, unsigned char addr, + char *buf, int len) { int ret; ret = dev->em2820_read_reg_req_len(dev, 2, addr, buf, len); @@ -89,10 +205,10 @@ static int i2c_recv_bytes(struct em2820 *dev, unsigned char addr, char *buf, } /* - * i2c_check_for_device() + * em2820_i2c_check_for_device() * check if there is a i2c_device at the supplied address */ -static int i2c_check_for_device(struct em2820 *dev, unsigned char addr) +static int em2820_i2c_check_for_device(struct em2820 *dev, unsigned char addr) { char msg; int ret; @@ -126,18 +242,25 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, (msgs[i].flags & I2C_M_RD) ? "read" : "write", i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); if (!msgs[i].len) { /* no len: check only for device presence */ - rc = i2c_check_for_device(dev, addr); + if (dev->is_em2800) + rc = em2800_i2c_check_for_device(dev, addr); + else + rc = em2820_i2c_check_for_device(dev, addr); if (rc < 0) { dprintk2(" no device\n"); return rc; } - } - if (msgs[i].flags & I2C_M_RD) { + } else if (msgs[i].flags & I2C_M_RD) { /* read bytes */ - - rc = i2c_recv_bytes(dev, addr, msgs[i].buf, - msgs[i].len); + if (dev->is_em2800) + rc = em2800_i2c_recv_bytes(dev, addr, + msgs[i].buf, + msgs[i].len); + else + rc = em2820_i2c_recv_bytes(dev, addr, + msgs[i].buf, + msgs[i].len); if (i2c_debug) { for (byte = 0; byte < msgs[i].len; byte++) { printk(" %02x", msgs[i].buf[byte]); @@ -149,8 +272,15 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, for (byte = 0; byte < msgs[i].len; byte++) printk(" %02x", msgs[i].buf[byte]); } - rc = i2c_send_bytes(dev, addr, msgs[i].buf, msgs[i].len, - i == num - 1); + if (dev->is_em2800) + rc = em2800_i2c_send_bytes(dev, addr, + msgs[i].buf, + msgs[i].len); + else + rc = em2820_i2c_send_bytes(dev, addr, + msgs[i].buf, + msgs[i].len, + i == num - 1); if (rc < 0) goto err; } @@ -171,6 +301,12 @@ static int em2820_i2c_eeprom(struct em2820 *dev, unsigned char *eedata, int len) int i, err, size = len, block; dev->i2c_client.addr = 0xa0 >> 1; + + /* Check if board has eeprom */ + err = i2c_master_recv(&dev->i2c_client, &buf, 0); + if (err < 0) + return -1; + buf = 0; if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) { printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", @@ -389,7 +525,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) rc = i2c_master_recv(c, &buf, 0); if (rc < 0) continue; - printk(KERN_INFO "%s: found device @ 0x%x [%s]", name, + printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n", name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); } } -- cgit v1.2.3-70-g09d2