aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/si470x/radio-si470x-usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio/si470x/radio-si470x-usb.c')
-rw-r--r--drivers/media/radio/si470x/radio-si470x-usb.c265
1 files changed, 113 insertions, 152 deletions
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c
index b7debb67932a..e9f638761296 100644
--- a/drivers/media/radio/si470x/radio-si470x-usb.c
+++ b/drivers/media/radio/si470x/radio-si470x-usb.c
@@ -367,23 +367,6 @@ static int si470x_get_scratch_page_versions(struct si470x_device *radio)
367 367
368 368
369/************************************************************************** 369/**************************************************************************
370 * General Driver Functions - DISCONNECT_CHECK
371 **************************************************************************/
372
373/*
374 * si470x_disconnect_check - check whether radio disconnects
375 */
376int si470x_disconnect_check(struct si470x_device *radio)
377{
378 if (radio->disconnected)
379 return -EIO;
380 else
381 return 0;
382}
383
384
385
386/**************************************************************************
387 * RDS Driver Functions 370 * RDS Driver Functions
388 **************************************************************************/ 371 **************************************************************************/
389 372
@@ -414,9 +397,6 @@ static void si470x_int_in_callback(struct urb *urb)
414 } 397 }
415 } 398 }
416 399
417 /* safety checks */
418 if (radio->disconnected)
419 return;
420 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) 400 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
421 goto resubmit; 401 goto resubmit;
422 402
@@ -501,112 +481,30 @@ resubmit:
501} 481}
502 482
503 483
504
505/**************************************************************************
506 * File Operations Interface
507 **************************************************************************/
508
509/*
510 * si470x_fops_open - file open
511 */
512int si470x_fops_open(struct file *file) 484int si470x_fops_open(struct file *file)
513{ 485{
514 struct si470x_device *radio = video_drvdata(file); 486 return v4l2_fh_open(file);
515 int retval;
516
517 mutex_lock(&radio->lock);
518 radio->users++;
519
520 retval = usb_autopm_get_interface(radio->intf);
521 if (retval < 0) {
522 radio->users--;
523 retval = -EIO;
524 goto done;
525 }
526
527 if (radio->users == 1) {
528 /* start radio */
529 retval = si470x_start(radio);
530 if (retval < 0) {
531 usb_autopm_put_interface(radio->intf);
532 goto done;
533 }
534
535 /* initialize interrupt urb */
536 usb_fill_int_urb(radio->int_in_urb, radio->usbdev,
537 usb_rcvintpipe(radio->usbdev,
538 radio->int_in_endpoint->bEndpointAddress),
539 radio->int_in_buffer,
540 le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize),
541 si470x_int_in_callback,
542 radio,
543 radio->int_in_endpoint->bInterval);
544
545 radio->int_in_running = 1;
546 mb();
547
548 retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL);
549 if (retval) {
550 dev_info(&radio->intf->dev,
551 "submitting int urb failed (%d)\n", retval);
552 radio->int_in_running = 0;
553 usb_autopm_put_interface(radio->intf);
554 }
555 }
556
557done:
558 mutex_unlock(&radio->lock);
559 return retval;
560} 487}
561 488
562
563/*
564 * si470x_fops_release - file release
565 */
566int si470x_fops_release(struct file *file) 489int si470x_fops_release(struct file *file)
567{ 490{
568 struct si470x_device *radio = video_drvdata(file); 491 return v4l2_fh_release(file);
569 int retval = 0; 492}
570
571 /* safety check */
572 if (!radio) {
573 retval = -ENODEV;
574 goto done;
575 }
576
577 mutex_lock(&radio->lock);
578 radio->users--;
579 if (radio->users == 0) {
580 /* shutdown interrupt handler */
581 if (radio->int_in_running) {
582 radio->int_in_running = 0;
583 if (radio->int_in_urb)
584 usb_kill_urb(radio->int_in_urb);
585 }
586
587 if (radio->disconnected) {
588 video_unregister_device(radio->videodev);
589 kfree(radio->int_in_buffer);
590 kfree(radio->buffer);
591 mutex_unlock(&radio->lock);
592 kfree(radio);
593 goto done;
594 }
595 493
596 /* cancel read processes */ 494static void si470x_usb_release(struct v4l2_device *v4l2_dev)
597 wake_up_interruptible(&radio->read_queue); 495{
496 struct si470x_device *radio =
497 container_of(v4l2_dev, struct si470x_device, v4l2_dev);
598 498
599 /* stop radio */ 499 usb_free_urb(radio->int_in_urb);
600 retval = si470x_stop(radio); 500 v4l2_ctrl_handler_free(&radio->hdl);
601 usb_autopm_put_interface(radio->intf); 501 v4l2_device_unregister(&radio->v4l2_dev);
602 } 502 kfree(radio->int_in_buffer);
603 mutex_unlock(&radio->lock); 503 kfree(radio->buffer);
604done: 504 kfree(radio);
605 return retval;
606} 505}
607 506
608 507
609
610/************************************************************************** 508/**************************************************************************
611 * Video4Linux Interface 509 * Video4Linux Interface
612 **************************************************************************/ 510 **************************************************************************/
@@ -623,13 +521,45 @@ int si470x_vidioc_querycap(struct file *file, void *priv,
623 strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); 521 strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
624 usb_make_path(radio->usbdev, capability->bus_info, 522 usb_make_path(radio->usbdev, capability->bus_info,
625 sizeof(capability->bus_info)); 523 sizeof(capability->bus_info));
626 capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | 524 capability->device_caps = V4L2_CAP_HW_FREQ_SEEK |
627 V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; 525 V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;
628 526 capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS;
629 return 0; 527 return 0;
630} 528}
631 529
632 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}
633 563
634/************************************************************************** 564/**************************************************************************
635 * USB Interface 565 * USB Interface
@@ -653,8 +583,6 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
653 retval = -ENOMEM; 583 retval = -ENOMEM;
654 goto err_initial; 584 goto err_initial;
655 } 585 }
656 radio->users = 0;
657 radio->disconnected = 0;
658 radio->usbdev = interface_to_usbdev(intf); 586 radio->usbdev = interface_to_usbdev(intf);
659 radio->intf = intf; 587 radio->intf = intf;
660 mutex_init(&radio->lock); 588 mutex_init(&radio->lock);
@@ -691,20 +619,35 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
691 goto err_intbuffer; 619 goto err_intbuffer;
692 } 620 }
693 621
694 /* video device allocation and initialization */ 622 radio->v4l2_dev.release = si470x_usb_release;
695 radio->videodev = video_device_alloc(); 623 retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
696 if (!radio->videodev) { 624 if (retval < 0) {
697 retval = -ENOMEM; 625 dev_err(&intf->dev, "couldn't register v4l2_device\n");
698 goto err_urb; 626 goto err_urb;
699 } 627 }
700 memcpy(radio->videodev, &si470x_viddev_template, 628
701 sizeof(si470x_viddev_template)); 629 v4l2_ctrl_handler_init(&radio->hdl, 2);
702 video_set_drvdata(radio->videodev, radio); 630 v4l2_ctrl_new_std(&radio->hdl, &si470x_ctrl_ops,
631 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
632 v4l2_ctrl_new_std(&radio->hdl, &si470x_ctrl_ops,
633 V4L2_CID_AUDIO_VOLUME, 0, 15, 1, 15);
634 if (radio->hdl.error) {
635 retval = radio->hdl.error;
636 dev_err(&intf->dev, "couldn't register control\n");
637 goto err_dev;
638 }
639 radio->videodev = si470x_viddev_template;
640 radio->videodev.ctrl_handler = &radio->hdl;
641 radio->videodev.lock = &radio->lock;
642 radio->videodev.v4l2_dev = &radio->v4l2_dev;
643 radio->videodev.release = video_device_release_empty;
644 set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
645 video_set_drvdata(&radio->videodev, radio);
703 646
704 /* get device and chip versions */ 647 /* get device and chip versions */
705 if (si470x_get_all_registers(radio) < 0) { 648 if (si470x_get_all_registers(radio) < 0) {
706 retval = -EIO; 649 retval = -EIO;
707 goto err_video; 650 goto err_ctrl;
708 } 651 }
709 dev_info(&intf->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", 652 dev_info(&intf->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
710 radio->registers[DEVICEID], radio->registers[CHIPID]); 653 radio->registers[DEVICEID], radio->registers[CHIPID]);
@@ -721,7 +664,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
721 /* get software and hardware versions */ 664 /* get software and hardware versions */
722 if (si470x_get_scratch_page_versions(radio) < 0) { 665 if (si470x_get_scratch_page_versions(radio) < 0) {
723 retval = -EIO; 666 retval = -EIO;
724 goto err_video; 667 goto err_ctrl;
725 } 668 }
726 dev_info(&intf->dev, "software version %d, hardware version %d\n", 669 dev_info(&intf->dev, "software version %d, hardware version %d\n",
727 radio->software_version, radio->hardware_version); 670 radio->software_version, radio->hardware_version);
@@ -764,28 +707,35 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
764 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); 707 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
765 if (!radio->buffer) { 708 if (!radio->buffer) {
766 retval = -EIO; 709 retval = -EIO;
767 goto err_video; 710 goto err_ctrl;
768 } 711 }
769 712
770 /* rds buffer configuration */ 713 /* rds buffer configuration */
771 radio->wr_index = 0; 714 radio->wr_index = 0;
772 radio->rd_index = 0; 715 radio->rd_index = 0;
773 init_waitqueue_head(&radio->read_queue); 716 init_waitqueue_head(&radio->read_queue);
717 usb_set_intfdata(intf, radio);
718
719 /* start radio */
720 retval = si470x_start_usb(radio);
721 if (retval < 0)
722 goto err_all;
774 723
775 /* register video device */ 724 /* register video device */
776 retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, 725 retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
777 radio_nr); 726 radio_nr);
778 if (retval) { 727 if (retval) {
779 dev_warn(&intf->dev, "Could not register video device\n"); 728 dev_err(&intf->dev, "Could not register video device\n");
780 goto err_all; 729 goto err_all;
781 } 730 }
782 usb_set_intfdata(intf, radio);
783 731
784 return 0; 732 return 0;
785err_all: 733err_all:
786 kfree(radio->buffer); 734 kfree(radio->buffer);
787err_video: 735err_ctrl:
788 video_device_release(radio->videodev); 736 v4l2_ctrl_handler_free(&radio->hdl);
737err_dev:
738 v4l2_device_unregister(&radio->v4l2_dev);
789err_urb: 739err_urb:
790 usb_free_urb(radio->int_in_urb); 740 usb_free_urb(radio->int_in_urb);
791err_intbuffer: 741err_intbuffer:
@@ -803,8 +753,22 @@ err_initial:
803static int si470x_usb_driver_suspend(struct usb_interface *intf, 753static int si470x_usb_driver_suspend(struct usb_interface *intf,
804 pm_message_t message) 754 pm_message_t message)
805{ 755{
756 struct si470x_device *radio = usb_get_intfdata(intf);
757
806 dev_info(&intf->dev, "suspending now...\n"); 758 dev_info(&intf->dev, "suspending now...\n");
807 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);
808 return 0; 772 return 0;
809} 773}
810 774
@@ -814,9 +778,12 @@ static int si470x_usb_driver_suspend(struct usb_interface *intf,
814 */ 778 */
815static int si470x_usb_driver_resume(struct usb_interface *intf) 779static int si470x_usb_driver_resume(struct usb_interface *intf)
816{ 780{
781 struct si470x_device *radio = usb_get_intfdata(intf);
782
817 dev_info(&intf->dev, "resuming now...\n"); 783 dev_info(&intf->dev, "resuming now...\n");
818 784
819 return 0; 785 /* start radio */
786 return si470x_start_usb(radio);
820} 787}
821 788
822 789
@@ -828,28 +795,22 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
828 struct si470x_device *radio = usb_get_intfdata(intf); 795 struct si470x_device *radio = usb_get_intfdata(intf);
829 796
830 mutex_lock(&radio->lock); 797 mutex_lock(&radio->lock);
831 radio->disconnected = 1; 798 v4l2_device_disconnect(&radio->v4l2_dev);
799 video_unregister_device(&radio->videodev);
832 usb_set_intfdata(intf, NULL); 800 usb_set_intfdata(intf, NULL);
833 if (radio->users == 0) { 801 mutex_unlock(&radio->lock);
834 /* set led to disconnect state */ 802 v4l2_device_put(&radio->v4l2_dev);
835 si470x_set_led_state(radio, BLINK_ORANGE_LED);
836
837 /* Free data structures. */
838 usb_free_urb(radio->int_in_urb);
839
840 kfree(radio->int_in_buffer);
841 video_unregister_device(radio->videodev);
842 kfree(radio->buffer);
843 mutex_unlock(&radio->lock);
844 kfree(radio);
845 } else {
846 mutex_unlock(&radio->lock);
847 }
848} 803}
849 804
850 805
851/* 806/*
852 * 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.
853 */ 814 */
854static struct usb_driver si470x_usb_driver = { 815static struct usb_driver si470x_usb_driver = {
855 .name = DRIVER_NAME, 816 .name = DRIVER_NAME,
@@ -857,8 +818,8 @@ static struct usb_driver si470x_usb_driver = {
857 .disconnect = si470x_usb_driver_disconnect, 818 .disconnect = si470x_usb_driver_disconnect,
858 .suspend = si470x_usb_driver_suspend, 819 .suspend = si470x_usb_driver_suspend,
859 .resume = si470x_usb_driver_resume, 820 .resume = si470x_usb_driver_resume,
821 .reset_resume = si470x_usb_driver_resume,
860 .id_table = si470x_usb_driver_id_table, 822 .id_table = si470x_usb_driver_id_table,
861 .supports_autosuspend = 1,
862}; 823};
863 824
864module_usb_driver(si470x_usb_driver); 825module_usb_driver(si470x_usb_driver);