drivers/media/dvb-frontends/s5h1420.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/dvb-frontends/s5h1420.c
Extension
.c
Size
24913 bytes
Lines
965
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 s5h1420_state {
	struct i2c_adapter* i2c;
	const struct s5h1420_config* config;

	struct dvb_frontend frontend;
	struct i2c_adapter tuner_i2c_adapter;

	u8 CON_1_val;

	u8 postlocked:1;
	u32 fclk;
	u32 tunedfreq;
	enum fe_code_rate fec_inner;
	u32 symbol_rate;

	/* FIXME: ugly workaround for flexcop's incapable i2c-controller
	 * it does not support repeated-start, workaround: write addr-1
	 * and then read
	 */
	u8 shadow[256];
};

static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
				     struct dvb_frontend_tune_settings* fesettings);


static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debugging");

#define dprintk(x...) do { \
	if (debug) \
		printk(KERN_DEBUG "S5H1420: " x); \
} while (0)

static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)
{
	int ret;
	u8 b[2];
	struct i2c_msg msg[] = {
		{ .addr = state->config->demod_address, .flags = 0, .buf = b, .len = 2 },
		{ .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
		{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = 1 },
	};

	b[0] = (reg - 1) & 0xff;
	b[1] = state->shadow[(reg - 1) & 0xff];

	if (state->config->repeated_start_workaround) {
		ret = i2c_transfer(state->i2c, msg, 3);
		if (ret != 3)
			return ret;
	} else {
		ret = i2c_transfer(state->i2c, &msg[1], 1);
		if (ret != 1)
			return ret;
		ret = i2c_transfer(state->i2c, &msg[2], 1);
		if (ret != 1)
			return ret;
	}

	/* dprintk("rd(%02x): %02x %02x\n", state->config->demod_address, reg, b[0]); */

	return b[0];
}

static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data)
{
	u8 buf[] = { reg, data };
	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
	int err;

	/* dprintk("wr(%02x): %02x %02x\n", state->config->demod_address, reg, data); */
	err = i2c_transfer(state->i2c, &msg, 1);
	if (err != 1) {
		dprintk("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
		return -EREMOTEIO;
	}
	state->shadow[reg] = data;

	return 0;
}

static int s5h1420_set_voltage(struct dvb_frontend *fe,
			       enum fe_sec_voltage voltage)
{
	struct s5h1420_state* state = fe->demodulator_priv;

	dprintk("enter %s\n", __func__);

Annotation

Implementation Notes