drivers/media/i2c/ml86v7667.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/i2c/ml86v7667.c
Extension
.c
Size
11978 bytes
Lines
446
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 ml86v7667_priv {
	struct v4l2_subdev		sd;
	struct v4l2_ctrl_handler	hdl;
	v4l2_std_id			std;
};

static inline struct ml86v7667_priv *to_ml86v7667(struct v4l2_subdev *subdev)
{
	return container_of(subdev, struct ml86v7667_priv, sd);
}

static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
{
	return &container_of(ctrl->handler, struct ml86v7667_priv, hdl)->sd;
}

static int ml86v7667_mask_set(struct i2c_client *client, const u8 reg,
			      const u8 mask, const u8 data)
{
	int val = i2c_smbus_read_byte_data(client, reg);
	if (val < 0)
		return val;

	val = (val & ~mask) | (data & mask);
	return i2c_smbus_write_byte_data(client, reg, val);
}

static int ml86v7667_s_ctrl(struct v4l2_ctrl *ctrl)
{
	struct v4l2_subdev *sd = to_sd(ctrl);
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	int ret = -EINVAL;

	switch (ctrl->id) {
	case V4L2_CID_BRIGHTNESS:
		ret = ml86v7667_mask_set(client, SSEPL_REG,
					 SSEPL_LUMINANCE_MASK, ctrl->val);
		break;
	case V4L2_CID_CONTRAST:
		ret = ml86v7667_mask_set(client, CLC_REG,
					 CLC_CONTRAST_MASK, ctrl->val);
		break;
	case V4L2_CID_CHROMA_GAIN:
		ret = ml86v7667_mask_set(client, ACCRC_REG, ACCRC_CHROMA_MASK,
					 ctrl->val << ACCRC_CHROMA_SHIFT);
		break;
	case V4L2_CID_HUE:
		ret = ml86v7667_mask_set(client, HUE_REG, ~0, ctrl->val);
		break;
	case V4L2_CID_RED_BALANCE:
		ret = ml86v7667_mask_set(client, ACCC_REG,
					 ACCC_CHROMA_CR_MASK,
					 ctrl->val << ACCC_CHROMA_CR_SHIFT);
		break;
	case V4L2_CID_BLUE_BALANCE:
		ret = ml86v7667_mask_set(client, ACCC_REG,
					 ACCC_CHROMA_CB_MASK,
					 ctrl->val << ACCC_CHROMA_CB_SHIFT);
		break;
	case V4L2_CID_SHARPNESS:
		ret = ml86v7667_mask_set(client, LUMC_REG,
					 LUMC_ONOFF_MASK,
					 ctrl->val << LUMC_ONOFF_SHIFT);
		break;
	case V4L2_CID_COLOR_KILLER:
		ret = ml86v7667_mask_set(client, CHRCA_REG,
					 CHRCA_MODE_MASK,
					 ctrl->val << CHRCA_MODE_SHIFT);
		break;
	}

	return ret;
}

static int ml86v7667_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	int status;

	status = i2c_smbus_read_byte_data(client, STATUS_REG);
	if (status < 0)
		return status;

	if (status & STATUS_HLOCK_DETECT)
		*std &= status & STATUS_NTSCPAL ? V4L2_STD_625_50 : V4L2_STD_525_60;
	else
		*std = V4L2_STD_UNKNOWN;

	return 0;
}

Annotation

Implementation Notes