diff options
author | Patrick Boettcher <devnull@localhost> | 2004-09-05 20:13:07 +0000 |
---|---|---|
committer | Patrick Boettcher <devnull@localhost> | 2004-09-05 20:13:07 +0000 |
commit | 58a6c6dc6a1cea3ba3a6a1c7a4cc0e36640f87e5 (patch) | |
tree | 755c293a3fb40cd07e028085a6d7a85130029282 | |
parent | 71f6ea3ca21cf22dbb9b12cdc154fc653c11d5bd (diff) | |
download | mediapointer-dvb-s2-58a6c6dc6a1cea3ba3a6a1c7a4cc0e36640f87e5.tar.gz mediapointer-dvb-s2-58a6c6dc6a1cea3ba3a6a1c7a4cc0e36640f87e5.tar.bz2 |
added some more ioctl calls, modified the SET_FRONTED behaviour.
-rw-r--r-- | linux/drivers/media/dvb/frontends/dib3000mb.c | 272 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/dib3000mb.h | 6 |
2 files changed, 232 insertions, 46 deletions
diff --git a/linux/drivers/media/dvb/frontends/dib3000mb.c b/linux/drivers/media/dvb/frontends/dib3000mb.c index 05adffa1d..5e2276ef2 100644 --- a/linux/drivers/media/dvb/frontends/dib3000mb.c +++ b/linux/drivers/media/dvb/frontends/dib3000mb.c @@ -57,7 +57,8 @@ static struct dvb_frontend_info dib3000mb_info = { .frequency_min = 44250000, .frequency_max = 867250000, .frequency_stepsize = 62500, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | @@ -138,13 +139,18 @@ struct dib3000mb_fe_param { u16 cr; u16 inv; u16 seq; - u8 qam_vit_auto; + u8 qam_vit_manual; }; static int dib3000mb_fe_set_parameters(struct dib3000mb_state *state, struct dib3000mb_fe_param *p) { struct i2c_client *i2c = state->i2c; + + wr(DIB3000MB_REG_LOCK1_MASK,DIB3000MB_LOCK1_SEARCH_4); + + dprintk("inversion: %d, seq: %d\n",p->inv,p->seq); + wr(DIB3000MB_REG_FFT,p->fft); wr(DIB3000MB_REG_GUARD_TIME,p->guard); wr(DIB3000MB_REG_DDS_INV,p->inv); @@ -165,7 +171,7 @@ static int dib3000mb_fe_set_parameters(struct dib3000mb_state *state, wr(DIB3000MB_REG_UNK_121,DIB3000MB_UNK_121_DEFAULT); } - if (p->qam_vit_auto) { + if (p->qam_vit_manual) { wr(DIB3000MB_REG_QAM,p->qam); wr(DIB3000MB_REG_VIT_ALPHA,p->alpha); wr(DIB3000MB_REG_VIT_HRCH,p->hrch); @@ -189,25 +195,6 @@ static int dib3000mb_fe_read_search_status(struct dib3000mb_state *state) irq = rd(DIB3000MB_REG_AS_IRQ_PENDING); if (irq & 0x02) { - if (rd(DIB3000MB_REG_TPS_LOCK)) { - p.qam = rd(DIB3000MB_REG_TPS_QAM); - p.hrch = rd(DIB3000MB_REG_TPS_HRCH); - p.alpha = rd(DIB3000MB_REG_TPS_VIT_ALPHA); - p.hp = !p.hrch; - p.cr = p.hp ? rd(DIB3000MB_REG_TPS_CODE_RATE_HP) : - rd(DIB3000MB_REG_TPS_CODE_RATE_LP); - p.guard = rd(DIB3000MB_REG_TPS_GUARD_TIME); - p.fft = rd(DIB3000MB_REG_TPS_FFT); - p.seq = 0; - p.qam_vit_auto = 0; - p.inv = 1; - -// dib3000mb_fe_set_parameters(state,&p); - -// wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_CTRL); -// wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_OFF); - } - dprintk("autoval: tps: %d, qam: %d, hrch: %d, alpha: %d, hp: %d, lp: %d, guard: %d, fft: %d cell: %d\n", rd(DIB3000MB_REG_TPS_LOCK), rd(DIB3000MB_REG_TPS_QAM), @@ -219,11 +206,51 @@ static int dib3000mb_fe_read_search_status(struct dib3000mb_state *state) rd(DIB3000MB_REG_TPS_FFT), rd(DIB3000MB_REG_TPS_CELL_ID)); - if (rd(DIB3000MB_REG_LOCK2_VALUE)) + if (rd(DIB3000MB_REG_TPS_LOCK) && rd(DIB3000MB_REG_LOCK2_VALUE)) { + int inv_test1,inv_test2; + u32 dds_val, threshold = 0x800000; + + p.qam = rd(DIB3000MB_REG_TPS_QAM); + p.hrch = rd(DIB3000MB_REG_TPS_HRCH); + p.alpha = rd(DIB3000MB_REG_TPS_VIT_ALPHA); + p.hp = !p.hrch; + p.cr = p.hp ? rd(DIB3000MB_REG_TPS_CODE_RATE_HP) : + rd(DIB3000MB_REG_TPS_CODE_RATE_LP); + p.guard = rd(DIB3000MB_REG_TPS_GUARD_TIME); + p.fft = rd(DIB3000MB_REG_TPS_FFT); + p.seq = 0; + p.qam_vit_manual = 0; + + dds_val = (rd(DIB3000MB_REG_DDS_VALUE_MSB & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB); + if (dds_val & threshold) + inv_test1 = 0; + else if (dds_val == threshold) + inv_test1 = 1; + else + inv_test1 = 2; + + dds_val = (rd(DIB3000MB_REG_DDS_FREQ_MSB & 0xff) << 16) + rd(DIB3000MB_REG_DDS_FREQ_LSB); + if (dds_val & threshold) + inv_test2 = 0; + else if (dds_val == threshold) + inv_test2 = 1; + else + inv_test2 = 2; + + p.inv = ((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) + || + ((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)); + + dib3000mb_fe_set_parameters(state,&p); + + wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_CTRL); + wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_OFF); + + msleep(70); + return 1; - else + } else return 0; - } else if (irq & 0x01) return 0; @@ -238,16 +265,10 @@ static int dib3000mb_set_frontend(struct dib3000mb_state *state, fe_code_rate_t fe_cr; struct dib3000mb_fe_param par; - par.seq = dib3000mb_seq - [ofdm->transmission_mode == TRANSMISSION_MODE_AUTO] - [ofdm->guard_interval == GUARD_INTERVAL_AUTO] - [1]; - - dprintk("Auto search will be enabled? %d\n",par.seq); - wr(DIB3000MB_REG_TUNER, DIB3000MB_ACTIVATE_TUNER_XFER( DIB3000MB_TUNER_ADDR_DEFAULT ) ); dib3000mb_tuner_thomson_cable_eu(state,fep->frequency); + /* wait for tuner */ msleep(1); wr(DIB3000MB_REG_TUNER, @@ -273,8 +294,6 @@ static int dib3000mb_set_frontend(struct dib3000mb_state *state, break; } - wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4); - switch (ofdm->transmission_mode) { case TRANSMISSION_MODE_2K: par.fft = DIB3000MB_FFT_2K; @@ -309,12 +328,18 @@ static int dib3000mb_set_frontend(struct dib3000mb_state *state, return -EINVAL; } - par.inv = DIB3000MB_DDS_INV_OFF; - - par.qam_vit_auto = (ofdm->constellation != QAM_AUTO && - ofdm->hierarchy_information != HIERARCHY_AUTO && - ofdm->code_rate_HP != FEC_AUTO && - ofdm->code_rate_LP != FEC_AUTO); + switch (fep->inversion) { + case INVERSION_OFF: + par.inv = DIB3000MB_DDS_INV_OFF; + break; + case INVERSION_AUTO: + case INVERSION_ON: + par.inv = DIB3000MB_DDS_INV_ON; + break; + default: + return -EINVAL; + } + switch (ofdm->constellation) { case QPSK: par.qam = DIB3000MB_QAM_QPSK; @@ -383,6 +408,18 @@ static int dib3000mb_set_frontend(struct dib3000mb_state *state, default: return -EINVAL; } + + par.seq = dib3000mb_seq + [ofdm->transmission_mode == TRANSMISSION_MODE_AUTO] + [ofdm->guard_interval == GUARD_INTERVAL_AUTO] + [fep->inversion == INVERSION_AUTO]; + + par.qam_vit_manual = (ofdm->constellation != QAM_AUTO && + ofdm->hierarchy_information != HIERARCHY_AUTO && + ofdm->code_rate_HP != FEC_AUTO && + ofdm->code_rate_LP != FEC_AUTO); + + dprintk("auto search will be enabled? %d %d\n",par.seq,!par.qam_vit_manual); dib3000mb_fe_set_parameters(state,&par); @@ -393,23 +430,145 @@ static int dib3000mb_set_frontend(struct dib3000mb_state *state, wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_AGC+DIB3000MB_RESTART_CTRL); wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_OFF); + /* wait for AGC lock */ msleep(70); wr_foreach(dib3000mb_reg_agc_bandwidth,dib3000mb_agc_bandwidth_low); - wr(DIB3000MB_REG_ISI,DIB3000MB_ISI_INHIBIT); - wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_AUTO_SEARCH); - wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_OFF); + /* something has to be auto searched */ + if (par.seq || !par.qam_vit_manual) { + wr(DIB3000MB_REG_ISI,DIB3000MB_ISI_INHIBIT); + wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_AUTO_SEARCH); + wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_OFF); + } else { + wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_CTRL); + wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_OFF); + } + if (ofdm->constellation != QAM_AUTO && + ofdm->transmission_mode != TRANSMISSION_MODE_AUTO && + ofdm->guard_interval != GUARD_INTERVAL_AUTO && + fep->inversion != INVERSION_AUTO) { + wr(DIB3000MB_REG_LOCK1_MASK,DIB3000MB_LOCK1_SEARCH_2048); + } + while (dib3000mb_fe_read_search_status(state) < 0); return 0; } + +static int dib3000mb_get_frontend(struct dib3000mb_state *state, + struct dvb_frontend_parameters *fep) +{ + struct i2c_client *i2c = state->i2c; + struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm; + fe_code_rate_t *cr; + u16 tps_val; + + if (!rd(DIB3000MB_REG_TPS_LOCK)) + return -EINVAL; + + switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) { + case DIB3000MB_QAM_QPSK: + ofdm->constellation = QPSK; + break; + case DIB3000MB_QAM_QAM16: + ofdm->constellation = QAM_16; + break; + case DIB3000MB_QAM_QAM64: + ofdm->constellation = QAM_64; + break; + default: + err("Unexpected constellation returned by TPS (%d)",tps_val); + break; + } + + if (rd(DIB3000MB_REG_TPS_HRCH)) { + tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP); + cr = &ofdm->code_rate_LP; + ofdm->code_rate_HP = FEC_NONE; + + switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) { + case DIB3000MB_VIT_ALPHA_OFF: + ofdm->hierarchy_information = HIERARCHY_NONE; + break; + case DIB3000MB_VIT_ALPHA_1: + ofdm->hierarchy_information = HIERARCHY_1; + break; + case DIB3000MB_VIT_ALPHA_2: + ofdm->hierarchy_information = HIERARCHY_2; + break; + case DIB3000MB_VIT_ALPHA_4: + ofdm->hierarchy_information = HIERARCHY_4; + break; + default: + err("Unexpected ALPHA value returned by TPS (%d)",tps_val); + } + } else { + tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP); + cr = &ofdm->code_rate_HP; + ofdm->code_rate_LP = FEC_NONE; + ofdm->hierarchy_information = HIERARCHY_NONE; + } + switch (tps_val) { + case DIB3000MB_FEC_1_2: + *cr = FEC_1_2; + break; + case DIB3000MB_FEC_2_3: + *cr = FEC_2_3; + break; + case DIB3000MB_FEC_3_4: + *cr = FEC_3_4; + break; + case DIB3000MB_FEC_5_6: + *cr = FEC_4_5; + break; + case DIB3000MB_FEC_7_8: + *cr = FEC_7_8; + break; + default: + err("Unexpected FEC returned by TPS (%d)",tps_val); + break; + } + + switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) { + case DIB3000MB_GUARD_TIME_1_32: + ofdm->guard_interval = GUARD_INTERVAL_1_32; + break; + case DIB3000MB_GUARD_TIME_1_16: + ofdm->guard_interval = GUARD_INTERVAL_1_16; + break; + case DIB3000MB_GUARD_TIME_1_8: + ofdm->guard_interval = GUARD_INTERVAL_1_8; + break; + case DIB3000MB_GUARD_TIME_1_4: + ofdm->guard_interval = GUARD_INTERVAL_1_4; + break; + default: + err("Unexpected Guard Time returned by TPS (%d)",tps_val); + break; + } + + switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) { + case DIB3000MB_FFT_2K: + ofdm->transmission_mode = TRANSMISSION_MODE_2K; + break; + case DIB3000MB_FFT_8K: + ofdm->transmission_mode = TRANSMISSION_MODE_8K; + break; + default: + err("unexpected transmission mode return by TPS (%d)",tps_val); + } + return 0; +} + static int dib3000mb_fe_init(struct dib3000mb_state *state,int mobile_mode) { struct i2c_client *i2c = state->i2c; + wr(DIB3000MB_REG_POWER_CONTROL,DIB3000MB_POWER_UP); + wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC); wr(DIB3000MB_REG_RESET_DEVICE,DIB3000MB_RESET_DEVICE); @@ -511,6 +670,29 @@ static int dib3000mb_read_status(struct dib3000mb_state *state,fe_status_t *stat return 0; } +static int dib3000mb_read_ber(struct dib3000mb_state *state,u32 *ber) +{ + struct i2c_client *i2c = state->i2c; + *ber = + (((rd(DIB3000MB_REG_BER_MSB) << 16) & 0x1f) | rd(DIB3000MB_REG_BER_LSB) ) / + 100000000; + return 0; +} + +static int dib3000mb_signal_strength(struct dib3000mb_state *state, u16 *strength) +{ + struct i2c_client *i2c = state->i2c; +// *stength = DIB3000MB_REG_SIGNAL_POWER + return 0; +} + +static int dib3000mb_sleep(struct dib3000mb_state *state) +{ + struct i2c_client *i2c = state->i2c; + wr(DIB3000MB_REG_POWER_CONTROL,DIB3000MB_POWER_DOWN); + return 0; +} + static int dib3000mb_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) { struct dib3000mb_state *state = fe->data; @@ -528,10 +710,12 @@ static int dib3000mb_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg case FE_READ_BER: dprintk("FE_READ_BER\n"); + ret = dib3000mb_read_ber(state,(u32 *)arg); break; case FE_READ_SIGNAL_STRENGTH: dprintk("FE_READ_SIG_STRENGTH\n"); + ret = dib3000mb_signal_strength(state,(u16 *) arg); break; case FE_READ_SNR: @@ -549,10 +733,12 @@ static int dib3000mb_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg case FE_GET_FRONTEND: dprintk("FE_GET_FRONTEND\n"); + ret = dib3000mb_get_frontend(state,(struct dvb_frontend_parameters *) arg); break; case FE_SLEEP: dprintk("FE_SLEEP\n"); + ret = dib3000mb_sleep(state); break; case FE_INIT: diff --git a/linux/drivers/media/dvb/frontends/dib3000mb.h b/linux/drivers/media/dvb/frontends/dib3000mb.h index e606ff7b7..5f81b6eb0 100644 --- a/linux/drivers/media/dvb/frontends/dib3000mb.h +++ b/linux/drivers/media/dvb/frontends/dib3000mb.h @@ -517,9 +517,9 @@ static u16 dib3000mb_filter_coeffs[] = { #define DIB3000MB_CLOCK_DIVERSITY (0x92b0) /* power down config */ -#define DIB3000MB_REG_POWER_DOWN ( 1028) -#define DIB3000MB_POWER_DOWN ( 1) -#define DIB3000MB_POWER_UP ( 0) +#define DIB3000MB_REG_POWER_CONTROL ( 1028) +#define DIB3000MB_POWER_DOWN ( 1) +#define DIB3000MB_POWER_UP ( 0) /* electrical output mode */ #define DIB3000MB_REG_ELECT_OUT_MODE ( 1029) |