xref: /linux/drivers/media/platform/qcom/iris/iris_vb2.c (revision 69050f8d6d075dc01af7a5f2f550a8067510366f)
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