于 2013年01月31日 05:25, Hans Verkuil 写道:
> From: Hans Verkuil <hans.verk...@cisco.com>
>
> 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.verk...@cisco.com>
> ---
> drivers/media/usb/tlg2300/pd-common.h | 1 -
> drivers/media/usb/tlg2300/pd-main.c | 3 ++-
> drivers/media/usb/tlg2300/pd-radio.c | 35
> ++++++++++++++++++---------------
> 3 files changed, 21 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/media/usb/tlg2300/pd-common.h
> b/drivers/media/usb/tlg2300/pd-common.h
> index b26082a..67ad065 100644
> --- a/drivers/media/usb/tlg2300/pd-common.h
> +++ b/drivers/media/usb/tlg2300/pd-common.h
> @@ -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;
> diff --git a/drivers/media/usb/tlg2300/pd-main.c
> b/drivers/media/usb/tlg2300/pd-main.c
> index c4eb57a..5be5a73 100644
> --- a/drivers/media/usb/tlg2300/pd-main.c
> +++ b/drivers/media/usb/tlg2300/pd-main.c
> @@ -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 */
> diff --git a/drivers/media/usb/tlg2300/pd-radio.c
> b/drivers/media/usb/tlg2300/pd-radio.c
> index 45b3d7a..854ffa0 100644
> --- a/drivers/media/usb/tlg2300/pd-radio.c
> +++ b/drivers/media/usb/tlg2300/pd-radio.c
> @@ -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);
> }
Acked-by: Huang Shijie <shij...@gmail.com>
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html