File Index
Files and directories
Sign in
FILE

iris_common.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/qcom/iris/iris_common.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
  4 */
  5
  6#include <media/v4l2-mem2mem.h>
  7
  8#include "iris_common.h"
  9#include "iris_ctrls.h"
 10#include "iris_instance.h"
 11#include "iris_power.h"
 12
 13int iris_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf)
 14{
 15	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
 16
 17	buf->type = iris_v4l2_type_to_driver(vb2->type);
 18	buf->index = vb2->index;
 19	buf->fd = vb2->planes[0].m.fd;
 20	buf->buffer_size = vb2->planes[0].length;
 21	buf->data_offset = vb2->planes[0].data_offset;
 22	buf->data_size = vb2->planes[0].bytesused - vb2->planes[0].data_offset;
 23	buf->flags = vbuf->flags;
 24	buf->timestamp = vb2->timestamp;
 25	buf->attr = 0;
 26
 27	return 0;
 28}
 29
 30void iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf)
 31{
 32	u32 mask = V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
 33	struct vb2_buffer *vb = &vbuf->vb2_buf;
 34	u64 ts_us = vb->timestamp;
 35
 36	if (inst->metadata_idx >= ARRAY_SIZE(inst->tss))
 37		inst->metadata_idx = 0;
 38
 39	do_div(ts_us, NSEC_PER_USEC);
 40
 41	inst->tss[inst->metadata_idx].flags = vbuf->flags & mask;
 42	inst->tss[inst->metadata_idx].tc = vbuf->timecode;
 43	inst->tss[inst->metadata_idx].ts_us = ts_us;
 44	inst->tss[inst->metadata_idx].ts_ns = vb->timestamp;
 45
 46	inst->metadata_idx++;
 47}
 48
 49int iris_process_streamon_input(struct iris_inst *inst)
 50{
 51	const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
 52	enum iris_inst_sub_state set_sub_state = 0;
 53	int ret;
 54
 55	iris_scale_power(inst);
 56
 57	ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 58	if (ret)
 59		return ret;
 60
 61	if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
 62		ret = iris_inst_change_sub_state(inst, IRIS_INST_SUB_INPUT_PAUSE, 0);
 63		if (ret)
 64			return ret;
 65	}
 66
 67	if (inst->domain == DECODER &&
 68	    (inst->sub_state & IRIS_INST_SUB_DRC ||
 69	     inst->sub_state & IRIS_INST_SUB_DRAIN ||
 70	     inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)) {
 71		if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) {
 72			if (hfi_ops->session_pause) {
 73				ret = hfi_ops->session_pause(inst,
 74							     V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 75				if (ret)
 76					return ret;
 77			}
 78			set_sub_state = IRIS_INST_SUB_INPUT_PAUSE;
 79		}
 80	}
 81
 82	ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 83	if (ret)
 84		return ret;
 85
 86	inst->last_buffer_dequeued = false;
 87
 88	return iris_inst_change_sub_state(inst, 0, set_sub_state);
 89}
 90
 91int iris_process_streamon_output(struct iris_inst *inst)
 92{
 93	const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
 94	enum iris_inst_sub_state clear_sub_state = 0;
 95	bool drain_active, drc_active, first_ipsc;
 96	int ret = 0;
 97
 98	iris_scale_power(inst);
 99
100	first_ipsc = inst->sub_state & IRIS_INST_SUB_FIRST_IPSC;
101
102	drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN &&
103		inst->sub_state & IRIS_INST_SUB_DRAIN_LAST;
104
105	drc_active = inst->sub_state & IRIS_INST_SUB_DRC &&
106		inst->sub_state & IRIS_INST_SUB_DRC_LAST;
107
108	if (drc_active)
109		clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST;
110	else if (drain_active)
111		clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST;
112
113	/* Input internal buffer reconfiguration required in case of resolution change */
114	if (first_ipsc || drc_active) {
115		ret = iris_alloc_and_queue_input_int_bufs(inst);
116		if (ret)
117			return ret;
118		ret = iris_set_stage(inst, STAGE);
119		if (ret)
120			return ret;
121		ret = iris_set_pipe(inst, PIPE);
122		if (ret)
123			return ret;
124	}
125
126	if (inst->state == IRIS_INST_INPUT_STREAMING &&
127	    inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
128		if (!drain_active)
129			ret = hfi_ops->session_resume_drc(inst,
130							  V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
131		else if (hfi_ops->session_resume_drain)
132			ret = hfi_ops->session_resume_drain(inst,
133							    V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
134		if (ret)
135			return ret;
136		clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
137	}
138
139	if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)
140		clear_sub_state |= IRIS_INST_SUB_FIRST_IPSC;
141
142	ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
143	if (ret)
144		return ret;
145
146	if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE)
147		clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
148
149	ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
150	if (ret)
151		return ret;
152
153	inst->last_buffer_dequeued = false;
154
155	return iris_inst_change_sub_state(inst, clear_sub_state, 0);
156}
157
158static void iris_flush_deferred_buffers(struct iris_inst *inst,
159					enum iris_buffer_type type)
160{
161	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
162	struct v4l2_m2m_buffer *buffer, *n;
163	struct iris_buffer *buf;
164
165	if (type == BUF_INPUT) {
166		v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) {
167			buf = to_iris_buffer(&buffer->vb);
168			if (buf->attr & BUF_ATTR_DEFERRED) {
169				if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) {
170					buf->attr |= BUF_ATTR_BUFFER_DONE;
171					buf->data_size = 0;
172					iris_vb2_buffer_done(inst, buf);
173				}
174			}
175		}
176	} else {
177		v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buffer, n) {
178			buf = to_iris_buffer(&buffer->vb);
179			if (buf->attr & BUF_ATTR_DEFERRED) {
180				if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) {
181					buf->attr |= BUF_ATTR_BUFFER_DONE;
182					buf->data_size = 0;
183					iris_vb2_buffer_done(inst, buf);
184				}
185			}
186		}
187	}
188}
189
190static void iris_kill_session(struct iris_inst *inst)
191{
192	const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
193
194	if (!inst->session_id)
195		return;
196
197	hfi_ops->session_close(inst);
198	iris_inst_change_state(inst, IRIS_INST_ERROR);
199}
200
201int iris_session_streamoff(struct iris_inst *inst, u32 plane)
202{
203	const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
204	enum iris_buffer_type buffer_type;
205	int ret;
206
207	switch (plane) {
208	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
209		buffer_type = BUF_INPUT;
210		break;
211	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
212		buffer_type = BUF_OUTPUT;
213		break;
214	default:
215		return -EINVAL;
216	}
217
218	ret = hfi_ops->session_stop(inst, plane);
219	if (ret)
220		goto error;
221
222	ret = iris_inst_state_change_streamoff(inst, plane);
223	if (ret)
224		goto error;
225
226	iris_flush_deferred_buffers(inst, buffer_type);
227
228	return 0;
229
230error:
231	iris_kill_session(inst);
232	iris_flush_deferred_buffers(inst, buffer_type);
233
234	return ret;
235}
~/ Read-only file preview.