Commit 1963c907b21e140082d081b1c8f8c2154593c7d7

Authored by Michael Krufky
Committed by Linus Torvalds
1 parent 66aea23ff8

[PATCH] dvb: lgdt330x frontend: some bug fixes & add lgdt3303 support

- Structural changes within lgdt330x driver, framework now supports
  both chips... tested OK on lgdt3302 and lgdt3303.
- Add LG/TUA6034 dvb_pll_desc for ATSC with LG TDVS-H062F & DViCO FusionHDTV5.
- Fixed LGDT330X signal strength: For now, always set it to 0.
- Corrected LGDT330X boundary condition error in read_snr: dB calculation.

Signed-off-by: Mac Michaels <wmichaels1@earthlink.net>
Signed-off-by: Michael Krufky <mkrufky@m1k.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 6 changed files with 443 additions and 173 deletions Side-by-side Diff

drivers/media/dvb/frontends/dvb-pll.c
... ... @@ -225,6 +225,22 @@
225 225 };
226 226 EXPORT_SYMBOL(dvb_pll_tua6034);
227 227  
  228 +/* Infineon TUA6034
  229 + * used in LG Innotek TDVS-H062F
  230 + */
  231 +struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
  232 + .name = "LG/Infineon TUA6034",
  233 + .min = 54000000,
  234 + .max = 863000000,
  235 + .count = 3,
  236 + .entries = {
  237 + { 160000000, 44000000, 62500, 0xce, 0x01 },
  238 + { 455000000, 44000000, 62500, 0xce, 0x02 },
  239 + { 999999999, 44000000, 62500, 0xce, 0x04 },
  240 + },
  241 +};
  242 +EXPORT_SYMBOL(dvb_pll_tdvs_tua6034);
  243 +
228 244 /* Philips FMD1216ME
229 245 * used in Medion Hybrid PCMCIA card and USB Box
230 246 */
drivers/media/dvb/frontends/dvb-pll.h
... ... @@ -31,6 +31,7 @@
31 31 extern struct dvb_pll_desc dvb_pll_tua6010xs;
32 32 extern struct dvb_pll_desc dvb_pll_env57h1xd5;
33 33 extern struct dvb_pll_desc dvb_pll_tua6034;
  34 +extern struct dvb_pll_desc dvb_pll_tdvs_tua6034;
34 35 extern struct dvb_pll_desc dvb_pll_tda665x;
35 36 extern struct dvb_pll_desc dvb_pll_fmd1216me;
36 37 extern struct dvb_pll_desc dvb_pll_tded4;
drivers/media/dvb/frontends/lgdt330x.c
1 1 /*
2   - * Support for LGDT3302 & LGDT3303 (DViCO FusionHDTV Gold) - VSB/QAM
  2 + * Support for LGDT3302 and LGDT3303 - VSB/QAM
3 3 *
4 4 * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
5 5 *
6   - * Based on code from Kirk Lapray <kirk_lapray@bigfoot.com>
7   - * Copyright (C) 2005
8   - *
9 6 * This program is free software; you can redistribute it and/or modify
10 7 * it under the terms of the GNU General Public License as published by
11 8 * the Free Software Foundation; either version 2 of the License, or
12 9  
... ... @@ -25,11 +22,13 @@
25 22 /*
26 23 * NOTES ABOUT THIS DRIVER
27 24 *
28   - * This driver supports DViCO FusionHDTV Gold under Linux.
  25 + * This Linux driver supports:
  26 + * DViCO FusionHDTV 3 Gold-Q
  27 + * DViCO FusionHDTV 3 Gold-T
  28 + * DViCO FusionHDTV 5 Gold
29 29 *
30 30 * TODO:
31   - * BER and signal strength always return 0.
32   - * Include support for LGDT3303
  31 + * signal strength always returns 0.
33 32 *
34 33 */
35 34  
... ... @@ -41,7 +40,6 @@
41 40 #include <asm/byteorder.h>
42 41  
43 42 #include "dvb_frontend.h"
44   -#include "dvb-pll.h"
45 43 #include "lgdt330x_priv.h"
46 44 #include "lgdt330x.h"
47 45  
48 46  
49 47  
50 48  
51 49  
52 50  
53 51  
54 52  
55 53  
... ... @@ -70,55 +68,37 @@
70 68 u32 current_frequency;
71 69 };
72 70  
73   -static int i2c_writebytes (struct lgdt330x_state* state,
74   - u8 addr, /* demod_address or pll_address */
  71 +static int i2c_write_demod_bytes (struct lgdt330x_state* state,
75 72 u8 *buf, /* data bytes to send */
76 73 int len /* number of bytes to send */ )
77 74 {
78   - u8 tmp[] = { buf[0], buf[1] };
79 75 struct i2c_msg msg =
80   - { .addr = addr, .flags = 0, .buf = tmp, .len = 2 };
81   - int err;
  76 + { .addr = state->config->demod_address,
  77 + .flags = 0,
  78 + .buf = buf,
  79 + .len = 2 };
82 80 int i;
  81 + int err;
83 82  
84   - for (i=1; i<len; i++) {
85   - tmp[1] = buf[i];
  83 + for (i=0; i<len-1; i+=2){
86 84 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
87   - printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err == %i)\n", __FUNCTION__, addr, buf[0], err);
  85 + printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
88 86 if (err < 0)
89 87 return err;
90 88 else
91 89 return -EREMOTEIO;
92 90 }
93   - tmp[0]++;
  91 + msg.buf += 2;
94 92 }
95 93 return 0;
96 94 }
97 95  
98   -#if 0
99   -static int i2c_readbytes (struct lgdt330x_state* state,
100   - u8 addr, /* demod_address or pll_address */
101   - u8 *buf, /* holds data bytes read */
102   - int len /* number of bytes to read */ )
103   -{
104   - struct i2c_msg msg =
105   - { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len };
106   - int err;
107   -
108   - if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
109   - printk(KERN_WARNING "lgdt330x: %s error (addr %02x, err == %i)\n", __FUNCTION__, addr, err);
110   - return -EREMOTEIO;
111   - }
112   - return 0;
113   -}
114   -#endif
115   -
116 96 /*
117 97 * This routine writes the register (reg) to the demod bus
118 98 * then reads the data returned for (len) bytes.
119 99 */
120 100  
121   -static u8 i2c_selectreadbytes (struct lgdt330x_state* state,
  101 +static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
122 102 enum I2C_REG reg, u8* buf, int len)
123 103 {
124 104 u8 wr [] = { reg };
... ... @@ -139,7 +119,7 @@
139 119 }
140 120  
141 121 /* Software reset */
142   -int lgdt330x_SwReset(struct lgdt330x_state* state)
  122 +static int lgdt3302_SwReset(struct lgdt330x_state* state)
143 123 {
144 124 u8 ret;
145 125 u8 reset[] = {
146 126  
147 127  
148 128  
... ... @@ -148,23 +128,83 @@
148 128 * bits 5-0 are 1 to mask interrupts */
149 129 };
150 130  
151   - ret = i2c_writebytes(state,
152   - state->config->demod_address,
  131 + ret = i2c_write_demod_bytes(state,
153 132 reset, sizeof(reset));
154 133 if (ret == 0) {
155   - /* spec says reset takes 100 ns why wait */
156   - /* mdelay(100); */ /* keep low for 100mS */
157   - reset[1] = 0x7f; /* force reset high (inactive)
158   - * and unmask interrupts */
159   - ret = i2c_writebytes(state,
160   - state->config->demod_address,
  134 +
  135 + /* force reset high (inactive) and unmask interrupts */
  136 + reset[1] = 0x7f;
  137 + ret = i2c_write_demod_bytes(state,
161 138 reset, sizeof(reset));
162 139 }
163   - /* Spec does not indicate a need for this either */
164   - /*mdelay(5); */ /* wait 5 msec before doing more */
165 140 return ret;
166 141 }
167 142  
  143 +static int lgdt3303_SwReset(struct lgdt330x_state* state)
  144 +{
  145 + u8 ret;
  146 + u8 reset[] = {
  147 + 0x02,
  148 + 0x00 /* bit 0 is active low software reset */
  149 + };
  150 +
  151 + ret = i2c_write_demod_bytes(state,
  152 + reset, sizeof(reset));
  153 + if (ret == 0) {
  154 +
  155 + /* force reset high (inactive) */
  156 + reset[1] = 0x01;
  157 + ret = i2c_write_demod_bytes(state,
  158 + reset, sizeof(reset));
  159 + }
  160 + return ret;
  161 +}
  162 +
  163 +static int lgdt330x_SwReset(struct lgdt330x_state* state)
  164 +{
  165 + switch (state->config->demod_chip) {
  166 + case LGDT3302:
  167 + return lgdt3302_SwReset(state);
  168 + case LGDT3303:
  169 + return lgdt3303_SwReset(state);
  170 + default:
  171 + return -ENODEV;
  172 + }
  173 +}
  174 +
  175 +#ifdef MUTE_TDA9887
  176 +static int i2c_write_ntsc_demod (struct lgdt330x_state* state, u8 buf[2])
  177 +{
  178 + struct i2c_msg msg =
  179 + { .addr = 0x43,
  180 + .flags = 0,
  181 + .buf = buf,
  182 + .len = 2 };
  183 + int err;
  184 +
  185 + if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
  186 + printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
  187 + if (err < 0)
  188 + return err;
  189 + else
  190 + return -EREMOTEIO;
  191 + }
  192 + return 0;
  193 +}
  194 +
  195 +static void fiddle_with_ntsc_if_demod(struct lgdt330x_state* state)
  196 +{
  197 + // Experimental code
  198 + u8 buf0[] = {0x00, 0x20};
  199 + u8 buf1[] = {0x01, 0x00};
  200 + u8 buf2[] = {0x02, 0x00};
  201 +
  202 + i2c_write_ntsc_demod(state, buf0);
  203 + i2c_write_ntsc_demod(state, buf1);
  204 + i2c_write_ntsc_demod(state, buf2);
  205 +}
  206 +#endif
  207 +
168 208 static int lgdt330x_init(struct dvb_frontend* fe)
169 209 {
170 210 /* Hardware reset is done using gpio[0] of cx23880x chip.
171 211  
172 212  
173 213  
... ... @@ -173,22 +213,101 @@
173 213 * Maybe there needs to be a callable function in cx88-core or
174 214 * the caller of this function needs to do it. */
175 215  
176   - dprintk("%s entered\n", __FUNCTION__);
177   - return lgdt330x_SwReset((struct lgdt330x_state*) fe->demodulator_priv);
  216 + /*
  217 + * Array of byte pairs <address, value>
  218 + * to initialize each different chip
  219 + */
  220 + static u8 lgdt3302_init_data[] = {
  221 + /* Use 50MHz parameter values from spec sheet since xtal is 50 */
  222 + /* Change the value of NCOCTFV[25:0] of carrier
  223 + recovery center frequency register */
  224 + VSB_CARRIER_FREQ0, 0x00,
  225 + VSB_CARRIER_FREQ1, 0x87,
  226 + VSB_CARRIER_FREQ2, 0x8e,
  227 + VSB_CARRIER_FREQ3, 0x01,
  228 + /* Change the TPCLK pin polarity
  229 + data is valid on falling clock */
  230 + DEMUX_CONTROL, 0xfb,
  231 + /* Change the value of IFBW[11:0] of
  232 + AGC IF/RF loop filter bandwidth register */
  233 + AGC_RF_BANDWIDTH0, 0x40,
  234 + AGC_RF_BANDWIDTH1, 0x93,
  235 + AGC_RF_BANDWIDTH2, 0x00,
  236 + /* Change the value of bit 6, 'nINAGCBY' and
  237 + 'NSSEL[1:0] of ACG function control register 2 */
  238 + AGC_FUNC_CTRL2, 0xc6,
  239 + /* Change the value of bit 6 'RFFIX'
  240 + of AGC function control register 3 */
  241 + AGC_FUNC_CTRL3, 0x40,
  242 + /* Set the value of 'INLVTHD' register 0x2a/0x2c
  243 + to 0x7fe */
  244 + AGC_DELAY0, 0x07,
  245 + AGC_DELAY2, 0xfe,
  246 + /* Change the value of IAGCBW[15:8]
  247 + of inner AGC loop filter bandwith */
  248 + AGC_LOOP_BANDWIDTH0, 0x08,
  249 + AGC_LOOP_BANDWIDTH1, 0x9a
  250 + };
  251 +
  252 + static u8 lgdt3303_init_data[] = {
  253 + 0x4c, 0x14
  254 + };
  255 +
  256 + struct lgdt330x_state* state = fe->demodulator_priv;
  257 + char *chip_name;
  258 + int err;
  259 +
  260 + switch (state->config->demod_chip) {
  261 + case LGDT3302:
  262 + chip_name = "LGDT3302";
  263 + err = i2c_write_demod_bytes(state, lgdt3302_init_data,
  264 + sizeof(lgdt3302_init_data));
  265 + break;
  266 + case LGDT3303:
  267 + chip_name = "LGDT3303";
  268 + err = i2c_write_demod_bytes(state, lgdt3303_init_data,
  269 + sizeof(lgdt3303_init_data));
  270 +#ifdef MUTE_TDA9887
  271 + fiddle_with_ntsc_if_demod(state);
  272 +#endif
  273 + break;
  274 + default:
  275 + chip_name = "undefined";
  276 + printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
  277 + err = -ENODEV;
  278 + }
  279 + dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
  280 + if (err < 0)
  281 + return err;
  282 + return lgdt330x_SwReset(state);
178 283 }
179 284  
180 285 static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber)
181 286 {
182   - *ber = 0; /* Dummy out for now */
  287 + *ber = 0; /* Not supplied by the demod chips */
183 288 return 0;
184 289 }
185 290  
186 291 static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
187 292 {
188   - struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
  293 + struct lgdt330x_state* state = fe->demodulator_priv;
  294 + int err;
189 295 u8 buf[2];
190 296  
191   - i2c_selectreadbytes(state, PACKET_ERR_COUNTER1, buf, sizeof(buf));
  297 + switch (state->config->demod_chip) {
  298 + case LGDT3302:
  299 + err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
  300 + buf, sizeof(buf));
  301 + break;
  302 + case LGDT3303:
  303 + err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
  304 + buf, sizeof(buf));
  305 + break;
  306 + default:
  307 + printk(KERN_WARNING
  308 + "Only LGDT3302 and LGDT3303 are supported chips.\n");
  309 + err = -ENODEV;
  310 + }
192 311  
193 312 *ucblocks = (buf[0] << 8) | buf[1];
194 313 return 0;
195 314  
196 315  
197 316  
198 317  
199 318  
200 319  
201 320  
202 321  
203 322  
204 323  
205 324  
206 325  
... ... @@ -197,123 +316,113 @@
197 316 static int lgdt330x_set_parameters(struct dvb_frontend* fe,
198 317 struct dvb_frontend_parameters *param)
199 318 {
200   - struct lgdt330x_state* state =
201   - (struct lgdt330x_state*) fe->demodulator_priv;
  319 + /*
  320 + * Array of byte pairs <address, value>
  321 + * to initialize 8VSB for lgdt3303 chip 50 MHz IF
  322 + */
  323 + static u8 lgdt3303_8vsb_44_data[] = {
  324 + 0x04, 0x00,
  325 + 0x0d, 0x40,
  326 + 0x0e, 0x87,
  327 + 0x0f, 0x8e,
  328 + 0x10, 0x01,
  329 + 0x47, 0x8b };
202 330  
203   - /* Use 50MHz parameter values from spec sheet since xtal is 50 */
  331 + /*
  332 + * Array of byte pairs <address, value>
  333 + * to initialize QAM for lgdt3303 chip
  334 + */
  335 + static u8 lgdt3303_qam_data[] = {
  336 + 0x04, 0x00,
  337 + 0x0d, 0x00,
  338 + 0x0e, 0x00,
  339 + 0x0f, 0x00,
  340 + 0x10, 0x00,
  341 + 0x51, 0x63,
  342 + 0x47, 0x66,
  343 + 0x48, 0x66,
  344 + 0x4d, 0x1a,
  345 + 0x49, 0x08,
  346 + 0x4a, 0x9b };
  347 +
  348 + struct lgdt330x_state* state = fe->demodulator_priv;
  349 +
204 350 static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 };
205   - static u8 vsb_freq_cfg[] = { VSB_CARRIER_FREQ0, 0x00, 0x87, 0x8e, 0x01 };
206   - static u8 demux_ctrl_cfg[] = { DEMUX_CONTROL, 0xfb };
207   - static u8 agc_rf_cfg[] = { AGC_RF_BANDWIDTH0, 0x40, 0x93, 0x00 };
208   - static u8 agc_ctrl_cfg[] = { AGC_FUNC_CTRL2, 0xc6, 0x40 };
209   - static u8 agc_delay_cfg[] = { AGC_DELAY0, 0x07, 0x00, 0xfe };
210   - static u8 agc_loop_cfg[] = { AGC_LOOP_BANDWIDTH0, 0x08, 0x9a };
211 351  
  352 + int err;
212 353 /* Change only if we are actually changing the modulation */
213 354 if (state->current_modulation != param->u.vsb.modulation) {
214 355 switch(param->u.vsb.modulation) {
215 356 case VSB_8:
216 357 dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
217 358  
218   - /* Select VSB mode and serial MPEG interface */
219   - top_ctrl_cfg[1] = 0x07;
  359 + /* Select VSB mode */
  360 + top_ctrl_cfg[1] = 0x03;
220 361  
221 362 /* Select ANT connector if supported by card */
222 363 if (state->config->pll_rf_set)
223 364 state->config->pll_rf_set(fe, 1);
  365 +
  366 + if (state->config->demod_chip == LGDT3303) {
  367 + err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data,
  368 + sizeof(lgdt3303_8vsb_44_data));
  369 + }
224 370 break;
225 371  
226 372 case QAM_64:
227 373 dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
228 374  
229   - /* Select QAM_64 mode and serial MPEG interface */
230   - top_ctrl_cfg[1] = 0x04;
  375 + /* Select QAM_64 mode */
  376 + top_ctrl_cfg[1] = 0x00;
231 377  
232 378 /* Select CABLE connector if supported by card */
233 379 if (state->config->pll_rf_set)
234 380 state->config->pll_rf_set(fe, 0);
  381 +
  382 + if (state->config->demod_chip == LGDT3303) {
  383 + err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
  384 + sizeof(lgdt3303_qam_data));
  385 + }
235 386 break;
236 387  
237 388 case QAM_256:
238 389 dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
239 390  
240   - /* Select QAM_256 mode and serial MPEG interface */
241   - top_ctrl_cfg[1] = 0x05;
  391 + /* Select QAM_256 mode */
  392 + top_ctrl_cfg[1] = 0x01;
242 393  
243 394 /* Select CABLE connector if supported by card */
244 395 if (state->config->pll_rf_set)
245 396 state->config->pll_rf_set(fe, 0);
  397 +
  398 + if (state->config->demod_chip == LGDT3303) {
  399 + err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
  400 + sizeof(lgdt3303_qam_data));
  401 + }
246 402 break;
247 403 default:
248 404 printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
249 405 return -1;
250 406 }
251   - /* Initializations common to all modes */
  407 + /*
  408 + * select serial or parallel MPEG harware interface
  409 + * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303
  410 + * Parallel: 0x00
  411 + */
  412 + top_ctrl_cfg[1] |= state->config->serial_mpeg;
252 413  
253 414 /* Select the requested mode */
254   - i2c_writebytes(state, state->config->demod_address,
255   - top_ctrl_cfg, sizeof(top_ctrl_cfg));
256   -
257   - /* Change the value of IFBW[11:0]
258   - of AGC IF/RF loop filter bandwidth register */
259   - i2c_writebytes(state, state->config->demod_address,
260   - agc_rf_cfg, sizeof(agc_rf_cfg));
261   -
262   - /* Change the value of bit 6, 'nINAGCBY' and
263   - 'NSSEL[1:0] of ACG function control register 2 */
264   - /* Change the value of bit 6 'RFFIX'
265   - of AGC function control register 3 */
266   - i2c_writebytes(state, state->config->demod_address,
267   - agc_ctrl_cfg, sizeof(agc_ctrl_cfg));
268   -
269   - /* Change the TPCLK pin polarity
270   - data is valid on falling clock */
271   - i2c_writebytes(state, state->config->demod_address,
272   - demux_ctrl_cfg, sizeof(demux_ctrl_cfg));
273   -
274   - /* Change the value of NCOCTFV[25:0] of carrier
275   - recovery center frequency register */
276   - i2c_writebytes(state, state->config->demod_address,
277   - vsb_freq_cfg, sizeof(vsb_freq_cfg));
278   -
279   - /* Set the value of 'INLVTHD' register 0x2a/0x2c to 0x7fe */
280   - i2c_writebytes(state, state->config->demod_address,
281   - agc_delay_cfg, sizeof(agc_delay_cfg));
282   -
283   - /* Change the value of IAGCBW[15:8]
284   - of inner AGC loop filter bandwith */
285   - i2c_writebytes(state, state->config->demod_address,
286   - agc_loop_cfg, sizeof(agc_loop_cfg));
287   -
  415 + i2c_write_demod_bytes(state, top_ctrl_cfg,
  416 + sizeof(top_ctrl_cfg));
288 417 state->config->set_ts_params(fe, 0);
289 418 state->current_modulation = param->u.vsb.modulation;
290 419 }
291 420  
292 421 /* Change only if we are actually changing the channel */
293 422 if (state->current_frequency != param->frequency) {
294   - u8 buf[5];
295   - struct i2c_msg msg = { .flags = 0, .buf = &buf[1], .len = 4 };
296   - int err;
297   -
298   - state->config->pll_set(fe, param, buf);
299   - msg.addr = buf[0];
300   -
301   - dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x "
302   - "0x%02x 0x%02x\n", __FUNCTION__,
303   - buf[0],buf[1],buf[2],buf[3],buf[4]);
304   - if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
305   - printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, buf[0], buf[1], err);
306   - if (err < 0)
307   - return err;
308   - else
309   - return -EREMOTEIO;
310   - }
311   -#if 0
312   - /* Check the status of the tuner pll */
313   - i2c_readbytes(state, buf[0], &buf[1], 1);
314   - dprintk("%s: tuner status byte = 0x%02x\n", __FUNCTION__, buf[1]);
315   -#endif
316   - /* Update current frequency */
  423 + /* Tune to the new frequency */
  424 + state->config->pll_set(fe, param);
  425 + /* Keep track of the new frequency */
317 426 state->current_frequency = param->frequency;
318 427 }
319 428 lgdt330x_SwReset(state);
320 429  
321 430  
322 431  
... ... @@ -328,21 +437,15 @@
328 437 return 0;
329 438 }
330 439  
331   -static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status)
  440 +static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
332 441 {
333   - struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
  442 + struct lgdt330x_state* state = fe->demodulator_priv;
334 443 u8 buf[3];
335 444  
336 445 *status = 0; /* Reset status result */
337 446  
338   - /*
339   - * You must set the Mask bits to 1 in the IRQ_MASK in order
340   - * to see that status bit in the IRQ_STATUS register.
341   - * This is done in SwReset();
342   - */
343   -
344 447 /* AGC status register */
345   - i2c_selectreadbytes(state, AGC_STATUS, buf, 1);
  448 + i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
346 449 dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
347 450 if ((buf[0] & 0x0c) == 0x8){
348 451 /* Test signal does not exist flag */
349 452  
350 453  
... ... @@ -353,16 +456,15 @@
353 456 return 0;
354 457 }
355 458  
  459 + /*
  460 + * You must set the Mask bits to 1 in the IRQ_MASK in order
  461 + * to see that status bit in the IRQ_STATUS register.
  462 + * This is done in SwReset();
  463 + */
356 464 /* signal status */
357   - i2c_selectreadbytes(state, TOP_CONTROL, buf, sizeof(buf));
  465 + i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
358 466 dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
359 467  
360   -#if 0
361   - /* Alternative method to check for a signal */
362   - /* using the SNR good/bad interrupts. */
363   - if ((buf[2] & 0x30) == 0x10)
364   - *status |= FE_HAS_SIGNAL;
365   -#endif
366 468  
367 469 /* sync status */
368 470 if ((buf[2] & 0x03) == 0x01) {
... ... @@ -376,7 +478,7 @@
376 478 }
377 479  
378 480 /* Carrier Recovery Lock Status Register */
379   - i2c_selectreadbytes(state, CARRIER_LOCK, buf, 1);
  481 + i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
380 482 dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
381 483 switch (state->current_modulation) {
382 484 case QAM_256:
383 485  
384 486  
... ... @@ -396,13 +498,75 @@
396 498 return 0;
397 499 }
398 500  
  501 +static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
  502 +{
  503 + struct lgdt330x_state* state = fe->demodulator_priv;
  504 + int err;
  505 + u8 buf[3];
  506 +
  507 + *status = 0; /* Reset status result */
  508 +
  509 + /* lgdt3303 AGC status register */
  510 + err = i2c_read_demod_bytes(state, 0x58, buf, 1);
  511 + if (err < 0)
  512 + return err;
  513 +
  514 + dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
  515 + if ((buf[0] & 0x21) == 0x01){
  516 + /* Test input signal does not exist flag */
  517 + /* as well as the AGC lock flag. */
  518 + *status |= FE_HAS_SIGNAL;
  519 + } else {
  520 + /* Without a signal all other status bits are meaningless */
  521 + return 0;
  522 + }
  523 +
  524 + /* Carrier Recovery Lock Status Register */
  525 + i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
  526 + dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
  527 + switch (state->current_modulation) {
  528 + case QAM_256:
  529 + case QAM_64:
  530 + /* Need to undestand why there are 3 lock levels here */
  531 + if ((buf[0] & 0x07) == 0x07)
  532 + *status |= FE_HAS_CARRIER;
  533 + else
  534 + break;
  535 + i2c_read_demod_bytes(state, 0x8a, buf, 1);
  536 + if ((buf[0] & 0x04) == 0x04)
  537 + *status |= FE_HAS_SYNC;
  538 + if ((buf[0] & 0x01) == 0x01)
  539 + *status |= FE_HAS_LOCK;
  540 + if ((buf[0] & 0x08) == 0x08)
  541 + *status |= FE_HAS_VITERBI;
  542 + break;
  543 + case VSB_8:
  544 + if ((buf[0] & 0x80) == 0x80)
  545 + *status |= FE_HAS_CARRIER;
  546 + else
  547 + break;
  548 + i2c_read_demod_bytes(state, 0x38, buf, 1);
  549 + if ((buf[0] & 0x02) == 0x00)
  550 + *status |= FE_HAS_SYNC;
  551 + if ((buf[0] & 0x01) == 0x01) {
  552 + *status |= FE_HAS_LOCK;
  553 + *status |= FE_HAS_VITERBI;
  554 + }
  555 + break;
  556 + default:
  557 + printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
  558 + }
  559 + return 0;
  560 +}
  561 +
399 562 static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
400 563 {
401 564 /* not directly available. */
  565 + *strength = 0;
402 566 return 0;
403 567 }
404 568  
405   -static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
  569 +static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
406 570 {
407 571 #ifdef SNR_IN_DB
408 572 /*
... ... @@ -451,7 +615,7 @@
451 615 91, 115, 144, 182, 229, 288, 362, 456, 574, 722,
452 616 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216,
453 617 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151,
454   - 90833, 114351, 143960, 181235, 228161, 0x040000
  618 + 90833, 114351, 143960, 181235, 228161, 0x080000
455 619 };
456 620  
457 621 static u8 buf[5];/* read data buffer */
... ... @@ -459,8 +623,8 @@
459 623 static u32 snr_db; /* index into SNR_EQ[] */
460 624 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
461 625  
462   - /* read both equalizer and pase tracker noise data */
463   - i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf));
  626 + /* read both equalizer and phase tracker noise data */
  627 + i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
464 628  
465 629 if (state->current_modulation == VSB_8) {
466 630 /* Equalizer Mean-Square Error Register for VSB */
467 631  
468 632  
469 633  
... ... @@ -496,19 +660,20 @@
496 660 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
497 661  
498 662 /* read both equalizer and pase tracker noise data */
499   - i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf));
  663 + i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
500 664  
501 665 if (state->current_modulation == VSB_8) {
502   - /* Equalizer Mean-Square Error Register for VSB */
503   - noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
504   - } else {
505   - /* Phase Tracker Mean-Square Error Register for QAM */
  666 + /* Phase Tracker Mean-Square Error Register for VSB */
506 667 noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
  668 + } else {
  669 +
  670 + /* Carrier Recovery Mean-Square Error for QAM */
  671 + i2c_read_demod_bytes(state, 0x1a, buf, 2);
  672 + noise = ((buf[0] & 3) << 8) | buf[1];
507 673 }
508 674  
509 675 /* Small values for noise mean signal is better so invert noise */
510   - /* Noise is 19 bit value so discard 3 LSB*/
511   - *snr = ~noise>>3;
  676 + *snr = ~noise;
512 677 #endif
513 678  
514 679 dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
... ... @@ -516,6 +681,32 @@
516 681 return 0;
517 682 }
518 683  
  684 +static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
  685 +{
  686 + /* Return the raw noise value */
  687 + static u8 buf[5];/* read data buffer */
  688 + static u32 noise; /* noise value */
  689 + struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
  690 +
  691 + if (state->current_modulation == VSB_8) {
  692 +
  693 + /* Phase Tracker Mean-Square Error Register for VSB */
  694 + noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
  695 + } else {
  696 +
  697 + /* Carrier Recovery Mean-Square Error for QAM */
  698 + i2c_read_demod_bytes(state, 0x1a, buf, 2);
  699 + noise = (buf[0] << 8) | buf[1];
  700 + }
  701 +
  702 + /* Small values for noise mean signal is better so invert noise */
  703 + *snr = ~noise;
  704 +
  705 + dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
  706 +
  707 + return 0;
  708 +}
  709 +
519 710 static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
520 711 {
521 712 /* I have no idea about this - it may not be needed */
... ... @@ -531,7 +722,8 @@
531 722 kfree(state);
532 723 }
533 724  
534   -static struct dvb_frontend_ops lgdt330x_ops;
  725 +static struct dvb_frontend_ops lgdt3302_ops;
  726 +static struct dvb_frontend_ops lgdt3303_ops;
535 727  
536 728 struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
537 729 struct i2c_adapter* i2c)
538 730  
... ... @@ -548,9 +740,19 @@
548 740 /* Setup the state */
549 741 state->config = config;
550 742 state->i2c = i2c;
551   - memcpy(&state->ops, &lgdt330x_ops, sizeof(struct dvb_frontend_ops));
  743 + switch (config->demod_chip) {
  744 + case LGDT3302:
  745 + memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
  746 + break;
  747 + case LGDT3303:
  748 + memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
  749 + break;
  750 + default:
  751 + goto error;
  752 + }
  753 +
552 754 /* Verify communication with demod chip */
553   - if (i2c_selectreadbytes(state, 2, buf, 1))
  755 + if (i2c_read_demod_bytes(state, 2, buf, 1))
554 756 goto error;
555 757  
556 758 state->current_frequency = -1;
557 759  
... ... @@ -568,9 +770,9 @@
568 770 return NULL;
569 771 }
570 772  
571   -static struct dvb_frontend_ops lgdt330x_ops = {
  773 +static struct dvb_frontend_ops lgdt3302_ops = {
572 774 .info = {
573   - .name= "LG Electronics lgdt330x VSB/QAM Frontend",
  775 + .name= "LG Electronics LGDT3302/LGDT3303 VSB/QAM Frontend",
574 776 .type = FE_ATSC,
575 777 .frequency_min= 54000000,
576 778 .frequency_max= 858000000,
577 779  
578 780  
... ... @@ -584,15 +786,39 @@
584 786 .set_frontend = lgdt330x_set_parameters,
585 787 .get_frontend = lgdt330x_get_frontend,
586 788 .get_tune_settings = lgdt330x_get_tune_settings,
587   - .read_status = lgdt330x_read_status,
  789 + .read_status = lgdt3302_read_status,
588 790 .read_ber = lgdt330x_read_ber,
589 791 .read_signal_strength = lgdt330x_read_signal_strength,
590   - .read_snr = lgdt330x_read_snr,
  792 + .read_snr = lgdt3302_read_snr,
591 793 .read_ucblocks = lgdt330x_read_ucblocks,
592 794 .release = lgdt330x_release,
593 795 };
594 796  
595   -MODULE_DESCRIPTION("lgdt330x [DViCO FusionHDTV 3 Gold] (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
  797 +static struct dvb_frontend_ops lgdt3303_ops = {
  798 + .info = {
  799 + .name= "LG Electronics LGDT3303 VSB/QAM Frontend",
  800 + .type = FE_ATSC,
  801 + .frequency_min= 54000000,
  802 + .frequency_max= 858000000,
  803 + .frequency_stepsize= 62500,
  804 + /* Symbol rate is for all VSB modes need to check QAM */
  805 + .symbol_rate_min = 10762000,
  806 + .symbol_rate_max = 10762000,
  807 + .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
  808 + },
  809 + .init = lgdt330x_init,
  810 + .set_frontend = lgdt330x_set_parameters,
  811 + .get_frontend = lgdt330x_get_frontend,
  812 + .get_tune_settings = lgdt330x_get_tune_settings,
  813 + .read_status = lgdt3303_read_status,
  814 + .read_ber = lgdt330x_read_ber,
  815 + .read_signal_strength = lgdt330x_read_signal_strength,
  816 + .read_snr = lgdt3303_read_snr,
  817 + .read_ucblocks = lgdt330x_read_ucblocks,
  818 + .release = lgdt330x_release,
  819 +};
  820 +
  821 +MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
596 822 MODULE_AUTHOR("Wilson Michaels");
597 823 MODULE_LICENSE("GPL");
598 824  
... ... @@ -601,7 +827,6 @@
601 827 /*
602 828 * Local variables:
603 829 * c-basic-offset: 8
604   - * compile-command: "make DVB=1"
605 830 * End:
606 831 */
drivers/media/dvb/frontends/lgdt330x.h
1 1 /*
2   - * Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM
  2 + * Support for LGDT3302 and LGDT3303 - VSB/QAM
3 3 *
4 4 * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
5 5 *
6 6  
7 7  
... ... @@ -24,14 +24,26 @@
24 24  
25 25 #include <linux/dvb/frontend.h>
26 26  
  27 +typedef enum lg_chip_t {
  28 + UNDEFINED,
  29 + LGDT3302,
  30 + LGDT3303
  31 +}lg_chip_type;
  32 +
27 33 struct lgdt330x_config
28 34 {
29 35 /* The demodulator's i2c address */
30 36 u8 demod_address;
31 37  
  38 + /* LG demodulator chip LGDT3302 or LGDT3303 */
  39 + lg_chip_type demod_chip;
  40 +
  41 + /* MPEG hardware interface - 0:parallel 1:serial */
  42 + int serial_mpeg;
  43 +
32 44 /* PLL interface */
33 45 int (*pll_rf_set) (struct dvb_frontend* fe, int index);
34   - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pll_address);
  46 + int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
35 47  
36 48 /* Need to set device param for start_dma */
37 49 int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
drivers/media/dvb/frontends/lgdt330x_priv.h
1 1 /*
2   - * Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM
  2 + * Support for LGDT3302 and LGDT3303 - VSB/QAM
3 3 *
4 4 * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
5 5 *
... ... @@ -57,8 +57,10 @@
57 57 PH_ERR1= 0x4a,
58 58 PH_ERR2= 0x4b,
59 59 DEMUX_CONTROL= 0x66,
60   - PACKET_ERR_COUNTER1= 0x6a,
61   - PACKET_ERR_COUNTER2= 0x6b,
  60 + LGDT3302_PACKET_ERR_COUNTER1= 0x6a,
  61 + LGDT3302_PACKET_ERR_COUNTER2= 0x6b,
  62 + LGDT3303_PACKET_ERR_COUNTER1= 0x8b,
  63 + LGDT3303_PACKET_ERR_COUNTER2= 0x8c,
62 64 };
63 65  
64 66 #endif /* _LGDT330X_PRIV_ */
drivers/media/video/cx88/cx88-dvb.c
1 1 /*
2   - * $Id: cx88-dvb.c,v 1.54 2005/07/25 05:13:50 mkrufky Exp $
  2 + * $Id: cx88-dvb.c,v 1.58 2005/08/07 09:24:08 mkrufky Exp $
3 3 *
4 4 * device driver for Conexant 2388x based TV cards
5 5 * MPEG Transport Stream (DVB) routines
6 6  
7 7  
... ... @@ -208,14 +208,26 @@
208 208  
209 209 #ifdef HAVE_LGDT330X
210 210 static int lgdt330x_pll_set(struct dvb_frontend* fe,
211   - struct dvb_frontend_parameters* params,
212   - u8* pllbuf)
  211 + struct dvb_frontend_parameters* params)
213 212 {
214 213 struct cx8802_dev *dev= fe->dvb->priv;
  214 + u8 buf[4];
  215 + struct i2c_msg msg =
  216 + { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
  217 + int err;
215 218  
216   - pllbuf[0] = dev->core->pll_addr;
217   - dvb_pll_configure(dev->core->pll_desc, &pllbuf[1],
218   - params->frequency, 0);
  219 + dvb_pll_configure(dev->core->pll_desc, buf, params->frequency, 0);
  220 + dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
  221 + __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
  222 + if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
  223 + printk(KERN_WARNING "cx88-dvb: %s error "
  224 + "(addr %02x <- %02x, err = %i)\n",
  225 + __FUNCTION__, buf[0], buf[1], err);
  226 + if (err < 0)
  227 + return err;
  228 + else
  229 + return -EREMOTEIO;
  230 + }
219 231 return 0;
220 232 }
221 233  
... ... @@ -244,6 +256,8 @@
244 256  
245 257 static struct lgdt330x_config fusionhdtv_3_gold = {
246 258 .demod_address = 0x0e,
  259 + .demod_chip = LGDT3302,
  260 + .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
247 261 .pll_set = lgdt330x_pll_set,
248 262 .set_ts_params = lgdt330x_set_ts_param,
249 263 };