// SPDX-License-Identifier: GPL-2.0-or-later /* Frontend part of the Linux driver for the Afatech 9005 * USB1.1 DVB-T receiver. * * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org) * * Thanks to Afatech who kindly provided information. * * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
*/ #include"af9005.h" #include"af9005-script.h" #include"mt2060.h" #include"qt1010.h" #include <asm/div64.h>
/* set super frame count to 1 */
ret =
af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_7_0,
1 & 0xff); if (ret) return ret;
ret = af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_15_8,
1 >> 8); if (ret) return ret; /* reset pre viterbi error count */
ret =
af9005_write_register_bits(state->d, xd_p_fec_vtb_ber_rst,
fec_vtb_ber_rst_pos, fec_vtb_ber_rst_len,
1);
deb_info("GET STATISTIC\n");
ret = af9005_is_fecmon_available(fe, &fecavailable); if (ret) return ret; if (!fecavailable) {
deb_info("fecmon not available\n"); return 0;
}
ret = af9005_get_pre_vit_err_bit_count(fe, &state->pre_vit_error_count,
&state->pre_vit_bit_count); if (ret == 0) {
af9005_reset_pre_viterbi(fe); if (state->pre_vit_bit_count > 0) { /* according to v 0.0.4 of the dvb api ber should be a multiple of 10E-9 so we have to multiply the error count by
10E9=1000000000 */
numerator =
(u64) state->pre_vit_error_count * (u64) 1000000000;
denominator = (u64) state->pre_vit_bit_count;
state->ber = do_div(numerator, denominator);
} else {
state->ber = 0xffffffff;
}
}
ret = af9005_get_post_vit_ber(fe, &state->post_vit_error_count,
&state->post_vit_bit_count,
&state->abort_count); if (ret == 0) {
ret = af9005_reset_post_viterbi(fe);
state->unc += state->abort_count; if (ret) return ret;
} return 0;
}
if (fe->ops.tuner_ops.release == NULL) return -ENODEV;
ret =
af9005_read_ofdm_register(state->d, xd_r_reg_aagc_rf_gain,
&rf_gain); if (ret) return ret;
ret =
af9005_read_ofdm_register(state->d, xd_r_reg_aagc_if_gain,
&if_gain); if (ret) return ret; /* this value has no real meaning, but i don't have the tables that relate
the rf and if gain with the dbm, so I just scale the value */
*strength = (512 - rf_gain - if_gain) << 7; return 0;
}
staticint af9005_fe_read_snr(struct dvb_frontend *fe, u16 * snr)
{ /* the snr can be derived from the ber and the modulation but I don't think this kind of complex calculations belong
in the driver. I may be wrong.... */ return -ENOSYS;
}
if (ret) return ret; /* don't know what register aefc is, but this is what the windows driver does */
ret = af9005_write_ofdm_register(state->d, 0xaefc, 0); if (ret) return ret;
/* set stand alone chip */
deb_info("set stand alone chip\n"); if ((ret =
af9005_write_register_bits(state->d, xd_p_reg_dca_stand_alone,
reg_dca_stand_alone_pos,
reg_dca_stand_alone_len, 1))) return ret;
/* set 2wire master clock to 0x14 (for 60KHz) */
deb_info("set 2wire master clock to 0x14 (for 60KHz)\n"); if ((ret =
af9005_write_ofdm_register(state->d, xd_I2C_i2c_m_period, 0x14))) return ret;
/* clear dca enable chip */
deb_info("clear dca enable chip\n"); if ((ret =
af9005_write_register_bits(state->d, xd_p_reg_dca_en,
reg_dca_en_pos, reg_dca_en_len, 0))) return ret; /* FIXME these are register bits, but I don't know which ones */
ret = af9005_write_ofdm_register(state->d, 0xa16c, 1); if (ret) return ret;
ret = af9005_write_ofdm_register(state->d, 0xa3c1, 0); if (ret) return ret;
/* init other parameters: program cfoe and select bandwidth */
deb_info("program cfoe\n");
ret = af9005_fe_program_cfoe(state->d, 6000000); if (ret) return ret; /* set read-update bit for modulation */
deb_info("set read-update bit for modulation\n"); if ((ret =
af9005_write_register_bits(state->d, xd_p_reg_feq_read_update,
reg_feq_read_update_pos,
reg_feq_read_update_len, 1))) return ret;
/* sample code has a set MPEG TS code here
but sniffing reveals that it doesn't do it */
/* set read-update bit to 1 for DCA modulation */
deb_info("set read-update bit 1 for DCA modulation\n"); if ((ret =
af9005_write_register_bits(state->d, xd_p_reg_dca_read_update,
reg_dca_read_update_pos,
reg_dca_read_update_len, 1))) return ret;
/* save original TOPs */
deb_info("save original TOPs\n");
/* RF TOP */
ret =
af9005_read_word_agc(state->d,
xd_p_reg_aagc_rf_top_numerator_9_8,
xd_p_reg_aagc_rf_top_numerator_7_0, 0, 2,
&state->original_rf_top); if (ret) return ret;
/* IF TOP */
ret =
af9005_read_word_agc(state->d,
xd_p_reg_aagc_if_top_numerator_9_8,
xd_p_reg_aagc_if_top_numerator_7_0, 0, 2,
&state->original_if_top); if (ret) return ret;
/* ACI 0 IF TOP */
ret =
af9005_read_word_agc(state->d, 0xA60E, 0xA60A, 4, 2,
&state->original_aci0_if_top); if (ret) return ret;
/* ACI 1 IF TOP */
ret =
af9005_read_word_agc(state->d, 0xA60E, 0xA60B, 6, 2,
&state->original_aci1_if_top); if (ret) return ret;
/* attach tuner and init */ if (fe->ops.tuner_ops.release == NULL) { /* read tuner and board id from eeprom */
ret = af9005_read_eeprom(adap->dev, 0xc6, buf, 2); if (ret) {
err("Impossible to read EEPROM\n"); return ret;
}
deb_info("Tuner id %d, board id %d\n", buf[0], buf[1]); switch (buf[0]) { case 2: /* MT2060 */ /* read if1 from eeprom */
ret = af9005_read_eeprom(adap->dev, 0xc8, buf, 2); if (ret) {
err("Impossible to read EEPROM\n"); return ret;
}
if1 = (u16) (buf[0] << 8) + buf[1]; if (dvb_attach(mt2060_attach, fe, &adap->dev->i2c_adap,
&af9005_mt2060_config, if1) == NULL) {
deb_info("MT2060 attach failed\n"); return -ENODEV;
} break; case 3: /* QT1010 */ case 9: /* QT1010B */ if (dvb_attach(qt1010_attach, fe, &adap->dev->i2c_adap,
&af9005_qt1010_config) ==NULL) {
deb_info("QT1010 attach failed\n"); return -ENODEV;
} break; default:
err("Unsupported tuner type %d", buf[0]); return -ENODEV;
}
ret = fe->ops.tuner_ops.init(fe); if (ret) return ret;
}
deb_info("af9005_fe_set_frontend freq %d bw %d\n", fep->frequency,
fep->bandwidth_hz); if (fe->ops.tuner_ops.release == NULL) {
err("Tuner not attached"); return -ENODEV;
}
deb_info("turn off led\n"); /* not in the log */
ret = af9005_led_control(state->d, 0); if (ret) return ret; /* not sure about the bits */
ret = af9005_write_register_bits(state->d, XD_MP2IF_MISC, 2, 1, 0); if (ret) return ret;
/* set FCW to default value */
deb_info("set FCW to default value\n");
temp0 = (u8) (state->original_fcw & 0x000000ff);
temp1 = (u8) ((state->original_fcw & 0x0000ff00) >> 8);
temp2 = (u8) ((state->original_fcw & 0x00ff0000) >> 16);
ret = af9005_write_ofdm_register(state->d, 0xae1a, temp0); if (ret) return ret;
ret = af9005_write_ofdm_register(state->d, 0xae19, temp1); if (ret) return ret;
ret = af9005_write_ofdm_register(state->d, 0xae18, temp2); if (ret) return ret;
/* restore original TOPs */
deb_info("restore original TOPs\n");
ret =
af9005_write_word_agc(state->d,
xd_p_reg_aagc_rf_top_numerator_9_8,
xd_p_reg_aagc_rf_top_numerator_7_0, 0, 2,
state->original_rf_top); if (ret) return ret;
ret =
af9005_write_word_agc(state->d,
xd_p_reg_aagc_if_top_numerator_9_8,
xd_p_reg_aagc_if_top_numerator_7_0, 0, 2,
state->original_if_top); if (ret) return ret;
ret =
af9005_write_word_agc(state->d, 0xA60E, 0xA60A, 4, 2,
state->original_aci0_if_top); if (ret) return ret;
ret =
af9005_write_word_agc(state->d, 0xA60E, 0xA60B, 6, 2,
state->original_aci1_if_top); if (ret) return ret;
/* select bandwidth */
deb_info("select bandwidth");
ret = af9005_fe_select_bw(state->d, fep->bandwidth_hz); if (ret) return ret;
ret = af9005_fe_program_cfoe(state->d, fep->bandwidth_hz); if (ret) return ret;
/* clear easy mode flag */
deb_info("clear easy mode flag\n");
ret = af9005_write_ofdm_register(state->d, 0xaefd, 0); if (ret) return ret;
/* set unplug threshold to original value */
deb_info("set unplug threshold to original value\n");
ret =
af9005_write_ofdm_register(state->d, xd_p_reg_unplug_th,
state->original_if_unplug_th); if (ret) return ret; /* set tuner */
deb_info("set tuner\n");
ret = fe->ops.tuner_ops.set_params(fe); if (ret) return ret;
/* trigger ofsm */
deb_info("trigger ofsm\n");
temp = 0;
ret = af9005_write_tuner_registers(state->d, 0xffff, &temp, 1); if (ret) return ret;
/* clear retrain and freeze flag */
deb_info("clear retrain and freeze flag\n");
ret =
af9005_write_register_bits(state->d,
xd_p_reg_api_retrain_request,
reg_api_retrain_request_pos, 2, 0); if (ret) return ret;
/* reset pre viterbi and post viterbi registers and statistics */
af9005_reset_pre_viterbi(fe);
af9005_reset_post_viterbi(fe);
state->pre_vit_error_count = 0;
state->pre_vit_bit_count = 0;
state->ber = 0;
state->post_vit_error_count = 0; /* state->unc = 0; commented out since it should be ever increasing */
state->abort_count = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.