V4L/DVB (6986): tda18271: share state between analog and digital tuner instances
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
b3d98135aa
commit
a4f263b587
3 changed files with 81 additions and 24 deletions
|
@ -27,6 +27,9 @@ module_param_named(debug, tda18271_debug, int, 0644);
|
||||||
MODULE_PARM_DESC(debug, "set debug level "
|
MODULE_PARM_DESC(debug, "set debug level "
|
||||||
"(info=1, map=2, reg=4, adv=8 (or-able))");
|
"(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)
|
static int tda18271_ir_cal_init(struct dvb_frontend *fe)
|
||||||
|
@ -936,8 +939,24 @@ fail:
|
||||||
|
|
||||||
static int tda18271_release(struct dvb_frontend *fe)
|
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;
|
fe->tuner_priv = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1071,43 +1090,73 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
|
||||||
struct tda18271_config *cfg)
|
struct tda18271_config *cfg)
|
||||||
{
|
{
|
||||||
struct tda18271_priv *priv = NULL;
|
struct tda18271_priv *priv = NULL;
|
||||||
|
int state_found = 0;
|
||||||
|
|
||||||
priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL);
|
mutex_lock(&tda18271_list_mutex);
|
||||||
if (priv == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
priv->i2c_addr = addr;
|
list_for_each_entry(priv, &tda18271_list, tda18271_list) {
|
||||||
priv->i2c_adap = i2c;
|
if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) &&
|
||||||
priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
|
(priv->i2c_addr == addr)) {
|
||||||
priv->cal_initialized = false;
|
tda_dbg("attaching existing tuner @ %d-%04x\n",
|
||||||
mutex_init(&priv->lock);
|
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);
|
||||||
|
|
||||||
fe->tuner_priv = priv;
|
priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL);
|
||||||
|
if (priv == NULL) {
|
||||||
|
mutex_unlock(&tda18271_list_mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (tda18271_get_id(fe) < 0)
|
priv->i2c_addr = addr;
|
||||||
goto fail;
|
priv->i2c_adap = i2c;
|
||||||
|
priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
|
||||||
|
priv->cal_initialized = false;
|
||||||
|
mutex_init(&priv->lock);
|
||||||
|
priv->count++;
|
||||||
|
|
||||||
if (tda18271_assign_map_layout(fe) < 0)
|
fe->tuner_priv = priv;
|
||||||
goto fail;
|
|
||||||
|
|
||||||
memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
|
list_add_tail(&priv->tda18271_list, &tda18271_list);
|
||||||
sizeof(struct dvb_tuner_ops));
|
|
||||||
|
if (tda18271_get_id(fe) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (tda18271_assign_map_layout(fe) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
mutex_lock(&priv->lock);
|
||||||
|
tda18271_init_regs(fe);
|
||||||
|
mutex_unlock(&priv->lock);
|
||||||
|
}
|
||||||
|
|
||||||
/* override default std map with values in config struct */
|
/* override default std map with values in config struct */
|
||||||
if ((cfg) && (cfg->std_map))
|
if ((cfg) && (cfg->std_map))
|
||||||
tda18271_update_std_map(fe, cfg->std_map);
|
tda18271_update_std_map(fe, cfg->std_map);
|
||||||
|
|
||||||
|
mutex_unlock(&tda18271_list_mutex);
|
||||||
|
|
||||||
|
memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
|
||||||
|
sizeof(struct dvb_tuner_ops));
|
||||||
|
|
||||||
if (tda18271_debug & DBG_MAP)
|
if (tda18271_debug & DBG_MAP)
|
||||||
tda18271_dump_std_map(fe);
|
tda18271_dump_std_map(fe);
|
||||||
|
|
||||||
mutex_lock(&priv->lock);
|
|
||||||
|
|
||||||
tda18271_init_regs(fe);
|
|
||||||
|
|
||||||
mutex_unlock(&priv->lock);
|
|
||||||
|
|
||||||
return fe;
|
return fe;
|
||||||
fail:
|
fail:
|
||||||
|
mutex_unlock(&tda18271_list_mutex);
|
||||||
|
|
||||||
tda18271_release(fe);
|
tda18271_release(fe);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,10 +102,13 @@ struct tda18271_priv {
|
||||||
struct i2c_adapter *i2c_adap;
|
struct i2c_adapter *i2c_adap;
|
||||||
unsigned char tda18271_regs[TDA18271_NUM_REGS];
|
unsigned char tda18271_regs[TDA18271_NUM_REGS];
|
||||||
|
|
||||||
|
struct list_head tda18271_list;
|
||||||
|
|
||||||
enum tda18271_mode mode;
|
enum tda18271_mode mode;
|
||||||
enum tda18271_i2c_gate gate;
|
enum tda18271_i2c_gate gate;
|
||||||
enum tda18271_ver id;
|
enum tda18271_ver id;
|
||||||
|
|
||||||
|
unsigned int count;
|
||||||
unsigned int tm_rfcal;
|
unsigned int tm_rfcal;
|
||||||
unsigned int cal_initialized:1;
|
unsigned int cal_initialized:1;
|
||||||
|
|
||||||
|
|
|
@ -502,8 +502,13 @@ static void tda8290_init_tuner(struct dvb_frontend *fe)
|
||||||
|
|
||||||
static void tda829x_release(struct dvb_frontend *fe)
|
static void tda829x_release(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
if (fe->ops.tuner_ops.release)
|
struct tda8290_priv *priv = fe->analog_demod_priv;
|
||||||
fe->ops.tuner_ops.release(fe);
|
|
||||||
|
/* 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);
|
kfree(fe->analog_demod_priv);
|
||||||
fe->analog_demod_priv = NULL;
|
fe->analog_demod_priv = NULL;
|
||||||
|
|
Loading…
Add table
Reference in a new issue