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