drivers/media/dvb-frontends/lgdt3306a.c

Source file repositories/reference/linux-study-clean/drivers/media/dvb-frontends/lgdt3306a.c

File Facts

System
Linux kernel
Corpus path
drivers/media/dvb-frontends/lgdt3306a.c
Extension
.c
Size
56546 bytes
Lines
2268
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 lgdt3306a_state {
	struct i2c_adapter *i2c_adap;
	const struct lgdt3306a_config *cfg;

	struct dvb_frontend frontend;

	enum fe_modulation current_modulation;
	u32 current_frequency;
	u32 snr;

	struct i2c_mux_core *muxc;
};

/*
 * LG3306A Register Usage
 *  (LG does not really name the registers, so this code does not either)
 *
 * 0000 -> 00FF Common control and status
 * 1000 -> 10FF Synchronizer control and status
 * 1F00 -> 1FFF Smart Antenna control and status
 * 2100 -> 21FF VSB Equalizer control and status
 * 2800 -> 28FF QAM Equalizer control and status
 * 3000 -> 30FF FEC control and status
 */

enum lgdt3306a_lock_status {
	LG3306_UNLOCK       = 0x00,
	LG3306_LOCK         = 0x01,
	LG3306_UNKNOWN_LOCK = 0xff
};

enum lgdt3306a_neverlock_status {
	LG3306_NL_INIT    = 0x00,
	LG3306_NL_PROCESS = 0x01,
	LG3306_NL_LOCK    = 0x02,
	LG3306_NL_FAIL    = 0x03,
	LG3306_NL_UNKNOWN = 0xff
};

enum lgdt3306a_modulation {
	LG3306_VSB          = 0x00,
	LG3306_QAM64        = 0x01,
	LG3306_QAM256       = 0x02,
	LG3306_UNKNOWN_MODE = 0xff
};

enum lgdt3306a_lock_check {
	LG3306_SYNC_LOCK,
	LG3306_FEC_LOCK,
	LG3306_TR_LOCK,
	LG3306_AGC_LOCK,
};


#ifdef DBG_DUMP
static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state);
static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state);
#endif


static int lgdt3306a_write_reg(struct lgdt3306a_state *state, u16 reg, u8 val)
{
	int ret;
	u8 buf[] = { reg >> 8, reg & 0xff, val };
	struct i2c_msg msg = {
		.addr = state->cfg->i2c_addr, .flags = 0,
		.buf = buf, .len = 3,
	};

	dbg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);

	ret = i2c_transfer(state->i2c_adap, &msg, 1);

	if (ret != 1) {
		pr_err("error (addr %02x %02x <- %02x, err = %i)\n",
		       msg.buf[0], msg.buf[1], msg.buf[2], ret);
		if (ret < 0)
			return ret;
		else
			return -EREMOTEIO;
	}
	return 0;
}

static int lgdt3306a_read_reg(struct lgdt3306a_state *state, u16 reg, u8 *val)
{
	int ret;
	u8 reg_buf[] = { reg >> 8, reg & 0xff };
	struct i2c_msg msg[] = {
		{ .addr = state->cfg->i2c_addr,

Annotation

Implementation Notes