Mailing List archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[linux-dvb] Re: [patches] cx22702 + mt352 updates
Hi,
> > But I don't want to start over from scratch with a code base where I
> > don't even know whenever it works or not, which I would have to to
> > create a minimal patch.
>
> I got that already, but it is still what I'm asking you to do,
> whether you see the point or not. If you can convince someone else
> (Andrew, Michael, ...) to commit your patch, fine. But I won't do it.
How about this one? Switched over to using a config struct like the
current linuxtv version, also reordered the functions to match the
linuxtv version's ordering so diff produces a smaller and more readable
patch ...
Gerd
diff -pu --ignore-all-space --minimal /work/bk/2.6/Linux/drivers/media/dvb/frontends/cx22702.h ./cx22702.h
--- /work/bk/2.6/Linux/drivers/media/dvb/frontends/cx22702.h 2004-12-08 16:43:38.000000000 +0100
+++ ./cx22702.h 2005-02-04 10:37:46.000000000 +0100
@@ -36,8 +36,14 @@ struct cx22702_config
u8 demod_address;
/* PLL maintenance */
+ u8 pll_address;
+ struct dvb_pll_desc *pll_desc;
+
+#if 0 /* disabled for now, but maybe we'll need it again for plls
+ * which don't fit into the dvb_pll_desc model ... */
int (*pll_init)(struct dvb_frontend* fe);
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+#endif
};
extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
diff -pu --ignore-all-space --minimal /work/bk/2.6/Linux/drivers/media/dvb/frontends/cx22702.c ./cx22702.c
--- /work/bk/2.6/Linux/drivers/media/dvb/frontends/cx22702.c 2004-12-08 16:37:00.000000000 +0100
+++ ./cx22702.c 2005-02-04 13:34:55.000000000 +0100
@@ -1,8 +1,8 @@
/*
- Conexant 22702 DVB OFDM demodulator driver
+ Conexant 22702 DVB OFDM frontend driver
based on:
- Alps TDMB7 DVB OFDM demodulator driver
+ Alps TDMB7 DVB OFDM frontend driver
Copyright (C) 2001-2002 Convergence Integrated Media GmbH
Holger Waechtler <holger@convergence.de>
@@ -31,27 +31,32 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/delay.h>
+
#include "dvb_frontend.h"
+#include "dvb-pll.h"
#include "cx22702.h"
+#define FRONTEND_NAME "dvbfe_cx22702"
-struct cx22702_state {
+#define dprintk if (debug) printk
- struct i2c_adapter* i2c;
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
- struct dvb_frontend_ops ops;
+/* ------------------------------------------------------------------ */
- /* configuration settings */
+struct cx22702_state {
const struct cx22702_config* config;
-
- struct dvb_frontend frontend;
-
- /* previous uncorrected block counter */
+ struct i2c_client demod;
+ struct i2c_client pll;
+ struct dvb_frontend fe;
+ struct dvb_frontend_ops ops;
u8 prevUCBlocks;
};
-static int debug = 0;
-#define dprintk if (debug) printk
+static struct i2c_client demod_template;
+static struct i2c_client pll_template;
/* Register values to initialise the demod */
static u8 init_tab [] = {
@@ -83,37 +88,71 @@ static u8 init_tab [] = {
0xfd, 0x00,
};
-static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data)
+/* ------------------------------------------------------------------ */
+
+static int writereg(struct i2c_client *c, u8 reg, u8 data)
{
- int ret;
u8 buf [] = { reg, data };
- struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
-
- ret = i2c_transfer(state->i2c, &msg, 1);
+ int ret;
- if (ret != 1)
+ ret = i2c_master_send(c, buf, 2);
+ if (ret != 2) {
printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
__FUNCTION__, reg, data, ret);
+ return -1;
+ }
+ return 0;
+}
- return (ret != 1) ? -1 : 0;
+static int readreg(struct i2c_client *c, u8 reg)
+{
+ u8 wr [] = { reg };
+ u8 rd [] = { 0 };
+ struct i2c_msg msg [] = {
+ { .addr = c->addr, .flags = 0, .buf = wr, .len = 1 },
+ { .addr = c->addr, .flags = I2C_M_RD, .buf = rd, .len = 1 },
+ };
+ int ret;
+
+ ret = i2c_transfer(c->adapter, msg, 2);
+ if (ret != 2) {
+ printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+ return -1;
+ }
+ return rd[0];
}
-static u8 cx22702_readreg (struct cx22702_state* state, u8 reg)
+/* ------------------------------------------------------------------ */
+
+#define PLL_ENABLE(cx) writereg(&cx->demod, 0x0D, readreg(&cx->demod, 0x0D) & 0xfe)
+#define PLL_DISABLE(cx) writereg(&cx->demod, 0x0D, readreg(&cx->demod, 0x0D) | 0x01)
+
+static int pll_write4(struct i2c_client *c, u8 *data)
{
int ret;
- u8 b0 [] = { reg };
- u8 b1 [] = { 0 };
- struct i2c_msg msg [] = {
- { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+ ret = i2c_master_send(c, data, 4);
+ if (ret != 4) {
+ printk("%s: i/o error (addr == 0x%02x, ret == %i)\n",
+ __FUNCTION__, c->addr, ret);
+ return -EIO;
+ }
+ return 0;
+}
- ret = i2c_transfer(state->i2c, msg, 2);
+/* ------------------------------------------------------------------ */
- if (ret != 2)
- printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+static int cx22702_reset(struct cx22702_state *state)
+{
+ int i;
- return b1[0];
+ dprintk("%s\n",__FUNCTION__);
+ writereg(&state->demod, 0x00, 0x02);
+ msleep(10);
+
+ for (i=0; i<ARRAY_SIZE(init_tab); i+=2)
+ writereg(&state->demod, init_tab[i], init_tab[i+1]);
+ return 0;
}
static int cx22702_set_inversion (struct cx22702_state *state, int inversion)
@@ -121,35 +160,33 @@ static int cx22702_set_inversion (struct
u8 val;
switch (inversion) {
-
case INVERSION_AUTO:
return -EOPNOTSUPP;
case INVERSION_ON:
- val = cx22702_readreg (state, 0x0C);
- return cx22702_writereg (state, 0x0C, val | 0x01);
+ val = readreg(&state->demod, 0x0C);
+ return writereg(&state->demod, 0x0C, val | 0x01);
case INVERSION_OFF:
- val = cx22702_readreg (state, 0x0C);
- return cx22702_writereg (state, 0x0C, val & 0xfe);
+ val = readreg(&state->demod, 0x0C);
+ return writereg(&state->demod, 0x0C, val & 0xfe);
default:
return -EINVAL;
-
}
-
}
/* Retrieve the demod settings */
-static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_parameters *p)
+static int cx22702_get_tps(struct cx22702_state *state,
+ struct dvb_ofdm_parameters *p)
{
u8 val;
/* Make sure the TPS regs are valid */
- if (!(cx22702_readreg(state, 0x0A) & 0x20))
+ if (!(readreg(&state->demod, 0x0A) & 0x20))
return -EAGAIN;
- val = cx22702_readreg (state, 0x01);
+ val = readreg(&state->demod, 0x01);
switch( (val&0x18)>>3) {
case 0: p->constellation = QPSK; break;
case 1: p->constellation = QAM_16; break;
@@ -162,8 +199,7 @@ static int cx22702_get_tps (struct cx227
case 3: p->hierarchy_information = HIERARCHY_4; break;
}
-
- val = cx22702_readreg (state, 0x02);
+ val = readreg(&state->demod, 0x02);
switch( (val&0x38)>>3 ) {
case 0: p->code_rate_HP = FEC_1_2; break;
case 1: p->code_rate_HP = FEC_2_3; break;
@@ -179,8 +215,7 @@ static int cx22702_get_tps (struct cx227
case 4: p->code_rate_LP = FEC_7_8; break;
}
-
- val = cx22702_readreg (state, 0x03);
+ val = readreg(&state->demod, 0x03);
switch( (val&0x0c)>>2 ) {
case 0: p->guard_interval = GUARD_INTERVAL_1_32; break;
case 1: p->guard_interval = GUARD_INTERVAL_1_16; break;
@@ -195,28 +230,22 @@ static int cx22702_get_tps (struct cx227
return 0;
}
-
-
-
-
-
-
-
-
-
-
-
-
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx22702_set_tps(struct cx22702_state *state,
+ struct dvb_frontend_parameters *p)
{
u8 val;
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
+ u8 pllbuf[4];
+
+ dprintk("%s\n",__FUNCTION__);
/* set PLL */
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe);
- state->config->pll_set(fe, p);
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
+ dvb_pll_configure(state->config->pll_desc, pllbuf,
+ p->frequency,
+ p->u.ofdm.bandwidth);
+ PLL_ENABLE(state);
+ pll_write4(&state->pll,pllbuf);
+ PLL_DISABLE(state);
/* set inversion */
cx22702_set_inversion (state, p->inversion);
@@ -224,13 +253,13 @@ static int cx22702_set_tps (struct dvb_f
/* set bandwidth */
switch(p->u.ofdm.bandwidth) {
case BANDWIDTH_6_MHZ:
- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x20 );
+ writereg(&state->demod, 0x0C, (readreg(&state->demod, 0x0C) & 0xcf) | 0x20 );
break;
case BANDWIDTH_7_MHZ:
- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x10 );
+ writereg(&state->demod, 0x0C, (readreg(&state->demod, 0x0C) & 0xcf) | 0x10 );
break;
case BANDWIDTH_8_MHZ:
- cx22702_writereg(state, 0x0C, cx22702_readreg(state, 0x0C) &0xcf );
+ writereg(&state->demod, 0x0C, readreg(&state->demod, 0x0C) &0xcf );
break;
default:
dprintk ("%s: invalid bandwidth\n",__FUNCTION__);
@@ -249,13 +278,13 @@ static int cx22702_set_tps (struct dvb_f
(p->u.ofdm.transmission_mode==TRANSMISSION_MODE_AUTO) ) {
/* TPS Source - use hardware driven values */
- cx22702_writereg(state, 0x06, 0x10);
- cx22702_writereg(state, 0x07, 0x9);
- cx22702_writereg(state, 0x08, 0xC1);
- cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc );
- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
- cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */
- printk("%s: Autodetecting\n",__FUNCTION__);
+ writereg(&state->demod, 0x06, 0x10);
+ writereg(&state->demod, 0x07, 0x9);
+ writereg(&state->demod, 0x08, 0xC1);
+ writereg(&state->demod, 0x0B, readreg(&state->demod, 0x0B) & 0xfc );
+ writereg(&state->demod, 0x0C, (readreg(&state->demod, 0x0C) & 0xBF) | 0x40 );
+ writereg(&state->demod, 0x00, 0x01); /* Begin aquisition */
+ dprintk("%s: Autodetecting\n",__FUNCTION__);
return 0;
}
@@ -278,7 +307,7 @@ static int cx22702_set_tps (struct dvb_f
dprintk ("%s: invalid hierarchy\n",__FUNCTION__);
return -EINVAL;
}
- cx22702_writereg (state, 0x06, val);
+ writereg(&state->demod, 0x06, val);
val=0;
switch(p->u.ofdm.code_rate_HP) {
@@ -303,7 +332,7 @@ static int cx22702_set_tps (struct dvb_f
dprintk ("%s: invalid code_rate_LP\n",__FUNCTION__);
return -EINVAL;
}
- cx22702_writereg (state, 0x07, val);
+ writereg(&state->demod, 0x07, val);
val=0;
switch(p->u.ofdm.guard_interval) {
@@ -322,211 +351,298 @@ static int cx22702_set_tps (struct dvb_f
dprintk ("%s: invalid transmission_mode\n",__FUNCTION__);
return -EINVAL;
}
- cx22702_writereg(state, 0x08, val);
- cx22702_writereg(state, 0x0B, (cx22702_readreg(state, 0x0B) & 0xfc) | 0x02 );
- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
+ writereg(&state->demod, 0x08, val);
+ writereg(&state->demod, 0x0B, (readreg(&state->demod, 0x0B) & 0xfc) | 0x02 );
+ writereg(&state->demod, 0x0C, (readreg(&state->demod, 0x0C) & 0xBF) | 0x40 );
/* Begin channel aquisition */
- cx22702_writereg(state, 0x00, 0x01);
+ writereg(&state->demod, 0x00, 0x01);
return 0;
}
+/* ------------------------------------------------------------------ */
-/* Reset the demod hardware and reset all of the configuration registers
- to a default state. */
static int cx22702_init (struct dvb_frontend* fe)
{
- int i;
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
-
- cx22702_writereg (state, 0x00, 0x02);
-
- msleep(10);
-
- for (i=0; i<sizeof(init_tab); i+=2)
- cx22702_writereg (state, init_tab[i], init_tab[i+1]);
-
-
- /* init PLL */
- if (state->config->pll_init) {
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe);
- state->config->pll_init(fe);
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
- }
+ struct cx22702_state *state = fe->demodulator_priv;
+ cx22702_reset(state);
return 0;
}
static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
- u8 reg0A;
- u8 reg23;
+ struct cx22702_state *state = fe->demodulator_priv;
+ u8 reg0A = readreg(&state->demod, 0x0A);
+ u8 reg23 = readreg(&state->demod, 0x23);
*status = 0;
-
- reg0A = cx22702_readreg (state, 0x0A);
- reg23 = cx22702_readreg (state, 0x23);
-
- dprintk ("%s: status demod=0x%02x agc=0x%02x\n"
- ,__FUNCTION__,reg0A,reg23);
-
- if(reg0A & 0x10) {
- *status |= FE_HAS_LOCK;
- *status |= FE_HAS_VITERBI;
- *status |= FE_HAS_SYNC;
- }
-
+ if (reg0A & 0x10)
+ *status |= FE_HAS_LOCK| FE_HAS_VITERBI | FE_HAS_SYNC;
if(reg0A & 0x20)
*status |= FE_HAS_CARRIER;
-
if(reg23 < 0xf0)
*status |= FE_HAS_SIGNAL;
+ dprintk ("%s: status demod=0x%02x agc=0x%02x status=0x%x\n",
+ __FUNCTION__,reg0A,reg23,*status);
return 0;
}
static int cx22702_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
-
- if(cx22702_readreg (state, 0xE4) & 0x02) {
- /* Realtime statistics */
- *ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
- | (cx22702_readreg (state, 0xDF)&0x7F);
- } else {
- /* Averagtine statistics */
- *ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
- | cx22702_readreg (state, 0xDF);
- }
+ struct cx22702_state *state = fe->demodulator_priv;
+ *ber = (readreg(&state->demod, 0xDE) & 0x7F) << 7;
+ *ber |= readreg(&state->demod, 0xDF) & 0x7F;
return 0;
}
-static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
-
- *signal_strength = cx22702_readreg (state, 0x23);
+ struct cx22702_state *state = fe->demodulator_priv;
+ *strength = readreg(&state->demod, 0x23);
return 0;
}
static int cx22702_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
-
- u16 rs_ber=0;
- if(cx22702_readreg (state, 0xE4) & 0x02) {
- /* Realtime statistics */
- rs_ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
- | (cx22702_readreg (state, 0xDF)& 0x7F);
- } else {
- /* Averagine statistics */
- rs_ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 8
- | cx22702_readreg (state, 0xDF);
- }
- *snr = ~rs_ber;
+ u32 ber;
+ /* We don't have an register for this */
+ /* We'll take the inverse of the BER register */
+ cx22702_read_ber(fe, &ber);
+ *snr = ~ber;
return 0;
}
static int cx22702_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
-
- u8 _ucblocks;
+ struct cx22702_state *state = fe->demodulator_priv;
+ u8 ucb;
/* RS Uncorrectable Packet Count then reset */
- _ucblocks = cx22702_readreg (state, 0xE3);
- if (state->prevUCBlocks < _ucblocks) *ucblocks = (_ucblocks - state->prevUCBlocks);
- else *ucblocks = state->prevUCBlocks - _ucblocks;
- state->prevUCBlocks = _ucblocks;
-
+ ucb = readreg(&state->demod, 0xE3);
+ if (state->prevUCBlocks < ucb)
+ *ucblocks = (ucb - state->prevUCBlocks);
+ else
+ *ucblocks = 256 + ucb - state->prevUCBlocks;
+ state->prevUCBlocks = ucb;
return 0;
}
-static int cx22702_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx22702_get_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
+ u8 reg0C = readreg(&state->demod, 0x0C);
+ params->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF;
+ return cx22702_get_tps(state, ¶ms->u.ofdm);
+}
- u8 reg0C = cx22702_readreg (state, 0x0C);
+static int cx22702_set_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params)
+{
+ struct cx22702_state *state = fe->demodulator_priv;
+ int ret;
- p->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF;
- return cx22702_get_tps (state, &p->u.ofdm);
+ ret=cx22702_set_tps(state, params);
+ if (debug && ret < 0)
+ printk("%s: set_tps failed ret=%d\n",__FUNCTION__,ret);
+ return ret;
}
static void cx22702_release(struct dvb_frontend* fe)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
+
+ i2c_detach_client(&state->demod);
+ i2c_detach_client(&state->pll);
kfree(state);
}
-static struct dvb_frontend_ops cx22702_ops;
-
-struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
- struct i2c_adapter* i2c)
+static int cx22702_sleep(struct dvb_frontend* fe)
{
- struct cx22702_state* state = NULL;
-
- /* allocate memory for the internal state */
- state = (struct cx22702_state*) kmalloc(sizeof(struct cx22702_state), GFP_KERNEL);
- if (state == NULL) goto error;
-
- /* setup the state */
- state->config = config;
- state->i2c = i2c;
- memcpy(&state->ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
- state->prevUCBlocks = 0;
-
- /* check if the demod is there */
- if (cx22702_readreg(state, 0x1f) != 0x3) goto error;
+ struct cx22702_state *state = fe->demodulator_priv;
+ u8 pllbuf[4];
- /* create dvb_frontend */
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
- return &state->frontend;
+ dprintk("%s\n",__FUNCTION__);
-error:
- if (state) kfree(state);
- return NULL;
+ dvb_pll_configure(state->config->pll_desc, pllbuf, 0, 0);
+ PLL_ENABLE(state);
+ pll_write4(&state->pll,pllbuf);
+ PLL_DISABLE(state);
+ return 0;
}
-static struct dvb_frontend_ops cx22702_ops = {
-
+static struct dvb_frontend_ops cx22702_fe_ops = {
.info = {
- .name = "Conexant CX22702 DVB-T",
+ .name = "cx22702 demod",
.type = FE_OFDM,
.frequency_min = 177000000,
.frequency_max = 858000000,
.frequency_stepsize = 166666,
- .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
- FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
- FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
- FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
+ .caps =
+ FE_CAN_FEC_1_2 |
+ FE_CAN_FEC_2_3 |
+ FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 |
+ FE_CAN_FEC_7_8 |
+ FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK |
+ FE_CAN_QAM_16 |
+ FE_CAN_QAM_64 |
+ FE_CAN_QAM_AUTO |
+ FE_CAN_HIERARCHY_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_RECOVER,
},
-
- .release = cx22702_release,
-
.init = cx22702_init,
-
- .set_frontend = cx22702_set_tps,
+ .sleep = cx22702_sleep,
+ .set_frontend = cx22702_set_frontend,
.get_frontend = cx22702_get_frontend,
-
.read_status = cx22702_read_status,
.read_ber = cx22702_read_ber,
.read_signal_strength = cx22702_read_signal_strength,
.read_snr = cx22702_read_snr,
.read_ucblocks = cx22702_read_ucblocks,
+ .release = cx22702_release,
};
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+/* ------------------------------------------------------------------ */
-MODULE_DESCRIPTION("Conexant CX22702 DVB-T Demodulator driver");
+/* Validate the demod, make sure we understand the hardware */
+static int cx22702_validate_demod(struct i2c_client *c)
+{
+ int type = readreg(c, 0x1f);
+
+ if (0x03 != type) {
+ printk ("%s i2c demod type 0x%02x not known\n",
+ __FUNCTION__, type);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+/* Validate the tuner PLL, make sure we understand the hardware */
+static int cx22702_validate_pll(struct cx22702_state *state)
+{
+ int result=0;
+
+ PLL_ENABLE(state);
+ result = readreg(&state->pll,0xc2);
+ PLL_DISABLE(state);
+ return result;
+}
+
+struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
+ struct i2c_adapter* i2c)
+{
+ struct cx22702_state *state;
+ int ret;
+
+ state = kmalloc(sizeof(*state), GFP_KERNEL);
+ if (NULL == state)
+ return NULL;
+ memset(state, 0, sizeof(*state));
+
+ state->config = config;
+ state->ops = cx22702_fe_ops;
+ state->fe.demodulator_priv = state;
+ state->fe.ops = &state->ops;
+
+ state->demod = demod_template;
+ state->demod.adapter = i2c;
+ state->demod.addr = config->demod_address;
+ state->pll = pll_template;
+ strlcpy(state->pll.name, config->pll_desc->name, sizeof(state->pll.name));
+ state->pll.adapter = i2c;
+ state->pll.addr = config->pll_address;
+ i2c_set_clientdata(&state->demod, state);
+ i2c_set_clientdata(&state->pll, state);
+
+ /* verify devices */
+ ret=cx22702_validate_demod(&state->demod);
+ if (ret < 0)
+ goto fail_free;
+ ret=cx22702_validate_pll(state);
+ if(ret < 0)
+ goto fail_free;
+
+ /* register i2c */
+ ret = i2c_attach_client(&state->demod);
+ if (0 != ret) {
+ printk("cx22702: i2c demod register failed (%d)\n", ret);
+ goto fail_free;
+ }
+ ret = i2c_attach_client(&state->pll);
+ if (0 != ret) {
+ printk("cx22702: i2c pll register failed (%d)\n", ret);
+ goto fail_unreg1;
+ }
+
+ /* all fine ;) */
+ return &state->fe;
+
+fail_unreg1:
+ i2c_detach_client(&state->demod);
+fail_free:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(cx22702_attach);
+
+/* ------------------------------------------------------------------ */
+
+static struct i2c_driver demod_driver = {
+ .owner = THIS_MODULE,
+ .name = __stringify(KBUILD_MODNAME) " demod",
+ .id = I2C_DRIVERID_DVBFE_CX22702,
+};
+static struct i2c_client demod_template = {
+ .name = "cx22702",
+ .flags = I2C_CLIENT_ALLOW_USE,
+ .driver = &demod_driver,
+};
+
+static struct i2c_driver pll_driver = {
+ .owner = THIS_MODULE,
+ .name = __stringify(KBUILD_MODNAME) " pll",
+ .id = I2C_DRIVERID_DVBFE_CX22702,
+};
+static struct i2c_client pll_template = {
+ .name = "unset",
+ .flags = I2C_CLIENT_ALLOW_USE,
+ .driver = &pll_driver,
+};
+
+static int __init init_cx22702 (void)
+{
+ i2c_add_driver(&demod_driver);
+ i2c_add_driver(&pll_driver);
+ return 0;
+}
+
+static void __exit exit_cx22702 (void)
+{
+ i2c_del_driver(&pll_driver);
+ i2c_del_driver(&demod_driver);
+}
+
+module_init (init_cx22702);
+module_exit (exit_cx22702);
+
+MODULE_DESCRIPTION("CX22702 DVB Frontend driver");
MODULE_AUTHOR("Steven Toth");
+MODULE_AUTHOR("Gerd Knorr");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(cx22702_attach);
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * compile-command: "make DVB=1"
+ * End:
+ */
Home |
Main Index |
Thread Index