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