drivers/media/usb/au0828/au0828-i2c.c

Source file repositories/reference/linux-study-clean/drivers/media/usb/au0828/au0828-i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/media/usb/au0828/au0828-i2c.c
Extension
.c
Size
9062 bytes
Lines
394
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if ((strobe >= 4) || (i >= msg->len)) {

			/* Strobe the byte into the bus */
			if (i < msg->len)
				au0828_write(dev, AU0828_I2C_TRIGGER_200,
					     AU0828_I2C_TRIGGER_WRITE |
					     AU0828_I2C_TRIGGER_HOLD);
			else
				au0828_write(dev, AU0828_I2C_TRIGGER_200,
					     AU0828_I2C_TRIGGER_WRITE);

			/* Reset strobe trigger */
			strobe = 0;

			if (!i2c_wait_write_done(i2c_adap))
				return -EIO;

		}

	}
	if (!i2c_wait_done(i2c_adap))
		return -EIO;

	dprintk(4, "\n");

	return msg->len;
}

/* FIXME: Implement join handling correctly */
static int i2c_readbytes(struct i2c_adapter *i2c_adap,
	const struct i2c_msg *msg, int joined)
{
	struct au0828_dev *dev = i2c_adap->algo_data;
	u8 i2c_speed = dev->board.i2c_clk_divider;
	int i;

	dprintk(4, "%s()\n", __func__);

	au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);

	/*
	 * Due to xc5000c clock stretch, we cannot use full speed at
	 * readings from xc5000, as otherwise they'll fail.
	 */
	if (((dev->board.tuner_type == TUNER_XC5000) ||
	     (dev->board.tuner_type == TUNER_XC5000C)) &&
	    (dev->board.tuner_addr == msg->addr))
		i2c_speed = AU0828_I2C_CLK_20KHZ;

	/* Set the I2C clock */
	au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed);

	/* Hardware needs 8 bit addresses */
	au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);

	dprintk(4, " RECV:\n");

	/* Deal with i2c_scan */
	if (msg->len == 0) {
		au0828_write(dev, AU0828_I2C_TRIGGER_200,
			     AU0828_I2C_TRIGGER_READ);

		if (i2c_wait_read_ack(i2c_adap))
			return -EIO;
		return 0;
	}

	for (i = 0; i < msg->len;) {

		i++;

		if (i < msg->len)
			au0828_write(dev, AU0828_I2C_TRIGGER_200,
				     AU0828_I2C_TRIGGER_READ |
				     AU0828_I2C_TRIGGER_HOLD);
		else
			au0828_write(dev, AU0828_I2C_TRIGGER_200,
				     AU0828_I2C_TRIGGER_READ);

		if (!i2c_wait_read_done(i2c_adap))
			return -EIO;

		msg->buf[i-1] = au0828_read(dev, AU0828_I2C_READ_FIFO_209) &
			0xff;

		dprintk(4, " %02x\n", msg->buf[i-1]);
	}
	if (!i2c_wait_done(i2c_adap))
		return -EIO;

Annotation

Implementation Notes