[media] em28xx: add helper function for reading data blocks from i2c clients

Add a helper function for reading data blocks from i2c devices with 8 or 16 bit
address width and 8 bit register width.
This allows us to reduce the size of new code added by the following patches.
Works only for devices with activated register auto incrementation.

Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Frank Schaefer 2013-03-03 15:37:41 -03:00 committed by Mauro Carvalho Chehab
parent 87b52439cf
commit d832c5b28a

View File

@ -370,51 +370,69 @@ static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
return (hash >> (32 - bits)) & 0xffffffffUL; return (hash >> (32 - bits)) & 0xffffffffUL;
} }
/* Helper function to read data blocks from i2c clients with 8 or 16 bit
* address width, 8 bit register width and auto incrementation been activated */
static int em28xx_i2c_read_block(struct em28xx *dev, u16 addr, bool addr_w16,
u16 len, u8 *data)
{
int remain = len, rsize, rsize_max, ret;
u8 buf[2];
/* Sanity check */
if (addr + remain > (addr_w16 * 0xff00 + 0xff + 1))
return -EINVAL;
/* Select address */
buf[0] = addr >> 8;
buf[1] = addr & 0xff;
ret = i2c_master_send(&dev->i2c_client, buf + !addr_w16, 1 + addr_w16);
if (ret < 0)
return ret;
/* Read data */
if (dev->board.is_em2800)
rsize_max = 4;
else
rsize_max = 64;
while (remain > 0) {
if (remain > rsize_max)
rsize = rsize_max;
else
rsize = remain;
ret = i2c_master_recv(&dev->i2c_client, data, rsize);
if (ret < 0)
return ret;
remain -= rsize;
data += rsize;
}
return len;
}
static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
{ {
unsigned char buf[2], *p = eedata; unsigned char buf, *p = eedata;
struct em28xx_eeprom *em_eeprom = (void *)eedata; struct em28xx_eeprom *em_eeprom = (void *)eedata;
int i, err, size = len, block, block_max; int i, err;
dev->i2c_client.addr = 0xa0 >> 1; dev->i2c_client.addr = 0xa0 >> 1;
/* Check if board has eeprom */ /* Check if board has eeprom */
err = i2c_master_recv(&dev->i2c_client, buf, 0); err = i2c_master_recv(&dev->i2c_client, &buf, 0);
if (err < 0) { if (err < 0) {
em28xx_info("board has no eeprom\n"); em28xx_info("board has no eeprom\n");
memset(eedata, 0, len); memset(eedata, 0, len);
return -ENODEV; return -ENODEV;
} }
/* Select address memory address 0x00(00) */ /* Read EEPROM content */
buf[0] = 0; err = em28xx_i2c_read_block(dev, 0x0000, dev->eeprom_addrwidth_16bit,
buf[1] = 0; len, p);
err = i2c_master_send(&dev->i2c_client, buf, 1 + dev->eeprom_addrwidth_16bit); if (err != len) {
if (err != 1 + dev->eeprom_addrwidth_16bit) {
em28xx_errdev("failed to read eeprom (err=%d)\n", err); em28xx_errdev("failed to read eeprom (err=%d)\n", err);
return err; return err;
} }
/* Read eeprom content */
if (dev->board.is_em2800)
block_max = 4;
else
block_max = 64;
while (size > 0) {
if (size > block_max)
block = block_max;
else
block = size;
if (block !=
(err = i2c_master_recv(&dev->i2c_client, p, block))) {
em28xx_errdev("i2c eeprom read error (err=%d)\n", err);
return err;
}
size -= block;
p += block;
}
/* Display eeprom content */ /* Display eeprom content */
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (0 == (i % 16)) { if (0 == (i % 16)) {