diff options
Diffstat (limited to 'drivers/media/platform/qcom/iris/iris_vb2.c')
| -rw-r--r-- | drivers/media/platform/qcom/iris/iris_vb2.c | 98 |
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); } |
