[media] ivtv: embed video_device

Embed the video_device struct to simplify the error handling and in
order to (eventually) get rid of video_device_alloc/release.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Andy Walls <awalls@md.metrocast.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
This commit is contained in:
Hans Verkuil 2015-03-09 13:33:55 -03:00 committed by Mauro Carvalho Chehab
parent b3226f961a
commit 635d62f073
9 changed files with 61 additions and 76 deletions

View File

@ -224,7 +224,7 @@ static int ivtv_alsa_load(struct ivtv *itv)
}
s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
if (s->vdev == NULL) {
if (s->vdev.v4l2_dev == NULL) {
IVTV_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - "
"skipping\n", __func__);
return 0;

View File

@ -167,7 +167,7 @@ static int snd_ivtv_pcm_capture_open(struct snd_pcm_substream *substream)
s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
v4l2_fh_init(&item.fh, s->vdev);
v4l2_fh_init(&item.fh, &s->vdev);
item.itv = itv;
item.type = s->type;

View File

@ -1284,7 +1284,7 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
return 0;
free_streams:
ivtv_streams_cleanup(itv, 1);
ivtv_streams_cleanup(itv);
free_irq:
free_irq(itv->pdev->irq, (void *)itv);
free_i2c:
@ -1444,7 +1444,7 @@ static void ivtv_remove(struct pci_dev *pdev)
flush_kthread_worker(&itv->irq_worker);
kthread_stop(itv->irq_worker_task);
ivtv_streams_cleanup(itv, 1);
ivtv_streams_cleanup(itv);
ivtv_udma_free(itv);
v4l2_ctrl_handler_free(&itv->cxhdl.hdl);

View File

@ -327,7 +327,7 @@ struct ivtv; /* forward reference */
struct ivtv_stream {
/* These first four fields are always set, even if the stream
is not actually created. */
struct video_device *vdev; /* NULL when stream not created */
struct video_device vdev; /* vdev.v4l2_dev is NULL if there is no device */
struct ivtv *itv; /* for ease of use */
const char *name; /* name of the stream */
int type; /* stream type */

View File

@ -995,7 +995,7 @@ static int ivtv_open(struct file *filp)
IVTV_DEBUG_WARN("nomem on v4l2 open\n");
return -ENOMEM;
}
v4l2_fh_init(&item->fh, s->vdev);
v4l2_fh_init(&item->fh, &s->vdev);
item->itv = itv;
item->type = s->type;

View File

@ -987,7 +987,7 @@ int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
else
std = V4L2_STD_ALL;
for (i = 0; i <= IVTV_ENC_STREAM_TYPE_VBI; i++)
itv->streams[i].vdev->tvnorms = std;
itv->streams[i].vdev.tvnorms = std;
/* prevent others from messing with the streams until
we're finished changing inputs. */
@ -1038,7 +1038,7 @@ static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *
struct ivtv *itv = fh2id(fh)->itv;
struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
if (s->vdev->vfl_dir)
if (s->vdev.vfl_dir)
return -ENOTTY;
if (vf->tuner != 0)
return -EINVAL;
@ -1052,7 +1052,7 @@ int ivtv_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *v
struct ivtv *itv = fh2id(fh)->itv;
struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
if (s->vdev->vfl_dir)
if (s->vdev.vfl_dir)
return -ENOTTY;
if (vf->tuner != 0)
return -EINVAL;
@ -1547,7 +1547,7 @@ static int ivtv_log_status(struct file *file, void *fh)
for (i = 0; i < IVTV_MAX_STREAMS; i++) {
struct ivtv_stream *s = &itv->streams[i];
if (s->vdev == NULL || s->buffers == 0)
if (s->vdev.v4l2_dev == NULL || s->buffers == 0)
continue;
IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
(s->buffers - s->q_free.buffers) * 100 / s->buffers,

View File

@ -75,7 +75,7 @@ static void ivtv_pio_work_handler(struct ivtv *itv)
IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n");
if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS ||
s->vdev == NULL || !ivtv_use_pio(s)) {
s->vdev.v4l2_dev == NULL || !ivtv_use_pio(s)) {
itv->cur_pio_stream = -1;
/* trigger PIO complete user interrupt */
write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
@ -132,7 +132,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
int rc;
/* sanity checks */
if (s->vdev == NULL) {
if (s->vdev.v4l2_dev == NULL) {
IVTV_DEBUG_WARN("Stream %s not started\n", s->name);
return -1;
}
@ -890,8 +890,8 @@ static void ivtv_irq_vsync(struct ivtv *itv)
if (s)
wake_up(&s->waitq);
}
if (s && s->vdev)
v4l2_event_queue(s->vdev, frame ? &evtop : &evbottom);
if (s && s->vdev.v4l2_dev)
v4l2_event_queue(&s->vdev, frame ? &evtop : &evbottom);
wake_up(&itv->vsync_waitq);
/* Send VBI to saa7127 */

View File

@ -159,11 +159,9 @@ static struct {
static void ivtv_stream_init(struct ivtv *itv, int type)
{
struct ivtv_stream *s = &itv->streams[type];
struct video_device *vdev = s->vdev;
/* we need to keep vdev, so restore it afterwards */
memset(s, 0, sizeof(*s));
s->vdev = vdev;
/* initialize ivtv_stream fields */
s->itv = itv;
@ -194,10 +192,10 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
int num_offset = ivtv_stream_info[type].num_offset;
int num = itv->instance + ivtv_first_minor + num_offset;
/* These four fields are always initialized. If vdev == NULL, then
/* These four fields are always initialized. If vdev.v4l2_dev == NULL, then
this stream is not in use. In that case no other fields but these
four can be used. */
s->vdev = NULL;
s->vdev.v4l2_dev = NULL;
s->itv = itv;
s->type = type;
s->name = ivtv_stream_info[type].name;
@ -218,40 +216,33 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
ivtv_stream_init(itv, type);
/* allocate and initialize the v4l2 video device structure */
s->vdev = video_device_alloc();
if (s->vdev == NULL) {
IVTV_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name);
return -ENOMEM;
}
snprintf(s->vdev->name, sizeof(s->vdev->name), "%s %s",
snprintf(s->vdev.name, sizeof(s->vdev.name), "%s %s",
itv->v4l2_dev.name, s->name);
s->vdev->num = num;
s->vdev->v4l2_dev = &itv->v4l2_dev;
s->vdev.num = num;
s->vdev.v4l2_dev = &itv->v4l2_dev;
if (ivtv_stream_info[type].v4l2_caps &
(V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_SLICED_VBI_OUTPUT))
s->vdev->vfl_dir = VFL_DIR_TX;
s->vdev->fops = ivtv_stream_info[type].fops;
s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler;
s->vdev->release = video_device_release;
s->vdev->tvnorms = V4L2_STD_ALL;
s->vdev->lock = &itv->serialize_lock;
s->vdev.vfl_dir = VFL_DIR_TX;
s->vdev.fops = ivtv_stream_info[type].fops;
s->vdev.ctrl_handler = itv->v4l2_dev.ctrl_handler;
s->vdev.release = video_device_release_empty;
s->vdev.tvnorms = V4L2_STD_ALL;
s->vdev.lock = &itv->serialize_lock;
if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
v4l2_disable_ioctl(s->vdev, VIDIOC_S_AUDIO);
v4l2_disable_ioctl(s->vdev, VIDIOC_G_AUDIO);
v4l2_disable_ioctl(s->vdev, VIDIOC_ENUMAUDIO);
v4l2_disable_ioctl(s->vdev, VIDIOC_ENUMINPUT);
v4l2_disable_ioctl(s->vdev, VIDIOC_S_INPUT);
v4l2_disable_ioctl(s->vdev, VIDIOC_G_INPUT);
v4l2_disable_ioctl(s->vdev, VIDIOC_S_FREQUENCY);
v4l2_disable_ioctl(s->vdev, VIDIOC_G_FREQUENCY);
v4l2_disable_ioctl(s->vdev, VIDIOC_S_TUNER);
v4l2_disable_ioctl(s->vdev, VIDIOC_G_TUNER);
v4l2_disable_ioctl(s->vdev, VIDIOC_S_STD);
v4l2_disable_ioctl(&s->vdev, VIDIOC_S_AUDIO);
v4l2_disable_ioctl(&s->vdev, VIDIOC_G_AUDIO);
v4l2_disable_ioctl(&s->vdev, VIDIOC_ENUMAUDIO);
v4l2_disable_ioctl(&s->vdev, VIDIOC_ENUMINPUT);
v4l2_disable_ioctl(&s->vdev, VIDIOC_S_INPUT);
v4l2_disable_ioctl(&s->vdev, VIDIOC_G_INPUT);
v4l2_disable_ioctl(&s->vdev, VIDIOC_S_FREQUENCY);
v4l2_disable_ioctl(&s->vdev, VIDIOC_G_FREQUENCY);
v4l2_disable_ioctl(&s->vdev, VIDIOC_S_TUNER);
v4l2_disable_ioctl(&s->vdev, VIDIOC_G_TUNER);
v4l2_disable_ioctl(&s->vdev, VIDIOC_S_STD);
}
ivtv_set_funcs(s->vdev);
ivtv_set_funcs(&s->vdev);
return 0;
}
@ -266,7 +257,7 @@ int ivtv_streams_setup(struct ivtv *itv)
if (ivtv_prep_dev(itv, type))
break;
if (itv->streams[type].vdev == NULL)
if (itv->streams[type].vdev.v4l2_dev == NULL)
continue;
/* Allocate Stream */
@ -277,7 +268,7 @@ int ivtv_streams_setup(struct ivtv *itv)
return 0;
/* One or more streams could not be initialized. Clean 'em all up. */
ivtv_streams_cleanup(itv, 0);
ivtv_streams_cleanup(itv);
return -ENOMEM;
}
@ -288,28 +279,26 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
const char *name;
int num;
if (s->vdev == NULL)
if (s->vdev.v4l2_dev == NULL)
return 0;
num = s->vdev->num;
num = s->vdev.num;
/* card number + user defined offset + device offset */
if (type != IVTV_ENC_STREAM_TYPE_MPG) {
struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG];
if (s_mpg->vdev)
num = s_mpg->vdev->num + ivtv_stream_info[type].num_offset;
if (s_mpg->vdev.v4l2_dev)
num = s_mpg->vdev.num + ivtv_stream_info[type].num_offset;
}
video_set_drvdata(s->vdev, s);
video_set_drvdata(&s->vdev, s);
/* Register device. First try the desired minor, then any free one. */
if (video_register_device_no_warn(s->vdev, vfl_type, num)) {
if (video_register_device_no_warn(&s->vdev, vfl_type, num)) {
IVTV_ERR("Couldn't register v4l2 device for %s (device node number %d)\n",
s->name, num);
video_device_release(s->vdev);
s->vdev = NULL;
return -ENOMEM;
}
name = video_device_node_name(s->vdev);
name = video_device_node_name(&s->vdev);
switch (vfl_type) {
case VFL_TYPE_GRABBER:
@ -346,29 +335,25 @@ int ivtv_streams_register(struct ivtv *itv)
return 0;
/* One or more streams could not be initialized. Clean 'em all up. */
ivtv_streams_cleanup(itv, 1);
ivtv_streams_cleanup(itv);
return -ENOMEM;
}
/* Unregister v4l2 devices */
void ivtv_streams_cleanup(struct ivtv *itv, int unregister)
void ivtv_streams_cleanup(struct ivtv *itv)
{
int type;
/* Teardown all streams */
for (type = 0; type < IVTV_MAX_STREAMS; type++) {
struct video_device *vdev = itv->streams[type].vdev;
struct video_device *vdev = &itv->streams[type].vdev;
itv->streams[type].vdev = NULL;
if (vdev == NULL)
if (vdev->v4l2_dev == NULL)
continue;
video_unregister_device(vdev);
ivtv_stream_free(&itv->streams[type]);
/* Unregister or release device */
if (unregister)
video_unregister_device(vdev);
else
video_device_release(vdev);
itv->streams[type].vdev.v4l2_dev = NULL;
}
}
@ -492,7 +477,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
int captype = 0, subtype = 0;
int enable_passthrough = 0;
if (s->vdev == NULL)
if (s->vdev.v4l2_dev == NULL)
return -EINVAL;
IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name);
@ -661,7 +646,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
u16 width;
u16 height;
if (s->vdev == NULL)
if (s->vdev.v4l2_dev == NULL)
return -EINVAL;
IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
@ -723,7 +708,7 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
struct ivtv *itv = s->itv;
int rc;
if (s->vdev == NULL)
if (s->vdev.v4l2_dev == NULL)
return -EINVAL;
if (test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags))
@ -778,7 +763,7 @@ void ivtv_stop_all_captures(struct ivtv *itv)
for (i = IVTV_MAX_STREAMS - 1; i >= 0; i--) {
struct ivtv_stream *s = &itv->streams[i];
if (s->vdev == NULL)
if (s->vdev.v4l2_dev == NULL)
continue;
if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
ivtv_stop_v4l2_encode_stream(s, 0);
@ -793,7 +778,7 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
int cap_type;
int stopmode;
if (s->vdev == NULL)
if (s->vdev.v4l2_dev == NULL)
return -EINVAL;
/* This function assumes that you are allowed to stop the capture
@ -917,7 +902,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
};
struct ivtv *itv = s->itv;
if (s->vdev == NULL)
if (s->vdev.v4l2_dev == NULL)
return -EINVAL;
if (s->type != IVTV_DEC_STREAM_TYPE_YUV && s->type != IVTV_DEC_STREAM_TYPE_MPG)
@ -969,7 +954,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
set_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags);
wake_up(&itv->event_waitq);
v4l2_event_queue(s->vdev, &ev);
v4l2_event_queue(&s->vdev, &ev);
/* wake up wait queues */
wake_up(&s->waitq);
@ -982,7 +967,7 @@ int ivtv_passthrough_mode(struct ivtv *itv, int enable)
struct ivtv_stream *yuv_stream = &itv->streams[IVTV_ENC_STREAM_TYPE_YUV];
struct ivtv_stream *dec_stream = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
if (yuv_stream->vdev == NULL || dec_stream->vdev == NULL)
if (yuv_stream->vdev.v4l2_dev == NULL || dec_stream->vdev.v4l2_dev == NULL)
return -EINVAL;
IVTV_DEBUG_INFO("ivtv ioctl: Select passthrough mode\n");

View File

@ -23,7 +23,7 @@
int ivtv_streams_setup(struct ivtv *itv);
int ivtv_streams_register(struct ivtv *itv);
void ivtv_streams_cleanup(struct ivtv *itv, int unregister);
void ivtv_streams_cleanup(struct ivtv *itv);
/* Capture related */
int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s);