aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorTobias Lorenz <tobias.lorenz@gmx.net>2008-02-04 20:26:08 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-02-18 09:15:18 -0500
commit5caf51342c81c7cb2a8c3998e3f606ccfa79cee2 (patch)
tree2ecd097a9192d1a3494de035e66cf00cb8bcd2db /drivers/media
parentea75baf4b0f117564bd50827a49c4b14d61d24e9 (diff)
V4L/DVB (7188): radio-si470x version 1.0.6
This patch combines all the finished discussions and its resulting patches from the mailing list. The version 1.0.6 is mainly influenced by Oliver Neukum. He found a lot of small issues, that are fixed with this patch now. For me the most interesting thing is, that it's now safer to use it on other architectures. The history for version 1.0.6 is: - fixed coverity checker warnings in *_usb_driver_disconnect - probe()/open() race by correct ordering in probe() - DMA coherency rules by separate allocation of all buffers - use of endianness macros - abuse of spinlock, replaced by mutex - racy handling of timer in disconnect, replaced by delayed_work - racy interruptible_sleep_on(), replaced with wait_event_interruptible() - handle signals in read() The driver is tested with all Debian/testing radio programs and rdsd. The patch is tested against checkpatch.pl v1.12. Signed-off-by: Tobias Lorenz <tobias.lorenz@gmx.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/radio/radio-si470x.c330
1 files changed, 167 insertions, 163 deletions
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
index d428c3aa2bf9..c72a9e7ad885 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -66,8 +66,21 @@
66 * Version 1.0.5 66 * Version 1.0.5
67 * - number of seek_retries changed to tune_timeout 67 * - number of seek_retries changed to tune_timeout
68 * - fixed problem with incomplete tune operations by own buffers 68 * - fixed problem with incomplete tune operations by own buffers
69 * - optimization of variables 69 * - optimization of variables and printf types
70 * - improved error logging 70 * - improved error logging
71 * 2008-01-31 Tobias Lorenz <tobias.lorenz@gmx.net>
72 * Oliver Neukum <oliver@neukum.org>
73 * Version 1.0.6
74 * - fixed coverity checker warnings in *_usb_driver_disconnect
75 * - probe()/open() race by correct ordering in probe()
76 * - DMA coherency rules by separate allocation of all buffers
77 * - use of endianness macros
78 * - abuse of spinlock, replaced by mutex
79 * - racy handling of timer in disconnect,
80 * replaced by delayed_work
81 * - racy interruptible_sleep_on(),
82 * replaced with wait_event_interruptible()
83 * - handle signals in read()
71 * 84 *
72 * ToDo: 85 * ToDo:
73 * - add seeking support 86 * - add seeking support
@@ -80,10 +93,10 @@
80/* driver definitions */ 93/* driver definitions */
81#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>" 94#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
82#define DRIVER_NAME "radio-si470x" 95#define DRIVER_NAME "radio-si470x"
83#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 5) 96#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 6)
84#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" 97#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
85#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" 98#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
86#define DRIVER_VERSION "1.0.5" 99#define DRIVER_VERSION "1.0.6"
87 100
88 101
89/* kernel includes */ 102/* kernel includes */
@@ -96,8 +109,10 @@
96#include <linux/hid.h> 109#include <linux/hid.h>
97#include <linux/version.h> 110#include <linux/version.h>
98#include <linux/videodev2.h> 111#include <linux/videodev2.h>
112#include <linux/mutex.h>
99#include <media/v4l2-common.h> 113#include <media/v4l2-common.h>
100#include <media/rds.h> 114#include <media/rds.h>
115#include <asm/unaligned.h>
101 116
102 117
103/* USB Device ID List */ 118/* USB Device ID List */
@@ -409,10 +424,9 @@ struct si470x_device {
409 unsigned short registers[RADIO_REGISTER_NUM]; 424 unsigned short registers[RADIO_REGISTER_NUM];
410 425
411 /* RDS receive buffer */ 426 /* RDS receive buffer */
412 struct work_struct work; 427 struct delayed_work work;
413 wait_queue_head_t read_queue; 428 wait_queue_head_t read_queue;
414 struct timer_list timer; 429 struct mutex lock; /* buffer locking */
415 spinlock_t lock; /* buffer locking */
416 unsigned char *buffer; /* size is always multiple of three */ 430 unsigned char *buffer; /* size is always multiple of three */
417 unsigned int buf_size; 431 unsigned int buf_size;
418 unsigned int rd_index; 432 unsigned int rd_index;
@@ -494,7 +508,8 @@ static int si470x_get_register(struct si470x_device *radio, int regnr)
494 retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); 508 retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
495 509
496 if (retval >= 0) 510 if (retval >= 0)
497 radio->registers[regnr] = (buf[1] << 8) | buf[2]; 511 radio->registers[regnr] = be16_to_cpu(get_unaligned(
512 (unsigned short *) &buf[1]));
498 513
499 return (retval < 0) ? -EINVAL : 0; 514 return (retval < 0) ? -EINVAL : 0;
500} 515}
@@ -509,8 +524,8 @@ static int si470x_set_register(struct si470x_device *radio, int regnr)
509 int retval; 524 int retval;
510 525
511 buf[0] = REGISTER_REPORT(regnr); 526 buf[0] = REGISTER_REPORT(regnr);
512 buf[1] = (radio->registers[regnr] & 0xff00) >> 8; 527 put_unaligned(cpu_to_be16(radio->registers[regnr]),
513 buf[2] = (radio->registers[regnr] & 0x00ff); 528 (unsigned short *) &buf[1]);
514 529
515 retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); 530 retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
516 531
@@ -533,9 +548,9 @@ static int si470x_get_all_registers(struct si470x_device *radio)
533 548
534 if (retval >= 0) 549 if (retval >= 0)
535 for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++) 550 for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)
536 radio->registers[regnr] = 551 radio->registers[regnr] = be16_to_cpu(get_unaligned(
537 (buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) | 552 (unsigned short *)
538 buf[regnr * RADIO_REGISTER_SIZE + 2]; 553 &buf[regnr * RADIO_REGISTER_SIZE + 1]));
539 554
540 return (retval < 0) ? -EINVAL : 0; 555 return (retval < 0) ? -EINVAL : 0;
541} 556}
@@ -558,7 +573,7 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
558 (void *) &buf, sizeof(buf), &size, usb_timeout); 573 (void *) &buf, sizeof(buf), &size, usb_timeout);
559 if (size != sizeof(buf)) 574 if (size != sizeof(buf))
560 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_register: " 575 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_register: "
561 "return size differs: %d != %uld\n", size, sizeof(buf)); 576 "return size differs: %d != %zu\n", size, sizeof(buf));
562 if (retval < 0) 577 if (retval < 0)
563 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " 578 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
564 "usb_interrupt_msg returned %d\n", retval); 579 "usb_interrupt_msg returned %d\n", retval);
@@ -566,8 +581,8 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
566 if (retval >= 0) 581 if (retval >= 0)
567 for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) 582 for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
568 radio->registers[STATUSRSSI + regnr] = 583 radio->registers[STATUSRSSI + regnr] =
569 (buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) | 584 be16_to_cpu(get_unaligned((unsigned short *)
570 buf[regnr * RADIO_REGISTER_SIZE + 2]; 585 &buf[regnr * RADIO_REGISTER_SIZE + 1]));
571 586
572 return (retval < 0) ? -EINVAL : 0; 587 return (retval < 0) ? -EINVAL : 0;
573} 588}
@@ -600,7 +615,7 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
600 (!timed_out)); 615 (!timed_out));
601 if (timed_out) 616 if (timed_out)
602 printk(KERN_WARNING DRIVER_NAME 617 printk(KERN_WARNING DRIVER_NAME
603 ": seek does not finish after %d ms\n", tune_timeout); 618 ": seek does not finish after %u ms\n", tune_timeout);
604 619
605 /* stop tuning */ 620 /* stop tuning */
606 radio->registers[CHANNEL] &= ~CHANNEL_TUNE; 621 radio->registers[CHANNEL] &= ~CHANNEL_TUNE;
@@ -763,6 +778,11 @@ static int si470x_rds_on(struct si470x_device *radio)
763 */ 778 */
764static void si470x_rds(struct si470x_device *radio) 779static void si470x_rds(struct si470x_device *radio)
765{ 780{
781 unsigned char blocknum;
782 unsigned short bler; /* rds block errors */
783 unsigned short rds;
784 unsigned char tmpbuf[3];
785
766 /* get rds blocks */ 786 /* get rds blocks */
767 if (si470x_get_rds_registers(radio) < 0) 787 if (si470x_get_rds_registers(radio) < 0)
768 return; 788 return;
@@ -775,69 +795,58 @@ static void si470x_rds(struct si470x_device *radio)
775 return; 795 return;
776 } 796 }
777 797
778 /* copy four RDS blocks to internal buffer */ 798 /* copy all four RDS blocks to internal buffer */
779 if (spin_trylock(&radio->lock)) { 799 mutex_lock(&radio->lock);
780 unsigned char blocknum; 800 for (blocknum = 0; blocknum < 4; blocknum++) {
781 unsigned short bler; /* rds block errors */ 801 switch (blocknum) {
782 unsigned short rds; 802 default:
783 unsigned char tmpbuf[3]; 803 bler = (radio->registers[STATUSRSSI] &
784 unsigned char i; 804 STATUSRSSI_BLERA) >> 9;
785 805 rds = radio->registers[RDSA];
786 /* process each rds block */ 806 break;
787 for (blocknum = 0; blocknum < 4; blocknum++) { 807 case 1:
788 switch (blocknum) { 808 bler = (radio->registers[READCHAN] &
789 default: 809 READCHAN_BLERB) >> 14;
790 bler = (radio->registers[STATUSRSSI] & 810 rds = radio->registers[RDSB];
791 STATUSRSSI_BLERA) >> 9; 811 break;
792 rds = radio->registers[RDSA]; 812 case 2:
793 break; 813 bler = (radio->registers[READCHAN] &
794 case 1: 814 READCHAN_BLERC) >> 12;
795 bler = (radio->registers[READCHAN] & 815 rds = radio->registers[RDSC];
796 READCHAN_BLERB) >> 14; 816 break;
797 rds = radio->registers[RDSB]; 817 case 3:
798 break; 818 bler = (radio->registers[READCHAN] &
799 case 2: 819 READCHAN_BLERD) >> 10;
800 bler = (radio->registers[READCHAN] & 820 rds = radio->registers[RDSD];
801 READCHAN_BLERC) >> 12; 821 break;
802 rds = radio->registers[RDSC]; 822 };
803 break; 823
804 case 3: 824 /* Fill the V4L2 RDS buffer */
805 bler = (radio->registers[READCHAN] & 825 put_unaligned(cpu_to_le16(rds), (unsigned short *) &tmpbuf);
806 READCHAN_BLERD) >> 10; 826 tmpbuf[2] = blocknum; /* offset name */
807 rds = radio->registers[RDSD]; 827 tmpbuf[2] |= blocknum << 3; /* received offset */
808 break; 828 if (bler > max_rds_errors)
809 }; 829 tmpbuf[2] |= 0x80; /* uncorrectable errors */
810 830 else if (bler > 0)
811 /* Fill the V4L2 RDS buffer */ 831 tmpbuf[2] |= 0x40; /* corrected error(s) */
812 tmpbuf[0] = rds & 0x00ff; /* LSB */ 832
813 tmpbuf[1] = (rds & 0xff00) >> 8;/* MSB */ 833 /* copy RDS block to internal buffer */
814 tmpbuf[2] = blocknum; /* offset name */ 834 memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3);
815 tmpbuf[2] |= blocknum << 3; /* received offset */ 835 radio->wr_index += 3;
816 if (bler > max_rds_errors) 836
817 tmpbuf[2] |= 0x80; /* uncorrectable errors */ 837 /* wrap write pointer */
818 else if (bler > 0) 838 if (radio->wr_index >= radio->buf_size)
819 tmpbuf[2] |= 0x40; /* corrected error(s) */ 839 radio->wr_index = 0;
820 840
821 /* copy RDS block to internal buffer */ 841 /* check for overflow */
822 for (i = 0; i < 3; i++) { 842 if (radio->wr_index == radio->rd_index) {
823 radio->buffer[radio->wr_index] = tmpbuf[i]; 843 /* increment and wrap read pointer */
824 radio->wr_index++; 844 radio->rd_index += 3;
825 } 845 if (radio->rd_index >= radio->buf_size)
826 846 radio->rd_index = 0;
827 /* wrap write pointer */
828 if (radio->wr_index >= radio->buf_size)
829 radio->wr_index = 0;
830
831 /* check for overflow */
832 if (radio->wr_index == radio->rd_index) {
833 /* increment and wrap read pointer */
834 radio->rd_index += 3;
835 if (radio->rd_index >= radio->buf_size)
836 radio->rd_index = 0;
837 }
838 } 847 }
839 spin_unlock(&radio->lock);
840 } 848 }
849 mutex_unlock(&radio->lock);
841 850
842 /* wake up read queue */ 851 /* wake up read queue */
843 if (radio->wr_index != radio->rd_index) 852 if (radio->wr_index != radio->rd_index)
@@ -846,29 +855,18 @@ static void si470x_rds(struct si470x_device *radio)
846 855
847 856
848/* 857/*
849 * si470x_timer - rds timer function
850 */
851static void si470x_timer(unsigned long data)
852{
853 struct si470x_device *radio = (struct si470x_device *) data;
854
855 schedule_work(&radio->work);
856}
857
858
859/*
860 * si470x_work - rds work function 858 * si470x_work - rds work function
861 */ 859 */
862static void si470x_work(struct work_struct *work) 860static void si470x_work(struct work_struct *work)
863{ 861{
864 struct si470x_device *radio = container_of(work, struct si470x_device, 862 struct si470x_device *radio = container_of(work, struct si470x_device,
865 work); 863 work.work);
866 864
867 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) 865 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
868 return; 866 return;
869 867
870 si470x_rds(radio); 868 si470x_rds(radio);
871 mod_timer(&radio->timer, jiffies + msecs_to_jiffies(rds_poll_time)); 869 schedule_delayed_work(&radio->work, msecs_to_jiffies(rds_poll_time));
872} 870}
873 871
874 872
@@ -885,49 +883,49 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf,
885{ 883{
886 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 884 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
887 int retval = 0; 885 int retval = 0;
886 unsigned int block_count = 0;
888 887
889 /* switch on rds reception */ 888 /* switch on rds reception */
890 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { 889 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) {
891 si470x_rds_on(radio); 890 si470x_rds_on(radio);
892 schedule_work(&radio->work); 891 schedule_delayed_work(&radio->work,
892 msecs_to_jiffies(rds_poll_time));
893 } 893 }
894 894
895 /* block if no new data available */ 895 /* block if no new data available */
896 while (radio->wr_index == radio->rd_index) { 896 while (radio->wr_index == radio->rd_index) {
897 if (file->f_flags & O_NONBLOCK) 897 if (file->f_flags & O_NONBLOCK)
898 return -EWOULDBLOCK; 898 return -EWOULDBLOCK;
899 interruptible_sleep_on(&radio->read_queue); 899 if (wait_event_interruptible(radio->read_queue,
900 radio->wr_index != radio->rd_index) < 0)
901 return -EINTR;
900 } 902 }
901 903
902 /* calculate block count from byte count */ 904 /* calculate block count from byte count */
903 count /= 3; 905 count /= 3;
904 906
905 /* copy RDS block out of internal buffer and to user buffer */ 907 /* copy RDS block out of internal buffer and to user buffer */
906 if (spin_trylock(&radio->lock)) { 908 mutex_lock(&radio->lock);
907 unsigned int block_count = 0; 909 while (block_count < count) {
908 while (block_count < count) { 910 if (radio->rd_index == radio->wr_index)
909 if (radio->rd_index == radio->wr_index) 911 break;
910 break;
911
912 /* always transfer rds complete blocks */
913 if (copy_to_user(buf,
914 &radio->buffer[radio->rd_index], 3))
915 /* retval = -EFAULT; */
916 break;
917 912
918 /* increment and wrap read pointer */ 913 /* always transfer rds complete blocks */
919 radio->rd_index += 3; 914 if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
920 if (radio->rd_index >= radio->buf_size) 915 /* retval = -EFAULT; */
921 radio->rd_index = 0; 916 break;
922 917
923 /* increment counters */ 918 /* increment and wrap read pointer */
924 block_count++; 919 radio->rd_index += 3;
925 buf += 3; 920 if (radio->rd_index >= radio->buf_size)
926 retval += 3; 921 radio->rd_index = 0;
927 }
928 922
929 spin_unlock(&radio->lock); 923 /* increment counters */
924 block_count++;
925 buf += 3;
926 retval += 3;
930 } 927 }
928 mutex_unlock(&radio->lock);
931 929
932 return retval; 930 return retval;
933} 931}
@@ -944,7 +942,8 @@ static unsigned int si470x_fops_poll(struct file *file,
944 /* switch on rds reception */ 942 /* switch on rds reception */
945 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { 943 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) {
946 si470x_rds_on(radio); 944 si470x_rds_on(radio);
947 schedule_work(&radio->work); 945 schedule_delayed_work(&radio->work,
946 msecs_to_jiffies(rds_poll_time));
948 } 947 }
949 948
950 poll_wait(file, &radio->read_queue, pts); 949 poll_wait(file, &radio->read_queue, pts);
@@ -984,8 +983,7 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
984 radio->users--; 983 radio->users--;
985 if (radio->users == 0) { 984 if (radio->users == 0) {
986 /* stop rds reception */ 985 /* stop rds reception */
987 del_timer_sync(&radio->timer); 986 cancel_delayed_work_sync(&radio->work);
988 flush_scheduled_work();
989 987
990 /* cancel read processes */ 988 /* cancel read processes */
991 wake_up_interruptible(&radio->read_queue); 989 wake_up_interruptible(&radio->read_queue);
@@ -1362,73 +1360,82 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
1362 const struct usb_device_id *id) 1360 const struct usb_device_id *id)
1363{ 1361{
1364 struct si470x_device *radio; 1362 struct si470x_device *radio;
1363 int retval = -ENOMEM;
1365 1364
1366 /* memory and interface allocations */ 1365 /* private data allocation */
1367 radio = kmalloc(sizeof(struct si470x_device), GFP_KERNEL); 1366 radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);
1368 if (!radio) 1367 if (!radio)
1369 return -ENOMEM; 1368 goto err_initial;
1369
1370 /* video device allocation */
1370 radio->videodev = video_device_alloc(); 1371 radio->videodev = video_device_alloc();
1371 if (!radio->videodev) { 1372 if (!radio->videodev)
1372 kfree(radio); 1373 goto err_radio;
1373 return -ENOMEM; 1374
1374 } 1375 /* initial configuration */
1375 memcpy(radio->videodev, &si470x_viddev_template, 1376 memcpy(radio->videodev, &si470x_viddev_template,
1376 sizeof(si470x_viddev_template)); 1377 sizeof(si470x_viddev_template));
1377 radio->users = 0; 1378 radio->users = 0;
1378 radio->usbdev = interface_to_usbdev(intf); 1379 radio->usbdev = interface_to_usbdev(intf);
1380 mutex_init(&radio->lock);
1379 video_set_drvdata(radio->videodev, radio); 1381 video_set_drvdata(radio->videodev, radio);
1380 if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
1381 printk(KERN_WARNING DRIVER_NAME
1382 ": Could not register video device\n");
1383 video_device_release(radio->videodev);
1384 kfree(radio);
1385 return -EIO;
1386 }
1387 usb_set_intfdata(intf, radio);
1388 1382
1389 /* show some infos about the specific device */ 1383 /* show some infos about the specific device */
1390 if (si470x_get_all_registers(radio) < 0) { 1384 retval = -EIO;
1391 video_device_release(radio->videodev); 1385 if (si470x_get_all_registers(radio) < 0)
1392 kfree(radio); 1386 goto err_all;
1393 return -EIO; 1387 printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
1394 }
1395 printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4x ChipID=0x%4.4x\n",
1396 radio->registers[DEVICEID], radio->registers[CHIPID]); 1388 radio->registers[DEVICEID], radio->registers[CHIPID]);
1397 1389
1398 /* check if firmware is current */ 1390 /* check if firmware is current */
1399 if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) 1391 if ((radio->registers[CHIPID] & CHIPID_FIRMWARE)
1400 < RADIO_SW_VERSION_CURRENT) 1392 < RADIO_SW_VERSION_CURRENT) {
1393 printk(KERN_WARNING DRIVER_NAME
1394 ": This driver is known to work with "
1395 "firmware version %hu,\n", RADIO_SW_VERSION_CURRENT);
1396 printk(KERN_WARNING DRIVER_NAME
1397 ": but the device has firmware version %hu.\n",
1398 radio->registers[CHIPID] & CHIPID_FIRMWARE);
1399 printk(KERN_WARNING DRIVER_NAME
1400 ": If you have some trouble using this driver,\n");
1401 printk(KERN_WARNING DRIVER_NAME 1401 printk(KERN_WARNING DRIVER_NAME
1402 ": This driver is known to work with chip version %d, " 1402 ": please report to V4L ML at "
1403 "but the device has firmware %d.\n" 1403 "video4linux-list@redhat.com\n");
1404 DRIVER_NAME 1404 }
1405 "If you have some trouble using this driver, please "
1406 "report to V4L ML at video4linux-list@redhat.com\n",
1407 radio->registers[CHIPID] & CHIPID_FIRMWARE,
1408 RADIO_SW_VERSION_CURRENT);
1409 1405
1410 /* set initial frequency */ 1406 /* set initial frequency */
1411 si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ 1407 si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
1412 1408
1413 /* rds initialization */ 1409 /* rds buffer allocation */
1414 radio->buf_size = rds_buf * 3; 1410 radio->buf_size = rds_buf * 3;
1415 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); 1411 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
1416 if (!radio->buffer) { 1412 if (!radio->buffer)
1417 video_device_release(radio->videodev); 1413 goto err_all;
1418 kfree(radio); 1414
1419 return -ENOMEM; 1415 /* rds buffer configuration */
1420 }
1421 radio->wr_index = 0; 1416 radio->wr_index = 0;
1422 radio->rd_index = 0; 1417 radio->rd_index = 0;
1423 init_waitqueue_head(&radio->read_queue); 1418 init_waitqueue_head(&radio->read_queue);
1424 1419
1425 /* prepare polling via eventd */ 1420 /* prepare rds work function */
1426 INIT_WORK(&radio->work, si470x_work); 1421 INIT_DELAYED_WORK(&radio->work, si470x_work);
1427 init_timer(&radio->timer); 1422
1428 radio->timer.function = si470x_timer; 1423 /* register video device */
1429 radio->timer.data = (unsigned long) radio; 1424 if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
1425 printk(KERN_WARNING DRIVER_NAME
1426 ": Could not register video device\n");
1427 goto err_all;
1428 }
1429 usb_set_intfdata(intf, radio);
1430 1430
1431 return 0; 1431 return 0;
1432err_all:
1433 video_device_release(radio->videodev);
1434 kfree(radio->buffer);
1435err_radio:
1436 kfree(radio);
1437err_initial:
1438 return retval;
1432} 1439}
1433 1440
1434 1441
@@ -1439,14 +1446,11 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
1439{ 1446{
1440 struct si470x_device *radio = usb_get_intfdata(intf); 1447 struct si470x_device *radio = usb_get_intfdata(intf);
1441 1448
1449 cancel_delayed_work_sync(&radio->work);
1442 usb_set_intfdata(intf, NULL); 1450 usb_set_intfdata(intf, NULL);
1443 if (radio) { 1451 video_unregister_device(radio->videodev);
1444 del_timer_sync(&radio->timer); 1452 kfree(radio->buffer);
1445 flush_scheduled_work(); 1453 kfree(radio);
1446 video_unregister_device(radio->videodev);
1447 kfree(radio->buffer);
1448 kfree(radio);
1449 }
1450} 1454}
1451 1455
1452 1456