0001
0002
0003
0004
0005
0006
0007
0008 #include "mxl111sf-demod.h"
0009 #include "mxl111sf-reg.h"
0010
0011
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
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
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
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
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
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
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
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},
0281 {0x40, 0xff, 0x05},
0282 {0x40, 0xff, 0x01},
0283 {0x41, 0xff, 0xca},
0284 {0x41, 0xff, 0xc0},
0285 {0x00, 0xff, 0x00},
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
0311
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
0325
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
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
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
0361
0362
0363
0364
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;
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)
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 = ? 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");