📄 af9013.c
字号:
signal_strength = 0xffff; state->signal_strength = signal_strength; }error: return ret;}static int af9013_update_statistics(struct dvb_frontend *fe){ struct af9013_state *state = fe->demodulator_priv; int ret; if (time_before(jiffies, state->next_statistics_check)) return 0; /* set minimum statistic update interval */ state->next_statistics_check = jiffies + msecs_to_jiffies(1200); ret = af9013_update_signal_strength(fe); if (ret) goto error; ret = af9013_update_snr(fe); if (ret) goto error; ret = af9013_update_ber_unc(fe); if (ret) goto error;error: return ret;}static int af9013_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *fesettings){ fesettings->min_delay_ms = 800; fesettings->step_size = 0; fesettings->max_drift = 0; return 0;}static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status){ struct af9013_state *state = fe->demodulator_priv; int ret = 0; u8 tmp; *status = 0; /* TPS lock */ ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp); if (ret) goto error; if (tmp) *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL; /* MPEG2 lock */ ret = af9013_read_reg_bits(state, 0xd507, 6, 1, &tmp); if (ret) goto error; if (tmp) *status |= FE_HAS_SYNC | FE_HAS_LOCK; if (!*status & FE_HAS_SIGNAL) { /* AGC lock */ ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp); if (ret) goto error; if (tmp) *status |= FE_HAS_SIGNAL; } if (!*status & FE_HAS_CARRIER) { /* CFO lock */ ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp); if (ret) goto error; if (tmp) *status |= FE_HAS_CARRIER; } if (!*status & FE_HAS_CARRIER) { /* SFOE lock */ ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp); if (ret) goto error; if (tmp) *status |= FE_HAS_CARRIER; } ret = af9013_update_statistics(fe);error: return ret;}static int af9013_read_ber(struct dvb_frontend *fe, u32 *ber){ struct af9013_state *state = fe->demodulator_priv; int ret; ret = af9013_update_statistics(fe); *ber = state->ber; return ret;}static int af9013_read_signal_strength(struct dvb_frontend *fe, u16 *strength){ struct af9013_state *state = fe->demodulator_priv; int ret; ret = af9013_update_statistics(fe); *strength = state->signal_strength; return ret;}static int af9013_read_snr(struct dvb_frontend *fe, u16 *snr){ struct af9013_state *state = fe->demodulator_priv; int ret; ret = af9013_update_statistics(fe); *snr = state->snr; return ret;}static int af9013_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks){ struct af9013_state *state = fe->demodulator_priv; int ret; ret = af9013_update_statistics(fe); *ucblocks = state->ucblocks; return ret;}static int af9013_sleep(struct dvb_frontend *fe){ struct af9013_state *state = fe->demodulator_priv; int ret; deb_info("%s\n", __func__); ret = af9013_lock_led(state, 0); if (ret) goto error; ret = af9013_power_ctrl(state, 0);error: return ret;}static int af9013_init(struct dvb_frontend *fe){ struct af9013_state *state = fe->demodulator_priv; int ret, i, len; u8 tmp0, tmp1; struct regdesc *init; deb_info("%s\n", __func__); /* reset OFDM */ ret = af9013_reset(state, 0); if (ret) goto error; /* power on */ ret = af9013_power_ctrl(state, 1); if (ret) goto error; /* enable ADC */ ret = af9013_write_reg(state, 0xd73a, 0xa4); if (ret) goto error; /* write API version to firmware */ for (i = 0; i < sizeof(state->config.api_version); i++) { ret = af9013_write_reg(state, 0x9bf2 + i, state->config.api_version[i]); if (ret) goto error; } /* program ADC control */ ret = af9013_set_adc_ctrl(state); if (ret) goto error; /* set I2C master clock */ ret = af9013_write_reg(state, 0xd416, 0x14); if (ret) goto error; /* set 16 embx */ ret = af9013_write_reg_bits(state, 0xd700, 1, 1, 1); if (ret) goto error; /* set no trigger */ ret = af9013_write_reg_bits(state, 0xd700, 2, 1, 0); if (ret) goto error; /* set read-update bit for constellation */ ret = af9013_write_reg_bits(state, 0xd371, 1, 1, 1); if (ret) goto error; /* enable FEC monitor */ ret = af9013_write_reg_bits(state, 0xd392, 1, 1, 1); if (ret) goto error; /* load OFSM settings */ deb_info("%s: load ofsm settings\n", __func__); len = ARRAY_SIZE(ofsm_init); init = ofsm_init; for (i = 0; i < len; i++) { ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos, init[i].len, init[i].val); if (ret) goto error; } /* load tuner specific settings */ deb_info("%s: load tuner specific settings\n", __func__); switch (state->config.tuner) { case AF9013_TUNER_MXL5003D: len = ARRAY_SIZE(tuner_init_mxl5003d); init = tuner_init_mxl5003d; break; case AF9013_TUNER_MXL5005D: case AF9013_TUNER_MXL5005R: len = ARRAY_SIZE(tuner_init_mxl5005); init = tuner_init_mxl5005; break; case AF9013_TUNER_ENV77H11D5: len = ARRAY_SIZE(tuner_init_env77h11d5); init = tuner_init_env77h11d5; break; case AF9013_TUNER_MT2060: len = ARRAY_SIZE(tuner_init_mt2060); init = tuner_init_mt2060; break; case AF9013_TUNER_MC44S803: len = ARRAY_SIZE(tuner_init_mc44s803); init = tuner_init_mc44s803; break; case AF9013_TUNER_QT1010: case AF9013_TUNER_QT1010A: len = ARRAY_SIZE(tuner_init_qt1010); init = tuner_init_qt1010; break; case AF9013_TUNER_MT2060_2: len = ARRAY_SIZE(tuner_init_mt2060_2); init = tuner_init_mt2060_2; break; case AF9013_TUNER_TDA18271: len = ARRAY_SIZE(tuner_init_tda18271); init = tuner_init_tda18271; break; case AF9013_TUNER_UNKNOWN: default: len = ARRAY_SIZE(tuner_init_unknown); init = tuner_init_unknown; break; } for (i = 0; i < len; i++) { ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos, init[i].len, init[i].val); if (ret) goto error; } /* set TS mode */ deb_info("%s: setting ts mode\n", __func__); tmp0 = 0; /* parallel mode */ tmp1 = 0; /* serial mode */ switch (state->config.output_mode) { case AF9013_OUTPUT_MODE_PARALLEL: tmp0 = 1; break; case AF9013_OUTPUT_MODE_SERIAL: tmp1 = 1; break; case AF9013_OUTPUT_MODE_USB: /* usb mode for AF9015 */ default: break; } ret = af9013_write_reg_bits(state, 0xd500, 1, 1, tmp0); /* parallel */ if (ret) goto error; ret = af9013_write_reg_bits(state, 0xd500, 2, 1, tmp1); /* serial */ if (ret) goto error; /* enable lock led */ ret = af9013_lock_led(state, 1); if (ret) goto error;error: return ret;}static struct dvb_frontend_ops af9013_ops;static int af9013_download_firmware(struct af9013_state *state){ int i, len, packets, remainder, ret; const struct firmware *fw; u16 addr = 0x5100; /* firmware start address */ u16 checksum = 0; u8 val; u8 fw_params[4]; u8 *data; u8 *fw_file = AF9013_DEFAULT_FIRMWARE; msleep(100); /* check whether firmware is already running */ ret = af9013_read_reg(state, 0x98be, &val); if (ret) goto error; else deb_info("%s: firmware status:%02x\n", __func__, val); if (val == 0x0c) /* fw is running, no need for download */ goto exit; info("found a '%s' in cold state, will try to load a firmware", af9013_ops.info.name); /* request the firmware, this will block and timeout */ ret = request_firmware(&fw, fw_file, &state->i2c->dev); if (ret) { err("did not find the firmware file. (%s) " "Please see linux/Documentation/dvb/ for more details" \ " on firmware-problems. (%d)", fw_file, ret); goto error; } info("downloading firmware from file '%s'", fw_file); /* calc checksum */ for (i = 0; i < fw->size; i++) checksum += fw->data[i]; fw_params[0] = checksum >> 8; fw_params[1] = checksum & 0xff; fw_params[2] = fw->size >> 8; fw_params[3] = fw->size & 0xff; /* write fw checksum & size */ ret = af9013_write_ofsm_regs(state, 0x50fc, fw_params, sizeof(fw_params)); if (ret) goto error_release; #define FW_PACKET_MAX_DATA 16 packets = fw->size / FW_PACKET_MAX_DATA; remainder = fw->size % FW_PACKET_MAX_DATA; len = FW_PACKET_MAX_DATA; for (i = 0; i <= packets; i++) { if (i == packets) /* set size of the last packet */ len = remainder; data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA); ret = af9013_write_ofsm_regs(state, addr, data, len); addr += FW_PACKET_MAX_DATA; if (ret) { err("firmware download failed at %d with %d", i, ret); goto error_release; } } /* request boot firmware */ ret = af9013_write_reg(state, 0xe205, 1); if (ret) goto error_release; for (i = 0; i < 15; i++) { msleep(100); /* check firmware status */ ret = af9013_read_reg(state, 0x98be, &val); if (ret) goto error_release; deb_info("%s: firmware status:%02x\n", __func__, val); if (val == 0x0c || val == 0x04) /* success or fail */ break; } if (val == 0x04) { err("firmware did not run"); ret = -1; } else if (val != 0x0c) { err("firmware boot timeout"); ret = -1; }error_release: release_firmware(fw);error:exit: if (!ret) info("found a '%s' in warm state.", af9013_ops.info.name); return ret;}static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable){ int ret; struct af9013_state *state = fe->demodulator_priv; deb_info("%s: enable:%d\n", __func__, enable); if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) ret = af9013_write_reg_bits(state, 0xd417, 3, 1, enable); else ret = af9013_write_reg_bits(state, 0xd607, 2, 1, enable); return ret;}static void af9013_release(struct dvb_frontend *fe){ struct af9013_state *state = fe->demodulator_priv; kfree(state);}static struct dvb_frontend_ops af9013_ops;struct dvb_frontend *af9013_attach(const struct af9013_config *config, struct i2c_adapter *i2c){ int ret; struct af9013_state *state = NULL; u8 buf[3], i; /* allocate memory for the internal state */ state = kzalloc(sizeof(struct af9013_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ state->i2c = i2c; memcpy(&state->config, config, sizeof(struct af9013_config)); /* chip version */ ret = af9013_read_reg_bits(state, 0xd733, 4, 4, &buf[2]); if (ret) goto error; /* ROM version */ for (i = 0; i < 2; i++) { ret = af9013_read_reg(state, 0x116b + i, &buf[i]); if (ret) goto error; } deb_info("%s: chip version:%d ROM version:%d.%d\n", __func__, buf[2], buf[0], buf[1]); /* download firmware */ if (state->config.output_mode != AF9013_OUTPUT_MODE_USB) { ret = af9013_download_firmware(state); if (ret) goto error; } /* firmware version */ for (i = 0; i < 3; i++) { ret = af9013_read_reg(state, 0x5103 + i, &buf[i]); if (ret) goto error; } info("firmware version:%d.%d.%d", buf[0], buf[1], buf[2]); /* settings for mp2if */ if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) { /* AF9015 split PSB to 1.5k + 0.5k */ ret = af9013_write_reg_bits(state, 0xd50b, 2, 1, 1); } else { /* AF9013 change the output bit to data7 */ ret = af9013_write_reg_bits(state, 0xd500, 3, 1, 1); if (ret) goto error; /* AF9013 set mpeg to full speed */ ret = af9013_write_reg_bits(state, 0xd502, 4, 1, 1); } if (ret) goto error; ret = af9013_write_reg_bits(state, 0xd520, 4, 1, 1); if (ret) goto error; /* set GPIOs */ for (i = 0; i < sizeof(state->config.gpio); i++) { ret = af9013_set_gpio(state, i, state->config.gpio[i]); if (ret) goto error; } /* create dvb_frontend */ memcpy(&state->frontend.ops, &af9013_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend;error: kfree(state); return NULL;}EXPORT_SYMBOL(af9013_attach);static struct dvb_frontend_ops af9013_ops = { .info = { .name = "Afatech AF9013 DVB-T", .type = FE_OFDM, .frequency_min = 174000000, .frequency_max = 862000000, .frequency_stepsize = 250000, .frequency_tolerance = 0, .caps = 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_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS }, .release = af9013_release, .init = af9013_init, .sleep = af9013_sleep, .i2c_gate_ctrl = af9013_i2c_gate_ctrl, .set_frontend = af9013_set_frontend, .get_frontend = af9013_get_frontend, .get_tune_settings = af9013_get_tune_settings, .read_status = af9013_read_status, .read_ber = af9013_read_ber, .read_signal_strength = af9013_read_signal_strength, .read_snr = af9013_read_snr, .read_ucblocks = af9013_read_ucblocks,};module_param_named(debug, af9013_debug, int, 0644);MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");MODULE_DESCRIPTION("Afatech AF9013 DVB-T demodulator driver");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -