]> err.no Git - linux-2.6/commitdiff
V4L/DVB (4012): Fix cx24123 diseqc
authorAndrew de Quincey <adq_dvb@lidskialf.net>
Fri, 12 May 2006 23:31:51 +0000 (20:31 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Sun, 25 Jun 2006 05:00:21 +0000 (02:00 -0300)
Rework diseqc support to be more in line with the other demod drivers.
Fix Nova-S-Plus/Nova-SE2 diseqc.
Cleanup API.

Signed-off-by: Andrew de Quincey <adq_dvb@lidskialf.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/dvb/frontends/cx24123.c
drivers/media/dvb/frontends/cx24123.h
drivers/media/video/cx88/Kconfig
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88.h

index aa3fd8e6cef7a56452c706ff34ef50530b66a520..c714229640647b7a935e1904922b77154771dccc 100644 (file)
@@ -48,7 +48,6 @@ struct cx24123_state
 
        u32 lastber;
        u16 snr;
-       u8  lnbreg;
 
        /* Some PLL specifics for tuning */
        u32 VCAarg;
@@ -249,29 +248,6 @@ static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
        return 0;
 }
 
-static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data)
-{
-       u8 buf[] = { reg, data };
-       /* fixme: put the intersil addr int the config */
-       struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 };
-       int err;
-
-       if (debug>1)
-               printk("cx24123: %s:  writeln addr=0x08, reg 0x%02x, value 0x%02x\n",
-                                               __FUNCTION__,reg, data);
-
-       if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-               printk("%s: writelnbreg error (err == %i, reg == 0x%02x,"
-                        " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
-               return -EREMOTEIO;
-       }
-
-       /* cache the write, no way to read back */
-       state->lnbreg = data;
-
-       return 0;
-}
-
 static int cx24123_readreg(struct cx24123_state* state, u8 reg)
 {
        int ret;
@@ -295,11 +271,6 @@ static int cx24123_readreg(struct cx24123_state* state, u8 reg)
        return b1[0];
 }
 
-static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
-{
-       return state->lnbreg;
-}
-
 static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
 {
        u8 nom_reg = cx24123_readreg(state, 0x0e);
@@ -687,10 +658,6 @@ static int cx24123_initfe(struct dvb_frontend* fe)
        for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
                cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
 
-       /* Configure the LNB for 14V */
-       if (state->config->use_isl6421)
-               cx24123_writelnbreg(state, 0x0, 0x2a);
-
        return 0;
 }
 
@@ -699,50 +666,18 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
        struct cx24123_state *state = fe->demodulator_priv;
        u8 val;
 
-       switch (state->config->use_isl6421) {
-
-       case 1:
+       val = cx24123_readreg(state, 0x29) & ~0x40;
 
-               val = cx24123_readlnbreg(state, 0x0);
-
-               switch (voltage) {
-               case SEC_VOLTAGE_13:
-                       dprintk("%s:  isl6421 voltage = 13V\n",__FUNCTION__);
-                       return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */
-               case SEC_VOLTAGE_18:
-                       dprintk("%s:  isl6421 voltage = 18V\n",__FUNCTION__);
-                       return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */
-               case SEC_VOLTAGE_OFF:
-                       dprintk("%s:  isl5421 voltage off\n",__FUNCTION__);
-                       return cx24123_writelnbreg(state, 0x0, val & 0x30);
-               default:
-                       return -EINVAL;
-               };
-
-       case 0:
-
-               val = cx24123_readreg(state, 0x29);
-
-               switch (voltage) {
-               case SEC_VOLTAGE_13:
-                       dprintk("%s: setting voltage 13V\n", __FUNCTION__);
-                       if (state->config->enable_lnb_voltage)
-                               state->config->enable_lnb_voltage(fe, 1);
-                       return cx24123_writereg(state, 0x29, val | 0x80);
-               case SEC_VOLTAGE_18:
-                       dprintk("%s: setting voltage 18V\n", __FUNCTION__);
-                       if (state->config->enable_lnb_voltage)
-                               state->config->enable_lnb_voltage(fe, 1);
-                       return cx24123_writereg(state, 0x29, val & 0x7f);
-               case SEC_VOLTAGE_OFF:
-                       dprintk("%s: setting voltage off\n", __FUNCTION__);
-                       if (state->config->enable_lnb_voltage)
-                               state->config->enable_lnb_voltage(fe, 0);
-                       return 0;
-               default:
-                       return -EINVAL;
-               };
-       }
+       switch (voltage) {
+       case SEC_VOLTAGE_13:
+               dprintk("%s: setting voltage 13V\n", __FUNCTION__);
+               return cx24123_writereg(state, 0x29, val | 0x80);
+       case SEC_VOLTAGE_18:
+               dprintk("%s: setting voltage 18V\n", __FUNCTION__);
+               return cx24123_writereg(state, 0x29, val & 0x7f);
+       default:
+               return -EINVAL;
+       };
 
        return 0;
 }
@@ -763,27 +698,20 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
 static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
 {
        struct cx24123_state *state = fe->demodulator_priv;
-       int i, val;
+       int i, val, tone;
 
        dprintk("%s:\n",__FUNCTION__);
 
-       /* check if continuous tone has been stopped */
-       if (state->config->use_isl6421)
-               val = cx24123_readlnbreg(state, 0x00) & 0x10;
-       else
-               val = cx24123_readreg(state, 0x29) & 0x10;
-
-
-       if (val) {
-               printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
-               return -ENOTSUPP;
-       }
+       /* stop continuous tone if enabled */
+       tone = cx24123_readreg(state, 0x29);
+       if (tone & 0x10)
+               cx24123_writereg(state, 0x29, tone & ~0x50);
 
        /* wait for diseqc queue ready */
        cx24123_wait_for_diseqc(state);
 
        /* select tone mode */
-       cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8);
+       cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
 
        for (i = 0; i < cmd->msg_len; i++)
                cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
@@ -794,36 +722,33 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
        /* wait for diseqc message to finish sending */
        cx24123_wait_for_diseqc(state);
 
+       /* restart continuous tone if enabled */
+       if (tone & 0x10) {
+               cx24123_writereg(state, 0x29, tone & ~0x40);
+       }
+
        return 0;
 }
 
 static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
 {
        struct cx24123_state *state = fe->demodulator_priv;
-       int val;
+       int val, tone;
 
        dprintk("%s:\n", __FUNCTION__);
 
-       /* check if continuous tone has been stoped */
-       if (state->config->use_isl6421)
-               val = cx24123_readlnbreg(state, 0x00) & 0x10;
-       else
-               val = cx24123_readreg(state, 0x29) & 0x10;
-
-
-       if (val) {
-               printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
-               return -ENOTSUPP;
-       }
+       /* stop continuous tone if enabled */
+       tone = cx24123_readreg(state, 0x29);
+       if (tone & 0x10)
+               cx24123_writereg(state, 0x29, tone & ~0x50);
 
+       /* wait for diseqc queue ready */
        cx24123_wait_for_diseqc(state);
 
        /* select tone mode */
-       val = cx24123_readreg(state, 0x2a) & 0xf8;
-       cx24123_writereg(state, 0x2a, val | 0x04);
-
+       cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) | 0x4);
+       msleep(30);
        val = cx24123_readreg(state, 0x29);
-
        if (burst == SEC_MINI_A)
                cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00));
        else if (burst == SEC_MINI_B)
@@ -832,7 +757,12 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
                return -EINVAL;
 
        cx24123_wait_for_diseqc(state);
+       cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
 
+       /* restart continuous tone if enabled */
+       if (tone & 0x10) {
+               cx24123_writereg(state, 0x29, tone & ~0x40);
+       }
        return 0;
 }
 
@@ -973,38 +903,21 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
        struct cx24123_state *state = fe->demodulator_priv;
        u8 val;
 
-       switch (state->config->use_isl6421) {
-       case 1:
-
-               val = cx24123_readlnbreg(state, 0x0);
-
-               switch (tone) {
-               case SEC_TONE_ON:
-                       dprintk("%s:  isl6421 sec tone on\n",__FUNCTION__);
-                       return cx24123_writelnbreg(state, 0x0, val | 0x10);
-               case SEC_TONE_OFF:
-                       dprintk("%s:  isl6421 sec tone off\n",__FUNCTION__);
-                       return cx24123_writelnbreg(state, 0x0, val & 0x2f);
-               default:
-                       printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
-                       return -EINVAL;
-               }
-
-       case 0:
+       /* wait for diseqc queue ready */
+       cx24123_wait_for_diseqc(state);
 
-               val = cx24123_readreg(state, 0x29);
+       val = cx24123_readreg(state, 0x29) & ~0x40;
 
-               switch (tone) {
-               case SEC_TONE_ON:
-                       dprintk("%s: setting tone on\n", __FUNCTION__);
-                       return cx24123_writereg(state, 0x29, val | 0x10);
-               case SEC_TONE_OFF:
-                       dprintk("%s: setting tone off\n",__FUNCTION__);
-                       return cx24123_writereg(state, 0x29, val & 0xef);
-               default:
-                       printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
-                       return -EINVAL;
-               }
+       switch (tone) {
+       case SEC_TONE_ON:
+               dprintk("%s: setting tone on\n", __FUNCTION__);
+               return cx24123_writereg(state, 0x29, val | 0x10);
+       case SEC_TONE_OFF:
+               dprintk("%s: setting tone off\n",__FUNCTION__);
+               return cx24123_writereg(state, 0x29, val & 0xef);
+       default:
+               printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+               return -EINVAL;
        }
 
        return 0;
@@ -1040,7 +953,6 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
        memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
        state->lastber = 0;
        state->snr = 0;
-       state->lnbreg = 0;
        state->VCAarg = 0;
        state->VGAarg = 0;
        state->bandselectarg = 0;
index 7ec4ee856014a4c753ed922515c29f4f03e95d16..9606f825935c8341f53b760e9c91f06e4146e9a8 100644 (file)
@@ -28,17 +28,8 @@ struct cx24123_config
        /* the demodulator's i2c address */
        u8 demod_address;
 
-       /*
-          cards like Hauppauge Nova-S Plus/Nova-SE2 use an Intersil ISL6421 chip
-          for LNB control, while KWorld DVB-S 100 use the LNBDC and LNBTone bits
-          from register 0x29 of the CX24123 demodulator
-       */
-       int use_isl6421;
-
        /* Need to set device param for start_dma */
        int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
-
-       void (*enable_lnb_voltage)(struct dvb_frontend* fe, int on);
 };
 
 extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
index 630273992a419b05986bd00a462366db212709f4..c092d2219f0b69895f9dabd070a8e4dc9527fc8f 100644 (file)
@@ -61,6 +61,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS
        select DVB_LGDT330X
        select DVB_NXT200X
        select DVB_CX24123
+       select DVB_ISL6421
        ---help---
          This builds cx88-dvb with all currently supported frontend
          demodulators.  If you wish to tweak your configuration, and
@@ -139,6 +140,7 @@ config VIDEO_CX88_DVB_CX24123
        default y
        depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
        select DVB_CX24123
+       select DVB_ISL6421
        ---help---
          This adds DVB-S support for cards based on the
          Connexant 2388x chip and the CX24123 demodulator.
index ce225202f327f16b2df365a660c3b895e078388b..4d369f8393d98aac80bc6197b8c1f3d3afc66dce 100644 (file)
@@ -59,6 +59,7 @@
 #ifdef HAVE_CX24123
 # include "cx24123.h"
 #endif
+#include "isl6421.h"
 
 MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -479,28 +480,30 @@ static int cx24123_set_ts_param(struct dvb_frontend* fe,
        return 0;
 }
 
-static void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on)
+static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
 {
        struct cx8802_dev *dev= fe->dvb->priv;
        struct cx88_core *core = dev->core;
 
-       if (on)
-               cx_write(MO_GP0_IO, 0x000006f9);
-       else
+       if (voltage == SEC_VOLTAGE_OFF) {
                cx_write(MO_GP0_IO, 0x000006fB);
+       } else {
+               cx_write(MO_GP0_IO, 0x000006f9);
+       }
+
+       if (core->prev_set_voltage)
+               return core->prev_set_voltage(fe, voltage);
+       return 0;
 }
 
 static struct cx24123_config hauppauge_novas_config = {
        .demod_address          = 0x55,
-       .use_isl6421            = 1,
        .set_ts_params          = cx24123_set_ts_param,
 };
 
 static struct cx24123_config kworld_dvbs_100_config = {
        .demod_address          = 0x15,
-       .use_isl6421            = 0,
        .set_ts_params          = cx24123_set_ts_param,
-       .enable_lnb_voltage     = cx24123_enable_lnb_voltage,
 };
 #endif
 
@@ -710,10 +713,17 @@ static int dvb_register(struct cx8802_dev *dev)
        case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
                dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config,
                        &dev->core->i2c_adap);
+               if (dev->dvb.frontend) {
+                       isl6421_attach(dev->dvb.frontend, &dev->core->i2c_adap, 0x08, 0x00, 0x00);
+               }
                break;
        case CX88_BOARD_KWORLD_DVBS_100:
                dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config,
                        &dev->core->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->core->prev_set_voltage = dev->dvb.frontend->ops->set_voltage;
+                       dev->dvb.frontend->ops->set_voltage = kworld_dvbs_100_set_voltage;
+               }
                break;
 #endif
        default:
index 8413e54ef4b8bfdb731291f5dc1052912e534613..411bb9f39c779495a100989cd4cff609f2079fea 100644 (file)
@@ -298,6 +298,7 @@ struct cx88_core {
        /* config info -- dvb */
        struct dvb_pll_desc        *pll_desc;
        unsigned int               pll_addr;
+       int                        (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
 
        /* state info */
        struct task_struct         *kthread;