[media] media: au0828 video change to use v4l_enable_media_source()
authorShuah Khan <shuahkh@osg.samsung.com>
Thu, 11 Feb 2016 23:41:37 +0000 (21:41 -0200)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Sat, 27 Feb 2016 12:35:18 +0000 (09:35 -0300)
Change au0828 to check if tuner is free or not before changing tuner
configuration.

vidioc_g_tuner(), and au0828_v4l2_close() now call v4l-core interface
v4l_enable_media_source() before changing tuner configuration.

Remove au0828_enable_analog_tuner() as it is no longer needed because
v4l2-core implements common interfaces to check for media source
availability.

In addition, queue_setup() no longer needs the tuner availability check
since v4l2-core does it.

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/usb/au0828/au0828-video.c

index 25e27c86e9ca55aa4769f0f3b5fadc5635dba424..1958de192608b3a2e8f80c2c27a9df66d425f180 100644 (file)
@@ -796,64 +796,6 @@ int au0828_v4l2_device_register(struct usb_interface *interface,
        return 0;
 }
 
-static int au0828_enable_analog_tuner(struct au0828_dev *dev)
-{
-#ifdef CONFIG_MEDIA_CONTROLLER
-       struct media_device *mdev = dev->media_dev;
-       struct media_entity *source;
-       struct media_link *link, *found_link = NULL;
-       int ret, active_links = 0;
-
-       if (!mdev || !dev->decoder)
-               return 0;
-
-       /*
-        * This will find the tuner that is connected into the decoder.
-        * Technically, this is not 100% correct, as the device may be
-        * using an analog input instead of the tuner. However, as we can't
-        * do DVB streaming while the DMA engine is being used for V4L2,
-        * this should be enough for the actual needs.
-        */
-       list_for_each_entry(link, &dev->decoder->links, list) {
-               if (link->sink->entity == dev->decoder) {
-                       found_link = link;
-                       if (link->flags & MEDIA_LNK_FL_ENABLED)
-                               active_links++;
-                       break;
-               }
-       }
-
-       if (active_links == 1 || !found_link)
-               return 0;
-
-       source = found_link->source->entity;
-       list_for_each_entry(link, &source->links, list) {
-               struct media_entity *sink;
-               int flags = 0;
-
-               sink = link->sink->entity;
-
-               if (sink == dev->decoder)
-                       flags = MEDIA_LNK_FL_ENABLED;
-
-               ret = media_entity_setup_link(link, flags);
-               if (ret) {
-                       pr_err(
-                               "Couldn't change link %s->%s to %s. Error %d\n",
-                               source->name, sink->name,
-                               flags ? "enabled" : "disabled",
-                               ret);
-                       return ret;
-               } else
-                       au0828_isocdbg(
-                               "link %s->%s was %s\n",
-                               source->name, sink->name,
-                               flags ? "ENABLED" : "disabled");
-       }
-#endif
-       return 0;
-}
-
 static int queue_setup(struct vb2_queue *vq,
                       unsigned int *nbuffers, unsigned int *nplanes,
                       unsigned int sizes[], void *alloc_ctxs[])
@@ -865,9 +807,6 @@ static int queue_setup(struct vb2_queue *vq,
                return sizes[0] < size ? -EINVAL : 0;
        *nplanes = 1;
        sizes[0] = size;
-
-       au0828_enable_analog_tuner(dev);
-
        return 0;
 }
 
@@ -1235,8 +1174,39 @@ static int au0828_v4l2_close(struct file *filp)
                goto end;
 
        if (dev->users == 1) {
-               /* Save some power by putting tuner to sleep */
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
+               /*
+                * Avoid putting tuner in sleep if DVB or ALSA are
+                * streaming.
+                *
+                * On most USB devices  like au0828 the tuner can
+                * be safely put in sleep stare here if ALSA isn't
+                * streaming. Exceptions are some very old USB tuner
+                * models such as em28xx-based WinTV USB2 which have
+                * a separate audio output jack. The devices that have
+                * a separate audio output jack have analog tuners,
+                * like Philips FM1236. Those devices are always on,
+                * so the s_power callback are silently ignored.
+                * So, the current logic here does the following:
+                * Disable (put tuner to sleep) when
+                * - ALSA and DVB aren't not streaming;
+                * - the last V4L2 file handler is closed.
+                *
+                * FIXME:
+                *
+                * Additionally, this logic could be improved to
+                * disable the media source if the above conditions
+                * are met and if the device:
+                * - doesn't have a separate audio out plug (or
+                * - doesn't use a silicon tuner like xc2028/3028/4000/5000).
+                *
+                * Once this additional logic is in place, a callback
+                * is needed to enable the media source and power on
+                * the tuner, for radio to work.
+               */
+               ret = v4l_enable_media_source(vdev);
+               if (ret == 0)
+                       v4l2_device_call_all(&dev->v4l2_dev, 0, core,
+                                            s_power, 0);
                dev->std_set_in_tuner_core = 0;
 
                /* When close the device, set the usb intf0 into alt0 to free
@@ -1636,10 +1606,16 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio
 static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 {
        struct au0828_dev *dev = video_drvdata(file);
+       struct video_device *vfd = video_devdata(file);
+       int ret;
 
        if (t->index != 0)
                return -EINVAL;
 
+       ret = v4l_enable_media_source(vfd);
+       if (ret)
+               return ret;
+
        dprintk(1, "%s called std_set %d dev_state %d\n", __func__,
                dev->std_set_in_tuner_core, dev->dev_state);