1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
5 * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
8 #include "mxl111sf-tuner.h"
9 #include "mxl111sf-phy.h"
10 #include "mxl111sf-reg.h"
13 static int mxl111sf_tuner_debug
;
14 module_param_named(debug
, mxl111sf_tuner_debug
, int, 0644);
15 MODULE_PARM_DESC(debug
, "set debugging level (1=info (or-able)).");
17 #define mxl_dbg(fmt, arg...) \
18 if (mxl111sf_tuner_debug) \
19 mxl_printk(KERN_DEBUG, fmt, ##arg)
21 /* ------------------------------------------------------------------------ */
23 struct mxl111sf_tuner_state
{
24 struct mxl111sf_state
*mxl_state
;
26 const struct mxl111sf_tuner_config
*cfg
;
28 enum mxl_if_freq if_freq
;
34 static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state
*state
,
37 return (state
->cfg
->read_reg
) ?
38 state
->cfg
->read_reg(state
->mxl_state
, addr
, data
) :
42 static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state
*state
,
45 return (state
->cfg
->write_reg
) ?
46 state
->cfg
->write_reg(state
->mxl_state
, addr
, data
) :
50 static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state
*state
,
51 struct mxl111sf_reg_ctrl_info
*ctrl_reg_info
)
53 return (state
->cfg
->program_regs
) ?
54 state
->cfg
->program_regs(state
->mxl_state
, ctrl_reg_info
) :
58 static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state
*state
,
61 return (state
->cfg
->top_master_ctrl
) ?
62 state
->cfg
->top_master_ctrl(state
->mxl_state
, onoff
) :
66 /* ------------------------------------------------------------------------ */
68 static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf
[] = {
69 {0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3,
70 DIG_MODEINDEX, _A, _CSF, */
71 {0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */
72 {0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */
76 /* ------------------------------------------------------------------------ */
78 static struct mxl111sf_reg_ctrl_info
*mxl111sf_calc_phy_tune_regs(u32 freq
,
83 /* set channel bandwidth */
101 pr_err("%s: invalid bandwidth setting!", __func__
);
105 /* calculate RF channel */
114 mxl_phy_tune_rf
[0].data
= filt_bw
;
117 mxl_phy_tune_rf
[1].data
= (freq
& 0xff);
118 mxl_phy_tune_rf
[2].data
= (freq
>> 8) & 0xff;
121 return mxl_phy_tune_rf
;
124 static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state
*state
)
132 mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)",
133 state
->cfg
->invert_spectrum
, state
->cfg
->if_freq
);
135 /* set IF polarity */
136 ctrl
= state
->cfg
->invert_spectrum
;
138 ctrl
|= state
->cfg
->if_freq
;
140 ret
= mxl111sf_tuner_write_reg(state
, V6_TUNER_IF_SEL_REG
, ctrl
);
150 if (MXL_IF_LO
== state
->cfg
->if_freq
) {
152 iffcw
= (u16
)(if_freq
/ (108 * 4096));
153 } else if (MXL_IF_HI
== state
->cfg
->if_freq
) {
155 iffcw
= (u16
)(if_freq
/ (216 * 4096));
161 ctrl
|= (iffcw
>> 8);
163 ret
= mxl111sf_tuner_read_reg(state
, V6_TUNER_IF_FCW_BYP_REG
, &ctrl
);
170 ret
= mxl111sf_tuner_write_reg(state
, V6_TUNER_IF_FCW_BYP_REG
, ctrl
);
175 ctrl
= iffcw
& 0x00ff;
177 ret
= mxl111sf_tuner_write_reg(state
, V6_TUNER_IF_FCW_REG
, ctrl
);
181 state
->if_freq
= state
->cfg
->if_freq
;
186 static int mxl1x1sf_tune_rf(struct dvb_frontend
*fe
, u32 freq
, u8 bw
)
188 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
189 static struct mxl111sf_reg_ctrl_info
*reg_ctrl_array
;
193 mxl_dbg("(freq = %d, bw = 0x%x)", freq
, bw
);
196 ret
= mxl111sf_tuner_write_reg(state
, START_TUNE_REG
, 0);
200 /* check device mode */
201 ret
= mxl111sf_tuner_read_reg(state
, MXL_MODE_REG
, &mxl_mode
);
205 /* Fill out registers for channel tune */
206 reg_ctrl_array
= mxl111sf_calc_phy_tune_regs(freq
, bw
);
210 ret
= mxl111sf_tuner_program_regs(state
, reg_ctrl_array
);
214 if ((mxl_mode
& MXL_DEV_MODE_MASK
) == MXL_TUNER_MODE
) {
215 /* IF tuner mode only */
216 mxl1x1sf_tuner_top_master_ctrl(state
, 0);
217 mxl1x1sf_tuner_top_master_ctrl(state
, 1);
218 mxl1x1sf_tuner_set_if_output_freq(state
);
221 ret
= mxl111sf_tuner_write_reg(state
, START_TUNE_REG
, 1);
225 if (state
->cfg
->ant_hunt
)
226 state
->cfg
->ant_hunt(fe
);
231 static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state
*state
,
241 ret
= mxl111sf_tuner_read_reg(state
, V6_RF_LOCK_STATUS_REG
, &data
);
245 *ref_synth_lock
= ((data
& 0x03) == 0x03) ? 1 : 0;
246 *rf_synth_lock
= ((data
& 0x0c) == 0x0c) ? 1 : 0;
252 static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state
*state
,
255 return mxl111sf_tuner_write_reg(state
, V6_TUNER_LOOP_THRU_CTRL_REG
,
260 /* ------------------------------------------------------------------------ */
262 static int mxl111sf_tuner_set_params(struct dvb_frontend
*fe
)
264 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
265 u32 delsys
= c
->delivery_system
;
266 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
277 case SYS_DVBC_ANNEX_B
:
278 bw
= 1; /* US CABLE */
281 switch (c
->bandwidth_hz
) {
292 pr_err("%s: bandwidth not set!", __func__
);
297 pr_err("%s: modulation type not supported!", __func__
);
300 ret
= mxl1x1sf_tune_rf(fe
, c
->frequency
, bw
);
304 state
->frequency
= c
->frequency
;
305 state
->bandwidth
= c
->bandwidth_hz
;
310 /* ------------------------------------------------------------------------ */
313 static int mxl111sf_tuner_init(struct dvb_frontend
*fe
)
315 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
318 /* wake from standby handled by usb driver */
323 static int mxl111sf_tuner_sleep(struct dvb_frontend
*fe
)
325 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
328 /* enter standby mode handled by usb driver */
334 /* ------------------------------------------------------------------------ */
336 static int mxl111sf_tuner_get_status(struct dvb_frontend
*fe
, u32
*status
)
338 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
339 int rf_locked
, ref_locked
, ret
;
343 ret
= mxl1x1sf_tuner_get_lock_status(state
, &rf_locked
, &ref_locked
);
346 mxl_info("%s%s", rf_locked
? "rf locked " : "",
347 ref_locked
? "ref locked" : "");
349 if ((rf_locked
) || (ref_locked
))
350 *status
|= TUNER_STATUS_LOCKED
;
355 static int mxl111sf_get_rf_strength(struct dvb_frontend
*fe
, u16
*strength
)
357 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
363 ret
= mxl111sf_tuner_write_reg(state
, 0x00, 0x02);
366 ret
= mxl111sf_tuner_read_reg(state
, V6_DIG_RF_PWR_LSB_REG
, &val1
);
369 ret
= mxl111sf_tuner_read_reg(state
, V6_DIG_RF_PWR_MSB_REG
, &val2
);
373 *strength
= val1
| ((val2
& 0x07) << 8);
375 ret
= mxl111sf_tuner_write_reg(state
, 0x00, 0x00);
381 /* ------------------------------------------------------------------------ */
383 static int mxl111sf_tuner_get_frequency(struct dvb_frontend
*fe
, u32
*frequency
)
385 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
386 *frequency
= state
->frequency
;
390 static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend
*fe
, u32
*bandwidth
)
392 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
393 *bandwidth
= state
->bandwidth
;
397 static int mxl111sf_tuner_get_if_frequency(struct dvb_frontend
*fe
,
400 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
404 switch (state
->if_freq
) {
405 case MXL_IF_4_0
: /* 4.0 MHz */
406 *frequency
= 4000000;
408 case MXL_IF_4_5
: /* 4.5 MHz */
409 *frequency
= 4500000;
411 case MXL_IF_4_57
: /* 4.57 MHz */
412 *frequency
= 4570000;
414 case MXL_IF_5_0
: /* 5.0 MHz */
415 *frequency
= 5000000;
417 case MXL_IF_5_38
: /* 5.38 MHz */
418 *frequency
= 5380000;
420 case MXL_IF_6_0
: /* 6.0 MHz */
421 *frequency
= 6000000;
423 case MXL_IF_6_28
: /* 6.28 MHz */
424 *frequency
= 6280000;
426 case MXL_IF_7_2
: /* 7.2 MHz */
427 *frequency
= 7200000;
429 case MXL_IF_35_25
: /* 35.25 MHz */
430 *frequency
= 35250000;
432 case MXL_IF_36
: /* 36 MHz */
433 *frequency
= 36000000;
435 case MXL_IF_36_15
: /* 36.15 MHz */
436 *frequency
= 36150000;
438 case MXL_IF_44
: /* 44 MHz */
439 *frequency
= 44000000;
445 static void mxl111sf_tuner_release(struct dvb_frontend
*fe
)
447 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
450 fe
->tuner_priv
= NULL
;
453 /* ------------------------------------------------------------------------- */
455 static const struct dvb_tuner_ops mxl111sf_tuner_tuner_ops
= {
457 .name
= "MaxLinear MxL111SF",
459 .frequency_min_hz
= ,
460 .frequency_max_hz
= ,
461 .frequency_step_hz
= ,
465 .init
= mxl111sf_tuner_init
,
466 .sleep
= mxl111sf_tuner_sleep
,
468 .set_params
= mxl111sf_tuner_set_params
,
469 .get_status
= mxl111sf_tuner_get_status
,
470 .get_rf_strength
= mxl111sf_get_rf_strength
,
471 .get_frequency
= mxl111sf_tuner_get_frequency
,
472 .get_bandwidth
= mxl111sf_tuner_get_bandwidth
,
473 .get_if_frequency
= mxl111sf_tuner_get_if_frequency
,
474 .release
= mxl111sf_tuner_release
,
477 struct dvb_frontend
*mxl111sf_tuner_attach(struct dvb_frontend
*fe
,
478 struct mxl111sf_state
*mxl_state
,
479 const struct mxl111sf_tuner_config
*cfg
)
481 struct mxl111sf_tuner_state
*state
= NULL
;
485 state
= kzalloc(sizeof(struct mxl111sf_tuner_state
), GFP_KERNEL
);
489 state
->mxl_state
= mxl_state
;
492 memcpy(&fe
->ops
.tuner_ops
, &mxl111sf_tuner_tuner_ops
,
493 sizeof(struct dvb_tuner_ops
));
495 fe
->tuner_priv
= state
;
498 EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach
);
500 MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
501 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
502 MODULE_LICENSE("GPL");
503 MODULE_VERSION("0.1");