summaryrefslogtreecommitdiff
path: root/drivers/media/platform/qcom/iris/iris_vb2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/qcom/iris/iris_vb2.c')
-rw-r--r--drivers/media/platform/qcom/iris/iris_vb2.c98
1 files changed, 97 insertions, 1 deletions
diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c
index b93da860d336..770e51f9ef91 100644
--- a/drivers/media/platform/qcom/iris/iris_vb2.c
+++ b/drivers/media/platform/qcom/iris/iris_vb2.c
@@ -3,10 +3,23 @@
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
+#include <media/videobuf2-dma-contig.h>
+#include <media/v4l2-mem2mem.h>
+
#include "iris_instance.h"
#include "iris_vb2.h"
#include "iris_vdec.h"
+int iris_vb2_buf_init(struct vb2_buffer *vb2)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+ struct iris_buffer *buf = to_iris_buffer(vbuf);
+
+ buf->device_addr = vb2_dma_contig_plane_dma_addr(vb2, 0);
+
+ return 0;
+}
+
int iris_vb2_queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], struct device *alloc_devs[])
@@ -60,6 +73,7 @@ unlock:
int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
{
+ enum iris_buffer_type buf_type;
struct iris_inst *inst;
int ret = 0;
@@ -87,11 +101,18 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
if (ret)
goto error;
+ buf_type = iris_v4l2_type_to_driver(q->type);
+
+ ret = iris_queue_deferred_buffers(inst, buf_type);
+ if (ret)
+ goto error;
+
mutex_unlock(&inst->lock);
return ret;
error:
+ iris_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED);
iris_inst_change_state(inst, IRIS_INST_ERROR);
mutex_unlock(&inst->lock);
@@ -101,6 +122,7 @@ error:
void iris_vb2_stop_streaming(struct vb2_queue *q)
{
struct iris_inst *inst;
+ int ret = 0;
inst = vb2_get_drv_priv(q);
@@ -113,8 +135,82 @@ void iris_vb2_stop_streaming(struct vb2_queue *q)
!V4L2_TYPE_IS_CAPTURE(q->type))
goto exit;
- iris_vdec_session_streamoff(inst, q->type);
+ ret = iris_vdec_session_streamoff(inst, q->type);
+ if (ret)
+ goto exit;
+
+exit:
+ iris_helper_buffers_done(inst, q->type, VB2_BUF_STATE_ERROR);
+ if (ret)
+ iris_inst_change_state(inst, IRIS_INST_ERROR);
+
+ mutex_unlock(&inst->lock);
+}
+
+int iris_vb2_buf_prepare(struct vb2_buffer *vb)
+{
+ struct iris_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+ if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
+ if (vbuf->field == V4L2_FIELD_ANY)
+ vbuf->field = V4L2_FIELD_NONE;
+ if (vbuf->field != V4L2_FIELD_NONE)
+ return -EINVAL;
+ }
+
+ if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+ vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_OUTPUT))
+ return -EINVAL;
+ if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+ vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_INPUT))
+ return -EINVAL;
+
+ return 0;
+}
+
+int iris_vb2_buf_out_validate(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb);
+
+ v4l2_buf->field = V4L2_FIELD_NONE;
+
+ return 0;
+}
+
+void iris_vb2_buf_queue(struct vb2_buffer *vb2)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+ struct v4l2_m2m_ctx *m2m_ctx;
+ struct iris_inst *inst;
+ int ret = 0;
+
+ inst = vb2_get_drv_priv(vb2->vb2_queue);
+
+ mutex_lock(&inst->lock);
+ if (inst->state == IRIS_INST_ERROR) {
+ ret = -EBUSY;
+ goto exit;
+ }
+
+ if (vbuf->field == V4L2_FIELD_ANY)
+ vbuf->field = V4L2_FIELD_NONE;
+
+ m2m_ctx = inst->m2m_ctx;
+
+ if (!vb2->planes[0].bytesused && V4L2_TYPE_IS_OUTPUT(vb2->type)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ v4l2_m2m_buf_queue(m2m_ctx, vbuf);
+
+ ret = iris_vdec_qbuf(inst, vbuf);
exit:
+ if (ret) {
+ iris_inst_change_state(inst, IRIS_INST_ERROR);
+ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+ }
mutex_unlock(&inst->lock);
}