ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / media / dvb / frontends / grundig_29504-401.c
1 /* 
2     driver for Grundig 29504-401 DVB-T Frontends based on
3     LSI L64781 COFDM demodulator as used in Technotrend DVB-T cards
4
5     Copyright (C) 2001 Holger Waechtler <holger@convergence.de>
6                        for Convergence Integrated Media GmbH
7                        Marko Kohtala <marko.kohtala@nokia.com>
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 #include <linux/init.h>
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/string.h>
29 #include <linux/slab.h>
30
31 #include "dvb_frontend.h"
32 #include "dvb_functions.h"
33
34 static int debug = 0;
35
36 #define dprintk if (debug) printk
37
38 struct grundig_state {
39         int first:1;
40 };
41
42 struct dvb_frontend_info grundig_29504_401_info = {
43         .name = "Grundig 29504-401",
44         .type = FE_OFDM,
45 /*      .frequency_min = ???,*/
46 /*      .frequency_max = ???,*/
47         .frequency_stepsize = 166666,
48 /*      .frequency_tolerance = ???,*/
49 /*      .symbol_rate_tolerance = ???,*/
50         .notifier_delay = 0,
51         .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
52               FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
53               FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
54               FE_CAN_MUTE_TS
55 };
56
57
58 static int l64781_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data)
59 {
60         int ret;
61         u8 buf [] = { reg, data };
62         struct i2c_msg msg = { .addr = 0x55, .flags = 0, .buf = buf, .len = 2 };
63
64         if ((ret = i2c->xfer (i2c, &msg, 1)) != 1)
65                 dprintk ("%s: write_reg error (reg == %02x) = %02x!\n",
66                          __FUNCTION__, reg, ret);
67
68         return (ret != 1) ? -1 : 0;
69 }
70
71
72 static u8 l64781_readreg (struct dvb_i2c_bus *i2c, u8 reg)
73 {
74         int ret;
75         u8 b0 [] = { reg };
76         u8 b1 [] = { 0 };
77         struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 },
78                            { .addr = 0x55, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
79
80         ret = i2c->xfer (i2c, msg, 2);
81
82         if (ret != 2)
83                 dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
84
85         return b1[0];
86 }
87
88
89 static int tsa5060_write (struct dvb_i2c_bus *i2c, u8 data [4])
90 {
91         int ret;
92         struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = 4 };
93
94         if ((ret = i2c->xfer (i2c, &msg, 1)) != 1)
95                 dprintk ("%s: write_reg error == %02x!\n", __FUNCTION__, ret);
96
97         return (ret != 1) ? -1 : 0;
98 }
99
100
101 /**
102  *   set up the downconverter frequency divisor for a
103  *   reference clock comparision frequency of 166666 Hz.
104  *   frequency offset is 36125000 Hz.
105  */
106 static int tsa5060_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq)
107 {
108 #if 1
109         u32 div;
110         u8 buf [4];
111         u8 cfg, cpump, band_select;
112
113         div = (36125000 + freq) / 166666;
114         cfg = 0x88;
115
116         cpump = freq < 175000000 ? 2 : freq < 390000000 ? 1 :
117                 freq < 470000000 ? 2 : freq < 750000000 ? 1 : 3;
118
119         band_select = freq < 175000000 ? 0x0e : freq < 470000000 ? 0x05 : 0x03;
120
121         buf [0] = (div >> 8) & 0x7f;
122         buf [1] = div & 0xff;
123         buf [2] = ((div >> 10) & 0x60) | cfg;
124         buf [3] = (cpump << 6) | band_select;
125 #else
126         /* old code which seems to work better for at least one person */
127         u32 div;
128         u8 buf [4];
129         u8 cfg;
130
131         div = (36000000 + freq) / 166666;
132         cfg = 0x88;
133
134         buf [0] = (div >> 8) & 0x7f;
135         buf [1] = div & 0xff;
136         buf [2] = ((div >> 10) & 0x60) | cfg;
137         buf [3] = 0xc0;
138 #endif
139
140         return tsa5060_write (i2c, buf);
141 }
142
143
144 static void apply_tps (struct dvb_i2c_bus *i2c)
145 {
146         l64781_writereg (i2c, 0x2a, 0x00);
147         l64781_writereg (i2c, 0x2a, 0x01);
148
149         /* This here is a little bit questionable because it enables
150            the automatic update of TPS registers. I think we'd need to
151            handle the IRQ from FE to update some other registers as
152            well, or at least implement some magic to tuning to correct
153            to the TPS received from transmission. */
154         l64781_writereg (i2c, 0x2a, 0x02);
155 }
156
157
158 static void reset_afc (struct dvb_i2c_bus *i2c)
159 {
160         /* Set AFC stall for the AFC_INIT_FRQ setting, TIM_STALL for
161            timing offset */
162         l64781_writereg (i2c, 0x07, 0x9e); /* stall AFC */
163         l64781_writereg (i2c, 0x08, 0);    /* AFC INIT FREQ */
164         l64781_writereg (i2c, 0x09, 0);
165         l64781_writereg (i2c, 0x0a, 0);
166         l64781_writereg (i2c, 0x07, 0x8e);
167         l64781_writereg (i2c, 0x0e, 0);    /* AGC gain to zero in beginning */
168         l64781_writereg (i2c, 0x11, 0x80); /* stall TIM */
169         l64781_writereg (i2c, 0x10, 0);    /* TIM_OFFSET_LSB */
170         l64781_writereg (i2c, 0x12, 0);
171         l64781_writereg (i2c, 0x13, 0);
172         l64781_writereg (i2c, 0x11, 0x00);
173 }
174
175
176 static int apply_frontend_param (struct dvb_i2c_bus *i2c,
177                           struct dvb_frontend_parameters *param)
178 {
179         /* The coderates for FEC_NONE, FEC_4_5 and FEC_FEC_6_7 are arbitrary */
180         static const u8 fec_tab[] = { 7, 0, 1, 2, 9, 3, 10, 4 };
181         /* QPSK, QAM_16, QAM_64 */
182         static const u8 qam_tab [] = { 2, 4, 0, 6 };
183         static const u8 bw_tab [] = { 8, 7, 6 };  /* 8Mhz, 7MHz, 6MHz */
184         static const u8 guard_tab [] = { 1, 2, 4, 8 };
185         /* The Grundig 29504-401.04 Tuner comes with 18.432MHz crystal. */
186         static const u32 ppm = 8000;
187         struct dvb_ofdm_parameters *p = &param->u.ofdm;
188         u32 ddfs_offset_fixed;
189 /*      u32 ddfs_offset_variable = 0x6000-((1000000UL+ppm)/ */
190 /*                      bw_tab[p->bandWidth]<<10)/15625; */
191         u32 init_freq;
192         u32 spi_bias;
193         u8 val0x04;
194         u8 val0x05;
195         u8 val0x06;
196         int bw = p->bandwidth - BANDWIDTH_8_MHZ;
197
198         if (param->inversion != INVERSION_ON &&
199             param->inversion != INVERSION_OFF)
200                 return -EINVAL;
201
202         if (bw < 0 || bw > 2)
203                 return -EINVAL;
204         
205         if (p->code_rate_HP != FEC_1_2 && p->code_rate_HP != FEC_2_3 &&
206             p->code_rate_HP != FEC_3_4 && p->code_rate_HP != FEC_5_6 &&
207             p->code_rate_HP != FEC_7_8)
208                 return -EINVAL;
209
210         if (p->hierarchy_information != HIERARCHY_NONE &&
211             (p->code_rate_LP != FEC_1_2 && p->code_rate_LP != FEC_2_3 &&
212              p->code_rate_LP != FEC_3_4 && p->code_rate_LP != FEC_5_6 &&
213              p->code_rate_LP != FEC_7_8))
214                 return -EINVAL;
215
216         if (p->constellation != QPSK && p->constellation != QAM_16 &&
217             p->constellation != QAM_64)
218                 return -EINVAL;
219
220         if (p->transmission_mode != TRANSMISSION_MODE_2K &&
221             p->transmission_mode != TRANSMISSION_MODE_8K)
222                 return -EINVAL;
223
224         if (p->guard_interval < GUARD_INTERVAL_1_32 ||
225             p->guard_interval > GUARD_INTERVAL_1_4)
226                 return -EINVAL;
227
228         if (p->hierarchy_information < HIERARCHY_NONE ||
229             p->hierarchy_information > HIERARCHY_4)
230                 return -EINVAL;
231
232         ddfs_offset_fixed = 0x4000-(ppm<<16)/bw_tab[p->bandwidth]/1000000;
233
234         /* This works up to 20000 ppm, it overflows if too large ppm! */
235         init_freq = (((8UL<<25) + (8UL<<19) / 25*ppm / (15625/25)) /
236                         bw_tab[p->bandwidth] & 0xFFFFFF);
237
238         /* SPI bias calculation is slightly modified to fit in 32bit */
239         /* will work for high ppm only... */
240         spi_bias = 378 * (1 << 10);
241         spi_bias *= 16;
242         spi_bias *= bw_tab[p->bandwidth];
243         spi_bias *= qam_tab[p->constellation];
244         spi_bias /= p->code_rate_HP + 1;
245         spi_bias /= (guard_tab[p->guard_interval] + 32);
246         spi_bias *= 1000ULL;
247         spi_bias /= 1000ULL + ppm/1000;
248         spi_bias *= p->code_rate_HP;
249
250         val0x04 = (p->transmission_mode << 2) | p->guard_interval;
251         val0x05 = fec_tab[p->code_rate_HP];
252
253         if (p->hierarchy_information != HIERARCHY_NONE)
254                 val0x05 |= (p->code_rate_LP - FEC_1_2) << 3;
255
256         val0x06 = (p->hierarchy_information << 2) | p->constellation;
257
258         l64781_writereg (i2c, 0x04, val0x04);
259         l64781_writereg (i2c, 0x05, val0x05);
260         l64781_writereg (i2c, 0x06, val0x06);
261
262         reset_afc (i2c);
263
264         /* Technical manual section 2.6.1, TIM_IIR_GAIN optimal values */
265         l64781_writereg (i2c, 0x15,
266                          p->transmission_mode == TRANSMISSION_MODE_2K ? 1 : 3);
267         l64781_writereg (i2c, 0x16, init_freq & 0xff);
268         l64781_writereg (i2c, 0x17, (init_freq >> 8) & 0xff);
269         l64781_writereg (i2c, 0x18, (init_freq >> 16) & 0xff);
270
271         l64781_writereg (i2c, 0x1b, spi_bias & 0xff);
272         l64781_writereg (i2c, 0x1c, (spi_bias >> 8) & 0xff);
273         l64781_writereg (i2c, 0x1d, ((spi_bias >> 16) & 0x7f) |
274                 (param->inversion == INVERSION_ON ? 0x80 : 0x00));
275
276         l64781_writereg (i2c, 0x22, ddfs_offset_fixed & 0xff);
277         l64781_writereg (i2c, 0x23, (ddfs_offset_fixed >> 8) & 0x3f);
278
279         l64781_readreg (i2c, 0x00);  /*  clear interrupt registers... */
280         l64781_readreg (i2c, 0x01);  /*  dto. */
281
282         apply_tps (i2c);
283
284         return 0;
285 }
286
287
288 static int reset_and_configure (struct dvb_i2c_bus *i2c)
289 {
290         u8 buf [] = { 0x06 };
291         struct i2c_msg msg = { .addr = 0x00, .flags = 0, .buf = buf, .len = 1 };
292
293         return (i2c->xfer (i2c, &msg, 1) == 1) ? 0 : -ENODEV;
294 }
295
296
297 static int get_frontend(struct dvb_i2c_bus* i2c, struct dvb_frontend_parameters* param)
298 {
299         int tmp;
300
301
302         tmp = l64781_readreg(i2c, 0x04);
303         switch(tmp & 3) {
304         case 0: 
305                 param->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; 
306                 break;
307         case 1:
308                 param->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
309                 break;
310         case 2:
311                 param->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; 
312                 break;
313         case 3:
314                 param->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; 
315                 break;
316         }
317         switch((tmp >> 2) & 3) {
318         case 0: 
319                 param->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
320                 break;
321         case 1:
322                 param->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
323                 break;
324         default:
325                 printk("Unexpected value for transmission_mode\n");
326         }
327         
328         
329         
330         tmp = l64781_readreg(i2c, 0x05);
331         switch(tmp & 7) {
332         case 0: 
333                 param->u.ofdm.code_rate_HP = FEC_1_2;
334                 break;
335         case 1:
336                 param->u.ofdm.code_rate_HP = FEC_2_3;
337                 break;
338         case 2:
339                 param->u.ofdm.code_rate_HP = FEC_3_4;
340                 break;
341         case 3:
342                 param->u.ofdm.code_rate_HP = FEC_5_6;
343                 break;
344         case 4:
345                 param->u.ofdm.code_rate_HP = FEC_7_8;
346                 break;
347         default:
348                 printk("Unexpected value for code_rate_HP\n");
349         }
350         switch((tmp >> 3) & 7) {
351         case 0: 
352                 param->u.ofdm.code_rate_LP = FEC_1_2;
353                 break;
354         case 1:
355                 param->u.ofdm.code_rate_LP = FEC_2_3;
356                 break;
357         case 2:
358                 param->u.ofdm.code_rate_LP = FEC_3_4;
359                 break;
360         case 3:
361                 param->u.ofdm.code_rate_LP = FEC_5_6;
362                 break;
363         case 4:
364                 param->u.ofdm.code_rate_LP = FEC_7_8;
365                 break;
366         default:
367                 printk("Unexpected value for code_rate_LP\n");
368         }
369         
370         
371         tmp = l64781_readreg(i2c, 0x06);
372         switch(tmp & 3) {
373         case 0: 
374                 param->u.ofdm.constellation = QPSK;
375                 break;
376         case 1:
377                 param->u.ofdm.constellation = QAM_16;
378                 break;
379         case 2:
380                 param->u.ofdm.constellation = QAM_64;
381                 break;
382         default:
383                 printk("Unexpected value for constellation\n");
384         }
385         switch((tmp >> 2) & 7) {
386         case 0: 
387                 param->u.ofdm.hierarchy_information = HIERARCHY_NONE;
388                 break;
389         case 1:
390                 param->u.ofdm.hierarchy_information = HIERARCHY_1;
391                 break;
392         case 2:
393                 param->u.ofdm.hierarchy_information = HIERARCHY_2;
394                 break;
395         case 3:
396                 param->u.ofdm.hierarchy_information = HIERARCHY_4;
397                 break;
398         default:
399                 printk("Unexpected value for hierarchy\n");
400         }
401
402
403         tmp = l64781_readreg (i2c, 0x1d);
404         param->inversion = (tmp & 0x80) ? INVERSION_ON : INVERSION_OFF;
405
406         tmp = (int) (l64781_readreg (i2c, 0x08) | 
407                      (l64781_readreg (i2c, 0x09) << 8) |
408                      (l64781_readreg (i2c, 0x0a) << 16));
409         param->frequency += tmp;
410
411         return 0;
412 }
413
414
415 static int init (struct dvb_i2c_bus *i2c)
416 {
417         reset_and_configure (i2c);
418
419         /* Power up */
420         l64781_writereg (i2c, 0x3e, 0xa5);
421
422         /* Reset hard */
423         l64781_writereg (i2c, 0x2a, 0x04);
424         l64781_writereg (i2c, 0x2a, 0x00);
425
426         /* Set tuner specific things */
427         /* AFC_POL, set also in reset_afc */
428         l64781_writereg (i2c, 0x07, 0x8e);
429
430         /* Use internal ADC */
431         l64781_writereg (i2c, 0x0b, 0x81);
432
433         /* AGC loop gain, and polarity is positive */
434         l64781_writereg (i2c, 0x0c, 0x84);
435
436         /* Internal ADC outputs two's complement */
437         l64781_writereg (i2c, 0x0d, 0x8c);
438
439         /* With ppm=8000, it seems the DTR_SENSITIVITY will result in
440            value of 2 with all possible bandwidths and guard
441            intervals, which is the initial value anyway. */
442         /*l64781_writereg (i2c, 0x19, 0x92);*/
443
444         /* Everything is two's complement, soft bit and CSI_OUT too */
445         l64781_writereg (i2c, 0x1e, 0x09);
446
447         return 0;
448 }
449
450
451 static 
452 int grundig_29504_401_ioctl (struct dvb_frontend *fe,
453                              unsigned int cmd, void *arg)
454 {
455         struct dvb_i2c_bus *i2c = fe->i2c;
456         int res;
457         struct grundig_state* state = (struct grundig_state*) fe->data;
458
459         switch (cmd) {
460         case FE_GET_INFO:
461                 memcpy (arg, &grundig_29504_401_info,
462                         sizeof(struct dvb_frontend_info));
463                 break;
464
465         case FE_READ_STATUS:
466         {
467                 fe_status_t *status = (fe_status_t *) arg;
468                 int sync = l64781_readreg (i2c, 0x32);
469                 int gain = l64781_readreg (i2c, 0x0e);
470
471                 l64781_readreg (i2c, 0x00);  /*  clear interrupt registers... */
472                 l64781_readreg (i2c, 0x01);  /*  dto. */
473
474                 *status = 0;
475
476                 if (gain > 5)
477                         *status |= FE_HAS_SIGNAL;
478
479                 if (sync & 0x02) /* VCXO locked, this criteria should be ok */
480                         *status |= FE_HAS_CARRIER;
481
482                 if (sync & 0x20)
483                         *status |= FE_HAS_VITERBI;
484
485                 if (sync & 0x40)
486                         *status |= FE_HAS_SYNC;
487
488                 if (sync == 0x7f)
489                         *status |= FE_HAS_LOCK;
490
491                 break;
492         }
493
494         case FE_READ_BER:
495         {
496                 /*   XXX FIXME: set up counting period (reg 0x26...0x28)
497                  */
498                 u32 *ber = (u32 *) arg;
499                 *ber = l64781_readreg (i2c, 0x39)
500                     | (l64781_readreg (i2c, 0x3a) << 8);
501                 break;
502         }
503
504         case FE_READ_SIGNAL_STRENGTH:
505         {
506                 u8 gain = l64781_readreg (i2c, 0x0e);
507                 *(u16 *) arg = (gain << 8) | gain;
508                 break;
509         }
510
511         case FE_READ_SNR:
512         {
513                 u16 *snr = (u16 *) arg;
514                 u8 avg_quality = 0xff - l64781_readreg (i2c, 0x33);
515                 *snr = (avg_quality << 8) | avg_quality; /* not exact, but...*/ 
516                 break;
517         }
518
519         case FE_READ_UNCORRECTED_BLOCKS: 
520         {
521                 u32 *ub = (u32 *) arg;
522                 *ub = l64781_readreg (i2c, 0x37)
523                    | (l64781_readreg (i2c, 0x38) << 8);
524                 break;
525         }
526
527         case FE_SET_FRONTEND:
528         {
529                 struct dvb_frontend_parameters *p = arg;
530
531                 tsa5060_set_tv_freq (i2c, p->frequency);
532                 return apply_frontend_param (i2c, p);
533         }
534
535         case FE_GET_FRONTEND:
536         {
537                 struct dvb_frontend_parameters *p = arg;
538                 return get_frontend(i2c, p);
539         }
540
541         case FE_SLEEP:
542                 /* Power down */
543                 return l64781_writereg (i2c, 0x3e, 0x5a);
544
545         case FE_INIT:
546                 res = init (i2c);
547                 if ((res == 0) && (state->first)) {
548                         state->first = 0;
549                         dvb_delay(200);
550                 }
551                 return res;
552
553         case FE_GET_TUNE_SETTINGS:
554         {
555                 struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
556                 fesettings->min_delay_ms = 200;
557                 fesettings->step_size = 166667;
558                 fesettings->max_drift = 166667*2;
559                 return 0;
560         }
561
562         default:
563                 dprintk ("%s: unknown command !!!\n", __FUNCTION__);
564                 return -EINVAL;
565         };
566         
567         return 0;
568
569
570
571 static int l64781_attach (struct dvb_i2c_bus *i2c, void **data)
572 {
573         u8 reg0x3e;
574         u8 b0 [] = { 0x1a };
575         u8 b1 [] = { 0x00 };
576         struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 },
577                            { .addr = 0x55, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
578         struct grundig_state* state;
579
580         /**
581          *  the L64781 won't show up before we send the reset_and_configure()
582          *  broadcast. If nothing responds there is no L64781 on the bus...
583          */
584         if (reset_and_configure(i2c) < 0) {
585                 dprintk("no response on reset_and_configure() broadcast, bailing out...\n");
586                 return -ENODEV;
587         }
588
589         /* The chip always responds to reads */
590         if (i2c->xfer(i2c, msg, 2) != 2) {  
591                 dprintk("no response to read on I2C bus\n");
592                 return -ENODEV;
593         }
594
595         /* Save current register contents for bailout */
596         reg0x3e = l64781_readreg(i2c, 0x3e);
597
598         /* Reading the POWER_DOWN register always returns 0 */
599         if (reg0x3e != 0) {
600                 dprintk("Device doesn't look like L64781\n");
601                 return -ENODEV;
602         }
603
604         /* Turn the chip off */
605         l64781_writereg (i2c, 0x3e, 0x5a);
606
607         /* Responds to all reads with 0 */
608         if (l64781_readreg(i2c, 0x1a) != 0) {
609                 dprintk("Read 1 returned unexpcted value\n");
610                 goto bailout;
611         }         
612
613         /* Turn the chip on */
614         l64781_writereg (i2c, 0x3e, 0xa5);
615         
616         /* Responds with register default value */
617         if (l64781_readreg(i2c, 0x1a) != 0xa1) { 
618                 dprintk("Read 2 returned unexpcted value\n");
619                 goto bailout;
620         }
621
622         state = kmalloc(sizeof(struct grundig_state), GFP_KERNEL);
623         if (state == NULL) goto bailout;
624         *data = state;
625         state->first = 1;
626
627         return dvb_register_frontend (grundig_29504_401_ioctl, i2c, state,
628                                &grundig_29504_401_info);
629
630  bailout:
631         l64781_writereg (i2c, 0x3e, reg0x3e);  /* restore reg 0x3e */
632         return -ENODEV;
633 }
634
635
636
637 static void l64781_detach (struct dvb_i2c_bus *i2c, void *data)
638 {
639         kfree(data);
640         dvb_unregister_frontend (grundig_29504_401_ioctl, i2c);
641 }
642
643
644 static int __init init_grundig_29504_401 (void)
645 {
646         return dvb_register_i2c_device (THIS_MODULE,
647                                         l64781_attach, l64781_detach);
648 }
649
650
651 static void __exit exit_grundig_29504_401 (void)
652 {
653         dvb_unregister_i2c_device (l64781_attach);
654 }
655
656 module_init(init_grundig_29504_401);
657 module_exit(exit_grundig_29504_401);
658
659 MODULE_PARM(debug,"i");
660 MODULE_PARM_DESC(debug, "enable verbose debug messages");
661 MODULE_DESCRIPTION("Grundig 29504-401 DVB-T Frontend");
662 MODULE_AUTHOR("Holger Waechtler, Marko Kohtala");
663 MODULE_LICENSE("GPL");
664