^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * mxl111sf-demod.c - driver for the MaxLinear MXL111SF DVB-T demodulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "mxl111sf-demod.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "mxl111sf-reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) /* debug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static int mxl111sf_demod_debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) module_param_named(debug, mxl111sf_demod_debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define mxl_dbg(fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) if (mxl111sf_demod_debug) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) mxl_printk(KERN_DEBUG, fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct mxl111sf_demod_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct mxl111sf_state *mxl_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) const struct mxl111sf_demod_config *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct dvb_frontend fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static int mxl111sf_demod_read_reg(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) u8 addr, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return (state->cfg->read_reg) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) state->cfg->read_reg(state->mxl_state, addr, data) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int mxl111sf_demod_write_reg(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u8 addr, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return (state->cfg->write_reg) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) state->cfg->write_reg(state->mxl_state, addr, data) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int mxl111sf_demod_program_regs(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return (state->cfg->program_regs) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* TPS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int mxl1x1sf_demod_get_tps_code_rate(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) enum fe_code_rate *code_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int ret = mxl111sf_demod_read_reg(state, V6_CODE_RATE_TPS_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* bit<2:0> - 000:1/2, 001:2/3, 010:3/4, 011:5/6, 100:7/8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) switch (val & V6_CODE_RATE_TPS_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) *code_rate = FEC_1_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) *code_rate = FEC_2_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) *code_rate = FEC_3_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) *code_rate = FEC_5_6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) *code_rate = FEC_7_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int mxl1x1sf_demod_get_tps_modulation(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) enum fe_modulation *modulation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int ret = mxl111sf_demod_read_reg(state, V6_MODORDER_TPS_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* Constellation, 00 : QPSK, 01 : 16QAM, 10:64QAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) switch ((val & V6_PARAM_CONSTELLATION_MASK) >> 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) *modulation = QPSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) *modulation = QAM_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) *modulation = QAM_64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int mxl1x1sf_demod_get_tps_guard_fft_mode(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) enum fe_transmit_mode *fft_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int ret = mxl111sf_demod_read_reg(state, V6_MODE_TPS_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* FFT Mode, 00:2K, 01:8K, 10:4K */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) switch ((val & V6_PARAM_FFT_MODE_MASK) >> 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) *fft_mode = TRANSMISSION_MODE_2K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) *fft_mode = TRANSMISSION_MODE_8K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) *fft_mode = TRANSMISSION_MODE_4K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int mxl1x1sf_demod_get_tps_guard_interval(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) enum fe_guard_interval *guard)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int ret = mxl111sf_demod_read_reg(state, V6_CP_TPS_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* 00:1/32, 01:1/16, 10:1/8, 11:1/4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) switch ((val & V6_PARAM_GI_MASK) >> 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) *guard = GUARD_INTERVAL_1_32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) *guard = GUARD_INTERVAL_1_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) *guard = GUARD_INTERVAL_1_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) *guard = GUARD_INTERVAL_1_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int mxl1x1sf_demod_get_tps_hierarchy(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) enum fe_hierarchy *hierarchy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int ret = mxl111sf_demod_read_reg(state, V6_TPS_HIERACHY_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /* bit<6:4> - 000:Non hierarchy, 001:1, 010:2, 011:4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) switch ((val & V6_TPS_HIERARCHY_INFO_MASK) >> 6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) *hierarchy = HIERARCHY_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) *hierarchy = HIERARCHY_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) *hierarchy = HIERARCHY_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) *hierarchy = HIERARCHY_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /* LOCKS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int mxl1x1sf_demod_get_sync_lock_status(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int *sync_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) u8 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) int ret = mxl111sf_demod_read_reg(state, V6_SYNC_LOCK_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) *sync_lock = (val & SYNC_LOCK_MASK) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int mxl1x1sf_demod_get_rs_lock_status(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int *rs_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) u8 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int ret = mxl111sf_demod_read_reg(state, V6_RS_LOCK_DET_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) *rs_lock = (val & RS_LOCK_DET_MASK) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int mxl1x1sf_demod_get_tps_lock_status(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) int *tps_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) u8 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int ret = mxl111sf_demod_read_reg(state, V6_TPS_LOCK_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) *tps_lock = (val & V6_PARAM_TPS_LOCK_MASK) >> 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int mxl1x1sf_demod_get_fec_lock_status(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int *fec_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) u8 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) int ret = mxl111sf_demod_read_reg(state, V6_IRQ_STATUS_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) *fec_lock = (val & IRQ_MASK_FEC_LOCK) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int mxl1x1sf_demod_get_cp_lock_status(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) int *cp_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) u8 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int ret = mxl111sf_demod_read_reg(state, V6_CP_LOCK_DET_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) *cp_lock = (val & V6_CP_LOCK_DET_MASK) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static int mxl1x1sf_demod_reset_irq_status(struct mxl111sf_demod_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return mxl111sf_demod_write_reg(state, 0x0e, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct mxl111sf_demod_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct mxl111sf_reg_ctrl_info phy_pll_patch[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {0x00, 0xff, 0x01}, /* change page to 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {0x40, 0xff, 0x05},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {0x40, 0xff, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {0x41, 0xff, 0xca},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {0x41, 0xff, 0xc0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {0x00, 0xff, 0x00}, /* change page to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {0, 0, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) mxl_dbg("()");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (fe->ops.tuner_ops.set_params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ret = fe->ops.tuner_ops.set_params(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) msleep(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ret = mxl111sf_demod_program_regs(state, phy_pll_patch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) mxl_fail(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) msleep(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) ret = mxl1x1sf_demod_reset_irq_status(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) mxl_fail(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* resets TS Packet error count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /* After setting 7th bit of V5_PER_COUNT_RESET_REG, it should be reset to 0. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) int mxl1x1sf_demod_reset_packet_error_count(struct mxl111sf_demod_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct mxl111sf_reg_ctrl_info reset_per_count[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {0x20, 0x01, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {0x20, 0x01, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {0, 0, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return mxl111sf_demod_program_regs(state, reset_per_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /* returns TS Packet error count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /* PER Count = FEC_PER_COUNT * (2 ** (FEC_PER_SCALE * 4)) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static int mxl111sf_demod_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct mxl111sf_demod_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) u32 fec_per_count, fec_per_scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) *ucblocks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /* FEC_PER_COUNT Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_COUNT_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) fec_per_count = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /* FEC_PER_SCALE Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_SCALE_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) val &= V6_FEC_PER_SCALE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) val *= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) fec_per_scale = 1 << val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) fec_per_count *= fec_per_scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) *ucblocks = fec_per_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) #ifdef MXL111SF_DEMOD_ENABLE_CALCULATIONS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) /* FIXME: leaving this enabled breaks the build on some architectures,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * and we shouldn't have any floating point math in the kernel, anyway.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * These macros need to be re-written, but it's harmless to simply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * return zero for now. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) #define CALCULATE_BER(avg_errors, count) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) ((u32)(avg_errors * 4)/(count*64*188*8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) #define CALCULATE_SNR(data) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ((u32)((10 * (u32)data / 64) - 2.5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) #define CALCULATE_BER(avg_errors, count) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) #define CALCULATE_SNR(data) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static int mxl111sf_demod_read_ber(struct dvb_frontend *fe, u32 *ber)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct mxl111sf_demod_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) u8 val1, val2, val3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) *ber = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_LSB_REG, &val1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_MSB_REG, &val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) ret = mxl111sf_demod_read_reg(state, V6_N_ACCUMULATE_REG, &val3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) *ber = CALCULATE_BER((val1 | (val2 << 8)), val3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static int mxl111sf_demod_calc_snr(struct mxl111sf_demod_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) u16 *snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) u8 val1, val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) *snr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_LSB_REG, &val1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_MSB_REG, &val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) *snr = CALCULATE_SNR(val1 | ((val2 & 0x03) << 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) static int mxl111sf_demod_read_snr(struct dvb_frontend *fe, u16 *snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct mxl111sf_demod_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) int ret = mxl111sf_demod_calc_snr(state, snr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) *snr /= 10; /* 0.1 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static int mxl111sf_demod_read_status(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) enum fe_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) struct mxl111sf_demod_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) int ret, locked, cr_lock, sync_lock, fec_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) *status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) ret = mxl1x1sf_demod_get_rs_lock_status(state, &locked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) ret = mxl1x1sf_demod_get_tps_lock_status(state, &cr_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) ret = mxl1x1sf_demod_get_sync_lock_status(state, &sync_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ret = mxl1x1sf_demod_get_fec_lock_status(state, &fec_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (mxl_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) *status |= FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (cr_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) *status |= FE_HAS_CARRIER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (sync_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) *status |= FE_HAS_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (fec_lock) /* false positives? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) *status |= FE_HAS_VITERBI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if ((locked) && (cr_lock) && (sync_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) *status |= FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) u16 *signal_strength)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct mxl111sf_demod_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) enum fe_modulation modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) u16 snr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) ret = mxl111sf_demod_calc_snr(state, &snr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) ret = mxl1x1sf_demod_get_tps_modulation(state, &modulation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) switch (modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) case QPSK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) *signal_strength = (snr >= 1300) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) min(65535, snr * 44) : snr * 38;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) case QAM_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) *signal_strength = (snr >= 1500) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) min(65535, snr * 38) : snr * 33;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) *signal_strength = (snr >= 2000) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) min(65535, snr * 29) : snr * 25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) *signal_strength = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) struct dtv_frontend_properties *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) struct mxl111sf_demod_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) mxl_dbg("()");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) p->inversion = /* FIXME */ ? INVERSION_ON : INVERSION_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (fe->ops.tuner_ops.get_bandwidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) fe->ops.tuner_ops.get_bandwidth(fe, &p->bandwidth_hz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (fe->ops.tuner_ops.get_frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) fe->ops.tuner_ops.get_frequency(fe, &p->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_HP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_LP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) mxl1x1sf_demod_get_tps_modulation(state, &p->modulation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) mxl1x1sf_demod_get_tps_guard_fft_mode(state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) &p->transmission_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) mxl1x1sf_demod_get_tps_guard_interval(state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) &p->guard_interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) mxl1x1sf_demod_get_tps_hierarchy(state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) &p->hierarchy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) int mxl111sf_demod_get_tune_settings(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct dvb_frontend_tune_settings *tune)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) tune->min_delay_ms = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) static void mxl111sf_demod_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct mxl111sf_demod_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) mxl_dbg("()");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) fe->demodulator_priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) static const struct dvb_frontend_ops mxl111sf_demod_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) .delsys = { SYS_DVBT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) .name = "MaxLinear MxL111SF DVB-T demodulator",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) .frequency_min_hz = 177 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) .frequency_max_hz = 858 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) .frequency_stepsize_hz = 166666,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) FE_CAN_QAM_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) .release = mxl111sf_demod_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) .init = mxl111sf_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) .i2c_gate_ctrl = mxl111sf_i2c_gate_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) .set_frontend = mxl111sf_demod_set_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) .get_frontend = mxl111sf_demod_get_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) .get_tune_settings = mxl111sf_demod_get_tune_settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) .read_status = mxl111sf_demod_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) .read_signal_strength = mxl111sf_demod_read_signal_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) .read_ber = mxl111sf_demod_read_ber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) .read_snr = mxl111sf_demod_read_snr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) .read_ucblocks = mxl111sf_demod_read_ucblocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) const struct mxl111sf_demod_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) struct mxl111sf_demod_state *state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) mxl_dbg("()");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) state = kzalloc(sizeof(struct mxl111sf_demod_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (state == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) state->mxl_state = mxl_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) state->cfg = cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) memcpy(&state->fe.ops, &mxl111sf_demod_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) sizeof(struct dvb_frontend_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) state->fe.demodulator_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return &state->fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) EXPORT_SYMBOL_GPL(mxl111sf_demod_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) MODULE_VERSION("0.1");