|
@@ -1378,6 +1378,39 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(vb2_prepare_buf);
|
|
EXPORT_SYMBOL_GPL(vb2_prepare_buf);
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * vb2_start_streaming() - Attempt to start streaming.
|
|
|
|
+ * @q: videobuf2 queue
|
|
|
|
+ *
|
|
|
|
+ * If there are not enough buffers, then retry_start_streaming is set to
|
|
|
|
+ * 1 and 0 is returned. The next time a buffer is queued and
|
|
|
|
+ * retry_start_streaming is 1, this function will be called again to
|
|
|
|
+ * retry starting the DMA engine.
|
|
|
|
+ */
|
|
|
|
+static int vb2_start_streaming(struct vb2_queue *q)
|
|
|
|
+{
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ /* Tell the driver to start streaming */
|
|
|
|
+ ret = call_qop(q, start_streaming, q, atomic_read(&q->queued_count));
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * If there are not enough buffers queued to start streaming, then
|
|
|
|
+ * the start_streaming operation will return -ENOBUFS and you have to
|
|
|
|
+ * retry when the next buffer is queued.
|
|
|
|
+ */
|
|
|
|
+ if (ret == -ENOBUFS) {
|
|
|
|
+ dprintk(1, "qbuf: not enough buffers, retry when more buffers are queued.\n");
|
|
|
|
+ q->retry_start_streaming = 1;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ if (ret)
|
|
|
|
+ dprintk(1, "qbuf: driver refused to start streaming\n");
|
|
|
|
+ else
|
|
|
|
+ q->retry_start_streaming = 0;
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
|
|
static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
|
|
{
|
|
{
|
|
int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
|
|
int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
|
|
@@ -1426,6 +1459,12 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
|
|
/* Fill buffer information for the userspace */
|
|
/* Fill buffer information for the userspace */
|
|
__fill_v4l2_buffer(vb, b);
|
|
__fill_v4l2_buffer(vb, b);
|
|
|
|
|
|
|
|
+ if (q->retry_start_streaming) {
|
|
|
|
+ ret = vb2_start_streaming(q);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
dprintk(1, "%s() of buffer %d succeeded\n", __func__, vb->v4l2_buf.index);
|
|
dprintk(1, "%s() of buffer %d succeeded\n", __func__, vb->v4l2_buf.index);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -1575,7 +1614,8 @@ int vb2_wait_for_all_buffers(struct vb2_queue *q)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- wait_event(q->done_wq, !atomic_read(&q->queued_count));
|
|
|
|
|
|
+ if (!q->retry_start_streaming)
|
|
|
|
+ wait_event(q->done_wq, !atomic_read(&q->queued_count));
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(vb2_wait_for_all_buffers);
|
|
EXPORT_SYMBOL_GPL(vb2_wait_for_all_buffers);
|
|
@@ -1689,6 +1729,11 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
|
|
{
|
|
{
|
|
unsigned int i;
|
|
unsigned int i;
|
|
|
|
|
|
|
|
+ if (q->retry_start_streaming) {
|
|
|
|
+ q->retry_start_streaming = 0;
|
|
|
|
+ q->streaming = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Tell driver to stop all transactions and release all queued
|
|
* Tell driver to stop all transactions and release all queued
|
|
* buffers.
|
|
* buffers.
|
|
@@ -1738,12 +1783,9 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
|
|
list_for_each_entry(vb, &q->queued_list, queued_entry)
|
|
list_for_each_entry(vb, &q->queued_list, queued_entry)
|
|
__enqueue_in_driver(vb);
|
|
__enqueue_in_driver(vb);
|
|
|
|
|
|
- /*
|
|
|
|
- * Let driver notice that streaming state has been enabled.
|
|
|
|
- */
|
|
|
|
- ret = call_qop(q, start_streaming, q, atomic_read(&q->queued_count));
|
|
|
|
|
|
+ /* Tell driver to start streaming. */
|
|
|
|
+ ret = vb2_start_streaming(q);
|
|
if (ret) {
|
|
if (ret) {
|
|
- dprintk(1, "streamon: driver refused to start streaming\n");
|
|
|
|
__vb2_queue_cancel(q);
|
|
__vb2_queue_cancel(q);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -2313,15 +2355,15 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
|
|
goto err_reqbufs;
|
|
goto err_reqbufs;
|
|
fileio->bufs[i].queued = 1;
|
|
fileio->bufs[i].queued = 1;
|
|
}
|
|
}
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Start streaming.
|
|
|
|
- */
|
|
|
|
- ret = vb2_streamon(q, q->type);
|
|
|
|
- if (ret)
|
|
|
|
- goto err_reqbufs;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Start streaming.
|
|
|
|
+ */
|
|
|
|
+ ret = vb2_streamon(q, q->type);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto err_reqbufs;
|
|
|
|
+
|
|
q->fileio = fileio;
|
|
q->fileio = fileio;
|
|
|
|
|
|
return ret;
|
|
return ret;
|