blob: c85a2a99df428b2188f05d9409cd0ecd3cc2b9a3 [file] [log] [blame]
Mac Michaelsd8667cb2005-07-07 17:58:29 -07001/*
Mac Michaelsd8667cb2005-07-07 17:58:29 -07002 * Support for LGDT3302 (DViCO FustionHDTV 3 Gold) - VSB/QAM
3 *
4 * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
5 *
6 * Based on code from Kirk Lapray <kirk_lapray@bigfoot.com>
7 * Copyright (C) 2005
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25/*
26 * NOTES ABOUT THIS DRIVER
27 *
28 * This driver supports DViCO FusionHDTV 3 Gold under Linux.
29 *
30 * TODO:
31 * BER and signal strength always return 0.
32 *
33 */
34
Mac Michaelsd8667cb2005-07-07 17:58:29 -070035#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/moduleparam.h>
38#include <linux/init.h>
39#include <linux/delay.h>
40#include <asm/byteorder.h>
41
42#include "dvb_frontend.h"
43#include "dvb-pll.h"
44#include "lgdt3302_priv.h"
45#include "lgdt3302.h"
46
47static int debug = 0;
48module_param(debug, int, 0644);
49MODULE_PARM_DESC(debug,"Turn on/off lgdt3302 frontend debugging (default:off).");
50#define dprintk(args...) \
51do { \
52if (debug) printk(KERN_DEBUG "lgdt3302: " args); \
53} while (0)
54
55struct lgdt3302_state
56{
57 struct i2c_adapter* i2c;
58 struct dvb_frontend_ops ops;
59
60 /* Configuration settings */
61 const struct lgdt3302_config* config;
62
63 struct dvb_frontend frontend;
64
65 /* Demodulator private data */
66 fe_modulation_t current_modulation;
67
68 /* Tuner private data */
69 u32 current_frequency;
70};
71
72static int i2c_writebytes (struct lgdt3302_state* state,
73 u8 addr, /* demod_address or pll_address */
74 u8 *buf, /* data bytes to send */
75 int len /* number of bytes to send */ )
76{
77 if (addr == state->config->pll_address) {
78 struct i2c_msg msg =
79 { .addr = addr, .flags = 0, .buf = buf, .len = len };
80 int err;
81
82 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
83 printk(KERN_WARNING "lgdt3302: %s error (addr %02x <- %02x, err == %i)\n", __FUNCTION__, addr, buf[0], err);
Michael Krufky58ba0062005-07-12 13:58:37 -070084 if (err < 0)
85 return err;
86 else
87 return -EREMOTEIO;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070088 }
89 } else {
90 u8 tmp[] = { buf[0], buf[1] };
91 struct i2c_msg msg =
92 { .addr = addr, .flags = 0, .buf = tmp, .len = 2 };
93 int err;
94 int i;
95
96 for (i=1; i<len; i++) {
97 tmp[1] = buf[i];
98 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
99 printk(KERN_WARNING "lgdt3302: %s error (addr %02x <- %02x, err == %i)\n", __FUNCTION__, addr, buf[0], err);
Michael Krufky58ba0062005-07-12 13:58:37 -0700100 if (err < 0)
101 return err;
102 else
103 return -EREMOTEIO;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700104 }
105 tmp[0]++;
106 }
107 }
108 return 0;
109}
110static int i2c_readbytes (struct lgdt3302_state* state,
111 u8 addr, /* demod_address or pll_address */
112 u8 *buf, /* holds data bytes read */
113 int len /* number of bytes to read */ )
114{
115 struct i2c_msg msg =
116 { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len };
117 int err;
118
119 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
120 printk(KERN_WARNING "lgdt3302: %s error (addr %02x, err == %i)\n", __FUNCTION__, addr, err);
121 return -EREMOTEIO;
122 }
123 return 0;
124}
125
126/*
127 * This routine writes the register (reg) to the demod bus
128 * then reads the data returned for (len) bytes.
129 */
130
131static u8 i2c_selectreadbytes (struct lgdt3302_state* state,
132 enum I2C_REG reg, u8* buf, int len)
133{
134 u8 wr [] = { reg };
135 struct i2c_msg msg [] = {
136 { .addr = state->config->demod_address,
137 .flags = 0, .buf = wr, .len = 1 },
138 { .addr = state->config->demod_address,
139 .flags = I2C_M_RD, .buf = buf, .len = len },
140 };
141 int ret;
142 ret = i2c_transfer(state->i2c, msg, 2);
143 if (ret != 2) {
144 printk(KERN_WARNING "lgdt3302: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __FUNCTION__, state->config->demod_address, reg, ret);
145 } else {
146 ret = 0;
147 }
148 return ret;
149}
150
151/* Software reset */
152int lgdt3302_SwReset(struct lgdt3302_state* state)
153{
154 u8 ret;
155 u8 reset[] = {
156 IRQ_MASK,
157 0x00 /* bit 6 is active low software reset
158 * bits 5-0 are 1 to mask interrupts */
159 };
160
161 ret = i2c_writebytes(state,
162 state->config->demod_address,
163 reset, sizeof(reset));
164 if (ret == 0) {
165 /* spec says reset takes 100 ns why wait */
166 /* mdelay(100); */ /* keep low for 100mS */
167 reset[1] = 0x7f; /* force reset high (inactive)
168 * and unmask interrupts */
169 ret = i2c_writebytes(state,
170 state->config->demod_address,
171 reset, sizeof(reset));
172 }
173 /* Spec does not indicate a need for this either */
174 /*mdelay(5); */ /* wait 5 msec before doing more */
175 return ret;
176}
177
178static int lgdt3302_init(struct dvb_frontend* fe)
179{
180 /* Hardware reset is done using gpio[0] of cx23880x chip.
181 * I'd like to do it here, but don't know how to find chip address.
182 * cx88-cards.c arranges for the reset bit to be inactive (high).
183 * Maybe there needs to be a callable function in cx88-core or
184 * the caller of this function needs to do it. */
185
186 dprintk("%s entered\n", __FUNCTION__);
187 return lgdt3302_SwReset((struct lgdt3302_state*) fe->demodulator_priv);
188}
189
190static int lgdt3302_read_ber(struct dvb_frontend* fe, u32* ber)
191{
192 *ber = 0; /* Dummy out for now */
193 return 0;
194}
195
196static int lgdt3302_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
197{
198 struct lgdt3302_state* state = (struct lgdt3302_state*) fe->demodulator_priv;
199 u8 buf[2];
200
201 i2c_selectreadbytes(state, PACKET_ERR_COUNTER1, buf, sizeof(buf));
202
203 *ucblocks = (buf[0] << 8) | buf[1];
204 return 0;
205}
206
207static int lgdt3302_set_parameters(struct dvb_frontend* fe,
208 struct dvb_frontend_parameters *param)
209{
210 u8 buf[4];
211 struct lgdt3302_state* state =
212 (struct lgdt3302_state*) fe->demodulator_priv;
213
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700214 /* Use 50MHz parameter values from spec sheet since xtal is 50 */
215 static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 };
216 static u8 vsb_freq_cfg[] = { VSB_CARRIER_FREQ0, 0x00, 0x87, 0x8e, 0x01 };
217 static u8 demux_ctrl_cfg[] = { DEMUX_CONTROL, 0xfb };
218 static u8 agc_rf_cfg[] = { AGC_RF_BANDWIDTH0, 0x40, 0x93, 0x00 };
219 static u8 agc_ctrl_cfg[] = { AGC_FUNC_CTRL2, 0xc6, 0x40 };
Michael Krufky3952db62005-07-14 00:33:33 -0700220 static u8 agc_delay_cfg[] = { AGC_DELAY0, 0x07, 0x00, 0xfe };
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700221 static u8 agc_loop_cfg[] = { AGC_LOOP_BANDWIDTH0, 0x08, 0x9a };
222
223 /* Change only if we are actually changing the modulation */
224 if (state->current_modulation != param->u.vsb.modulation) {
225 switch(param->u.vsb.modulation) {
226 case VSB_8:
227 dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
228
229 /* Select VSB mode and serial MPEG interface */
230 top_ctrl_cfg[1] = 0x07;
231 break;
232
233 case QAM_64:
234 dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
235
236 /* Select QAM_64 mode and serial MPEG interface */
237 top_ctrl_cfg[1] = 0x04;
238 break;
239
240 case QAM_256:
241 dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
242
243 /* Select QAM_256 mode and serial MPEG interface */
244 top_ctrl_cfg[1] = 0x05;
245 break;
246 default:
247 printk(KERN_WARNING "lgdt3302: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
248 return -1;
249 }
250 /* Initializations common to all modes */
251
252 /* Select the requested mode */
253 i2c_writebytes(state, state->config->demod_address,
254 top_ctrl_cfg, sizeof(top_ctrl_cfg));
255
256 /* Change the value of IFBW[11:0]
257 of AGC IF/RF loop filter bandwidth register */
258 i2c_writebytes(state, state->config->demod_address,
259 agc_rf_cfg, sizeof(agc_rf_cfg));
260
261 /* Change the value of bit 6, 'nINAGCBY' and
262 'NSSEL[1:0] of ACG function control register 2 */
263 /* Change the value of bit 6 'RFFIX'
264 of AGC function control register 3 */
265 i2c_writebytes(state, state->config->demod_address,
266 agc_ctrl_cfg, sizeof(agc_ctrl_cfg));
267
268 /* Change the TPCLK pin polarity
269 data is valid on falling clock */
270 i2c_writebytes(state, state->config->demod_address,
271 demux_ctrl_cfg, sizeof(demux_ctrl_cfg));
272
Michael Krufky58ba0062005-07-12 13:58:37 -0700273 /* Change the value of NCOCTFV[25:0] of carrier
274 recovery center frequency register */
275 i2c_writebytes(state, state->config->demod_address,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700276 vsb_freq_cfg, sizeof(vsb_freq_cfg));
Michael Krufky3952db62005-07-14 00:33:33 -0700277
278 /* Set the value of 'INLVTHD' register 0x2a/0x2c to 0x7fe */
Michael Krufky58ba0062005-07-12 13:58:37 -0700279 i2c_writebytes(state, state->config->demod_address,
280 agc_delay_cfg, sizeof(agc_delay_cfg));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700281
Michael Krufky58ba0062005-07-12 13:58:37 -0700282 /* Change the value of IAGCBW[15:8]
283 of inner AGC loop filter bandwith */
284 i2c_writebytes(state, state->config->demod_address,
285 agc_loop_cfg, sizeof(agc_loop_cfg));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700286
287 state->config->set_ts_params(fe, 0);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700288 state->current_modulation = param->u.vsb.modulation;
289 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700290
291 /* Change only if we are actually changing the channel */
292 if (state->current_frequency != param->frequency) {
293 dvb_pll_configure(state->config->pll_desc, buf,
294 param->frequency, 0);
295 dprintk("%s: tuner bytes: 0x%02x 0x%02x "
296 "0x%02x 0x%02x\n", __FUNCTION__, buf[0],buf[1],buf[2],buf[3]);
297 i2c_writebytes(state, state->config->pll_address ,buf, 4);
298
299 /* Check the status of the tuner pll */
300 i2c_readbytes(state, state->config->pll_address, buf, 1);
301 dprintk("%s: tuner status byte = 0x%02x\n", __FUNCTION__, buf[0]);
302
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700303 /* Update current frequency */
304 state->current_frequency = param->frequency;
305 }
Michael Krufky58ba0062005-07-12 13:58:37 -0700306 lgdt3302_SwReset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700307 return 0;
308}
309
310static int lgdt3302_get_frontend(struct dvb_frontend* fe,
311 struct dvb_frontend_parameters* param)
312{
313 struct lgdt3302_state *state = fe->demodulator_priv;
314 param->frequency = state->current_frequency;
315 return 0;
316}
317
318static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
319{
320 struct lgdt3302_state* state = (struct lgdt3302_state*) fe->demodulator_priv;
321 u8 buf[3];
322
323 *status = 0; /* Reset status result */
324
325 /* Check the status of the tuner pll */
326 i2c_readbytes(state, state->config->pll_address, buf, 1);
327 dprintk("%s: tuner status byte = 0x%02x\n", __FUNCTION__, buf[0]);
328 if ((buf[0] & 0xc0) != 0x40)
329 return 0; /* Tuner PLL not locked or not powered on */
330
331 /*
332 * You must set the Mask bits to 1 in the IRQ_MASK in order
333 * to see that status bit in the IRQ_STATUS register.
334 * This is done in SwReset();
335 */
336
Michael Krufky08d80522005-07-07 17:58:43 -0700337 /* AGC status register */
338 i2c_selectreadbytes(state, AGC_STATUS, buf, 1);
339 dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
340 if ((buf[0] & 0x0c) == 0x8){
341 /* Test signal does not exist flag */
342 /* as well as the AGC lock flag. */
343 *status |= FE_HAS_SIGNAL;
344 } else {
345 /* Without a signal all other status bits are meaningless */
346 return 0;
347 }
348
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700349 /* signal status */
350 i2c_selectreadbytes(state, TOP_CONTROL, buf, sizeof(buf));
351 dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
Michael Krufky08d80522005-07-07 17:58:43 -0700352
353#if 0
354 /* Alternative method to check for a signal */
355 /* using the SNR good/bad interrupts. */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700356 if ((buf[2] & 0x30) == 0x10)
357 *status |= FE_HAS_SIGNAL;
Michael Krufky08d80522005-07-07 17:58:43 -0700358#endif
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700359
360 /* sync status */
361 if ((buf[2] & 0x03) == 0x01) {
362 *status |= FE_HAS_SYNC;
363 }
364
365 /* FEC error status */
366 if ((buf[2] & 0x0c) == 0x08) {
367 *status |= FE_HAS_LOCK;
368 *status |= FE_HAS_VITERBI;
369 }
370
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700371 /* Carrier Recovery Lock Status Register */
372 i2c_selectreadbytes(state, CARRIER_LOCK, buf, 1);
373 dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
374 switch (state->current_modulation) {
375 case QAM_256:
376 case QAM_64:
377 /* Need to undestand why there are 3 lock levels here */
378 if ((buf[0] & 0x07) == 0x07)
379 *status |= FE_HAS_CARRIER;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700380 break;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700381 case VSB_8:
382 if ((buf[0] & 0x80) == 0x80)
383 *status |= FE_HAS_CARRIER;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700384 break;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700385 default:
386 printk("KERN_WARNING lgdt3302: %s: Modulation set to unsupported value\n", __FUNCTION__);
387 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700388
389 return 0;
390}
391
392static int lgdt3302_read_signal_strength(struct dvb_frontend* fe, u16* strength)
393{
394 /* not directly available. */
395 return 0;
396}
397
398static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
399{
400#ifdef SNR_IN_DB
401 /*
402 * Spec sheet shows formula for SNR_EQ = 10 log10(25 * 24**2 / noise)
403 * and SNR_PH = 10 log10(25 * 32**2 / noise) for equalizer and phase tracker
404 * respectively. The following tables are built on these formulas.
405 * The usual definition is SNR = 20 log10(signal/noise)
406 * If the specification is wrong the value retuned is 1/2 the actual SNR in db.
407 *
408 * This table is a an ordered list of noise values computed by the
409 * formula from the spec sheet such that the index into the table
410 * starting at 43 or 45 is the SNR value in db. There are duplicate noise
411 * value entries at the beginning because the SNR varies more than
412 * 1 db for a change of 1 digit in noise at very small values of noise.
413 *
414 * Examples from SNR_EQ table:
415 * noise SNR
416 * 0 43
417 * 1 42
418 * 2 39
419 * 3 37
420 * 4 36
421 * 5 35
422 * 6 34
423 * 7 33
424 * 8 33
425 * 9 32
426 * 10 32
427 * 11 31
428 * 12 31
429 * 13 30
430 */
431
432 static const u32 SNR_EQ[] =
433 { 1, 2, 2, 2, 3, 3, 4, 4, 5, 7,
434 9, 11, 13, 17, 21, 26, 33, 41, 52, 65,
435 81, 102, 129, 162, 204, 257, 323, 406, 511, 644,
436 810, 1020, 1284, 1616, 2035, 2561, 3224, 4059, 5110, 6433,
437 8098, 10195, 12835, 16158, 20341, 25608, 32238, 40585, 51094, 64323,
438 80978, 101945, 128341, 161571, 203406, 256073, 0x40000
439 };
440
441 static const u32 SNR_PH[] =
442 { 1, 2, 2, 2, 3, 3, 4, 5, 6, 8,
443 10, 12, 15, 19, 23, 29, 37, 46, 58, 73,
444 91, 115, 144, 182, 229, 288, 362, 456, 574, 722,
445 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216,
446 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151,
447 90833, 114351, 143960, 181235, 228161, 0x040000
448 };
449
450 static u8 buf[5];/* read data buffer */
451 static u32 noise; /* noise value */
452 static u32 snr_db; /* index into SNR_EQ[] */
453 struct lgdt3302_state* state = (struct lgdt3302_state*) fe->demodulator_priv;
454
455 /* read both equalizer and pase tracker noise data */
456 i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf));
457
458 if (state->current_modulation == VSB_8) {
459 /* Equalizer Mean-Square Error Register for VSB */
460 noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
461
462 /*
463 * Look up noise value in table.
464 * A better search algorithm could be used...
465 * watch out there are duplicate entries.
466 */
467 for (snr_db = 0; snr_db < sizeof(SNR_EQ); snr_db++) {
468 if (noise < SNR_EQ[snr_db]) {
469 *snr = 43 - snr_db;
470 break;
471 }
472 }
473 } else {
474 /* Phase Tracker Mean-Square Error Register for QAM */
475 noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
476
477 /* Look up noise value in table. */
478 for (snr_db = 0; snr_db < sizeof(SNR_PH); snr_db++) {
479 if (noise < SNR_PH[snr_db]) {
480 *snr = 45 - snr_db;
481 break;
482 }
483 }
484 }
485#else
486 /* Return the raw noise value */
487 static u8 buf[5];/* read data buffer */
488 static u32 noise; /* noise value */
489 struct lgdt3302_state* state = (struct lgdt3302_state*) fe->demodulator_priv;
490
491 /* read both equalizer and pase tracker noise data */
492 i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf));
493
494 if (state->current_modulation == VSB_8) {
495 /* Equalizer Mean-Square Error Register for VSB */
496 noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
497 } else {
498 /* Phase Tracker Mean-Square Error Register for QAM */
499 noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
500 }
501
502 /* Small values for noise mean signal is better so invert noise */
503 /* Noise is 19 bit value so discard 3 LSB*/
504 *snr = ~noise>>3;
505#endif
506
507 dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
508
509 return 0;
510}
511
512static int lgdt3302_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
513{
514 /* I have no idea about this - it may not be needed */
515 fe_tune_settings->min_delay_ms = 500;
516 fe_tune_settings->step_size = 0;
517 fe_tune_settings->max_drift = 0;
518 return 0;
519}
520
521static void lgdt3302_release(struct dvb_frontend* fe)
522{
523 struct lgdt3302_state* state = (struct lgdt3302_state*) fe->demodulator_priv;
524 kfree(state);
525}
526
527static struct dvb_frontend_ops lgdt3302_ops;
528
529struct dvb_frontend* lgdt3302_attach(const struct lgdt3302_config* config,
530 struct i2c_adapter* i2c)
531{
532 struct lgdt3302_state* state = NULL;
533 u8 buf[1];
534
535 /* Allocate memory for the internal state */
536 state = (struct lgdt3302_state*) kmalloc(sizeof(struct lgdt3302_state), GFP_KERNEL);
537 if (state == NULL)
538 goto error;
539 memset(state,0,sizeof(*state));
540
541 /* Setup the state */
542 state->config = config;
543 state->i2c = i2c;
544 memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
545 /* Verify communication with demod chip */
546 if (i2c_selectreadbytes(state, 2, buf, 1))
547 goto error;
548
549 state->current_frequency = -1;
550 state->current_modulation = -1;
551
552 /* Create dvb_frontend */
553 state->frontend.ops = &state->ops;
554 state->frontend.demodulator_priv = state;
555 return &state->frontend;
556
557error:
558 if (state)
559 kfree(state);
560 dprintk("%s: ERROR\n",__FUNCTION__);
561 return NULL;
562}
563
564static struct dvb_frontend_ops lgdt3302_ops = {
565 .info = {
566 .name= "LG Electronics LGDT3302 VSB/QAM Frontend",
567 .type = FE_ATSC,
568 .frequency_min= 54000000,
569 .frequency_max= 858000000,
570 .frequency_stepsize= 62500,
571 /* Symbol rate is for all VSB modes need to check QAM */
572 .symbol_rate_min = 10762000,
573 .symbol_rate_max = 10762000,
574 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
575 },
576 .init = lgdt3302_init,
577 .set_frontend = lgdt3302_set_parameters,
578 .get_frontend = lgdt3302_get_frontend,
579 .get_tune_settings = lgdt3302_get_tune_settings,
580 .read_status = lgdt3302_read_status,
581 .read_ber = lgdt3302_read_ber,
582 .read_signal_strength = lgdt3302_read_signal_strength,
583 .read_snr = lgdt3302_read_snr,
584 .read_ucblocks = lgdt3302_read_ucblocks,
585 .release = lgdt3302_release,
586};
587
588MODULE_DESCRIPTION("LGDT3302 [DViCO FusionHDTV 3 Gold] (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
589MODULE_AUTHOR("Wilson Michaels");
590MODULE_LICENSE("GPL");
591
592EXPORT_SYMBOL(lgdt3302_attach);
593
594/*
595 * Local variables:
596 * c-basic-offset: 8
597 * compile-command: "make DVB=1"
598 * End:
599 */