]>
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); | |
139 | kfree(dev->media_dev); | |
140 | dev->media_dev = NULL; | |
141 | } | |
142 | #endif | |
143 | } | |
144 | ||
823beb7e | 145 | static void au0828_usb_release(struct au0828_dev *dev) |
265a6510 | 146 | { |
bed69196 RLLC |
147 | au0828_unregister_media_device(dev); |
148 | ||
265a6510 ST |
149 | /* I2C */ |
150 | au0828_i2c_unregister(dev); | |
151 | ||
823beb7e HV |
152 | kfree(dev); |
153 | } | |
154 | ||
8a4e7866 | 155 | #ifdef CONFIG_VIDEO_AU0828_V4L2 |
823beb7e HV |
156 | static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev) |
157 | { | |
158 | struct au0828_dev *dev = | |
159 | container_of(v4l2_dev, struct au0828_dev, v4l2_dev); | |
160 | ||
e8c26f45 | 161 | v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl); |
b14667f3 | 162 | v4l2_device_unregister(&dev->v4l2_dev); |
823beb7e HV |
163 | au0828_usb_release(dev); |
164 | } | |
8a4e7866 | 165 | #endif |
b14667f3 | 166 | |
823beb7e HV |
167 | static void au0828_usb_disconnect(struct usb_interface *interface) |
168 | { | |
169 | struct au0828_dev *dev = usb_get_intfdata(interface); | |
170 | ||
171 | dprintk(1, "%s()\n", __func__); | |
172 | ||
eb336eab SK |
173 | /* there is a small window after disconnect, before |
174 | dev->usbdev is NULL, for poll (e.g: IR) try to access | |
175 | the device and fill the dmesg with error messages. | |
176 | Set the status so poll routines can check and avoid | |
177 | access after disconnect. | |
178 | */ | |
179 | dev->dev_state = DEV_DISCONNECTED; | |
180 | ||
bed69196 RLLC |
181 | au0828_unregister_media_device(dev); |
182 | ||
2fcfd317 | 183 | au0828_rc_unregister(dev); |
823beb7e HV |
184 | /* Digital TV */ |
185 | au0828_dvb_unregister(dev); | |
265a6510 | 186 | |
823beb7e | 187 | usb_set_intfdata(interface, NULL); |
265a6510 ST |
188 | mutex_lock(&dev->mutex); |
189 | dev->usbdev = NULL; | |
190 | mutex_unlock(&dev->mutex); | |
823beb7e HV |
191 | #ifdef CONFIG_VIDEO_AU0828_V4L2 |
192 | if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { | |
193 | au0828_analog_unregister(dev); | |
194 | v4l2_device_disconnect(&dev->v4l2_dev); | |
195 | v4l2_device_put(&dev->v4l2_dev); | |
196 | return; | |
197 | } | |
198 | #endif | |
199 | au0828_usb_release(dev); | |
265a6510 ST |
200 | } |
201 | ||
bed69196 RLLC |
202 | static void au0828_media_device_register(struct au0828_dev *dev, |
203 | struct usb_device *udev) | |
204 | { | |
205 | #ifdef CONFIG_MEDIA_CONTROLLER | |
206 | struct media_device *mdev; | |
207 | int ret; | |
208 | ||
209 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); | |
210 | if (!mdev) | |
211 | return; | |
212 | ||
213 | mdev->dev = &udev->dev; | |
214 | ||
215 | if (!dev->board.name) | |
216 | strlcpy(mdev->model, "unknown au0828", sizeof(mdev->model)); | |
217 | else | |
218 | strlcpy(mdev->model, dev->board.name, sizeof(mdev->model)); | |
219 | if (udev->serial) | |
220 | strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); | |
221 | strcpy(mdev->bus_info, udev->devpath); | |
222 | mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); | |
223 | mdev->driver_version = LINUX_VERSION_CODE; | |
224 | ||
225 | ret = media_device_register(mdev); | |
226 | if (ret) { | |
227 | pr_err( | |
228 | "Couldn't create a media device. Error: %d\n", | |
229 | ret); | |
230 | kfree(mdev); | |
231 | return; | |
232 | } | |
233 | ||
234 | dev->media_dev = mdev; | |
235 | #endif | |
236 | } | |
237 | ||
238 | ||
239 | static void au0828_create_media_graph(struct au0828_dev *dev) | |
240 | { | |
241 | #ifdef CONFIG_MEDIA_CONTROLLER | |
242 | struct media_device *mdev = dev->media_dev; | |
243 | struct media_entity *entity; | |
244 | struct media_entity *tuner = NULL, *decoder = NULL; | |
245 | ||
246 | if (!mdev) | |
247 | return; | |
248 | ||
249 | media_device_for_each_entity(entity, mdev) { | |
250 | switch (entity->type) { | |
251 | case MEDIA_ENT_T_V4L2_SUBDEV_TUNER: | |
252 | tuner = entity; | |
253 | break; | |
254 | case MEDIA_ENT_T_V4L2_SUBDEV_DECODER: | |
255 | decoder = entity; | |
256 | break; | |
257 | } | |
258 | } | |
259 | ||
260 | /* Analog setup, using tuner as a link */ | |
261 | ||
262 | if (!decoder) | |
263 | return; | |
264 | ||
265 | if (tuner) | |
188d2d55 | 266 | media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT, decoder, 0, |
57208e5e MCC |
267 | MEDIA_LNK_FL_ENABLED); |
268 | media_create_pad_link(decoder, 1, &dev->vdev.entity, 0, | |
269 | MEDIA_LNK_FL_ENABLED); | |
270 | media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0, | |
271 | MEDIA_LNK_FL_ENABLED); | |
bed69196 RLLC |
272 | #endif |
273 | } | |
274 | ||
18d73c58 | 275 | static int au0828_usb_probe(struct usb_interface *interface, |
265a6510 ST |
276 | const struct usb_device_id *id) |
277 | { | |
8a4e7866 | 278 | int ifnum; |
f251b3e7 TM |
279 | int retval = 0; |
280 | ||
265a6510 ST |
281 | struct au0828_dev *dev; |
282 | struct usb_device *usbdev = interface_to_usbdev(interface); | |
283 | ||
284 | ifnum = interface->altsetting->desc.bInterfaceNumber; | |
285 | ||
286 | if (ifnum != 0) | |
287 | return -ENODEV; | |
288 | ||
a9c36aad | 289 | dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__, |
265a6510 ST |
290 | le16_to_cpu(usbdev->descriptor.idVendor), |
291 | le16_to_cpu(usbdev->descriptor.idProduct), | |
292 | ifnum); | |
293 | ||
ee3436b8 DH |
294 | /* |
295 | * Make sure we have 480 Mbps of bandwidth, otherwise things like | |
296 | * video stream wouldn't likely work, since 12 Mbps is generally | |
297 | * not enough even for most Digital TV streams. | |
298 | */ | |
d6a9a430 | 299 | if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) { |
83afb32a MCC |
300 | pr_err("au0828: Device initialization failed.\n"); |
301 | pr_err("au0828: Device must be connected to a high-speed USB 2.0 port.\n"); | |
ee3436b8 DH |
302 | return -ENODEV; |
303 | } | |
304 | ||
265a6510 ST |
305 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
306 | if (dev == NULL) { | |
83afb32a | 307 | pr_err("%s() Unable to allocate memory\n", __func__); |
265a6510 ST |
308 | return -ENOMEM; |
309 | } | |
310 | ||
549ee4df DH |
311 | mutex_init(&dev->lock); |
312 | mutex_lock(&dev->lock); | |
265a6510 ST |
313 | mutex_init(&dev->mutex); |
314 | mutex_init(&dev->dvb.lock); | |
315 | dev->usbdev = usbdev; | |
f1add5b5 | 316 | dev->boardnr = id->driver_info; |
e42c8c6e RLLC |
317 | dev->board = au0828_boards[dev->boardnr]; |
318 | ||
bed69196 RLLC |
319 | /* Register the media controller */ |
320 | au0828_media_device_register(dev, usbdev); | |
265a6510 | 321 | |
8a4e7866 | 322 | #ifdef CONFIG_VIDEO_AU0828_V4L2 |
823beb7e HV |
323 | dev->v4l2_dev.release = au0828_usb_v4l2_release; |
324 | ||
b14667f3 | 325 | /* Create the v4l2_device */ |
bed69196 RLLC |
326 | #ifdef CONFIG_MEDIA_CONTROLLER |
327 | dev->v4l2_dev.mdev = dev->media_dev; | |
328 | #endif | |
a4124aa9 | 329 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); |
b14667f3 | 330 | if (retval) { |
e8c26f45 | 331 | pr_err("%s() v4l2_device_register failed\n", |
b14667f3 | 332 | __func__); |
549ee4df | 333 | mutex_unlock(&dev->lock); |
b14667f3 | 334 | kfree(dev); |
e8c26f45 | 335 | return retval; |
b14667f3 | 336 | } |
e8c26f45 HV |
337 | /* This control handler will inherit the controls from au8522 */ |
338 | retval = v4l2_ctrl_handler_init(&dev->v4l2_ctrl_hdl, 4); | |
339 | if (retval) { | |
340 | pr_err("%s() v4l2_ctrl_handler_init failed\n", | |
341 | __func__); | |
342 | mutex_unlock(&dev->lock); | |
343 | kfree(dev); | |
344 | return retval; | |
345 | } | |
346 | dev->v4l2_dev.ctrl_handler = &dev->v4l2_ctrl_hdl; | |
8a4e7866 | 347 | #endif |
b14667f3 | 348 | |
265a6510 ST |
349 | /* Power Up the bridge */ |
350 | au0828_write(dev, REG_600, 1 << 4); | |
351 | ||
352 | /* Bring up the GPIO's and supporting devices */ | |
353 | au0828_gpio_setup(dev); | |
354 | ||
355 | /* I2C */ | |
356 | au0828_i2c_register(dev); | |
357 | ||
28930fa9 ST |
358 | /* Setup */ |
359 | au0828_card_setup(dev); | |
360 | ||
8a4e7866 | 361 | #ifdef CONFIG_VIDEO_AU0828_V4L2 |
8b2f0795 | 362 | /* Analog TV */ |
220be77c | 363 | if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) |
fc4ce6cd | 364 | au0828_analog_register(dev, interface); |
8a4e7866 | 365 | #endif |
8b2f0795 | 366 | |
265a6510 | 367 | /* Digital TV */ |
f251b3e7 TM |
368 | retval = au0828_dvb_register(dev); |
369 | if (retval) | |
370 | pr_err("%s() au0282_dev_register failed\n", | |
371 | __func__); | |
372 | ||
2fcfd317 MCC |
373 | /* Remote controller */ |
374 | au0828_rc_register(dev); | |
265a6510 | 375 | |
2fcfd317 MCC |
376 | /* |
377 | * Store the pointer to the au0828_dev so it can be accessed in | |
378 | * au0828_usb_disconnect | |
379 | */ | |
fe78a49c DH |
380 | usb_set_intfdata(interface, dev); |
381 | ||
83afb32a | 382 | pr_info("Registered device AU0828 [%s]\n", |
f1add5b5 | 383 | dev->board.name == NULL ? "Unset" : dev->board.name); |
265a6510 | 384 | |
549ee4df DH |
385 | mutex_unlock(&dev->lock); |
386 | ||
bed69196 RLLC |
387 | au0828_create_media_graph(dev); |
388 | ||
f251b3e7 | 389 | return retval; |
265a6510 ST |
390 | } |
391 | ||
aaeac199 MCC |
392 | static int au0828_suspend(struct usb_interface *interface, |
393 | pm_message_t message) | |
394 | { | |
395 | struct au0828_dev *dev = usb_get_intfdata(interface); | |
396 | ||
397 | if (!dev) | |
398 | return 0; | |
399 | ||
81187240 MCC |
400 | pr_info("Suspend\n"); |
401 | ||
aaeac199 | 402 | au0828_rc_suspend(dev); |
1a1ba95e | 403 | au0828_v4l2_suspend(dev); |
b799de75 | 404 | au0828_dvb_suspend(dev); |
aaeac199 MCC |
405 | |
406 | /* FIXME: should suspend also ATV/DTV */ | |
407 | ||
408 | return 0; | |
409 | } | |
410 | ||
411 | static int au0828_resume(struct usb_interface *interface) | |
412 | { | |
413 | struct au0828_dev *dev = usb_get_intfdata(interface); | |
414 | if (!dev) | |
415 | return 0; | |
416 | ||
81187240 MCC |
417 | pr_info("Resume\n"); |
418 | ||
fa500461 MCC |
419 | /* Power Up the bridge */ |
420 | au0828_write(dev, REG_600, 1 << 4); | |
421 | ||
422 | /* Bring up the GPIO's and supporting devices */ | |
423 | au0828_gpio_setup(dev); | |
424 | ||
aaeac199 | 425 | au0828_rc_resume(dev); |
1a1ba95e | 426 | au0828_v4l2_resume(dev); |
b799de75 | 427 | au0828_dvb_resume(dev); |
aaeac199 MCC |
428 | |
429 | /* FIXME: should resume also ATV/DTV */ | |
430 | ||
431 | return 0; | |
432 | } | |
433 | ||
265a6510 | 434 | static struct usb_driver au0828_usb_driver = { |
83afb32a | 435 | .name = KBUILD_MODNAME, |
265a6510 ST |
436 | .probe = au0828_usb_probe, |
437 | .disconnect = au0828_usb_disconnect, | |
438 | .id_table = au0828_usb_id_table, | |
aaeac199 MCC |
439 | .suspend = au0828_suspend, |
440 | .resume = au0828_resume, | |
441 | .reset_resume = au0828_resume, | |
265a6510 ST |
442 | }; |
443 | ||
444 | static int __init au0828_init(void) | |
445 | { | |
446 | int ret; | |
447 | ||
b33d24c4 | 448 | if (au0828_debug & 1) |
83afb32a | 449 | pr_info("%s() Debugging is enabled\n", __func__); |
bc3c613c | 450 | |
b33d24c4 | 451 | if (au0828_debug & 2) |
83afb32a | 452 | pr_info("%s() USB Debugging is enabled\n", __func__); |
bc3c613c | 453 | |
b33d24c4 | 454 | if (au0828_debug & 4) |
83afb32a | 455 | pr_info("%s() I2C Debugging is enabled\n", __func__); |
bc3c613c | 456 | |
b33d24c4 | 457 | if (au0828_debug & 8) |
83afb32a | 458 | pr_info("%s() Bridge Debugging is enabled\n", |
f07e8e4b | 459 | __func__); |
bc3c613c | 460 | |
2fcfd317 | 461 | if (au0828_debug & 16) |
83afb32a | 462 | pr_info("%s() IR Debugging is enabled\n", |
2fcfd317 MCC |
463 | __func__); |
464 | ||
83afb32a | 465 | pr_info("au0828 driver loaded\n"); |
265a6510 ST |
466 | |
467 | ret = usb_register(&au0828_usb_driver); | |
468 | if (ret) | |
83afb32a | 469 | pr_err("usb_register failed, error = %d\n", ret); |
265a6510 ST |
470 | |
471 | return ret; | |
472 | } | |
473 | ||
474 | static void __exit au0828_exit(void) | |
475 | { | |
476 | usb_deregister(&au0828_usb_driver); | |
477 | } | |
478 | ||
479 | module_init(au0828_init); | |
480 | module_exit(au0828_exit); | |
481 | ||
482 | MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products"); | |
6d897616 | 483 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); |
265a6510 | 484 | MODULE_LICENSE("GPL"); |
2fcfd317 | 485 | MODULE_VERSION("0.0.3"); |