drivers/media/common/b2c2/flexcop-i2c.c

Source file repositories/reference/linux-study-clean/drivers/media/common/b2c2/flexcop-i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/media/common/b2c2/flexcop-i2c.c
Extension
.c
Size
7901 bytes
Lines
281
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (!r.tw_sm_c_100.no_base_addr_ack_error) {
			if (r.tw_sm_c_100.st_done) {
				*r100 = r;
				deb_i2c("i2c success\n");
				return 0;
			}
		} else {
			deb_i2c("suffering from an i2c ack_error\n");
			return -EREMOTEIO;
		}
	}
	deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",
		i);
	return -EREMOTEIO;
}

static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c,
		flexcop_ibi_value r100, u8 *buf)
{
	flexcop_ibi_value r104;
	int len = r100.tw_sm_c_100.total_bytes,
		/* remember total_bytes is buflen-1 */
		ret;

	/* work-around to have CableStar2 and SkyStar2 rev 2.7 work
	 * correctly:
	 *
	 * the ITD1000 is behind an i2c-gate which closes automatically
	 * after an i2c-transaction the STV0297 needs 2 consecutive reads
	 * one with no_base_addr = 0 and one with 1
	 *
	 * those two work-arounds are conflictin: we check for the card
	 * type, it is set when probing the ITD1000 */
	if (i2c->fc->dev_type == FC_SKY_REV27)
		r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;

	ret = flexcop_i2c_operation(i2c->fc, &r100);
	if (ret != 0) {
		deb_i2c("Retrying operation\n");
		r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;
		ret = flexcop_i2c_operation(i2c->fc, &r100);
	}
	if (ret != 0) {
		deb_i2c("read failed. %d\n", ret);
		return ret;
	}

	buf[0] = r100.tw_sm_c_100.data1_reg;

	if (len > 0) {
		r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104);
		deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw);

		/* there is at least one more byte, otherwise we wouldn't be here */
		buf[1] = r104.tw_sm_c_104.data2_reg;
		if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg;
		if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg;
	}
	return 0;
}

static int flexcop_i2c_write4(struct flexcop_device *fc,
		flexcop_ibi_value r100, u8 *buf)
{
	flexcop_ibi_value r104;
	int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */
	r104.raw = 0;

	/* there is at least one byte, otherwise we wouldn't be here */
	r100.tw_sm_c_100.data1_reg = buf[0];
	r104.tw_sm_c_104.data2_reg = len > 0 ? buf[1] : 0;
	r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0;
	r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;

	deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw);

	/* write the additional i2c data before doing the actual i2c operation */
	fc->write_ibi_reg(fc, tw_sm_c_104, r104);
	return flexcop_i2c_operation(fc, &r100);
}

int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
			flexcop_access_op_t op, u8 chipaddr,
			u8 start_addr, u8 *buf, u16 size)
{
	int ret;
	int len = size;
	u8 *p;
	u8 addr = start_addr;

Annotation

Implementation Notes