File Index
Files and directories
Sign in
FILE

iris_vb2.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/qcom/iris/iris_vb2.c C
  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
 17static 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
 31static 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
 52static 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;
 82exit:
 83	dev_err(inst->core->dev, "current session not supported(%d)\n", ret);
 84
 85	return ret;
 86}
 87
 88int 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
 98int 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
147unlock:
148	mutex_unlock(&inst->lock);
149
150	return ret;
151}
152
153int 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
219error:
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
227void 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
247exit:
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
255int 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
278int 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
287void 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
339exit:
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}
~/ Read-only file preview.