?? dib7000m.c
字號:
0x00a4, // P_adp_regul_ext 0x7ff0, // P_adp_noise_ext 0x3ccc, // P_adp_fil 1, 226, 0, // P_2d_byp_ti_num 1, 255, 0x800, // P_equal_thres_wgn 1, 263, 0x0001, 1, 281, 0x0010, // P_fec_* 1, 294, 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard 0};static u16 dib7000m_defaults[] ={ /* set ADC level to -16 */ 11, 76, (1 << 13) - 825 - 117, (1 << 13) - 837 - 117, (1 << 13) - 811 - 117, (1 << 13) - 766 - 117, (1 << 13) - 737 - 117, (1 << 13) - 693 - 117, (1 << 13) - 648 - 117, (1 << 13) - 619 - 117, (1 << 13) - 575 - 117, (1 << 13) - 531 - 117, (1 << 13) - 501 - 117, // Tuner IO bank: max drive (14mA) 1, 912, 0x2c8a, 1, 1817, 1, 0,};static int dib7000m_demod_reset(struct dib7000m_state *state){ dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE); /* restart all parts */ dib7000m_write_word(state, 898, 0xffff); dib7000m_write_word(state, 899, 0xffff); dib7000m_write_word(state, 900, 0xff0f); dib7000m_write_word(state, 901, 0xfffc); dib7000m_write_word(state, 898, 0); dib7000m_write_word(state, 899, 0); dib7000m_write_word(state, 900, 0); dib7000m_write_word(state, 901, 0); if (state->revision == 0x4000) dib7000m_reset_pll(state); else dib7000mc_reset_pll(state); if (dib7000m_reset_gpio(state) != 0) dprintk( "GPIO reset was not successful."); if (dib7000m_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 */ dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) ); dib7000m_set_bandwidth(state, 8000); dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON); dib7000m_sad_calib(state); dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF); if (state->cfg.dvbt_mode) dib7000m_write_word(state, 1796, 0x0); // select DVB-T output if (state->cfg.mobile_mode) dib7000m_write_word(state, 261 + state->reg_offs, 2); else dib7000m_write_word(state, 224 + state->reg_offs, 1); // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... if(state->cfg.tuner_is_baseband) dib7000m_write_word(state, 36, 0x0755); else dib7000m_write_word(state, 36, 0x1f55); // P_divclksel=3 P_divbitsel=1 if (state->revision == 0x4000) dib7000m_write_word(state, 909, (3 << 10) | (1 << 6)); else dib7000m_write_word(state, 909, (3 << 4) | 1); dib7000m_write_tab(state, dib7000m_defaults_common); dib7000m_write_tab(state, dib7000m_defaults); dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY); state->internal_clk = state->cfg.bw->internal; return 0;}static void dib7000m_restart_agc(struct dib7000m_state *state){ // P_restart_iqc & P_restart_agc dib7000m_write_word(state, 898, 0x0c00); dib7000m_write_word(state, 898, 0x0000);}static int dib7000m_agc_soft_split(struct dib7000m_state *state){ u16 agc,split_offset; if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0) return 0; // n_agc_global agc = dib7000m_read_word(state, 390); if (agc > state->current_agc->split.min_thres) split_offset = state->current_agc->split.min; else if (agc < state->current_agc->split.max_thres) split_offset = state->current_agc->split.max; else split_offset = state->current_agc->split.max * (agc - state->current_agc->split.min_thres) / (state->current_agc->split.max_thres - state->current_agc->split.min_thres); dprintk( "AGC split_offset: %d",split_offset); // P_agc_force_split and P_agc_split_offset return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset);}static int dib7000m_update_lna(struct dib7000m_state *state){ u16 dyn_gain; if (state->cfg.update_lna) { // read dyn_gain here (because it is demod-dependent and not fe) dyn_gain = dib7000m_read_word(state, 390); if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed dib7000m_restart_agc(state); return 1; } } return 0;}static int dib7000m_set_agc_config(struct dib7000m_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 */ dib7000m_write_word(state, 72 , agc->setup); dib7000m_write_word(state, 73 , agc->inv_gain); dib7000m_write_word(state, 74 , agc->time_stabiliz); dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock); // Demod AGC loop configuration dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp); dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp); 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); /* AGC continued */ if (state->wbd_ref != 0) dib7000m_write_word(state, 102, state->wbd_ref); else // use default dib7000m_write_word(state, 102, agc->wbd_ref); dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); dib7000m_write_word(state, 104, agc->agc1_max); dib7000m_write_word(state, 105, agc->agc1_min); dib7000m_write_word(state, 106, agc->agc2_max); dib7000m_write_word(state, 107, agc->agc2_min); dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2); dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2); dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2); if (state->revision > 0x4000) { // settings for the MC dib7000m_write_word(state, 71, agc->agc1_pt3);// dprintk( "929: %x %d %d",// (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel); dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); } else { // wrong default values u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 }; for (i = 0; i < 9; i++) dib7000m_write_word(state, 88 + i, b[i]); } return 0;}static void dib7000m_update_timf(struct dib7000m_state *state){ u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437); state->timf = timf * 160 / (state->current_bandwidth / 50); dib7000m_write_word(state, 23, (u16) (timf >> 16)); dib7000m_write_word(state, 24, (u16) (timf & 0xffff)); dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->timf_default);}static int dib7000m_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch){ struct dib7000m_state *state = demod->demodulator_priv; u16 cfg_72 = dib7000m_read_word(state, 72); 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 dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC); dib7000m_set_adc_state(state, DIBX000_ADC_ON); if (dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0) return -1; ret = 7; /* ADC power up */ (*agc_state)++; break; case 1: /* AGC initialization */ if (state->cfg.agc_control) state->cfg.agc_control(&state->demod, 1); dib7000m_write_word(state, 75, 32768); if (!state->current_agc->perform_agc_softsplit) { /* we are using the wbd - so slow AGC startup */ dib7000m_write_word(state, 103, 1 << 8); /* force 0 split on WBD and restart AGC */ (*agc_state)++; ret = 5; } else { /* default AGC startup */ (*agc_state) = 4; /* wait AGC rough lock time */ ret = 7; } dib7000m_restart_agc(state); break; case 2: /* fast split search path after 5sec */ dib7000m_write_word(state, 72, cfg_72 | (1 << 4)); /* freeze AGC loop */ dib7000m_write_word(state, 103, 2 << 9); /* fast split search 0.25kHz */ (*agc_state)++; ret = 14; break; case 3: /* split search ended */ agc_split = (u8)dib7000m_read_word(state, 392); /* store the split value for the next time */ dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */ dib7000m_write_word(state, 72, cfg_72 & ~(1 << 4)); /* std AGC loop */ dib7000m_write_word(state, 103, (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */ dib7000m_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 (dib7000m_update_lna(state)) // wait only AGC rough lock time ret = 5; else (*agc_state)++; break; case 5: dib7000m_agc_soft_split(state); if (state->cfg.agc_control) state->cfg.agc_control(&state->demod, 0); (*agc_state)++; break; default: break; } return ret;}static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_frontend_parameters *ch, u8 seq){ u16 value, est[4]; dib7000m_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; } dib7000m_write_word(state, 0, value); dib7000m_write_word(state, 5, (seq << 4)); /* 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; } dib7000m_write_word(state, 267 + state->reg_offs, value); /* offset loop parameters */ /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */ dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80); /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3)); /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */ dib7000m_write_word(state, 32, (0 << 4) | 0x3); /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */ dib7000m_write_word(state, 33, (0 << 4) | 0x5); /* 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 interleave - not for 7000MC */ /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ if (1 == 1 || state->revision > 0x4000) state->div_force_off = 0; else state->div_force_off = 1; dib7000m_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++) dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]); // set power-up level: autosearch dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);}static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch){ struct dib7000m_state *state = demod->demodulator_priv; struct dvb_frontend_parameters schan; int ret = 0; 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; dib7000m_set_channel(state, &schan, 7); factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth); if (factor >= 5000)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -