Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
atbm8830.c
Go to the documentation of this file.
1 /*
2  * Support for AltoBeam GB20600 (a.k.a DMB-TH) demodulator
3  * ATBM8830, ATBM8831
4  *
5  * Copyright (C) 2009 David T.L. Wong <[email protected]>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 
22 #include <asm/div64.h>
23 #include "dvb_frontend.h"
24 
25 #include "atbm8830.h"
26 #include "atbm8830_priv.h"
27 
28 #define dprintk(args...) \
29  do { \
30  if (debug) \
31  printk(KERN_DEBUG "atbm8830: " args); \
32  } while (0)
33 
34 static int debug;
35 
36 module_param(debug, int, 0644);
37 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
38 
39 static int atbm8830_write_reg(struct atbm_state *priv, u16 reg, u8 data)
40 {
41  int ret = 0;
42  u8 dev_addr;
43  u8 buf1[] = { reg >> 8, reg & 0xFF };
44  u8 buf2[] = { data };
45  struct i2c_msg msg1 = { .flags = 0, .buf = buf1, .len = 2 };
46  struct i2c_msg msg2 = { .flags = 0, .buf = buf2, .len = 1 };
47 
48  dev_addr = priv->config->demod_address;
49  msg1.addr = dev_addr;
50  msg2.addr = dev_addr;
51 
52  if (debug >= 2)
53  dprintk("%s: reg=0x%04X, data=0x%02X\n", __func__, reg, data);
54 
55  ret = i2c_transfer(priv->i2c, &msg1, 1);
56  if (ret != 1)
57  return -EIO;
58 
59  ret = i2c_transfer(priv->i2c, &msg2, 1);
60  return (ret != 1) ? -EIO : 0;
61 }
62 
63 static int atbm8830_read_reg(struct atbm_state *priv, u16 reg, u8 *p_data)
64 {
65  int ret;
66  u8 dev_addr;
67 
68  u8 buf1[] = { reg >> 8, reg & 0xFF };
69  u8 buf2[] = { 0 };
70  struct i2c_msg msg1 = { .flags = 0, .buf = buf1, .len = 2 };
71  struct i2c_msg msg2 = { .flags = I2C_M_RD, .buf = buf2, .len = 1 };
72 
73  dev_addr = priv->config->demod_address;
74  msg1.addr = dev_addr;
75  msg2.addr = dev_addr;
76 
77  ret = i2c_transfer(priv->i2c, &msg1, 1);
78  if (ret != 1) {
79  dprintk("%s: error reg=0x%04x, ret=%i\n", __func__, reg, ret);
80  return -EIO;
81  }
82 
83  ret = i2c_transfer(priv->i2c, &msg2, 1);
84  if (ret != 1)
85  return -EIO;
86 
87  *p_data = buf2[0];
88  if (debug >= 2)
89  dprintk("%s: reg=0x%04X, data=0x%02X\n",
90  __func__, reg, buf2[0]);
91 
92  return 0;
93 }
94 
95 /* Lock register latch so that multi-register read is atomic */
96 static inline int atbm8830_reglatch_lock(struct atbm_state *priv, int lock)
97 {
98  return atbm8830_write_reg(priv, REG_READ_LATCH, lock ? 1 : 0);
99 }
100 
101 static int set_osc_freq(struct atbm_state *priv, u32 freq /*in kHz*/)
102 {
103  u32 val;
104  u64 t;
105 
106  /* 0x100000 * freq / 30.4MHz */
107  t = (u64)0x100000 * freq;
108  do_div(t, 30400);
109  val = t;
110 
111  atbm8830_write_reg(priv, REG_OSC_CLK, val);
112  atbm8830_write_reg(priv, REG_OSC_CLK + 1, val >> 8);
113  atbm8830_write_reg(priv, REG_OSC_CLK + 2, val >> 16);
114 
115  return 0;
116 }
117 
118 static int set_if_freq(struct atbm_state *priv, u32 freq /*in kHz*/)
119 {
120 
121  u32 fs = priv->config->osc_clk_freq;
122  u64 t;
123  u32 val;
124  u8 dat;
125 
126  if (freq != 0) {
127  /* 2 * PI * (freq - fs) / fs * (2 ^ 22) */
128  t = (u64) 2 * 31416 * (freq - fs);
129  t <<= 22;
130  do_div(t, fs);
131  do_div(t, 1000);
132  val = t;
133 
134  atbm8830_write_reg(priv, REG_TUNER_BASEBAND, 1);
135  atbm8830_write_reg(priv, REG_IF_FREQ, val);
136  atbm8830_write_reg(priv, REG_IF_FREQ+1, val >> 8);
137  atbm8830_write_reg(priv, REG_IF_FREQ+2, val >> 16);
138 
139  atbm8830_read_reg(priv, REG_ADC_CONFIG, &dat);
140  dat &= 0xFC;
141  atbm8830_write_reg(priv, REG_ADC_CONFIG, dat);
142  } else {
143  /* Zero IF */
144  atbm8830_write_reg(priv, REG_TUNER_BASEBAND, 0);
145 
146  atbm8830_read_reg(priv, REG_ADC_CONFIG, &dat);
147  dat &= 0xFC;
148  dat |= 0x02;
149  atbm8830_write_reg(priv, REG_ADC_CONFIG, dat);
150 
151  if (priv->config->zif_swap_iq)
152  atbm8830_write_reg(priv, REG_SWAP_I_Q, 0x03);
153  else
154  atbm8830_write_reg(priv, REG_SWAP_I_Q, 0x01);
155  }
156 
157  return 0;
158 }
159 
160 static int is_locked(struct atbm_state *priv, u8 *locked)
161 {
162  u8 status;
163 
164  atbm8830_read_reg(priv, REG_LOCK_STATUS, &status);
165 
166  if (locked != NULL)
167  *locked = (status == 1);
168  return 0;
169 }
170 
171 static int set_agc_config(struct atbm_state *priv,
172  u8 min, u8 max, u8 hold_loop)
173 {
174  /* no effect if both min and max are zero */
175  if (!min && !max)
176  return 0;
177 
178  atbm8830_write_reg(priv, REG_AGC_MIN, min);
179  atbm8830_write_reg(priv, REG_AGC_MAX, max);
180  atbm8830_write_reg(priv, REG_AGC_HOLD_LOOP, hold_loop);
181 
182  return 0;
183 }
184 
185 static int set_static_channel_mode(struct atbm_state *priv)
186 {
187  int i;
188 
189  for (i = 0; i < 5; i++)
190  atbm8830_write_reg(priv, 0x099B + i, 0x08);
191 
192  atbm8830_write_reg(priv, 0x095B, 0x7F);
193  atbm8830_write_reg(priv, 0x09CB, 0x01);
194  atbm8830_write_reg(priv, 0x09CC, 0x7F);
195  atbm8830_write_reg(priv, 0x09CD, 0x7F);
196  atbm8830_write_reg(priv, 0x0E01, 0x20);
197 
198  /* For single carrier */
199  atbm8830_write_reg(priv, 0x0B03, 0x0A);
200  atbm8830_write_reg(priv, 0x0935, 0x10);
201  atbm8830_write_reg(priv, 0x0936, 0x08);
202  atbm8830_write_reg(priv, 0x093E, 0x08);
203  atbm8830_write_reg(priv, 0x096E, 0x06);
204 
205  /* frame_count_max0 */
206  atbm8830_write_reg(priv, 0x0B09, 0x00);
207  /* frame_count_max1 */
208  atbm8830_write_reg(priv, 0x0B0A, 0x08);
209 
210  return 0;
211 }
212 
213 static int set_ts_config(struct atbm_state *priv)
214 {
215  const struct atbm8830_config *cfg = priv->config;
216 
217  /*Set parallel/serial ts mode*/
218  atbm8830_write_reg(priv, REG_TS_SERIAL, cfg->serial_ts ? 1 : 0);
219  atbm8830_write_reg(priv, REG_TS_CLK_MODE, cfg->serial_ts ? 1 : 0);
220  /*Set ts sampling edge*/
221  atbm8830_write_reg(priv, REG_TS_SAMPLE_EDGE,
222  cfg->ts_sampling_edge ? 1 : 0);
223  /*Set ts clock freerun*/
224  atbm8830_write_reg(priv, REG_TS_CLK_FREERUN,
225  cfg->ts_clk_gated ? 0 : 1);
226 
227  return 0;
228 }
229 
230 static int atbm8830_init(struct dvb_frontend *fe)
231 {
232  struct atbm_state *priv = fe->demodulator_priv;
233  const struct atbm8830_config *cfg = priv->config;
234 
235  /*Set oscillator frequency*/
236  set_osc_freq(priv, cfg->osc_clk_freq);
237 
238  /*Set IF frequency*/
239  set_if_freq(priv, cfg->if_freq);
240 
241  /*Set AGC Config*/
242  set_agc_config(priv, cfg->agc_min, cfg->agc_max,
243  cfg->agc_hold_loop);
244 
245  /*Set static channel mode*/
246  set_static_channel_mode(priv);
247 
248  set_ts_config(priv);
249  /*Turn off DSP reset*/
250  atbm8830_write_reg(priv, 0x000A, 0);
251 
252  /*SW version test*/
253  atbm8830_write_reg(priv, 0x020C, 11);
254 
255  /* Run */
256  atbm8830_write_reg(priv, REG_DEMOD_RUN, 1);
257 
258  return 0;
259 }
260 
261 
262 static void atbm8830_release(struct dvb_frontend *fe)
263 {
264  struct atbm_state *state = fe->demodulator_priv;
265  dprintk("%s\n", __func__);
266 
267  kfree(state);
268 }
269 
270 static int atbm8830_set_fe(struct dvb_frontend *fe)
271 {
272  struct atbm_state *priv = fe->demodulator_priv;
273  int i;
274  u8 locked = 0;
275  dprintk("%s\n", __func__);
276 
277  /* set frequency */
278  if (fe->ops.tuner_ops.set_params) {
279  if (fe->ops.i2c_gate_ctrl)
280  fe->ops.i2c_gate_ctrl(fe, 1);
281  fe->ops.tuner_ops.set_params(fe);
282  if (fe->ops.i2c_gate_ctrl)
283  fe->ops.i2c_gate_ctrl(fe, 0);
284  }
285 
286  /* start auto lock */
287  for (i = 0; i < 10; i++) {
288  mdelay(100);
289  dprintk("Try %d\n", i);
290  is_locked(priv, &locked);
291  if (locked != 0) {
292  dprintk("ATBM8830 locked!\n");
293  break;
294  }
295  }
296 
297  return 0;
298 }
299 
300 static int atbm8830_get_fe(struct dvb_frontend *fe)
301 {
303  dprintk("%s\n", __func__);
304 
305  /* TODO: get real readings from device */
306  /* inversion status */
308 
309  /* bandwidth */
310  c->bandwidth_hz = 8000000;
311 
312  c->code_rate_HP = FEC_AUTO;
313  c->code_rate_LP = FEC_AUTO;
314 
315  c->modulation = QAM_AUTO;
316 
317  /* transmission mode */
319 
320  /* guard interval */
322 
323  /* hierarchy */
325 
326  return 0;
327 }
328 
329 static int atbm8830_get_tune_settings(struct dvb_frontend *fe,
330  struct dvb_frontend_tune_settings *fesettings)
331 {
332  fesettings->min_delay_ms = 0;
333  fesettings->step_size = 0;
334  fesettings->max_drift = 0;
335  return 0;
336 }
337 
338 static int atbm8830_read_status(struct dvb_frontend *fe, fe_status_t *fe_status)
339 {
340  struct atbm_state *priv = fe->demodulator_priv;
341  u8 locked = 0;
342  u8 agc_locked = 0;
343 
344  dprintk("%s\n", __func__);
345  *fe_status = 0;
346 
347  is_locked(priv, &locked);
348  if (locked) {
349  *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
351  }
352  dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
353 
354  atbm8830_read_reg(priv, REG_AGC_LOCK, &agc_locked);
355  dprintk("AGC Lock: %d\n", agc_locked);
356 
357  return 0;
358 }
359 
360 static int atbm8830_read_ber(struct dvb_frontend *fe, u32 *ber)
361 {
362  struct atbm_state *priv = fe->demodulator_priv;
363  u32 frame_err;
364  u8 t;
365 
366  dprintk("%s\n", __func__);
367 
368  atbm8830_reglatch_lock(priv, 1);
369 
370  atbm8830_read_reg(priv, REG_FRAME_ERR_CNT + 1, &t);
371  frame_err = t & 0x7F;
372  frame_err <<= 8;
373  atbm8830_read_reg(priv, REG_FRAME_ERR_CNT, &t);
374  frame_err |= t;
375 
376  atbm8830_reglatch_lock(priv, 0);
377 
378  *ber = frame_err * 100 / 32767;
379 
380  dprintk("%s: ber=0x%x\n", __func__, *ber);
381  return 0;
382 }
383 
384 static int atbm8830_read_signal_strength(struct dvb_frontend *fe, u16 *signal)
385 {
386  struct atbm_state *priv = fe->demodulator_priv;
387  u32 pwm;
388  u8 t;
389 
390  dprintk("%s\n", __func__);
391  atbm8830_reglatch_lock(priv, 1);
392 
393  atbm8830_read_reg(priv, REG_AGC_PWM_VAL + 1, &t);
394  pwm = t & 0x03;
395  pwm <<= 8;
396  atbm8830_read_reg(priv, REG_AGC_PWM_VAL, &t);
397  pwm |= t;
398 
399  atbm8830_reglatch_lock(priv, 0);
400 
401  dprintk("AGC PWM = 0x%02X\n", pwm);
402  pwm = 0x400 - pwm;
403 
404  *signal = pwm * 0x10000 / 0x400;
405 
406  return 0;
407 }
408 
409 static int atbm8830_read_snr(struct dvb_frontend *fe, u16 *snr)
410 {
411  dprintk("%s\n", __func__);
412  *snr = 0;
413  return 0;
414 }
415 
416 static int atbm8830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
417 {
418  dprintk("%s\n", __func__);
419  *ucblocks = 0;
420  return 0;
421 }
422 
423 static int atbm8830_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
424 {
425  struct atbm_state *priv = fe->demodulator_priv;
426 
427  return atbm8830_write_reg(priv, REG_I2C_GATE, enable ? 1 : 0);
428 }
429 
430 static struct dvb_frontend_ops atbm8830_ops = {
431  .delsys = { SYS_DTMB },
432  .info = {
433  .name = "AltoBeam ATBM8830/8831 DMB-TH",
434  .frequency_min = 474000000,
435  .frequency_max = 858000000,
436  .frequency_stepsize = 10000,
437  .caps =
442  },
443 
444  .release = atbm8830_release,
445 
446  .init = atbm8830_init,
447  .sleep = NULL,
448  .write = NULL,
449  .i2c_gate_ctrl = atbm8830_i2c_gate_ctrl,
450 
451  .set_frontend = atbm8830_set_fe,
452  .get_frontend = atbm8830_get_fe,
453  .get_tune_settings = atbm8830_get_tune_settings,
454 
455  .read_status = atbm8830_read_status,
456  .read_ber = atbm8830_read_ber,
457  .read_signal_strength = atbm8830_read_signal_strength,
458  .read_snr = atbm8830_read_snr,
459  .read_ucblocks = atbm8830_read_ucblocks,
460 };
461 
463  struct i2c_adapter *i2c)
464 {
465  struct atbm_state *priv = NULL;
466  u8 data = 0;
467 
468  dprintk("%s()\n", __func__);
469 
470  if (config == NULL || i2c == NULL)
471  return NULL;
472 
473  priv = kzalloc(sizeof(struct atbm_state), GFP_KERNEL);
474  if (priv == NULL)
475  goto error_out;
476 
477  priv->config = config;
478  priv->i2c = i2c;
479 
480  /* check if the demod is there */
481  if (atbm8830_read_reg(priv, REG_CHIP_ID, &data) != 0) {
482  dprintk("%s atbm8830/8831 not found at i2c addr 0x%02X\n",
483  __func__, priv->config->demod_address);
484  goto error_out;
485  }
486  dprintk("atbm8830 chip id: 0x%02X\n", data);
487 
488  memcpy(&priv->frontend.ops, &atbm8830_ops,
489  sizeof(struct dvb_frontend_ops));
490  priv->frontend.demodulator_priv = priv;
491 
492  atbm8830_init(&priv->frontend);
493 
494  atbm8830_i2c_gate_ctrl(&priv->frontend, 1);
495 
496  return &priv->frontend;
497 
498 error_out:
499  dprintk("%s() error_out\n", __func__);
500  kfree(priv);
501  return NULL;
502 
503 }
505 
506 MODULE_DESCRIPTION("AltoBeam ATBM8830/8831 GB20600 demodulator driver");
507 MODULE_AUTHOR("David T. L. Wong <[email protected]>");
508 MODULE_LICENSE("GPL");