Commit d0910076 authored by Dikshita Agarwal's avatar Dikshita Agarwal Committed by Hans Verkuil
Browse files

media: iris: add support for drain sequence



handle the V4L2_DEC_CMD_STOP by initiating a drain sequence on the
firmware. Process and decode all OUTPUT buffers, that are  queued by the
client, before the VIDIOC_DECODER_CMD() was issued and mark the last
buffer with the V4L2_BUF_FLAG_LAST flag. The decoder is stopped, after
processing the last buffer.

Resume the decoder when one of these operations are issued by the client:
- V4L2_DEC_CMD_START
- pair of VIDIOC_STREAMOFF() and VIDIOC_STREAMON() on the CAPTURE queue
- pair of VIDIOC_STREAMOFF() and VIDIOC_STREAMON() on the OUTPUT queue

Add the handling to resume decoding when client issues
V4L2_DEC_CMD_START to resume decoding after a source change is detected.

Tested-by: Stefan Schmidt <stefan.schmidt@linaro.org> # x1e80100 (Dell XPS 13 9345)
Reviewed-by: default avatarStefan Schmidt <stefan.schmidt@linaro.org>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-HDK
Signed-off-by: default avatarDikshita Agarwal <quic_dikshita@quicinc.com>
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
parent c1f8b2cc
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -121,6 +121,8 @@ struct iris_hfi_command_ops {
	int (*session_pause)(struct iris_inst *inst, u32 plane);
	int (*session_resume_drc)(struct iris_inst *inst, u32 plane);
	int (*session_stop)(struct iris_inst *inst, u32 plane);
	int (*session_drain)(struct iris_inst *inst, u32 plane);
	int (*session_resume_drain)(struct iris_inst *inst, u32 plane);
	int (*session_close)(struct iris_inst *inst);
};

+13 −0
Original line number Diff line number Diff line
@@ -368,6 +368,18 @@ static int iris_hfi_gen1_session_unset_buffers(struct iris_inst *inst, struct ir
	return ret;
}

static int iris_hfi_gen1_session_drain(struct iris_inst *inst, u32 plane)
{
	struct hfi_session_empty_buffer_compressed_pkt ip_pkt = {0};

	ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt);
	ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER;
	ip_pkt.shdr.session_id = inst->session_id;
	ip_pkt.flags = HFI_BUFFERFLAG_EOS;

	return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size);
}

static int
iris_hfi_gen1_packet_session_set_property(struct hfi_session_set_property_pkt *packet,
					  struct iris_inst *inst, u32 ptype, void *pdata)
@@ -789,6 +801,7 @@ static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = {
	.session_release_buf = iris_hfi_gen1_session_unset_buffers,
	.session_resume_drc = iris_hfi_gen1_session_continue,
	.session_stop = iris_hfi_gen1_session_stop,
	.session_drain = iris_hfi_gen1_session_drain,
	.session_close = iris_hfi_gen1_session_close,
};

+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@
#define HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES 0x1000002
#define HFI_EVENT_SESSION_SEQUENCE_CHANGED			   0x1000003

#define HFI_BUFFERFLAG_EOS				0x00000001
#define HFI_BUFFERFLAG_TIMESTAMPINVALID			0x00000100

#define HFI_FLUSH_OUTPUT				0x1000002
+15 −0
Original line number Diff line number Diff line
@@ -386,6 +386,7 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
	struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt = packet;
	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
	struct v4l2_m2m_buffer *m2m_buffer, *n;
	struct hfi_session_flush_pkt flush_pkt;
	u32 timestamp_hi = pkt->time_stamp_hi;
	u32 timestamp_lo = pkt->time_stamp_lo;
	struct iris_core *core = inst->core;
@@ -394,11 +395,25 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
	u32 output_tag = pkt->output_tag;
	struct iris_buffer *buf, *iter;
	struct iris_buffers *buffers;
	u32 hfi_flags = pkt->flags;
	u32 offset = pkt->offset;
	u64 timestamp_us = 0;
	bool found = false;
	u32 flags = 0;

	if ((hfi_flags & HFI_BUFFERFLAG_EOS) && !filled_len) {
		reinit_completion(&inst->flush_completion);

		flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt);
		flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH;
		flush_pkt.shdr.session_id = inst->session_id;
		flush_pkt.flush_type = HFI_FLUSH_OUTPUT;
		iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size);
		iris_inst_sub_state_change_drain_last(inst);

		return;
	}

	if (iris_split_mode_enabled(inst) && pkt->stream_id == 0) {
		buffers = &inst->buffers[BUF_DPB];
		if (!buffers)
+43 −0
Original line number Diff line number Diff line
@@ -774,6 +774,47 @@ static int iris_hfi_gen2_session_resume_drc(struct iris_inst *inst, u32 plane)
					inst_hfi_gen2->packet->size);
}

static int iris_hfi_gen2_session_resume_drain(struct iris_inst *inst, u32 plane)
{
	struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
	u32 payload = HFI_CMD_DRAIN;

	iris_hfi_gen2_packet_session_command(inst,
					     HFI_CMD_RESUME,
					     (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
					     HFI_HOST_FLAGS_INTR_REQUIRED),
					     iris_hfi_gen2_get_port(plane),
					     inst->session_id,
					     HFI_PAYLOAD_U32,
					     &payload,
					     sizeof(u32));

	return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
					inst_hfi_gen2->packet->size);
}

static int iris_hfi_gen2_session_drain(struct iris_inst *inst, u32 plane)
{
	struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);

	if (!V4L2_TYPE_IS_OUTPUT(plane))
		return 0;

	iris_hfi_gen2_packet_session_command(inst,
					     HFI_CMD_DRAIN,
					     (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
					     HFI_HOST_FLAGS_INTR_REQUIRED |
					     HFI_HOST_FLAGS_NON_DISCARDABLE),
					     iris_hfi_gen2_get_port(plane),
					     inst->session_id,
					     HFI_PAYLOAD_NONE,
					     NULL,
					     0);

	return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
					inst_hfi_gen2->packet->size);
}

static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type)
{
	switch (buffer_type) {
@@ -900,6 +941,8 @@ static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = {
	.session_pause = iris_hfi_gen2_session_pause,
	.session_resume_drc = iris_hfi_gen2_session_resume_drc,
	.session_stop = iris_hfi_gen2_session_stop,
	.session_drain = iris_hfi_gen2_session_drain,
	.session_resume_drain = iris_hfi_gen2_session_resume_drain,
	.session_close = iris_hfi_gen2_session_close,
};

Loading