[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]; 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 - " IVTV_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - "
"skipping\n", __func__); "skipping\n", __func__);
return 0; 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]; 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.itv = itv;
item.type = s->type; 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; return 0;
free_streams: free_streams:
ivtv_streams_cleanup(itv, 1); ivtv_streams_cleanup(itv);
free_irq: free_irq:
free_irq(itv->pdev->irq, (void *)itv); free_irq(itv->pdev->irq, (void *)itv);
free_i2c: free_i2c:
@ -1444,7 +1444,7 @@ static void ivtv_remove(struct pci_dev *pdev)
flush_kthread_worker(&itv->irq_worker); flush_kthread_worker(&itv->irq_worker);
kthread_stop(itv->irq_worker_task); kthread_stop(itv->irq_worker_task);
ivtv_streams_cleanup(itv, 1); ivtv_streams_cleanup(itv);
ivtv_udma_free(itv); ivtv_udma_free(itv);
v4l2_ctrl_handler_free(&itv->cxhdl.hdl); v4l2_ctrl_handler_free(&itv->cxhdl.hdl);

View file

@ -327,7 +327,7 @@ struct ivtv; /* forward reference */
struct ivtv_stream { struct ivtv_stream {
/* These first four fields are always set, even if the stream /* These first four fields are always set, even if the stream
is not actually created. */ 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 */ struct ivtv *itv; /* for ease of use */
const char *name; /* name of the stream */ const char *name; /* name of the stream */
int type; /* stream type */ 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"); IVTV_DEBUG_WARN("nomem on v4l2 open\n");
return -ENOMEM; return -ENOMEM;
} }
v4l2_fh_init(&item->fh, s->vdev); v4l2_fh_init(&item->fh, &s->vdev);
item->itv = itv; item->itv = itv;
item->type = s->type; item->type = s->type;

View file

@ -987,7 +987,7 @@ int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
else else
std = V4L2_STD_ALL; std = V4L2_STD_ALL;
for (i = 0; i <= IVTV_ENC_STREAM_TYPE_VBI; i++) 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 /* prevent others from messing with the streams until
we're finished changing inputs. */ 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 *itv = fh2id(fh)->itv;
struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
if (s->vdev->vfl_dir) if (s->vdev.vfl_dir)
return -ENOTTY; return -ENOTTY;
if (vf->tuner != 0) if (vf->tuner != 0)
return -EINVAL; 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 *itv = fh2id(fh)->itv;
struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
if (s->vdev->vfl_dir) if (s->vdev.vfl_dir)
return -ENOTTY; return -ENOTTY;
if (vf->tuner != 0) if (vf->tuner != 0)
return -EINVAL; return -EINVAL;
@ -1547,7 +1547,7 @@ static int ivtv_log_status(struct file *file, void *fh)
for (i = 0; i < IVTV_MAX_STREAMS; i++) { for (i = 0; i < IVTV_MAX_STREAMS; i++) {
struct ivtv_stream *s = &itv->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; continue;
IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags, 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, (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"); IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n");
if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS || 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; itv->cur_pio_stream = -1;
/* trigger PIO complete user interrupt */ /* trigger PIO complete user interrupt */
write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); 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; int rc;
/* sanity checks */ /* sanity checks */
if (s->vdev == NULL) { if (s->vdev.v4l2_dev == NULL) {
IVTV_DEBUG_WARN("Stream %s not started\n", s->name); IVTV_DEBUG_WARN("Stream %s not started\n", s->name);
return -1; return -1;
} }
@ -890,8 +890,8 @@ static void ivtv_irq_vsync(struct ivtv *itv)
if (s) if (s)
wake_up(&s->waitq); wake_up(&s->waitq);
} }
if (s && s->vdev) if (s && s->vdev.v4l2_dev)
v4l2_event_queue(s->vdev, frame ? &evtop : &evbottom); v4l2_event_queue(&s->vdev, frame ? &evtop : &evbottom);
wake_up(&itv->vsync_waitq); wake_up(&itv->vsync_waitq);
/* Send VBI to saa7127 */ /* Send VBI to saa7127 */

View file

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