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