Commit 668cb00e authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

[media] tlg2300: switch to v4l2_fh

This switch to v4l2_fh resolves the last v4l2_compliance issues with respect
to control events and priority handling.
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Acked-by: default avatarHuang Shijie <shijie8@gmail.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 173fdb8a
...@@ -116,7 +116,6 @@ struct poseidon_audio { ...@@ -116,7 +116,6 @@ struct poseidon_audio {
struct radio_data { struct radio_data {
__u32 fm_freq; __u32 fm_freq;
int users;
unsigned int is_radio_streaming; unsigned int is_radio_streaming;
int pre_emphasis; int pre_emphasis;
struct video_device fm_dev; struct video_device fm_dev;
......
...@@ -267,7 +267,8 @@ static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) ...@@ -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) static inline int get_autopm_ref(struct poseidon *pd)
{ {
return pd->video_data.users + pd->vbi_data.users + pd->audio.users 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 */ /* fixup something for poseidon */
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fh.h>
#include <linux/sched.h> #include <linux/sched.h>
#include "pd-common.h" #include "pd-common.h"
...@@ -77,13 +79,9 @@ static int pm_fm_resume(struct poseidon *p) ...@@ -77,13 +79,9 @@ static int pm_fm_resume(struct poseidon *p)
static int poseidon_fm_open(struct file *filp) static int poseidon_fm_open(struct file *filp)
{ {
struct video_device *vfd = video_devdata(filp); struct poseidon *p = video_drvdata(filp);
struct poseidon *p = video_get_drvdata(vfd);
int ret = 0; int ret = 0;
if (!p)
return -1;
mutex_lock(&p->lock); mutex_lock(&p->lock);
if (p->state & POSEIDON_STATE_DISCONNECT) { if (p->state & POSEIDON_STATE_DISCONNECT) {
ret = -ENODEV; ret = -ENODEV;
...@@ -94,9 +92,14 @@ static int poseidon_fm_open(struct file *filp) ...@@ -94,9 +92,14 @@ static int poseidon_fm_open(struct file *filp)
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
} }
ret = v4l2_fh_open(filp);
if (ret)
goto out;
usb_autopm_get_interface(p->interface); usb_autopm_get_interface(p->interface);
if (0 == p->state) { if (0 == p->state) {
struct video_device *vfd = &p->radio_data.fm_dev;
/* default pre-emphasis */ /* default pre-emphasis */
if (p->radio_data.pre_emphasis == 0) if (p->radio_data.pre_emphasis == 0)
p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR; p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR;
...@@ -109,9 +112,7 @@ static int poseidon_fm_open(struct file *filp) ...@@ -109,9 +112,7 @@ static int poseidon_fm_open(struct file *filp)
} }
p->state |= POSEIDON_STATE_FM; p->state |= POSEIDON_STATE_FM;
} }
p->radio_data.users++;
kref_get(&p->kref); kref_get(&p->kref);
filp->private_data = p;
out: out:
mutex_unlock(&p->lock); mutex_unlock(&p->lock);
return ret; return ret;
...@@ -119,13 +120,12 @@ static int poseidon_fm_open(struct file *filp) ...@@ -119,13 +120,12 @@ static int poseidon_fm_open(struct file *filp)
static int poseidon_fm_close(struct file *filp) 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; struct radio_data *fm = &p->radio_data;
uint32_t status; uint32_t status;
mutex_lock(&p->lock); mutex_lock(&p->lock);
fm->users--; if (v4l2_fh_is_singular_file(filp))
if (0 == fm->users)
p->state &= ~POSEIDON_STATE_FM; p->state &= ~POSEIDON_STATE_FM;
if (fm->is_radio_streaming && filp == p->file_for_stream) { if (fm->is_radio_streaming && filp == p->file_for_stream) {
...@@ -136,14 +136,13 @@ static int poseidon_fm_close(struct file *filp) ...@@ -136,14 +136,13 @@ static int poseidon_fm_close(struct file *filp)
mutex_unlock(&p->lock); mutex_unlock(&p->lock);
kref_put(&p->kref, poseidon_delete); kref_put(&p->kref, poseidon_delete);
filp->private_data = NULL; return v4l2_fh_release(filp);
return 0;
} }
static int vidioc_querycap(struct file *file, void *priv, static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *v) 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->driver, "tele-radio", sizeof(v->driver));
strlcpy(v->card, "Telegent Poseidon", sizeof(v->card)); strlcpy(v->card, "Telegent Poseidon", sizeof(v->card));
...@@ -156,15 +155,16 @@ static const struct v4l2_file_operations poseidon_fm_fops = { ...@@ -156,15 +155,16 @@ static const struct v4l2_file_operations poseidon_fm_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = poseidon_fm_open, .open = poseidon_fm_open,
.release = poseidon_fm_close, .release = poseidon_fm_close,
.poll = v4l2_ctrl_poll,
.unlocked_ioctl = video_ioctl2, .unlocked_ioctl = video_ioctl2,
}; };
static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv, static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *vt) struct v4l2_tuner *vt)
{ {
struct poseidon *p = video_drvdata(file);
struct tuner_fm_sig_stat_s fm_stat = {}; struct tuner_fm_sig_stat_s fm_stat = {};
int ret, status, count = 5; int ret, status, count = 5;
struct poseidon *p = file->private_data;
if (vt->index != 0) if (vt->index != 0)
return -EINVAL; return -EINVAL;
...@@ -206,7 +206,7 @@ static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv, ...@@ -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, static int fm_get_freq(struct file *file, void *priv,
struct v4l2_frequency *argp) struct v4l2_frequency *argp)
{ {
struct poseidon *p = file->private_data; struct poseidon *p = video_drvdata(file);
if (argp->tuner) if (argp->tuner)
return -EINVAL; return -EINVAL;
...@@ -249,7 +249,7 @@ static int set_frequency(struct poseidon *p, __u32 frequency) ...@@ -249,7 +249,7 @@ static int set_frequency(struct poseidon *p, __u32 frequency)
static int fm_set_freq(struct file *file, void *priv, static int fm_set_freq(struct file *file, void *priv,
struct v4l2_frequency *argp) struct v4l2_frequency *argp)
{ {
struct poseidon *p = file->private_data; struct poseidon *p = video_drvdata(file);
if (argp->tuner) if (argp->tuner)
return -EINVAL; return -EINVAL;
...@@ -293,6 +293,8 @@ static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = { ...@@ -293,6 +293,8 @@ static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = {
.vidioc_g_tuner = tlg_fm_vidioc_g_tuner, .vidioc_g_tuner = tlg_fm_vidioc_g_tuner,
.vidioc_g_frequency = fm_get_freq, .vidioc_g_frequency = fm_get_freq,
.vidioc_s_frequency = fm_set_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 = { static struct video_device poseidon_fm_template = {
...@@ -320,6 +322,7 @@ int poseidon_fm_init(struct poseidon *p) ...@@ -320,6 +322,7 @@ int poseidon_fm_init(struct poseidon *p)
} }
vfd->v4l2_dev = &p->v4l2_dev; vfd->v4l2_dev = &p->v4l2_dev;
vfd->ctrl_handler = hdl; vfd->ctrl_handler = hdl;
set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
video_set_drvdata(vfd, p); video_set_drvdata(vfd, p);
return video_register_device(vfd, VFL_TYPE_RADIO, -1); return video_register_device(vfd, VFL_TYPE_RADIO, -1);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment