GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / media / usb / au0828 / au0828-core.c
1 /*
2  *  Driver for the Auvitek USB bridge
3  *
4  *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *
15  *  GNU General Public License for more details.
16  */
17
18 #include "au0828.h"
19 #include "au8522.h"
20
21 #include <linux/module.h>
22 #include <linux/slab.h>
23 #include <linux/videodev2.h>
24 #include <media/v4l2-common.h>
25 #include <linux/mutex.h>
26
27 /* Due to enum tuner_pad_index */
28 #include <media/tuner.h>
29
30 /*
31  * 1 = General debug messages
32  * 2 = USB handling
33  * 4 = I2C related
34  * 8 = Bridge related
35  * 16 = IR related
36  */
37 int au0828_debug;
38 module_param_named(debug, au0828_debug, int, 0644);
39 MODULE_PARM_DESC(debug,
40                  "set debug bitmask: 1=general, 2=USB, 4=I2C, 8=bridge, 16=IR");
41
42 static unsigned int disable_usb_speed_check;
43 module_param(disable_usb_speed_check, int, 0444);
44 MODULE_PARM_DESC(disable_usb_speed_check,
45                  "override min bandwidth requirement of 480M bps");
46
47 #define _AU0828_BULKPIPE 0x03
48 #define _BULKPIPESIZE 0xffff
49
50 static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
51                             u16 index);
52 static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
53         u16 index, unsigned char *cp, u16 size);
54
55 /* USB Direction */
56 #define CMD_REQUEST_IN          0x00
57 #define CMD_REQUEST_OUT         0x01
58
59 u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
60 {
61         u8 result = 0;
62
63         recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, &result, 1);
64         dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, result);
65
66         return result;
67 }
68
69 u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
70 {
71         dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val);
72         return send_control_msg(dev, CMD_REQUEST_OUT, val, reg);
73 }
74
75 static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
76         u16 index)
77 {
78         int status = -ENODEV;
79
80         if (dev->usbdev) {
81
82                 /* cp must be memory that has been allocated by kmalloc */
83                 status = usb_control_msg(dev->usbdev,
84                                 usb_sndctrlpipe(dev->usbdev, 0),
85                                 request,
86                                 USB_DIR_OUT | USB_TYPE_VENDOR |
87                                         USB_RECIP_DEVICE,
88                                 value, index, NULL, 0, 1000);
89
90                 status = min(status, 0);
91
92                 if (status < 0) {
93                         pr_err("%s() Failed sending control message, error %d.\n",
94                                 __func__, status);
95                 }
96
97         }
98
99         return status;
100 }
101
102 static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
103         u16 index, unsigned char *cp, u16 size)
104 {
105         int status = -ENODEV;
106         mutex_lock(&dev->mutex);
107         if (dev->usbdev) {
108                 status = usb_control_msg(dev->usbdev,
109                                 usb_rcvctrlpipe(dev->usbdev, 0),
110                                 request,
111                                 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
112                                 value, index,
113                                 dev->ctrlmsg, size, 1000);
114
115                 status = min(status, 0);
116
117                 if (status < 0) {
118                         pr_err("%s() Failed receiving control message, error %d.\n",
119                                 __func__, status);
120                 }
121
122                 /* the host controller requires heap allocated memory, which
123                    is why we didn't just pass "cp" into usb_control_msg */
124                 memcpy(cp, dev->ctrlmsg, size);
125         }
126         mutex_unlock(&dev->mutex);
127         return status;
128 }
129
130 #ifdef CONFIG_MEDIA_CONTROLLER
131 static void au0828_media_graph_notify(struct media_entity *new,
132                                       void *notify_data);
133 #endif
134
135 static void au0828_unregister_media_device(struct au0828_dev *dev)
136 {
137 #ifdef CONFIG_MEDIA_CONTROLLER
138         struct media_device *mdev = dev->media_dev;
139         struct media_entity_notify *notify, *nextp;
140
141         if (!mdev || !media_devnode_is_registered(mdev->devnode))
142                 return;
143
144         /* Remove au0828 entity_notify callbacks */
145         list_for_each_entry_safe(notify, nextp, &mdev->entity_notify, list) {
146                 if (notify->notify != au0828_media_graph_notify)
147                         continue;
148                 media_device_unregister_entity_notify(mdev, notify);
149         }
150
151         /* clear enable_source, disable_source */
152         mutex_lock(&mdev->graph_mutex);
153         dev->media_dev->source_priv = NULL;
154         dev->media_dev->enable_source = NULL;
155         dev->media_dev->disable_source = NULL;
156         mutex_unlock(&mdev->graph_mutex);
157
158         media_device_unregister(dev->media_dev);
159         media_device_cleanup(dev->media_dev);
160         kfree(dev->media_dev);
161         dev->media_dev = NULL;
162 #endif
163 }
164
165 void au0828_usb_release(struct au0828_dev *dev)
166 {
167         au0828_unregister_media_device(dev);
168
169         /* I2C */
170         au0828_i2c_unregister(dev);
171
172         kfree(dev);
173 }
174
175 static void au0828_usb_disconnect(struct usb_interface *interface)
176 {
177         struct au0828_dev *dev = usb_get_intfdata(interface);
178
179         dprintk(1, "%s()\n", __func__);
180
181         /* there is a small window after disconnect, before
182            dev->usbdev is NULL, for poll (e.g: IR) try to access
183            the device and fill the dmesg with error messages.
184            Set the status so poll routines can check and avoid
185            access after disconnect.
186         */
187         set_bit(DEV_DISCONNECTED, &dev->dev_state);
188
189         au0828_rc_unregister(dev);
190         /* Digital TV */
191         au0828_dvb_unregister(dev);
192
193         usb_set_intfdata(interface, NULL);
194         mutex_lock(&dev->mutex);
195         dev->usbdev = NULL;
196         mutex_unlock(&dev->mutex);
197         if (au0828_analog_unregister(dev)) {
198                 /*
199                  * No need to call au0828_usb_release() if V4L2 is enabled,
200                  * as this is already called via au0828_usb_v4l2_release()
201                  */
202                 return;
203         }
204         au0828_usb_release(dev);
205 }
206
207 static int au0828_media_device_init(struct au0828_dev *dev,
208                                     struct usb_device *udev)
209 {
210 #ifdef CONFIG_MEDIA_CONTROLLER
211         struct media_device *mdev;
212
213         mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
214         if (!mdev)
215                 return -ENOMEM;
216
217         /* check if media device is already initialized */
218         if (!mdev->dev)
219                 media_device_usb_init(mdev, udev, udev->product);
220
221         dev->media_dev = mdev;
222 #endif
223         return 0;
224 }
225
226 #ifdef CONFIG_MEDIA_CONTROLLER
227 static void au0828_media_graph_notify(struct media_entity *new,
228                                       void *notify_data)
229 {
230         struct au0828_dev *dev = (struct au0828_dev *) notify_data;
231         int ret;
232         struct media_entity *entity, *mixer = NULL, *decoder = NULL;
233
234         if (!new) {
235                 /*
236                  * Called during au0828 probe time to connect
237                  * entites that were created prior to registering
238                  * the notify handler. Find mixer and decoder.
239                 */
240                 media_device_for_each_entity(entity, dev->media_dev) {
241                         if (entity->function == MEDIA_ENT_F_AUDIO_MIXER)
242                                 mixer = entity;
243                         else if (entity->function == MEDIA_ENT_F_ATV_DECODER)
244                                 decoder = entity;
245                 }
246                 goto create_link;
247         }
248
249         switch (new->function) {
250         case MEDIA_ENT_F_AUDIO_MIXER:
251                 mixer = new;
252                 if (dev->decoder)
253                         decoder = dev->decoder;
254                 break;
255         case MEDIA_ENT_F_ATV_DECODER:
256                 /* In case, Mixer is added first, find mixer and create link */
257                 media_device_for_each_entity(entity, dev->media_dev) {
258                         if (entity->function == MEDIA_ENT_F_AUDIO_MIXER)
259                                 mixer = entity;
260                 }
261                 decoder = new;
262                 break;
263         default:
264                 break;
265         }
266
267 create_link:
268         if (decoder && mixer) {
269                 ret = media_create_pad_link(decoder,
270                                             DEMOD_PAD_AUDIO_OUT,
271                                             mixer, 0,
272                                             MEDIA_LNK_FL_ENABLED);
273                 if (ret)
274                         dev_err(&dev->usbdev->dev,
275                                 "Mixer Pad Link Create Error: %d\n", ret);
276         }
277 }
278
279 /* Callers should hold graph_mutex */
280 static int au0828_enable_source(struct media_entity *entity,
281                                 struct media_pipeline *pipe)
282 {
283         struct media_entity  *source, *find_source;
284         struct media_entity *sink;
285         struct media_link *link, *found_link = NULL;
286         int ret = 0;
287         struct media_device *mdev = entity->graph_obj.mdev;
288         struct au0828_dev *dev;
289
290         if (!mdev)
291                 return -ENODEV;
292
293         dev = mdev->source_priv;
294
295         /*
296          * For Audio and V4L2 entity, find the link to which decoder
297          * is the sink. Look for an active link between decoder and
298          * source (tuner/s-video/Composite), if one exists, nothing
299          * to do. If not, look for any  active links between source
300          * and any other entity. If one exists, source is busy. If
301          * source is free, setup link and start pipeline from source.
302          * For DVB FE entity, the source for the link is the tuner.
303          * Check if tuner is available and setup link and start
304          * pipeline.
305         */
306         if (entity->function == MEDIA_ENT_F_DTV_DEMOD) {
307                 sink = entity;
308                 find_source = dev->tuner;
309         } else {
310                 /* Analog isn't configured or register failed */
311                 if (!dev->decoder) {
312                         ret = -ENODEV;
313                         goto end;
314                 }
315
316                 sink = dev->decoder;
317
318                 /*
319                  * Default input is tuner and default input_type
320                  * is AU0828_VMUX_TELEVISION.
321                  * FIXME:
322                  * There is a problem when s_input is called to
323                  * change the default input. s_input will try to
324                  * enable_source before attempting to change the
325                  * input on the device, and will end up enabling
326                  * default source which is tuner.
327                  *
328                  * Additional logic is necessary in au0828
329                  * to detect that the input has changed and
330                  * enable the right source.
331                 */
332
333                 if (dev->input_type == AU0828_VMUX_TELEVISION)
334                         find_source = dev->tuner;
335                 else if (dev->input_type == AU0828_VMUX_SVIDEO ||
336                          dev->input_type == AU0828_VMUX_COMPOSITE)
337                         find_source = &dev->input_ent[dev->input_type];
338                 else {
339                         /* unknown input - let user select input */
340                         ret = 0;
341                         goto end;
342                 }
343         }
344
345         /* Is an active link between sink and source */
346         if (dev->active_link) {
347                 /*
348                  * If DVB is using the tuner and calling entity is
349                  * audio/video, the following check will be false,
350                  * since sink is different. Result is Busy.
351                  */
352                 if (dev->active_link->sink->entity == sink &&
353                     dev->active_link->source->entity == find_source) {
354                         /*
355                          * Either ALSA or Video own tuner. sink is
356                          * the same for both. Prevent Video stepping
357                          * on ALSA when ALSA owns the source.
358                         */
359                         if (dev->active_link_owner != entity &&
360                             dev->active_link_owner->function ==
361                                                 MEDIA_ENT_F_AUDIO_CAPTURE) {
362                                 pr_debug("ALSA has the tuner\n");
363                                 ret = -EBUSY;
364                                 goto end;
365                         }
366                         ret = 0;
367                         goto end;
368                 } else {
369                         ret = -EBUSY;
370                         goto end;
371                 }
372         }
373
374         list_for_each_entry(link, &sink->links, list) {
375                 /* Check sink, and source */
376                 if (link->sink->entity == sink &&
377                     link->source->entity == find_source) {
378                         found_link = link;
379                         break;
380                 }
381         }
382
383         if (!found_link) {
384                 ret = -ENODEV;
385                 goto end;
386         }
387
388         /* activate link between source and sink and start pipeline */
389         source = found_link->source->entity;
390         ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);
391         if (ret) {
392                 pr_err("Activate tuner link %s->%s. Error %d\n",
393                         source->name, sink->name, ret);
394                 goto end;
395         }
396
397         ret = __media_pipeline_start(entity, pipe);
398         if (ret) {
399                 pr_err("Start Pipeline: %s->%s Error %d\n",
400                         source->name, entity->name, ret);
401                 ret = __media_entity_setup_link(found_link, 0);
402                 pr_err("Deactivate link Error %d\n", ret);
403                 goto end;
404         }
405         /*
406          * save active link and active link owner to avoid audio
407          * deactivating video owned link from disable_source and
408          * vice versa
409         */
410         dev->active_link = found_link;
411         dev->active_link_owner = entity;
412         dev->active_source = source;
413         dev->active_sink = sink;
414
415         pr_debug("Enabled Source: %s->%s->%s Ret %d\n",
416                  dev->active_source->name, dev->active_sink->name,
417                  dev->active_link_owner->name, ret);
418 end:
419         pr_debug("au0828_enable_source() end %s %d %d\n",
420                  entity->name, entity->function, ret);
421         return ret;
422 }
423
424 /* Callers should hold graph_mutex */
425 static void au0828_disable_source(struct media_entity *entity)
426 {
427         int ret = 0;
428         struct media_device *mdev = entity->graph_obj.mdev;
429         struct au0828_dev *dev;
430
431         if (!mdev)
432                 return;
433
434         dev = mdev->source_priv;
435
436         if (!dev->active_link)
437                 return;
438
439         /* link is active - stop pipeline from source (tuner) */
440         if (dev->active_link->sink->entity == dev->active_sink &&
441             dev->active_link->source->entity == dev->active_source) {
442                 /*
443                  * prevent video from deactivating link when audio
444                  * has active pipeline
445                 */
446                 if (dev->active_link_owner != entity)
447                         return;
448                 __media_pipeline_stop(entity);
449                 ret = __media_entity_setup_link(dev->active_link, 0);
450                 if (ret)
451                         pr_err("Deactivate link Error %d\n", ret);
452
453                 pr_debug("Disabled Source: %s->%s->%s Ret %d\n",
454                          dev->active_source->name, dev->active_sink->name,
455                          dev->active_link_owner->name, ret);
456
457                 dev->active_link = NULL;
458                 dev->active_link_owner = NULL;
459                 dev->active_source = NULL;
460                 dev->active_sink = NULL;
461         }
462 }
463 #endif
464
465 static int au0828_media_device_register(struct au0828_dev *dev,
466                                         struct usb_device *udev)
467 {
468 #ifdef CONFIG_MEDIA_CONTROLLER
469         int ret;
470         struct media_entity *entity, *demod = NULL;
471         struct media_link *link;
472
473         if (!dev->media_dev)
474                 return 0;
475
476         if (!media_devnode_is_registered(dev->media_dev->devnode)) {
477
478                 /* register media device */
479                 ret = media_device_register(dev->media_dev);
480                 if (ret) {
481                         dev_err(&udev->dev,
482                                 "Media Device Register Error: %d\n", ret);
483                         return ret;
484                 }
485         } else {
486                 /*
487                  * Call au0828_media_graph_notify() to connect
488                  * audio graph to our graph. In this case, audio
489                  * driver registered the device and there is no
490                  * entity_notify to be called when new entities
491                  * are added. Invoke it now.
492                 */
493                 au0828_media_graph_notify(NULL, (void *) dev);
494         }
495
496         /*
497          * Find tuner, decoder and demod.
498          *
499          * The tuner and decoder should be cached, as they'll be used by
500          *      au0828_enable_source.
501          *
502          * It also needs to disable the link between tuner and
503          * decoder/demod, to avoid disable step when tuner is requested
504          * by video or audio. Note that this step can't be done until dvb
505          * graph is created during dvb register.
506         */
507         media_device_for_each_entity(entity, dev->media_dev) {
508                 switch (entity->function) {
509                 case MEDIA_ENT_F_TUNER:
510                         dev->tuner = entity;
511                         break;
512                 case MEDIA_ENT_F_ATV_DECODER:
513                         dev->decoder = entity;
514                         break;
515                 case MEDIA_ENT_F_DTV_DEMOD:
516                         demod = entity;
517                         break;
518                 }
519         }
520
521         /* Disable link between tuner->demod and/or tuner->decoder */
522         if (dev->tuner) {
523                 list_for_each_entry(link, &dev->tuner->links, list) {
524                         if (demod && link->sink->entity == demod)
525                                 media_entity_setup_link(link, 0);
526                         if (dev->decoder && link->sink->entity == dev->decoder)
527                                 media_entity_setup_link(link, 0);
528                 }
529         }
530
531         /* register entity_notify callback */
532         dev->entity_notify.notify_data = (void *) dev;
533         dev->entity_notify.notify = (void *) au0828_media_graph_notify;
534         ret = media_device_register_entity_notify(dev->media_dev,
535                                                   &dev->entity_notify);
536         if (ret) {
537                 dev_err(&udev->dev,
538                         "Media Device register entity_notify Error: %d\n",
539                         ret);
540                 return ret;
541         }
542         /* set enable_source */
543         mutex_lock(&dev->media_dev->graph_mutex);
544         dev->media_dev->source_priv = (void *) dev;
545         dev->media_dev->enable_source = au0828_enable_source;
546         dev->media_dev->disable_source = au0828_disable_source;
547         mutex_unlock(&dev->media_dev->graph_mutex);
548 #endif
549         return 0;
550 }
551
552 static int au0828_usb_probe(struct usb_interface *interface,
553         const struct usb_device_id *id)
554 {
555         int ifnum;
556         int retval = 0;
557
558         struct au0828_dev *dev;
559         struct usb_device *usbdev = interface_to_usbdev(interface);
560
561         ifnum = interface->altsetting->desc.bInterfaceNumber;
562
563         if (ifnum != 0)
564                 return -ENODEV;
565
566         dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,
567                 le16_to_cpu(usbdev->descriptor.idVendor),
568                 le16_to_cpu(usbdev->descriptor.idProduct),
569                 ifnum);
570
571         /*
572          * Make sure we have 480 Mbps of bandwidth, otherwise things like
573          * video stream wouldn't likely work, since 12 Mbps is generally
574          * not enough even for most Digital TV streams.
575          */
576         if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
577                 pr_err("au0828: Device initialization failed.\n");
578                 pr_err("au0828: Device must be connected to a high-speed USB 2.0 port.\n");
579                 return -ENODEV;
580         }
581
582         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
583         if (dev == NULL) {
584                 pr_err("%s() Unable to allocate memory\n", __func__);
585                 return -ENOMEM;
586         }
587
588         mutex_init(&dev->lock);
589         mutex_lock(&dev->lock);
590         mutex_init(&dev->mutex);
591         mutex_init(&dev->dvb.lock);
592         dev->usbdev = usbdev;
593         dev->boardnr = id->driver_info;
594         dev->board = au0828_boards[dev->boardnr];
595
596         /* Initialize the media controller */
597         retval = au0828_media_device_init(dev, usbdev);
598         if (retval) {
599                 pr_err("%s() au0828_media_device_init failed\n",
600                        __func__);
601                 mutex_unlock(&dev->lock);
602                 kfree(dev);
603                 return retval;
604         }
605
606         retval = au0828_v4l2_device_register(interface, dev);
607         if (retval) {
608                 au0828_usb_v4l2_media_release(dev);
609                 mutex_unlock(&dev->lock);
610                 kfree(dev);
611                 return retval;
612         }
613
614         /* Power Up the bridge */
615         au0828_write(dev, REG_600, 1 << 4);
616
617         /* Bring up the GPIO's and supporting devices */
618         au0828_gpio_setup(dev);
619
620         /* I2C */
621         au0828_i2c_register(dev);
622
623         /* Setup */
624         au0828_card_setup(dev);
625
626         /*
627          * Store the pointer to the au0828_dev so it can be accessed in
628          * au0828_usb_disconnect
629          */
630         usb_set_intfdata(interface, dev);
631
632         /* Analog TV */
633         retval = au0828_analog_register(dev, interface);
634         if (retval) {
635                 pr_err("%s() au0828_analog_register failed to register on V4L2\n",
636                         __func__);
637                 mutex_unlock(&dev->lock);
638                 goto done;
639         }
640
641         /* Digital TV */
642         retval = au0828_dvb_register(dev);
643         if (retval)
644                 pr_err("%s() au0828_dvb_register failed\n",
645                        __func__);
646
647         /* Remote controller */
648         au0828_rc_register(dev);
649
650         pr_info("Registered device AU0828 [%s]\n",
651                 dev->board.name == NULL ? "Unset" : dev->board.name);
652
653         mutex_unlock(&dev->lock);
654
655         retval = au0828_media_device_register(dev, usbdev);
656
657 done:
658         if (retval < 0)
659                 au0828_usb_disconnect(interface);
660
661         return retval;
662 }
663
664 static int au0828_suspend(struct usb_interface *interface,
665                                 pm_message_t message)
666 {
667         struct au0828_dev *dev = usb_get_intfdata(interface);
668
669         if (!dev)
670                 return 0;
671
672         pr_info("Suspend\n");
673
674         au0828_rc_suspend(dev);
675         au0828_v4l2_suspend(dev);
676         au0828_dvb_suspend(dev);
677
678         /* FIXME: should suspend also ATV/DTV */
679
680         return 0;
681 }
682
683 static int au0828_resume(struct usb_interface *interface)
684 {
685         struct au0828_dev *dev = usb_get_intfdata(interface);
686         if (!dev)
687                 return 0;
688
689         pr_info("Resume\n");
690
691         /* Power Up the bridge */
692         au0828_write(dev, REG_600, 1 << 4);
693
694         /* Bring up the GPIO's and supporting devices */
695         au0828_gpio_setup(dev);
696
697         au0828_rc_resume(dev);
698         au0828_v4l2_resume(dev);
699         au0828_dvb_resume(dev);
700
701         /* FIXME: should resume also ATV/DTV */
702
703         return 0;
704 }
705
706 static struct usb_driver au0828_usb_driver = {
707         .name           = KBUILD_MODNAME,
708         .probe          = au0828_usb_probe,
709         .disconnect     = au0828_usb_disconnect,
710         .id_table       = au0828_usb_id_table,
711         .suspend        = au0828_suspend,
712         .resume         = au0828_resume,
713         .reset_resume   = au0828_resume,
714 };
715
716 static int __init au0828_init(void)
717 {
718         int ret;
719
720         if (au0828_debug & 1)
721                 pr_info("%s() Debugging is enabled\n", __func__);
722
723         if (au0828_debug & 2)
724                 pr_info("%s() USB Debugging is enabled\n", __func__);
725
726         if (au0828_debug & 4)
727                 pr_info("%s() I2C Debugging is enabled\n", __func__);
728
729         if (au0828_debug & 8)
730                 pr_info("%s() Bridge Debugging is enabled\n",
731                        __func__);
732
733         if (au0828_debug & 16)
734                 pr_info("%s() IR Debugging is enabled\n",
735                        __func__);
736
737         pr_info("au0828 driver loaded\n");
738
739         ret = usb_register(&au0828_usb_driver);
740         if (ret)
741                 pr_err("usb_register failed, error = %d\n", ret);
742
743         return ret;
744 }
745
746 static void __exit au0828_exit(void)
747 {
748         usb_deregister(&au0828_usb_driver);
749 }
750
751 module_init(au0828_init);
752 module_exit(au0828_exit);
753
754 MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
755 MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
756 MODULE_LICENSE("GPL");
757 MODULE_VERSION("0.0.3");