aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio')
-rw-r--r--drivers/media/radio/radio-si470x.c83
1 files changed, 75 insertions, 8 deletions
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
index c72a9e7ad885..649f14d2c013 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -81,6 +81,10 @@
81 * - racy interruptible_sleep_on(), 81 * - racy interruptible_sleep_on(),
82 * replaced with wait_event_interruptible() 82 * replaced with wait_event_interruptible()
83 * - handle signals in read() 83 * - handle signals in read()
84 * 2008-02-08 Tobias Lorenz <tobias.lorenz@gmx.net>
85 * Oliver Neukum <oliver@neukum.org>
86 * Version 1.0.7
87 * - usb autosuspend support
84 * 88 *
85 * ToDo: 89 * ToDo:
86 * - add seeking support 90 * - add seeking support
@@ -415,6 +419,7 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
415struct si470x_device { 419struct si470x_device {
416 /* reference to USB and video device */ 420 /* reference to USB and video device */
417 struct usb_device *usbdev; 421 struct usb_device *usbdev;
422 struct usb_interface *intf;
418 struct video_device *videodev; 423 struct video_device *videodev;
419 424
420 /* driver management */ 425 /* driver management */
@@ -762,9 +767,17 @@ static int si470x_stop(struct si470x_device *radio)
762 */ 767 */
763static int si470x_rds_on(struct si470x_device *radio) 768static int si470x_rds_on(struct si470x_device *radio)
764{ 769{
770 int retval;
771
765 /* sysconfig 1 */ 772 /* sysconfig 1 */
773 mutex_lock(&radio->lock);
766 radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS; 774 radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS;
767 return si470x_set_register(radio, SYSCONFIG1); 775 retval = si470x_set_register(radio, SYSCONFIG1);
776 if (retval < 0)
777 radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
778 mutex_unlock(&radio->lock);
779
780 return retval;
768} 781}
769 782
770 783
@@ -961,10 +974,22 @@ static unsigned int si470x_fops_poll(struct file *file,
961static int si470x_fops_open(struct inode *inode, struct file *file) 974static int si470x_fops_open(struct inode *inode, struct file *file)
962{ 975{
963 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 976 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
977 int retval;
964 978
965 radio->users++; 979 radio->users++;
966 if (radio->users == 1) 980
967 return si470x_start(radio); 981 retval = usb_autopm_get_interface(radio->intf);
982 if (retval < 0) {
983 radio->users--;
984 return -EIO;
985 }
986
987 if (radio->users == 1) {
988 retval = si470x_start(radio);
989 if (retval < 0)
990 usb_autopm_put_interface(radio->intf);
991 return retval;
992 }
968 993
969 return 0; 994 return 0;
970} 995}
@@ -976,6 +1001,7 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
976static int si470x_fops_release(struct inode *inode, struct file *file) 1001static int si470x_fops_release(struct inode *inode, struct file *file)
977{ 1002{
978 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1003 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1004 int retval;
979 1005
980 if (!radio) 1006 if (!radio)
981 return -ENODEV; 1007 return -ENODEV;
@@ -988,7 +1014,9 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
988 /* cancel read processes */ 1014 /* cancel read processes */
989 wake_up_interruptible(&radio->read_queue); 1015 wake_up_interruptible(&radio->read_queue);
990 1016
991 return si470x_stop(radio); 1017 retval = si470x_stop(radio);
1018 usb_autopm_put_interface(radio->intf);
1019 return retval;
992 } 1020 }
993 1021
994 return 0; 1022 return 0;
@@ -1377,6 +1405,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
1377 sizeof(si470x_viddev_template)); 1405 sizeof(si470x_viddev_template));
1378 radio->users = 0; 1406 radio->users = 0;
1379 radio->usbdev = interface_to_usbdev(intf); 1407 radio->usbdev = interface_to_usbdev(intf);
1408 radio->intf = intf;
1380 mutex_init(&radio->lock); 1409 mutex_init(&radio->lock);
1381 video_set_drvdata(radio->videodev, radio); 1410 video_set_drvdata(radio->videodev, radio);
1382 1411
@@ -1440,6 +1469,41 @@ err_initial:
1440 1469
1441 1470
1442/* 1471/*
1472 * si470x_usb_driver_suspend - suspend the device
1473 */
1474static int si470x_usb_driver_suspend(struct usb_interface *intf,
1475 pm_message_t message)
1476{
1477 struct si470x_device *radio = usb_get_intfdata(intf);
1478
1479 printk(KERN_INFO DRIVER_NAME ": suspending now...\n");
1480
1481 cancel_delayed_work_sync(&radio->work);
1482
1483 return 0;
1484}
1485
1486
1487/*
1488 * si470x_usb_driver_resume - resume the device
1489 */
1490static int si470x_usb_driver_resume(struct usb_interface *intf)
1491{
1492 struct si470x_device *radio = usb_get_intfdata(intf);
1493
1494 printk(KERN_INFO DRIVER_NAME ": resuming now...\n");
1495
1496 mutex_lock(&radio->lock);
1497 if (radio->users && radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS)
1498 schedule_delayed_work(&radio->work,
1499 msecs_to_jiffies(rds_poll_time));
1500 mutex_unlock(&radio->lock);
1501
1502 return 0;
1503}
1504
1505
1506/*
1443 * si470x_usb_driver_disconnect - disconnect the device 1507 * si470x_usb_driver_disconnect - disconnect the device
1444 */ 1508 */
1445static void si470x_usb_driver_disconnect(struct usb_interface *intf) 1509static void si470x_usb_driver_disconnect(struct usb_interface *intf)
@@ -1458,10 +1522,13 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
1458 * si470x_usb_driver - usb driver interface 1522 * si470x_usb_driver - usb driver interface
1459 */ 1523 */
1460static struct usb_driver si470x_usb_driver = { 1524static struct usb_driver si470x_usb_driver = {
1461 .name = DRIVER_NAME, 1525 .name = DRIVER_NAME,
1462 .probe = si470x_usb_driver_probe, 1526 .probe = si470x_usb_driver_probe,
1463 .disconnect = si470x_usb_driver_disconnect, 1527 .disconnect = si470x_usb_driver_disconnect,
1464 .id_table = si470x_usb_driver_id_table, 1528 .suspend = si470x_usb_driver_suspend,
1529 .resume = si470x_usb_driver_resume,
1530 .id_table = si470x_usb_driver_id_table,
1531 .supports_autosuspend = 1,
1465}; 1532};
1466 1533
1467 1534