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 (inst->state == IRIS_INST_STREAMING) 197 ret = iris_queue_internal_deferred_buffers(inst, BUF_DPB); 198 if (!ret) 199 ret = iris_queue_deferred_buffers(inst, buf_type); 200 } else { 201 if (inst->state == IRIS_INST_STREAMING) { 202 ret = iris_queue_deferred_buffers(inst, BUF_INPUT); 203 if (!ret) 204 ret = iris_queue_deferred_buffers(inst, BUF_OUTPUT); 205 } 206 } 207 208 if (ret) 209 goto error; 210 211 mutex_unlock(&inst->lock); 212 213 return ret; 214 215 error: 216 iris_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED); 217 iris_inst_change_state(inst, IRIS_INST_ERROR); 218 mutex_unlock(&inst->lock); 219 220 return ret; 221 } 222 223 void iris_vb2_stop_streaming(struct vb2_queue *q) 224 { 225 struct iris_inst *inst; 226 int ret = 0; 227 228 inst = vb2_get_drv_priv(q); 229 230 if (V4L2_TYPE_IS_CAPTURE(q->type) && inst->state == IRIS_INST_INIT) 231 return; 232 233 mutex_lock(&inst->lock); 234 235 if (!V4L2_TYPE_IS_OUTPUT(q->type) && 236 !V4L2_TYPE_IS_CAPTURE(q->type)) 237 goto exit; 238 239 ret = iris_session_streamoff(inst, q->type); 240 if (ret) 241 goto exit; 242 243 exit: 244 iris_helper_buffers_done(inst, q->type, VB2_BUF_STATE_ERROR); 245 if (ret) 246 iris_inst_change_state(inst, IRIS_INST_ERROR); 247 248 mutex_unlock(&inst->lock); 249 } 250 251 int iris_vb2_buf_prepare(struct vb2_buffer *vb) 252 { 253 struct iris_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 254 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 255 256 if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { 257 if (vbuf->field == V4L2_FIELD_ANY) 258 vbuf->field = V4L2_FIELD_NONE; 259 if (vbuf->field != V4L2_FIELD_NONE) 260 return -EINVAL; 261 } 262 263 if (!(inst->sub_state & IRIS_INST_SUB_DRC)) { 264 if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 265 vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_OUTPUT)) 266 return -EINVAL; 267 if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && 268 vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_INPUT)) 269 return -EINVAL; 270 } 271 return 0; 272 } 273 274 int iris_vb2_buf_out_validate(struct vb2_buffer *vb) 275 { 276 struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); 277 278 v4l2_buf->field = V4L2_FIELD_NONE; 279 280 return 0; 281 } 282 283 void iris_vb2_buf_queue(struct vb2_buffer *vb2) 284 { 285 static const struct v4l2_event eos = { .type = V4L2_EVENT_EOS }; 286 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); 287 struct v4l2_m2m_ctx *m2m_ctx; 288 struct iris_inst *inst; 289 int ret = 0; 290 291 inst = vb2_get_drv_priv(vb2->vb2_queue); 292 293 mutex_lock(&inst->lock); 294 if (inst->state == IRIS_INST_ERROR) { 295 ret = -EBUSY; 296 goto exit; 297 } 298 299 if (vbuf->field == V4L2_FIELD_ANY) 300 vbuf->field = V4L2_FIELD_NONE; 301 302 m2m_ctx = inst->m2m_ctx; 303 304 if (!vb2->planes[0].bytesused && V4L2_TYPE_IS_OUTPUT(vb2->type)) { 305 ret = -EINVAL; 306 goto exit; 307 } 308 309 if (!inst->last_buffer_dequeued && V4L2_TYPE_IS_CAPTURE(vb2->vb2_queue->type)) { 310 if ((inst->sub_state & IRIS_INST_SUB_DRC && 311 inst->sub_state & IRIS_INST_SUB_DRC_LAST) || 312 (inst->sub_state & IRIS_INST_SUB_DRAIN && 313 inst->sub_state & IRIS_INST_SUB_DRAIN_LAST)) { 314 vbuf->flags |= V4L2_BUF_FLAG_LAST; 315 vbuf->sequence = inst->sequence_cap++; 316 vbuf->field = V4L2_FIELD_NONE; 317 vb2_set_plane_payload(vb2, 0, 0); 318 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); 319 if (!v4l2_m2m_has_stopped(m2m_ctx)) { 320 v4l2_event_queue_fh(&inst->fh, &eos); 321 v4l2_m2m_mark_stopped(m2m_ctx); 322 } 323 inst->last_buffer_dequeued = true; 324 goto exit; 325 } 326 } 327 328 v4l2_m2m_buf_queue(m2m_ctx, vbuf); 329 330 if (inst->domain == DECODER) 331 ret = iris_vdec_qbuf(inst, vbuf); 332 else 333 ret = iris_venc_qbuf(inst, vbuf); 334 335 exit: 336 if (ret) { 337 iris_inst_change_state(inst, IRIS_INST_ERROR); 338 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); 339 } 340 mutex_unlock(&inst->lock); 341 } 342