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 
iris_check_core_mbpf(struct iris_inst * inst)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 
iris_check_inst_mbpf(struct iris_inst * inst)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 
iris_check_resolution_supported(struct iris_inst * inst)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 
iris_check_session_supported(struct iris_inst * inst)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 
iris_vb2_buf_init(struct vb2_buffer * vb2)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 
iris_vb2_queue_setup(struct vb2_queue * q,unsigned int * num_buffers,unsigned int * num_planes,unsigned int sizes[],struct device * alloc_devs[])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 
iris_vb2_start_streaming(struct vb2_queue * q,unsigned int count)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 
iris_vb2_stop_streaming(struct vb2_queue * q)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 
iris_vb2_buf_prepare(struct vb2_buffer * vb)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 
iris_vb2_buf_out_validate(struct vb2_buffer * vb)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 
iris_vb2_buf_queue(struct vb2_buffer * vb2)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