diff options
Diffstat (limited to 'drivers/media/video/cx18/cx18-fileops.c')
-rw-r--r-- | drivers/media/video/cx18/cx18-fileops.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index e9802d99439b..07411f34885a 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -597,6 +597,13 @@ ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count, mutex_unlock(&cx->serialize_lock); if (rc) return rc; + + if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) && + (id->type == CX18_ENC_STREAM_TYPE_YUV)) { + return videobuf_read_stream(&s->vbuf_q, buf, count, pos, 0, + filp->f_flags & O_NONBLOCK); + } + return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); } @@ -622,6 +629,15 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) CX18_DEBUG_FILE("Encoder poll started capture\n"); } + if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) && + (id->type == CX18_ENC_STREAM_TYPE_YUV)) { + int videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait); + if (eof && videobuf_poll == POLLERR) + return POLLHUP; + else + return videobuf_poll; + } + /* add stream's waitq to the poll list */ CX18_DEBUG_HI_FILE("Encoder poll\n"); poll_wait(filp, &s->waitq, wait); @@ -633,6 +649,58 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) return 0; } +int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct cx18_open_id *id = file->private_data; + struct cx18 *cx = id->cx; + struct cx18_stream *s = &cx->streams[id->type]; + int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags); + + if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) && + (id->type == CX18_ENC_STREAM_TYPE_YUV)) { + + /* Start a capture if there is none */ + if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) { + int rc; + + mutex_lock(&cx->serialize_lock); + rc = cx18_start_capture(id); + mutex_unlock(&cx->serialize_lock); + if (rc) { + CX18_DEBUG_INFO( + "Could not start capture for %s (%d)\n", + s->name, rc); + return -EINVAL; + } + CX18_DEBUG_FILE("Encoder mmap started capture\n"); + } + + return videobuf_mmap_mapper(&s->vbuf_q, vma); + } + + return -EINVAL; +} + +void cx18_vb_timeout(unsigned long data) +{ + struct cx18_stream *s = (struct cx18_stream *)data; + struct cx18_videobuf_buffer *buf; + unsigned long flags; + + /* Return all of the buffers in error state, so the vbi/vid inode + * can return from blocking. + */ + spin_lock_irqsave(&s->vb_lock, flags); + while (!list_empty(&s->vb_capture)) { + buf = list_entry(s->vb_capture.next, + struct cx18_videobuf_buffer, vb.queue); + list_del(&buf->vb.queue); + buf->vb.state = VIDEOBUF_ERROR; + wake_up(&buf->vb.done); + } + spin_unlock_irqrestore(&s->vb_lock, flags); +} + void cx18_stop_capture(struct cx18_open_id *id, int gop_end) { struct cx18 *cx = id->cx; @@ -716,6 +784,8 @@ int cx18_v4l2_close(struct file *filp) cx18_release_stream(s); } else { cx18_stop_capture(id, 0); + if (id->type == CX18_ENC_STREAM_TYPE_YUV) + videobuf_mmap_free(&id->vbuf_q); } kfree(id); mutex_unlock(&cx->serialize_lock); |