drivers/media/i2c/saa717x.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/i2c/saa717x.c
Extension
.c
Size
32418 bytes
Lines
1352
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 saa717x_state {
	struct v4l2_subdev sd;
	struct v4l2_ctrl_handler hdl;
	v4l2_std_id std;
	int input;
	int enable;
	int radio;
	int playback;
	int audio;
	int tuner_audio_mode;
	int audio_main_mute;
	int audio_main_vol_r;
	int audio_main_vol_l;
	u16 audio_main_bass;
	u16 audio_main_treble;
	u16 audio_main_volume;
	u16 audio_main_balance;
	int audio_input;
};

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

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

/* ----------------------------------------------------------------------- */

/* for audio mode */
#define TUNER_AUDIO_MONO	0  /* LL */
#define TUNER_AUDIO_STEREO	1  /* LR */
#define TUNER_AUDIO_LANG1	2  /* LL */
#define TUNER_AUDIO_LANG2	3  /* RR */

#define SAA717X_NTSC_WIDTH	(704)
#define SAA717X_NTSC_HEIGHT	(480)

/* ----------------------------------------------------------------------- */

static int saa717x_write(struct v4l2_subdev *sd, u32 reg, u32 value)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct i2c_adapter *adap = client->adapter;
	int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488;
	unsigned char mm1[6];
	struct i2c_msg msg;

	msg.flags = 0;
	msg.addr = client->addr;
	mm1[0] = (reg >> 8) & 0xff;
	mm1[1] = reg & 0xff;

	if (fw_addr) {
		mm1[4] = (value >> 16) & 0xff;
		mm1[3] = (value >> 8) & 0xff;
		mm1[2] = value & 0xff;
	} else {
		mm1[2] = value & 0xff;
	}
	msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */
	msg.buf = mm1;
	v4l2_dbg(2, debug, sd, "wrote:  reg 0x%03x=%08x\n", reg, value);
	return i2c_transfer(adap, &msg, 1) == 1;
}

static void saa717x_write_regs(struct v4l2_subdev *sd, u32 *data)
{
	while (data[0] || data[1]) {
		saa717x_write(sd, data[0], data[1]);
		data += 2;
	}
}

static u32 saa717x_read(struct v4l2_subdev *sd, u32 reg)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct i2c_adapter *adap = client->adapter;
	int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528;
	unsigned char mm1[2];
	unsigned char mm2[4] = { 0, 0, 0, 0 };
	struct i2c_msg msgs[2];
	u32 value;

	msgs[0].flags = 0;
	msgs[1].flags = I2C_M_RD;
	msgs[0].addr = msgs[1].addr = client->addr;

Annotation

Implementation Notes