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