Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d832c5b2 authored by Frank Schaefer's avatar Frank Schaefer Committed by Mauro Carvalho Chehab
Browse files

[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: default avatarFrank Schäfer <fschaefer.oss@googlemail.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 87b52439
Loading
Loading
Loading
Loading
+46 −28
Original line number Diff line number Diff line
@@ -370,51 +370,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 > (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)
{
	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)) {