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....@googlemail.com>
---
 drivers/media/usb/em28xx/em28xx-i2c.c |   74 ++++++++++++++++++++-------------
 1 Datei geändert, 46 Zeilen hinzugefügt(+), 28 Zeilen entfernt(-)

diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c 
b/drivers/media/usb/em28xx/em28xx-i2c.c
index 7185812..a3e9547 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -366,51 +366,69 @@ static inline unsigned long em28xx_hash_mem(char *buf, 
int length, int bits)
        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 > (256 + addr_w16*256))
+               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)
 {
-       unsigned char buf[2], *p = eedata;
+       unsigned char buf, *p = 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;
 
        /* 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) {
                em28xx_info("board has no eeprom\n");
                memset(eedata, 0, len);
                return -ENODEV;
        }
 
-       /* Select address memory address 0x00(00) */
-       buf[0] = 0;
-       buf[1] = 0;
-       err = i2c_master_send(&dev->i2c_client, buf, 1 + 
dev->eeprom_addrwidth_16bit);
-       if (err != 1 + dev->eeprom_addrwidth_16bit) {
+       /* Read EEPROM content */
+       err = em28xx_i2c_read_block(dev, 0x0000, dev->eeprom_addrwidth_16bit,
+                                   len, p);
+       if (err != len) {
                em28xx_errdev("failed to read eeprom (err=%d)\n", 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 */
        for (i = 0; i < len; i++) {
                if (0 == (i % 16)) {
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to