2 * mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
4 * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
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.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "mxl111sf-tuner.h"
22 #include "mxl111sf-phy.h"
23 #include "mxl111sf-reg.h"
26 static int mxl111sf_tuner_debug
;
27 module_param_named(debug
, mxl111sf_tuner_debug
, int, 0644);
28 MODULE_PARM_DESC(debug
, "set debugging level (1=info (or-able)).");
30 #define mxl_dbg(fmt, arg...) \
31 if (mxl111sf_tuner_debug) \
32 mxl_printk(KERN_DEBUG, fmt, ##arg)
34 /* ------------------------------------------------------------------------ */
36 struct mxl111sf_tuner_state
{
37 struct mxl111sf_state
*mxl_state
;
39 struct mxl111sf_tuner_config
*cfg
;
41 enum mxl_if_freq if_freq
;
47 static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state
*state
,
50 return (state
->cfg
->read_reg
) ?
51 state
->cfg
->read_reg(state
->mxl_state
, addr
, data
) :
55 static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state
*state
,
58 return (state
->cfg
->write_reg
) ?
59 state
->cfg
->write_reg(state
->mxl_state
, addr
, data
) :
63 static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state
*state
,
64 struct mxl111sf_reg_ctrl_info
*ctrl_reg_info
)
66 return (state
->cfg
->program_regs
) ?
67 state
->cfg
->program_regs(state
->mxl_state
, ctrl_reg_info
) :
71 static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state
*state
,
74 return (state
->cfg
->top_master_ctrl
) ?
75 state
->cfg
->top_master_ctrl(state
->mxl_state
, onoff
) :
79 /* ------------------------------------------------------------------------ */
81 static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf
[] = {
82 {0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3,
83 DIG_MODEINDEX, _A, _CSF, */
84 {0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */
85 {0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */
89 /* ------------------------------------------------------------------------ */
91 static struct mxl111sf_reg_ctrl_info
*mxl111sf_calc_phy_tune_regs(u32 freq
,
96 /* set channel bandwidth */
114 pr_err("%s: invalid bandwidth setting!", __func__
);
118 /* calculate RF channel */
127 mxl_phy_tune_rf
[0].data
= filt_bw
;
130 mxl_phy_tune_rf
[1].data
= (freq
& 0xff);
131 mxl_phy_tune_rf
[2].data
= (freq
>> 8) & 0xff;
134 return mxl_phy_tune_rf
;
137 static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state
*state
)
145 mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)",
146 state
->cfg
->invert_spectrum
, state
->cfg
->if_freq
);
148 /* set IF polarity */
149 ctrl
= state
->cfg
->invert_spectrum
;
151 ctrl
|= state
->cfg
->if_freq
;
153 ret
= mxl111sf_tuner_write_reg(state
, V6_TUNER_IF_SEL_REG
, ctrl
);
163 if (MXL_IF_LO
== state
->cfg
->if_freq
) {
165 iffcw
= (u16
)(if_freq
/ (108 * 4096));
166 } else if (MXL_IF_HI
== state
->cfg
->if_freq
) {
168 iffcw
= (u16
)(if_freq
/ (216 * 4096));
174 ctrl
|= (iffcw
>> 8);
176 ret
= mxl111sf_tuner_read_reg(state
, V6_TUNER_IF_FCW_BYP_REG
, &ctrl
);
183 ret
= mxl111sf_tuner_write_reg(state
, V6_TUNER_IF_FCW_BYP_REG
, ctrl
);
188 ctrl
= iffcw
& 0x00ff;
190 ret
= mxl111sf_tuner_write_reg(state
, V6_TUNER_IF_FCW_REG
, ctrl
);
194 state
->if_freq
= state
->cfg
->if_freq
;
199 static int mxl1x1sf_tune_rf(struct dvb_frontend
*fe
, u32 freq
, u8 bw
)
201 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
202 static struct mxl111sf_reg_ctrl_info
*reg_ctrl_array
;
206 mxl_dbg("(freq = %d, bw = 0x%x)", freq
, bw
);
209 ret
= mxl111sf_tuner_write_reg(state
, START_TUNE_REG
, 0);
213 /* check device mode */
214 ret
= mxl111sf_tuner_read_reg(state
, MXL_MODE_REG
, &mxl_mode
);
218 /* Fill out registers for channel tune */
219 reg_ctrl_array
= mxl111sf_calc_phy_tune_regs(freq
, bw
);
223 ret
= mxl111sf_tuner_program_regs(state
, reg_ctrl_array
);
227 if ((mxl_mode
& MXL_DEV_MODE_MASK
) == MXL_TUNER_MODE
) {
228 /* IF tuner mode only */
229 mxl1x1sf_tuner_top_master_ctrl(state
, 0);
230 mxl1x1sf_tuner_top_master_ctrl(state
, 1);
231 mxl1x1sf_tuner_set_if_output_freq(state
);
234 ret
= mxl111sf_tuner_write_reg(state
, START_TUNE_REG
, 1);
238 if (state
->cfg
->ant_hunt
)
239 state
->cfg
->ant_hunt(fe
);
244 static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state
*state
,
254 ret
= mxl111sf_tuner_read_reg(state
, V6_RF_LOCK_STATUS_REG
, &data
);
258 *ref_synth_lock
= ((data
& 0x03) == 0x03) ? 1 : 0;
259 *rf_synth_lock
= ((data
& 0x0c) == 0x0c) ? 1 : 0;
265 static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state
*state
,
268 return mxl111sf_tuner_write_reg(state
, V6_TUNER_LOOP_THRU_CTRL_REG
,
273 /* ------------------------------------------------------------------------ */
275 static int mxl111sf_tuner_set_params(struct dvb_frontend
*fe
)
277 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
278 u32 delsys
= c
->delivery_system
;
279 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
290 case SYS_DVBC_ANNEX_B
:
291 bw
= 1; /* US CABLE */
294 switch (c
->bandwidth_hz
) {
305 pr_err("%s: bandwidth not set!", __func__
);
310 pr_err("%s: modulation type not supported!", __func__
);
313 ret
= mxl1x1sf_tune_rf(fe
, c
->frequency
, bw
);
317 state
->frequency
= c
->frequency
;
318 state
->bandwidth
= c
->bandwidth_hz
;
323 /* ------------------------------------------------------------------------ */
326 static int mxl111sf_tuner_init(struct dvb_frontend
*fe
)
328 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
331 /* wake from standby handled by usb driver */
336 static int mxl111sf_tuner_sleep(struct dvb_frontend
*fe
)
338 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
341 /* enter standby mode handled by usb driver */
347 /* ------------------------------------------------------------------------ */
349 static int mxl111sf_tuner_get_status(struct dvb_frontend
*fe
, u32
*status
)
351 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
352 int rf_locked
, ref_locked
, ret
;
356 ret
= mxl1x1sf_tuner_get_lock_status(state
, &rf_locked
, &ref_locked
);
359 mxl_info("%s%s", rf_locked
? "rf locked " : "",
360 ref_locked
? "ref locked" : "");
362 if ((rf_locked
) || (ref_locked
))
363 *status
|= TUNER_STATUS_LOCKED
;
368 static int mxl111sf_get_rf_strength(struct dvb_frontend
*fe
, u16
*strength
)
370 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
376 ret
= mxl111sf_tuner_write_reg(state
, 0x00, 0x02);
379 ret
= mxl111sf_tuner_read_reg(state
, V6_DIG_RF_PWR_LSB_REG
, &val1
);
382 ret
= mxl111sf_tuner_read_reg(state
, V6_DIG_RF_PWR_MSB_REG
, &val2
);
386 *strength
= val1
| ((val2
& 0x07) << 8);
388 ret
= mxl111sf_tuner_write_reg(state
, 0x00, 0x00);
394 /* ------------------------------------------------------------------------ */
396 static int mxl111sf_tuner_get_frequency(struct dvb_frontend
*fe
, u32
*frequency
)
398 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
399 *frequency
= state
->frequency
;
403 static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend
*fe
, u32
*bandwidth
)
405 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
406 *bandwidth
= state
->bandwidth
;
410 static int mxl111sf_tuner_get_if_frequency(struct dvb_frontend
*fe
,
413 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
417 switch (state
->if_freq
) {
418 case MXL_IF_4_0
: /* 4.0 MHz */
419 *frequency
= 4000000;
421 case MXL_IF_4_5
: /* 4.5 MHz */
422 *frequency
= 4500000;
424 case MXL_IF_4_57
: /* 4.57 MHz */
425 *frequency
= 4570000;
427 case MXL_IF_5_0
: /* 5.0 MHz */
428 *frequency
= 5000000;
430 case MXL_IF_5_38
: /* 5.38 MHz */
431 *frequency
= 5380000;
433 case MXL_IF_6_0
: /* 6.0 MHz */
434 *frequency
= 6000000;
436 case MXL_IF_6_28
: /* 6.28 MHz */
437 *frequency
= 6280000;
439 case MXL_IF_7_2
: /* 7.2 MHz */
440 *frequency
= 7200000;
442 case MXL_IF_35_25
: /* 35.25 MHz */
443 *frequency
= 35250000;
445 case MXL_IF_36
: /* 36 MHz */
446 *frequency
= 36000000;
448 case MXL_IF_36_15
: /* 36.15 MHz */
449 *frequency
= 36150000;
451 case MXL_IF_44
: /* 44 MHz */
452 *frequency
= 44000000;
458 static int mxl111sf_tuner_release(struct dvb_frontend
*fe
)
460 struct mxl111sf_tuner_state
*state
= fe
->tuner_priv
;
463 fe
->tuner_priv
= NULL
;
467 /* ------------------------------------------------------------------------- */
469 static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops
= {
471 .name
= "MaxLinear MxL111SF",
479 .init
= mxl111sf_tuner_init
,
480 .sleep
= mxl111sf_tuner_sleep
,
482 .set_params
= mxl111sf_tuner_set_params
,
483 .get_status
= mxl111sf_tuner_get_status
,
484 .get_rf_strength
= mxl111sf_get_rf_strength
,
485 .get_frequency
= mxl111sf_tuner_get_frequency
,
486 .get_bandwidth
= mxl111sf_tuner_get_bandwidth
,
487 .get_if_frequency
= mxl111sf_tuner_get_if_frequency
,
488 .release
= mxl111sf_tuner_release
,
491 struct dvb_frontend
*mxl111sf_tuner_attach(struct dvb_frontend
*fe
,
492 struct mxl111sf_state
*mxl_state
,
493 struct mxl111sf_tuner_config
*cfg
)
495 struct mxl111sf_tuner_state
*state
= NULL
;
499 state
= kzalloc(sizeof(struct mxl111sf_tuner_state
), GFP_KERNEL
);
503 state
->mxl_state
= mxl_state
;
506 memcpy(&fe
->ops
.tuner_ops
, &mxl111sf_tuner_tuner_ops
,
507 sizeof(struct dvb_tuner_ops
));
509 fe
->tuner_priv
= state
;
512 EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach
);
514 MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
515 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
516 MODULE_LICENSE("GPL");
517 MODULE_VERSION("0.1");
520 * Overrides for Emacs so that we follow Linus's tabbing style.
521 * ---------------------------------------------------------------------------