📄 dib7000p.c
字号:
1, 198, 0x800, // P_equal_thres_wgn 1, 222, 0x0010, // P_fec_ber_rs_len=2 1, 235, 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard 2, 901, 0x0006, // P_clk_cfg1 (3 << 10) | (1 << 6), // P_divclksel=3 P_divbitsel=1 1, 905, 0x2c8e, // Tuner IO bank: max drive (14mA) + divout pads max drive 0,};static int dib7000p_demod_reset(struct dib7000p_state *state){ dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE); /* restart all parts */ dib7000p_write_word(state, 770, 0xffff); dib7000p_write_word(state, 771, 0xffff); dib7000p_write_word(state, 772, 0x001f); dib7000p_write_word(state, 898, 0x0003); /* except i2c, sdio, gpio - control interfaces */ dib7000p_write_word(state, 1280, 0x01fc - ((1 << 7) | (1 << 6) | (1 << 5)) ); dib7000p_write_word(state, 770, 0); dib7000p_write_word(state, 771, 0); dib7000p_write_word(state, 772, 0); dib7000p_write_word(state, 898, 0); dib7000p_write_word(state, 1280, 0); /* default */ dib7000p_reset_pll(state); if (dib7000p_reset_gpio(state) != 0) dprintk( "GPIO reset was not successful."); if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0) dprintk( "OUTPUT_MODE could not be reset."); /* unforce divstr regardless whether i2c enumeration was done or not */ dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) ); dib7000p_set_bandwidth(state, 8000); dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON); dib7000p_sad_calib(state); dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_OFF); // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ... if(state->cfg.tuner_is_baseband) dib7000p_write_word(state, 36,0x0755); else dib7000p_write_word(state, 36,0x1f55); dib7000p_write_tab(state, dib7000p_defaults); dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); return 0;}static void dib7000p_pll_clk_cfg(struct dib7000p_state *state){ u16 tmp = 0; tmp = dib7000p_read_word(state, 903); dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll tmp = dib7000p_read_word(state, 900); dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock}static void dib7000p_restart_agc(struct dib7000p_state *state){ // P_restart_iqc & P_restart_agc dib7000p_write_word(state, 770, (1 << 11) | (1 << 9)); dib7000p_write_word(state, 770, 0x0000);}static int dib7000p_update_lna(struct dib7000p_state *state){ u16 dyn_gain; // when there is no LNA to program return immediatly if (state->cfg.update_lna) { // read dyn_gain here (because it is demod-dependent and not fe) dyn_gain = dib7000p_read_word(state, 394); if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed dib7000p_restart_agc(state); return 1; } } return 0;}static int dib7000p_set_agc_config(struct dib7000p_state *state, u8 band){ struct dibx000_agc_config *agc = NULL; int i; if (state->current_band == band && state->current_agc != NULL) return 0; state->current_band = band; for (i = 0; i < state->cfg.agc_config_count; i++) if (state->cfg.agc[i].band_caps & band) { agc = &state->cfg.agc[i]; break; } if (agc == NULL) { dprintk( "no valid AGC configuration found for band 0x%02x",band); return -EINVAL; } state->current_agc = agc; /* AGC */ dib7000p_write_word(state, 75 , agc->setup ); dib7000p_write_word(state, 76 , agc->inv_gain ); dib7000p_write_word(state, 77 , agc->time_stabiliz ); dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock); // Demod AGC loop configuration dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp); dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp); /* AGC continued */ dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d", state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); if (state->wbd_ref != 0) dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref); else dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref); dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8)); dib7000p_write_word(state, 107, agc->agc1_max); dib7000p_write_word(state, 108, agc->agc1_min); dib7000p_write_word(state, 109, agc->agc2_max); dib7000p_write_word(state, 110, agc->agc2_min); dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2); dib7000p_write_word(state, 112, agc->agc1_pt3); dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2); dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2); dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); return 0;}static int dib7000p_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch){ struct dib7000p_state *state = demod->demodulator_priv; int ret = -1; u8 *agc_state = &state->agc_state; u8 agc_split; switch (state->agc_state) { case 0: // set power-up level: interf+analog+AGC dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); dib7000p_set_adc_state(state, DIBX000_ADC_ON); dib7000p_pll_clk_cfg(state); if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0) return -1; ret = 7; (*agc_state)++; break; case 1: // AGC initialization if (state->cfg.agc_control) state->cfg.agc_control(&state->demod, 1); dib7000p_write_word(state, 78, 32768); if (!state->current_agc->perform_agc_softsplit) { /* we are using the wbd - so slow AGC startup */ /* force 0 split on WBD and restart AGC */ dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8)); (*agc_state)++; ret = 5; } else { /* default AGC startup */ (*agc_state) = 4; /* wait AGC rough lock time */ ret = 7; } dib7000p_restart_agc(state); break; case 2: /* fast split search path after 5sec */ dib7000p_write_word(state, 75, state->current_agc->setup | (1 << 4)); /* freeze AGC loop */ dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8)); /* fast split search 0.25kHz */ (*agc_state)++; ret = 14; break; case 3: /* split search ended */ agc_split = (u8)dib7000p_read_word(state, 396); /* store the split value for the next time */ dib7000p_write_word(state, 78, dib7000p_read_word(state, 394)); /* set AGC gain start value */ dib7000p_write_word(state, 75, state->current_agc->setup); /* std AGC loop */ dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */ dib7000p_restart_agc(state); dprintk( "SPLIT %p: %hd", demod, agc_split); (*agc_state)++; ret = 5; break; case 4: /* LNA startup */ // wait AGC accurate lock time ret = 7; if (dib7000p_update_lna(state)) // wait only AGC rough lock time ret = 5; else // nothing was done, go to the next state (*agc_state)++; break; case 5: if (state->cfg.agc_control) state->cfg.agc_control(&state->demod, 0); (*agc_state)++; break; default: break; } return ret;}static void dib7000p_update_timf(struct dib7000p_state *state){ u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428); state->timf = timf * 160 / (state->current_bandwidth / 50); dib7000p_write_word(state, 23, (u16) (timf >> 16)); dib7000p_write_word(state, 24, (u16) (timf & 0xffff)); dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->cfg.bw->timf);}static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_frontend_parameters *ch, u8 seq){ u16 value, est[4]; dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)); /* nfft, guard, qam, alpha */ value = 0; switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: value |= (0 << 7); break; case /* 4K MODE */ 255: value |= (2 << 7); break; default: case TRANSMISSION_MODE_8K: value |= (1 << 7); break; } switch (ch->u.ofdm.guard_interval) { case GUARD_INTERVAL_1_32: value |= (0 << 5); break; case GUARD_INTERVAL_1_16: value |= (1 << 5); break; case GUARD_INTERVAL_1_4: value |= (3 << 5); break; default: case GUARD_INTERVAL_1_8: value |= (2 << 5); break; } switch (ch->u.ofdm.constellation) { case QPSK: value |= (0 << 3); break; case QAM_16: value |= (1 << 3); break; default: case QAM_64: value |= (2 << 3); break; } switch (HIERARCHY_1) { case HIERARCHY_2: value |= 2; break; case HIERARCHY_4: value |= 4; break; default: case HIERARCHY_1: value |= 1; break; } dib7000p_write_word(state, 0, value); dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */ /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */ value = 0; if (1 != 0) value |= (1 << 6); if (ch->u.ofdm.hierarchy_information == 1) value |= (1 << 4); if (1 == 1) value |= 1; switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) { case FEC_2_3: value |= (2 << 1); break; case FEC_3_4: value |= (3 << 1); break; case FEC_5_6: value |= (5 << 1); break; case FEC_7_8: value |= (7 << 1); break; default: case FEC_1_2: value |= (1 << 1); break; } dib7000p_write_word(state, 208, value); /* offset loop parameters */ dib7000p_write_word(state, 26, 0x6680); // timf(6xxx) dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3) dib7000p_write_word(state, 29, 0x1273); // isi dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5) /* P_dvsy_sync_wait */ switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_8K: value = 256; break; case /* 4K MODE */ 255: value = 128; break; case TRANSMISSION_MODE_2K: default: value = 64; break; } switch (ch->u.ofdm.guard_interval) { case GUARD_INTERVAL_1_16: value *= 2; break; case GUARD_INTERVAL_1_8: value *= 4; break; case GUARD_INTERVAL_1_4: value *= 8; break; default: case GUARD_INTERVAL_1_32: value *= 1; break; } state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO /* deactive the possibility of diversity reception if extended interleaver */ state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K; dib7000p_set_diversity_in(&state->demod, state->div_state); /* channel estimation fine configuration */ switch (ch->u.ofdm.constellation) { case QAM_64: est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ break; case QAM_16: est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ break; default: est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ est[2] = 0x0333; /* P_adp_regul_ext 0.1 */ est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ break; } for (value = 0; value < 4; value++) dib7000p_write_word(state, 187 + value, est[value]);}static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch){ struct dib7000p_state *state = demod->demodulator_priv; struct dvb_frontend_parameters schan; u32 value, factor; schan = *ch; schan.u.ofdm.constellation = QAM_64; schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32; schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; schan.u.ofdm.code_rate_HP = FEC_2_3; schan.u.ofdm.code_rate_LP = FEC_3_4; schan.u.ofdm.hierarchy_information = 0; dib7000p_set_channel(state, &schan, 7); factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth); if (factor >= 5000) factor = 1; else factor = 6; // always use the setting for 8MHz here lock_time for 7,6 MHz are longer value = 30 * state->cfg.bw->internal * factor; dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time dib7000p_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time value = 100 * state->cfg.bw->internal * factor; dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time dib7000p_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time value = 500 * state->cfg.bw->internal * factor; dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time dib7000p_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time value = dib7000p_read_word(state, 0); dib7000p_write_word(state, 0, (u16) ((1 << 9) | value)); dib7000p_read_word(state, 1284); dib7000p_write_word(state, 0, (u16) value); return 0;}static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod){ struct dib7000p_state *state = demod->demodulator_priv; u16 irq_pending = dib7000p_read_word(state, 1284); if (irq_pending & 0x1) // failed return 1; if (irq_pending & 0x2) // succeeded return 2; return 0; // still pending}static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 bw){ static s16 notch[]={16143, 14402, 12238, 9713, 6902, 3888, 759, -2392}; static u8 sine [] ={0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51, 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80, 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105, 107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126, 128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146, 147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165, 166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212, 213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224, 225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235, 235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249, 250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; u32 xtal = state->cfg.bw->xtal_hz / 1000; int f_rel = ( (rf_khz + xtal/2) / xtal) * xtal - rf_khz; int k; int coef_re[8],coef_im[8]; int bw_khz = bw; u32 pha; dprintk( "relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal); if (f_rel < -bw_khz/2 || f_rel > bw_khz/2) return; bw_khz /= 100; dib7000p_write_word(state, 142 ,0x0610); for (k = 0; k < 8; k++) { pha = ((f_rel * (k+1) * 112 * 80/bw_khz) /1000) & 0x3ff; if (pha==0) { coef_re[k] = 256; coef_im[k] = 0; } else if(pha < 256) { coef_re[k] = sine[256-(pha&0xff)]; coef_im[k] = sine[pha&0xff]; } else if (pha == 256) { coef_re[k] = 0; coef_im[k] = 256; } else if (pha < 512) { coef_re[k] = -sine[pha&0xff]; coef_im[k] = sine[256 - (pha&0xff)]; } else if (pha == 512) { coef_re[k] = -256; coef_im[k] = 0; } else if (pha < 768) { coef_re[k] = -sine[256-(pha&0xff)]; coef_im[k] = -sine[pha&0xff];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -