Commit | Line | Data |
---|---|---|
265a6510 ST |
1 | /* |
2 | * Driver for the Auvitek USB bridge | |
3 | * | |
6d897616 | 4 | * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> |
265a6510 ST |
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 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
20 | */ | |
21 | ||
83afb32a MCC |
22 | #include "au0828.h" |
23 | ||
265a6510 | 24 | #include <linux/module.h> |
5a0e3ad6 | 25 | #include <linux/slab.h> |
265a6510 ST |
26 | #include <linux/videodev2.h> |
27 | #include <media/v4l2-common.h> | |
28 | #include <linux/mutex.h> | |
29 | ||
188d2d55 MCC |
30 | /* Due to enum tuner_pad_index */ |
31 | #include <media/tuner.h> | |
32 | ||
bc3c613c ST |
33 | /* |
34 | * 1 = General debug messages | |
35 | * 2 = USB handling | |
36 | * 4 = I2C related | |
37 | * 8 = Bridge related | |
2fcfd317 | 38 | * 16 = IR related |
bc3c613c | 39 | */ |
b33d24c4 AB |
40 | int au0828_debug; |
41 | module_param_named(debug, au0828_debug, int, 0644); | |
2fcfd317 MCC |
42 | MODULE_PARM_DESC(debug, |
43 | "set debug bitmask: 1=general, 2=USB, 4=I2C, 8=bridge, 16=IR"); | |
265a6510 | 44 | |
d6a9a430 DH |
45 | static unsigned int disable_usb_speed_check; |
46 | module_param(disable_usb_speed_check, int, 0444); | |
47 | MODULE_PARM_DESC(disable_usb_speed_check, | |
48 | "override min bandwidth requirement of 480M bps"); | |
49 | ||
265a6510 ST |
50 | #define _AU0828_BULKPIPE 0x03 |
51 | #define _BULKPIPESIZE 0xffff | |
52 | ||
53 | static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, | |
8ff63de6 | 54 | u16 index); |
265a6510 ST |
55 | static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, |
56 | u16 index, unsigned char *cp, u16 size); | |
57 | ||
58 | /* USB Direction */ | |
59 | #define CMD_REQUEST_IN 0x00 | |
60 | #define CMD_REQUEST_OUT 0x01 | |
61 | ||
62 | u32 au0828_readreg(struct au0828_dev *dev, u16 reg) | |
63 | { | |
77fc2863 DH |
64 | u8 result = 0; |
65 | ||
66 | recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, &result, 1); | |
67 | dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, result); | |
68 | ||
69 | return result; | |
265a6510 ST |
70 | } |
71 | ||
72 | u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val) | |
73 | { | |
b80f770a | 74 | dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val); |
8ff63de6 | 75 | return send_control_msg(dev, CMD_REQUEST_OUT, val, reg); |
265a6510 ST |
76 | } |
77 | ||
265a6510 | 78 | static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, |
8ff63de6 | 79 | u16 index) |
265a6510 ST |
80 | { |
81 | int status = -ENODEV; | |
8ff63de6 | 82 | |
265a6510 ST |
83 | if (dev->usbdev) { |
84 | ||
85 | /* cp must be memory that has been allocated by kmalloc */ | |
86 | status = usb_control_msg(dev->usbdev, | |
87 | usb_sndctrlpipe(dev->usbdev, 0), | |
88 | request, | |
a8eb912c ST |
89 | USB_DIR_OUT | USB_TYPE_VENDOR | |
90 | USB_RECIP_DEVICE, | |
8ff63de6 | 91 | value, index, NULL, 0, 1000); |
265a6510 ST |
92 | |
93 | status = min(status, 0); | |
94 | ||
95 | if (status < 0) { | |
83afb32a | 96 | pr_err("%s() Failed sending control message, error %d.\n", |
f07e8e4b | 97 | __func__, status); |
265a6510 ST |
98 | } |
99 | ||
100 | } | |
8ff63de6 | 101 | |
265a6510 ST |
102 | return status; |
103 | } | |
104 | ||
105 | static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, | |
106 | u16 index, unsigned char *cp, u16 size) | |
107 | { | |
108 | int status = -ENODEV; | |
109 | mutex_lock(&dev->mutex); | |
110 | if (dev->usbdev) { | |
265a6510 ST |
111 | status = usb_control_msg(dev->usbdev, |
112 | usb_rcvctrlpipe(dev->usbdev, 0), | |
113 | request, | |
114 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
115 | value, index, | |
77fc2863 | 116 | dev->ctrlmsg, size, 1000); |
265a6510 ST |
117 | |
118 | status = min(status, 0); | |
119 | ||
120 | if (status < 0) { | |
83afb32a | 121 | pr_err("%s() Failed receiving control message, error %d.\n", |
f07e8e4b | 122 | __func__, status); |
77fc2863 DH |
123 | } |
124 | ||
125 | /* the host controller requires heap allocated memory, which | |
126 | is why we didn't just pass "cp" into usb_control_msg */ | |
127 | memcpy(cp, dev->ctrlmsg, size); | |
265a6510 ST |
128 | } |
129 | mutex_unlock(&dev->mutex); | |
130 | return status; | |
131 | } | |
a9c36aad | 132 | |
bed69196 RLLC |
133 | static void au0828_unregister_media_device(struct au0828_dev *dev) |
134 | { | |
135 | ||
136 | #ifdef CONFIG_MEDIA_CONTROLLER | |
137 | if (dev->media_dev) { | |
138 | media_device_unregister(dev->media_dev); | |
9832e155 | 139 | media_device_cleanup(dev->media_dev); |
bed69196 RLLC |
140 | kfree(dev->media_dev); |
141 | dev->media_dev = NULL; | |
142 | } | |
143 | #endif | |
144 | } | |
145 | ||
823beb7e | 146 | static void au0828_usb_release(struct au0828_dev *dev) |
265a6510 | 147 | { |
bed69196 RLLC |
148 | au0828_unregister_media_device(dev); |
149 | ||
265a6510 ST |
150 | /* I2C */ |
151 | au0828_i2c_unregister(dev); | |
152 | ||
823beb7e HV |
153 | kfree(dev); |
154 | } | |
155 | ||
8a4e7866 | 156 | #ifdef CONFIG_VIDEO_AU0828_V4L2 |
d1f33737 MCC |
157 | |
158 | static void au0828_usb_v4l2_media_release(struct au0828_dev *dev) | |
159 | { | |
160 | #ifdef CONFIG_MEDIA_CONTROLLER | |
161 | int i; | |
162 | ||
163 | for (i = 0; i < AU0828_MAX_INPUT; i++) { | |
164 | if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) | |
165 | return; | |
166 | media_device_unregister_entity(&dev->input_ent[i]); | |
167 | } | |
168 | #endif | |
169 | } | |
170 | ||
823beb7e HV |
171 | static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev) |
172 | { | |
173 | struct au0828_dev *dev = | |
174 | container_of(v4l2_dev, struct au0828_dev, v4l2_dev); | |
175 | ||
e8c26f45 | 176 | v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl); |
b14667f3 | 177 | v4l2_device_unregister(&dev->v4l2_dev); |
4e26f3ab | 178 | au0828_usb_v4l2_media_release(dev); |
823beb7e HV |
179 | au0828_usb_release(dev); |
180 | } | |
8a4e7866 | 181 | #endif |
b14667f3 | 182 | |
823beb7e HV |
183 | static void au0828_usb_disconnect(struct usb_interface *interface) |
184 | { | |
185 | struct au0828_dev *dev = usb_get_intfdata(interface); | |
186 | ||
187 | dprintk(1, "%s()\n", __func__); | |
188 | ||
eb336eab SK |
189 | /* there is a small window after disconnect, before |
190 | dev->usbdev is NULL, for poll (e.g: IR) try to access | |
191 | the device and fill the dmesg with error messages. | |
192 | Set the status so poll routines can check and avoid | |
193 | access after disconnect. | |
194 | */ | |
195 | dev->dev_state = DEV_DISCONNECTED; | |
196 | ||
2fcfd317 | 197 | au0828_rc_unregister(dev); |
823beb7e HV |
198 | /* Digital TV */ |
199 | au0828_dvb_unregister(dev); | |
265a6510 | 200 | |
823beb7e | 201 | usb_set_intfdata(interface, NULL); |
265a6510 ST |
202 | mutex_lock(&dev->mutex); |
203 | dev->usbdev = NULL; | |
204 | mutex_unlock(&dev->mutex); | |
823beb7e HV |
205 | #ifdef CONFIG_VIDEO_AU0828_V4L2 |
206 | if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { | |
207 | au0828_analog_unregister(dev); | |
208 | v4l2_device_disconnect(&dev->v4l2_dev); | |
209 | v4l2_device_put(&dev->v4l2_dev); | |
7e9a8ad5 MCC |
210 | /* |
211 | * No need to call au0828_usb_release() if V4L2 is enabled, | |
212 | * as this is already called via au0828_usb_v4l2_release() | |
213 | */ | |
823beb7e HV |
214 | return; |
215 | } | |
216 | #endif | |
217 | au0828_usb_release(dev); | |
265a6510 ST |
218 | } |
219 | ||
9832e155 JMC |
220 | static void au0828_media_device_init(struct au0828_dev *dev, |
221 | struct usb_device *udev) | |
bed69196 RLLC |
222 | { |
223 | #ifdef CONFIG_MEDIA_CONTROLLER | |
224 | struct media_device *mdev; | |
bed69196 RLLC |
225 | |
226 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); | |
227 | if (!mdev) | |
228 | return; | |
229 | ||
230 | mdev->dev = &udev->dev; | |
231 | ||
232 | if (!dev->board.name) | |
233 | strlcpy(mdev->model, "unknown au0828", sizeof(mdev->model)); | |
234 | else | |
235 | strlcpy(mdev->model, dev->board.name, sizeof(mdev->model)); | |
236 | if (udev->serial) | |
237 | strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); | |
238 | strcpy(mdev->bus_info, udev->devpath); | |
239 | mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); | |
240 | mdev->driver_version = LINUX_VERSION_CODE; | |
241 | ||
9832e155 | 242 | media_device_init(mdev); |
bed69196 RLLC |
243 | |
244 | dev->media_dev = mdev; | |
245 | #endif | |
246 | } | |
247 | ||
248 | ||
4e26f3ab | 249 | static int au0828_create_media_graph(struct au0828_dev *dev) |
bed69196 RLLC |
250 | { |
251 | #ifdef CONFIG_MEDIA_CONTROLLER | |
252 | struct media_device *mdev = dev->media_dev; | |
253 | struct media_entity *entity; | |
254 | struct media_entity *tuner = NULL, *decoder = NULL; | |
4e26f3ab | 255 | int i, ret; |
bed69196 RLLC |
256 | |
257 | if (!mdev) | |
4e26f3ab | 258 | return 0; |
bed69196 RLLC |
259 | |
260 | media_device_for_each_entity(entity, mdev) { | |
0e576b76 | 261 | switch (entity->function) { |
4ca72efa | 262 | case MEDIA_ENT_F_TUNER: |
bed69196 RLLC |
263 | tuner = entity; |
264 | break; | |
4ca72efa | 265 | case MEDIA_ENT_F_ATV_DECODER: |
bed69196 RLLC |
266 | decoder = entity; |
267 | break; | |
268 | } | |
269 | } | |
270 | ||
271 | /* Analog setup, using tuner as a link */ | |
272 | ||
28b6ba11 | 273 | /* Something bad happened! */ |
bed69196 | 274 | if (!decoder) |
4e26f3ab MCC |
275 | return -EINVAL; |
276 | ||
277 | if (tuner) { | |
278 | ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT, | |
279 | decoder, 0, | |
280 | MEDIA_LNK_FL_ENABLED); | |
281 | if (ret) | |
282 | return ret; | |
283 | } | |
284 | ret = media_create_pad_link(decoder, 1, &dev->vdev.entity, 0, | |
285 | MEDIA_LNK_FL_ENABLED); | |
286 | if (ret) | |
287 | return ret; | |
288 | ret = media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0, | |
289 | MEDIA_LNK_FL_ENABLED); | |
290 | if (ret) | |
291 | return ret; | |
28b6ba11 MCC |
292 | |
293 | for (i = 0; i < AU0828_MAX_INPUT; i++) { | |
294 | struct media_entity *ent = &dev->input_ent[i]; | |
295 | ||
296 | if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) | |
297 | break; | |
298 | ||
299 | switch (AUVI_INPUT(i).type) { | |
300 | case AU0828_VMUX_CABLE: | |
301 | case AU0828_VMUX_TELEVISION: | |
302 | case AU0828_VMUX_DVB: | |
4e26f3ab MCC |
303 | if (!tuner) |
304 | break; | |
305 | ||
306 | ret = media_create_pad_link(ent, 0, tuner, | |
307 | TUNER_PAD_RF_INPUT, | |
308 | MEDIA_LNK_FL_ENABLED); | |
309 | if (ret) | |
310 | return ret; | |
28b6ba11 MCC |
311 | break; |
312 | case AU0828_VMUX_COMPOSITE: | |
313 | case AU0828_VMUX_SVIDEO: | |
314 | default: /* AU0828_VMUX_DEBUG */ | |
315 | /* FIXME: fix the decoder PAD */ | |
4e26f3ab MCC |
316 | ret = media_create_pad_link(ent, 0, decoder, 0, 0); |
317 | if (ret) | |
318 | return ret; | |
28b6ba11 MCC |
319 | break; |
320 | } | |
321 | } | |
bed69196 | 322 | #endif |
4e26f3ab | 323 | return 0; |
bed69196 RLLC |
324 | } |
325 | ||
18d73c58 | 326 | static int au0828_usb_probe(struct usb_interface *interface, |
265a6510 ST |
327 | const struct usb_device_id *id) |
328 | { | |
8a4e7866 | 329 | int ifnum; |
f251b3e7 TM |
330 | int retval = 0; |
331 | ||
265a6510 ST |
332 | struct au0828_dev *dev; |
333 | struct usb_device *usbdev = interface_to_usbdev(interface); | |
334 | ||
335 | ifnum = interface->altsetting->desc.bInterfaceNumber; | |
336 | ||
337 | if (ifnum != 0) | |
338 | return -ENODEV; | |
339 | ||
a9c36aad | 340 | dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__, |
265a6510 ST |
341 | le16_to_cpu(usbdev->descriptor.idVendor), |
342 | le16_to_cpu(usbdev->descriptor.idProduct), | |
343 | ifnum); | |
344 | ||
ee3436b8 DH |
345 | /* |
346 | * Make sure we have 480 Mbps of bandwidth, otherwise things like | |
347 | * video stream wouldn't likely work, since 12 Mbps is generally | |
348 | * not enough even for most Digital TV streams. | |
349 | */ | |
d6a9a430 | 350 | if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) { |
83afb32a MCC |
351 | pr_err("au0828: Device initialization failed.\n"); |
352 | pr_err("au0828: Device must be connected to a high-speed USB 2.0 port.\n"); | |
ee3436b8 DH |
353 | return -ENODEV; |
354 | } | |
355 | ||
265a6510 ST |
356 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
357 | if (dev == NULL) { | |
83afb32a | 358 | pr_err("%s() Unable to allocate memory\n", __func__); |
265a6510 ST |
359 | return -ENOMEM; |
360 | } | |
361 | ||
549ee4df DH |
362 | mutex_init(&dev->lock); |
363 | mutex_lock(&dev->lock); | |
265a6510 ST |
364 | mutex_init(&dev->mutex); |
365 | mutex_init(&dev->dvb.lock); | |
366 | dev->usbdev = usbdev; | |
f1add5b5 | 367 | dev->boardnr = id->driver_info; |
e42c8c6e RLLC |
368 | dev->board = au0828_boards[dev->boardnr]; |
369 | ||
9832e155 JMC |
370 | /* Initialize the media controller */ |
371 | au0828_media_device_init(dev, usbdev); | |
265a6510 | 372 | |
8a4e7866 | 373 | #ifdef CONFIG_VIDEO_AU0828_V4L2 |
823beb7e HV |
374 | dev->v4l2_dev.release = au0828_usb_v4l2_release; |
375 | ||
b14667f3 | 376 | /* Create the v4l2_device */ |
bed69196 RLLC |
377 | #ifdef CONFIG_MEDIA_CONTROLLER |
378 | dev->v4l2_dev.mdev = dev->media_dev; | |
379 | #endif | |
a4124aa9 | 380 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); |
b14667f3 | 381 | if (retval) { |
e8c26f45 | 382 | pr_err("%s() v4l2_device_register failed\n", |
b14667f3 | 383 | __func__); |
549ee4df | 384 | mutex_unlock(&dev->lock); |
b14667f3 | 385 | kfree(dev); |
e8c26f45 | 386 | return retval; |
b14667f3 | 387 | } |
e8c26f45 HV |
388 | /* This control handler will inherit the controls from au8522 */ |
389 | retval = v4l2_ctrl_handler_init(&dev->v4l2_ctrl_hdl, 4); | |
390 | if (retval) { | |
391 | pr_err("%s() v4l2_ctrl_handler_init failed\n", | |
392 | __func__); | |
393 | mutex_unlock(&dev->lock); | |
394 | kfree(dev); | |
395 | return retval; | |
396 | } | |
397 | dev->v4l2_dev.ctrl_handler = &dev->v4l2_ctrl_hdl; | |
8a4e7866 | 398 | #endif |
b14667f3 | 399 | |
265a6510 ST |
400 | /* Power Up the bridge */ |
401 | au0828_write(dev, REG_600, 1 << 4); | |
402 | ||
403 | /* Bring up the GPIO's and supporting devices */ | |
404 | au0828_gpio_setup(dev); | |
405 | ||
406 | /* I2C */ | |
407 | au0828_i2c_register(dev); | |
408 | ||
28930fa9 ST |
409 | /* Setup */ |
410 | au0828_card_setup(dev); | |
411 | ||
8a4e7866 | 412 | #ifdef CONFIG_VIDEO_AU0828_V4L2 |
8b2f0795 | 413 | /* Analog TV */ |
220be77c | 414 | if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) |
fc4ce6cd | 415 | au0828_analog_register(dev, interface); |
8a4e7866 | 416 | #endif |
8b2f0795 | 417 | |
265a6510 | 418 | /* Digital TV */ |
f251b3e7 TM |
419 | retval = au0828_dvb_register(dev); |
420 | if (retval) | |
421 | pr_err("%s() au0282_dev_register failed\n", | |
422 | __func__); | |
423 | ||
2fcfd317 MCC |
424 | /* Remote controller */ |
425 | au0828_rc_register(dev); | |
265a6510 | 426 | |
2fcfd317 MCC |
427 | /* |
428 | * Store the pointer to the au0828_dev so it can be accessed in | |
429 | * au0828_usb_disconnect | |
430 | */ | |
fe78a49c DH |
431 | usb_set_intfdata(interface, dev); |
432 | ||
83afb32a | 433 | pr_info("Registered device AU0828 [%s]\n", |
f1add5b5 | 434 | dev->board.name == NULL ? "Unset" : dev->board.name); |
265a6510 | 435 | |
549ee4df DH |
436 | mutex_unlock(&dev->lock); |
437 | ||
4e26f3ab MCC |
438 | retval = au0828_create_media_graph(dev); |
439 | if (retval) { | |
440 | pr_err("%s() au0282_dev_register failed to create graph\n", | |
441 | __func__); | |
9832e155 | 442 | goto done; |
4e26f3ab | 443 | } |
bed69196 | 444 | |
9832e155 JMC |
445 | #ifdef CONFIG_MEDIA_CONTROLLER |
446 | retval = media_device_register(dev->media_dev); | |
447 | #endif | |
448 | ||
449 | done: | |
450 | if (retval < 0) | |
451 | au0828_usb_disconnect(interface); | |
452 | ||
f251b3e7 | 453 | return retval; |
265a6510 ST |
454 | } |
455 | ||
aaeac199 MCC |
456 | static int au0828_suspend(struct usb_interface *interface, |
457 | pm_message_t message) | |
458 | { | |
459 | struct au0828_dev *dev = usb_get_intfdata(interface); | |
460 | ||
461 | if (!dev) | |
462 | return 0; | |
463 | ||
81187240 MCC |
464 | pr_info("Suspend\n"); |
465 | ||
aaeac199 | 466 | au0828_rc_suspend(dev); |
1a1ba95e | 467 | au0828_v4l2_suspend(dev); |
b799de75 | 468 | au0828_dvb_suspend(dev); |
aaeac199 MCC |
469 | |
470 | /* FIXME: should suspend also ATV/DTV */ | |
471 | ||
472 | return 0; | |
473 | } | |
474 | ||
475 | static int au0828_resume(struct usb_interface *interface) | |
476 | { | |
477 | struct au0828_dev *dev = usb_get_intfdata(interface); | |
478 | if (!dev) | |
479 | return 0; | |
480 | ||
81187240 MCC |
481 | pr_info("Resume\n"); |
482 | ||
fa500461 MCC |
483 | /* Power Up the bridge */ |
484 | au0828_write(dev, REG_600, 1 << 4); | |
485 | ||
486 | /* Bring up the GPIO's and supporting devices */ | |
487 | au0828_gpio_setup(dev); | |
488 | ||
aaeac199 | 489 | au0828_rc_resume(dev); |
1a1ba95e | 490 | au0828_v4l2_resume(dev); |
b799de75 | 491 | au0828_dvb_resume(dev); |
aaeac199 MCC |
492 | |
493 | /* FIXME: should resume also ATV/DTV */ | |
494 | ||
495 | return 0; | |
496 | } | |
497 | ||
265a6510 | 498 | static struct usb_driver au0828_usb_driver = { |
83afb32a | 499 | .name = KBUILD_MODNAME, |
265a6510 ST |
500 | .probe = au0828_usb_probe, |
501 | .disconnect = au0828_usb_disconnect, | |
502 | .id_table = au0828_usb_id_table, | |
aaeac199 MCC |
503 | .suspend = au0828_suspend, |
504 | .resume = au0828_resume, | |
505 | .reset_resume = au0828_resume, | |
265a6510 ST |
506 | }; |
507 | ||
508 | static int __init au0828_init(void) | |
509 | { | |
510 | int ret; | |
511 | ||
b33d24c4 | 512 | if (au0828_debug & 1) |
83afb32a | 513 | pr_info("%s() Debugging is enabled\n", __func__); |
bc3c613c | 514 | |
b33d24c4 | 515 | if (au0828_debug & 2) |
83afb32a | 516 | pr_info("%s() USB Debugging is enabled\n", __func__); |
bc3c613c | 517 | |
b33d24c4 | 518 | if (au0828_debug & 4) |
83afb32a | 519 | pr_info("%s() I2C Debugging is enabled\n", __func__); |
bc3c613c | 520 | |
b33d24c4 | 521 | if (au0828_debug & 8) |
83afb32a | 522 | pr_info("%s() Bridge Debugging is enabled\n", |
f07e8e4b | 523 | __func__); |
bc3c613c | 524 | |
2fcfd317 | 525 | if (au0828_debug & 16) |
83afb32a | 526 | pr_info("%s() IR Debugging is enabled\n", |
2fcfd317 MCC |
527 | __func__); |
528 | ||
83afb32a | 529 | pr_info("au0828 driver loaded\n"); |
265a6510 ST |
530 | |
531 | ret = usb_register(&au0828_usb_driver); | |
532 | if (ret) | |
83afb32a | 533 | pr_err("usb_register failed, error = %d\n", ret); |
265a6510 ST |
534 | |
535 | return ret; | |
536 | } | |
537 | ||
538 | static void __exit au0828_exit(void) | |
539 | { | |
540 | usb_deregister(&au0828_usb_driver); | |
541 | } | |
542 | ||
543 | module_init(au0828_init); | |
544 | module_exit(au0828_exit); | |
545 | ||
546 | MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products"); | |
6d897616 | 547 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); |
265a6510 | 548 | MODULE_LICENSE("GPL"); |
2fcfd317 | 549 | MODULE_VERSION("0.0.3"); |