Hi,
this should implement autosuspend. Could you please test it?
It's against 1.0.6.
Regards
Oliver
----
commit 5929871d540c96a05df7c7d3cbaeff4524ffe8e2
Author: Oliver Neukum <[EMAIL PROTECTED]>
Date: Fri Feb 1 15:48:09 2008 +0100
autosuspend for the si470x driver
diff --git a/drivers/media/radio/radio-si470x.c
b/drivers/media/radio/radio-si470x.c
index bb29e44..251e081 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -416,6 +416,7 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
struct si470x_device {
/* reference to USB and video device */
struct usb_device *usbdev;
+ struct usb_interface *intf;
struct video_device *videodev;
/* driver management */
@@ -763,9 +764,15 @@ static int si470x_stop(struct si470x_device *radio)
*/
static int si470x_rds_on(struct si470x_device *radio)
{
+ int retval;
+
/* sysconfig 1 */
+ mutex_lock(&radio->lock);
radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS;
- return si470x_set_register(radio, SYSCONFIG1);
+ retval = si470x_set_register(radio, SYSCONFIG1);
+ mutex_unlock(&radio->lock);
+
+ return retval;
}
@@ -887,11 +894,13 @@ static ssize_t si470x_fops_read(struct file *file, char
__user *buf,
unsigned int block_count = 0;
/* switch on rds reception */
+ mutex_lock(&radio->lock);
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) {
si470x_rds_on(radio);
schedule_delayed_work(&radio->work,
msecs_to_jiffies(rds_poll_time));
}
+ mutex_unlock(&radio->lock);
/* block if no new data available */
while (radio->wr_index == radio->rd_index) {
@@ -941,11 +950,13 @@ static unsigned int si470x_fops_poll(struct file *file,
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
/* switch on rds reception */
+ mutex_lock(&radio->lock);
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) {
si470x_rds_on(radio);
schedule_delayed_work(&radio->work,
msecs_to_jiffies(rds_poll_time));
}
+ mutex_unlock(&radio->lock);
poll_wait(file, &radio->read_queue, pts);
@@ -962,10 +973,21 @@ static unsigned int si470x_fops_poll(struct file *file,
static int si470x_fops_open(struct inode *inode, struct file *file)
{
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
-
+ int err;
radio->users++;
- if (radio->users == 1)
- return si470x_start(radio);
+
+ err = usb_autopm_get_interface(radio->intf);
+ if (err < 0) {
+ radio->users--;
+ return -EIO;
+ }
+
+ if (radio->users == 1) {
+ err = si470x_start(radio);
+ if (err < 0)
+ usb_autopm_put_interface(radio->intf);
+ return err;
+ }
return 0;
}
@@ -977,6 +999,7 @@ static int si470x_fops_open(struct inode *inode, struct
file *file)
static int si470x_fops_release(struct inode *inode, struct file *file)
{
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ int err;
if (!radio)
return -ENODEV;
@@ -989,7 +1012,9 @@ static int si470x_fops_release(struct inode *inode, struct
file *file)
/* cancel read processes */
wake_up_interruptible(&radio->read_queue);
- return si470x_stop(radio);
+ err = si470x_stop(radio);
+ usb_autopm_put_interface(radio->intf);
+ return err;
}
return 0;
@@ -1378,6 +1403,7 @@ static int si470x_usb_driver_probe(struct usb_interface
*intf,
sizeof(si470x_viddev_template));
radio->users = 0;
radio->usbdev = interface_to_usbdev(intf);
+ radio->intf = intf;
mutex_init(&radio->lock);
video_set_drvdata(radio->videodev, radio);
@@ -1454,6 +1480,28 @@ static void si470x_usb_driver_disconnect(struct
usb_interface *intf)
kfree(radio);
}
+static int si470x_usb_driver_suspend (struct usb_interface *intf, pm_message_t
message)
+{
+ struct si470x_device *radio = usb_get_intfdata(intf);
+
+ mutex_lock(&radio->lock);
+ cancel_delayed_work_sync(&radio->work);
+ mutex_unlock(&radio->lock);
+
+ return 0;
+}
+
+static int si470x_usb_driver_resume (struct usb_interface *intf)
+{
+ struct si470x_device *radio = usb_get_intfdata(intf);
+
+ mutex_lock(&radio->lock);
+ if (radio->users && radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS)
+ schedule_delayed_work(&radio->work,
msecs_to_jiffies(rds_poll_time));
+ mutex_unlock(&radio->lock);
+
+ return 0;
+}
/*
* si470x_usb_driver - usb driver interface
@@ -1462,7 +1510,10 @@ static struct usb_driver si470x_usb_driver = {
.name = DRIVER_NAME,
.probe = si470x_usb_driver_probe,
.disconnect = si470x_usb_driver_disconnect,
+ .suspend = si470x_usb_driver_suspend,
+ .resume = si470x_usb_driver_resume,
.id_table = si470x_usb_driver_id_table,
+ .supports_autosuspend = 1,
};
-
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html