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_common.h" 11 #include "iris_instance.h" 12 #include "iris_vb2.h" 13 #include "iris_vdec.h" 14 #include "iris_venc.h" 15 #include "iris_power.h" 16 17 static int iris_check_inst_mbpf(struct iris_inst *inst) 18 { 19 struct platform_inst_caps *caps; 20 u32 mbpf, max_mbpf; 21 22 caps = inst->core->iris_platform_data->inst_caps; 23 max_mbpf = caps->max_mbpf; 24 mbpf = iris_get_mbpf(inst); 25 if (mbpf > max_mbpf) 26 return -ENOMEM; 27 28 return 0; 29 } 30 31 static int iris_check_resolution_supported(struct iris_inst *inst) 32 { 33 u32 width, height, min_width, min_height, max_width, max_height; 34 struct platform_inst_caps *caps; 35 36 caps = inst->core->iris_platform_data->inst_caps; 37 width = inst->fmt_src->fmt.pix_mp.width; 38 height = inst->fmt_src->fmt.pix_mp.height; 39 40 min_width = caps->min_frame_width; 41 max_width = caps->max_frame_width; 42 min_height = caps->min_frame_height; 43 max_height = caps->max_frame_height; 44 45 if (!(min_width <= width && width <= max_width) || 46 !(min_height <= height && height <= max_height)) 47 return -EINVAL; 48 49 return 0; 50 } 51 52 static int iris_check_session_supported(struct iris_inst *inst) 53 { 54 struct iris_core *core = inst->core; 55 struct iris_inst *instance = NULL; 56 bool found = false; 57 int ret; 58 59 list_for_each_entry(instance, &core->instances, list) { 60 if (instance == inst) 61 found = true; 62 } 63 64 if (!found) { 65 ret = -EINVAL; 66 goto exit; 67 } 68 69 ret = iris_check_core_mbpf(inst); 70 if (ret) 71 goto exit; 72 73 ret = iris_check_inst_mbpf(inst); 74 if (ret) 75 goto exit; 76 77 ret = iris_check_resolution_supported(inst); 78 if (ret) 79 goto exit; 80 81 return 0; 82 exit: 83 dev_err(inst->core->dev, "current session not supported(%d)\n", ret); 84 85 return ret; 86 } 87 88 int iris_vb2_buf_init(struct vb2_buffer *vb2) 89 { 90 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); 91 struct iris_buffer *buf = to_iris_buffer(vbuf); 92 93 buf->device_addr = vb2_dma_contig_plane_dma_addr(vb2, 0); 94 95 return 0; 96 } 97 98 int iris_vb2_queue_setup(struct vb2_queue *q, 99 unsigned int *num_buffers, unsigned int *num_planes, 100 unsigned int sizes[], struct device *alloc_devs[]) 101 { 102 struct iris_inst *inst; 103 struct iris_core *core; 104 struct v4l2_format *f; 105 int ret = 0; 106 107 inst = vb2_get_drv_priv(q); 108 109 mutex_lock(&inst->lock); 110 if (inst->state == IRIS_INST_ERROR) { 111 ret = -EBUSY; 112 goto unlock; 113 } 114 115 core = inst->core; 116 f = V4L2_TYPE_IS_OUTPUT(q->type) ? inst->fmt_src : inst->fmt_dst; 117 118 if (*num_planes) { 119 if (*num_planes != f->fmt.pix_mp.num_planes || 120 sizes[0] < f->fmt.pix_mp.plane_fmt[0].sizeimage) 121 ret = -EINVAL; 122 goto unlock; 123 } 124 125 ret = iris_check_session_supported(inst); 126 if (ret) 127 goto unlock; 128 129 if (!inst->once_per_session_set) { 130 inst->once_per_session_set = true; 131 132 ret = core->hfi_ops->session_open(inst); 133 if (ret) { 134 ret = -EINVAL; 135 dev_err(core->dev, "session open failed\n"); 136 goto unlock; 137 } 138 139 ret = iris_inst_change_state(inst, IRIS_INST_INIT); 140 if (ret) 141 goto unlock; 142 } 143 144 *num_planes = 1; 145 sizes[0] = f->fmt.pix_mp.plane_fmt[0].sizeimage; 146 147 unlock: 148 mutex_unlock(&inst->lock); 149 150 return ret; 151 } 152 153 int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) 154 { 155 enum iris_buffer_type buf_type; 156 struct iris_inst *inst; 157 int ret = 0; 158 159 inst = vb2_get_drv_priv(q); 160 161 mutex_lock(&inst->lock); 162 if (inst->state == IRIS_INST_ERROR) { 163 ret = -EBUSY; 164 goto error; 165 } 166 167 if (!V4L2_TYPE_IS_OUTPUT(q->type) && 168 !V4L2_TYPE_IS_CAPTURE(q->type)) { 169 ret = -EINVAL; 170 goto error; 171 } 172 173 iris_scale_power(inst); 174 175 ret = iris_check_session_supported(inst); 176 if (ret) 177 goto error; 178 179 if (V4L2_TYPE_IS_OUTPUT(q->type)) { 180 if (inst->domain == DECODER) 181 ret = iris_vdec_streamon_input(inst); 182 else 183 ret = iris_venc_streamon_input(inst); 184 } else if (V4L2_TYPE_IS_CAPTURE(q->type)) { 185 if (inst->domain == DECODER) 186 ret = iris_vdec_streamon_output(inst); 187 else 188 ret = iris_venc_streamon_output(inst); 189 } 190 if (ret) 191 goto error; 192 193 buf_type = iris_v4l2_type_to_driver(q->type); 194 195 if (inst->domain == DECODER) { 196 if (buf_type == BUF_INPUT) 197 ret = iris_queue_deferred_buffers(inst, BUF_INPUT); 198 199 if (!ret && inst->state == IRIS_INST_STREAMING) { 200 ret = iris_queue_internal_deferred_buffers(inst, BUF_DPB); 201 if (!ret) 202 ret = iris_queue_deferred_buffers(inst, BUF_OUTPUT); 203 } 204 } else { 205 if (inst->state == IRIS_INST_STREAMING) { 206 ret = iris_queue_deferred_buffers(inst, BUF_INPUT); 207 if (!ret) 208 ret = iris_queue_deferred_buffers(inst, BUF_OUTPUT); 209 } 210 } 211 212 if (ret) 213 goto error; 214 215 mutex_unlock(&inst->lock); 216 217 return ret; 218 219 error: 220 iris_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED); 221 iris_inst_change_state(inst, IRIS_INST_ERROR); 222 mutex_unlock(&inst->lock); 223 224 return ret; 225 } 226 227 void iris_vb2_stop_streaming(struct vb2_queue *q) 228 { 229 struct iris_inst *inst; 230 int ret = 0; 231 232 inst = vb2_get_drv_priv(q); 233 234 if (V4L2_TYPE_IS_CAPTURE(q->type) && inst->state == IRIS_INST_INIT) 235 return; 236 237 mutex_lock(&inst->lock); 238 239 if (!V4L2_TYPE_IS_OUTPUT(q->type) && 240 !V4L2_TYPE_IS_CAPTURE(q->type)) 241 goto exit; 242 243 ret = iris_session_streamoff(inst, q->type); 244 if (ret) 245 goto exit; 246 247 exit: 248 iris_helper_buffers_done(inst, q->type, VB2_BUF_STATE_ERROR); 249 if (ret) 250 iris_inst_change_state(inst, IRIS_INST_ERROR); 251 252 mutex_unlock(&inst->lock); 253 } 254 255 int iris_vb2_buf_prepare(struct vb2_buffer *vb) 256 { 257 struct iris_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 258 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 259 260 if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { 261 if (vbuf->field == V4L2_FIELD_ANY) 262 vbuf->field = V4L2_FIELD_NONE; 263 if (vbuf->field != V4L2_FIELD_NONE) 264 return -EINVAL; 265 } 266 267 if (!(inst->sub_state & IRIS_INST_SUB_DRC)) { 268 if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 269 vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_OUTPUT)) 270 return -EINVAL; 271 if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && 272 vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_INPUT)) 273 return -EINVAL; 274 } 275 return 0; 276 } 277 278 int iris_vb2_buf_out_validate(struct vb2_buffer *vb) 279 { 280 struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); 281 282 v4l2_buf->field = V4L2_FIELD_NONE; 283 284 return 0; 285 } 286 287 void iris_vb2_buf_queue(struct vb2_buffer *vb2) 288 { 289 static const struct v4l2_event eos = { .type = V4L2_EVENT_EOS }; 290 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); 291 struct v4l2_m2m_ctx *m2m_ctx; 292 struct iris_inst *inst; 293 int ret = 0; 294 295 inst = vb2_get_drv_priv(vb2->vb2_queue); 296 297 mutex_lock(&inst->lock); 298 if (inst->state == IRIS_INST_ERROR) { 299 ret = -EBUSY; 300 goto exit; 301 } 302 303 if (vbuf->field == V4L2_FIELD_ANY) 304 vbuf->field = V4L2_FIELD_NONE; 305 306 m2m_ctx = inst->m2m_ctx; 307 308 if (!vb2->planes[0].bytesused && V4L2_TYPE_IS_OUTPUT(vb2->type)) { 309 ret = -EINVAL; 310 goto exit; 311 } 312 313 if (!inst->last_buffer_dequeued && V4L2_TYPE_IS_CAPTURE(vb2->vb2_queue->type)) { 314 if ((inst->sub_state & IRIS_INST_SUB_DRC && 315 inst->sub_state & IRIS_INST_SUB_DRC_LAST) || 316 (inst->sub_state & IRIS_INST_SUB_DRAIN && 317 inst->sub_state & IRIS_INST_SUB_DRAIN_LAST)) { 318 vbuf->flags |= V4L2_BUF_FLAG_LAST; 319 vbuf->sequence = inst->sequence_cap++; 320 vbuf->field = V4L2_FIELD_NONE; 321 vb2_set_plane_payload(vb2, 0, 0); 322 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); 323 if (!v4l2_m2m_has_stopped(m2m_ctx)) { 324 v4l2_event_queue_fh(&inst->fh, &eos); 325 v4l2_m2m_mark_stopped(m2m_ctx); 326 } 327 inst->last_buffer_dequeued = true; 328 goto exit; 329 } 330 } 331 332 v4l2_m2m_buf_queue(m2m_ctx, vbuf); 333 334 if (inst->domain == DECODER) 335 ret = iris_vdec_qbuf(inst, vbuf); 336 else 337 ret = iris_venc_qbuf(inst, vbuf); 338 339 exit: 340 if (ret) { 341 iris_inst_change_state(inst, IRIS_INST_ERROR); 342 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); 343 } 344 mutex_unlock(&inst->lock); 345 } 346