drivers/media/i2c/s5c73m3/s5c73m3-core.c

Source file repositories/reference/linux-study-clean/drivers/media/i2c/s5c73m3/s5c73m3-core.c

File Facts

System
Linux kernel
Corpus path
drivers/media/i2c/s5c73m3/s5c73m3-core.c
Extension
.c
Size
42647 bytes
Lines
1759
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 (ret < 0) {
			state->i2c_write_address = 0;
			return ret;
		}
	}

	if ((addr ^ state->i2c_write_address) & 0xffff) {
		ret = s5c73m3_i2c_write(client, REG_CMDWR_ADDRL, addr & 0xffff);
		if (ret < 0) {
			state->i2c_write_address = 0;
			return ret;
		}
	}

	state->i2c_write_address = addr;

	ret = s5c73m3_i2c_write(client, REG_CMDBUF_ADDR, data);
	if (ret < 0)
		return ret;

	state->i2c_write_address += 2;

	return ret;
}

int s5c73m3_read(struct s5c73m3 *state, u32 addr, u16 *data)
{
	struct i2c_client *client = state->i2c_client;
	int ret;

	if ((addr ^ state->i2c_read_address) & 0xffff0000) {
		ret = s5c73m3_i2c_write(client, REG_CMDRD_ADDRH, addr >> 16);
		if (ret < 0) {
			state->i2c_read_address = 0;
			return ret;
		}
	}

	if ((addr ^ state->i2c_read_address) & 0xffff) {
		ret = s5c73m3_i2c_write(client, REG_CMDRD_ADDRL, addr & 0xffff);
		if (ret < 0) {
			state->i2c_read_address = 0;
			return ret;
		}
	}

	state->i2c_read_address = addr;

	ret = s5c73m3_i2c_read(client, REG_CMDBUF_ADDR, data);
	if (ret < 0)
		return ret;

	state->i2c_read_address += 2;

	return ret;
}

static int s5c73m3_check_status(struct s5c73m3 *state, unsigned int value)
{
	unsigned long start = jiffies;
	unsigned long end = start + msecs_to_jiffies(2000);
	int ret;
	u16 status;
	int count = 0;

	do {
		ret = s5c73m3_read(state, REG_STATUS, &status);
		if (ret < 0 || status == value)
			break;
		usleep_range(500, 1000);
		++count;
	} while (time_is_after_jiffies(end));

	if (count > 0)
		v4l2_dbg(1, s5c73m3_dbg, &state->sensor_sd,
			 "status check took %dms\n",
			 jiffies_to_msecs(jiffies - start));

	if (ret == 0 && status != value) {
		u16 i2c_status = 0;
		u16 i2c_seq_status = 0;

		s5c73m3_read(state, REG_I2C_STATUS, &i2c_status);
		s5c73m3_read(state, REG_I2C_SEQ_STATUS, &i2c_seq_status);

		v4l2_err(&state->sensor_sd,
			 "wrong status %#x, expected: %#x, i2c_status: %#x/%#x\n",
			 status, value, i2c_status, i2c_seq_status);

		return -ETIMEDOUT;

Annotation

Implementation Notes