Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  mxl111sf-demod.c - driver for the MaxLinear MXL111SF DVB-T demodulator
0004  *
0005  *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
0006  */
0007 
0008 #include "mxl111sf-demod.h"
0009 #include "mxl111sf-reg.h"
0010 
0011 /* debug */
0012 static int mxl111sf_demod_debug;
0013 module_param_named(debug, mxl111sf_demod_debug, int, 0644);
0014 MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
0015 
0016 #define mxl_dbg(fmt, arg...) \
0017     if (mxl111sf_demod_debug) \
0018         mxl_printk(KERN_DEBUG, fmt, ##arg)
0019 
0020 /* ------------------------------------------------------------------------ */
0021 
0022 struct mxl111sf_demod_state {
0023     struct mxl111sf_state *mxl_state;
0024 
0025     const struct mxl111sf_demod_config *cfg;
0026 
0027     struct dvb_frontend fe;
0028 };
0029 
0030 /* ------------------------------------------------------------------------ */
0031 
0032 static int mxl111sf_demod_read_reg(struct mxl111sf_demod_state *state,
0033                    u8 addr, u8 *data)
0034 {
0035     return (state->cfg->read_reg) ?
0036         state->cfg->read_reg(state->mxl_state, addr, data) :
0037         -EINVAL;
0038 }
0039 
0040 static int mxl111sf_demod_write_reg(struct mxl111sf_demod_state *state,
0041                     u8 addr, u8 data)
0042 {
0043     return (state->cfg->write_reg) ?
0044         state->cfg->write_reg(state->mxl_state, addr, data) :
0045         -EINVAL;
0046 }
0047 
0048 static
0049 int mxl111sf_demod_program_regs(struct mxl111sf_demod_state *state,
0050                 struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
0051 {
0052     return (state->cfg->program_regs) ?
0053         state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
0054         -EINVAL;
0055 }
0056 
0057 /* ------------------------------------------------------------------------ */
0058 /* TPS */
0059 
0060 static
0061 int mxl1x1sf_demod_get_tps_code_rate(struct mxl111sf_demod_state *state,
0062                      enum fe_code_rate *code_rate)
0063 {
0064     u8 val;
0065     int ret = mxl111sf_demod_read_reg(state, V6_CODE_RATE_TPS_REG, &val);
0066     /* bit<2:0> - 000:1/2, 001:2/3, 010:3/4, 011:5/6, 100:7/8 */
0067     if (mxl_fail(ret))
0068         goto fail;
0069 
0070     switch (val & V6_CODE_RATE_TPS_MASK) {
0071     case 0:
0072         *code_rate = FEC_1_2;
0073         break;
0074     case 1:
0075         *code_rate = FEC_2_3;
0076         break;
0077     case 2:
0078         *code_rate = FEC_3_4;
0079         break;
0080     case 3:
0081         *code_rate = FEC_5_6;
0082         break;
0083     case 4:
0084         *code_rate = FEC_7_8;
0085         break;
0086     }
0087 fail:
0088     return ret;
0089 }
0090 
0091 static
0092 int mxl1x1sf_demod_get_tps_modulation(struct mxl111sf_demod_state *state,
0093                       enum fe_modulation *modulation)
0094 {
0095     u8 val;
0096     int ret = mxl111sf_demod_read_reg(state, V6_MODORDER_TPS_REG, &val);
0097     /* Constellation, 00 : QPSK, 01 : 16QAM, 10:64QAM */
0098     if (mxl_fail(ret))
0099         goto fail;
0100 
0101     switch ((val & V6_PARAM_CONSTELLATION_MASK) >> 4) {
0102     case 0:
0103         *modulation = QPSK;
0104         break;
0105     case 1:
0106         *modulation = QAM_16;
0107         break;
0108     case 2:
0109         *modulation = QAM_64;
0110         break;
0111     }
0112 fail:
0113     return ret;
0114 }
0115 
0116 static
0117 int mxl1x1sf_demod_get_tps_guard_fft_mode(struct mxl111sf_demod_state *state,
0118                       enum fe_transmit_mode *fft_mode)
0119 {
0120     u8 val;
0121     int ret = mxl111sf_demod_read_reg(state, V6_MODE_TPS_REG, &val);
0122     /* FFT Mode, 00:2K, 01:8K, 10:4K */
0123     if (mxl_fail(ret))
0124         goto fail;
0125 
0126     switch ((val & V6_PARAM_FFT_MODE_MASK) >> 2) {
0127     case 0:
0128         *fft_mode = TRANSMISSION_MODE_2K;
0129         break;
0130     case 1:
0131         *fft_mode = TRANSMISSION_MODE_8K;
0132         break;
0133     case 2:
0134         *fft_mode = TRANSMISSION_MODE_4K;
0135         break;
0136     }
0137 fail:
0138     return ret;
0139 }
0140 
0141 static
0142 int mxl1x1sf_demod_get_tps_guard_interval(struct mxl111sf_demod_state *state,
0143                       enum fe_guard_interval *guard)
0144 {
0145     u8 val;
0146     int ret = mxl111sf_demod_read_reg(state, V6_CP_TPS_REG, &val);
0147     /* 00:1/32, 01:1/16, 10:1/8, 11:1/4 */
0148     if (mxl_fail(ret))
0149         goto fail;
0150 
0151     switch ((val & V6_PARAM_GI_MASK) >> 4) {
0152     case 0:
0153         *guard = GUARD_INTERVAL_1_32;
0154         break;
0155     case 1:
0156         *guard = GUARD_INTERVAL_1_16;
0157         break;
0158     case 2:
0159         *guard = GUARD_INTERVAL_1_8;
0160         break;
0161     case 3:
0162         *guard = GUARD_INTERVAL_1_4;
0163         break;
0164     }
0165 fail:
0166     return ret;
0167 }
0168 
0169 static
0170 int mxl1x1sf_demod_get_tps_hierarchy(struct mxl111sf_demod_state *state,
0171                      enum fe_hierarchy *hierarchy)
0172 {
0173     u8 val;
0174     int ret = mxl111sf_demod_read_reg(state, V6_TPS_HIERACHY_REG, &val);
0175     /* bit<6:4> - 000:Non hierarchy, 001:1, 010:2, 011:4 */
0176     if (mxl_fail(ret))
0177         goto fail;
0178 
0179     switch ((val & V6_TPS_HIERARCHY_INFO_MASK) >> 6) {
0180     case 0:
0181         *hierarchy = HIERARCHY_NONE;
0182         break;
0183     case 1:
0184         *hierarchy = HIERARCHY_1;
0185         break;
0186     case 2:
0187         *hierarchy = HIERARCHY_2;
0188         break;
0189     case 3:
0190         *hierarchy = HIERARCHY_4;
0191         break;
0192     }
0193 fail:
0194     return ret;
0195 }
0196 
0197 /* ------------------------------------------------------------------------ */
0198 /* LOCKS */
0199 
0200 static
0201 int mxl1x1sf_demod_get_sync_lock_status(struct mxl111sf_demod_state *state,
0202                     int *sync_lock)
0203 {
0204     u8 val = 0;
0205     int ret = mxl111sf_demod_read_reg(state, V6_SYNC_LOCK_REG, &val);
0206     if (mxl_fail(ret))
0207         goto fail;
0208     *sync_lock = (val & SYNC_LOCK_MASK) >> 4;
0209 fail:
0210     return ret;
0211 }
0212 
0213 static
0214 int mxl1x1sf_demod_get_rs_lock_status(struct mxl111sf_demod_state *state,
0215                       int *rs_lock)
0216 {
0217     u8 val = 0;
0218     int ret = mxl111sf_demod_read_reg(state, V6_RS_LOCK_DET_REG, &val);
0219     if (mxl_fail(ret))
0220         goto fail;
0221     *rs_lock = (val & RS_LOCK_DET_MASK) >> 3;
0222 fail:
0223     return ret;
0224 }
0225 
0226 static
0227 int mxl1x1sf_demod_get_tps_lock_status(struct mxl111sf_demod_state *state,
0228                        int *tps_lock)
0229 {
0230     u8 val = 0;
0231     int ret = mxl111sf_demod_read_reg(state, V6_TPS_LOCK_REG, &val);
0232     if (mxl_fail(ret))
0233         goto fail;
0234     *tps_lock = (val & V6_PARAM_TPS_LOCK_MASK) >> 6;
0235 fail:
0236     return ret;
0237 }
0238 
0239 static
0240 int mxl1x1sf_demod_get_fec_lock_status(struct mxl111sf_demod_state *state,
0241                        int *fec_lock)
0242 {
0243     u8 val = 0;
0244     int ret = mxl111sf_demod_read_reg(state, V6_IRQ_STATUS_REG, &val);
0245     if (mxl_fail(ret))
0246         goto fail;
0247     *fec_lock = (val & IRQ_MASK_FEC_LOCK) >> 4;
0248 fail:
0249     return ret;
0250 }
0251 
0252 #if 0
0253 static
0254 int mxl1x1sf_demod_get_cp_lock_status(struct mxl111sf_demod_state *state,
0255                       int *cp_lock)
0256 {
0257     u8 val = 0;
0258     int ret = mxl111sf_demod_read_reg(state, V6_CP_LOCK_DET_REG, &val);
0259     if (mxl_fail(ret))
0260         goto fail;
0261     *cp_lock = (val & V6_CP_LOCK_DET_MASK) >> 2;
0262 fail:
0263     return ret;
0264 }
0265 #endif
0266 
0267 static int mxl1x1sf_demod_reset_irq_status(struct mxl111sf_demod_state *state)
0268 {
0269     return mxl111sf_demod_write_reg(state, 0x0e, 0xff);
0270 }
0271 
0272 /* ------------------------------------------------------------------------ */
0273 
0274 static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe)
0275 {
0276     struct mxl111sf_demod_state *state = fe->demodulator_priv;
0277     int ret = 0;
0278 
0279     struct mxl111sf_reg_ctrl_info phy_pll_patch[] = {
0280         {0x00, 0xff, 0x01}, /* change page to 1 */
0281         {0x40, 0xff, 0x05},
0282         {0x40, 0xff, 0x01},
0283         {0x41, 0xff, 0xca},
0284         {0x41, 0xff, 0xc0},
0285         {0x00, 0xff, 0x00}, /* change page to 0 */
0286         {0,    0,    0}
0287     };
0288 
0289     mxl_dbg("()");
0290 
0291     if (fe->ops.tuner_ops.set_params) {
0292         ret = fe->ops.tuner_ops.set_params(fe);
0293         if (mxl_fail(ret))
0294             goto fail;
0295         msleep(50);
0296     }
0297     ret = mxl111sf_demod_program_regs(state, phy_pll_patch);
0298     mxl_fail(ret);
0299     msleep(50);
0300     ret = mxl1x1sf_demod_reset_irq_status(state);
0301     mxl_fail(ret);
0302     msleep(100);
0303 fail:
0304     return ret;
0305 }
0306 
0307 /* ------------------------------------------------------------------------ */
0308 
0309 #if 0
0310 /* resets TS Packet error count */
0311 /* After setting 7th bit of V5_PER_COUNT_RESET_REG, it should be reset to 0. */
0312 static
0313 int mxl1x1sf_demod_reset_packet_error_count(struct mxl111sf_demod_state *state)
0314 {
0315     struct mxl111sf_reg_ctrl_info reset_per_count[] = {
0316         {0x20, 0x01, 0x01},
0317         {0x20, 0x01, 0x00},
0318         {0,    0,    0}
0319     };
0320     return mxl111sf_demod_program_regs(state, reset_per_count);
0321 }
0322 #endif
0323 
0324 /* returns TS Packet error count */
0325 /* PER Count = FEC_PER_COUNT * (2 ** (FEC_PER_SCALE * 4)) */
0326 static int mxl111sf_demod_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
0327 {
0328     struct mxl111sf_demod_state *state = fe->demodulator_priv;
0329     u32 fec_per_count, fec_per_scale;
0330     u8 val;
0331     int ret;
0332 
0333     *ucblocks = 0;
0334 
0335     /* FEC_PER_COUNT Register */
0336     ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_COUNT_REG, &val);
0337     if (mxl_fail(ret))
0338         goto fail;
0339 
0340     fec_per_count = val;
0341 
0342     /* FEC_PER_SCALE Register */
0343     ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_SCALE_REG, &val);
0344     if (mxl_fail(ret))
0345         goto fail;
0346 
0347     val &= V6_FEC_PER_SCALE_MASK;
0348     val *= 4;
0349 
0350     fec_per_scale = 1 << val;
0351 
0352     fec_per_count *= fec_per_scale;
0353 
0354     *ucblocks = fec_per_count;
0355 fail:
0356     return ret;
0357 }
0358 
0359 #ifdef MXL111SF_DEMOD_ENABLE_CALCULATIONS
0360 /* FIXME: leaving this enabled breaks the build on some architectures,
0361  * and we shouldn't have any floating point math in the kernel, anyway.
0362  *
0363  * These macros need to be re-written, but it's harmless to simply
0364  * return zero for now. */
0365 #define CALCULATE_BER(avg_errors, count) \
0366     ((u32)(avg_errors * 4)/(count*64*188*8))
0367 #define CALCULATE_SNR(data) \
0368     ((u32)((10 * (u32)data / 64) - 2.5))
0369 #else
0370 #define CALCULATE_BER(avg_errors, count) 0
0371 #define CALCULATE_SNR(data) 0
0372 #endif
0373 
0374 static int mxl111sf_demod_read_ber(struct dvb_frontend *fe, u32 *ber)
0375 {
0376     struct mxl111sf_demod_state *state = fe->demodulator_priv;
0377     u8 val1, val2, val3;
0378     int ret;
0379 
0380     *ber = 0;
0381 
0382     ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_LSB_REG, &val1);
0383     if (mxl_fail(ret))
0384         goto fail;
0385     ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_MSB_REG, &val2);
0386     if (mxl_fail(ret))
0387         goto fail;
0388     ret = mxl111sf_demod_read_reg(state, V6_N_ACCUMULATE_REG, &val3);
0389     if (mxl_fail(ret))
0390         goto fail;
0391 
0392     *ber = CALCULATE_BER((val1 | (val2 << 8)), val3);
0393 fail:
0394     return ret;
0395 }
0396 
0397 static int mxl111sf_demod_calc_snr(struct mxl111sf_demod_state *state,
0398                    u16 *snr)
0399 {
0400     u8 val1, val2;
0401     int ret;
0402 
0403     *snr = 0;
0404 
0405     ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_LSB_REG, &val1);
0406     if (mxl_fail(ret))
0407         goto fail;
0408     ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_MSB_REG, &val2);
0409     if (mxl_fail(ret))
0410         goto fail;
0411 
0412     *snr = CALCULATE_SNR(val1 | ((val2 & 0x03) << 8));
0413 fail:
0414     return ret;
0415 }
0416 
0417 static int mxl111sf_demod_read_snr(struct dvb_frontend *fe, u16 *snr)
0418 {
0419     struct mxl111sf_demod_state *state = fe->demodulator_priv;
0420 
0421     int ret = mxl111sf_demod_calc_snr(state, snr);
0422     if (mxl_fail(ret))
0423         goto fail;
0424 
0425     *snr /= 10; /* 0.1 dB */
0426 fail:
0427     return ret;
0428 }
0429 
0430 static int mxl111sf_demod_read_status(struct dvb_frontend *fe,
0431                       enum fe_status *status)
0432 {
0433     struct mxl111sf_demod_state *state = fe->demodulator_priv;
0434     int ret, locked, cr_lock, sync_lock, fec_lock;
0435 
0436     *status = 0;
0437 
0438     ret = mxl1x1sf_demod_get_rs_lock_status(state, &locked);
0439     if (mxl_fail(ret))
0440         goto fail;
0441     ret = mxl1x1sf_demod_get_tps_lock_status(state, &cr_lock);
0442     if (mxl_fail(ret))
0443         goto fail;
0444     ret = mxl1x1sf_demod_get_sync_lock_status(state, &sync_lock);
0445     if (mxl_fail(ret))
0446         goto fail;
0447     ret = mxl1x1sf_demod_get_fec_lock_status(state, &fec_lock);
0448     if (mxl_fail(ret))
0449         goto fail;
0450 
0451     if (locked)
0452         *status |= FE_HAS_SIGNAL;
0453     if (cr_lock)
0454         *status |= FE_HAS_CARRIER;
0455     if (sync_lock)
0456         *status |= FE_HAS_SYNC;
0457     if (fec_lock) /* false positives? */
0458         *status |= FE_HAS_VITERBI;
0459 
0460     if ((locked) && (cr_lock) && (sync_lock))
0461         *status |= FE_HAS_LOCK;
0462 fail:
0463     return ret;
0464 }
0465 
0466 static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe,
0467                            u16 *signal_strength)
0468 {
0469     struct mxl111sf_demod_state *state = fe->demodulator_priv;
0470     enum fe_modulation modulation;
0471     int ret;
0472     u16 snr;
0473 
0474     ret = mxl111sf_demod_calc_snr(state, &snr);
0475     if (ret < 0)
0476         return ret;
0477     ret = mxl1x1sf_demod_get_tps_modulation(state, &modulation);
0478     if (ret < 0)
0479         return ret;
0480 
0481     switch (modulation) {
0482     case QPSK:
0483         *signal_strength = (snr >= 1300) ?
0484             min(65535, snr * 44) : snr * 38;
0485         break;
0486     case QAM_16:
0487         *signal_strength = (snr >= 1500) ?
0488             min(65535, snr * 38) : snr * 33;
0489         break;
0490     case QAM_64:
0491         *signal_strength = (snr >= 2000) ?
0492             min(65535, snr * 29) : snr * 25;
0493         break;
0494     default:
0495         *signal_strength = 0;
0496         return -EINVAL;
0497     }
0498 
0499     return 0;
0500 }
0501 
0502 static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe,
0503                        struct dtv_frontend_properties *p)
0504 {
0505     struct mxl111sf_demod_state *state = fe->demodulator_priv;
0506 
0507     mxl_dbg("()");
0508 #if 0
0509     p->inversion = /* FIXME */ ? INVERSION_ON : INVERSION_OFF;
0510 #endif
0511     if (fe->ops.tuner_ops.get_bandwidth)
0512         fe->ops.tuner_ops.get_bandwidth(fe, &p->bandwidth_hz);
0513     if (fe->ops.tuner_ops.get_frequency)
0514         fe->ops.tuner_ops.get_frequency(fe, &p->frequency);
0515     mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_HP);
0516     mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_LP);
0517     mxl1x1sf_demod_get_tps_modulation(state, &p->modulation);
0518     mxl1x1sf_demod_get_tps_guard_fft_mode(state,
0519                           &p->transmission_mode);
0520     mxl1x1sf_demod_get_tps_guard_interval(state,
0521                           &p->guard_interval);
0522     mxl1x1sf_demod_get_tps_hierarchy(state,
0523                      &p->hierarchy);
0524 
0525     return 0;
0526 }
0527 
0528 static
0529 int mxl111sf_demod_get_tune_settings(struct dvb_frontend *fe,
0530                      struct dvb_frontend_tune_settings *tune)
0531 {
0532     tune->min_delay_ms = 1000;
0533     return 0;
0534 }
0535 
0536 static void mxl111sf_demod_release(struct dvb_frontend *fe)
0537 {
0538     struct mxl111sf_demod_state *state = fe->demodulator_priv;
0539     mxl_dbg("()");
0540     kfree(state);
0541     fe->demodulator_priv = NULL;
0542 }
0543 
0544 static const struct dvb_frontend_ops mxl111sf_demod_ops = {
0545     .delsys = { SYS_DVBT },
0546     .info = {
0547         .name               = "MaxLinear MxL111SF DVB-T demodulator",
0548         .frequency_min_hz      = 177 * MHz,
0549         .frequency_max_hz      = 858 * MHz,
0550         .frequency_stepsize_hz = 166666,
0551         .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
0552             FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
0553             FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
0554             FE_CAN_QAM_AUTO |
0555             FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
0556             FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
0557     },
0558     .release              = mxl111sf_demod_release,
0559 #if 0
0560     .init                 = mxl111sf_init,
0561     .i2c_gate_ctrl        = mxl111sf_i2c_gate_ctrl,
0562 #endif
0563     .set_frontend         = mxl111sf_demod_set_frontend,
0564     .get_frontend         = mxl111sf_demod_get_frontend,
0565     .get_tune_settings    = mxl111sf_demod_get_tune_settings,
0566     .read_status          = mxl111sf_demod_read_status,
0567     .read_signal_strength = mxl111sf_demod_read_signal_strength,
0568     .read_ber             = mxl111sf_demod_read_ber,
0569     .read_snr             = mxl111sf_demod_read_snr,
0570     .read_ucblocks        = mxl111sf_demod_read_ucblocks,
0571 };
0572 
0573 struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
0574                    const struct mxl111sf_demod_config *cfg)
0575 {
0576     struct mxl111sf_demod_state *state = NULL;
0577 
0578     mxl_dbg("()");
0579 
0580     state = kzalloc(sizeof(struct mxl111sf_demod_state), GFP_KERNEL);
0581     if (state == NULL)
0582         return NULL;
0583 
0584     state->mxl_state = mxl_state;
0585     state->cfg = cfg;
0586 
0587     memcpy(&state->fe.ops, &mxl111sf_demod_ops,
0588            sizeof(struct dvb_frontend_ops));
0589 
0590     state->fe.demodulator_priv = state;
0591     return &state->fe;
0592 }
0593 EXPORT_SYMBOL_GPL(mxl111sf_demod_attach);
0594 
0595 MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver");
0596 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
0597 MODULE_LICENSE("GPL");
0598 MODULE_VERSION("0.1");