Merge branch 'sh-latest' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal...
[pandora-kernel.git] / drivers / media / video / cx18 / cx18-fileops.c
index e9802d9..07411f3 100644 (file)
@@ -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);