aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-si470x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio/radio-si470x.c')
-rw-r--r--drivers/media/radio/radio-si470x.c483
1 files changed, 345 insertions, 138 deletions
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
index 77354ca6e8e9..dc93a882b385 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -24,6 +24,19 @@
24 24
25 25
26/* 26/*
27 * User Notes:
28 * - USB Audio is provided by the alsa snd_usb_audio module.
29 * For listing you have to redirect the sound, for example using:
30 * arecord -D hw:1,0 -r96000 -c2 -f S16_LE | artsdsp aplay -B -
31 * - regarding module parameters in /sys/module/radio_si470x/parameters:
32 * the contents of read-only files (0444) are not updated, even if
33 * space, band and de are changed using private video controls
34 * - increase tune_timeout, if you often get -EIO errors
35 * - hw_freq_seek returns -EAGAIN, when timed out or band limit is reached
36 */
37
38
39/*
27 * History: 40 * History:
28 * 2008-01-12 Tobias Lorenz <tobias.lorenz@gmx.net> 41 * 2008-01-12 Tobias Lorenz <tobias.lorenz@gmx.net>
29 * Version 1.0.0 42 * Version 1.0.0
@@ -85,10 +98,14 @@
85 * Oliver Neukum <oliver@neukum.org> 98 * Oliver Neukum <oliver@neukum.org>
86 * Version 1.0.7 99 * Version 1.0.7
87 * - usb autosuspend support 100 * - usb autosuspend support
88 * - unplugging fixed 101 * - unplugging fixed
102 * 2008-05-07 Tobias Lorenz <tobias.lorenz@gmx.net>
103 * Version 1.0.8
104 * - hardware frequency seek support
105 * - afc indication
106 * - more safety checks, let si470x_get_freq return errno
89 * 107 *
90 * ToDo: 108 * ToDo:
91 * - add seeking support
92 * - add firmware download/update support 109 * - add firmware download/update support
93 * - RDS support: interrupt mode, instead of polling 110 * - RDS support: interrupt mode, instead of polling
94 * - add LED status output (check if that's not already done in firmware) 111 * - add LED status output (check if that's not already done in firmware)
@@ -98,10 +115,10 @@
98/* driver definitions */ 115/* driver definitions */
99#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>" 116#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
100#define DRIVER_NAME "radio-si470x" 117#define DRIVER_NAME "radio-si470x"
101#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 7) 118#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 8)
102#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" 119#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
103#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" 120#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
104#define DRIVER_VERSION "1.0.7" 121#define DRIVER_VERSION "1.0.8"
105 122
106 123
107/* kernel includes */ 124/* kernel includes */
@@ -175,6 +192,11 @@ static unsigned int tune_timeout = 3000;
175module_param(tune_timeout, uint, 0); 192module_param(tune_timeout, uint, 0);
176MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*"); 193MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");
177 194
195/* Seek timeout */
196static unsigned int seek_timeout = 5000;
197module_param(seek_timeout, uint, 0);
198MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*");
199
178/* RDS buffer blocks */ 200/* RDS buffer blocks */
179static unsigned int rds_buf = 100; 201static unsigned int rds_buf = 100;
180module_param(rds_buf, uint, 0); 202module_param(rds_buf, uint, 0);
@@ -425,7 +447,8 @@ struct si470x_device {
425 447
426 /* driver management */ 448 /* driver management */
427 unsigned int users; 449 unsigned int users;
428 unsigned char disconnected; 450 unsigned char disconnected;
451 struct mutex disconnect_lock;
429 452
430 /* Silabs internal registers (0..15) */ 453 /* Silabs internal registers (0..15) */
431 unsigned short registers[RADIO_REGISTER_NUM]; 454 unsigned short registers[RADIO_REGISTER_NUM];
@@ -442,12 +465,6 @@ struct si470x_device {
442 465
443 466
444/* 467/*
445 * Lock to prevent kfree of data before all users have releases the device.
446 */
447static DEFINE_MUTEX(open_close_lock);
448
449
450/*
451 * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, 468 * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW,
452 * 62.5 kHz otherwise. 469 * 62.5 kHz otherwise.
453 * The tuner is able to have a channel spacing of 50, 100 or 200 kHz. 470 * The tuner is able to have a channel spacing of 50, 100 or 200 kHz.
@@ -476,11 +493,11 @@ static int si470x_get_report(struct si470x_device *radio, void *buf, int size)
476 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, 493 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
477 report[0], 2, 494 report[0], 2,
478 buf, size, usb_timeout); 495 buf, size, usb_timeout);
496
479 if (retval < 0) 497 if (retval < 0)
480 printk(KERN_WARNING DRIVER_NAME 498 printk(KERN_WARNING DRIVER_NAME
481 ": si470x_get_report: usb_control_msg returned %d\n", 499 ": si470x_get_report: usb_control_msg returned %d\n",
482 retval); 500 retval);
483
484 return retval; 501 return retval;
485} 502}
486 503
@@ -499,11 +516,11 @@ static int si470x_set_report(struct si470x_device *radio, void *buf, int size)
499 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, 516 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
500 report[0], 2, 517 report[0], 2,
501 buf, size, usb_timeout); 518 buf, size, usb_timeout);
519
502 if (retval < 0) 520 if (retval < 0)
503 printk(KERN_WARNING DRIVER_NAME 521 printk(KERN_WARNING DRIVER_NAME
504 ": si470x_set_report: usb_control_msg returned %d\n", 522 ": si470x_set_report: usb_control_msg returned %d\n",
505 retval); 523 retval);
506
507 return retval; 524 return retval;
508} 525}
509 526
@@ -521,8 +538,7 @@ static int si470x_get_register(struct si470x_device *radio, int regnr)
521 retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); 538 retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
522 539
523 if (retval >= 0) 540 if (retval >= 0)
524 radio->registers[regnr] = be16_to_cpu(get_unaligned( 541 radio->registers[regnr] = get_unaligned_be16(&buf[1]);
525 (unsigned short *) &buf[1]));
526 542
527 return (retval < 0) ? -EINVAL : 0; 543 return (retval < 0) ? -EINVAL : 0;
528} 544}
@@ -537,8 +553,7 @@ static int si470x_set_register(struct si470x_device *radio, int regnr)
537 int retval; 553 int retval;
538 554
539 buf[0] = REGISTER_REPORT(regnr); 555 buf[0] = REGISTER_REPORT(regnr);
540 put_unaligned(cpu_to_be16(radio->registers[regnr]), 556 put_unaligned_be16(radio->registers[regnr], &buf[1]);
541 (unsigned short *) &buf[1]);
542 557
543 retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); 558 retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
544 559
@@ -561,9 +576,8 @@ static int si470x_get_all_registers(struct si470x_device *radio)
561 576
562 if (retval >= 0) 577 if (retval >= 0)
563 for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++) 578 for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)
564 radio->registers[regnr] = be16_to_cpu(get_unaligned( 579 radio->registers[regnr] = get_unaligned_be16(
565 (unsigned short *) 580 &buf[regnr * RADIO_REGISTER_SIZE + 1]);
566 &buf[regnr * RADIO_REGISTER_SIZE + 1]));
567 581
568 return (retval < 0) ? -EINVAL : 0; 582 return (retval < 0) ? -EINVAL : 0;
569} 583}
@@ -585,7 +599,7 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
585 usb_rcvintpipe(radio->usbdev, 1), 599 usb_rcvintpipe(radio->usbdev, 1),
586 (void *) &buf, sizeof(buf), &size, usb_timeout); 600 (void *) &buf, sizeof(buf), &size, usb_timeout);
587 if (size != sizeof(buf)) 601 if (size != sizeof(buf))
588 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " 602 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
589 "return size differs: %d != %zu\n", size, sizeof(buf)); 603 "return size differs: %d != %zu\n", size, sizeof(buf));
590 if (retval < 0) 604 if (retval < 0)
591 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " 605 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
@@ -594,8 +608,8 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
594 if (retval >= 0) 608 if (retval >= 0)
595 for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) 609 for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
596 radio->registers[STATUSRSSI + regnr] = 610 radio->registers[STATUSRSSI + regnr] =
597 be16_to_cpu(get_unaligned((unsigned short *) 611 get_unaligned_be16(
598 &buf[regnr * RADIO_REGISTER_SIZE + 1])); 612 &buf[regnr * RADIO_REGISTER_SIZE + 1]);
599 613
600 return (retval < 0) ? -EINVAL : 0; 614 return (retval < 0) ? -EINVAL : 0;
601} 615}
@@ -615,33 +629,39 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
615 radio->registers[CHANNEL] |= CHANNEL_TUNE | chan; 629 radio->registers[CHANNEL] |= CHANNEL_TUNE | chan;
616 retval = si470x_set_register(radio, CHANNEL); 630 retval = si470x_set_register(radio, CHANNEL);
617 if (retval < 0) 631 if (retval < 0)
618 return retval; 632 goto done;
619 633
620 /* wait till seek operation has completed */ 634 /* wait till tune operation has completed */
621 timeout = jiffies + msecs_to_jiffies(tune_timeout); 635 timeout = jiffies + msecs_to_jiffies(tune_timeout);
622 do { 636 do {
623 retval = si470x_get_register(radio, STATUSRSSI); 637 retval = si470x_get_register(radio, STATUSRSSI);
624 if (retval < 0) 638 if (retval < 0)
625 return retval; 639 goto stop;
626 timed_out = time_after(jiffies, timeout); 640 timed_out = time_after(jiffies, timeout);
627 } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && 641 } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
628 (!timed_out)); 642 (!timed_out));
643 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
644 printk(KERN_WARNING DRIVER_NAME ": tune does not complete\n");
629 if (timed_out) 645 if (timed_out)
630 printk(KERN_WARNING DRIVER_NAME 646 printk(KERN_WARNING DRIVER_NAME
631 ": seek does not finish after %u ms\n", tune_timeout); 647 ": tune timed out after %u ms\n", tune_timeout);
632 648
649stop:
633 /* stop tuning */ 650 /* stop tuning */
634 radio->registers[CHANNEL] &= ~CHANNEL_TUNE; 651 radio->registers[CHANNEL] &= ~CHANNEL_TUNE;
635 return si470x_set_register(radio, CHANNEL); 652 retval = si470x_set_register(radio, CHANNEL);
653
654done:
655 return retval;
636} 656}
637 657
638 658
639/* 659/*
640 * si470x_get_freq - get the frequency 660 * si470x_get_freq - get the frequency
641 */ 661 */
642static unsigned int si470x_get_freq(struct si470x_device *radio) 662static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq)
643{ 663{
644 unsigned int spacing, band_bottom, freq; 664 unsigned int spacing, band_bottom;
645 unsigned short chan; 665 unsigned short chan;
646 int retval; 666 int retval;
647 667
@@ -667,14 +687,12 @@ static unsigned int si470x_get_freq(struct si470x_device *radio)
667 687
668 /* read channel */ 688 /* read channel */
669 retval = si470x_get_register(radio, READCHAN); 689 retval = si470x_get_register(radio, READCHAN);
670 if (retval < 0)
671 return retval;
672 chan = radio->registers[READCHAN] & READCHAN_READCHAN; 690 chan = radio->registers[READCHAN] & READCHAN_READCHAN;
673 691
674 /* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */ 692 /* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */
675 freq = chan * spacing + band_bottom; 693 *freq = chan * spacing + band_bottom;
676 694
677 return freq; 695 return retval;
678} 696}
679 697
680 698
@@ -714,6 +732,62 @@ static int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
714 732
715 733
716/* 734/*
735 * si470x_set_seek - set seek
736 */
737static int si470x_set_seek(struct si470x_device *radio,
738 unsigned int wrap_around, unsigned int seek_upward)
739{
740 int retval = 0;
741 unsigned long timeout;
742 bool timed_out = 0;
743
744 /* start seeking */
745 radio->registers[POWERCFG] |= POWERCFG_SEEK;
746 if (wrap_around == 1)
747 radio->registers[POWERCFG] &= ~POWERCFG_SKMODE;
748 else
749 radio->registers[POWERCFG] |= POWERCFG_SKMODE;
750 if (seek_upward == 1)
751 radio->registers[POWERCFG] |= POWERCFG_SEEKUP;
752 else
753 radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP;
754 retval = si470x_set_register(radio, POWERCFG);
755 if (retval < 0)
756 goto done;
757
758 /* wait till seek operation has completed */
759 timeout = jiffies + msecs_to_jiffies(seek_timeout);
760 do {
761 retval = si470x_get_register(radio, STATUSRSSI);
762 if (retval < 0)
763 goto stop;
764 timed_out = time_after(jiffies, timeout);
765 } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
766 (!timed_out));
767 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
768 printk(KERN_WARNING DRIVER_NAME ": seek does not complete\n");
769 if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
770 printk(KERN_WARNING DRIVER_NAME
771 ": seek failed / band limit reached\n");
772 if (timed_out)
773 printk(KERN_WARNING DRIVER_NAME
774 ": seek timed out after %u ms\n", seek_timeout);
775
776stop:
777 /* stop seeking */
778 radio->registers[POWERCFG] &= ~POWERCFG_SEEK;
779 retval = si470x_set_register(radio, POWERCFG);
780
781done:
782 /* try again, if timed out */
783 if ((retval == 0) && timed_out)
784 retval = -EAGAIN;
785
786 return retval;
787}
788
789
790/*
717 * si470x_start - switch on radio 791 * si470x_start - switch on radio
718 */ 792 */
719static int si470x_start(struct si470x_device *radio) 793static int si470x_start(struct si470x_device *radio)
@@ -725,27 +799,30 @@ static int si470x_start(struct si470x_device *radio)
725 POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM; 799 POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM;
726 retval = si470x_set_register(radio, POWERCFG); 800 retval = si470x_set_register(radio, POWERCFG);
727 if (retval < 0) 801 if (retval < 0)
728 return retval; 802 goto done;
729 803
730 /* sysconfig 1 */ 804 /* sysconfig 1 */
731 radio->registers[SYSCONFIG1] = SYSCONFIG1_DE; 805 radio->registers[SYSCONFIG1] = SYSCONFIG1_DE;
732 retval = si470x_set_register(radio, SYSCONFIG1); 806 retval = si470x_set_register(radio, SYSCONFIG1);
733 if (retval < 0) 807 if (retval < 0)
734 return retval; 808 goto done;
735 809
736 /* sysconfig 2 */ 810 /* sysconfig 2 */
737 radio->registers[SYSCONFIG2] = 811 radio->registers[SYSCONFIG2] =
738 (0x3f << 8) | /* SEEKTH */ 812 (0x3f << 8) | /* SEEKTH */
739 (band << 6) | /* BAND */ 813 ((band << 6) & SYSCONFIG2_BAND) | /* BAND */
740 (space << 4) | /* SPACE */ 814 ((space << 4) & SYSCONFIG2_SPACE) | /* SPACE */
741 15; /* VOLUME (max) */ 815 15; /* VOLUME (max) */
742 retval = si470x_set_register(radio, SYSCONFIG2); 816 retval = si470x_set_register(radio, SYSCONFIG2);
743 if (retval < 0) 817 if (retval < 0)
744 return retval; 818 goto done;
745 819
746 /* reset last channel */ 820 /* reset last channel */
747 return si470x_set_chan(radio, 821 retval = si470x_set_chan(radio,
748 radio->registers[CHANNEL] & CHANNEL_CHAN); 822 radio->registers[CHANNEL] & CHANNEL_CHAN);
823
824done:
825 return retval;
749} 826}
750 827
751 828
@@ -760,13 +837,16 @@ static int si470x_stop(struct si470x_device *radio)
760 radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS; 837 radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
761 retval = si470x_set_register(radio, SYSCONFIG1); 838 retval = si470x_set_register(radio, SYSCONFIG1);
762 if (retval < 0) 839 if (retval < 0)
763 return retval; 840 goto done;
764 841
765 /* powercfg */ 842 /* powercfg */
766 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; 843 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
767 /* POWERCFG_ENABLE has to automatically go low */ 844 /* POWERCFG_ENABLE has to automatically go low */
768 radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE; 845 radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE;
769 return si470x_set_register(radio, POWERCFG); 846 retval = si470x_set_register(radio, POWERCFG);
847
848done:
849 return retval;
770} 850}
771 851
772 852
@@ -843,7 +923,7 @@ static void si470x_rds(struct si470x_device *radio)
843 }; 923 };
844 924
845 /* Fill the V4L2 RDS buffer */ 925 /* Fill the V4L2 RDS buffer */
846 put_unaligned(cpu_to_le16(rds), (unsigned short *) &tmpbuf); 926 put_unaligned_le16(rds, &tmpbuf);
847 tmpbuf[2] = blocknum; /* offset name */ 927 tmpbuf[2] = blocknum; /* offset name */
848 tmpbuf[2] |= blocknum << 3; /* received offset */ 928 tmpbuf[2] |= blocknum << 3; /* received offset */
849 if (bler > max_rds_errors) 929 if (bler > max_rds_errors)
@@ -883,8 +963,9 @@ static void si470x_work(struct work_struct *work)
883 struct si470x_device *radio = container_of(work, struct si470x_device, 963 struct si470x_device *radio = container_of(work, struct si470x_device,
884 work.work); 964 work.work);
885 965
886 if (radio->disconnected) 966 /* safety checks */
887 return; 967 if (radio->disconnected)
968 return;
888 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) 969 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
889 return; 970 return;
890 971
@@ -917,11 +998,15 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf,
917 998
918 /* block if no new data available */ 999 /* block if no new data available */
919 while (radio->wr_index == radio->rd_index) { 1000 while (radio->wr_index == radio->rd_index) {
920 if (file->f_flags & O_NONBLOCK) 1001 if (file->f_flags & O_NONBLOCK) {
921 return -EWOULDBLOCK; 1002 retval = -EWOULDBLOCK;
1003 goto done;
1004 }
922 if (wait_event_interruptible(radio->read_queue, 1005 if (wait_event_interruptible(radio->read_queue,
923 radio->wr_index != radio->rd_index) < 0) 1006 radio->wr_index != radio->rd_index) < 0) {
924 return -EINTR; 1007 retval = -EINTR;
1008 goto done;
1009 }
925 } 1010 }
926 1011
927 /* calculate block count from byte count */ 1012 /* calculate block count from byte count */
@@ -950,6 +1035,7 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf,
950 } 1035 }
951 mutex_unlock(&radio->lock); 1036 mutex_unlock(&radio->lock);
952 1037
1038done:
953 return retval; 1039 return retval;
954} 1040}
955 1041
@@ -961,6 +1047,7 @@ static unsigned int si470x_fops_poll(struct file *file,
961 struct poll_table_struct *pts) 1047 struct poll_table_struct *pts)
962{ 1048{
963 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1049 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1050 int retval = 0;
964 1051
965 /* switch on rds reception */ 1052 /* switch on rds reception */
966 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { 1053 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) {
@@ -972,9 +1059,9 @@ static unsigned int si470x_fops_poll(struct file *file,
972 poll_wait(file, &radio->read_queue, pts); 1059 poll_wait(file, &radio->read_queue, pts);
973 1060
974 if (radio->rd_index != radio->wr_index) 1061 if (radio->rd_index != radio->wr_index)
975 return POLLIN | POLLRDNORM; 1062 retval = POLLIN | POLLRDNORM;
976 1063
977 return 0; 1064 return retval;
978} 1065}
979 1066
980 1067
@@ -991,17 +1078,18 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
991 retval = usb_autopm_get_interface(radio->intf); 1078 retval = usb_autopm_get_interface(radio->intf);
992 if (retval < 0) { 1079 if (retval < 0) {
993 radio->users--; 1080 radio->users--;
994 return -EIO; 1081 retval = -EIO;
1082 goto done;
995 } 1083 }
996 1084
997 if (radio->users == 1) { 1085 if (radio->users == 1) {
998 retval = si470x_start(radio); 1086 retval = si470x_start(radio);
999 if (retval < 0) 1087 if (retval < 0)
1000 usb_autopm_put_interface(radio->intf); 1088 usb_autopm_put_interface(radio->intf);
1001 return retval;
1002 } 1089 }
1003 1090
1004 return 0; 1091done:
1092 return retval;
1005} 1093}
1006 1094
1007 1095
@@ -1011,20 +1099,23 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
1011static int si470x_fops_release(struct inode *inode, struct file *file) 1099static int si470x_fops_release(struct inode *inode, struct file *file)
1012{ 1100{
1013 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1101 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1014 int retval = 0; 1102 int retval = 0;
1015 1103
1016 if (!radio) 1104 /* safety check */
1017 return -ENODEV; 1105 if (!radio) {
1106 retval = -ENODEV;
1107 goto done;
1108 }
1018 1109
1019 mutex_lock(&open_close_lock); 1110 mutex_lock(&radio->disconnect_lock);
1020 radio->users--; 1111 radio->users--;
1021 if (radio->users == 0) { 1112 if (radio->users == 0) {
1022 if (radio->disconnected) { 1113 if (radio->disconnected) {
1023 video_unregister_device(radio->videodev); 1114 video_unregister_device(radio->videodev);
1024 kfree(radio->buffer); 1115 kfree(radio->buffer);
1025 kfree(radio); 1116 kfree(radio);
1026 goto done; 1117 goto unlock;
1027 } 1118 }
1028 1119
1029 /* stop rds reception */ 1120 /* stop rds reception */
1030 cancel_delayed_work_sync(&radio->work); 1121 cancel_delayed_work_sync(&radio->work);
@@ -1036,9 +1127,11 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
1036 usb_autopm_put_interface(radio->intf); 1127 usb_autopm_put_interface(radio->intf);
1037 } 1128 }
1038 1129
1130unlock:
1131 mutex_unlock(&radio->disconnect_lock);
1132
1039done: 1133done:
1040 mutex_unlock(&open_close_lock); 1134 return retval;
1041 return retval;
1042} 1135}
1043 1136
1044 1137
@@ -1116,7 +1209,8 @@ static int si470x_vidioc_querycap(struct file *file, void *priv,
1116 strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); 1209 strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
1117 sprintf(capability->bus_info, "USB"); 1210 sprintf(capability->bus_info, "USB");
1118 capability->version = DRIVER_KERNEL_VERSION; 1211 capability->version = DRIVER_KERNEL_VERSION;
1119 capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; 1212 capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
1213 V4L2_CAP_TUNER | V4L2_CAP_RADIO;
1120 1214
1121 return 0; 1215 return 0;
1122} 1216}
@@ -1125,7 +1219,7 @@ static int si470x_vidioc_querycap(struct file *file, void *priv,
1125/* 1219/*
1126 * si470x_vidioc_g_input - get input 1220 * si470x_vidioc_g_input - get input
1127 */ 1221 */
1128static int si470x_vidioc_g_input(struct file *filp, void *priv, 1222static int si470x_vidioc_g_input(struct file *file, void *priv,
1129 unsigned int *i) 1223 unsigned int *i)
1130{ 1224{
1131 *i = 0; 1225 *i = 0;
@@ -1137,12 +1231,18 @@ static int si470x_vidioc_g_input(struct file *filp, void *priv,
1137/* 1231/*
1138 * si470x_vidioc_s_input - set input 1232 * si470x_vidioc_s_input - set input
1139 */ 1233 */
1140static int si470x_vidioc_s_input(struct file *filp, void *priv, unsigned int i) 1234static int si470x_vidioc_s_input(struct file *file, void *priv, unsigned int i)
1141{ 1235{
1236 int retval = 0;
1237
1238 /* safety checks */
1142 if (i != 0) 1239 if (i != 0)
1143 return -EINVAL; 1240 retval = -EINVAL;
1144 1241
1145 return 0; 1242 if (retval < 0)
1243 printk(KERN_WARNING DRIVER_NAME
1244 ": set input failed with %d\n", retval);
1245 return retval;
1146} 1246}
1147 1247
1148 1248
@@ -1155,17 +1255,22 @@ static int si470x_vidioc_queryctrl(struct file *file, void *priv,
1155 unsigned char i; 1255 unsigned char i;
1156 int retval = -EINVAL; 1256 int retval = -EINVAL;
1157 1257
1258 /* safety checks */
1259 if (!qc->id)
1260 goto done;
1261
1158 for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) { 1262 for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) {
1159 if (qc->id && qc->id == si470x_v4l2_queryctrl[i].id) { 1263 if (qc->id == si470x_v4l2_queryctrl[i].id) {
1160 memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc)); 1264 memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc));
1161 retval = 0; 1265 retval = 0;
1162 break; 1266 break;
1163 } 1267 }
1164 } 1268 }
1269
1270done:
1165 if (retval < 0) 1271 if (retval < 0)
1166 printk(KERN_WARNING DRIVER_NAME 1272 printk(KERN_WARNING DRIVER_NAME
1167 ": query control failed with %d\n", retval); 1273 ": query controls failed with %d\n", retval);
1168
1169 return retval; 1274 return retval;
1170} 1275}
1171 1276
@@ -1177,9 +1282,13 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
1177 struct v4l2_control *ctrl) 1282 struct v4l2_control *ctrl)
1178{ 1283{
1179 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1284 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1285 int retval = 0;
1180 1286
1181 if (radio->disconnected) 1287 /* safety checks */
1182 return -EIO; 1288 if (radio->disconnected) {
1289 retval = -EIO;
1290 goto done;
1291 }
1183 1292
1184 switch (ctrl->id) { 1293 switch (ctrl->id) {
1185 case V4L2_CID_AUDIO_VOLUME: 1294 case V4L2_CID_AUDIO_VOLUME:
@@ -1190,9 +1299,15 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
1190 ctrl->value = ((radio->registers[POWERCFG] & 1299 ctrl->value = ((radio->registers[POWERCFG] &
1191 POWERCFG_DMUTE) == 0) ? 1 : 0; 1300 POWERCFG_DMUTE) == 0) ? 1 : 0;
1192 break; 1301 break;
1302 default:
1303 retval = -EINVAL;
1193 } 1304 }
1194 1305
1195 return 0; 1306done:
1307 if (retval < 0)
1308 printk(KERN_WARNING DRIVER_NAME
1309 ": get control failed with %d\n", retval);
1310 return retval;
1196} 1311}
1197 1312
1198 1313
@@ -1203,10 +1318,13 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
1203 struct v4l2_control *ctrl) 1318 struct v4l2_control *ctrl)
1204{ 1319{
1205 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1320 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1206 int retval; 1321 int retval = 0;
1207 1322
1208 if (radio->disconnected) 1323 /* safety checks */
1209 return -EIO; 1324 if (radio->disconnected) {
1325 retval = -EIO;
1326 goto done;
1327 }
1210 1328
1211 switch (ctrl->id) { 1329 switch (ctrl->id) {
1212 case V4L2_CID_AUDIO_VOLUME: 1330 case V4L2_CID_AUDIO_VOLUME:
@@ -1224,10 +1342,11 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
1224 default: 1342 default:
1225 retval = -EINVAL; 1343 retval = -EINVAL;
1226 } 1344 }
1345
1346done:
1227 if (retval < 0) 1347 if (retval < 0)
1228 printk(KERN_WARNING DRIVER_NAME 1348 printk(KERN_WARNING DRIVER_NAME
1229 ": set control failed with %d\n", retval); 1349 ": set control failed with %d\n", retval);
1230
1231 return retval; 1350 return retval;
1232} 1351}
1233 1352
@@ -1238,13 +1357,22 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
1238static int si470x_vidioc_g_audio(struct file *file, void *priv, 1357static int si470x_vidioc_g_audio(struct file *file, void *priv,
1239 struct v4l2_audio *audio) 1358 struct v4l2_audio *audio)
1240{ 1359{
1241 if (audio->index > 1) 1360 int retval = 0;
1242 return -EINVAL; 1361
1362 /* safety checks */
1363 if (audio->index != 0) {
1364 retval = -EINVAL;
1365 goto done;
1366 }
1243 1367
1244 strcpy(audio->name, "Radio"); 1368 strcpy(audio->name, "Radio");
1245 audio->capability = V4L2_AUDCAP_STEREO; 1369 audio->capability = V4L2_AUDCAP_STEREO;
1246 1370
1247 return 0; 1371done:
1372 if (retval < 0)
1373 printk(KERN_WARNING DRIVER_NAME
1374 ": get audio failed with %d\n", retval);
1375 return retval;
1248} 1376}
1249 1377
1250 1378
@@ -1254,10 +1382,19 @@ static int si470x_vidioc_g_audio(struct file *file, void *priv,
1254static int si470x_vidioc_s_audio(struct file *file, void *priv, 1382static int si470x_vidioc_s_audio(struct file *file, void *priv,
1255 struct v4l2_audio *audio) 1383 struct v4l2_audio *audio)
1256{ 1384{
1257 if (audio->index != 0) 1385 int retval = 0;
1258 return -EINVAL;
1259 1386
1260 return 0; 1387 /* safety checks */
1388 if (audio->index != 0) {
1389 retval = -EINVAL;
1390 goto done;
1391 }
1392
1393done:
1394 if (retval < 0)
1395 printk(KERN_WARNING DRIVER_NAME
1396 ": set audio failed with %d\n", retval);
1397 return retval;
1261} 1398}
1262 1399
1263 1400
@@ -1268,20 +1405,23 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
1268 struct v4l2_tuner *tuner) 1405 struct v4l2_tuner *tuner)
1269{ 1406{
1270 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1407 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1271 int retval; 1408 int retval = 0;
1272 1409
1273 if (radio->disconnected) 1410 /* safety checks */
1274 return -EIO; 1411 if (radio->disconnected) {
1275 if (tuner->index > 0) 1412 retval = -EIO;
1276 return -EINVAL; 1413 goto done;
1414 }
1415 if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) {
1416 retval = -EINVAL;
1417 goto done;
1418 }
1277 1419
1278 /* read status rssi */
1279 retval = si470x_get_register(radio, STATUSRSSI); 1420 retval = si470x_get_register(radio, STATUSRSSI);
1280 if (retval < 0) 1421 if (retval < 0)
1281 return retval; 1422 goto done;
1282 1423
1283 strcpy(tuner->name, "FM"); 1424 strcpy(tuner->name, "FM");
1284 tuner->type = V4L2_TUNER_RADIO;
1285 switch (band) { 1425 switch (band) {
1286 /* 0: 87.5 - 108 MHz (USA, Europe, default) */ 1426 /* 0: 87.5 - 108 MHz (USA, Europe, default) */
1287 default: 1427 default:
@@ -1313,9 +1453,14 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
1313 * 0x0101; 1453 * 0x0101;
1314 1454
1315 /* automatic frequency control: -1: freq to low, 1 freq to high */ 1455 /* automatic frequency control: -1: freq to low, 1 freq to high */
1316 tuner->afc = 0; 1456 /* AFCRL does only indicate that freq. differs, not if too low/high */
1457 tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0;
1317 1458
1318 return 0; 1459done:
1460 if (retval < 0)
1461 printk(KERN_WARNING DRIVER_NAME
1462 ": get tuner failed with %d\n", retval);
1463 return retval;
1319} 1464}
1320 1465
1321 1466
@@ -1326,12 +1471,17 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
1326 struct v4l2_tuner *tuner) 1471 struct v4l2_tuner *tuner)
1327{ 1472{
1328 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1473 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1329 int retval; 1474 int retval = 0;
1330 1475
1331 if (radio->disconnected) 1476 /* safety checks */
1332 return -EIO; 1477 if (radio->disconnected) {
1333 if (tuner->index > 0) 1478 retval = -EIO;
1334 return -EINVAL; 1479 goto done;
1480 }
1481 if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) {
1482 retval = -EINVAL;
1483 goto done;
1484 }
1335 1485
1336 if (tuner->audmode == V4L2_TUNER_MODE_MONO) 1486 if (tuner->audmode == V4L2_TUNER_MODE_MONO)
1337 radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */ 1487 radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */
@@ -1339,10 +1489,11 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
1339 radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */ 1489 radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
1340 1490
1341 retval = si470x_set_register(radio, POWERCFG); 1491 retval = si470x_set_register(radio, POWERCFG);
1492
1493done:
1342 if (retval < 0) 1494 if (retval < 0)
1343 printk(KERN_WARNING DRIVER_NAME 1495 printk(KERN_WARNING DRIVER_NAME
1344 ": set tuner failed with %d\n", retval); 1496 ": set tuner failed with %d\n", retval);
1345
1346 return retval; 1497 return retval;
1347} 1498}
1348 1499
@@ -1354,14 +1505,25 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
1354 struct v4l2_frequency *freq) 1505 struct v4l2_frequency *freq)
1355{ 1506{
1356 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1507 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1508 int retval = 0;
1357 1509
1358 if (radio->disconnected) 1510 /* safety checks */
1359 return -EIO; 1511 if (radio->disconnected) {
1512 retval = -EIO;
1513 goto done;
1514 }
1515 if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) {
1516 retval = -EINVAL;
1517 goto done;
1518 }
1360 1519
1361 freq->type = V4L2_TUNER_RADIO; 1520 retval = si470x_get_freq(radio, &freq->frequency);
1362 freq->frequency = si470x_get_freq(radio);
1363 1521
1364 return 0; 1522done:
1523 if (retval < 0)
1524 printk(KERN_WARNING DRIVER_NAME
1525 ": get frequency failed with %d\n", retval);
1526 return retval;
1365} 1527}
1366 1528
1367 1529
@@ -1372,19 +1534,55 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
1372 struct v4l2_frequency *freq) 1534 struct v4l2_frequency *freq)
1373{ 1535{
1374 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1536 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1375 int retval; 1537 int retval = 0;
1376 1538
1377 if (radio->disconnected) 1539 /* safety checks */
1378 return -EIO; 1540 if (radio->disconnected) {
1379 if (freq->type != V4L2_TUNER_RADIO) 1541 retval = -EIO;
1380 return -EINVAL; 1542 goto done;
1543 }
1544 if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) {
1545 retval = -EINVAL;
1546 goto done;
1547 }
1381 1548
1382 retval = si470x_set_freq(radio, freq->frequency); 1549 retval = si470x_set_freq(radio, freq->frequency);
1550
1551done:
1383 if (retval < 0) 1552 if (retval < 0)
1384 printk(KERN_WARNING DRIVER_NAME 1553 printk(KERN_WARNING DRIVER_NAME
1385 ": set frequency failed with %d\n", retval); 1554 ": set frequency failed with %d\n", retval);
1555 return retval;
1556}
1386 1557
1387 return 0; 1558
1559/*
1560 * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek
1561 */
1562static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
1563 struct v4l2_hw_freq_seek *seek)
1564{
1565 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1566 int retval = 0;
1567
1568 /* safety checks */
1569 if (radio->disconnected) {
1570 retval = -EIO;
1571 goto done;
1572 }
1573 if ((seek->tuner != 0) && (seek->type != V4L2_TUNER_RADIO)) {
1574 retval = -EINVAL;
1575 goto done;
1576 }
1577
1578 retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward);
1579
1580done:
1581 if (retval < 0)
1582 printk(KERN_WARNING DRIVER_NAME
1583 ": set hardware frequency seek failed with %d\n",
1584 retval);
1585 return retval;
1388} 1586}
1389 1587
1390 1588
@@ -1408,6 +1606,7 @@ static struct video_device si470x_viddev_template = {
1408 .vidioc_s_tuner = si470x_vidioc_s_tuner, 1606 .vidioc_s_tuner = si470x_vidioc_s_tuner,
1409 .vidioc_g_frequency = si470x_vidioc_g_frequency, 1607 .vidioc_g_frequency = si470x_vidioc_g_frequency,
1410 .vidioc_s_frequency = si470x_vidioc_s_frequency, 1608 .vidioc_s_frequency = si470x_vidioc_s_frequency,
1609 .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek,
1411 .owner = THIS_MODULE, 1610 .owner = THIS_MODULE,
1412}; 1611};
1413 1612
@@ -1424,31 +1623,36 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
1424 const struct usb_device_id *id) 1623 const struct usb_device_id *id)
1425{ 1624{
1426 struct si470x_device *radio; 1625 struct si470x_device *radio;
1427 int retval = -ENOMEM; 1626 int retval = 0;
1428 1627
1429 /* private data allocation */ 1628 /* private data allocation and initialization */
1430 radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); 1629 radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);
1431 if (!radio) 1630 if (!radio) {
1631 retval = -ENOMEM;
1432 goto err_initial; 1632 goto err_initial;
1633 }
1634 radio->users = 0;
1635 radio->disconnected = 0;
1636 radio->usbdev = interface_to_usbdev(intf);
1637 radio->intf = intf;
1638 mutex_init(&radio->disconnect_lock);
1639 mutex_init(&radio->lock);
1433 1640
1434 /* video device allocation */ 1641 /* video device allocation and initialization */
1435 radio->videodev = video_device_alloc(); 1642 radio->videodev = video_device_alloc();
1436 if (!radio->videodev) 1643 if (!radio->videodev) {
1644 retval = -ENOMEM;
1437 goto err_radio; 1645 goto err_radio;
1438 1646 }
1439 /* initial configuration */
1440 memcpy(radio->videodev, &si470x_viddev_template, 1647 memcpy(radio->videodev, &si470x_viddev_template,
1441 sizeof(si470x_viddev_template)); 1648 sizeof(si470x_viddev_template));
1442 radio->users = 0;
1443 radio->usbdev = interface_to_usbdev(intf);
1444 radio->intf = intf;
1445 mutex_init(&radio->lock);
1446 video_set_drvdata(radio->videodev, radio); 1649 video_set_drvdata(radio->videodev, radio);
1447 1650
1448 /* show some infos about the specific device */ 1651 /* show some infos about the specific device */
1449 retval = -EIO; 1652 if (si470x_get_all_registers(radio) < 0) {
1450 if (si470x_get_all_registers(radio) < 0) 1653 retval = -EIO;
1451 goto err_all; 1654 goto err_all;
1655 }
1452 printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", 1656 printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
1453 radio->registers[DEVICEID], radio->registers[CHIPID]); 1657 radio->registers[DEVICEID], radio->registers[CHIPID]);
1454 1658
@@ -1474,8 +1678,10 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
1474 /* rds buffer allocation */ 1678 /* rds buffer allocation */
1475 radio->buf_size = rds_buf * 3; 1679 radio->buf_size = rds_buf * 3;
1476 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); 1680 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
1477 if (!radio->buffer) 1681 if (!radio->buffer) {
1682 retval = -EIO;
1478 goto err_all; 1683 goto err_all;
1684 }
1479 1685
1480 /* rds buffer configuration */ 1686 /* rds buffer configuration */
1481 radio->wr_index = 0; 1687 radio->wr_index = 0;
@@ -1487,6 +1693,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
1487 1693
1488 /* register video device */ 1694 /* register video device */
1489 if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) { 1695 if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
1696 retval = -EIO;
1490 printk(KERN_WARNING DRIVER_NAME 1697 printk(KERN_WARNING DRIVER_NAME
1491 ": Could not register video device\n"); 1698 ": Could not register video device\n");
1492 goto err_all; 1699 goto err_all;
@@ -1546,16 +1753,16 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
1546{ 1753{
1547 struct si470x_device *radio = usb_get_intfdata(intf); 1754 struct si470x_device *radio = usb_get_intfdata(intf);
1548 1755
1549 mutex_lock(&open_close_lock); 1756 mutex_lock(&radio->disconnect_lock);
1550 radio->disconnected = 1; 1757 radio->disconnected = 1;
1551 cancel_delayed_work_sync(&radio->work); 1758 cancel_delayed_work_sync(&radio->work);
1552 usb_set_intfdata(intf, NULL); 1759 usb_set_intfdata(intf, NULL);
1553 if (radio->users == 0) { 1760 if (radio->users == 0) {
1554 video_unregister_device(radio->videodev); 1761 video_unregister_device(radio->videodev);
1555 kfree(radio->buffer); 1762 kfree(radio->buffer);
1556 kfree(radio); 1763 kfree(radio);
1557 } 1764 }
1558 mutex_unlock(&open_close_lock); 1765 mutex_unlock(&radio->disconnect_lock);
1559} 1766}
1560 1767
1561 1768