aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/si470x
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio/si470x')
-rw-r--r--drivers/media/radio/si470x/radio-si470x-common.c1
-rw-r--r--drivers/media/radio/si470x/radio-si470x-usb.c149
2 files changed, 70 insertions, 80 deletions
diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c
index b9a44d4a032f..969cf494d85b 100644
--- a/drivers/media/radio/si470x/radio-si470x-common.c
+++ b/drivers/media/radio/si470x/radio-si470x-common.c
@@ -570,7 +570,6 @@ static int si470x_s_ctrl(struct v4l2_ctrl *ctrl)
570 else 570 else
571 radio->registers[POWERCFG] |= POWERCFG_DMUTE; 571 radio->registers[POWERCFG] |= POWERCFG_DMUTE;
572 return si470x_set_register(radio, POWERCFG); 572 return si470x_set_register(radio, POWERCFG);
573 break;
574 default: 573 default:
575 return -EINVAL; 574 return -EINVAL;
576 } 575 }
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c
index f133c3dea648..e9f638761296 100644
--- a/drivers/media/radio/si470x/radio-si470x-usb.c
+++ b/drivers/media/radio/si470x/radio-si470x-usb.c
@@ -481,91 +481,20 @@ resubmit:
481} 481}
482 482
483 483
484
485/**************************************************************************
486 * File Operations Interface
487 **************************************************************************/
488
489/*
490 * si470x_fops_open - file open
491 */
492int si470x_fops_open(struct file *file) 484int si470x_fops_open(struct file *file)
493{ 485{
494 struct si470x_device *radio = video_drvdata(file); 486 return v4l2_fh_open(file);
495 int retval = v4l2_fh_open(file);
496
497 if (retval)
498 return retval;
499
500 retval = usb_autopm_get_interface(radio->intf);
501 if (retval < 0)
502 goto done;
503
504 if (v4l2_fh_is_singular_file(file)) {
505 /* start radio */
506 retval = si470x_start(radio);
507 if (retval < 0) {
508 usb_autopm_put_interface(radio->intf);
509 goto done;
510 }
511
512 /* initialize interrupt urb */
513 usb_fill_int_urb(radio->int_in_urb, radio->usbdev,
514 usb_rcvintpipe(radio->usbdev,
515 radio->int_in_endpoint->bEndpointAddress),
516 radio->int_in_buffer,
517 le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize),
518 si470x_int_in_callback,
519 radio,
520 radio->int_in_endpoint->bInterval);
521
522 radio->int_in_running = 1;
523 mb();
524
525 retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL);
526 if (retval) {
527 dev_info(&radio->intf->dev,
528 "submitting int urb failed (%d)\n", retval);
529 radio->int_in_running = 0;
530 usb_autopm_put_interface(radio->intf);
531 }
532 }
533
534done:
535 if (retval)
536 v4l2_fh_release(file);
537 return retval;
538} 487}
539 488
540
541/*
542 * si470x_fops_release - file release
543 */
544int si470x_fops_release(struct file *file) 489int si470x_fops_release(struct file *file)
545{ 490{
546 struct si470x_device *radio = video_drvdata(file);
547
548 if (v4l2_fh_is_singular_file(file)) {
549 /* shutdown interrupt handler */
550 if (radio->int_in_running) {
551 radio->int_in_running = 0;
552 if (radio->int_in_urb)
553 usb_kill_urb(radio->int_in_urb);
554 }
555
556 /* cancel read processes */
557 wake_up_interruptible(&radio->read_queue);
558
559 /* stop radio */
560 si470x_stop(radio);
561 usb_autopm_put_interface(radio->intf);
562 }
563 return v4l2_fh_release(file); 491 return v4l2_fh_release(file);
564} 492}
565 493
566static void si470x_usb_release(struct video_device *vdev) 494static void si470x_usb_release(struct v4l2_device *v4l2_dev)
567{ 495{
568 struct si470x_device *radio = video_get_drvdata(vdev); 496 struct si470x_device *radio =
497 container_of(v4l2_dev, struct si470x_device, v4l2_dev);
569 498
570 usb_free_urb(radio->int_in_urb); 499 usb_free_urb(radio->int_in_urb);
571 v4l2_ctrl_handler_free(&radio->hdl); 500 v4l2_ctrl_handler_free(&radio->hdl);
@@ -599,6 +528,38 @@ int si470x_vidioc_querycap(struct file *file, void *priv,
599} 528}
600 529
601 530
531static int si470x_start_usb(struct si470x_device *radio)
532{
533 int retval;
534
535 /* start radio */
536 retval = si470x_start(radio);
537 if (retval < 0)
538 return retval;
539
540 v4l2_ctrl_handler_setup(&radio->hdl);
541
542 /* initialize interrupt urb */
543 usb_fill_int_urb(radio->int_in_urb, radio->usbdev,
544 usb_rcvintpipe(radio->usbdev,
545 radio->int_in_endpoint->bEndpointAddress),
546 radio->int_in_buffer,
547 le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize),
548 si470x_int_in_callback,
549 radio,
550 radio->int_in_endpoint->bInterval);
551
552 radio->int_in_running = 1;
553 mb();
554
555 retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL);
556 if (retval) {
557 dev_info(&radio->intf->dev,
558 "submitting int urb failed (%d)\n", retval);
559 radio->int_in_running = 0;
560 }
561 return retval;
562}
602 563
603/************************************************************************** 564/**************************************************************************
604 * USB Interface 565 * USB Interface
@@ -658,6 +619,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
658 goto err_intbuffer; 619 goto err_intbuffer;
659 } 620 }
660 621
622 radio->v4l2_dev.release = si470x_usb_release;
661 retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev); 623 retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
662 if (retval < 0) { 624 if (retval < 0) {
663 dev_err(&intf->dev, "couldn't register v4l2_device\n"); 625 dev_err(&intf->dev, "couldn't register v4l2_device\n");
@@ -678,7 +640,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
678 radio->videodev.ctrl_handler = &radio->hdl; 640 radio->videodev.ctrl_handler = &radio->hdl;
679 radio->videodev.lock = &radio->lock; 641 radio->videodev.lock = &radio->lock;
680 radio->videodev.v4l2_dev = &radio->v4l2_dev; 642 radio->videodev.v4l2_dev = &radio->v4l2_dev;
681 radio->videodev.release = si470x_usb_release; 643 radio->videodev.release = video_device_release_empty;
682 set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags); 644 set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
683 video_set_drvdata(&radio->videodev, radio); 645 video_set_drvdata(&radio->videodev, radio);
684 646
@@ -754,11 +716,16 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
754 init_waitqueue_head(&radio->read_queue); 716 init_waitqueue_head(&radio->read_queue);
755 usb_set_intfdata(intf, radio); 717 usb_set_intfdata(intf, radio);
756 718
719 /* start radio */
720 retval = si470x_start_usb(radio);
721 if (retval < 0)
722 goto err_all;
723
757 /* register video device */ 724 /* register video device */
758 retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO, 725 retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
759 radio_nr); 726 radio_nr);
760 if (retval) { 727 if (retval) {
761 dev_warn(&intf->dev, "Could not register video device\n"); 728 dev_err(&intf->dev, "Could not register video device\n");
762 goto err_all; 729 goto err_all;
763 } 730 }
764 731
@@ -786,8 +753,22 @@ err_initial:
786static int si470x_usb_driver_suspend(struct usb_interface *intf, 753static int si470x_usb_driver_suspend(struct usb_interface *intf,
787 pm_message_t message) 754 pm_message_t message)
788{ 755{
756 struct si470x_device *radio = usb_get_intfdata(intf);
757
789 dev_info(&intf->dev, "suspending now...\n"); 758 dev_info(&intf->dev, "suspending now...\n");
790 759
760 /* shutdown interrupt handler */
761 if (radio->int_in_running) {
762 radio->int_in_running = 0;
763 if (radio->int_in_urb)
764 usb_kill_urb(radio->int_in_urb);
765 }
766
767 /* cancel read processes */
768 wake_up_interruptible(&radio->read_queue);
769
770 /* stop radio */
771 si470x_stop(radio);
791 return 0; 772 return 0;
792} 773}
793 774
@@ -797,9 +778,12 @@ static int si470x_usb_driver_suspend(struct usb_interface *intf,
797 */ 778 */
798static int si470x_usb_driver_resume(struct usb_interface *intf) 779static int si470x_usb_driver_resume(struct usb_interface *intf)
799{ 780{
781 struct si470x_device *radio = usb_get_intfdata(intf);
782
800 dev_info(&intf->dev, "resuming now...\n"); 783 dev_info(&intf->dev, "resuming now...\n");
801 784
802 return 0; 785 /* start radio */
786 return si470x_start_usb(radio);
803} 787}
804 788
805 789
@@ -815,11 +799,18 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
815 video_unregister_device(&radio->videodev); 799 video_unregister_device(&radio->videodev);
816 usb_set_intfdata(intf, NULL); 800 usb_set_intfdata(intf, NULL);
817 mutex_unlock(&radio->lock); 801 mutex_unlock(&radio->lock);
802 v4l2_device_put(&radio->v4l2_dev);
818} 803}
819 804
820 805
821/* 806/*
822 * si470x_usb_driver - usb driver interface 807 * si470x_usb_driver - usb driver interface
808 *
809 * A note on suspend/resume: this driver had only empty suspend/resume
810 * functions, and when I tried to test suspend/resume it always disconnected
811 * instead of resuming (using my ADS InstantFM stick). So I've decided to
812 * remove these callbacks until someone else with better hardware can
813 * implement and test this.
823 */ 814 */
824static struct usb_driver si470x_usb_driver = { 815static struct usb_driver si470x_usb_driver = {
825 .name = DRIVER_NAME, 816 .name = DRIVER_NAME,
@@ -827,8 +818,8 @@ static struct usb_driver si470x_usb_driver = {
827 .disconnect = si470x_usb_driver_disconnect, 818 .disconnect = si470x_usb_driver_disconnect,
828 .suspend = si470x_usb_driver_suspend, 819 .suspend = si470x_usb_driver_suspend,
829 .resume = si470x_usb_driver_resume, 820 .resume = si470x_usb_driver_resume,
821 .reset_resume = si470x_usb_driver_resume,
830 .id_table = si470x_usb_driver_id_table, 822 .id_table = si470x_usb_driver_id_table,
831 .supports_autosuspend = 1,
832}; 823};
833 824
834module_usb_driver(si470x_usb_driver); 825module_usb_driver(si470x_usb_driver);