summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/frontends/tda18271-fe.c
diff options
context:
space:
mode:
authorMichael Krufky <mkrufky@linuxtv.org>2008-01-06 13:52:56 -0500
committerMichael Krufky <mkrufky@linuxtv.org>2008-01-06 13:52:56 -0500
commit5969fce339f2c43345b200da21c1bcf21f6440a7 (patch)
tree711abde95f19975abdd35455cb485e127f99ad89 /linux/drivers/media/dvb/frontends/tda18271-fe.c
parentef15cd3c577cdc80d27bbd6ee72c2a9c991cd270 (diff)
downloadmediapointer-dvb-s2-5969fce339f2c43345b200da21c1bcf21f6440a7.tar.gz
mediapointer-dvb-s2-5969fce339f2c43345b200da21c1bcf21f6440a7.tar.bz2
tda18271: share state between analog and digital tuner instances
From: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Diffstat (limited to 'linux/drivers/media/dvb/frontends/tda18271-fe.c')
-rw-r--r--linux/drivers/media/dvb/frontends/tda18271-fe.c93
1 files changed, 71 insertions, 22 deletions
diff --git a/linux/drivers/media/dvb/frontends/tda18271-fe.c b/linux/drivers/media/dvb/frontends/tda18271-fe.c
index 26352716a..fe8797855 100644
--- a/linux/drivers/media/dvb/frontends/tda18271-fe.c
+++ b/linux/drivers/media/dvb/frontends/tda18271-fe.c
@@ -28,6 +28,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)
@@ -969,8 +972,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;
}
@@ -1110,43 +1129,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;
}