Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mxl111sf-tuner.c
Go to the documentation of this file.
1 /*
2  * mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
3  *
4  * Copyright (C) 2010 Michael Krufky <[email protected]>
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  * 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.
19  */
20 
21 #include "mxl111sf-tuner.h"
22 #include "mxl111sf-phy.h"
23 #include "mxl111sf-reg.h"
24 
25 /* debug */
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)).");
29 
30 #define mxl_dbg(fmt, arg...) \
31  if (mxl111sf_tuner_debug) \
32  mxl_printk(KERN_DEBUG, fmt, ##arg)
33 
34 #define err pr_err
35 
36 /* ------------------------------------------------------------------------ */
37 
40 
42 
44 
47 };
48 
49 static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state *state,
50  u8 addr, u8 *data)
51 {
52  return (state->cfg->read_reg) ?
53  state->cfg->read_reg(state->mxl_state, addr, data) :
54  -EINVAL;
55 }
56 
57 static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state *state,
58  u8 addr, u8 data)
59 {
60  return (state->cfg->write_reg) ?
61  state->cfg->write_reg(state->mxl_state, addr, data) :
62  -EINVAL;
63 }
64 
65 static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state *state,
66  struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
67 {
68  return (state->cfg->program_regs) ?
69  state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
70  -EINVAL;
71 }
72 
73 static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state *state,
74  int onoff)
75 {
76  return (state->cfg->top_master_ctrl) ?
77  state->cfg->top_master_ctrl(state->mxl_state, onoff) :
78  -EINVAL;
79 }
80 
81 /* ------------------------------------------------------------------------ */
82 
83 static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf[] = {
84  {0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3,
85  DIG_MODEINDEX, _A, _CSF, */
86  {0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */
87  {0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */
88  {0, 0, 0}
89 };
90 
91 /* ------------------------------------------------------------------------ */
92 
93 static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq,
94  u8 bw)
95 {
96  u8 filt_bw;
97 
98  /* set channel bandwidth */
99  switch (bw) {
100  case 0: /* ATSC */
101  filt_bw = 25;
102  break;
103  case 1: /* QAM */
104  filt_bw = 69;
105  break;
106  case 6:
107  filt_bw = 21;
108  break;
109  case 7:
110  filt_bw = 42;
111  break;
112  case 8:
113  filt_bw = 63;
114  break;
115  default:
116  err("%s: invalid bandwidth setting!", __func__);
117  return NULL;
118  }
119 
120  /* calculate RF channel */
121  freq /= 1000000;
122 
123  freq *= 64;
124 #if 0
125  /* do round */
126  freq += 0.5;
127 #endif
128  /* set bandwidth */
129  mxl_phy_tune_rf[0].data = filt_bw;
130 
131  /* set RF */
132  mxl_phy_tune_rf[1].data = (freq & 0xff);
133  mxl_phy_tune_rf[2].data = (freq >> 8) & 0xff;
134 
135  /* start tune */
136  return mxl_phy_tune_rf;
137 }
138 
139 static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state)
140 {
141  int ret;
142  u8 ctrl;
143 #if 0
144  u16 iffcw;
145  u32 if_freq;
146 #endif
147  mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)",
148  state->cfg->invert_spectrum, state->cfg->if_freq);
149 
150  /* set IF polarity */
151  ctrl = state->cfg->invert_spectrum;
152 
153  ctrl |= state->cfg->if_freq;
154 
155  ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_SEL_REG, ctrl);
156  if (mxl_fail(ret))
157  goto fail;
158 
159 #if 0
160  if_freq /= 1000000;
161 
162  /* do round */
163  if_freq += 0.5;
164 
165  if (MXL_IF_LO == state->cfg->if_freq) {
166  ctrl = 0x08;
167  iffcw = (u16)(if_freq / (108 * 4096));
168  } else if (MXL_IF_HI == state->cfg->if_freq) {
169  ctrl = 0x08;
170  iffcw = (u16)(if_freq / (216 * 4096));
171  } else {
172  ctrl = 0;
173  iffcw = 0;
174  }
175 
176  ctrl |= (iffcw >> 8);
177 #endif
178  ret = mxl111sf_tuner_read_reg(state, V6_TUNER_IF_FCW_BYP_REG, &ctrl);
179  if (mxl_fail(ret))
180  goto fail;
181 
182  ctrl &= 0xf0;
183  ctrl |= 0x90;
184 
185  ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_BYP_REG, ctrl);
186  if (mxl_fail(ret))
187  goto fail;
188 
189 #if 0
190  ctrl = iffcw & 0x00ff;
191 #endif
192  ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl);
193  if (mxl_fail(ret))
194  goto fail;
195 
196  state->if_freq = state->cfg->if_freq;
197 fail:
198  return ret;
199 }
200 
201 static int mxl1x1sf_tune_rf(struct dvb_frontend *fe, u32 freq, u8 bw)
202 {
203  struct mxl111sf_tuner_state *state = fe->tuner_priv;
204  static struct mxl111sf_reg_ctrl_info *reg_ctrl_array;
205  int ret;
206  u8 mxl_mode;
207 
208  mxl_dbg("(freq = %d, bw = 0x%x)", freq, bw);
209 
210  /* stop tune */
211  ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 0);
212  if (mxl_fail(ret))
213  goto fail;
214 
215  /* check device mode */
216  ret = mxl111sf_tuner_read_reg(state, MXL_MODE_REG, &mxl_mode);
217  if (mxl_fail(ret))
218  goto fail;
219 
220  /* Fill out registers for channel tune */
221  reg_ctrl_array = mxl111sf_calc_phy_tune_regs(freq, bw);
222  if (!reg_ctrl_array)
223  return -EINVAL;
224 
225  ret = mxl111sf_tuner_program_regs(state, reg_ctrl_array);
226  if (mxl_fail(ret))
227  goto fail;
228 
229  if ((mxl_mode & MXL_DEV_MODE_MASK) == MXL_TUNER_MODE) {
230  /* IF tuner mode only */
231  mxl1x1sf_tuner_top_master_ctrl(state, 0);
232  mxl1x1sf_tuner_top_master_ctrl(state, 1);
233  mxl1x1sf_tuner_set_if_output_freq(state);
234  }
235 
236  ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 1);
237  if (mxl_fail(ret))
238  goto fail;
239 
240  if (state->cfg->ant_hunt)
241  state->cfg->ant_hunt(fe);
242 fail:
243  return ret;
244 }
245 
246 static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state *state,
247  int *rf_synth_lock,
248  int *ref_synth_lock)
249 {
250  int ret;
251  u8 data;
252 
253  *rf_synth_lock = 0;
254  *ref_synth_lock = 0;
255 
256  ret = mxl111sf_tuner_read_reg(state, V6_RF_LOCK_STATUS_REG, &data);
257  if (mxl_fail(ret))
258  goto fail;
259 
260  *ref_synth_lock = ((data & 0x03) == 0x03) ? 1 : 0;
261  *rf_synth_lock = ((data & 0x0c) == 0x0c) ? 1 : 0;
262 fail:
263  return ret;
264 }
265 
266 #if 0
267 static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state,
268  int onoff)
269 {
270  return mxl111sf_tuner_write_reg(state, V6_TUNER_LOOP_THRU_CTRL_REG,
271  onoff ? 1 : 0);
272 }
273 #endif
274 
275 /* ------------------------------------------------------------------------ */
276 
277 static int mxl111sf_tuner_set_params(struct dvb_frontend *fe)
278 {
280  u32 delsys = c->delivery_system;
281  struct mxl111sf_tuner_state *state = fe->tuner_priv;
282  int ret;
283  u8 bw;
284 
285  mxl_dbg("()");
286 
287  switch (delsys) {
288  case SYS_ATSC:
289  case SYS_ATSCMH:
290  bw = 0; /* ATSC */
291  break;
292  case SYS_DVBC_ANNEX_B:
293  bw = 1; /* US CABLE */
294  break;
295  case SYS_DVBT:
296  switch (c->bandwidth_hz) {
297  case 6000000:
298  bw = 6;
299  break;
300  case 7000000:
301  bw = 7;
302  break;
303  case 8000000:
304  bw = 8;
305  break;
306  default:
307  err("%s: bandwidth not set!", __func__);
308  return -EINVAL;
309  }
310  break;
311  default:
312  err("%s: modulation type not supported!", __func__);
313  return -EINVAL;
314  }
315  ret = mxl1x1sf_tune_rf(fe, c->frequency, bw);
316  if (mxl_fail(ret))
317  goto fail;
318 
319  state->frequency = c->frequency;
320  state->bandwidth = c->bandwidth_hz;
321 fail:
322  return ret;
323 }
324 
325 /* ------------------------------------------------------------------------ */
326 
327 #if 0
328 static int mxl111sf_tuner_init(struct dvb_frontend *fe)
329 {
330  struct mxl111sf_tuner_state *state = fe->tuner_priv;
331  int ret;
332 
333  /* wake from standby handled by usb driver */
334 
335  return ret;
336 }
337 
338 static int mxl111sf_tuner_sleep(struct dvb_frontend *fe)
339 {
340  struct mxl111sf_tuner_state *state = fe->tuner_priv;
341  int ret;
342 
343  /* enter standby mode handled by usb driver */
344 
345  return ret;
346 }
347 #endif
348 
349 /* ------------------------------------------------------------------------ */
350 
351 static int mxl111sf_tuner_get_status(struct dvb_frontend *fe, u32 *status)
352 {
353  struct mxl111sf_tuner_state *state = fe->tuner_priv;
354  int rf_locked, ref_locked, ret;
355 
356  *status = 0;
357 
358  ret = mxl1x1sf_tuner_get_lock_status(state, &rf_locked, &ref_locked);
359  if (mxl_fail(ret))
360  goto fail;
361  mxl_info("%s%s", rf_locked ? "rf locked " : "",
362  ref_locked ? "ref locked" : "");
363 
364  if ((rf_locked) || (ref_locked))
365  *status |= TUNER_STATUS_LOCKED;
366 fail:
367  return ret;
368 }
369 
370 static int mxl111sf_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
371 {
372  struct mxl111sf_tuner_state *state = fe->tuner_priv;
373  u8 val1, val2;
374  int ret;
375 
376  *strength = 0;
377 
378  ret = mxl111sf_tuner_write_reg(state, 0x00, 0x02);
379  if (mxl_fail(ret))
380  goto fail;
381  ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_LSB_REG, &val1);
382  if (mxl_fail(ret))
383  goto fail;
384  ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_MSB_REG, &val2);
385  if (mxl_fail(ret))
386  goto fail;
387 
388  *strength = val1 | ((val2 & 0x07) << 8);
389 fail:
390  ret = mxl111sf_tuner_write_reg(state, 0x00, 0x00);
391  mxl_fail(ret);
392 
393  return ret;
394 }
395 
396 /* ------------------------------------------------------------------------ */
397 
398 static int mxl111sf_tuner_get_frequency(struct dvb_frontend *fe, u32 *frequency)
399 {
400  struct mxl111sf_tuner_state *state = fe->tuner_priv;
401  *frequency = state->frequency;
402  return 0;
403 }
404 
405 static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
406 {
407  struct mxl111sf_tuner_state *state = fe->tuner_priv;
408  *bandwidth = state->bandwidth;
409  return 0;
410 }
411 
412 static int mxl111sf_tuner_get_if_frequency(struct dvb_frontend *fe,
413  u32 *frequency)
414 {
415  struct mxl111sf_tuner_state *state = fe->tuner_priv;
416 
417  *frequency = 0;
418 
419  switch (state->if_freq) {
420  case MXL_IF_4_0: /* 4.0 MHz */
421  *frequency = 4000000;
422  break;
423  case MXL_IF_4_5: /* 4.5 MHz */
424  *frequency = 4500000;
425  break;
426  case MXL_IF_4_57: /* 4.57 MHz */
427  *frequency = 4570000;
428  break;
429  case MXL_IF_5_0: /* 5.0 MHz */
430  *frequency = 5000000;
431  break;
432  case MXL_IF_5_38: /* 5.38 MHz */
433  *frequency = 5380000;
434  break;
435  case MXL_IF_6_0: /* 6.0 MHz */
436  *frequency = 6000000;
437  break;
438  case MXL_IF_6_28: /* 6.28 MHz */
439  *frequency = 6280000;
440  break;
441  case MXL_IF_7_2: /* 7.2 MHz */
442  *frequency = 7200000;
443  break;
444  case MXL_IF_35_25: /* 35.25 MHz */
445  *frequency = 35250000;
446  break;
447  case MXL_IF_36: /* 36 MHz */
448  *frequency = 36000000;
449  break;
450  case MXL_IF_36_15: /* 36.15 MHz */
451  *frequency = 36150000;
452  break;
453  case MXL_IF_44: /* 44 MHz */
454  *frequency = 44000000;
455  break;
456  }
457  return 0;
458 }
459 
460 static int mxl111sf_tuner_release(struct dvb_frontend *fe)
461 {
462  struct mxl111sf_tuner_state *state = fe->tuner_priv;
463  mxl_dbg("()");
464  kfree(state);
465  fe->tuner_priv = NULL;
466  return 0;
467 }
468 
469 /* ------------------------------------------------------------------------- */
470 
471 static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = {
472  .info = {
473  .name = "MaxLinear MxL111SF",
474 #if 0
475  .frequency_min = ,
476  .frequency_max = ,
477  .frequency_step = ,
478 #endif
479  },
480 #if 0
481  .init = mxl111sf_tuner_init,
482  .sleep = mxl111sf_tuner_sleep,
483 #endif
484  .set_params = mxl111sf_tuner_set_params,
485  .get_status = mxl111sf_tuner_get_status,
486  .get_rf_strength = mxl111sf_get_rf_strength,
487  .get_frequency = mxl111sf_tuner_get_frequency,
488  .get_bandwidth = mxl111sf_tuner_get_bandwidth,
489  .get_if_frequency = mxl111sf_tuner_get_if_frequency,
490  .release = mxl111sf_tuner_release,
491 };
492 
494  struct mxl111sf_state *mxl_state,
495  struct mxl111sf_tuner_config *cfg)
496 {
497  struct mxl111sf_tuner_state *state = NULL;
498 
499  mxl_dbg("()");
500 
501  state = kzalloc(sizeof(struct mxl111sf_tuner_state), GFP_KERNEL);
502  if (state == NULL)
503  return NULL;
504 
505  state->mxl_state = mxl_state;
506  state->cfg = cfg;
507 
508  memcpy(&fe->ops.tuner_ops, &mxl111sf_tuner_tuner_ops,
509  sizeof(struct dvb_tuner_ops));
510 
511  fe->tuner_priv = state;
512  return fe;
513 }
515 
516 MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
517 MODULE_AUTHOR("Michael Krufky <[email protected]>");
518 MODULE_LICENSE("GPL");
519 MODULE_VERSION("0.1");
520 
521 /*
522  * Overrides for Emacs so that we follow Linus's tabbing style.
523  * ---------------------------------------------------------------------------
524  * Local variables:
525  * c-basic-offset: 8
526  * End:
527  */