drivers/media/i2c/wm8775.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/i2c/wm8775.c
Extension
.c
Size
8118 bytes
Lines
307
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 wm8775_state {
	struct v4l2_subdev sd;
	struct v4l2_ctrl_handler hdl;
	struct v4l2_ctrl *mute;
	struct v4l2_ctrl *vol;
	struct v4l2_ctrl *bal;
	struct v4l2_ctrl *loud;
	u8 input;		/* Last selected input (0-0xf) */
};

static inline struct wm8775_state *to_state(struct v4l2_subdev *sd)
{
	return container_of(sd, struct wm8775_state, sd);
}

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

static int wm8775_write(struct v4l2_subdev *sd, int reg, u16 val)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	int i;

	if (reg < 0 || reg >= TOT_REGS) {
		v4l2_err(sd, "Invalid register R%d\n", reg);
		return -1;
	}

	for (i = 0; i < 3; i++)
		if (i2c_smbus_write_byte_data(client,
				(reg << 1) | (val >> 8), val & 0xff) == 0)
			return 0;
	v4l2_err(sd, "I2C: cannot write %03x to register R%d\n", val, reg);
	return -1;
}

static void wm8775_set_audio(struct v4l2_subdev *sd, int quietly)
{
	struct wm8775_state *state = to_state(sd);
	u8 vol_l, vol_r;
	int muted = 0 != state->mute->val;
	u16 volume = (u16)state->vol->val;
	u16 balance = (u16)state->bal->val;

	/* normalize ( 65535 to 0 -> 255 to 0 (+24dB to -103dB) ) */
	vol_l = (min(65536 - balance, 32768) * volume) >> 23;
	vol_r = (min(balance, (u16)32768) * volume) >> 23;

	/* Mute */
	if (muted || quietly)
		wm8775_write(sd, R21, 0x0c0 | state->input);

	wm8775_write(sd, R14, vol_l | 0x100); /* 0x100= Left channel ADC zero cross enable */
	wm8775_write(sd, R15, vol_r | 0x100); /* 0x100= Right channel ADC zero cross enable */

	/* Un-mute */
	if (!muted)
		wm8775_write(sd, R21, state->input);
}

static int wm8775_s_routing(struct v4l2_subdev *sd,
			    u32 input, u32 output, u32 config)
{
	struct wm8775_state *state = to_state(sd);

	/* There are 4 inputs and one output. Zero or more inputs
	   are multiplexed together to the output. Hence there are
	   16 combinations.
	   If only one input is active (the normal case) then the
	   input values 1, 2, 4 or 8 should be used. */
	if (input > 15) {
		v4l2_err(sd, "Invalid input %d.\n", input);
		return -EINVAL;
	}
	state->input = input;
	if (v4l2_ctrl_g_ctrl(state->mute))
		return 0;
	if (!v4l2_ctrl_g_ctrl(state->vol))
		return 0;
	wm8775_set_audio(sd, 1);
	return 0;
}

static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl)
{
	struct v4l2_subdev *sd = to_sd(ctrl);

	switch (ctrl->id) {

Annotation

Implementation Notes