mirror of https://gitee.com/openkylin/linux.git
[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: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Huang Shijie <shijie8@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
173fdb8aff
commit
668cb00ed5
|
@ -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)
|
||||||
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 @@
|
||||||
#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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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 = {
|
||||||
.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,
|
||||||
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)
|
||||||
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 = {
|
||||||
.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)
|
||||||
}
|
}
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue