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