Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=a4f263b587573f47cc6bc7ad85e5f650169d48f6
Commit:     a4f263b587573f47cc6bc7ad85e5f650169d48f6
Parent:     b3d98135aa6e462d7e3f42a86d12483a9003a4da
Author:     Michael Krufky <[EMAIL PROTECTED]>
AuthorDate: Sun Jan 6 15:52:56 2008 -0300
Committer:  Mauro Carvalho Chehab <[EMAIL PROTECTED]>
CommitDate: Fri Jan 25 19:04:43 2008 -0200

    V4L/DVB (6986): tda18271: share state between analog and digital tuner 
instances
    
    Signed-off-by: Michael Krufky <[EMAIL PROTECTED]>
    Signed-off-by: Mauro Carvalho Chehab <[EMAIL PROTECTED]>
---
 drivers/media/dvb/frontends/tda18271-fe.c   |   93 ++++++++++++++++++++------
 drivers/media/dvb/frontends/tda18271-priv.h |    3 +
 drivers/media/video/tda8290.c               |    9 ++-
 3 files changed, 81 insertions(+), 24 deletions(-)

diff --git a/drivers/media/dvb/frontends/tda18271-fe.c 
b/drivers/media/dvb/frontends/tda18271-fe.c
index e860f4c..aa93e15 100644
--- a/drivers/media/dvb/frontends/tda18271-fe.c
+++ b/drivers/media/dvb/frontends/tda18271-fe.c
@@ -27,6 +27,9 @@ module_param_named(debug, tda18271_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debug level "
                 "(info=1, map=2, reg=4, adv=8 (or-able))");
 
+static LIST_HEAD(tda18271_list);
+static DEFINE_MUTEX(tda18271_list_mutex);
+
 /*---------------------------------------------------------------------*/
 
 static int tda18271_ir_cal_init(struct dvb_frontend *fe)
@@ -936,8 +939,24 @@ fail:
 
 static int tda18271_release(struct dvb_frontend *fe)
 {
-       kfree(fe->tuner_priv);
+       struct tda18271_priv *priv = fe->tuner_priv;
+
+       mutex_lock(&tda18271_list_mutex);
+
+       priv->count--;
+
+       if (!priv->count) {
+               tda_dbg("destroying instance @ %d-%04x\n",
+                       i2c_adapter_id(priv->i2c_adap),
+                       priv->i2c_addr);
+               list_del(&priv->tda18271_list);
+
+               kfree(priv);
+       }
+       mutex_unlock(&tda18271_list_mutex);
+
        fe->tuner_priv = NULL;
+
        return 0;
 }
 
@@ -1071,43 +1090,73 @@ struct dvb_frontend *tda18271_attach(struct 
dvb_frontend *fe, u8 addr,
                                     struct tda18271_config *cfg)
 {
        struct tda18271_priv *priv = NULL;
+       int state_found = 0;
+
+       mutex_lock(&tda18271_list_mutex);
+
+       list_for_each_entry(priv, &tda18271_list, tda18271_list) {
+               if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) &&
+                   (priv->i2c_addr == addr)) {
+                       tda_dbg("attaching existing tuner @ %d-%04x\n",
+                               i2c_adapter_id(priv->i2c_adap),
+                               priv->i2c_addr);
+                       priv->count++;
+                       fe->tuner_priv = priv;
+                       state_found = 1;
+                       /* allow dvb driver to override i2c gate setting */
+                       if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
+                               priv->gate = cfg->gate;
+                       break;
+               }
+       }
+       if (state_found == 0) {
+               tda_dbg("creating new tuner instance @ %d-%04x\n",
+                       i2c_adapter_id(i2c), addr);
+
+               priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL);
+               if (priv == NULL) {
+                       mutex_unlock(&tda18271_list_mutex);
+                       return NULL;
+               }
 
-       priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL);
-       if (priv == NULL)
-               return NULL;
+               priv->i2c_addr = addr;
+               priv->i2c_adap = i2c;
+               priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
+               priv->cal_initialized = false;
+               mutex_init(&priv->lock);
+               priv->count++;
 
-       priv->i2c_addr = addr;
-       priv->i2c_adap = i2c;
-       priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
-       priv->cal_initialized = false;
-       mutex_init(&priv->lock);
+               fe->tuner_priv = priv;
 
-       fe->tuner_priv = priv;
+               list_add_tail(&priv->tda18271_list, &tda18271_list);
 
-       if (tda18271_get_id(fe) < 0)
-               goto fail;
+               if (tda18271_get_id(fe) < 0)
+                       goto fail;
 
-       if (tda18271_assign_map_layout(fe) < 0)
-               goto fail;
+               if (tda18271_assign_map_layout(fe) < 0)
+                       goto fail;
 
-       memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
-              sizeof(struct dvb_tuner_ops));
+               mutex_lock(&priv->lock);
+               tda18271_init_regs(fe);
+               mutex_unlock(&priv->lock);
+       }
 
        /* override default std map with values in config struct */
        if ((cfg) && (cfg->std_map))
                tda18271_update_std_map(fe, cfg->std_map);
 
-       if (tda18271_debug & DBG_MAP)
-               tda18271_dump_std_map(fe);
-
-       mutex_lock(&priv->lock);
+       mutex_unlock(&tda18271_list_mutex);
 
-       tda18271_init_regs(fe);
+       memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
+              sizeof(struct dvb_tuner_ops));
 
-       mutex_unlock(&priv->lock);
+       if (tda18271_debug & DBG_MAP)
+               tda18271_dump_std_map(fe);
 
        return fe;
 fail:
+       mutex_unlock(&tda18271_list_mutex);
+
        tda18271_release(fe);
        return NULL;
 }
diff --git a/drivers/media/dvb/frontends/tda18271-priv.h 
b/drivers/media/dvb/frontends/tda18271-priv.h
index af89cfa..5c04d63 100644
--- a/drivers/media/dvb/frontends/tda18271-priv.h
+++ b/drivers/media/dvb/frontends/tda18271-priv.h
@@ -102,10 +102,13 @@ struct tda18271_priv {
        struct i2c_adapter *i2c_adap;
        unsigned char tda18271_regs[TDA18271_NUM_REGS];
 
+       struct list_head tda18271_list;
+
        enum tda18271_mode mode;
        enum tda18271_i2c_gate gate;
        enum tda18271_ver id;
 
+       unsigned int count;
        unsigned int tm_rfcal;
        unsigned int cal_initialized:1;
 
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
index eab5307..4ac7c04 100644
--- a/drivers/media/video/tda8290.c
+++ b/drivers/media/video/tda8290.c
@@ -502,8 +502,13 @@ static void tda8290_init_tuner(struct dvb_frontend *fe)
 
 static void tda829x_release(struct dvb_frontend *fe)
 {
-       if (fe->ops.tuner_ops.release)
-               fe->ops.tuner_ops.release(fe);
+       struct tda8290_priv *priv = fe->analog_demod_priv;
+
+       /* dont try to release the tuner
+        * if we didn't attach it from this module */
+       if ((priv->ver > TDA8290) && (priv->ver > TDA8295))
+               if (fe->ops.tuner_ops.release)
+                       fe->ops.tuner_ops.release(fe);
 
        kfree(fe->analog_demod_priv);
        fe->analog_demod_priv = NULL;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to