1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6 #include <media/videobuf2-dma-contig.h> 7 #include <media/v4l2-event.h> 8 #include <media/v4l2-mem2mem.h> 9 10 #include "iris_instance.h" 11 #include "iris_vb2.h" 12 #include "iris_vdec.h" 13 14 int iris_vb2_buf_init(struct vb2_buffer *vb2) 15 { 16 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); 17 struct iris_buffer *buf = to_iris_buffer(vbuf); 18 19 buf->device_addr = vb2_dma_contig_plane_dma_addr(vb2, 0); 20 21 return 0; 22 } 23 24 int iris_vb2_queue_setup(struct vb2_queue *q, 25 unsigned int *num_buffers, unsigned int *num_planes, 26 unsigned int sizes[], struct device *alloc_devs[]) 27 { 28 struct iris_inst *inst; 29 struct iris_core *core; 30 struct v4l2_format *f; 31 int ret = 0; 32 33 inst = vb2_get_drv_priv(q); 34 35 mutex_lock(&inst->lock); 36 if (inst->state == IRIS_INST_ERROR) { 37 ret = -EBUSY; 38 goto unlock; 39 } 40 41 core = inst->core; 42 f = V4L2_TYPE_IS_OUTPUT(q->type) ? inst->fmt_src : inst->fmt_dst; 43 44 if (*num_planes) { 45 if (*num_planes != f->fmt.pix_mp.num_planes || 46 sizes[0] < f->fmt.pix_mp.plane_fmt[0].sizeimage) 47 ret = -EINVAL; 48 goto unlock; 49 } 50 51 if (!inst->once_per_session_set) { 52 inst->once_per_session_set = true; 53 54 ret = core->hfi_ops->session_open(inst); 55 if (ret) { 56 ret = -EINVAL; 57 dev_err(core->dev, "session open failed\n"); 58 goto unlock; 59 } 60 61 ret = iris_inst_change_state(inst, IRIS_INST_INIT); 62 if (ret) 63 goto unlock; 64 } 65 66 *num_planes = 1; 67 sizes[0] = f->fmt.pix_mp.plane_fmt[0].sizeimage; 68 69 unlock: 70 mutex_unlock(&inst->lock); 71 72 return ret; 73 } 74 75 int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) 76 { 77 enum iris_buffer_type buf_type; 78 struct iris_inst *inst; 79 int ret = 0; 80 81 inst = vb2_get_drv_priv(q); 82 83 if (V4L2_TYPE_IS_CAPTURE(q->type) && inst->state == IRIS_INST_INIT) 84 return 0; 85 86 mutex_lock(&inst->lock); 87 if (inst->state == IRIS_INST_ERROR) { 88 ret = -EBUSY; 89 goto error; 90 } 91 92 if (!V4L2_TYPE_IS_OUTPUT(q->type) && 93 !V4L2_TYPE_IS_CAPTURE(q->type)) { 94 ret = -EINVAL; 95 goto error; 96 } 97 98 if (V4L2_TYPE_IS_OUTPUT(q->type)) 99 ret = iris_vdec_streamon_input(inst); 100 else if (V4L2_TYPE_IS_CAPTURE(q->type)) 101 ret = iris_vdec_streamon_output(inst); 102 if (ret) 103 goto error; 104 105 buf_type = iris_v4l2_type_to_driver(q->type); 106 107 ret = iris_queue_deferred_buffers(inst, buf_type); 108 if (ret) 109 goto error; 110 111 mutex_unlock(&inst->lock); 112 113 return ret; 114 115 error: 116 iris_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED); 117 iris_inst_change_state(inst, IRIS_INST_ERROR); 118 mutex_unlock(&inst->lock); 119 120 return ret; 121 } 122 123 void iris_vb2_stop_streaming(struct vb2_queue *q) 124 { 125 struct iris_inst *inst; 126 int ret = 0; 127 128 inst = vb2_get_drv_priv(q); 129 130 if (V4L2_TYPE_IS_CAPTURE(q->type) && inst->state == IRIS_INST_INIT) 131 return; 132 133 mutex_lock(&inst->lock); 134 135 if (!V4L2_TYPE_IS_OUTPUT(q->type) && 136 !V4L2_TYPE_IS_CAPTURE(q->type)) 137 goto exit; 138 139 ret = iris_vdec_session_streamoff(inst, q->type); 140 if (ret) 141 goto exit; 142 143 exit: 144 iris_helper_buffers_done(inst, q->type, VB2_BUF_STATE_ERROR); 145 if (ret) 146 iris_inst_change_state(inst, IRIS_INST_ERROR); 147 148 mutex_unlock(&inst->lock); 149 } 150 151 int iris_vb2_buf_prepare(struct vb2_buffer *vb) 152 { 153 struct iris_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 154 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 155 156 if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { 157 if (vbuf->field == V4L2_FIELD_ANY) 158 vbuf->field = V4L2_FIELD_NONE; 159 if (vbuf->field != V4L2_FIELD_NONE) 160 return -EINVAL; 161 } 162 163 if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 164 vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_OUTPUT)) 165 return -EINVAL; 166 if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && 167 vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_INPUT)) 168 return -EINVAL; 169 170 return 0; 171 } 172 173 int iris_vb2_buf_out_validate(struct vb2_buffer *vb) 174 { 175 struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); 176 177 v4l2_buf->field = V4L2_FIELD_NONE; 178 179 return 0; 180 } 181 182 void iris_vb2_buf_queue(struct vb2_buffer *vb2) 183 { 184 static const struct v4l2_event eos = { .type = V4L2_EVENT_EOS }; 185 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); 186 struct v4l2_m2m_ctx *m2m_ctx; 187 struct iris_inst *inst; 188 int ret = 0; 189 190 inst = vb2_get_drv_priv(vb2->vb2_queue); 191 192 mutex_lock(&inst->lock); 193 if (inst->state == IRIS_INST_ERROR) { 194 ret = -EBUSY; 195 goto exit; 196 } 197 198 if (vbuf->field == V4L2_FIELD_ANY) 199 vbuf->field = V4L2_FIELD_NONE; 200 201 m2m_ctx = inst->m2m_ctx; 202 203 if (!vb2->planes[0].bytesused && V4L2_TYPE_IS_OUTPUT(vb2->type)) { 204 ret = -EINVAL; 205 goto exit; 206 } 207 208 if (V4L2_TYPE_IS_CAPTURE(vb2->vb2_queue->type)) { 209 if ((inst->sub_state & IRIS_INST_SUB_DRC && 210 inst->sub_state & IRIS_INST_SUB_DRC_LAST) || 211 (inst->sub_state & IRIS_INST_SUB_DRAIN && 212 inst->sub_state & IRIS_INST_SUB_DRAIN_LAST)) { 213 vbuf->flags |= V4L2_BUF_FLAG_LAST; 214 vbuf->sequence = inst->sequence_cap++; 215 vbuf->field = V4L2_FIELD_NONE; 216 vb2_set_plane_payload(vb2, 0, 0); 217 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); 218 if (!v4l2_m2m_has_stopped(m2m_ctx)) { 219 v4l2_event_queue_fh(&inst->fh, &eos); 220 v4l2_m2m_mark_stopped(m2m_ctx); 221 } 222 goto exit; 223 } 224 } 225 226 v4l2_m2m_buf_queue(m2m_ctx, vbuf); 227 228 ret = iris_vdec_qbuf(inst, vbuf); 229 230 exit: 231 if (ret) { 232 iris_inst_change_state(inst, IRIS_INST_ERROR); 233 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); 234 } 235 mutex_unlock(&inst->lock); 236 } 237