Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cx22702.c
Go to the documentation of this file.
1 /*
2  Conexant 22702 DVB OFDM demodulator driver
3 
4  based on:
5  Alps TDMB7 DVB OFDM demodulator driver
6 
7  Copyright (C) 2001-2002 Convergence Integrated Media GmbH
8  Holger Waechtler <[email protected]>
9 
10  Copyright (C) 2004 Steven Toth <[email protected]>
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 
26 */
27 
28 #include <linux/kernel.h>
29 #include <linux/init.h>
30 #include <linux/module.h>
31 #include <linux/string.h>
32 #include <linux/slab.h>
33 #include <linux/delay.h>
34 #include "dvb_frontend.h"
35 #include "cx22702.h"
36 
37 struct cx22702_state {
38 
39  struct i2c_adapter *i2c;
40 
41  /* configuration settings */
42  const struct cx22702_config *config;
43 
45 
46  /* previous uncorrected block counter */
48 };
49 
50 static int debug;
51 module_param(debug, int, 0644);
52 MODULE_PARM_DESC(debug, "Enable verbose debug messages");
53 
54 #define dprintk if (debug) printk
55 
56 /* Register values to initialise the demod */
57 static const u8 init_tab[] = {
58  0x00, 0x00, /* Stop acquisition */
59  0x0B, 0x06,
60  0x09, 0x01,
61  0x0D, 0x41,
62  0x16, 0x32,
63  0x20, 0x0A,
64  0x21, 0x17,
65  0x24, 0x3e,
66  0x26, 0xff,
67  0x27, 0x10,
68  0x28, 0x00,
69  0x29, 0x00,
70  0x2a, 0x10,
71  0x2b, 0x00,
72  0x2c, 0x10,
73  0x2d, 0x00,
74  0x48, 0xd4,
75  0x49, 0x56,
76  0x6b, 0x1e,
77  0xc8, 0x02,
78  0xf9, 0x00,
79  0xfa, 0x00,
80  0xfb, 0x00,
81  0xfc, 0x00,
82  0xfd, 0x00,
83 };
84 
85 static int cx22702_writereg(struct cx22702_state *state, u8 reg, u8 data)
86 {
87  int ret;
88  u8 buf[] = { reg, data };
89  struct i2c_msg msg = {
90  .addr = state->config->demod_address, .flags = 0,
91  .buf = buf, .len = 2 };
92 
93  ret = i2c_transfer(state->i2c, &msg, 1);
94 
95  if (unlikely(ret != 1)) {
97  "%s: error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
98  __func__, reg, data, ret);
99  return -1;
100  }
101 
102  return 0;
103 }
104 
105 static u8 cx22702_readreg(struct cx22702_state *state, u8 reg)
106 {
107  int ret;
108  u8 data;
109 
110  struct i2c_msg msg[] = {
111  { .addr = state->config->demod_address, .flags = 0,
112  .buf = &reg, .len = 1 },
113  { .addr = state->config->demod_address, .flags = I2C_M_RD,
114  .buf = &data, .len = 1 } };
115 
116  ret = i2c_transfer(state->i2c, msg, 2);
117 
118  if (unlikely(ret != 2)) {
119  printk(KERN_ERR "%s: error (reg == 0x%02x, ret == %i)\n",
120  __func__, reg, ret);
121  return 0;
122  }
123 
124  return data;
125 }
126 
127 static int cx22702_set_inversion(struct cx22702_state *state, int inversion)
128 {
129  u8 val;
130 
131  val = cx22702_readreg(state, 0x0C);
132  switch (inversion) {
133  case INVERSION_AUTO:
134  return -EOPNOTSUPP;
135  case INVERSION_ON:
136  val |= 0x01;
137  break;
138  case INVERSION_OFF:
139  val &= 0xfe;
140  break;
141  default:
142  return -EINVAL;
143  }
144  return cx22702_writereg(state, 0x0C, val);
145 }
146 
147 /* Retrieve the demod settings */
148 static int cx22702_get_tps(struct cx22702_state *state,
149  struct dtv_frontend_properties *p)
150 {
151  u8 val;
152 
153  /* Make sure the TPS regs are valid */
154  if (!(cx22702_readreg(state, 0x0A) & 0x20))
155  return -EAGAIN;
156 
157  val = cx22702_readreg(state, 0x01);
158  switch ((val & 0x18) >> 3) {
159  case 0:
160  p->modulation = QPSK;
161  break;
162  case 1:
163  p->modulation = QAM_16;
164  break;
165  case 2:
166  p->modulation = QAM_64;
167  break;
168  }
169  switch (val & 0x07) {
170  case 0:
172  break;
173  case 1:
174  p->hierarchy = HIERARCHY_1;
175  break;
176  case 2:
177  p->hierarchy = HIERARCHY_2;
178  break;
179  case 3:
180  p->hierarchy = HIERARCHY_4;
181  break;
182  }
183 
184 
185  val = cx22702_readreg(state, 0x02);
186  switch ((val & 0x38) >> 3) {
187  case 0:
188  p->code_rate_HP = FEC_1_2;
189  break;
190  case 1:
191  p->code_rate_HP = FEC_2_3;
192  break;
193  case 2:
194  p->code_rate_HP = FEC_3_4;
195  break;
196  case 3:
197  p->code_rate_HP = FEC_5_6;
198  break;
199  case 4:
200  p->code_rate_HP = FEC_7_8;
201  break;
202  }
203  switch (val & 0x07) {
204  case 0:
205  p->code_rate_LP = FEC_1_2;
206  break;
207  case 1:
208  p->code_rate_LP = FEC_2_3;
209  break;
210  case 2:
211  p->code_rate_LP = FEC_3_4;
212  break;
213  case 3:
214  p->code_rate_LP = FEC_5_6;
215  break;
216  case 4:
217  p->code_rate_LP = FEC_7_8;
218  break;
219  }
220 
221  val = cx22702_readreg(state, 0x03);
222  switch ((val & 0x0c) >> 2) {
223  case 0:
225  break;
226  case 1:
228  break;
229  case 2:
231  break;
232  case 3:
234  break;
235  }
236  switch (val & 0x03) {
237  case 0:
239  break;
240  case 1:
242  break;
243  }
244 
245  return 0;
246 }
247 
248 static int cx22702_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
249 {
250  struct cx22702_state *state = fe->demodulator_priv;
251  u8 val;
252 
253  dprintk("%s(%d)\n", __func__, enable);
254  val = cx22702_readreg(state, 0x0D);
255  if (enable)
256  val &= 0xfe;
257  else
258  val |= 0x01;
259  return cx22702_writereg(state, 0x0D, val);
260 }
261 
262 /* Talk to the demod, set the FEC, GUARD, QAM settings etc */
263 static int cx22702_set_tps(struct dvb_frontend *fe)
264 {
266  u8 val;
267  struct cx22702_state *state = fe->demodulator_priv;
268 
269  if (fe->ops.tuner_ops.set_params) {
270  fe->ops.tuner_ops.set_params(fe);
271  if (fe->ops.i2c_gate_ctrl)
272  fe->ops.i2c_gate_ctrl(fe, 0);
273  }
274 
275  /* set inversion */
276  cx22702_set_inversion(state, p->inversion);
277 
278  /* set bandwidth */
279  val = cx22702_readreg(state, 0x0C) & 0xcf;
280  switch (p->bandwidth_hz) {
281  case 6000000:
282  val |= 0x20;
283  break;
284  case 7000000:
285  val |= 0x10;
286  break;
287  case 8000000:
288  break;
289  default:
290  dprintk("%s: invalid bandwidth\n", __func__);
291  return -EINVAL;
292  }
293  cx22702_writereg(state, 0x0C, val);
294 
295  p->code_rate_LP = FEC_AUTO; /* temp hack as manual not working */
296 
297  /* use auto configuration? */
298  if ((p->hierarchy == HIERARCHY_AUTO) ||
299  (p->modulation == QAM_AUTO) ||
300  (p->code_rate_HP == FEC_AUTO) ||
301  (p->code_rate_LP == FEC_AUTO) ||
304 
305  /* TPS Source - use hardware driven values */
306  cx22702_writereg(state, 0x06, 0x10);
307  cx22702_writereg(state, 0x07, 0x9);
308  cx22702_writereg(state, 0x08, 0xC1);
309  cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B)
310  & 0xfc);
311  cx22702_writereg(state, 0x0C,
312  (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
313  cx22702_writereg(state, 0x00, 0x01); /* Begin acquisition */
314  dprintk("%s: Autodetecting\n", __func__);
315  return 0;
316  }
317 
318  /* manually programmed values */
319  switch (p->modulation) { /* mask 0x18 */
320  case QPSK:
321  val = 0x00;
322  break;
323  case QAM_16:
324  val = 0x08;
325  break;
326  case QAM_64:
327  val = 0x10;
328  break;
329  default:
330  dprintk("%s: invalid modulation\n", __func__);
331  return -EINVAL;
332  }
333  switch (p->hierarchy) { /* mask 0x07 */
334  case HIERARCHY_NONE:
335  break;
336  case HIERARCHY_1:
337  val |= 0x01;
338  break;
339  case HIERARCHY_2:
340  val |= 0x02;
341  break;
342  case HIERARCHY_4:
343  val |= 0x03;
344  break;
345  default:
346  dprintk("%s: invalid hierarchy\n", __func__);
347  return -EINVAL;
348  }
349  cx22702_writereg(state, 0x06, val);
350 
351  switch (p->code_rate_HP) { /* mask 0x38 */
352  case FEC_NONE:
353  case FEC_1_2:
354  val = 0x00;
355  break;
356  case FEC_2_3:
357  val = 0x08;
358  break;
359  case FEC_3_4:
360  val = 0x10;
361  break;
362  case FEC_5_6:
363  val = 0x18;
364  break;
365  case FEC_7_8:
366  val = 0x20;
367  break;
368  default:
369  dprintk("%s: invalid code_rate_HP\n", __func__);
370  return -EINVAL;
371  }
372  switch (p->code_rate_LP) { /* mask 0x07 */
373  case FEC_NONE:
374  case FEC_1_2:
375  break;
376  case FEC_2_3:
377  val |= 0x01;
378  break;
379  case FEC_3_4:
380  val |= 0x02;
381  break;
382  case FEC_5_6:
383  val |= 0x03;
384  break;
385  case FEC_7_8:
386  val |= 0x04;
387  break;
388  default:
389  dprintk("%s: invalid code_rate_LP\n", __func__);
390  return -EINVAL;
391  }
392  cx22702_writereg(state, 0x07, val);
393 
394  switch (p->guard_interval) { /* mask 0x0c */
395  case GUARD_INTERVAL_1_32:
396  val = 0x00;
397  break;
398  case GUARD_INTERVAL_1_16:
399  val = 0x04;
400  break;
401  case GUARD_INTERVAL_1_8:
402  val = 0x08;
403  break;
404  case GUARD_INTERVAL_1_4:
405  val = 0x0c;
406  break;
407  default:
408  dprintk("%s: invalid guard_interval\n", __func__);
409  return -EINVAL;
410  }
411  switch (p->transmission_mode) { /* mask 0x03 */
413  break;
415  val |= 0x1;
416  break;
417  default:
418  dprintk("%s: invalid transmission_mode\n", __func__);
419  return -EINVAL;
420  }
421  cx22702_writereg(state, 0x08, val);
422  cx22702_writereg(state, 0x0B,
423  (cx22702_readreg(state, 0x0B) & 0xfc) | 0x02);
424  cx22702_writereg(state, 0x0C,
425  (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
426 
427  /* Begin channel acquisition */
428  cx22702_writereg(state, 0x00, 0x01);
429 
430  return 0;
431 }
432 
433 /* Reset the demod hardware and reset all of the configuration registers
434  to a default state. */
435 static int cx22702_init(struct dvb_frontend *fe)
436 {
437  int i;
438  struct cx22702_state *state = fe->demodulator_priv;
439 
440  cx22702_writereg(state, 0x00, 0x02);
441 
442  msleep(10);
443 
444  for (i = 0; i < ARRAY_SIZE(init_tab); i += 2)
445  cx22702_writereg(state, init_tab[i], init_tab[i + 1]);
446 
447  cx22702_writereg(state, 0xf8, (state->config->output_mode << 1)
448  & 0x02);
449 
450  cx22702_i2c_gate_ctrl(fe, 0);
451 
452  return 0;
453 }
454 
455 static int cx22702_read_status(struct dvb_frontend *fe, fe_status_t *status)
456 {
457  struct cx22702_state *state = fe->demodulator_priv;
458  u8 reg0A;
459  u8 reg23;
460 
461  *status = 0;
462 
463  reg0A = cx22702_readreg(state, 0x0A);
464  reg23 = cx22702_readreg(state, 0x23);
465 
466  dprintk("%s: status demod=0x%02x agc=0x%02x\n"
467  , __func__, reg0A, reg23);
468 
469  if (reg0A & 0x10) {
470  *status |= FE_HAS_LOCK;
471  *status |= FE_HAS_VITERBI;
472  *status |= FE_HAS_SYNC;
473  }
474 
475  if (reg0A & 0x20)
476  *status |= FE_HAS_CARRIER;
477 
478  if (reg23 < 0xf0)
479  *status |= FE_HAS_SIGNAL;
480 
481  return 0;
482 }
483 
484 static int cx22702_read_ber(struct dvb_frontend *fe, u32 *ber)
485 {
486  struct cx22702_state *state = fe->demodulator_priv;
487 
488  if (cx22702_readreg(state, 0xE4) & 0x02) {
489  /* Realtime statistics */
490  *ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
491  | (cx22702_readreg(state, 0xDF) & 0x7F);
492  } else {
493  /* Averagtine statistics */
494  *ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
495  | cx22702_readreg(state, 0xDF);
496  }
497 
498  return 0;
499 }
500 
501 static int cx22702_read_signal_strength(struct dvb_frontend *fe,
502  u16 *signal_strength)
503 {
504  struct cx22702_state *state = fe->demodulator_priv;
505  u8 reg23;
506 
507  /*
508  * Experience suggests that the strength signal register works as
509  * follows:
510  * - In the absence of signal, value is 0xff.
511  * - In the presence of a weak signal, bit 7 is set, not sure what
512  * the lower 7 bits mean.
513  * - In the presence of a strong signal, the register holds a 7-bit
514  * value (bit 7 is cleared), with greater values standing for
515  * weaker signals.
516  */
517  reg23 = cx22702_readreg(state, 0x23);
518  if (reg23 & 0x80) {
519  *signal_strength = 0;
520  } else {
521  reg23 = ~reg23 & 0x7f;
522  /* Scale to 16 bit */
523  *signal_strength = (reg23 << 9) | (reg23 << 2) | (reg23 >> 5);
524  }
525 
526  return 0;
527 }
528 
529 static int cx22702_read_snr(struct dvb_frontend *fe, u16 *snr)
530 {
531  struct cx22702_state *state = fe->demodulator_priv;
532 
533  u16 rs_ber;
534  if (cx22702_readreg(state, 0xE4) & 0x02) {
535  /* Realtime statistics */
536  rs_ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
537  | (cx22702_readreg(state, 0xDF) & 0x7F);
538  } else {
539  /* Averagine statistics */
540  rs_ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 8
541  | cx22702_readreg(state, 0xDF);
542  }
543  *snr = ~rs_ber;
544 
545  return 0;
546 }
547 
548 static int cx22702_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
549 {
550  struct cx22702_state *state = fe->demodulator_priv;
551 
552  u8 _ucblocks;
553 
554  /* RS Uncorrectable Packet Count then reset */
555  _ucblocks = cx22702_readreg(state, 0xE3);
556  if (state->prevUCBlocks < _ucblocks)
557  *ucblocks = (_ucblocks - state->prevUCBlocks);
558  else
559  *ucblocks = state->prevUCBlocks - _ucblocks;
560  state->prevUCBlocks = _ucblocks;
561 
562  return 0;
563 }
564 
565 static int cx22702_get_frontend(struct dvb_frontend *fe)
566 {
568  struct cx22702_state *state = fe->demodulator_priv;
569 
570  u8 reg0C = cx22702_readreg(state, 0x0C);
571 
572  c->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF;
573  return cx22702_get_tps(state, c);
574 }
575 
576 static int cx22702_get_tune_settings(struct dvb_frontend *fe,
577  struct dvb_frontend_tune_settings *tune)
578 {
579  tune->min_delay_ms = 1000;
580  return 0;
581 }
582 
583 static void cx22702_release(struct dvb_frontend *fe)
584 {
585  struct cx22702_state *state = fe->demodulator_priv;
586  kfree(state);
587 }
588 
589 static const struct dvb_frontend_ops cx22702_ops;
590 
592  struct i2c_adapter *i2c)
593 {
594  struct cx22702_state *state = NULL;
595 
596  /* allocate memory for the internal state */
597  state = kzalloc(sizeof(struct cx22702_state), GFP_KERNEL);
598  if (state == NULL)
599  goto error;
600 
601  /* setup the state */
602  state->config = config;
603  state->i2c = i2c;
604 
605  /* check if the demod is there */
606  if (cx22702_readreg(state, 0x1f) != 0x3)
607  goto error;
608 
609  /* create dvb_frontend */
610  memcpy(&state->frontend.ops, &cx22702_ops,
611  sizeof(struct dvb_frontend_ops));
612  state->frontend.demodulator_priv = state;
613  return &state->frontend;
614 
615 error:
616  kfree(state);
617  return NULL;
618 }
620 
621 static const struct dvb_frontend_ops cx22702_ops = {
622  .delsys = { SYS_DVBT },
623  .info = {
624  .name = "Conexant CX22702 DVB-T",
625  .frequency_min = 177000000,
626  .frequency_max = 858000000,
627  .frequency_stepsize = 166666,
633  },
634 
635  .release = cx22702_release,
636 
637  .init = cx22702_init,
638  .i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
639 
640  .set_frontend = cx22702_set_tps,
641  .get_frontend = cx22702_get_frontend,
642  .get_tune_settings = cx22702_get_tune_settings,
643 
644  .read_status = cx22702_read_status,
645  .read_ber = cx22702_read_ber,
646  .read_signal_strength = cx22702_read_signal_strength,
647  .read_snr = cx22702_read_snr,
648  .read_ucblocks = cx22702_read_ucblocks,
649 };
650 
651 MODULE_DESCRIPTION("Conexant CX22702 DVB-T Demodulator driver");
652 MODULE_AUTHOR("Steven Toth");
653 MODULE_LICENSE("GPL");