Commit 48a8a03b authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

[media] cx88: kernel bz#9476: Fix tone setting for Nova-S+ model 92001

Hauppauge Nova-S-Plus DVB-S model 92001 does not lock on horizontal
polarisation. According with the info provided at the BZ, model
92002 does.

The difference is that, on model 92001, the tone select is done via
isl6421, while, on other devices, this is done via cx24123 code.
This patch adds a way to override the demod's set_tone at isl6421
driver. In order to avoid regressions, the override is enabled
only for cx88 Nova S plus model 92001. For all other models and
devices, the set_tone is provided by the demod driver.

Patch originally proposed at bz@9476[1] by Michel Meyers and
John Donoghue but applying the original patch would break support
for all other devices based on isl6421.

[1] https://bugzilla.kernel.org/show_bug.cgi?id=9476Tested-by: default avatarAdam Sampson <ats@offog.org>
Tested-by: default avatarHans-Peter Jansen <hpj@urpla.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent a9bd87c2
...@@ -325,7 +325,7 @@ static int skystar2_rev27_attach(struct flexcop_device *fc, ...@@ -325,7 +325,7 @@ static int skystar2_rev27_attach(struct flexcop_device *fc,
/* enable no_base_addr - no repeated start when reading */ /* enable no_base_addr - no repeated start when reading */
fc->fc_i2c_adap[2].no_base_addr = 1; fc->fc_i2c_adap[2].no_base_addr = 1;
if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
0x08, 1, 1)) { 0x08, 1, 1, false)) {
err("ISL6421 could NOT be attached"); err("ISL6421 could NOT be attached");
goto fail_isl; goto fail_isl;
} }
...@@ -391,7 +391,7 @@ static int skystar2_rev28_attach(struct flexcop_device *fc, ...@@ -391,7 +391,7 @@ static int skystar2_rev28_attach(struct flexcop_device *fc,
fc->fc_i2c_adap[2].no_base_addr = 1; fc->fc_i2c_adap[2].no_base_addr = 1;
if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
0x08, 0, 0)) { 0x08, 0, 0, false)) {
err("ISL6421 could NOT be attached"); err("ISL6421 could NOT be attached");
fc->fc_i2c_adap[2].no_base_addr = 0; fc->fc_i2c_adap[2].no_base_addr = 0;
return 0; return 0;
......
...@@ -89,6 +89,30 @@ static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) ...@@ -89,6 +89,30 @@ static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO; return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
} }
static int isl6421_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0,
.buf = &isl6421->config,
.len = sizeof(isl6421->config) };
switch (tone) {
case SEC_TONE_ON:
isl6421->config |= ISL6421_ENT1;
break;
case SEC_TONE_OFF:
isl6421->config &= ~ISL6421_ENT1;
break;
default:
return -EINVAL;
}
isl6421->config |= isl6421->override_or;
isl6421->config &= isl6421->override_and;
return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
}
static void isl6421_release(struct dvb_frontend *fe) static void isl6421_release(struct dvb_frontend *fe)
{ {
/* power off */ /* power off */
...@@ -100,7 +124,7 @@ static void isl6421_release(struct dvb_frontend *fe) ...@@ -100,7 +124,7 @@ static void isl6421_release(struct dvb_frontend *fe)
} }
struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
u8 override_set, u8 override_clear) u8 override_set, u8 override_clear, bool override_tone)
{ {
struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL); struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
if (!isl6421) if (!isl6421)
...@@ -131,6 +155,8 @@ struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter ...@@ -131,6 +155,8 @@ struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter
/* override frontend ops */ /* override frontend ops */
fe->ops.set_voltage = isl6421_set_voltage; fe->ops.set_voltage = isl6421_set_voltage;
fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage; fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
if (override_tone)
fe->ops.set_tone = isl6421_set_tone;
return fe; return fe;
} }
......
...@@ -42,10 +42,10 @@ ...@@ -42,10 +42,10 @@
#if IS_ENABLED(CONFIG_DVB_ISL6421) #if IS_ENABLED(CONFIG_DVB_ISL6421)
/* override_set and override_clear control which system register bits (above) to always set & clear */ /* override_set and override_clear control which system register bits (above) to always set & clear */
extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
u8 override_set, u8 override_clear); u8 override_set, u8 override_clear, bool override_tone);
#else #else
static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
u8 override_set, u8 override_clear) u8 override_set, u8 override_clear, bool override_tone)
{ {
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL; return NULL;
......
...@@ -2855,6 +2855,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) ...@@ -2855,6 +2855,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
core->board.tuner_type = tv.tuner_type; core->board.tuner_type = tv.tuner_type;
core->tuner_formats = tv.tuner_formats; core->tuner_formats = tv.tuner_formats;
core->board.radio.type = tv.has_radio ? CX88_RADIO : 0; core->board.radio.type = tv.has_radio ? CX88_RADIO : 0;
core->model = tv.model;
/* Make sure we support the board model */ /* Make sure we support the board model */
switch (tv.model) switch (tv.model)
......
...@@ -1042,7 +1042,7 @@ static int dvb_register(struct cx8802_dev *dev) ...@@ -1042,7 +1042,7 @@ static int dvb_register(struct cx8802_dev *dev)
if (!dvb_attach(isl6421_attach, if (!dvb_attach(isl6421_attach,
fe0->dvb.frontend, fe0->dvb.frontend,
&dev->core->i2c_adap, &dev->core->i2c_adap,
0x08, ISL6421_DCL, 0x00)) 0x08, ISL6421_DCL, 0x00, false))
goto frontend_detach; goto frontend_detach;
} }
/* MFE frontend 2 */ /* MFE frontend 2 */
...@@ -1279,8 +1279,16 @@ static int dvb_register(struct cx8802_dev *dev) ...@@ -1279,8 +1279,16 @@ static int dvb_register(struct cx8802_dev *dev)
&hauppauge_novas_config, &hauppauge_novas_config,
&core->i2c_adap); &core->i2c_adap);
if (fe0->dvb.frontend) { if (fe0->dvb.frontend) {
bool override_tone;
if (core->model == 92001)
override_tone = true;
else
override_tone = false;
if (!dvb_attach(isl6421_attach, fe0->dvb.frontend, if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) &core->i2c_adap, 0x08, ISL6421_DCL, 0x00,
override_tone))
goto frontend_detach; goto frontend_detach;
} }
break; break;
...@@ -1403,7 +1411,7 @@ static int dvb_register(struct cx8802_dev *dev) ...@@ -1403,7 +1411,7 @@ static int dvb_register(struct cx8802_dev *dev)
if (!dvb_attach(isl6421_attach, if (!dvb_attach(isl6421_attach,
fe0->dvb.frontend, fe0->dvb.frontend,
&dev->core->i2c_adap, &dev->core->i2c_adap,
0x08, ISL6421_DCL, 0x00)) 0x08, ISL6421_DCL, 0x00, false))
goto frontend_detach; goto frontend_detach;
} }
/* MFE frontend 2 */ /* MFE frontend 2 */
...@@ -1431,7 +1439,7 @@ static int dvb_register(struct cx8802_dev *dev) ...@@ -1431,7 +1439,7 @@ static int dvb_register(struct cx8802_dev *dev)
if (!dvb_attach(isl6421_attach, if (!dvb_attach(isl6421_attach,
fe0->dvb.frontend, fe0->dvb.frontend,
&dev->core->i2c_adap, &dev->core->i2c_adap,
0x08, ISL6421_DCL, 0x00)) 0x08, ISL6421_DCL, 0x00, false))
goto frontend_detach; goto frontend_detach;
} }
break; break;
......
...@@ -334,6 +334,7 @@ struct cx88_core { ...@@ -334,6 +334,7 @@ struct cx88_core {
/* board name */ /* board name */
int nr; int nr;
char name[32]; char name[32];
u32 model;
/* pci stuff */ /* pci stuff */
int pci_bus; int pci_bus;
......
...@@ -1391,8 +1391,9 @@ static int dvb_init(struct saa7134_dev *dev) ...@@ -1391,8 +1391,9 @@ static int dvb_init(struct saa7134_dev *dev)
wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__); wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__);
goto detach_frontend; goto detach_frontend;
} }
if (dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->i2c_adap, if (dvb_attach(isl6421_attach, fe0->dvb.frontend,
0x08, 0, 0) == NULL) { &dev->i2c_adap,
0x08, 0, 0, false) == NULL) {
wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__); wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__);
goto detach_frontend; goto detach_frontend;
} }
...@@ -1509,7 +1510,8 @@ static int dvb_init(struct saa7134_dev *dev) ...@@ -1509,7 +1510,8 @@ static int dvb_init(struct saa7134_dev *dev)
goto detach_frontend; goto detach_frontend;
} }
if (dvb_attach(isl6421_attach, fe0->dvb.frontend, if (dvb_attach(isl6421_attach, fe0->dvb.frontend,
&dev->i2c_adap, 0x08, 0, 0) == NULL) { &dev->i2c_adap,
0x08, 0, 0, false) == NULL) {
wprintk("%s: No ISL6421 found!\n", __func__); wprintk("%s: No ISL6421 found!\n", __func__);
goto detach_frontend; goto detach_frontend;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment