1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * mxl111sf-demod.c - driver for the MaxLinear MXL111SF DVB-T demodulator
5 * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
8 #include "mxl111sf-demod.h"
9 #include "mxl111sf-reg.h"
12 static int mxl111sf_demod_debug
;
13 module_param_named(debug
, mxl111sf_demod_debug
, int, 0644);
14 MODULE_PARM_DESC(debug
, "set debugging level (1=info (or-able)).");
16 #define mxl_dbg(fmt, arg...) \
17 if (mxl111sf_demod_debug) \
18 mxl_printk(KERN_DEBUG, fmt, ##arg)
20 /* ------------------------------------------------------------------------ */
22 struct mxl111sf_demod_state
{
23 struct mxl111sf_state
*mxl_state
;
25 const struct mxl111sf_demod_config
*cfg
;
27 struct dvb_frontend fe
;
30 /* ------------------------------------------------------------------------ */
32 static int mxl111sf_demod_read_reg(struct mxl111sf_demod_state
*state
,
35 return (state
->cfg
->read_reg
) ?
36 state
->cfg
->read_reg(state
->mxl_state
, addr
, data
) :
40 static int mxl111sf_demod_write_reg(struct mxl111sf_demod_state
*state
,
43 return (state
->cfg
->write_reg
) ?
44 state
->cfg
->write_reg(state
->mxl_state
, addr
, data
) :
49 int mxl111sf_demod_program_regs(struct mxl111sf_demod_state
*state
,
50 struct mxl111sf_reg_ctrl_info
*ctrl_reg_info
)
52 return (state
->cfg
->program_regs
) ?
53 state
->cfg
->program_regs(state
->mxl_state
, ctrl_reg_info
) :
57 /* ------------------------------------------------------------------------ */
61 int mxl1x1sf_demod_get_tps_code_rate(struct mxl111sf_demod_state
*state
,
62 enum fe_code_rate
*code_rate
)
65 int ret
= mxl111sf_demod_read_reg(state
, V6_CODE_RATE_TPS_REG
, &val
);
66 /* bit<2:0> - 000:1/2, 001:2/3, 010:3/4, 011:5/6, 100:7/8 */
70 switch (val
& V6_CODE_RATE_TPS_MASK
) {
92 int mxl1x1sf_demod_get_tps_modulation(struct mxl111sf_demod_state
*state
,
93 enum fe_modulation
*modulation
)
96 int ret
= mxl111sf_demod_read_reg(state
, V6_MODORDER_TPS_REG
, &val
);
97 /* Constellation, 00 : QPSK, 01 : 16QAM, 10:64QAM */
101 switch ((val
& V6_PARAM_CONSTELLATION_MASK
) >> 4) {
106 *modulation
= QAM_16
;
109 *modulation
= QAM_64
;
117 int mxl1x1sf_demod_get_tps_guard_fft_mode(struct mxl111sf_demod_state
*state
,
118 enum fe_transmit_mode
*fft_mode
)
121 int ret
= mxl111sf_demod_read_reg(state
, V6_MODE_TPS_REG
, &val
);
122 /* FFT Mode, 00:2K, 01:8K, 10:4K */
126 switch ((val
& V6_PARAM_FFT_MODE_MASK
) >> 2) {
128 *fft_mode
= TRANSMISSION_MODE_2K
;
131 *fft_mode
= TRANSMISSION_MODE_8K
;
134 *fft_mode
= TRANSMISSION_MODE_4K
;
142 int mxl1x1sf_demod_get_tps_guard_interval(struct mxl111sf_demod_state
*state
,
143 enum fe_guard_interval
*guard
)
146 int ret
= mxl111sf_demod_read_reg(state
, V6_CP_TPS_REG
, &val
);
147 /* 00:1/32, 01:1/16, 10:1/8, 11:1/4 */
151 switch ((val
& V6_PARAM_GI_MASK
) >> 4) {
153 *guard
= GUARD_INTERVAL_1_32
;
156 *guard
= GUARD_INTERVAL_1_16
;
159 *guard
= GUARD_INTERVAL_1_8
;
162 *guard
= GUARD_INTERVAL_1_4
;
170 int mxl1x1sf_demod_get_tps_hierarchy(struct mxl111sf_demod_state
*state
,
171 enum fe_hierarchy
*hierarchy
)
174 int ret
= mxl111sf_demod_read_reg(state
, V6_TPS_HIERACHY_REG
, &val
);
175 /* bit<6:4> - 000:Non hierarchy, 001:1, 010:2, 011:4 */
179 switch ((val
& V6_TPS_HIERARCHY_INFO_MASK
) >> 6) {
181 *hierarchy
= HIERARCHY_NONE
;
184 *hierarchy
= HIERARCHY_1
;
187 *hierarchy
= HIERARCHY_2
;
190 *hierarchy
= HIERARCHY_4
;
197 /* ------------------------------------------------------------------------ */
201 int mxl1x1sf_demod_get_sync_lock_status(struct mxl111sf_demod_state
*state
,
205 int ret
= mxl111sf_demod_read_reg(state
, V6_SYNC_LOCK_REG
, &val
);
208 *sync_lock
= (val
& SYNC_LOCK_MASK
) >> 4;
214 int mxl1x1sf_demod_get_rs_lock_status(struct mxl111sf_demod_state
*state
,
218 int ret
= mxl111sf_demod_read_reg(state
, V6_RS_LOCK_DET_REG
, &val
);
221 *rs_lock
= (val
& RS_LOCK_DET_MASK
) >> 3;
227 int mxl1x1sf_demod_get_tps_lock_status(struct mxl111sf_demod_state
*state
,
231 int ret
= mxl111sf_demod_read_reg(state
, V6_TPS_LOCK_REG
, &val
);
234 *tps_lock
= (val
& V6_PARAM_TPS_LOCK_MASK
) >> 6;
240 int mxl1x1sf_demod_get_fec_lock_status(struct mxl111sf_demod_state
*state
,
244 int ret
= mxl111sf_demod_read_reg(state
, V6_IRQ_STATUS_REG
, &val
);
247 *fec_lock
= (val
& IRQ_MASK_FEC_LOCK
) >> 4;
254 int mxl1x1sf_demod_get_cp_lock_status(struct mxl111sf_demod_state
*state
,
258 int ret
= mxl111sf_demod_read_reg(state
, V6_CP_LOCK_DET_REG
, &val
);
261 *cp_lock
= (val
& V6_CP_LOCK_DET_MASK
) >> 2;
267 static int mxl1x1sf_demod_reset_irq_status(struct mxl111sf_demod_state
*state
)
269 return mxl111sf_demod_write_reg(state
, 0x0e, 0xff);
272 /* ------------------------------------------------------------------------ */
274 static int mxl111sf_demod_set_frontend(struct dvb_frontend
*fe
)
276 struct mxl111sf_demod_state
*state
= fe
->demodulator_priv
;
279 struct mxl111sf_reg_ctrl_info phy_pll_patch
[] = {
280 {0x00, 0xff, 0x01}, /* change page to 1 */
285 {0x00, 0xff, 0x00}, /* change page to 0 */
291 if (fe
->ops
.tuner_ops
.set_params
) {
292 ret
= fe
->ops
.tuner_ops
.set_params(fe
);
297 ret
= mxl111sf_demod_program_regs(state
, phy_pll_patch
);
300 ret
= mxl1x1sf_demod_reset_irq_status(state
);
307 /* ------------------------------------------------------------------------ */
310 /* resets TS Packet error count */
311 /* After setting 7th bit of V5_PER_COUNT_RESET_REG, it should be reset to 0. */
313 int mxl1x1sf_demod_reset_packet_error_count(struct mxl111sf_demod_state
*state
)
315 struct mxl111sf_reg_ctrl_info reset_per_count
[] = {
320 return mxl111sf_demod_program_regs(state
, reset_per_count
);
324 /* returns TS Packet error count */
325 /* PER Count = FEC_PER_COUNT * (2 ** (FEC_PER_SCALE * 4)) */
326 static int mxl111sf_demod_read_ucblocks(struct dvb_frontend
*fe
, u32
*ucblocks
)
328 struct mxl111sf_demod_state
*state
= fe
->demodulator_priv
;
329 u32 fec_per_count
, fec_per_scale
;
335 /* FEC_PER_COUNT Register */
336 ret
= mxl111sf_demod_read_reg(state
, V6_FEC_PER_COUNT_REG
, &val
);
342 /* FEC_PER_SCALE Register */
343 ret
= mxl111sf_demod_read_reg(state
, V6_FEC_PER_SCALE_REG
, &val
);
347 val
&= V6_FEC_PER_SCALE_MASK
;
350 fec_per_scale
= 1 << val
;
352 fec_per_count
*= fec_per_scale
;
354 *ucblocks
= fec_per_count
;
359 #ifdef MXL111SF_DEMOD_ENABLE_CALCULATIONS
360 /* FIXME: leaving this enabled breaks the build on some architectures,
361 * and we shouldn't have any floating point math in the kernel, anyway.
363 * These macros need to be re-written, but it's harmless to simply
364 * return zero for now. */
365 #define CALCULATE_BER(avg_errors, count) \
366 ((u32)(avg_errors * 4)/(count*64*188*8))
367 #define CALCULATE_SNR(data) \
368 ((u32)((10 * (u32)data / 64) - 2.5))
370 #define CALCULATE_BER(avg_errors, count) 0
371 #define CALCULATE_SNR(data) 0
374 static int mxl111sf_demod_read_ber(struct dvb_frontend
*fe
, u32
*ber
)
376 struct mxl111sf_demod_state
*state
= fe
->demodulator_priv
;
382 ret
= mxl111sf_demod_read_reg(state
, V6_RS_AVG_ERRORS_LSB_REG
, &val1
);
385 ret
= mxl111sf_demod_read_reg(state
, V6_RS_AVG_ERRORS_MSB_REG
, &val2
);
388 ret
= mxl111sf_demod_read_reg(state
, V6_N_ACCUMULATE_REG
, &val3
);
392 *ber
= CALCULATE_BER((val1
| (val2
<< 8)), val3
);
397 static int mxl111sf_demod_calc_snr(struct mxl111sf_demod_state
*state
,
405 ret
= mxl111sf_demod_read_reg(state
, V6_SNR_RB_LSB_REG
, &val1
);
408 ret
= mxl111sf_demod_read_reg(state
, V6_SNR_RB_MSB_REG
, &val2
);
412 *snr
= CALCULATE_SNR(val1
| ((val2
& 0x03) << 8));
417 static int mxl111sf_demod_read_snr(struct dvb_frontend
*fe
, u16
*snr
)
419 struct mxl111sf_demod_state
*state
= fe
->demodulator_priv
;
421 int ret
= mxl111sf_demod_calc_snr(state
, snr
);
425 *snr
/= 10; /* 0.1 dB */
430 static int mxl111sf_demod_read_status(struct dvb_frontend
*fe
,
431 enum fe_status
*status
)
433 struct mxl111sf_demod_state
*state
= fe
->demodulator_priv
;
434 int ret
, locked
, cr_lock
, sync_lock
, fec_lock
;
438 ret
= mxl1x1sf_demod_get_rs_lock_status(state
, &locked
);
441 ret
= mxl1x1sf_demod_get_tps_lock_status(state
, &cr_lock
);
444 ret
= mxl1x1sf_demod_get_sync_lock_status(state
, &sync_lock
);
447 ret
= mxl1x1sf_demod_get_fec_lock_status(state
, &fec_lock
);
452 *status
|= FE_HAS_SIGNAL
;
454 *status
|= FE_HAS_CARRIER
;
456 *status
|= FE_HAS_SYNC
;
457 if (fec_lock
) /* false positives? */
458 *status
|= FE_HAS_VITERBI
;
460 if ((locked
) && (cr_lock
) && (sync_lock
))
461 *status
|= FE_HAS_LOCK
;
466 static int mxl111sf_demod_read_signal_strength(struct dvb_frontend
*fe
,
467 u16
*signal_strength
)
469 struct mxl111sf_demod_state
*state
= fe
->demodulator_priv
;
470 enum fe_modulation modulation
;
474 ret
= mxl111sf_demod_calc_snr(state
, &snr
);
477 ret
= mxl1x1sf_demod_get_tps_modulation(state
, &modulation
);
481 switch (modulation
) {
483 *signal_strength
= (snr
>= 1300) ?
484 min(65535, snr
* 44) : snr
* 38;
487 *signal_strength
= (snr
>= 1500) ?
488 min(65535, snr
* 38) : snr
* 33;
491 *signal_strength
= (snr
>= 2000) ?
492 min(65535, snr
* 29) : snr
* 25;
495 *signal_strength
= 0;
502 static int mxl111sf_demod_get_frontend(struct dvb_frontend
*fe
,
503 struct dtv_frontend_properties
*p
)
505 struct mxl111sf_demod_state
*state
= fe
->demodulator_priv
;
509 p
->inversion
= /* FIXME */ ? INVERSION_ON
: INVERSION_OFF
;
511 if (fe
->ops
.tuner_ops
.get_bandwidth
)
512 fe
->ops
.tuner_ops
.get_bandwidth(fe
, &p
->bandwidth_hz
);
513 if (fe
->ops
.tuner_ops
.get_frequency
)
514 fe
->ops
.tuner_ops
.get_frequency(fe
, &p
->frequency
);
515 mxl1x1sf_demod_get_tps_code_rate(state
, &p
->code_rate_HP
);
516 mxl1x1sf_demod_get_tps_code_rate(state
, &p
->code_rate_LP
);
517 mxl1x1sf_demod_get_tps_modulation(state
, &p
->modulation
);
518 mxl1x1sf_demod_get_tps_guard_fft_mode(state
,
519 &p
->transmission_mode
);
520 mxl1x1sf_demod_get_tps_guard_interval(state
,
522 mxl1x1sf_demod_get_tps_hierarchy(state
,
529 int mxl111sf_demod_get_tune_settings(struct dvb_frontend
*fe
,
530 struct dvb_frontend_tune_settings
*tune
)
532 tune
->min_delay_ms
= 1000;
536 static void mxl111sf_demod_release(struct dvb_frontend
*fe
)
538 struct mxl111sf_demod_state
*state
= fe
->demodulator_priv
;
541 fe
->demodulator_priv
= NULL
;
544 static const struct dvb_frontend_ops mxl111sf_demod_ops
= {
545 .delsys
= { SYS_DVBT
},
547 .name
= "MaxLinear MxL111SF DVB-T demodulator",
548 .frequency_min_hz
= 177 * MHz
,
549 .frequency_max_hz
= 858 * MHz
,
550 .frequency_stepsize_hz
= 166666,
551 .caps
= FE_CAN_FEC_1_2
| FE_CAN_FEC_2_3
| FE_CAN_FEC_3_4
|
552 FE_CAN_FEC_5_6
| FE_CAN_FEC_7_8
| FE_CAN_FEC_AUTO
|
553 FE_CAN_QPSK
| FE_CAN_QAM_16
| FE_CAN_QAM_64
|
555 FE_CAN_HIERARCHY_AUTO
| FE_CAN_GUARD_INTERVAL_AUTO
|
556 FE_CAN_TRANSMISSION_MODE_AUTO
| FE_CAN_RECOVER
558 .release
= mxl111sf_demod_release
,
560 .init
= mxl111sf_init
,
561 .i2c_gate_ctrl
= mxl111sf_i2c_gate_ctrl
,
563 .set_frontend
= mxl111sf_demod_set_frontend
,
564 .get_frontend
= mxl111sf_demod_get_frontend
,
565 .get_tune_settings
= mxl111sf_demod_get_tune_settings
,
566 .read_status
= mxl111sf_demod_read_status
,
567 .read_signal_strength
= mxl111sf_demod_read_signal_strength
,
568 .read_ber
= mxl111sf_demod_read_ber
,
569 .read_snr
= mxl111sf_demod_read_snr
,
570 .read_ucblocks
= mxl111sf_demod_read_ucblocks
,
573 struct dvb_frontend
*mxl111sf_demod_attach(struct mxl111sf_state
*mxl_state
,
574 const struct mxl111sf_demod_config
*cfg
)
576 struct mxl111sf_demod_state
*state
= NULL
;
580 state
= kzalloc(sizeof(struct mxl111sf_demod_state
), GFP_KERNEL
);
584 state
->mxl_state
= mxl_state
;
587 memcpy(&state
->fe
.ops
, &mxl111sf_demod_ops
,
588 sizeof(struct dvb_frontend_ops
));
590 state
->fe
.demodulator_priv
= state
;
593 EXPORT_SYMBOL_GPL(mxl111sf_demod_attach
);
595 MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver");
596 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
597 MODULE_LICENSE("GPL");
598 MODULE_VERSION("0.1");