Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] dvb-frontends/stv0367: add flag to make i2c_gatectrl optional

Some hardware and bridges (namely ddbridge) require that tuner access is
limited to one concurrent access and wrap i2c gate control with a
mutex_lock when attaching frontends. According to vendor information, this
is required as concurrent tuner reconfiguration can interfere each other
and at worst cause tuning fails or bad reception quality.

If the demod driver does gate_ctrl before setting up tuner parameters, and
the tuner does another I2C enable, it will deadlock forever when gate_ctrl
is wrapped into the mutex_lock. This adds a flag and a conditional before
triggering gate_ctrl in the demodulator driver.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

authored by

Daniel Scheller and committed by
Mauro Carvalho Chehab
f61c2991 8108f7f4

+12 -4
+12 -4
drivers/media/dvb-frontends/stv0367.c
··· 89 89 struct stv0367cab_state *cab_state; 90 90 /* DVB-T */ 91 91 struct stv0367ter_state *ter_state; 92 + /* flags for operation control */ 93 + u8 use_i2c_gatectrl; 92 94 }; 93 95 94 96 struct st_register { ··· 1829 1827 stv0367ter_init(fe); 1830 1828 1831 1829 if (fe->ops.tuner_ops.set_params) { 1832 - if (fe->ops.i2c_gate_ctrl) 1830 + if (state->use_i2c_gatectrl && fe->ops.i2c_gate_ctrl) 1833 1831 fe->ops.i2c_gate_ctrl(fe, 1); 1834 1832 fe->ops.tuner_ops.set_params(fe); 1835 - if (fe->ops.i2c_gate_ctrl) 1833 + if (state->use_i2c_gatectrl && fe->ops.i2c_gate_ctrl) 1836 1834 fe->ops.i2c_gate_ctrl(fe, 0); 1837 1835 } 1838 1836 ··· 2322 2320 state->fe.ops = stv0367ter_ops; 2323 2321 state->fe.demodulator_priv = state; 2324 2322 state->chip_id = stv0367_readreg(state, 0xf000); 2323 + 2324 + /* demod operation options */ 2325 + state->use_i2c_gatectrl = 1; 2325 2326 2326 2327 dprintk("%s: chip_id = 0x%x\n", __func__, state->chip_id); 2327 2328 ··· 3125 3120 3126 3121 /* Tuner Frequency Setting */ 3127 3122 if (fe->ops.tuner_ops.set_params) { 3128 - if (fe->ops.i2c_gate_ctrl) 3123 + if (state->use_i2c_gatectrl && fe->ops.i2c_gate_ctrl) 3129 3124 fe->ops.i2c_gate_ctrl(fe, 1); 3130 3125 fe->ops.tuner_ops.set_params(fe); 3131 - if (fe->ops.i2c_gate_ctrl) 3126 + if (state->use_i2c_gatectrl && fe->ops.i2c_gate_ctrl) 3132 3127 fe->ops.i2c_gate_ctrl(fe, 0); 3133 3128 } 3134 3129 ··· 3441 3436 state->fe.ops = stv0367cab_ops; 3442 3437 state->fe.demodulator_priv = state; 3443 3438 state->chip_id = stv0367_readreg(state, 0xf000); 3439 + 3440 + /* demod operation options */ 3441 + state->use_i2c_gatectrl = 1; 3444 3442 3445 3443 dprintk("%s: chip_id = 0x%x\n", __func__, state->chip_id); 3446 3444