drivers/media/i2c/lm3646.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/i2c/lm3646.c
Extension
.c
Size
10731 bytes
Lines
410
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 lm3646_flash {
	struct device *dev;
	struct lm3646_platform_data *pdata;
	struct regmap *regmap;

	struct v4l2_ctrl_handler ctrls_led;
	struct v4l2_subdev subdev_led;

	u8 mode_reg;
};

#define to_lm3646_flash(_ctrl)	\
	container_of(_ctrl->handler, struct lm3646_flash, ctrls_led)

/* enable mode control */
static int lm3646_mode_ctrl(struct lm3646_flash *flash,
			    enum v4l2_flash_led_mode led_mode)
{
	switch (led_mode) {
	case V4L2_FLASH_LED_MODE_NONE:
		return regmap_write(flash->regmap,
				    REG_ENABLE, flash->mode_reg | MODE_SHDN);
	case V4L2_FLASH_LED_MODE_TORCH:
		return regmap_write(flash->regmap,
				    REG_ENABLE, flash->mode_reg | MODE_TORCH);
	case V4L2_FLASH_LED_MODE_FLASH:
		return regmap_write(flash->regmap,
				    REG_ENABLE, flash->mode_reg | MODE_FLASH);
	}
	return -EINVAL;
}

/* V4L2 controls  */
static int lm3646_get_ctrl(struct v4l2_ctrl *ctrl)
{
	struct lm3646_flash *flash = to_lm3646_flash(ctrl);
	unsigned int reg_val;
	int rval;

	if (ctrl->id != V4L2_CID_FLASH_FAULT)
		return -EINVAL;

	rval = regmap_read(flash->regmap, REG_FLAG, &reg_val);
	if (rval < 0)
		return rval;

	ctrl->val = 0;
	if (reg_val & FAULT_TIMEOUT)
		ctrl->val |= V4L2_FLASH_FAULT_TIMEOUT;
	if (reg_val & FAULT_SHORT_CIRCUIT)
		ctrl->val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
	if (reg_val & FAULT_UVLO)
		ctrl->val |= V4L2_FLASH_FAULT_UNDER_VOLTAGE;
	if (reg_val & FAULT_IVFM)
		ctrl->val |= V4L2_FLASH_FAULT_INPUT_VOLTAGE;
	if (reg_val & FAULT_OCP)
		ctrl->val |= V4L2_FLASH_FAULT_OVER_CURRENT;
	if (reg_val & FAULT_OVERTEMP)
		ctrl->val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
	if (reg_val & FAULT_NTC_TRIP)
		ctrl->val |= V4L2_FLASH_FAULT_LED_OVER_TEMPERATURE;
	if (reg_val & FAULT_OVP)
		ctrl->val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;

	return 0;
}

static int lm3646_set_ctrl(struct v4l2_ctrl *ctrl)
{
	struct lm3646_flash *flash = to_lm3646_flash(ctrl);
	unsigned int reg_val;
	int rval;

	switch (ctrl->id) {
	case V4L2_CID_FLASH_LED_MODE:

		if (ctrl->val != V4L2_FLASH_LED_MODE_FLASH)
			return lm3646_mode_ctrl(flash, ctrl->val);
		/* switch to SHDN mode before flash strobe on */
		return lm3646_mode_ctrl(flash, V4L2_FLASH_LED_MODE_NONE);

	case V4L2_CID_FLASH_STROBE_SOURCE:
		return regmap_update_bits(flash->regmap,
					  REG_STROBE_SRC, MASK_STROBE_SRC,
					  (ctrl->val) << 7);

	case V4L2_CID_FLASH_STROBE:

		/* read and check current mode of chip to start flash */
		rval = regmap_read(flash->regmap, REG_ENABLE, &reg_val);

Annotation

Implementation Notes