]>
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 | ||
9f806795 MCC |
220 | static int 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) | |
9f806795 | 228 | return -ENOMEM; |
bed69196 RLLC |
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 | |
9f806795 | 246 | return 0; |
bed69196 RLLC |
247 | } |
248 | ||
249 | ||
4e26f3ab | 250 | static int au0828_create_media_graph(struct au0828_dev *dev) |
bed69196 RLLC |
251 | { |
252 | #ifdef CONFIG_MEDIA_CONTROLLER | |
253 | struct media_device *mdev = dev->media_dev; | |
254 | struct media_entity *entity; | |
255 | struct media_entity *tuner = NULL, *decoder = NULL; | |
4e26f3ab | 256 | int i, ret; |
bed69196 RLLC |
257 | |
258 | if (!mdev) | |
4e26f3ab | 259 | return 0; |
bed69196 RLLC |
260 | |
261 | media_device_for_each_entity(entity, mdev) { | |
0e576b76 | 262 | switch (entity->function) { |
4ca72efa | 263 | case MEDIA_ENT_F_TUNER: |
bed69196 RLLC |
264 | tuner = entity; |
265 | break; | |
4ca72efa | 266 | case MEDIA_ENT_F_ATV_DECODER: |
bed69196 RLLC |
267 | decoder = entity; |
268 | break; | |
269 | } | |
270 | } | |
271 | ||
272 | /* Analog setup, using tuner as a link */ | |
273 | ||
28b6ba11 | 274 | /* Something bad happened! */ |
bed69196 | 275 | if (!decoder) |
4e26f3ab MCC |
276 | return -EINVAL; |
277 | ||
278 | if (tuner) { | |
163c9bca | 279 | ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, |
4e26f3ab MCC |
280 | decoder, 0, |
281 | MEDIA_LNK_FL_ENABLED); | |
282 | if (ret) | |
283 | return ret; | |
284 | } | |
285 | ret = media_create_pad_link(decoder, 1, &dev->vdev.entity, 0, | |
286 | MEDIA_LNK_FL_ENABLED); | |
287 | if (ret) | |
288 | return ret; | |
289 | ret = media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0, | |
290 | MEDIA_LNK_FL_ENABLED); | |
291 | if (ret) | |
292 | return ret; | |
28b6ba11 MCC |
293 | |
294 | for (i = 0; i < AU0828_MAX_INPUT; i++) { | |
295 | struct media_entity *ent = &dev->input_ent[i]; | |
296 | ||
297 | if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) | |
298 | break; | |
299 | ||
300 | switch (AUVI_INPUT(i).type) { | |
301 | case AU0828_VMUX_CABLE: | |
302 | case AU0828_VMUX_TELEVISION: | |
303 | case AU0828_VMUX_DVB: | |
4e26f3ab MCC |
304 | if (!tuner) |
305 | break; | |
306 | ||
307 | ret = media_create_pad_link(ent, 0, tuner, | |
308 | TUNER_PAD_RF_INPUT, | |
309 | MEDIA_LNK_FL_ENABLED); | |
310 | if (ret) | |
311 | return ret; | |
28b6ba11 MCC |
312 | break; |
313 | case AU0828_VMUX_COMPOSITE: | |
314 | case AU0828_VMUX_SVIDEO: | |
315 | default: /* AU0828_VMUX_DEBUG */ | |
316 | /* FIXME: fix the decoder PAD */ | |
4e26f3ab MCC |
317 | ret = media_create_pad_link(ent, 0, decoder, 0, 0); |
318 | if (ret) | |
319 | return ret; | |
28b6ba11 MCC |
320 | break; |
321 | } | |
322 | } | |
bed69196 | 323 | #endif |
4e26f3ab | 324 | return 0; |
bed69196 RLLC |
325 | } |
326 | ||
18d73c58 | 327 | static int au0828_usb_probe(struct usb_interface *interface, |
265a6510 ST |
328 | const struct usb_device_id *id) |
329 | { | |
8a4e7866 | 330 | int ifnum; |
f251b3e7 TM |
331 | int retval = 0; |
332 | ||
265a6510 ST |
333 | struct au0828_dev *dev; |
334 | struct usb_device *usbdev = interface_to_usbdev(interface); | |
335 | ||
336 | ifnum = interface->altsetting->desc.bInterfaceNumber; | |
337 | ||
338 | if (ifnum != 0) | |
339 | return -ENODEV; | |
340 | ||
a9c36aad | 341 | dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__, |
265a6510 ST |
342 | le16_to_cpu(usbdev->descriptor.idVendor), |
343 | le16_to_cpu(usbdev->descriptor.idProduct), | |
344 | ifnum); | |
345 | ||
ee3436b8 DH |
346 | /* |
347 | * Make sure we have 480 Mbps of bandwidth, otherwise things like | |
348 | * video stream wouldn't likely work, since 12 Mbps is generally | |
349 | * not enough even for most Digital TV streams. | |
350 | */ | |
d6a9a430 | 351 | if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) { |
83afb32a MCC |
352 | pr_err("au0828: Device initialization failed.\n"); |
353 | pr_err("au0828: Device must be connected to a high-speed USB 2.0 port.\n"); | |
ee3436b8 DH |
354 | return -ENODEV; |
355 | } | |
356 | ||
265a6510 ST |
357 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
358 | if (dev == NULL) { | |
83afb32a | 359 | pr_err("%s() Unable to allocate memory\n", __func__); |
265a6510 ST |
360 | return -ENOMEM; |
361 | } | |
362 | ||
549ee4df DH |
363 | mutex_init(&dev->lock); |
364 | mutex_lock(&dev->lock); | |
265a6510 ST |
365 | mutex_init(&dev->mutex); |
366 | mutex_init(&dev->dvb.lock); | |
367 | dev->usbdev = usbdev; | |
f1add5b5 | 368 | dev->boardnr = id->driver_info; |
e42c8c6e RLLC |
369 | dev->board = au0828_boards[dev->boardnr]; |
370 | ||
9832e155 | 371 | /* Initialize the media controller */ |
9f806795 MCC |
372 | retval = au0828_media_device_init(dev, usbdev); |
373 | if (retval) { | |
374 | pr_err("%s() au0828_media_device_init failed\n", | |
375 | __func__); | |
376 | mutex_unlock(&dev->lock); | |
377 | kfree(dev); | |
378 | return retval; | |
379 | } | |
265a6510 | 380 | |
8a4e7866 | 381 | #ifdef CONFIG_VIDEO_AU0828_V4L2 |
823beb7e HV |
382 | dev->v4l2_dev.release = au0828_usb_v4l2_release; |
383 | ||
b14667f3 | 384 | /* Create the v4l2_device */ |
bed69196 RLLC |
385 | #ifdef CONFIG_MEDIA_CONTROLLER |
386 | dev->v4l2_dev.mdev = dev->media_dev; | |
387 | #endif | |
a4124aa9 | 388 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); |
b14667f3 | 389 | if (retval) { |
e8c26f45 | 390 | pr_err("%s() v4l2_device_register failed\n", |
b14667f3 | 391 | __func__); |
549ee4df | 392 | mutex_unlock(&dev->lock); |
b14667f3 | 393 | kfree(dev); |
e8c26f45 | 394 | return retval; |
b14667f3 | 395 | } |
e8c26f45 HV |
396 | /* This control handler will inherit the controls from au8522 */ |
397 | retval = v4l2_ctrl_handler_init(&dev->v4l2_ctrl_hdl, 4); | |
398 | if (retval) { | |
399 | pr_err("%s() v4l2_ctrl_handler_init failed\n", | |
400 | __func__); | |
401 | mutex_unlock(&dev->lock); | |
402 | kfree(dev); | |
403 | return retval; | |
404 | } | |
405 | dev->v4l2_dev.ctrl_handler = &dev->v4l2_ctrl_hdl; | |
8a4e7866 | 406 | #endif |
b14667f3 | 407 | |
265a6510 ST |
408 | /* Power Up the bridge */ |
409 | au0828_write(dev, REG_600, 1 << 4); | |
410 | ||
411 | /* Bring up the GPIO's and supporting devices */ | |
412 | au0828_gpio_setup(dev); | |
413 | ||
414 | /* I2C */ | |
415 | au0828_i2c_register(dev); | |
416 | ||
28930fa9 ST |
417 | /* Setup */ |
418 | au0828_card_setup(dev); | |
419 | ||
8a4e7866 | 420 | #ifdef CONFIG_VIDEO_AU0828_V4L2 |
8b2f0795 | 421 | /* Analog TV */ |
220be77c | 422 | if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) |
fc4ce6cd | 423 | au0828_analog_register(dev, interface); |
8a4e7866 | 424 | #endif |
8b2f0795 | 425 | |
265a6510 | 426 | /* Digital TV */ |
f251b3e7 TM |
427 | retval = au0828_dvb_register(dev); |
428 | if (retval) | |
429 | pr_err("%s() au0282_dev_register failed\n", | |
430 | __func__); | |
431 | ||
2fcfd317 MCC |
432 | /* Remote controller */ |
433 | au0828_rc_register(dev); | |
265a6510 | 434 | |
2fcfd317 MCC |
435 | /* |
436 | * Store the pointer to the au0828_dev so it can be accessed in | |
437 | * au0828_usb_disconnect | |
438 | */ | |
fe78a49c DH |
439 | usb_set_intfdata(interface, dev); |
440 | ||
83afb32a | 441 | pr_info("Registered device AU0828 [%s]\n", |
f1add5b5 | 442 | dev->board.name == NULL ? "Unset" : dev->board.name); |
265a6510 | 443 | |
549ee4df DH |
444 | mutex_unlock(&dev->lock); |
445 | ||
4e26f3ab MCC |
446 | retval = au0828_create_media_graph(dev); |
447 | if (retval) { | |
448 | pr_err("%s() au0282_dev_register failed to create graph\n", | |
449 | __func__); | |
9832e155 | 450 | goto done; |
4e26f3ab | 451 | } |
bed69196 | 452 | |
9832e155 JMC |
453 | #ifdef CONFIG_MEDIA_CONTROLLER |
454 | retval = media_device_register(dev->media_dev); | |
455 | #endif | |
456 | ||
457 | done: | |
458 | if (retval < 0) | |
459 | au0828_usb_disconnect(interface); | |
460 | ||
f251b3e7 | 461 | return retval; |
265a6510 ST |
462 | } |
463 | ||
aaeac199 MCC |
464 | static int au0828_suspend(struct usb_interface *interface, |
465 | pm_message_t message) | |
466 | { | |
467 | struct au0828_dev *dev = usb_get_intfdata(interface); | |
468 | ||
469 | if (!dev) | |
470 | return 0; | |
471 | ||
81187240 MCC |
472 | pr_info("Suspend\n"); |
473 | ||
aaeac199 | 474 | au0828_rc_suspend(dev); |
1a1ba95e | 475 | au0828_v4l2_suspend(dev); |
b799de75 | 476 | au0828_dvb_suspend(dev); |
aaeac199 MCC |
477 | |
478 | /* FIXME: should suspend also ATV/DTV */ | |
479 | ||
480 | return 0; | |
481 | } | |
482 | ||
483 | static int au0828_resume(struct usb_interface *interface) | |
484 | { | |
485 | struct au0828_dev *dev = usb_get_intfdata(interface); | |
486 | if (!dev) | |
487 | return 0; | |
488 | ||
81187240 MCC |
489 | pr_info("Resume\n"); |
490 | ||
fa500461 MCC |
491 | /* Power Up the bridge */ |
492 | au0828_write(dev, REG_600, 1 << 4); | |
493 | ||
494 | /* Bring up the GPIO's and supporting devices */ | |
495 | au0828_gpio_setup(dev); | |
496 | ||
aaeac199 | 497 | au0828_rc_resume(dev); |
1a1ba95e | 498 | au0828_v4l2_resume(dev); |
b799de75 | 499 | au0828_dvb_resume(dev); |
aaeac199 MCC |
500 | |
501 | /* FIXME: should resume also ATV/DTV */ | |
502 | ||
503 | return 0; | |
504 | } | |
505 | ||
265a6510 | 506 | static struct usb_driver au0828_usb_driver = { |
83afb32a | 507 | .name = KBUILD_MODNAME, |
265a6510 ST |
508 | .probe = au0828_usb_probe, |
509 | .disconnect = au0828_usb_disconnect, | |
510 | .id_table = au0828_usb_id_table, | |
aaeac199 MCC |
511 | .suspend = au0828_suspend, |
512 | .resume = au0828_resume, | |
513 | .reset_resume = au0828_resume, | |
265a6510 ST |
514 | }; |
515 | ||
516 | static int __init au0828_init(void) | |
517 | { | |
518 | int ret; | |
519 | ||
b33d24c4 | 520 | if (au0828_debug & 1) |
83afb32a | 521 | pr_info("%s() Debugging is enabled\n", __func__); |
bc3c613c | 522 | |
b33d24c4 | 523 | if (au0828_debug & 2) |
83afb32a | 524 | pr_info("%s() USB Debugging is enabled\n", __func__); |
bc3c613c | 525 | |
b33d24c4 | 526 | if (au0828_debug & 4) |
83afb32a | 527 | pr_info("%s() I2C Debugging is enabled\n", __func__); |
bc3c613c | 528 | |
b33d24c4 | 529 | if (au0828_debug & 8) |
83afb32a | 530 | pr_info("%s() Bridge Debugging is enabled\n", |
f07e8e4b | 531 | __func__); |
bc3c613c | 532 | |
2fcfd317 | 533 | if (au0828_debug & 16) |
83afb32a | 534 | pr_info("%s() IR Debugging is enabled\n", |
2fcfd317 MCC |
535 | __func__); |
536 | ||
83afb32a | 537 | pr_info("au0828 driver loaded\n"); |
265a6510 ST |
538 | |
539 | ret = usb_register(&au0828_usb_driver); | |
540 | if (ret) | |
83afb32a | 541 | pr_err("usb_register failed, error = %d\n", ret); |
265a6510 ST |
542 | |
543 | return ret; | |
544 | } | |
545 | ||
546 | static void __exit au0828_exit(void) | |
547 | { | |
548 | usb_deregister(&au0828_usb_driver); | |
549 | } | |
550 | ||
551 | module_init(au0828_init); | |
552 | module_exit(au0828_exit); | |
553 | ||
554 | MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products"); | |
6d897616 | 555 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); |
265a6510 | 556 | MODULE_LICENSE("GPL"); |
2fcfd317 | 557 | MODULE_VERSION("0.0.3"); |