aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@linuxtv.org>2009-03-11 03:00:36 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 12:43:24 -0300
commit209fdf66b8699a6b2998b58e572d67230dae507f (patch)
treea2b287bf353d610d50b1d041d15e3f8a927fe70c
parent7bf63eda681e095ca3c39d075354053107febf80 (diff)
V4L/DVB (11064): au8522: make use of hybrid framework so analog/digital demod can share state
Make use of the hybrid tuner framework so the analog and digital parts of the au8522 demodulator can make use of the same shared state. Thanks to Michael Krufky <mkrufky@linuxtv.org> and Steven Toth <stoth@linuxtv.org> for providing sample hardware, engineering level support, and testing. Signed-off-by: Devin Heitmueller <dheitmueller@linuxtv.org> Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/dvb/frontends/au8522_dig.c45
-rw-r--r--drivers/media/dvb/frontends/au8522_priv.h8
2 files changed, 46 insertions, 7 deletions
diff --git a/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb/frontends/au8522_dig.c
index fa3ecbed1e5..b04346687c6 100644
--- a/drivers/media/dvb/frontends/au8522_dig.c
+++ b/drivers/media/dvb/frontends/au8522_dig.c
@@ -31,6 +31,10 @@
static int debug;
+/* Despite the name "hybrid_tuner", the framework works just as well for
+ hybrid demodulators as well... */
+static LIST_HEAD(hybrid_tuner_instance_list);
+
#define dprintk(arg...) do { \
if (debug) \
printk(arg); \
@@ -786,23 +790,50 @@ static int au8522_get_tune_settings(struct dvb_frontend *fe,
return 0;
}
+static struct dvb_frontend_ops au8522_ops;
+
+int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
+ u8 client_address)
+{
+ return hybrid_tuner_request_state(struct au8522_state, (*state),
+ hybrid_tuner_instance_list,
+ i2c, client_address, "au8522");
+}
+
+void au8522_release_state(struct au8522_state *state)
+{
+ if (state != NULL)
+ hybrid_tuner_release_state(state);
+}
+
+
static void au8522_release(struct dvb_frontend *fe)
{
struct au8522_state *state = fe->demodulator_priv;
- kfree(state);
+ au8522_release_state(state);
}
-static struct dvb_frontend_ops au8522_ops;
-
struct dvb_frontend *au8522_attach(const struct au8522_config *config,
struct i2c_adapter *i2c)
{
struct au8522_state *state = NULL;
+ int instance;
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL);
- if (state == NULL)
- goto error;
+ instance = au8522_get_state(&state, i2c, config->demod_address);
+ switch (instance) {
+ case 0:
+ dprintk("%s state allocation failed\n", __func__);
+ break;
+ case 1:
+ /* new demod instance */
+ dprintk("%s using new instance\n", __func__);
+ break;
+ default:
+ /* existing demod instance */
+ dprintk("%s using existing instance\n", __func__);
+ break;
+ }
/* setup the state */
state->config = config;
@@ -824,7 +855,7 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config,
return &state->frontend;
error:
- kfree(state);
+ au8522_release_state(state);
return NULL;
}
EXPORT_SYMBOL(au8522_attach);
diff --git a/drivers/media/dvb/frontends/au8522_priv.h b/drivers/media/dvb/frontends/au8522_priv.h
index 569675d295d..98b09caa212 100644
--- a/drivers/media/dvb/frontends/au8522_priv.h
+++ b/drivers/media/dvb/frontends/au8522_priv.h
@@ -37,6 +37,10 @@
struct au8522_state {
struct i2c_adapter *i2c;
+ /* Used for sharing of the state between analog and digital mode */
+ struct tuner_i2c_props i2c_props;
+ struct list_head hybrid_tuner_instance_list;
+
/* configuration settings */
const struct au8522_config *config;
@@ -55,3 +59,7 @@ int au8522_writereg(struct au8522_state *state, u16 reg, u8 data);
u8 au8522_readreg(struct au8522_state *state, u16 reg);
int au8522_init(struct dvb_frontend *fe);
int au8522_sleep(struct dvb_frontend *fe);
+
+int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
+ u8 client_address);
+void au8522_release_state(struct au8522_state *state);