[media] tlg2300: switch to v4l2_fh
authorHans Verkuil <hans.verkuil@cisco.com>
Mon, 16 Jul 2012 10:53:36 +0000 (07:53 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 4 Mar 2013 20:33:46 +0000 (17:33 -0300)
This switch to v4l2_fh resolves the last v4l2_compliance issues with respect
to control events and priority handling.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Huang Shijie <shijie8@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/usb/tlg2300/pd-common.h
drivers/media/usb/tlg2300/pd-main.c
drivers/media/usb/tlg2300/pd-radio.c

index b26082af1b5264d15edd55b55de42133f456210c..67ad065d2c3c515c2bd684842bbecc772525fb24 100644 (file)
@@ -116,7 +116,6 @@ struct poseidon_audio {
 
 struct radio_data {
        __u32           fm_freq;
-       int             users;
        unsigned int    is_radio_streaming;
        int             pre_emphasis;
        struct video_device fm_dev;
index 247d6ac9994741e084b3bb2119ab917aa321a806..e07e4c699cc215344b86f10433f659a088617d00 100644 (file)
@@ -267,7 +267,8 @@ static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
 static inline int get_autopm_ref(struct poseidon *pd)
 {
        return  pd->video_data.users + pd->vbi_data.users + pd->audio.users
-               + atomic_read(&pd->dvb_data.users) + pd->radio_data.users;
+               + atomic_read(&pd->dvb_data.users) +
+               !list_empty(&pd->radio_data.fm_dev.fh_list);
 }
 
 /* fixup something for poseidon */
index 45b3d7a769f9a602cc567edbe11377c64e8ab5b7..854ffa007c1f744a77ce03407ffe8141020513c2 100644 (file)
@@ -9,6 +9,8 @@
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
 #include <linux/sched.h>
 
 #include "pd-common.h"
@@ -77,13 +79,9 @@ static int pm_fm_resume(struct poseidon *p)
 
 static int poseidon_fm_open(struct file *filp)
 {
-       struct video_device *vfd = video_devdata(filp);
-       struct poseidon *p = video_get_drvdata(vfd);
+       struct poseidon *p = video_drvdata(filp);
        int ret = 0;
 
-       if (!p)
-               return -1;
-
        mutex_lock(&p->lock);
        if (p->state & POSEIDON_STATE_DISCONNECT) {
                ret = -ENODEV;
@@ -94,9 +92,14 @@ static int poseidon_fm_open(struct file *filp)
                ret = -EBUSY;
                goto out;
        }
+       ret = v4l2_fh_open(filp);
+       if (ret)
+               goto out;
 
        usb_autopm_get_interface(p->interface);
        if (0 == p->state) {
+               struct video_device *vfd = &p->radio_data.fm_dev;
+
                /* default pre-emphasis */
                if (p->radio_data.pre_emphasis == 0)
                        p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR;
@@ -109,9 +112,7 @@ static int poseidon_fm_open(struct file *filp)
                }
                p->state |= POSEIDON_STATE_FM;
        }
-       p->radio_data.users++;
        kref_get(&p->kref);
-       filp->private_data = p;
 out:
        mutex_unlock(&p->lock);
        return ret;
@@ -119,13 +120,12 @@ out:
 
 static int poseidon_fm_close(struct file *filp)
 {
-       struct poseidon *p = filp->private_data;
+       struct poseidon *p = video_drvdata(filp);
        struct radio_data *fm = &p->radio_data;
        uint32_t status;
 
        mutex_lock(&p->lock);
-       fm->users--;
-       if (0 == fm->users)
+       if (v4l2_fh_is_singular_file(filp))
                p->state &= ~POSEIDON_STATE_FM;
 
        if (fm->is_radio_streaming && filp == p->file_for_stream) {
@@ -136,14 +136,13 @@ static int poseidon_fm_close(struct file *filp)
        mutex_unlock(&p->lock);
 
        kref_put(&p->kref, poseidon_delete);
-       filp->private_data = NULL;
-       return 0;
+       return v4l2_fh_release(filp);
 }
 
 static int vidioc_querycap(struct file *file, void *priv,
                        struct v4l2_capability *v)
 {
-       struct poseidon *p = file->private_data;
+       struct poseidon *p = video_drvdata(file);
 
        strlcpy(v->driver, "tele-radio", sizeof(v->driver));
        strlcpy(v->card, "Telegent Poseidon", sizeof(v->card));
@@ -156,15 +155,16 @@ static const struct v4l2_file_operations poseidon_fm_fops = {
        .owner         = THIS_MODULE,
        .open          = poseidon_fm_open,
        .release       = poseidon_fm_close,
+       .poll           = v4l2_ctrl_poll,
        .unlocked_ioctl = video_ioctl2,
 };
 
 static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv,
                                 struct v4l2_tuner *vt)
 {
+       struct poseidon *p = video_drvdata(file);
        struct tuner_fm_sig_stat_s fm_stat = {};
        int ret, status, count = 5;
-       struct poseidon *p = file->private_data;
 
        if (vt->index != 0)
                return -EINVAL;
@@ -206,7 +206,7 @@ static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv,
 static int fm_get_freq(struct file *file, void *priv,
                       struct v4l2_frequency *argp)
 {
-       struct poseidon *p = file->private_data;
+       struct poseidon *p = video_drvdata(file);
 
        if (argp->tuner)
                return -EINVAL;
@@ -249,7 +249,7 @@ error:
 static int fm_set_freq(struct file *file, void *priv,
                       struct v4l2_frequency *argp)
 {
-       struct poseidon *p = file->private_data;
+       struct poseidon *p = video_drvdata(file);
 
        if (argp->tuner)
                return -EINVAL;
@@ -293,6 +293,8 @@ static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = {
        .vidioc_g_tuner     = tlg_fm_vidioc_g_tuner,
        .vidioc_g_frequency = fm_get_freq,
        .vidioc_s_frequency = fm_set_freq,
+       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static struct video_device poseidon_fm_template = {
@@ -320,6 +322,7 @@ int poseidon_fm_init(struct poseidon *p)
        }
        vfd->v4l2_dev = &p->v4l2_dev;
        vfd->ctrl_handler = hdl;
+       set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
        video_set_drvdata(vfd, p);
        return video_register_device(vfd, VFL_TYPE_RADIO, -1);
 }