📄 dib3000mb.c
字号:
wr(DIB3000MB_REG_LOCK2_MASK, DIB3000MB_LOCK2_DEFAULT); wr(DIB3000MB_REG_SEQ, dib3000_seq[1][1][1]); wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz); wr(DIB3000MB_REG_UNK_68, DIB3000MB_UNK_68); wr(DIB3000MB_REG_UNK_69, DIB3000MB_UNK_69); wr(DIB3000MB_REG_UNK_71, DIB3000MB_UNK_71); wr(DIB3000MB_REG_UNK_77, DIB3000MB_UNK_77); wr(DIB3000MB_REG_UNK_78, DIB3000MB_UNK_78); wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT); wr(DIB3000MB_REG_UNK_92, DIB3000MB_UNK_92); wr(DIB3000MB_REG_UNK_96, DIB3000MB_UNK_96); wr(DIB3000MB_REG_UNK_97, DIB3000MB_UNK_97); wr(DIB3000MB_REG_UNK_106, DIB3000MB_UNK_106); wr(DIB3000MB_REG_UNK_107, DIB3000MB_UNK_107); wr(DIB3000MB_REG_UNK_108, DIB3000MB_UNK_108); wr(DIB3000MB_REG_UNK_122, DIB3000MB_UNK_122); wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF); wr(DIB3000MB_REG_BERLEN, DIB3000MB_BERLEN_DEFAULT); wr_foreach(dib3000mb_reg_filter_coeffs, dib3000mb_filter_coeffs); wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_ON); wr(DIB3000MB_REG_MULTI_DEMOD_MSB, DIB3000MB_MULTI_DEMOD_MSB); wr(DIB3000MB_REG_MULTI_DEMOD_LSB, DIB3000MB_MULTI_DEMOD_LSB); wr(DIB3000MB_REG_OUTPUT_MODE, DIB3000MB_OUTPUT_MODE_SLAVE); wr(DIB3000MB_REG_FIFO_142, DIB3000MB_FIFO_142); wr(DIB3000MB_REG_MPEG2_OUT_MODE, DIB3000MB_MPEG2_OUT_MODE_188); wr(DIB3000MB_REG_PID_PARSE, DIB3000MB_PID_PARSE_ACTIVATE); wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT); wr(DIB3000MB_REG_FIFO_146, DIB3000MB_FIFO_146); wr(DIB3000MB_REG_FIFO_147, DIB3000MB_FIFO_147); wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF); return 0;}static int dib3000mb_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep){ struct dib3000_state* state = fe->demodulator_priv; struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm; fe_code_rate_t *cr; u16 tps_val; int inv_test1,inv_test2; u32 dds_val, threshold = 0x800000; if (!rd(DIB3000MB_REG_TPS_LOCK)) return 0; dds_val = ((rd(DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB); deb_getf("DDS_VAL: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_VALUE_MSB), 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); deb_getf("DDS_FREQ: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_FREQ_MSB), 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; fep->inversion = ((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) || ((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ? INVERSION_ON : INVERSION_OFF; deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, fep->inversion); switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) { case DIB3000_CONSTELLATION_QPSK: deb_getf("QPSK "); ofdm->constellation = QPSK; break; case DIB3000_CONSTELLATION_16QAM: deb_getf("QAM16 "); ofdm->constellation = QAM_16; break; case DIB3000_CONSTELLATION_64QAM: deb_getf("QAM64 "); ofdm->constellation = QAM_64; break; default: err("Unexpected constellation returned by TPS (%d)", tps_val); break; } deb_getf("TPS: %d\n", tps_val); if (rd(DIB3000MB_REG_TPS_HRCH)) { deb_getf("HRCH ON\n"); cr = &ofdm->code_rate_LP; ofdm->code_rate_HP = FEC_NONE; switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) { case DIB3000_ALPHA_0: deb_getf("HIERARCHY_NONE "); ofdm->hierarchy_information = HIERARCHY_NONE; break; case DIB3000_ALPHA_1: deb_getf("HIERARCHY_1 "); ofdm->hierarchy_information = HIERARCHY_1; break; case DIB3000_ALPHA_2: deb_getf("HIERARCHY_2 "); ofdm->hierarchy_information = HIERARCHY_2; break; case DIB3000_ALPHA_4: deb_getf("HIERARCHY_4 "); ofdm->hierarchy_information = HIERARCHY_4; break; default: err("Unexpected ALPHA value returned by TPS (%d)", tps_val); break; } deb_getf("TPS: %d\n", tps_val); tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP); } else { deb_getf("HRCH OFF\n"); cr = &ofdm->code_rate_HP; ofdm->code_rate_LP = FEC_NONE; ofdm->hierarchy_information = HIERARCHY_NONE; tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP); } switch (tps_val) { case DIB3000_FEC_1_2: deb_getf("FEC_1_2 "); *cr = FEC_1_2; break; case DIB3000_FEC_2_3: deb_getf("FEC_2_3 "); *cr = FEC_2_3; break; case DIB3000_FEC_3_4: deb_getf("FEC_3_4 "); *cr = FEC_3_4; break; case DIB3000_FEC_5_6: deb_getf("FEC_5_6 "); *cr = FEC_4_5; break; case DIB3000_FEC_7_8: deb_getf("FEC_7_8 "); *cr = FEC_7_8; break; default: err("Unexpected FEC returned by TPS (%d)", tps_val); break; } deb_getf("TPS: %d\n",tps_val); switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) { case DIB3000_GUARD_TIME_1_32: deb_getf("GUARD_INTERVAL_1_32 "); ofdm->guard_interval = GUARD_INTERVAL_1_32; break; case DIB3000_GUARD_TIME_1_16: deb_getf("GUARD_INTERVAL_1_16 "); ofdm->guard_interval = GUARD_INTERVAL_1_16; break; case DIB3000_GUARD_TIME_1_8: deb_getf("GUARD_INTERVAL_1_8 "); ofdm->guard_interval = GUARD_INTERVAL_1_8; break; case DIB3000_GUARD_TIME_1_4: deb_getf("GUARD_INTERVAL_1_4 "); ofdm->guard_interval = GUARD_INTERVAL_1_4; break; default: err("Unexpected Guard Time returned by TPS (%d)", tps_val); break; } deb_getf("TPS: %d\n", tps_val); switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) { case DIB3000_TRANSMISSION_MODE_2K: deb_getf("TRANSMISSION_MODE_2K "); ofdm->transmission_mode = TRANSMISSION_MODE_2K; break; case DIB3000_TRANSMISSION_MODE_8K: deb_getf("TRANSMISSION_MODE_8K "); ofdm->transmission_mode = TRANSMISSION_MODE_8K; break; default: err("unexpected transmission mode return by TPS (%d)", tps_val); break; } deb_getf("TPS: %d\n", tps_val); return 0;}static int dib3000mb_read_status(struct dvb_frontend* fe, fe_status_t *stat){ struct dib3000_state* state = fe->demodulator_priv; *stat = 0; if (rd(DIB3000MB_REG_AGC_LOCK)) *stat |= FE_HAS_SIGNAL; if (rd(DIB3000MB_REG_CARRIER_LOCK)) *stat |= FE_HAS_CARRIER; if (rd(DIB3000MB_REG_VIT_LCK)) *stat |= FE_HAS_VITERBI; if (rd(DIB3000MB_REG_TS_SYNC_LOCK)) *stat |= (FE_HAS_SYNC | FE_HAS_LOCK); deb_getf("actual status is %2x\n",*stat); deb_getf("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), rd(DIB3000MB_REG_TPS_HRCH), rd(DIB3000MB_REG_TPS_VIT_ALPHA), rd(DIB3000MB_REG_TPS_CODE_RATE_HP), rd(DIB3000MB_REG_TPS_CODE_RATE_LP), rd(DIB3000MB_REG_TPS_GUARD_TIME), rd(DIB3000MB_REG_TPS_FFT), rd(DIB3000MB_REG_TPS_CELL_ID)); //*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; return 0;}static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber){ struct dib3000_state* state = fe->demodulator_priv; *ber = ((rd(DIB3000MB_REG_BER_MSB) << 16) | rd(DIB3000MB_REG_BER_LSB)); return 0;}/* see dib3000-watch dvb-apps for exact calcuations of signal_strength and snr */static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength){ struct dib3000_state* state = fe->demodulator_priv; *strength = rd(DIB3000MB_REG_SIGNAL_POWER) * 0xffff / 0x170; return 0;}static int dib3000mb_read_snr(struct dvb_frontend* fe, u16 *snr){ struct dib3000_state* state = fe->demodulator_priv; short sigpow = rd(DIB3000MB_REG_SIGNAL_POWER); int icipow = ((rd(DIB3000MB_REG_NOISE_POWER_MSB) & 0xff) << 16) | rd(DIB3000MB_REG_NOISE_POWER_LSB); *snr = (sigpow << 8) / ((icipow > 0) ? icipow : 1); return 0;}static int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc){ struct dib3000_state* state = fe->demodulator_priv; *unc = rd(DIB3000MB_REG_PACKET_ERROR_RATE); return 0;}static int dib3000mb_sleep(struct dvb_frontend* fe){ struct dib3000_state* state = fe->demodulator_priv; deb_info("dib3000mb is going to bed.\n"); wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_DOWN); return 0;}static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune){ tune->min_delay_ms = 800; return 0;}static int dib3000mb_fe_init_nonmobile(struct dvb_frontend* fe){ return dib3000mb_fe_init(fe, 0);}static int dib3000mb_set_frontend_and_tuner(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep){ return dib3000mb_set_frontend(fe, fep, 1);}static void dib3000mb_release(struct dvb_frontend* fe){ struct dib3000_state *state = fe->demodulator_priv; kfree(state);}/* pid filter and transfer stuff */static int dib3000mb_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff){ struct dib3000_state *state = fe->demodulator_priv; pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0); wr(index+DIB3000MB_REG_FIRST_PID,pid); return 0;}static int dib3000mb_fifo_control(struct dvb_frontend *fe, int onoff){ struct dib3000_state *state = fe->demodulator_priv; deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling"); if (onoff) { wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_ACTIVATE); } else { wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT); } return 0;}static int dib3000mb_pid_parse(struct dvb_frontend *fe, int onoff){ struct dib3000_state *state = fe->demodulator_priv; deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling"); wr(DIB3000MB_REG_PID_PARSE,onoff); return 0;}static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr){ struct dib3000_state *state = fe->demodulator_priv; if (onoff) { wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr)); } else { wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr)); } return 0;}static struct dvb_frontend_ops dib3000mb_ops;struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config, struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops){ struct dib3000_state* state = NULL; /* allocate memory for the internal state */ state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ state->i2c = i2c; memcpy(&state->config,config,sizeof(struct dib3000_config)); /* check for the correct demod */ if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM) goto error; if (rd(DIB3000_REG_DEVICE_ID) != DIB3000MB_DEVICE_ID) goto error; /* create dvb_frontend */ memcpy(&state->frontend.ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; /* set the xfer operations */ xfer_ops->pid_parse = dib3000mb_pid_parse; xfer_ops->fifo_ctrl = dib3000mb_fifo_control; xfer_ops->pid_ctrl = dib3000mb_pid_control; xfer_ops->tuner_pass_ctrl = dib3000mb_tuner_pass_ctrl; return &state->frontend;error: kfree(state); return NULL;}static struct dvb_frontend_ops dib3000mb_ops = { .info = { .name = "DiBcom 3000M-B DVB-T", .type = FE_OFDM, .frequency_min = 44250000, .frequency_max = 867250000, .frequency_stepsize = 62500, .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 | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO, }, .release = dib3000mb_release, .init = dib3000mb_fe_init_nonmobile, .sleep = dib3000mb_sleep, .set_frontend = dib3000mb_set_frontend_and_tuner, .get_frontend = dib3000mb_get_frontend, .get_tune_settings = dib3000mb_fe_get_tune_settings, .read_status = dib3000mb_read_status, .read_ber = dib3000mb_read_ber, .read_signal_strength = dib3000mb_read_signal_strength, .read_snr = dib3000mb_read_snr, .read_ucblocks = dib3000mb_read_unc_blocks,};MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");EXPORT_SYMBOL(dib3000mb_attach);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -