Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / media / dvb / frontends / cx24123.c
index 691dc84..1e7e790 100644 (file)
@@ -41,14 +41,12 @@ static int debug;
 struct cx24123_state
 {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        const struct cx24123_config* config;
 
        struct dvb_frontend frontend;
 
        u32 lastber;
        u16 snr;
-       u8  lnbreg;
 
        /* Some PLL specifics for tuning */
        u32 VCAarg;
@@ -249,29 +247,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 +270,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);
@@ -458,8 +428,8 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
        u8 pll_mult;
 
        /*  check if symbol rate is within limits */
-       if ((srate > state->ops.info.symbol_rate_max) ||
-           (srate < state->ops.info.symbol_rate_min))
+       if ((srate > state->frontend.ops.info.symbol_rate_max) ||
+           (srate < state->frontend.ops.info.symbol_rate_min))
                return -EOPNOTSUPP;;
 
        /* choose the sampling rate high enough for the required operation,
@@ -579,8 +549,8 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa
        ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff;
        adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f;
 
-       if (adiv == 0)
-               ndiv++;
+       if (adiv == 0 && ndiv > 0)
+               ndiv--;
 
        /* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */
        state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv;
@@ -687,13 +657,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);
 
-       if (state->config->pll_init)
-               state->config->pll_init(fe);
-
-       /* Configure the LNB for 14V */
-       if (state->config->use_isl6421)
-               cx24123_writelnbreg(state, 0x0, 0x2a);
-
        return 0;
 }
 
@@ -702,50 +665,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 & 0x7f);
+       case SEC_VOLTAGE_18:
+               dprintk("%s: setting voltage 18V\n", __FUNCTION__);
+               return cx24123_writereg(state, 0x29, val | 0x80);
+       default:
+               return -EINVAL;
+       };
 
        return 0;
 }
@@ -766,27 +697,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]);
@@ -797,36 +721,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)
@@ -835,7 +756,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;
 }
 
@@ -976,38 +902,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,10 +949,8 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       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;
@@ -1059,7 +966,7 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
        }
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;