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