diff options
Diffstat (limited to 'drivers/media/radio/dsbr100.c')
-rw-r--r-- | drivers/media/radio/dsbr100.c | 128 |
1 files changed, 38 insertions, 90 deletions
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c index ed9cd7ad060..3d8cc425fa6 100644 --- a/drivers/media/radio/dsbr100.c +++ b/drivers/media/radio/dsbr100.c | |||
@@ -129,7 +129,7 @@ devices, that would be 76 and 91. */ | |||
129 | #define STARTED 0 | 129 | #define STARTED 0 |
130 | #define STOPPED 1 | 130 | #define STOPPED 1 |
131 | 131 | ||
132 | #define videodev_to_radio(d) container_of(d, struct dsbr100_device, videodev) | 132 | #define v4l2_dev_to_radio(d) container_of(d, struct dsbr100_device, v4l2_dev) |
133 | 133 | ||
134 | static int usb_dsbr100_probe(struct usb_interface *intf, | 134 | static int usb_dsbr100_probe(struct usb_interface *intf, |
135 | const struct usb_device_id *id); | 135 | const struct usb_device_id *id); |
@@ -148,10 +148,9 @@ struct dsbr100_device { | |||
148 | struct v4l2_device v4l2_dev; | 148 | struct v4l2_device v4l2_dev; |
149 | 149 | ||
150 | u8 *transfer_buffer; | 150 | u8 *transfer_buffer; |
151 | struct mutex lock; /* buffer locking */ | 151 | struct mutex v4l2_lock; |
152 | int curfreq; | 152 | int curfreq; |
153 | int stereo; | 153 | int stereo; |
154 | int removed; | ||
155 | int status; | 154 | int status; |
156 | }; | 155 | }; |
157 | 156 | ||
@@ -182,8 +181,6 @@ static int dsbr100_start(struct dsbr100_device *radio) | |||
182 | int retval; | 181 | int retval; |
183 | int request; | 182 | int request; |
184 | 183 | ||
185 | mutex_lock(&radio->lock); | ||
186 | |||
187 | retval = usb_control_msg(radio->usbdev, | 184 | retval = usb_control_msg(radio->usbdev, |
188 | usb_rcvctrlpipe(radio->usbdev, 0), | 185 | usb_rcvctrlpipe(radio->usbdev, 0), |
189 | USB_REQ_GET_STATUS, | 186 | USB_REQ_GET_STATUS, |
@@ -207,11 +204,9 @@ static int dsbr100_start(struct dsbr100_device *radio) | |||
207 | } | 204 | } |
208 | 205 | ||
209 | radio->status = STARTED; | 206 | radio->status = STARTED; |
210 | mutex_unlock(&radio->lock); | ||
211 | return (radio->transfer_buffer)[0]; | 207 | return (radio->transfer_buffer)[0]; |
212 | 208 | ||
213 | usb_control_msg_failed: | 209 | usb_control_msg_failed: |
214 | mutex_unlock(&radio->lock); | ||
215 | dev_err(&radio->usbdev->dev, | 210 | dev_err(&radio->usbdev->dev, |
216 | "%s - usb_control_msg returned %i, request %i\n", | 211 | "%s - usb_control_msg returned %i, request %i\n", |
217 | __func__, retval, request); | 212 | __func__, retval, request); |
@@ -225,8 +220,6 @@ static int dsbr100_stop(struct dsbr100_device *radio) | |||
225 | int retval; | 220 | int retval; |
226 | int request; | 221 | int request; |
227 | 222 | ||
228 | mutex_lock(&radio->lock); | ||
229 | |||
230 | retval = usb_control_msg(radio->usbdev, | 223 | retval = usb_control_msg(radio->usbdev, |
231 | usb_rcvctrlpipe(radio->usbdev, 0), | 224 | usb_rcvctrlpipe(radio->usbdev, 0), |
232 | USB_REQ_GET_STATUS, | 225 | USB_REQ_GET_STATUS, |
@@ -250,11 +243,9 @@ static int dsbr100_stop(struct dsbr100_device *radio) | |||
250 | } | 243 | } |
251 | 244 | ||
252 | radio->status = STOPPED; | 245 | radio->status = STOPPED; |
253 | mutex_unlock(&radio->lock); | ||
254 | return (radio->transfer_buffer)[0]; | 246 | return (radio->transfer_buffer)[0]; |
255 | 247 | ||
256 | usb_control_msg_failed: | 248 | usb_control_msg_failed: |
257 | mutex_unlock(&radio->lock); | ||
258 | dev_err(&radio->usbdev->dev, | 249 | dev_err(&radio->usbdev->dev, |
259 | "%s - usb_control_msg returned %i, request %i\n", | 250 | "%s - usb_control_msg returned %i, request %i\n", |
260 | __func__, retval, request); | 251 | __func__, retval, request); |
@@ -269,8 +260,6 @@ static int dsbr100_setfreq(struct dsbr100_device *radio) | |||
269 | int request; | 260 | int request; |
270 | int freq = (radio->curfreq / 16 * 80) / 1000 + 856; | 261 | int freq = (radio->curfreq / 16 * 80) / 1000 + 856; |
271 | 262 | ||
272 | mutex_lock(&radio->lock); | ||
273 | |||
274 | retval = usb_control_msg(radio->usbdev, | 263 | retval = usb_control_msg(radio->usbdev, |
275 | usb_rcvctrlpipe(radio->usbdev, 0), | 264 | usb_rcvctrlpipe(radio->usbdev, 0), |
276 | DSB100_TUNE, | 265 | DSB100_TUNE, |
@@ -306,12 +295,10 @@ static int dsbr100_setfreq(struct dsbr100_device *radio) | |||
306 | } | 295 | } |
307 | 296 | ||
308 | radio->stereo = !((radio->transfer_buffer)[0] & 0x01); | 297 | radio->stereo = !((radio->transfer_buffer)[0] & 0x01); |
309 | mutex_unlock(&radio->lock); | ||
310 | return (radio->transfer_buffer)[0]; | 298 | return (radio->transfer_buffer)[0]; |
311 | 299 | ||
312 | usb_control_msg_failed: | 300 | usb_control_msg_failed: |
313 | radio->stereo = -1; | 301 | radio->stereo = -1; |
314 | mutex_unlock(&radio->lock); | ||
315 | dev_err(&radio->usbdev->dev, | 302 | dev_err(&radio->usbdev->dev, |
316 | "%s - usb_control_msg returned %i, request %i\n", | 303 | "%s - usb_control_msg returned %i, request %i\n", |
317 | __func__, retval, request); | 304 | __func__, retval, request); |
@@ -324,8 +311,6 @@ static void dsbr100_getstat(struct dsbr100_device *radio) | |||
324 | { | 311 | { |
325 | int retval; | 312 | int retval; |
326 | 313 | ||
327 | mutex_lock(&radio->lock); | ||
328 | |||
329 | retval = usb_control_msg(radio->usbdev, | 314 | retval = usb_control_msg(radio->usbdev, |
330 | usb_rcvctrlpipe(radio->usbdev, 0), | 315 | usb_rcvctrlpipe(radio->usbdev, 0), |
331 | USB_REQ_GET_STATUS, | 316 | USB_REQ_GET_STATUS, |
@@ -340,33 +325,8 @@ static void dsbr100_getstat(struct dsbr100_device *radio) | |||
340 | } else { | 325 | } else { |
341 | radio->stereo = !(radio->transfer_buffer[0] & 0x01); | 326 | radio->stereo = !(radio->transfer_buffer[0] & 0x01); |
342 | } | 327 | } |
343 | |||
344 | mutex_unlock(&radio->lock); | ||
345 | } | 328 | } |
346 | 329 | ||
347 | /* USB subsystem interface begins here */ | ||
348 | |||
349 | /* | ||
350 | * Handle unplugging of the device. | ||
351 | * We call video_unregister_device in any case. | ||
352 | * The last function called in this procedure is | ||
353 | * usb_dsbr100_video_device_release | ||
354 | */ | ||
355 | static void usb_dsbr100_disconnect(struct usb_interface *intf) | ||
356 | { | ||
357 | struct dsbr100_device *radio = usb_get_intfdata(intf); | ||
358 | |||
359 | usb_set_intfdata (intf, NULL); | ||
360 | |||
361 | mutex_lock(&radio->lock); | ||
362 | radio->removed = 1; | ||
363 | mutex_unlock(&radio->lock); | ||
364 | |||
365 | video_unregister_device(&radio->videodev); | ||
366 | v4l2_device_disconnect(&radio->v4l2_dev); | ||
367 | } | ||
368 | |||
369 | |||
370 | static int vidioc_querycap(struct file *file, void *priv, | 330 | static int vidioc_querycap(struct file *file, void *priv, |
371 | struct v4l2_capability *v) | 331 | struct v4l2_capability *v) |
372 | { | 332 | { |
@@ -385,10 +345,6 @@ static int vidioc_g_tuner(struct file *file, void *priv, | |||
385 | { | 345 | { |
386 | struct dsbr100_device *radio = video_drvdata(file); | 346 | struct dsbr100_device *radio = video_drvdata(file); |
387 | 347 | ||
388 | /* safety check */ | ||
389 | if (radio->removed) | ||
390 | return -EIO; | ||
391 | |||
392 | if (v->index > 0) | 348 | if (v->index > 0) |
393 | return -EINVAL; | 349 | return -EINVAL; |
394 | 350 | ||
@@ -410,16 +366,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, | |||
410 | static int vidioc_s_tuner(struct file *file, void *priv, | 366 | static int vidioc_s_tuner(struct file *file, void *priv, |
411 | struct v4l2_tuner *v) | 367 | struct v4l2_tuner *v) |
412 | { | 368 | { |
413 | struct dsbr100_device *radio = video_drvdata(file); | 369 | return v->index ? -EINVAL : 0; |
414 | |||
415 | /* safety check */ | ||
416 | if (radio->removed) | ||
417 | return -EIO; | ||
418 | |||
419 | if (v->index > 0) | ||
420 | return -EINVAL; | ||
421 | |||
422 | return 0; | ||
423 | } | 370 | } |
424 | 371 | ||
425 | static int vidioc_s_frequency(struct file *file, void *priv, | 372 | static int vidioc_s_frequency(struct file *file, void *priv, |
@@ -428,13 +375,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
428 | struct dsbr100_device *radio = video_drvdata(file); | 375 | struct dsbr100_device *radio = video_drvdata(file); |
429 | int retval; | 376 | int retval; |
430 | 377 | ||
431 | /* safety check */ | ||
432 | if (radio->removed) | ||
433 | return -EIO; | ||
434 | |||
435 | mutex_lock(&radio->lock); | ||
436 | radio->curfreq = f->frequency; | 378 | radio->curfreq = f->frequency; |
437 | mutex_unlock(&radio->lock); | ||
438 | 379 | ||
439 | retval = dsbr100_setfreq(radio); | 380 | retval = dsbr100_setfreq(radio); |
440 | if (retval < 0) | 381 | if (retval < 0) |
@@ -447,10 +388,6 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
447 | { | 388 | { |
448 | struct dsbr100_device *radio = video_drvdata(file); | 389 | struct dsbr100_device *radio = video_drvdata(file); |
449 | 390 | ||
450 | /* safety check */ | ||
451 | if (radio->removed) | ||
452 | return -EIO; | ||
453 | |||
454 | f->type = V4L2_TUNER_RADIO; | 391 | f->type = V4L2_TUNER_RADIO; |
455 | f->frequency = radio->curfreq; | 392 | f->frequency = radio->curfreq; |
456 | return 0; | 393 | return 0; |
@@ -472,10 +409,6 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
472 | { | 409 | { |
473 | struct dsbr100_device *radio = video_drvdata(file); | 410 | struct dsbr100_device *radio = video_drvdata(file); |
474 | 411 | ||
475 | /* safety check */ | ||
476 | if (radio->removed) | ||
477 | return -EIO; | ||
478 | |||
479 | switch (ctrl->id) { | 412 | switch (ctrl->id) { |
480 | case V4L2_CID_AUDIO_MUTE: | 413 | case V4L2_CID_AUDIO_MUTE: |
481 | ctrl->value = radio->status; | 414 | ctrl->value = radio->status; |
@@ -490,10 +423,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
490 | struct dsbr100_device *radio = video_drvdata(file); | 423 | struct dsbr100_device *radio = video_drvdata(file); |
491 | int retval; | 424 | int retval; |
492 | 425 | ||
493 | /* safety check */ | ||
494 | if (radio->removed) | ||
495 | return -EIO; | ||
496 | |||
497 | switch (ctrl->id) { | 426 | switch (ctrl->id) { |
498 | case V4L2_CID_AUDIO_MUTE: | 427 | case V4L2_CID_AUDIO_MUTE: |
499 | if (ctrl->value) { | 428 | if (ctrl->value) { |
@@ -535,25 +464,44 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | |||
535 | 464 | ||
536 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) | 465 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) |
537 | { | 466 | { |
538 | if (i != 0) | 467 | return i ? -EINVAL : 0; |
539 | return -EINVAL; | ||
540 | return 0; | ||
541 | } | 468 | } |
542 | 469 | ||
543 | static int vidioc_s_audio(struct file *file, void *priv, | 470 | static int vidioc_s_audio(struct file *file, void *priv, |
544 | struct v4l2_audio *a) | 471 | struct v4l2_audio *a) |
545 | { | 472 | { |
546 | if (a->index != 0) | 473 | return a->index ? -EINVAL : 0; |
547 | return -EINVAL; | 474 | } |
548 | return 0; | 475 | |
476 | /* USB subsystem interface begins here */ | ||
477 | |||
478 | /* | ||
479 | * Handle unplugging of the device. | ||
480 | * We call video_unregister_device in any case. | ||
481 | * The last function called in this procedure is | ||
482 | * usb_dsbr100_video_device_release | ||
483 | */ | ||
484 | static void usb_dsbr100_disconnect(struct usb_interface *intf) | ||
485 | { | ||
486 | struct dsbr100_device *radio = usb_get_intfdata(intf); | ||
487 | |||
488 | v4l2_device_get(&radio->v4l2_dev); | ||
489 | mutex_lock(&radio->v4l2_lock); | ||
490 | usb_set_intfdata(intf, NULL); | ||
491 | video_unregister_device(&radio->videodev); | ||
492 | v4l2_device_disconnect(&radio->v4l2_dev); | ||
493 | mutex_unlock(&radio->v4l2_lock); | ||
494 | v4l2_device_put(&radio->v4l2_dev); | ||
549 | } | 495 | } |
550 | 496 | ||
497 | |||
551 | /* Suspend device - stop device. */ | 498 | /* Suspend device - stop device. */ |
552 | static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message) | 499 | static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message) |
553 | { | 500 | { |
554 | struct dsbr100_device *radio = usb_get_intfdata(intf); | 501 | struct dsbr100_device *radio = usb_get_intfdata(intf); |
555 | int retval; | 502 | int retval; |
556 | 503 | ||
504 | mutex_lock(&radio->v4l2_lock); | ||
557 | if (radio->status == STARTED) { | 505 | if (radio->status == STARTED) { |
558 | retval = dsbr100_stop(radio); | 506 | retval = dsbr100_stop(radio); |
559 | if (retval < 0) | 507 | if (retval < 0) |
@@ -564,11 +512,9 @@ static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message) | |||
564 | * we set status equal to STARTED. | 512 | * we set status equal to STARTED. |
565 | * On resume we will check status and run radio if needed. | 513 | * On resume we will check status and run radio if needed. |
566 | */ | 514 | */ |
567 | |||
568 | mutex_lock(&radio->lock); | ||
569 | radio->status = STARTED; | 515 | radio->status = STARTED; |
570 | mutex_unlock(&radio->lock); | ||
571 | } | 516 | } |
517 | mutex_unlock(&radio->v4l2_lock); | ||
572 | 518 | ||
573 | dev_info(&intf->dev, "going into suspend..\n"); | 519 | dev_info(&intf->dev, "going into suspend..\n"); |
574 | 520 | ||
@@ -581,11 +527,13 @@ static int usb_dsbr100_resume(struct usb_interface *intf) | |||
581 | struct dsbr100_device *radio = usb_get_intfdata(intf); | 527 | struct dsbr100_device *radio = usb_get_intfdata(intf); |
582 | int retval; | 528 | int retval; |
583 | 529 | ||
530 | mutex_lock(&radio->v4l2_lock); | ||
584 | if (radio->status == STARTED) { | 531 | if (radio->status == STARTED) { |
585 | retval = dsbr100_start(radio); | 532 | retval = dsbr100_start(radio); |
586 | if (retval < 0) | 533 | if (retval < 0) |
587 | dev_warn(&intf->dev, "dsbr100_start failed\n"); | 534 | dev_warn(&intf->dev, "dsbr100_start failed\n"); |
588 | } | 535 | } |
536 | mutex_unlock(&radio->v4l2_lock); | ||
589 | 537 | ||
590 | dev_info(&intf->dev, "coming out of suspend..\n"); | 538 | dev_info(&intf->dev, "coming out of suspend..\n"); |
591 | 539 | ||
@@ -593,9 +541,9 @@ static int usb_dsbr100_resume(struct usb_interface *intf) | |||
593 | } | 541 | } |
594 | 542 | ||
595 | /* free data structures */ | 543 | /* free data structures */ |
596 | static void usb_dsbr100_video_device_release(struct video_device *videodev) | 544 | static void usb_dsbr100_release(struct v4l2_device *v4l2_dev) |
597 | { | 545 | { |
598 | struct dsbr100_device *radio = videodev_to_radio(videodev); | 546 | struct dsbr100_device *radio = v4l2_dev_to_radio(v4l2_dev); |
599 | 547 | ||
600 | v4l2_device_unregister(&radio->v4l2_dev); | 548 | v4l2_device_unregister(&radio->v4l2_dev); |
601 | kfree(radio->transfer_buffer); | 549 | kfree(radio->transfer_buffer); |
@@ -605,7 +553,7 @@ static void usb_dsbr100_video_device_release(struct video_device *videodev) | |||
605 | /* File system interface */ | 553 | /* File system interface */ |
606 | static const struct v4l2_file_operations usb_dsbr100_fops = { | 554 | static const struct v4l2_file_operations usb_dsbr100_fops = { |
607 | .owner = THIS_MODULE, | 555 | .owner = THIS_MODULE, |
608 | .ioctl = video_ioctl2, | 556 | .unlocked_ioctl = video_ioctl2, |
609 | }; | 557 | }; |
610 | 558 | ||
611 | static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = { | 559 | static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = { |
@@ -644,6 +592,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf, | |||
644 | } | 592 | } |
645 | 593 | ||
646 | v4l2_dev = &radio->v4l2_dev; | 594 | v4l2_dev = &radio->v4l2_dev; |
595 | v4l2_dev->release = usb_dsbr100_release; | ||
647 | 596 | ||
648 | retval = v4l2_device_register(&intf->dev, v4l2_dev); | 597 | retval = v4l2_device_register(&intf->dev, v4l2_dev); |
649 | if (retval < 0) { | 598 | if (retval < 0) { |
@@ -653,15 +602,14 @@ static int usb_dsbr100_probe(struct usb_interface *intf, | |||
653 | return retval; | 602 | return retval; |
654 | } | 603 | } |
655 | 604 | ||
605 | mutex_init(&radio->v4l2_lock); | ||
656 | strlcpy(radio->videodev.name, v4l2_dev->name, sizeof(radio->videodev.name)); | 606 | strlcpy(radio->videodev.name, v4l2_dev->name, sizeof(radio->videodev.name)); |
657 | radio->videodev.v4l2_dev = v4l2_dev; | 607 | radio->videodev.v4l2_dev = v4l2_dev; |
658 | radio->videodev.fops = &usb_dsbr100_fops; | 608 | radio->videodev.fops = &usb_dsbr100_fops; |
659 | radio->videodev.ioctl_ops = &usb_dsbr100_ioctl_ops; | 609 | radio->videodev.ioctl_ops = &usb_dsbr100_ioctl_ops; |
660 | radio->videodev.release = usb_dsbr100_video_device_release; | 610 | radio->videodev.release = video_device_release_empty; |
661 | 611 | radio->videodev.lock = &radio->v4l2_lock; | |
662 | mutex_init(&radio->lock); | ||
663 | 612 | ||
664 | radio->removed = 0; | ||
665 | radio->usbdev = interface_to_usbdev(intf); | 613 | radio->usbdev = interface_to_usbdev(intf); |
666 | radio->curfreq = FREQ_MIN * FREQ_MUL; | 614 | radio->curfreq = FREQ_MIN * FREQ_MUL; |
667 | radio->status = STOPPED; | 615 | radio->status = STOPPED; |