V4L/DVB (4648): Hauppauge Nova-T 500 support added
[linux-2.6.git] / drivers / media / dvb / frontends / dib3000mc.c
index 0b4b822..60e10db 100644 (file)
@@ -169,7 +169,7 @@ static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
        u16 outreg = 0;
        u16 outmode = 0;
        u16 elecout = 1;
-       u16 smo_reg = (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (1 << 1) | 0 ; //smo_mode = 1
+       u16 smo_reg = dib3000mc_read_word(state, 206) & 0x0010; /* keep the pid_parse bit */
 
        dprintk("-I-  Setting output mode for demod %p to %d\n",
                        &state->demod, mode);
@@ -197,7 +197,7 @@ static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
                        P_smo_mode           [2;2:1] = 11
                        P_smo_ovf_prot       [1;0:0] = 0
                        */
-                       smo_reg = (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) |(3 << 1) | 0;
+                       smo_reg |= 3 << 1;
                        fifo_threshold = 512;
                        outmode = 5;
                        break;
@@ -212,7 +212,7 @@ static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
        }
 
        if ((state->cfg->output_mpeg2_in_188_bytes))
-               smo_reg |= (1 << 5) ; //P_smo_rs_discard     [1;5:5] = 1
+               smo_reg |= (1 << 5); // P_smo_rs_discard     [1;5:5] = 1
 
        outreg = dib3000mc_read_word(state, 244) & 0x07FF;
        outreg |= (outmode << 11);
@@ -584,56 +584,6 @@ static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channe
        return 0;
 }
 
-static int dib3000mc_demod_output_mode(struct dvb_frontend *demod, int mode)
-{
-       struct dib3000mc_state *state = demod->demodulator_priv;
-       return dib3000mc_set_output_mode(state, mode);
-}
-
-static int dib3000mc_i2c_enumeration(struct dvb_frontend *demod[], int no_of_demods, u8 default_addr)
-{
-       struct dib3000mc_state *st;
-       int k,ret=0;
-       u8 new_addr;
-
-       static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26};
-
-       for (k = no_of_demods-1; k >= 0; k--) {
-               st = demod[k]->demodulator_priv;
-
-               /* designated i2c address */
-               new_addr          = DIB3000MC_I2C_ADDRESS[k];
-
-               st->i2c_addr = new_addr;
-               if (dib3000mc_identify(st) != 0) {
-                       st->i2c_addr = default_addr;
-                       if (dib3000mc_identify(st) != 0) {
-                               dprintk("-E-  DiB3000P/MC #%d: not identified\n", k);
-                               return -EINVAL;
-                       }
-               }
-
-               /* turn on div_out */
-               dib3000mc_demod_output_mode(demod[k], OUTMODE_MPEG2_PAR_CONT_CLK);
-
-               // set new i2c address and force divstr (Bit 1) to value 0 (Bit 0)
-               ret |= dib3000mc_write_word(st, 1024, (new_addr << 3) | 0x1);
-               st->i2c_addr = new_addr;
-       }
-
-       for (k = 0; k < no_of_demods; k++) {
-               st = demod[k]->demodulator_priv;
-
-               ret |= dib3000mc_write_word(st, 1024, st->i2c_addr << 3);
-
-               /* turn off data output */
-               dib3000mc_demod_output_mode(demod[k],OUTMODE_HIGH_Z);
-               dib3000mc_write_word(st, 769, (1 << 7) );
-
-       }
-       return 0;
-}
-
 struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating)
 {
        struct dib3000mc_state *st = demod->demodulator_priv;
@@ -826,61 +776,77 @@ void dib3000mc_set_config(struct dvb_frontend *fe, struct dib3000mc_config *cfg)
 }
 EXPORT_SYMBOL(dib3000mc_set_config);
 
-static struct dvb_frontend_ops dib3000mc_ops;
-
-int dib3000mc_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8        default_addr,                           u8 do_i2c_enum, struct dib3000mc_config cfg[], struct dvb_frontend *demod[])
+int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[])
 {
-       struct dib3000mc_state *st;
-       int k, num=0;
-
-       if (no_of_demods < 1)
-               return -EINVAL;
+       struct dib3000mc_state st = { .i2c_adap = i2c };
+       int k;
+       u8 new_addr;
 
-       for (k = 0; k < no_of_demods; k++) {
-               st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
-               if (st == NULL)
-                       goto error;
+       static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26};
 
-               num++;
+       for (k = no_of_demods-1; k >= 0; k--) {
+               st.cfg = &cfg[k];
 
-               st->cfg = &cfg[k];
-       //      st->gpio_val = cfg[k].gpio_val;
-       //      st->gpio_dir = cfg[k].gpio_dir;
-               st->i2c_adap = i2c_adap;
+               /* designated i2c address */
+               new_addr          = DIB3000MC_I2C_ADDRESS[k];
+               st.i2c_addr = new_addr;
+               if (dib3000mc_identify(&st) != 0) {
+                       st.i2c_addr = default_addr;
+                       if (dib3000mc_identify(&st) != 0) {
+                               dprintk("-E-  DiB3000P/MC #%d: not identified\n", k);
+                               return -ENODEV;
+                       }
+               }
 
-               demod[k]           = &st->demod;
-               demod[k]->demodulator_priv     = st;
-               memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
+               dib3000mc_set_output_mode(&st, OUTMODE_MPEG2_PAR_CONT_CLK);
 
-//             INIT_COMPONENT_REGISTER_ACCESS(&st->register_access, 12, 16, dib7000p_register_read, dib7000p_register_write, st);
-//             demod[k]->register_access = &st->register_access;
+               // set new i2c address and force divstr (Bit 1) to value 0 (Bit 0)
+               dib3000mc_write_word(&st, 1024, (new_addr << 3) | 0x1);
+               st.i2c_addr = new_addr;
        }
 
-       if (do_i2c_enum) {
-               if (dib3000mc_i2c_enumeration(demod,no_of_demods,default_addr) != 0)
-                       goto error;
-       } else {
-               st = demod[0]->demodulator_priv;
-               st->i2c_addr = default_addr;
-               if (dib3000mc_identify(st) != 0)
-                       goto error;
-       }
+       for (k = 0; k < no_of_demods; k++) {
+               st.cfg = &cfg[k];
+               st.i2c_addr = DIB3000MC_I2C_ADDRESS[k];
 
-       for (k = 0; k < num; k++) {
-               st = demod[k]->demodulator_priv;
-               dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);
-       }
+               dib3000mc_write_word(&st, 1024, st.i2c_addr << 3);
 
+               /* turn off data output */
+               dib3000mc_set_output_mode(&st, OUTMODE_HIGH_Z);
+       }
        return 0;
+}
+EXPORT_SYMBOL(dib3000mc_i2c_enumeration);
+
+static struct dvb_frontend_ops dib3000mc_ops;
+
+struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
+{
+       struct dvb_frontend *demod;
+       struct dib3000mc_state *st;
+       st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
+       if (st == NULL)
+               return NULL;
+
+       st->cfg = cfg;
+       st->i2c_adap = i2c_adap;
+       st->i2c_addr = i2c_addr;
+
+       demod                   = &st->demod;
+       demod->demodulator_priv = st;
+       memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
+
+       if (dib3000mc_identify(st) != 0)
+               goto error;
+
+       dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);
+
+       return demod;
 
 error:
-       for (k = 0; k < num; k++) {
-               kfree(demod[k]->demodulator_priv);
-               demod[k] = NULL;
-       }
-       return -EINVAL;
+       kfree(st);
+       return NULL;
 }
-
 EXPORT_SYMBOL(dib3000mc_attach);
 
 static struct dvb_frontend_ops dib3000mc_ops = {