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