drivers/media/i2c/imx296.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/i2c/imx296.c
Extension
.c
Size
34017 bytes
Lines
1161
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

struct imx296_clk_params {
	unsigned int freq;
	u8 incksel[4];
	u8 ctrl418c;
};

static const struct imx296_clk_params imx296_clk_params[] = {
	{ 37125000, { 0x80, 0x0b, 0x80, 0x08 }, 116 },
	{ 54000000, { 0xb0, 0x0f, 0xb0, 0x0c }, 168 },
	{ 74250000, { 0x80, 0x0f, 0x80, 0x0c }, 232 },
};

static const char * const imx296_supply_names[] = {
	"dvdd",
	"ovdd",
	"avdd",
};

struct imx296 {
	struct device *dev;
	struct clk *clk;
	struct regulator_bulk_data supplies[ARRAY_SIZE(imx296_supply_names)];
	struct gpio_desc *reset;
	struct regmap *regmap;

	const struct imx296_clk_params *clk_params;
	bool mono;

	struct v4l2_subdev subdev;
	struct media_pad pad;

	struct v4l2_ctrl_handler ctrls;
	struct v4l2_ctrl *hblank;
	struct v4l2_ctrl *vblank;
};

static inline struct imx296 *to_imx296(struct v4l2_subdev *sd)
{
	return container_of(sd, struct imx296, subdev);
}

static int imx296_read(struct imx296 *sensor, u32 addr)
{
	u8 data[3] = { 0, 0, 0 };
	int ret;

	ret = regmap_raw_read(sensor->regmap, addr & IMX296_REG_ADDR_MASK, data,
			      (addr >> IMX296_REG_SIZE_SHIFT) & 3);
	if (ret < 0)
		return ret;

	return (data[2] << 16) | (data[1] << 8) | data[0];
}

static int imx296_write(struct imx296 *sensor, u32 addr, u32 value, int *err)
{
	u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 };
	int ret;

	if (err && *err)
		return *err;

	ret = regmap_raw_write(sensor->regmap, addr & IMX296_REG_ADDR_MASK,
			       data, (addr >> IMX296_REG_SIZE_SHIFT) & 3);
	if (ret < 0) {
		dev_err(sensor->dev, "%u-bit write to 0x%04x failed: %d\n",
			((addr >> IMX296_REG_SIZE_SHIFT) & 3) * 8,
			addr & IMX296_REG_ADDR_MASK, ret);
		if (err)
			*err = ret;
	}

	return ret;
}

static int imx296_power_on(struct imx296 *sensor)
{
	int ret;

	ret = regulator_bulk_enable(ARRAY_SIZE(sensor->supplies),
				    sensor->supplies);
	if (ret < 0)
		return ret;

	udelay(1);

	ret = gpiod_direction_output(sensor->reset, 0);
	if (ret < 0)
		goto err_supply;

Annotation

Implementation Notes