mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-21 06:50:25 +00:00
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: Stefan 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: Dikshita Agarwal <quic_dikshita@quicinc.com> Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
This commit is contained in:
parent
c1f8b2cc72
commit
d09100763b
13 changed files with 329 additions and 8 deletions
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -368,6 +368,18 @@ exit:
|
|||
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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#define HFI_CMD_CLOSE 0x01000004
|
||||
#define HFI_CMD_START 0x01000005
|
||||
#define HFI_CMD_STOP 0x01000006
|
||||
#define HFI_CMD_DRAIN 0x01000007
|
||||
#define HFI_CMD_RESUME 0x01000008
|
||||
#define HFI_CMD_BUFFER 0x01000009
|
||||
#define HFI_CMD_SUBSCRIBE_MODE 0x0100000B
|
||||
|
@ -80,6 +81,7 @@
|
|||
#define HFI_INFO_UNSUPPORTED 0x06000001
|
||||
#define HFI_INFO_DATA_CORRUPT 0x06000002
|
||||
#define HFI_INFO_BUFFER_OVERFLOW 0x06000004
|
||||
#define HFI_INFO_HFI_FLAG_DRAIN_LAST 0x06000006
|
||||
#define HFI_INFO_HFI_FLAG_PSC_LAST 0x06000007
|
||||
#define HFI_INFORMATION_END 0x06FFFFFF
|
||||
|
||||
|
|
|
@ -201,6 +201,10 @@ static int iris_hfi_gen2_handle_session_info(struct iris_inst *inst,
|
|||
info = "buffer overflow";
|
||||
inst_hfi_gen2->hfi_frame_info.overflow = 1;
|
||||
break;
|
||||
case HFI_INFO_HFI_FLAG_DRAIN_LAST:
|
||||
info = "drain last flag";
|
||||
ret = iris_inst_sub_state_change_drain_last(inst);
|
||||
break;
|
||||
case HFI_INFO_HFI_FLAG_PSC_LAST:
|
||||
info = "drc last flag";
|
||||
ret = iris_inst_sub_state_change_drc_last(inst);
|
||||
|
@ -337,6 +341,12 @@ static int iris_hfi_gen2_handle_output_buffer(struct iris_inst *inst,
|
|||
bool found = false;
|
||||
int ret;
|
||||
|
||||
if (hfi_buffer->flags & HFI_BUF_FW_FLAG_LAST) {
|
||||
ret = iris_inst_sub_state_change_drain_last(inst);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (hfi_buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) {
|
||||
ret = iris_inst_sub_state_change_drc_last(inst);
|
||||
if (ret)
|
||||
|
@ -425,6 +435,21 @@ static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int iris_hfi_gen2_handle_session_stop(struct iris_inst *inst,
|
||||
struct iris_hfi_packet *pkt)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (pkt->port == HFI_PORT_RAW)
|
||||
ret = iris_inst_sub_state_change_pause(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
||||
else if (pkt->port == HFI_PORT_BITSTREAM)
|
||||
ret = iris_inst_sub_state_change_pause(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
|
||||
|
||||
complete(&inst->completion);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst,
|
||||
struct iris_hfi_packet *pkt)
|
||||
{
|
||||
|
@ -453,6 +478,22 @@ static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst,
|
|||
return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer);
|
||||
}
|
||||
|
||||
static int iris_hfi_gen2_handle_session_drain(struct iris_inst *inst,
|
||||
struct iris_hfi_packet *pkt)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS)) {
|
||||
iris_inst_change_state(inst, IRIS_INST_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (inst->sub_state & IRIS_INST_SUB_DRAIN)
|
||||
ret = iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_INPUT_PAUSE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iris_hfi_gen2_read_input_subcr_params(struct iris_inst *inst)
|
||||
{
|
||||
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
|
||||
|
@ -572,7 +613,7 @@ static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst,
|
|||
iris_hfi_gen2_handle_session_close(inst, pkt);
|
||||
break;
|
||||
case HFI_CMD_STOP:
|
||||
complete(&inst->completion);
|
||||
iris_hfi_gen2_handle_session_stop(inst, pkt);
|
||||
break;
|
||||
case HFI_CMD_BUFFER:
|
||||
ret = iris_hfi_gen2_handle_session_buffer(inst, pkt);
|
||||
|
@ -580,6 +621,9 @@ static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst,
|
|||
case HFI_CMD_SETTINGS_CHANGE:
|
||||
ret = iris_hfi_gen2_handle_src_change(inst, pkt);
|
||||
break;
|
||||
case HFI_CMD_DRAIN:
|
||||
ret = iris_hfi_gen2_handle_session_drain(inst, pkt);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <media/v4l2-mem2mem.h>
|
||||
|
||||
#include "iris_instance.h"
|
||||
|
||||
static bool iris_allow_inst_state_change(struct iris_inst *inst,
|
||||
|
@ -148,6 +150,21 @@ int iris_inst_sub_state_change_drc(struct iris_inst *inst)
|
|||
return iris_inst_change_sub_state(inst, 0, set_sub_state);
|
||||
}
|
||||
|
||||
int iris_inst_sub_state_change_drain_last(struct iris_inst *inst)
|
||||
{
|
||||
enum iris_inst_sub_state set_sub_state;
|
||||
|
||||
if (inst->sub_state & IRIS_INST_SUB_DRAIN_LAST)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(inst->sub_state & IRIS_INST_SUB_DRAIN))
|
||||
return -EINVAL;
|
||||
|
||||
set_sub_state = IRIS_INST_SUB_DRAIN_LAST | IRIS_INST_SUB_OUTPUT_PAUSE;
|
||||
|
||||
return iris_inst_change_sub_state(inst, 0, set_sub_state);
|
||||
}
|
||||
|
||||
int iris_inst_sub_state_change_drc_last(struct iris_inst *inst)
|
||||
{
|
||||
enum iris_inst_sub_state set_sub_state;
|
||||
|
@ -166,3 +183,54 @@ int iris_inst_sub_state_change_drc_last(struct iris_inst *inst)
|
|||
|
||||
return iris_inst_change_sub_state(inst, 0, set_sub_state);
|
||||
}
|
||||
|
||||
int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane)
|
||||
{
|
||||
enum iris_inst_sub_state set_sub_state;
|
||||
|
||||
if (V4L2_TYPE_IS_OUTPUT(plane)) {
|
||||
if (inst->sub_state & IRIS_INST_SUB_DRC &&
|
||||
!(inst->sub_state & IRIS_INST_SUB_DRC_LAST))
|
||||
return -EINVAL;
|
||||
|
||||
if (inst->sub_state & IRIS_INST_SUB_DRAIN &&
|
||||
!(inst->sub_state & IRIS_INST_SUB_DRAIN_LAST))
|
||||
return -EINVAL;
|
||||
|
||||
set_sub_state = IRIS_INST_SUB_INPUT_PAUSE;
|
||||
} else {
|
||||
set_sub_state = IRIS_INST_SUB_OUTPUT_PAUSE;
|
||||
}
|
||||
|
||||
return iris_inst_change_sub_state(inst, 0, set_sub_state);
|
||||
}
|
||||
|
||||
static inline bool iris_drc_pending(struct iris_inst *inst)
|
||||
{
|
||||
return inst->sub_state & IRIS_INST_SUB_DRC &&
|
||||
inst->sub_state & IRIS_INST_SUB_DRC_LAST;
|
||||
}
|
||||
|
||||
static inline bool iris_drain_pending(struct iris_inst *inst)
|
||||
{
|
||||
return inst->sub_state & IRIS_INST_SUB_DRAIN &&
|
||||
inst->sub_state & IRIS_INST_SUB_DRAIN_LAST;
|
||||
}
|
||||
|
||||
bool iris_allow_cmd(struct iris_inst *inst, u32 cmd)
|
||||
{
|
||||
struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx);
|
||||
struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx);
|
||||
|
||||
if (cmd == V4L2_DEC_CMD_START) {
|
||||
if (vb2_is_streaming(src_q) || vb2_is_streaming(dst_q))
|
||||
if (iris_drc_pending(inst) || iris_drain_pending(inst))
|
||||
return true;
|
||||
} else if (cmd == V4L2_DEC_CMD_STOP) {
|
||||
if (vb2_is_streaming(src_q))
|
||||
if (inst->sub_state != IRIS_INST_SUB_DRAIN)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -104,6 +104,9 @@ enum iris_inst_state {
|
|||
* sent to client.
|
||||
* @IRIS_INST_SUB_DRC_LAST: indicates last buffer is received from firmware
|
||||
* as part of source change.
|
||||
* @IRIS_INST_SUB_DRAIN: indicates drain is in progress.
|
||||
* @IRIS_INST_SUB_DRAIN_LAST: indicates last buffer is received from firmware
|
||||
* as part of drain sequence.
|
||||
* @IRIS_INST_SUB_INPUT_PAUSE: source change is received form firmware. This
|
||||
* indicates that firmware is paused to process
|
||||
* any further input frames.
|
||||
|
@ -115,8 +118,10 @@ enum iris_inst_sub_state {
|
|||
IRIS_INST_SUB_FIRST_IPSC = BIT(0),
|
||||
IRIS_INST_SUB_DRC = BIT(1),
|
||||
IRIS_INST_SUB_DRC_LAST = BIT(2),
|
||||
IRIS_INST_SUB_INPUT_PAUSE = BIT(3),
|
||||
IRIS_INST_SUB_OUTPUT_PAUSE = BIT(4),
|
||||
IRIS_INST_SUB_DRAIN = BIT(3),
|
||||
IRIS_INST_SUB_DRAIN_LAST = BIT(4),
|
||||
IRIS_INST_SUB_INPUT_PAUSE = BIT(5),
|
||||
IRIS_INST_SUB_OUTPUT_PAUSE = BIT(6),
|
||||
};
|
||||
|
||||
int iris_inst_change_state(struct iris_inst *inst,
|
||||
|
@ -124,9 +129,13 @@ int iris_inst_change_state(struct iris_inst *inst,
|
|||
int iris_inst_change_sub_state(struct iris_inst *inst,
|
||||
enum iris_inst_sub_state clear_sub_state,
|
||||
enum iris_inst_sub_state set_sub_state);
|
||||
|
||||
int iris_inst_state_change_streamon(struct iris_inst *inst, u32 plane);
|
||||
int iris_inst_state_change_streamoff(struct iris_inst *inst, u32 plane);
|
||||
int iris_inst_sub_state_change_drc(struct iris_inst *inst);
|
||||
int iris_inst_sub_state_change_drain_last(struct iris_inst *inst);
|
||||
int iris_inst_sub_state_change_drc_last(struct iris_inst *inst);
|
||||
int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane);
|
||||
bool iris_allow_cmd(struct iris_inst *inst, u32 cmd);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -206,8 +206,10 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2)
|
|||
}
|
||||
|
||||
if (V4L2_TYPE_IS_CAPTURE(vb2->vb2_queue->type)) {
|
||||
if (inst->sub_state & IRIS_INST_SUB_DRC &&
|
||||
inst->sub_state & IRIS_INST_SUB_DRC_LAST) {
|
||||
if ((inst->sub_state & IRIS_INST_SUB_DRC &&
|
||||
inst->sub_state & IRIS_INST_SUB_DRC_LAST) ||
|
||||
(inst->sub_state & IRIS_INST_SUB_DRAIN &&
|
||||
inst->sub_state & IRIS_INST_SUB_DRAIN_LAST)) {
|
||||
vbuf->flags |= V4L2_BUF_FLAG_LAST;
|
||||
vbuf->sequence = inst->sequence_cap++;
|
||||
vbuf->field = V4L2_FIELD_NONE;
|
||||
|
|
|
@ -371,6 +371,7 @@ static int iris_vdec_process_streamon_input(struct iris_inst *inst)
|
|||
}
|
||||
|
||||
if (inst->sub_state & IRIS_INST_SUB_DRC ||
|
||||
inst->sub_state & IRIS_INST_SUB_DRAIN ||
|
||||
inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) {
|
||||
if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) {
|
||||
if (hfi_ops->session_pause) {
|
||||
|
@ -422,15 +423,20 @@ int iris_vdec_streamon_input(struct iris_inst *inst)
|
|||
static int iris_vdec_process_streamon_output(struct iris_inst *inst)
|
||||
{
|
||||
const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
|
||||
bool drain_active = false, drc_active = false;
|
||||
enum iris_inst_sub_state clear_sub_state = 0;
|
||||
bool drc_active = false;
|
||||
int ret = 0;
|
||||
|
||||
drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN &&
|
||||
inst->sub_state & IRIS_INST_SUB_DRAIN_LAST;
|
||||
|
||||
drc_active = inst->sub_state & IRIS_INST_SUB_DRC &&
|
||||
inst->sub_state & IRIS_INST_SUB_DRC_LAST;
|
||||
|
||||
if (drc_active)
|
||||
clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST;
|
||||
else if (drain_active)
|
||||
clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST;
|
||||
|
||||
if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
|
||||
ret = iris_alloc_and_queue_input_int_bufs(inst);
|
||||
|
@ -446,8 +452,12 @@ static int iris_vdec_process_streamon_output(struct iris_inst *inst)
|
|||
|
||||
if (inst->state == IRIS_INST_INPUT_STREAMING &&
|
||||
inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
|
||||
ret = hfi_ops->session_resume_drc(inst,
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
|
||||
if (!drain_active)
|
||||
ret = hfi_ops->session_resume_drc(inst,
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
|
||||
else if (hfi_ops->session_resume_drain)
|
||||
ret = hfi_ops->session_resume_drain(inst,
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
|
||||
if (ret)
|
||||
return ret;
|
||||
clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
|
||||
|
@ -565,3 +575,78 @@ int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf)
|
|||
|
||||
return iris_queue_buffer(inst, buf);
|
||||
}
|
||||
|
||||
int iris_vdec_start_cmd(struct iris_inst *inst)
|
||||
{
|
||||
const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
|
||||
enum iris_inst_sub_state clear_sub_state = 0;
|
||||
struct vb2_queue *dst_vq;
|
||||
int ret;
|
||||
|
||||
dst_vq = v4l2_m2m_get_dst_vq(inst->m2m_ctx);
|
||||
|
||||
if (inst->sub_state & IRIS_INST_SUB_DRC &&
|
||||
inst->sub_state & IRIS_INST_SUB_DRC_LAST) {
|
||||
vb2_clear_last_buffer_dequeued(dst_vq);
|
||||
clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST;
|
||||
|
||||
if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
|
||||
ret = hfi_ops->session_resume_drc(inst,
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
|
||||
if (ret)
|
||||
return ret;
|
||||
clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
|
||||
}
|
||||
if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) {
|
||||
ret = hfi_ops->session_resume_drc(inst,
|
||||
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
||||
if (ret)
|
||||
return ret;
|
||||
clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
|
||||
}
|
||||
} else if (inst->sub_state & IRIS_INST_SUB_DRAIN &&
|
||||
inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) {
|
||||
vb2_clear_last_buffer_dequeued(dst_vq);
|
||||
clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST;
|
||||
if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
|
||||
if (hfi_ops->session_resume_drain) {
|
||||
ret =
|
||||
hfi_ops->session_resume_drain(inst,
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
|
||||
}
|
||||
if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) {
|
||||
if (hfi_ops->session_resume_drain) {
|
||||
ret =
|
||||
hfi_ops->session_resume_drain(inst,
|
||||
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
|
||||
}
|
||||
} else {
|
||||
dev_err(inst->core->dev, "start called before receiving last_flag\n");
|
||||
iris_inst_change_state(inst, IRIS_INST_ERROR);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return iris_inst_change_sub_state(inst, clear_sub_state, 0);
|
||||
}
|
||||
|
||||
int iris_vdec_stop_cmd(struct iris_inst *inst)
|
||||
{
|
||||
const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
|
||||
int ret;
|
||||
|
||||
ret = hfi_ops->session_drain(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_DRAIN);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ void iris_vdec_src_change(struct iris_inst *inst);
|
|||
int iris_vdec_streamon_input(struct iris_inst *inst);
|
||||
int iris_vdec_streamon_output(struct iris_inst *inst);
|
||||
int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf);
|
||||
int iris_vdec_start_cmd(struct iris_inst *inst);
|
||||
int iris_vdec_stop_cmd(struct iris_inst *inst);
|
||||
int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -365,6 +365,39 @@ static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subs
|
|||
return iris_vdec_subscribe_event(inst, sub);
|
||||
}
|
||||
|
||||
static int iris_dec_cmd(struct file *filp, void *fh,
|
||||
struct v4l2_decoder_cmd *dec)
|
||||
{
|
||||
struct iris_inst *inst = iris_get_inst(filp, NULL);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&inst->lock);
|
||||
|
||||
ret = v4l2_m2m_ioctl_decoder_cmd(filp, fh, dec);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
if (inst->state == IRIS_INST_DEINIT)
|
||||
goto unlock;
|
||||
|
||||
if (!iris_allow_cmd(inst, dec->cmd)) {
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (dec->cmd == V4L2_DEC_CMD_START)
|
||||
ret = iris_vdec_start_cmd(inst);
|
||||
else if (dec->cmd == V4L2_DEC_CMD_STOP)
|
||||
ret = iris_vdec_stop_cmd(inst);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&inst->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct v4l2_file_operations iris_v4l2_file_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = iris_open,
|
||||
|
@ -408,6 +441,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = {
|
|||
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
|
||||
.vidioc_streamon = v4l2_m2m_ioctl_streamon,
|
||||
.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
|
||||
.vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
|
||||
.vidioc_decoder_cmd = iris_dec_cmd,
|
||||
};
|
||||
|
||||
void iris_init_ops(struct iris_core *core)
|
||||
|
|
Loading…
Add table
Reference in a new issue