V4L/DVB (11064): au8522: make use of hybrid framework so analog/digital demod can...
authorDevin Heitmueller <dheitmueller@linuxtv.org>
Wed, 11 Mar 2009 06:00:36 +0000 (03:00 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:43:24 +0000 (12:43 -0300)
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>
drivers/media/dvb/frontends/au8522_dig.c
drivers/media/dvb/frontends/au8522_priv.h

index fa3ecbe..b043466 100644 (file)
 
 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);
index 569675d..98b09ca 100644 (file)
 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);