V4L/DVB (10053): radio-mr800: disable autosuspend support
[profile/ivi/kernel-x86-ivi.git] / drivers / media / radio / radio-mr800.c
index 256cbef..e730edd 100644 (file)
@@ -72,6 +72,11 @@ MODULE_LICENSE("GPL");
 #define USB_AMRADIO_VENDOR 0x07ca
 #define USB_AMRADIO_PRODUCT 0xb800
 
+/* dev_warn macro with driver name */
+#define MR800_DRIVER_NAME "radio-mr800"
+#define amradio_dev_warn(dev, fmt, arg...)                             \
+               dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
+
 /* Probably USB_TIMEOUT should be modified in module parameter */
 #define BUFFER_LENGTH 8
 #define USB_TIMEOUT 500
@@ -154,14 +159,14 @@ MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
 
 /* USB subsystem interface */
 static struct usb_driver usb_amradio_driver = {
-       .name                   = "radio-mr800",
+       .name                   = MR800_DRIVER_NAME,
        .probe                  = usb_amradio_probe,
        .disconnect             = usb_amradio_disconnect,
        .suspend                = usb_amradio_suspend,
        .resume                 = usb_amradio_resume,
        .reset_resume           = usb_amradio_resume,
        .id_table               = usb_amradio_device_table,
-       .supports_autosuspend   = 1,
+       .supports_autosuspend   = 0,
 };
 
 /* switch on radio. Send 8 bytes to device. */
@@ -202,6 +207,10 @@ static int amradio_stop(struct amradio_device *radio)
        int retval;
        int size;
 
+       /* safety check */
+       if (radio->removed)
+               return -EIO;
+
        mutex_lock(&radio->lock);
 
        radio->buffer[0] = 0x00;
@@ -235,6 +244,10 @@ static int amradio_setfreq(struct amradio_device *radio, int freq)
        int size;
        unsigned short freq_send = 0x13 + (freq >> 3) / 25;
 
+       /* safety check */
+       if (radio->removed)
+               return -EIO;
+
        mutex_lock(&radio->lock);
 
        radio->buffer[0] = 0x00;
@@ -288,18 +301,12 @@ static void usb_amradio_disconnect(struct usb_interface *intf)
 {
        struct amradio_device *radio = usb_get_intfdata(intf);
 
-       usb_set_intfdata(intf, NULL);
+       mutex_lock(&radio->lock);
+       radio->removed = 1;
+       mutex_unlock(&radio->lock);
 
-       if (radio) {
-               video_unregister_device(radio->videodev);
-               radio->videodev = NULL;
-               if (radio->users) {
-                       kfree(radio->buffer);
-                       kfree(radio);
-               } else {
-                       radio->removed = 1;
-               }
-       }
+       usb_set_intfdata(intf, NULL);
+       video_unregister_device(radio->videodev);
 }
 
 /* vidioc_querycap - query device capabilities */
@@ -320,6 +327,10 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 {
        struct amradio_device *radio = video_get_drvdata(video_devdata(file));
 
+       /* safety check */
+       if (radio->removed)
+               return -EIO;
+
        if (v->index > 0)
                return -EINVAL;
 
@@ -346,6 +357,12 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 static int vidioc_s_tuner(struct file *file, void *priv,
                                struct v4l2_tuner *v)
 {
+       struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+       /* safety check */
+       if (radio->removed)
+               return -EIO;
+
        if (v->index > 0)
                return -EINVAL;
        return 0;
@@ -357,9 +374,14 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 {
        struct amradio_device *radio = video_get_drvdata(video_devdata(file));
 
+       /* safety check */
+       if (radio->removed)
+               return -EIO;
+
        radio->curfreq = f->frequency;
        if (amradio_setfreq(radio, radio->curfreq) < 0)
-               warn("Set frequency failed");
+               amradio_dev_warn(&radio->videodev->dev,
+                       "set frequency failed\n");
        return 0;
 }
 
@@ -369,6 +391,10 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 {
        struct amradio_device *radio = video_get_drvdata(video_devdata(file));
 
+       /* safety check */
+       if (radio->removed)
+               return -EIO;
+
        f->type = V4L2_TUNER_RADIO;
        f->frequency = radio->curfreq;
        return 0;
@@ -382,8 +408,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
 
        for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
                if (qc->id && qc->id == radio_qctrl[i].id) {
-                       memcpy(qc, &(radio_qctrl[i]),
-                                               sizeof(*qc));
+                       memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
                        return 0;
                }
        }
@@ -396,6 +421,10 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 {
        struct amradio_device *radio = video_get_drvdata(video_devdata(file));
 
+       /* safety check */
+       if (radio->removed)
+               return -EIO;
+
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
                ctrl->value = radio->muted;
@@ -410,16 +439,22 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 {
        struct amradio_device *radio = video_get_drvdata(video_devdata(file));
 
+       /* safety check */
+       if (radio->removed)
+               return -EIO;
+
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
                if (ctrl->value) {
                        if (amradio_stop(radio) < 0) {
-                               warn("amradio_stop() failed");
+                               amradio_dev_warn(&radio->videodev->dev,
+                                       "amradio_stop failed\n");
                                return -1;
                        }
                } else {
                        if (amradio_start(radio) < 0) {
-                               warn("amradio_start() failed");
+                               amradio_dev_warn(&radio->videodev->dev,
+                                       "amradio_start failed\n");
                                return -1;
                        }
                }
@@ -475,30 +510,38 @@ static int usb_amradio_open(struct inode *inode, struct file *file)
        radio->muted = 1;
 
        if (amradio_start(radio) < 0) {
-               warn("Radio did not start up properly");
+               amradio_dev_warn(&radio->videodev->dev,
+                       "radio did not start up properly\n");
                radio->users = 0;
                unlock_kernel();
                return -EIO;
        }
        if (amradio_setfreq(radio, radio->curfreq) < 0)
-               warn("Set frequency failed");
+               amradio_dev_warn(&radio->videodev->dev,
+                       "set frequency failed\n");
 
        unlock_kernel();
        return 0;
 }
 
-/*close device - free driver structures */
+/*close device */
 static int usb_amradio_close(struct inode *inode, struct file *file)
 {
        struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+       int retval;
 
        if (!radio)
                return -ENODEV;
+
        radio->users = 0;
-       if (radio->removed) {
-               kfree(radio->buffer);
-               kfree(radio);
+
+       if (!radio->removed) {
+               retval = amradio_stop(radio);
+               if (retval < 0)
+                       amradio_dev_warn(&radio->videodev->dev,
+                               "amradio_stop failed\n");
        }
+
        return 0;
 }
 
@@ -508,9 +551,9 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
        struct amradio_device *radio = usb_get_intfdata(intf);
 
        if (amradio_stop(radio) < 0)
-               warn("amradio_stop() failed");
+               dev_warn(&intf->dev, "amradio_stop failed\n");
 
-       info("radio-mr800: Going into suspend..");
+       dev_info(&intf->dev, "going into suspend..\n");
 
        return 0;
 }
@@ -521,9 +564,9 @@ static int usb_amradio_resume(struct usb_interface *intf)
        struct amradio_device *radio = usb_get_intfdata(intf);
 
        if (amradio_start(radio) < 0)
-               warn("amradio_start() failed");
+               dev_warn(&intf->dev, "amradio_start failed\n");
 
-       info("radio-mr800: Coming out of suspend..");
+       dev_info(&intf->dev, "coming out of suspend..\n");
 
        return 0;
 }
@@ -555,12 +598,24 @@ static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
        .vidioc_s_input     = vidioc_s_input,
 };
 
+static void usb_amradio_device_release(struct video_device *videodev)
+{
+       struct amradio_device *radio = video_get_drvdata(videodev);
+
+       /* we call v4l to free radio->videodev */
+       video_device_release(videodev);
+
+       /* free rest memory */
+       kfree(radio->buffer);
+       kfree(radio);
+}
+
 /* V4L2 interface */
 static struct video_device amradio_videodev_template = {
        .name           = "AverMedia MR 800 USB FM Radio",
        .fops           = &usb_amradio_fops,
        .ioctl_ops      = &usb_amradio_ioctl_ops,
-       .release        = video_device_release,
+       .release        = usb_amradio_device_release,
 };
 
 /* check if the device is present and register with v4l and
@@ -602,7 +657,7 @@ static int usb_amradio_probe(struct usb_interface *intf,
 
        video_set_drvdata(radio->videodev, radio);
        if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
-               warn("Could not register video device");
+               dev_warn(&intf->dev, "could not register video device\n");
                video_device_release(radio->videodev);
                kfree(radio->buffer);
                kfree(radio);
@@ -617,9 +672,13 @@ static int __init amradio_init(void)
 {
        int retval = usb_register(&usb_amradio_driver);
 
-       info(DRIVER_VERSION " " DRIVER_DESC);
+       pr_info(KBUILD_MODNAME
+               ": version " DRIVER_VERSION " " DRIVER_DESC "\n");
+
        if (retval)
-               err("usb_register failed. Error number %d", retval);
+               pr_err(KBUILD_MODNAME
+                       ": usb_register failed. Error number %d\n", retval);
+
        return retval;
 }