diff options
author | Daniel Scheller <d.scheller@gmx.net> | 2017-04-09 16:38:16 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-06-20 09:45:20 -0300 |
commit | c7518d13f70e62e2af3a30858a977365811783df (patch) | |
tree | 219f5defb93f5fbeed611c293b8eb3f0585892cc /drivers/media | |
parent | 050863aac09453d74be9f8b3c6b91fb1af92c5c3 (diff) | |
download | linux-c7518d13f70e62e2af3a30858a977365811783df.tar.bz2 |
[media] dvb-frontends/cxd2841er: make call to i2c_gate_ctrl optional
Some cards/bridges wrap i2c_gate_ctrl handling with a mutex_lock(). This is
e.g. done in ddbridge to protect against concurrent tuner access with
regards to the dual tuner HW, where concurrent tuner reconfiguration can
result in tuning fails or bad reception quality. When the tuner driver
additionally tries to open the I2C gate (which e.g. the tda18212 driver
does) when the demod already did this, this will lead to a deadlock. This
makes the calls to i2c_gatectrl from the demod driver optional when the
flag is set, leaving this to the tuner driver. For readability reasons and
to not have the check duplicated multiple times, the setup is factored
into cxd2841er_tuner_set().
This commit also updates the netup card driver (which seems to be the only
consumer of the cxd2841er as of now).
Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
Acked-by: Abylay Ospan <aospan@netup.ru>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/dvb-frontends/cxd2841er.c | 32 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cxd2841er.h | 2 | ||||
-rw-r--r-- | drivers/media/pci/netup_unidvb/netup_unidvb_core.c | 3 |
3 files changed, 24 insertions, 13 deletions
diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c index 40189a395a67..d0035d2bf88d 100644 --- a/drivers/media/dvb-frontends/cxd2841er.c +++ b/drivers/media/dvb-frontends/cxd2841er.c @@ -327,6 +327,20 @@ static u32 cxd2841er_calc_iffreq(u32 ifhz) return cxd2841er_calc_iffreq_xtal(SONY_XTAL_20500, ifhz); } +static int cxd2841er_tuner_set(struct dvb_frontend *fe) +{ + struct cxd2841er_priv *priv = fe->demodulator_priv; + + if ((priv->flags & CXD2841ER_USE_GATECTRL) && fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe); + if ((priv->flags & CXD2841ER_USE_GATECTRL) && fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +} + static int cxd2841er_dvbs2_set_symbol_rate(struct cxd2841er_priv *priv, u32 symbol_rate) { @@ -3251,12 +3265,9 @@ static int cxd2841er_set_frontend_s(struct dvb_frontend *fe) dev_dbg(&priv->i2c->dev, "%s(): tune failed\n", __func__); goto done; } - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (fe->ops.tuner_ops.set_params) - fe->ops.tuner_ops.set_params(fe); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); + + cxd2841er_tuner_set(fe); + cxd2841er_tune_done(priv); timeout = ((3000000 + (symbol_rate - 1)) / symbol_rate) + 150; for (i = 0; i < timeout / CXD2841ER_DVBS_POLLING_INVL; i++) { @@ -3376,12 +3387,9 @@ static int cxd2841er_set_frontend_tc(struct dvb_frontend *fe) } if (ret) goto done; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (fe->ops.tuner_ops.set_params) - fe->ops.tuner_ops.set_params(fe); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); + + cxd2841er_tuner_set(fe); + cxd2841er_tune_done(priv); timeout = 2500; while (timeout > 0) { diff --git a/drivers/media/dvb-frontends/cxd2841er.h b/drivers/media/dvb-frontends/cxd2841er.h index 2fb8b385c643..15564af1cf92 100644 --- a/drivers/media/dvb-frontends/cxd2841er.h +++ b/drivers/media/dvb-frontends/cxd2841er.h @@ -24,6 +24,8 @@ #include <linux/dvb/frontend.h> +#define CXD2841ER_USE_GATECTRL 1 + enum cxd2841er_xtal { SONY_XTAL_20500, /* 20.5 MHz */ SONY_XTAL_24000, /* 24 MHz */ diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index 9444483fb942..48b9cd773988 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -122,7 +122,8 @@ static void netup_unidvb_queue_cleanup(struct netup_dma *dma); static struct cxd2841er_config demod_config = { .i2c_addr = 0xc8, - .xtal = SONY_XTAL_24000 + .xtal = SONY_XTAL_24000, + .flags = CXD2841ER_USE_GATECTRL }; static struct horus3a_config horus3a_conf = { |