[media] cx88: kernel bz#9476: Fix tone setting for Nova-S+ model 92001
authorMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 5 Apr 2013 15:18:54 +0000 (12:18 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 8 Apr 2013 09:56:47 +0000 (06:56 -0300)
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=9476

Tested-by: Adam Sampson <ats@offog.org>
Tested-by: Hans-Peter Jansen <hpj@urpla.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/common/b2c2/flexcop-fe-tuner.c
drivers/media/dvb-frontends/isl6421.c
drivers/media/dvb-frontends/isl6421.h
drivers/media/pci/cx88/cx88-cards.c
drivers/media/pci/cx88/cx88-dvb.c
drivers/media/pci/cx88/cx88.h
drivers/media/pci/saa7134/saa7134-dvb.c

index 850a6c606750240f502f82bdf25ca1ce3b675dc0..7e14e90d292233f70fc63ba13c5e356d862f27b5 100644 (file)
@@ -325,7 +325,7 @@ static int skystar2_rev27_attach(struct flexcop_device *fc,
        /* enable no_base_addr - no repeated start when reading */
        fc->fc_i2c_adap[2].no_base_addr = 1;
        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");
                goto fail_isl;
        }
@@ -391,7 +391,7 @@ static int skystar2_rev28_attach(struct flexcop_device *fc,
 
        fc->fc_i2c_adap[2].no_base_addr = 1;
        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");
                fc->fc_i2c_adap[2].no_base_addr = 0;
                return 0;
index 0cb3f0f74c9c9040b48f586212fae0680ad02145..c77002fcc8e2212fb825afb22a022a98fa873378 100644 (file)
@@ -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;
 }
 
+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)
 {
        /* power off */
@@ -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,
-                  u8 override_set, u8 override_clear)
+                  u8 override_set, u8 override_clear, bool override_tone)
 {
        struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
        if (!isl6421)
@@ -131,6 +155,8 @@ struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter
        /* override frontend ops */
        fe->ops.set_voltage = isl6421_set_voltage;
        fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
+       if (override_tone)
+               fe->ops.set_tone = isl6421_set_tone;
 
        return fe;
 }
index e7ca7d12b50a5432d239d1db5184caebce9584f2..630e7f8a150e64f650cc4c492f8396e577810565 100644 (file)
 #if IS_ENABLED(CONFIG_DVB_ISL6421)
 /* 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,
-                         u8 override_set, u8 override_clear);
+                         u8 override_set, u8 override_clear, bool override_tone);
 #else
 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__);
        return NULL;
index e2e0b8faf7a4021cb476c0c5e3a54f558bba0ca6..07b700a9ed7f0300513ec0188e09402697a8d90a 100644 (file)
@@ -2855,6 +2855,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
        core->board.tuner_type = tv.tuner_type;
        core->tuner_formats = tv.tuner_formats;
        core->board.radio.type = tv.has_radio ? CX88_RADIO : 0;
+       core->model = tv.model;
 
        /* Make sure we support the board model */
        switch (tv.model)
index 672b267a2d3ebdc598416dff8ed8e64bee67f1e4..053ed1ba1d85f34810b37dd78681d2cd5b9541e4 100644 (file)
@@ -1042,7 +1042,7 @@ static int dvb_register(struct cx8802_dev *dev)
                        if (!dvb_attach(isl6421_attach,
                                        fe0->dvb.frontend,
                                        &dev->core->i2c_adap,
-                                       0x08, ISL6421_DCL, 0x00))
+                                       0x08, ISL6421_DCL, 0x00, false))
                                goto frontend_detach;
                }
                /* MFE frontend 2 */
@@ -1279,8 +1279,16 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &hauppauge_novas_config,
                                               &core->i2c_adap);
                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,
-                                       &core->i2c_adap, 0x08, ISL6421_DCL, 0x00))
+                                       &core->i2c_adap, 0x08, ISL6421_DCL, 0x00,
+                                       override_tone))
                                goto frontend_detach;
                }
                break;
@@ -1403,7 +1411,7 @@ static int dvb_register(struct cx8802_dev *dev)
                        if (!dvb_attach(isl6421_attach,
                                        fe0->dvb.frontend,
                                        &dev->core->i2c_adap,
-                                       0x08, ISL6421_DCL, 0x00))
+                                       0x08, ISL6421_DCL, 0x00, false))
                                goto frontend_detach;
                }
                /* MFE frontend 2 */
@@ -1431,7 +1439,7 @@ static int dvb_register(struct cx8802_dev *dev)
                        if (!dvb_attach(isl6421_attach,
                                        fe0->dvb.frontend,
                                        &dev->core->i2c_adap,
-                                       0x08, ISL6421_DCL, 0x00))
+                                       0x08, ISL6421_DCL, 0x00, false))
                                goto frontend_detach;
                }
                break;
index eca02c2435def04f1fea7dd07993904445f10bf2..4e29c9deb684f88d3995e1f79f143d10d59085b2 100644 (file)
@@ -334,6 +334,7 @@ struct cx88_core {
        /* board name */
        int                        nr;
        char                       name[32];
+       u32                        model;
 
        /* pci stuff */
        int                        pci_bus;
index 27915e501db9d3bbcdb3944a4bf8237ef9254ba0..45271390d7fbaa0835a1b250afc0fd63fe14a6a0 100644 (file)
@@ -1391,8 +1391,9 @@ static int dvb_init(struct saa7134_dev *dev)
                                        wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__);
                                        goto detach_frontend;
                                }
-                               if (dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->i2c_adap,
-                                                                               0x08, 0, 0) == NULL) {
+                               if (dvb_attach(isl6421_attach, fe0->dvb.frontend,
+                                              &dev->i2c_adap,
+                                              0x08, 0, 0, false) == NULL) {
                                        wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__);
                                        goto detach_frontend;
                                }
@@ -1509,7 +1510,8 @@ static int dvb_init(struct saa7134_dev *dev)
                                goto detach_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__);
                                goto detach_frontend;
                        }