video: driver: initial state machine changes

- hierarchical state model which comprises of
  top level states and sub states
- top level states include OPEN, CLOSE, ERROR,
  INPUT_STREAMING, OUTPUT_STREAMING, STREAMING.
- sub states include DRAIN, DRC, DRAIN_LAST_BUFFER,
  DRC_LAST_BUFFER, INPUT_PAUSE, OUTPUT_PAUSE.
- follows deterministic approach for key sequences
  like DRC, DRAIN and last flag handling i.e none
  of these events are ignored or discarded.
- removal of auto start of firmware input port as
  part of ipsc handling.
- introduction of hfi commands for host controlled
  PAUSE and RESUME of firmware ports.
- introduction of information last flag packets
  for DRC and DRAIN when FW has insufficient
  output buffers.

Change-Id: Ie8c8f44af464d06f5a7bb76822f749c9874f869a
Signed-off-by: Darshana Patil <quic_darshana@quicinc.com>
This commit is contained in:
Darshana Patil
2022-06-02 10:42:56 -07:00
parent df3fd88dac
commit 10794c2968
17 changed files with 966 additions and 738 deletions

View File

@@ -1455,6 +1455,11 @@ static struct msm_platform_inst_capability instance_cap_data_kalama[] = {
HFI_PROP_AV1_DRAP_CONFIG, HFI_PROP_AV1_DRAP_CONFIG,
CAP_FLAG_INPUT_PORT}, CAP_FLAG_INPUT_PORT},
{LAST_FLAG_EVENT_ENABLE, DEC, CODECS_ALL,
V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_MPEG_MSM_VIDC_ENABLE,
1, V4L2_MPEG_MSM_VIDC_DISABLE,
V4L2_CID_MPEG_VIDC_LAST_FLAG_EVENT_ENABLE},
{META_BITSTREAM_RESOLUTION, DEC, AV1, {META_BITSTREAM_RESOLUTION, DEC, AV1,
V4L2_MPEG_VIDC_META_DISABLE, V4L2_MPEG_VIDC_META_DISABLE,
V4L2_MPEG_VIDC_META_ENABLE | V4L2_MPEG_VIDC_META_RX_INPUT | V4L2_MPEG_VIDC_META_ENABLE | V4L2_MPEG_VIDC_META_RX_INPUT |

View File

@@ -116,6 +116,7 @@ enum hfi_buffer_firmware_flags {
HFI_BUF_FW_FLAG_READONLY = 0x00000010, HFI_BUF_FW_FLAG_READONLY = 0x00000010,
HFI_BUF_FW_FLAG_CODEC_CONFIG = 0x00000100, HFI_BUF_FW_FLAG_CODEC_CONFIG = 0x00000100,
HFI_BUF_FW_FLAG_LAST = 0x10000000, HFI_BUF_FW_FLAG_LAST = 0x10000000,
HFI_BUF_FW_FLAG_PSC_LAST = 0x20000000,
}; };
enum hfi_metapayload_header_flags { enum hfi_metapayload_header_flags {
@@ -165,22 +166,23 @@ enum hfi_reserve_type {
#define HFI_CMD_DELIVERY_MODE 0x0100000A #define HFI_CMD_DELIVERY_MODE 0x0100000A
#define HFI_CMD_SUBSCRIBE_MODE 0x0100000B #define HFI_CMD_SUBSCRIBE_MODE 0x0100000B
#define HFI_CMD_SETTINGS_CHANGE 0x0100000C #define HFI_CMD_SETTINGS_CHANGE 0x0100000C
#define HFI_CMD_RESERVE 0x0100000F
#define HFI_SSR_TYPE_SW_ERR_FATAL 0x1 #define HFI_SSR_TYPE_SW_ERR_FATAL 0x1
#define HFI_SSR_TYPE_SW_DIV_BY_ZERO 0x2 #define HFI_SSR_TYPE_SW_DIV_BY_ZERO 0x2
#define HFI_SSR_TYPE_CPU_WDOG_IRQ 0x3 #define HFI_SSR_TYPE_CPU_WDOG_IRQ 0x3
#define HFI_SSR_TYPE_NOC_ERROR 0x4 #define HFI_SSR_TYPE_NOC_ERROR 0x4
#define HFI_BITMASK_HW_CLIENT_ID 0x000000f0 #define HFI_BITMASK_HW_CLIENT_ID 0x000000f0
#define HFI_BITMASK_SSR_TYPE 0x0000000f #define HFI_BITMASK_SSR_TYPE 0x0000000f
#define HFI_CMD_SSR 0x0100000D #define HFI_CMD_SSR 0x0100000D
#define HFI_STABILITY_TYPE_VCODEC_HUNG 0x1 #define HFI_STABILITY_TYPE_VCODEC_HUNG 0x1
#define HFI_STABILITY_TYPE_ENC_BUFFER_FULL 0x2 #define HFI_STABILITY_TYPE_ENC_BUFFER_FULL 0x2
#define HFI_BITMASK_STABILITY_TYPE 0x0000000f #define HFI_BITMASK_STABILITY_TYPE 0x0000000f
#define HFI_CMD_STABILITY 0x0100000E #define HFI_CMD_STABILITY 0x0100000E
#define HFI_CMD_RESERVE 0x0100000F
#define HFI_CMD_FLUSH 0x01000010
#define HFI_CMD_PAUSE 0x01000011
#define HFI_CMD_END 0x01FFFFFF #define HFI_CMD_END 0x01FFFFFF
#endif //__H_HFI_COMMAND_H__ #endif //__H_HFI_COMMAND_H__

View File

@@ -607,6 +607,10 @@ enum hfi_saliency_type {
#define HFI_INFO_VCODEC_RESET 0x06000005 #define HFI_INFO_VCODEC_RESET 0x06000005
#define HFI_INFO_HFI_FLAG_DRAIN_LAST 0x06000006
#define HFI_INFO_HFI_FLAG_PSC_LAST 0x06000007
#define HFI_INFORMATION_END 0x06FFFFFF #define HFI_INFORMATION_END 0x06FFFFFF
#endif //__H_HFI_PROPERTY_H__ #endif //__H_HFI_PROPERTY_H__

View File

@@ -520,7 +520,6 @@ static inline unsigned int VIDEO_RAW_BUFFER_SIZE(unsigned int v4l2_fmt,
uv_meta_scanlines, 4096); uv_meta_scanlines, 4096);
size = (y_ubwc_plane + uv_ubwc_plane + y_meta_plane + size = (y_ubwc_plane + uv_ubwc_plane + y_meta_plane +
uv_meta_plane); uv_meta_plane);
size = MSM_MEDIA_ALIGN(size, 4096);
} else { } else {
if (pix_width <= INTERLACE_WIDTH_MAX && if (pix_width <= INTERLACE_WIDTH_MAX &&
pix_height <= INTERLACE_HEIGHT_MAX && pix_height <= INTERLACE_HEIGHT_MAX &&
@@ -597,6 +596,7 @@ static inline unsigned int VIDEO_RAW_BUFFER_SIZE(unsigned int v4l2_fmt,
} }
invalid_input: invalid_input:
size = MSM_MEDIA_ALIGN(size, 4096);
return size; return size;
} }

View File

@@ -352,6 +352,17 @@ static inline bool is_enc_slice_delivery_mode(struct msm_vidc_inst *inst)
V4L2_MPEG_VIDC_HEVC_ENCODE_DELIVERY_MODE_SLICE_BASED))); V4L2_MPEG_VIDC_HEVC_ENCODE_DELIVERY_MODE_SLICE_BASED)));
} }
static inline bool is_state(struct msm_vidc_inst *inst, enum msm_vidc_state state)
{
return inst->state == state;
}
static inline bool is_sub_state(struct msm_vidc_inst *inst,
enum msm_vidc_sub_state sub_state)
{
return (inst->sub_state & sub_state);
}
const char *cap_name(enum msm_vidc_inst_capability_type cap_id); const char *cap_name(enum msm_vidc_inst_capability_type cap_id);
const char *v4l2_pixelfmt_name(u32 pixelfmt); const char *v4l2_pixelfmt_name(u32 pixelfmt);
const char *v4l2_type_name(u32 port); const char *v4l2_type_name(u32 port);
@@ -382,10 +393,13 @@ u32 v4l2_matrix_coeff_from_driver(struct msm_vidc_inst *inst,
int v4l2_type_to_driver_port(struct msm_vidc_inst *inst, u32 type, int v4l2_type_to_driver_port(struct msm_vidc_inst *inst, u32 type,
const char *func); const char *func);
const char *allow_name(enum msm_vidc_allow allow); const char *allow_name(enum msm_vidc_allow allow);
const char *state_name(enum msm_vidc_inst_state state); const char *state_name(enum msm_vidc_state state);
const char *core_state_name(enum msm_vidc_core_state state); const char *core_state_name(enum msm_vidc_core_state state);
int msm_vidc_change_inst_state(struct msm_vidc_inst *inst, int msm_vidc_change_state(struct msm_vidc_inst *inst,
enum msm_vidc_inst_state request_state, const char *func); enum msm_vidc_state request_state, const char *func);
int msm_vidc_change_sub_state(struct msm_vidc_inst *inst,
enum msm_vidc_sub_state clear_sub_states,
enum msm_vidc_sub_state set_sub_states, const char *func);
int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst, int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst,
enum msm_vidc_buffer_type buffer_type, u32 index); enum msm_vidc_buffer_type buffer_type, u32 index);
int msm_vidc_get_internal_buffers(struct msm_vidc_inst *inst, int msm_vidc_get_internal_buffers(struct msm_vidc_inst *inst,
@@ -406,8 +420,6 @@ int msm_vidc_session_open(struct msm_vidc_inst *inst);
int msm_vidc_session_set_codec(struct msm_vidc_inst *inst); int msm_vidc_session_set_codec(struct msm_vidc_inst *inst);
int msm_vidc_session_set_secure_mode(struct msm_vidc_inst *inst); int msm_vidc_session_set_secure_mode(struct msm_vidc_inst *inst);
int msm_vidc_session_set_default_header(struct msm_vidc_inst *inst); int msm_vidc_session_set_default_header(struct msm_vidc_inst *inst);
int msm_vidc_session_streamon(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port);
int msm_vidc_session_streamoff(struct msm_vidc_inst *inst, int msm_vidc_session_streamoff(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port); enum msm_vidc_port_type port);
int msm_vidc_session_close(struct msm_vidc_inst *inst); int msm_vidc_session_close(struct msm_vidc_inst *inst);
@@ -502,13 +514,21 @@ bool msm_vidc_allow_streamon(struct msm_vidc_inst *inst, u32 type);
enum msm_vidc_allow msm_vidc_allow_streamoff(struct msm_vidc_inst *inst, u32 type); enum msm_vidc_allow msm_vidc_allow_streamoff(struct msm_vidc_inst *inst, u32 type);
enum msm_vidc_allow msm_vidc_allow_qbuf(struct msm_vidc_inst *inst, u32 type); enum msm_vidc_allow msm_vidc_allow_qbuf(struct msm_vidc_inst *inst, u32 type);
enum msm_vidc_allow msm_vidc_allow_input_psc(struct msm_vidc_inst *inst); enum msm_vidc_allow msm_vidc_allow_input_psc(struct msm_vidc_inst *inst);
bool msm_vidc_allow_last_flag(struct msm_vidc_inst *inst); bool msm_vidc_allow_drain_last_flag(struct msm_vidc_inst *inst);
bool msm_vidc_allow_psc_last_flag(struct msm_vidc_inst *inst);
int msm_vidc_state_change_streamon(struct msm_vidc_inst *inst, u32 type); int msm_vidc_state_change_streamon(struct msm_vidc_inst *inst, u32 type);
int msm_vidc_state_change_streamoff(struct msm_vidc_inst *inst, u32 type); int msm_vidc_state_change_streamoff(struct msm_vidc_inst *inst, u32 type);
int msm_vidc_state_change_stop(struct msm_vidc_inst *inst);
int msm_vidc_state_change_start(struct msm_vidc_inst *inst);
int msm_vidc_state_change_input_psc(struct msm_vidc_inst *inst); int msm_vidc_state_change_input_psc(struct msm_vidc_inst *inst);
int msm_vidc_state_change_last_flag(struct msm_vidc_inst *inst); int msm_vidc_state_change_drain_last_flag(struct msm_vidc_inst *inst);
int msm_vidc_state_change_psc_last_flag(struct msm_vidc_inst *inst);
int msm_vidc_process_drain(struct msm_vidc_inst *inst);
int msm_vidc_process_resume(struct msm_vidc_inst *inst);
int msm_vidc_process_streamon(struct msm_vidc_inst *inst, u32 type);
int msm_vidc_process_stop_done(struct msm_vidc_inst *inst,
enum signal_session_response signal_type);
int msm_vidc_process_drain_done(struct msm_vidc_inst *inst);
int msm_vidc_process_drain_last_flag(struct msm_vidc_inst *inst);
int msm_vidc_process_psc_last_flag(struct msm_vidc_inst *inst);
int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst); int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst);
u32 msm_vidc_get_max_bitrate(struct msm_vidc_inst* inst); u32 msm_vidc_get_max_bitrate(struct msm_vidc_inst* inst);
int msm_vidc_get_fps(struct msm_vidc_inst *inst); int msm_vidc_get_fps(struct msm_vidc_inst *inst);
@@ -557,6 +577,8 @@ bool res_is_less_than(u32 width, u32 height,
u32 ref_width, u32 ref_height); u32 ref_width, u32 ref_height);
bool res_is_less_than_or_equal_to(u32 width, u32 height, bool res_is_less_than_or_equal_to(u32 width, u32 height,
u32 ref_width, u32 ref_height); u32 ref_width, u32 ref_height);
int signal_session_msg_receipt(struct msm_vidc_inst *inst,
enum signal_session_response cmd);
int msm_vidc_get_properties(struct msm_vidc_inst *inst); int msm_vidc_get_properties(struct msm_vidc_inst *inst);
int msm_vidc_create_input_metadata_buffer(struct msm_vidc_inst *inst, int buf_fd); int msm_vidc_create_input_metadata_buffer(struct msm_vidc_inst *inst, int buf_fd);
int msm_vidc_update_input_meta_buffer_index(struct msm_vidc_inst *inst, struct vb2_buffer *vb2); int msm_vidc_update_input_meta_buffer_index(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);

View File

@@ -75,19 +75,30 @@ struct msm_vidc_buffers_info {
struct msm_vidc_buffers partial_data; struct msm_vidc_buffers partial_data;
}; };
enum msm_vidc_inst_state { enum msm_vidc_state {
MSM_VIDC_OPEN = 1, MSM_VIDC_OPEN = 1,
MSM_VIDC_START_INPUT = 2, MSM_VIDC_INPUT_STREAMING = 2,
MSM_VIDC_START_OUTPUT = 3, MSM_VIDC_OUTPUT_STREAMING = 3,
MSM_VIDC_START = 4, MSM_VIDC_STREAMING = 4,
MSM_VIDC_DRC = 5, MSM_VIDC_CLOSE = 5,
MSM_VIDC_DRC_LAST_FLAG = 6, MSM_VIDC_ERROR = 6,
MSM_VIDC_DRAIN = 7, };
MSM_VIDC_DRAIN_LAST_FLAG = 8,
MSM_VIDC_DRC_DRAIN = 9, #define MSM_VIDC_SUB_STATE_NONE 0
MSM_VIDC_DRC_DRAIN_LAST_FLAG = 10, #define MSM_VIDC_MAX_SUB_STATES 6
MSM_VIDC_DRAIN_START_INPUT = 11, /*
MSM_VIDC_ERROR = 12, * max value of inst->sub_state if all
* the 6 valid bits are set i.e 111111==>63
*/
#define MSM_VIDC_MAX_SUB_STATE_VALUE ((1 << MSM_VIDC_MAX_SUB_STATES) - 1)
enum msm_vidc_sub_state {
MSM_VIDC_DRAIN = BIT(0),
MSM_VIDC_DRC = BIT(1),
MSM_VIDC_DRAIN_LAST_BUFFER = BIT(2),
MSM_VIDC_DRC_LAST_BUFFER = BIT(3),
MSM_VIDC_INPUT_PAUSE = BIT(4),
MSM_VIDC_OUTPUT_PAUSE = BIT(5),
}; };
struct buf_queue { struct buf_queue {
@@ -99,7 +110,9 @@ struct msm_vidc_inst {
struct mutex lock; struct mutex lock;
struct mutex request_lock; struct mutex request_lock;
struct mutex client_lock; struct mutex client_lock;
enum msm_vidc_inst_state state; enum msm_vidc_state state;
enum msm_vidc_sub_state sub_state;
char sub_state_name[MAX_NAME_LENGTH];
enum msm_vidc_domain_type domain; enum msm_vidc_domain_type domain;
enum msm_vidc_codec_type codec; enum msm_vidc_codec_type codec;
void *core; void *core;
@@ -138,12 +151,10 @@ struct msm_vidc_inst {
struct msm_vidc_decode_batch decode_batch; struct msm_vidc_decode_batch decode_batch;
struct msm_vidc_decode_vpp_delay decode_vpp_delay; struct msm_vidc_decode_vpp_delay decode_vpp_delay;
struct msm_vidc_session_idle session_idle; struct msm_vidc_session_idle session_idle;
struct delayed_work response_work;
struct delayed_work stats_work; struct delayed_work stats_work;
struct work_struct stability_work; struct work_struct stability_work;
struct msm_vidc_stability stability; struct msm_vidc_stability stability;
struct workqueue_struct *response_workq; struct workqueue_struct *workq;
struct list_head response_works; /* list of struct response_work */
struct list_head enc_input_crs; struct list_head enc_input_crs;
struct list_head dmabuf_tracker; /* list of struct msm_memory_dmabuf */ struct list_head dmabuf_tracker; /* list of struct msm_memory_dmabuf */
struct list_head input_timer_list; /* list of struct msm_vidc_input_timer */ struct list_head input_timer_list; /* list of struct msm_vidc_input_timer */

View File

@@ -500,6 +500,7 @@ enum msm_vidc_inst_capability_type {
CAVLC_MAX_BITRATE, CAVLC_MAX_BITRATE,
ALLINTRA_MAX_BITRATE, ALLINTRA_MAX_BITRATE,
LOWLATENCY_MAX_BITRATE, LOWLATENCY_MAX_BITRATE,
LAST_FLAG_EVENT_ENABLE,
/* place all root(no parent) enums before this line */ /* place all root(no parent) enums before this line */
PROFILE, PROFILE,
@@ -940,19 +941,6 @@ enum msm_vidc_allow {
MSM_VIDC_IGNORE, MSM_VIDC_IGNORE,
}; };
enum response_work_type {
RESP_WORK_INPUT_PSC = 1,
RESP_WORK_OUTPUT_PSC,
RESP_WORK_LAST_FLAG,
};
struct response_work {
struct list_head list;
enum response_work_type type;
void *data;
u32 data_size;
};
struct msm_vidc_ssr { struct msm_vidc_ssr {
bool trigger; bool trigger;
enum msm_vidc_ssr_trigger_type ssr_type; enum msm_vidc_ssr_trigger_type ssr_type;

View File

@@ -49,6 +49,10 @@ int venus_hfi_start(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
int venus_hfi_stop(struct msm_vidc_inst *inst, enum msm_vidc_port_type port); int venus_hfi_stop(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
int venus_hfi_session_close(struct msm_vidc_inst *inst); int venus_hfi_session_close(struct msm_vidc_inst *inst);
int venus_hfi_session_open(struct msm_vidc_inst *inst); int venus_hfi_session_open(struct msm_vidc_inst *inst);
int venus_hfi_session_pause(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
int venus_hfi_session_resume(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port, u32 payload);
int venus_hfi_session_drain(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
int venus_hfi_session_set_codec(struct msm_vidc_inst *inst); int venus_hfi_session_set_codec(struct msm_vidc_inst *inst);
int venus_hfi_session_set_secure_mode(struct msm_vidc_inst *inst); int venus_hfi_session_set_secure_mode(struct msm_vidc_inst *inst);
int venus_hfi_core_init(struct msm_vidc_core *core); int venus_hfi_core_init(struct msm_vidc_core *core);

View File

@@ -16,11 +16,6 @@ bool is_valid_port(struct msm_vidc_inst *inst, u32 port,
const char *func); const char *func);
bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst, bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst,
u32 buffer_type, const char *func); u32 buffer_type, const char *func);
void handle_session_response_work_handler(struct work_struct *work);
int handle_session_response_work(struct msm_vidc_inst *inst,
struct response_work *work);
int cancel_response_work(struct msm_vidc_inst *inst);
int cancel_response_work_sync(struct msm_vidc_inst *inst);
int handle_system_error(struct msm_vidc_core *core, int handle_system_error(struct msm_vidc_core *core,
struct hfi_packet *pkt); struct hfi_packet *pkt);
void fw_coredump(struct msm_vidc_core *core); void fw_coredump(struct msm_vidc_core *core);

View File

@@ -1160,24 +1160,6 @@ static int msm_vdec_set_delivery_mode_property(struct msm_vidc_inst *inst,
return rc; return rc;
} }
static int msm_vdec_session_resume(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
int rc = 0;
i_vpr_h(inst, "%s()\n", __func__);
rc = venus_hfi_session_command(inst,
HFI_CMD_RESUME,
port,
HFI_PAYLOAD_NONE,
NULL,
0);
if (rc)
return rc;
return rc;
}
int msm_vdec_init_input_subcr_params(struct msm_vidc_inst *inst) int msm_vdec_init_input_subcr_params(struct msm_vidc_inst *inst)
{ {
struct msm_vidc_subscription_params *subsc_params; struct msm_vidc_subscription_params *subsc_params;
@@ -1330,7 +1312,7 @@ static int msm_vdec_read_input_subcr_params(struct msm_vidc_inst *inst)
if (inst->buffers.output.min_count != 1) { if (inst->buffers.output.min_count != 1) {
i_vpr_e(inst, "%s: invalid min count %d in thumbnail case\n", i_vpr_e(inst, "%s: invalid min count %d in thumbnail case\n",
__func__, inst->buffers.output.min_count); __func__, inst->buffers.output.min_count);
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
} }
} }
inst->crop.top = subsc_params.crop_offsets[0] & 0xFFFF; inst->crop.top = subsc_params.crop_offsets[0] & 0xFFFF;
@@ -1413,16 +1395,11 @@ int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst)
if (rc) if (rc)
return rc; return rc;
rc = msm_vdec_session_resume(inst, INPUT_PORT);
if (rc)
return rc;
return rc; return rc;
} }
int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst) int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst)
{ {
//todo
return 0; return 0;
} }
@@ -1496,23 +1473,23 @@ int msm_vdec_streamon_input(struct msm_vidc_inst *inst)
rc = msm_vdec_subscribe_input_port_settings_change( rc = msm_vdec_subscribe_input_port_settings_change(
inst, INPUT_PORT); inst, INPUT_PORT);
if (rc) if (rc)
return rc; goto error;
inst->ipsc_properties_set = true; inst->ipsc_properties_set = true;
} }
rc = msm_vdec_subscribe_property(inst, INPUT_PORT); rc = msm_vdec_subscribe_property(inst, INPUT_PORT);
if (rc) if (rc)
return rc; goto error;
rc = msm_vdec_subscribe_metadata(inst, INPUT_PORT); rc = msm_vdec_subscribe_metadata(inst, INPUT_PORT);
if (rc) if (rc)
return rc; goto error;
rc = msm_vdec_set_delivery_mode_metadata(inst, INPUT_PORT); rc = msm_vdec_set_delivery_mode_metadata(inst, INPUT_PORT);
if (rc) if (rc)
return rc; goto error;
rc = msm_vidc_session_streamon(inst, INPUT_PORT); rc = msm_vidc_process_streamon(inst, INPUT_PORT);
if (rc) if (rc)
goto error; goto error;
@@ -1788,11 +1765,11 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
rc = msm_vidc_check_session_supported(inst); rc = msm_vidc_check_session_supported(inst);
if (rc) if (rc)
return rc; goto error;
rc = msm_vdec_update_max_map_output_count(inst); rc = msm_vdec_update_max_map_output_count(inst);
if (rc) if (rc)
return rc; goto error;
rc = msm_vdec_set_output_properties(inst); rc = msm_vdec_set_output_properties(inst);
if (rc) if (rc)
@@ -1800,8 +1777,8 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
if (!inst->opsc_properties_set) { if (!inst->opsc_properties_set) {
memcpy(&inst->subcr_params[OUTPUT_PORT], memcpy(&inst->subcr_params[OUTPUT_PORT],
&inst->subcr_params[INPUT_PORT], &inst->subcr_params[INPUT_PORT],
sizeof(inst->subcr_params[INPUT_PORT])); sizeof(inst->subcr_params[INPUT_PORT]));
rc = msm_vdec_subscribe_output_port_settings_change(inst, OUTPUT_PORT); rc = msm_vdec_subscribe_output_port_settings_change(inst, OUTPUT_PORT);
if (rc) if (rc)
goto error; goto error;
@@ -1810,7 +1787,7 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
rc = msm_vdec_subscribe_property(inst, OUTPUT_PORT); rc = msm_vdec_subscribe_property(inst, OUTPUT_PORT);
if (rc) if (rc)
return rc; goto error;
rc = msm_vdec_subscribe_metadata(inst, OUTPUT_PORT); rc = msm_vdec_subscribe_metadata(inst, OUTPUT_PORT);
if (rc) if (rc)
@@ -1818,11 +1795,11 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
rc = msm_vdec_set_delivery_mode_property(inst, OUTPUT_PORT); rc = msm_vdec_set_delivery_mode_property(inst, OUTPUT_PORT);
if (rc) if (rc)
return rc; goto error;
rc = msm_vdec_set_delivery_mode_metadata(inst, OUTPUT_PORT); rc = msm_vdec_set_delivery_mode_metadata(inst, OUTPUT_PORT);
if (rc) if (rc)
return rc; goto error;
rc = msm_vdec_get_output_internal_buffers(inst); rc = msm_vdec_get_output_internal_buffers(inst);
if (rc) if (rc)
@@ -1832,7 +1809,7 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
if (rc) if (rc)
goto error; goto error;
rc = msm_vidc_session_streamon(inst, OUTPUT_PORT); rc = msm_vidc_process_streamon(inst, OUTPUT_PORT);
if (rc) if (rc)
goto error; goto error;
@@ -1862,10 +1839,6 @@ static inline enum msm_vidc_allow msm_vdec_allow_queue_deferred_buffers(
if (inst->power.buffer_counter <= SKIP_BATCH_WINDOW) if (inst->power.buffer_counter <= SKIP_BATCH_WINDOW)
return MSM_VIDC_ALLOW; return MSM_VIDC_ALLOW;
/* do not defer, if client waiting for last flag FBD */
if (inst->state != MSM_VIDC_START)
return MSM_VIDC_ALLOW;
/* defer qbuf, if pending buffers count less than batch size */ /* defer qbuf, if pending buffers count less than batch size */
count = msm_vidc_num_buffers(inst, MSM_VIDC_BUF_OUTPUT, MSM_VIDC_ATTR_DEFERRED); count = msm_vidc_num_buffers(inst, MSM_VIDC_BUF_OUTPUT, MSM_VIDC_ATTR_DEFERRED);
if (count < inst->decode_batch.size) if (count < inst->decode_batch.size)
@@ -2192,7 +2165,6 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
{ {
int rc = 0; int rc = 0;
enum msm_vidc_allow allow = MSM_VIDC_DISALLOW; enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
enum msm_vidc_port_type port;
struct msm_vidc_inst_capability *capability; struct msm_vidc_inst_capability *capability;
if (!inst || !inst->core || !inst->capabilities) { if (!inst || !inst->core || !inst->capabilities) {
@@ -2210,15 +2182,7 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
return 0; return 0;
else if (allow != MSM_VIDC_ALLOW) else if (allow != MSM_VIDC_ALLOW)
return -EINVAL; return -EINVAL;
rc = venus_hfi_session_command(inst, rc = msm_vidc_process_drain(inst);
HFI_CMD_DRAIN,
INPUT_PORT,
HFI_PAYLOAD_NONE,
NULL,
0);
if (rc)
return rc;
rc = msm_vidc_state_change_stop(inst);
if (rc) if (rc)
return rc; return rc;
} else if (cmd == V4L2_DEC_CMD_START) { } else if (cmd == V4L2_DEC_CMD_START) {
@@ -2236,11 +2200,6 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
if (!msm_vidc_allow_start(inst)) if (!msm_vidc_allow_start(inst))
return -EBUSY; return -EBUSY;
port = (inst->state == MSM_VIDC_DRAIN_LAST_FLAG) ? INPUT_PORT : OUTPUT_PORT;
rc = msm_vidc_state_change_start(inst);
if (rc)
return rc;
/* tune power features */ /* tune power features */
inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst); inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
@@ -2252,10 +2211,15 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
if (rc) if (rc)
return rc; return rc;
/* queue pending deferred buffers */
rc = msm_vidc_queue_deferred_buffers(inst, MSM_VIDC_BUF_OUTPUT);
if (rc)
return rc;
/* print final buffer counts & size details */ /* print final buffer counts & size details */
msm_vidc_print_buffer_info(inst); msm_vidc_print_buffer_info(inst);
rc = msm_vdec_session_resume(inst, port); rc = msm_vidc_process_resume(inst);
if (rc) if (rc)
return rc; return rc;
@@ -2592,6 +2556,7 @@ int msm_vdec_subscribe_event(struct msm_vidc_inst *inst,
switch (sub->type) { switch (sub->type) {
case V4L2_EVENT_EOS: case V4L2_EVENT_EOS:
case V4L2_EVENT_VIDC_METADATA: case V4L2_EVENT_VIDC_METADATA:
case V4L2_EVENT_VIDC_LAST_FLAG:
rc = v4l2_event_subscribe(&inst->event_handler, sub, MAX_EVENTS, NULL); rc = v4l2_event_subscribe(&inst->event_handler, sub, MAX_EVENTS, NULL);
break; break;
case V4L2_EVENT_SOURCE_CHANGE: case V4L2_EVENT_SOURCE_CHANGE:

View File

@@ -857,13 +857,13 @@ int msm_venc_streamon_input(struct msm_vidc_inst *inst)
rc = msm_venc_property_subscription(inst, INPUT_PORT); rc = msm_venc_property_subscription(inst, INPUT_PORT);
if (rc) if (rc)
return rc; goto error;
rc = msm_venc_metadata_delivery(inst, INPUT_PORT); rc = msm_venc_metadata_delivery(inst, INPUT_PORT);
if (rc) if (rc)
return rc; goto error;
rc = msm_vidc_session_streamon(inst, INPUT_PORT); rc = msm_vidc_process_streamon(inst, INPUT_PORT);
if (rc) if (rc)
goto error; goto error;
@@ -910,15 +910,7 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
return 0; return 0;
else if (allow != MSM_VIDC_ALLOW) else if (allow != MSM_VIDC_ALLOW)
return -EINVAL; return -EINVAL;
rc = venus_hfi_session_command(inst, rc = msm_vidc_process_drain(inst);
HFI_CMD_DRAIN,
INPUT_PORT,
HFI_PAYLOAD_NONE,
NULL,
0);
if (rc)
return rc;
rc = msm_vidc_state_change_stop(inst);
if (rc) if (rc)
return rc; return rc;
} else if (cmd == V4L2_ENC_CMD_START) { } else if (cmd == V4L2_ENC_CMD_START) {
@@ -928,10 +920,6 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_META_PORT].vb2q); vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_META_PORT].vb2q);
vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_PORT].vb2q); vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_PORT].vb2q);
rc = msm_vidc_state_change_start(inst);
if (rc)
return rc;
/* tune power features */ /* tune power features */
msm_vidc_allow_dcvs(inst); msm_vidc_allow_dcvs(inst);
msm_vidc_power_data_reset(inst); msm_vidc_power_data_reset(inst);
@@ -939,12 +927,7 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
/* print final buffer counts & size details */ /* print final buffer counts & size details */
msm_vidc_print_buffer_info(inst); msm_vidc_print_buffer_info(inst);
rc = venus_hfi_session_command(inst, rc = msm_vidc_process_resume(inst);
HFI_CMD_RESUME,
INPUT_PORT,
HFI_PAYLOAD_NONE,
NULL,
0);
if (rc) if (rc)
return rc; return rc;
} else { } else {
@@ -1030,7 +1013,7 @@ int msm_venc_streamon_output(struct msm_vidc_inst *inst)
if (rc) if (rc)
goto error; goto error;
rc = msm_vidc_session_streamon(inst, OUTPUT_PORT); rc = msm_vidc_process_streamon(inst, OUTPUT_PORT);
if (rc) if (rc)
goto error; goto error;

View File

@@ -889,6 +889,8 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
inst->domain = session_type; inst->domain = session_type;
inst->session_id = hash32_ptr(inst); inst->session_id = hash32_ptr(inst);
inst->state = MSM_VIDC_OPEN; inst->state = MSM_VIDC_OPEN;
inst->sub_state = MSM_VIDC_SUB_STATE_NONE;
strlcpy(inst->sub_state_name, "SUB_STATE_NONE", sizeof(inst->sub_state_name));
inst->active = true; inst->active = true;
inst->request = false; inst->request = false;
inst->ipsc_properties_set = false; inst->ipsc_properties_set = false;
@@ -908,7 +910,6 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
msm_vidc_vmem_free((void **)&inst); msm_vidc_vmem_free((void **)&inst);
return NULL; return NULL;
} }
INIT_LIST_HEAD(&inst->response_works);
INIT_LIST_HEAD(&inst->caps_list); INIT_LIST_HEAD(&inst->caps_list);
INIT_LIST_HEAD(&inst->timestamps.list); INIT_LIST_HEAD(&inst->timestamps.list);
INIT_LIST_HEAD(&inst->ts_reorder.list); INIT_LIST_HEAD(&inst->ts_reorder.list);
@@ -959,13 +960,12 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
for (i = 0; i < MAX_SIGNAL; i++) for (i = 0; i < MAX_SIGNAL; i++)
init_completion(&inst->completions[i]); init_completion(&inst->completions[i]);
inst->response_workq = create_singlethread_workqueue("response_workq"); inst->workq = create_singlethread_workqueue("workq");
if (!inst->response_workq) { if (!inst->workq) {
i_vpr_e(inst, "%s: create input_psc_workq failed\n", __func__); i_vpr_e(inst, "%s: create workq failed\n", __func__);
goto error; goto error;
} }
INIT_DELAYED_WORK(&inst->response_work, handle_session_response_work_handler);
INIT_DELAYED_WORK(&inst->stats_work, msm_vidc_stats_handler); INIT_DELAYED_WORK(&inst->stats_work, msm_vidc_stats_handler);
INIT_WORK(&inst->stability_work, msm_vidc_stability_handler); INIT_WORK(&inst->stability_work, msm_vidc_stability_handler);
@@ -1042,7 +1042,6 @@ int msm_vidc_close(void *instance)
msm_vidc_destroy_buffers(inst); msm_vidc_destroy_buffers(inst);
inst_unlock(inst, __func__); inst_unlock(inst, __func__);
client_unlock(inst, __func__); client_unlock(inst, __func__);
cancel_response_work_sync(inst);
cancel_stability_work_sync(inst); cancel_stability_work_sync(inst);
cancel_stats_work_sync(inst); cancel_stats_work_sync(inst);
msm_vidc_show_stats(inst); msm_vidc_show_stats(inst);

File diff suppressed because it is too large Load Diff

View File

@@ -112,7 +112,7 @@ int msm_vidc_queue_setup(struct vb2_queue *q,
return -EINVAL; return -EINVAL;
} }
if (inst->state == MSM_VIDC_START) { if (is_state(inst, MSM_VIDC_STREAMING)) {
i_vpr_e(inst, "%s: invalid state %d\n", __func__, inst->state); i_vpr_e(inst, "%s: invalid state %d\n", __func__, inst->state);
return -EINVAL; return -EINVAL;
} }
@@ -217,10 +217,6 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
goto unlock; goto unlock;
} }
rc = msm_vidc_state_change_streamon(inst, q->type);
if (rc)
goto unlock;
if (q->type == INPUT_META_PLANE && if (q->type == INPUT_META_PLANE &&
inst->capabilities->cap[INPUT_META_VIA_REQUEST].value) { inst->capabilities->cap[INPUT_META_VIA_REQUEST].value) {
i_vpr_e(inst, i_vpr_e(inst,
@@ -335,7 +331,7 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
unlock: unlock:
if (rc) { if (rc) {
i_vpr_e(inst, "Streamon: %s failed\n", v4l2_type_name(q->type)); i_vpr_e(inst, "Streamon: %s failed\n", v4l2_type_name(q->type));
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
} }
inst_unlock(inst, __func__); inst_unlock(inst, __func__);
client_unlock(inst, __func__); client_unlock(inst, __func__);
@@ -381,10 +377,6 @@ void msm_vidc_stop_streaming(struct vb2_queue *q)
goto unlock; goto unlock;
} }
rc = msm_vidc_state_change_streamoff(inst, q->type);
if (rc)
goto unlock;
if (!is_decode_session(inst) && !is_encode_session(inst)) { if (!is_decode_session(inst) && !is_encode_session(inst)) {
i_vpr_e(inst, "%s: invalid session %d\n", i_vpr_e(inst, "%s: invalid session %d\n",
__func__, inst->domain); __func__, inst->domain);
@@ -420,7 +412,7 @@ void msm_vidc_stop_streaming(struct vb2_queue *q)
unlock: unlock:
if (rc) { if (rc) {
i_vpr_e(inst, "Streamoff: %s failed\n", v4l2_type_name(q->type)); i_vpr_e(inst, "Streamoff: %s failed\n", v4l2_type_name(q->type));
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
} }
inst_unlock(inst, __func__); inst_unlock(inst, __func__);
client_unlock(inst, __func__); client_unlock(inst, __func__);
@@ -531,7 +523,7 @@ void msm_vidc_buf_queue(struct vb2_buffer *vb2)
unlock: unlock:
if (rc) { if (rc) {
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
vb2_buffer_done(vb2, VB2_BUF_STATE_ERROR); vb2_buffer_done(vb2, VB2_BUF_STATE_ERROR);
} }
inst_unlock(inst, __func__); inst_unlock(inst, __func__);

View File

@@ -3308,6 +3308,137 @@ unlock:
return rc; return rc;
} }
int venus_hfi_session_pause(struct msm_vidc_inst *inst, enum msm_vidc_port_type port)
{
int rc = 0;
struct msm_vidc_core* core;
if (!inst || !inst->core || !inst->packet) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
core_lock(core, __func__);
if (!__valdiate_session(core, inst, __func__)) {
rc = -EINVAL;
goto unlock;
}
if (port != INPUT_PORT && port != OUTPUT_PORT) {
i_vpr_e(inst, "%s: invalid port %d\n", __func__, port);
goto unlock;
}
rc = hfi_packet_session_command(inst,
HFI_CMD_PAUSE,
(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
HFI_HOST_FLAGS_INTR_REQUIRED),
get_hfi_port(inst, port),
inst->session_id,
HFI_PAYLOAD_NONE,
NULL,
0);
if (rc)
goto unlock;
rc = __iface_cmdq_write(inst->core, inst->packet);
if (rc)
goto unlock;
unlock:
core_unlock(core, __func__);
return rc;
}
int venus_hfi_session_resume(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port, u32 payload)
{
int rc = 0;
struct msm_vidc_core* core;
if (!inst || !inst->core || !inst->packet) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
core_lock(core, __func__);
if (!__valdiate_session(core, inst, __func__)) {
rc = -EINVAL;
goto unlock;
}
if (port != INPUT_PORT && port != OUTPUT_PORT) {
i_vpr_e(inst, "%s: invalid port %d\n", __func__, port);
goto unlock;
}
rc = hfi_packet_session_command(inst,
HFI_CMD_RESUME,
(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
HFI_HOST_FLAGS_INTR_REQUIRED),
get_hfi_port(inst, port),
inst->session_id,
HFI_PAYLOAD_U32,
&payload,
sizeof(u32));
if (rc)
goto unlock;
rc = __iface_cmdq_write(inst->core, inst->packet);
if (rc)
goto unlock;
unlock:
core_unlock(core, __func__);
return rc;
}
int venus_hfi_session_drain(struct msm_vidc_inst *inst, enum msm_vidc_port_type port)
{
int rc = 0;
struct msm_vidc_core* core;
if (!inst || !inst->core || !inst->packet) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
core_lock(core, __func__);
if (!__valdiate_session(core, inst, __func__)) {
rc = -EINVAL;
goto unlock;
}
if (port != INPUT_PORT) {
i_vpr_e(inst, "%s: invalid port %d\n", __func__, port);
goto unlock;
}
rc = hfi_packet_session_command(inst,
HFI_CMD_DRAIN,
(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
HFI_HOST_FLAGS_INTR_REQUIRED |
HFI_HOST_FLAGS_NON_DISCARDABLE),
get_hfi_port(inst, port),
inst->session_id,
HFI_PAYLOAD_NONE,
NULL,
0);
if (rc)
goto unlock;
rc = __iface_cmdq_write(inst->core, inst->packet);
if (rc)
goto unlock;
unlock:
core_unlock(core, __func__);
return rc;
}
int venus_hfi_session_command(struct msm_vidc_inst *inst, int venus_hfi_session_command(struct msm_vidc_inst *inst,
u32 cmd, enum msm_vidc_port_type port, u32 payload_type, u32 cmd, enum msm_vidc_port_type port, u32 payload_type,
void *payload, u32 payload_size) void *payload, u32 payload_size)

View File

@@ -178,14 +178,6 @@ bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst,
return true; return true;
} }
static int signal_session_msg_receipt(struct msm_vidc_inst *inst,
enum signal_session_response cmd)
{
if (cmd < MAX_SIGNAL)
complete(&inst->completions[cmd]);
return 0;
}
int validate_packet(u8 *response_pkt, u8 *core_resp_pkt, int validate_packet(u8 *response_pkt, u8 *core_resp_pkt,
u32 core_resp_pkt_size, const char *func) u32 core_resp_pkt_size, const char *func)
{ {
@@ -304,29 +296,35 @@ static bool check_for_packet_payload(struct msm_vidc_inst *inst,
return true; return true;
} }
static bool check_last_flag(struct msm_vidc_inst *inst, static int handle_session_last_flag_info(struct msm_vidc_inst *inst,
struct hfi_packet *pkt) struct hfi_packet *pkt)
{ {
struct hfi_buffer *buffer; int rc = 0;
if (!inst || !pkt) { if (pkt->type == HFI_INFO_HFI_FLAG_PSC_LAST) {
d_vpr_e("%s: invalid params\n", __func__); if (msm_vidc_allow_psc_last_flag(inst))
return false; rc = msm_vidc_process_psc_last_flag(inst);
else
rc = -EINVAL;
} else if (pkt->type == HFI_INFO_HFI_FLAG_DRAIN_LAST) {
if (msm_vidc_allow_drain_last_flag(inst))
rc = msm_vidc_process_drain_last_flag(inst);
else
rc = -EINVAL;
} else {
i_vpr_e(inst, "%s: invalid packet type %#x\n", __func__,
pkt->type);
} }
buffer = (struct hfi_buffer *)((u8 *)pkt + sizeof(struct hfi_packet)); if (rc)
if (buffer->flags & HFI_BUF_FW_FLAG_LAST) { msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
i_vpr_h(inst, "%s: received last flag on FBD, index: %d\n",
__func__, buffer->index); return rc;
return true;
}
return false;
} }
static int handle_session_info(struct msm_vidc_inst *inst, static int handle_session_info(struct msm_vidc_inst *inst,
struct hfi_packet *pkt) struct hfi_packet *pkt)
{ {
int rc = 0; int rc = 0;
char *info; char *info;
@@ -342,12 +340,20 @@ static int handle_session_info(struct msm_vidc_inst *inst,
info = "buffer overflow"; info = "buffer overflow";
inst->hfi_frame_info.overflow = 1; inst->hfi_frame_info.overflow = 1;
break; break;
case HFI_INFO_HFI_FLAG_DRAIN_LAST:
info = "drain last flag";
rc = handle_session_last_flag_info(inst, pkt);
break;
case HFI_INFO_HFI_FLAG_PSC_LAST:
info = "drc last flag";
rc = handle_session_last_flag_info(inst, pkt);
break;
default: default:
info = "unknown"; info = "unknown";
break; break;
} }
i_vpr_e(inst, "session info (%#x): %s\n", pkt->type, info); i_vpr_h(inst, "session info (%#x): %s\n", pkt->type, info);
return rc; return rc;
} }
@@ -385,7 +391,7 @@ static int handle_session_error(struct msm_vidc_inst *inst,
i_vpr_e(inst, "%s: session error received %#x: %s\n", i_vpr_e(inst, "%s: session error received %#x: %s\n",
__func__, pkt->type, error); __func__, pkt->type, error);
rc = msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); rc = msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
return rc; return rc;
} }
@@ -537,7 +543,8 @@ static int handle_session_start(struct msm_vidc_inst *inst,
static int handle_session_stop(struct msm_vidc_inst *inst, static int handle_session_stop(struct msm_vidc_inst *inst,
struct hfi_packet *pkt) struct hfi_packet *pkt)
{ {
int signal_type = -1; int rc = 0;
enum signal_session_response signal_type = -1;
if (pkt->flags & HFI_FW_FLAGS_SUCCESS) if (pkt->flags & HFI_FW_FLAGS_SUCCESS)
i_vpr_h(inst, "%s: successful for port %d\n", i_vpr_h(inst, "%s: successful for port %d\n",
@@ -568,17 +575,28 @@ static int handle_session_stop(struct msm_vidc_inst *inst,
return -EINVAL; return -EINVAL;
} }
if (signal_type != -1) if (signal_type != -1) {
signal_session_msg_receipt(inst, signal_type); rc = msm_vidc_process_stop_done(inst, signal_type);
if (rc)
return rc;
}
return 0; return 0;
} }
static int handle_session_drain(struct msm_vidc_inst *inst, static int handle_session_drain(struct msm_vidc_inst *inst,
struct hfi_packet *pkt) struct hfi_packet *pkt)
{ {
int rc = 0;
if (pkt->flags & HFI_FW_FLAGS_SUCCESS) if (pkt->flags & HFI_FW_FLAGS_SUCCESS)
i_vpr_h(inst, "%s: successful\n", __func__); i_vpr_h(inst, "%s: successful\n", __func__);
return 0;
rc = msm_vidc_process_drain_done(inst);
if (rc)
return rc;
return rc;
} }
static int get_driver_buffer_flags(struct msm_vidc_inst *inst, u32 hfi_flags) static int get_driver_buffer_flags(struct msm_vidc_inst *inst, u32 hfi_flags)
@@ -618,7 +636,18 @@ static int get_driver_buffer_flags(struct msm_vidc_inst *inst, u32 hfi_flags)
if (hfi_flags & HFI_BUF_FW_FLAG_CODEC_CONFIG) if (hfi_flags & HFI_BUF_FW_FLAG_CODEC_CONFIG)
driver_flags |= MSM_VIDC_BUF_FLAG_CODECCONFIG; driver_flags |= MSM_VIDC_BUF_FLAG_CODECCONFIG;
if (hfi_flags & HFI_BUF_FW_FLAG_LAST) /*
* attach last flag to the buffer for encode session.
* For decode session attach only if control(LAST_FLAG_EVENT_ENABLE)
* is not set by client. If this control is enabled, last flag
* info will be sent via event(V4L2_EVENT_VIDC_LAST_FLAG) to client.
*/
if ((is_encode_session(inst) &&
(hfi_flags & HFI_BUF_FW_FLAG_LAST)) ||
(is_decode_session(inst) &&
!inst->capabilities->cap[LAST_FLAG_EVENT_ENABLE].value &&
((hfi_flags & HFI_BUF_FW_FLAG_LAST) ||
(hfi_flags & HFI_BUF_FW_FLAG_PSC_LAST))))
driver_flags |= MSM_VIDC_BUF_FLAG_LAST; driver_flags |= MSM_VIDC_BUF_FLAG_LAST;
return driver_flags; return driver_flags;
@@ -714,6 +743,48 @@ static int handle_non_read_only_buffer(struct msm_vidc_inst *inst,
return 0; return 0;
} }
static int handle_psc_last_flag_buffer(struct msm_vidc_inst *inst,
struct hfi_buffer *buffer)
{
int rc = 0;
if (!(buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST))
return 0;
if (!msm_vidc_allow_psc_last_flag(inst))
return -EINVAL;
rc = msm_vidc_process_psc_last_flag(inst);
if (rc)
return rc;
return rc;
}
static int handle_drain_last_flag_buffer(struct msm_vidc_inst *inst,
struct hfi_buffer *buffer)
{
int rc = 0;
if (!(buffer->flags & HFI_BUF_FW_FLAG_LAST))
return 0;
if (!msm_vidc_allow_drain_last_flag(inst))
return -EINVAL;
if (is_decode_session(inst)) {
rc = msm_vidc_process_drain_last_flag(inst);
if (rc)
return rc;
} else if (is_encode_session(inst)) {
rc = msm_vidc_state_change_drain_last_flag(inst);
if (rc)
return rc;
}
return rc;
}
static int handle_input_buffer(struct msm_vidc_inst *inst, static int handle_input_buffer(struct msm_vidc_inst *inst,
struct hfi_buffer *buffer) struct hfi_buffer *buffer)
{ {
@@ -801,11 +872,25 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
return -EINVAL; return -EINVAL;
} }
/* handle drain last flag buffer */
if (buffer->flags & HFI_BUF_FW_FLAG_LAST) {
rc = handle_drain_last_flag_buffer(inst, buffer);
if (rc)
msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
}
if (is_decode_session(inst)) { if (is_decode_session(inst)) {
/* handle psc last flag buffer */
if (buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) {
rc = handle_psc_last_flag_buffer(inst, buffer);
if (rc)
msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
}
/* handle non-read only buffer */
if (!(buffer->flags & HFI_BUF_FW_FLAG_READONLY)) { if (!(buffer->flags & HFI_BUF_FW_FLAG_READONLY)) {
rc = handle_non_read_only_buffer(inst, buffer); rc = handle_non_read_only_buffer(inst, buffer);
if (rc) if (rc)
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
} }
} }
@@ -861,14 +946,15 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
} }
} }
if (fatal) if (fatal)
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
} }
/* /*
* reset data size to zero for last flag buffer. * reset data size to zero for last flag buffer.
* reset RO flag for last flag buffer. * reset RO flag for last flag buffer.
*/ */
if (buffer->flags & HFI_BUF_FW_FLAG_LAST) { if ((buffer->flags & HFI_BUF_FW_FLAG_LAST) ||
(buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST)) {
if (buffer->data_size) { if (buffer->data_size) {
i_vpr_e(inst, "%s: reset data size to zero for last flag buffer\n", i_vpr_e(inst, "%s: reset data size to zero for last flag buffer\n",
__func__); __func__);
@@ -894,7 +980,7 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
buf->attr |= MSM_VIDC_ATTR_READ_ONLY; buf->attr |= MSM_VIDC_ATTR_READ_ONLY;
rc = handle_read_only_buffer(inst, buf); rc = handle_read_only_buffer(inst, buf);
if (rc) if (rc)
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
} else { } else {
buf->attr &= ~MSM_VIDC_ATTR_READ_ONLY; buf->attr &= ~MSM_VIDC_ATTR_READ_ONLY;
} }
@@ -993,7 +1079,12 @@ static int handle_input_metadata_buffer(struct msm_vidc_inst *inst,
buf->attr &= ~MSM_VIDC_ATTR_QUEUED; buf->attr &= ~MSM_VIDC_ATTR_QUEUED;
buf->attr |= MSM_VIDC_ATTR_DEQUEUED; buf->attr |= MSM_VIDC_ATTR_DEQUEUED;
buf->flags = 0; buf->flags = 0;
if (buffer->flags & HFI_BUF_FW_FLAG_LAST) if ((is_encode_session(inst) &&
(buffer->flags & HFI_BUF_FW_FLAG_LAST)) ||
(is_decode_session(inst) &&
!inst->capabilities->cap[LAST_FLAG_EVENT_ENABLE].value &&
((buffer->flags & HFI_BUF_FW_FLAG_LAST) ||
(buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST))))
buf->flags |= MSM_VIDC_BUF_FLAG_LAST; buf->flags |= MSM_VIDC_BUF_FLAG_LAST;
print_vidc_buffer(VIDC_LOW, "low ", "dqbuf", inst, buf); print_vidc_buffer(VIDC_LOW, "low ", "dqbuf", inst, buf);
@@ -1008,6 +1099,11 @@ static int handle_output_metadata_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buf; struct msm_vidc_buffer *buf;
bool found; bool found;
if (!inst || !inst->capabilities) {
d_vpr_e("%s: Invalid params\n", __func__);
return -EINVAL;
}
buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_OUTPUT_META, __func__); buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_OUTPUT_META, __func__);
if (!buffers) if (!buffers)
return -EINVAL; return -EINVAL;
@@ -1035,7 +1131,12 @@ static int handle_output_metadata_buffer(struct msm_vidc_inst *inst,
buf->attr &= ~MSM_VIDC_ATTR_QUEUED; buf->attr &= ~MSM_VIDC_ATTR_QUEUED;
buf->attr |= MSM_VIDC_ATTR_DEQUEUED; buf->attr |= MSM_VIDC_ATTR_DEQUEUED;
buf->flags = 0; buf->flags = 0;
if (buffer->flags & HFI_BUF_FW_FLAG_LAST) if ((is_encode_session(inst) &&
(buffer->flags & HFI_BUF_FW_FLAG_LAST)) ||
(is_decode_session(inst) &&
!inst->capabilities->cap[LAST_FLAG_EVENT_ENABLE].value &&
((buffer->flags & HFI_BUF_FW_FLAG_LAST) ||
(buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST))))
buf->flags |= MSM_VIDC_BUF_FLAG_LAST; buf->flags |= MSM_VIDC_BUF_FLAG_LAST;
print_vidc_buffer(VIDC_LOW, "low ", "dqbuf", inst, buf); print_vidc_buffer(VIDC_LOW, "low ", "dqbuf", inst, buf);
@@ -1267,18 +1368,18 @@ static int handle_session_buffer(struct msm_vidc_inst *inst,
} }
if (!check_for_packet_payload(inst, pkt, __func__)) { if (!check_for_packet_payload(inst, pkt, __func__)) {
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
return 0; return 0;
} }
buffer = (struct hfi_buffer *)((u8 *)pkt + sizeof(struct hfi_packet)); buffer = (struct hfi_buffer *)((u8 *)pkt + sizeof(struct hfi_packet));
if (!is_valid_hfi_buffer_type(inst, buffer->type, __func__)) { if (!is_valid_hfi_buffer_type(inst, buffer->type, __func__)) {
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
return 0; return 0;
} }
if (!is_valid_hfi_port(inst, pkt->port, buffer->type, __func__)) { if (!is_valid_hfi_port(inst, pkt->port, buffer->type, __func__)) {
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
return 0; return 0;
} }
if (is_decode_session(inst) && buffer->type == HFI_BUFFER_RAW && if (is_decode_session(inst) && buffer->type == HFI_BUFFER_RAW &&
@@ -1329,6 +1430,39 @@ static int handle_session_buffer(struct msm_vidc_inst *inst,
return rc; return rc;
} }
static int handle_input_port_settings_change(struct msm_vidc_inst *inst)
{
int rc = 0;
enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
allow = msm_vidc_allow_input_psc(inst);
if (allow == MSM_VIDC_DISALLOW) {
return -EINVAL;
} else if (allow == MSM_VIDC_ALLOW) {
rc = msm_vidc_state_change_input_psc(inst);
if (rc)
return rc;
print_psc_properties("INPUT_PSC", inst, inst->subcr_params[INPUT_PORT]);
rc = msm_vdec_input_port_settings_change(inst);
if (rc)
return rc;
}
return rc;
}
static int handle_output_port_settings_change(struct msm_vidc_inst *inst)
{
int rc = 0;
print_psc_properties("OUTPUT_PSC", inst, inst->subcr_params[OUTPUT_PORT]);
rc = msm_vdec_output_port_settings_change(inst);
if (rc)
return rc;
return rc;
}
static int handle_port_settings_change(struct msm_vidc_inst *inst, static int handle_port_settings_change(struct msm_vidc_inst *inst,
struct hfi_packet *pkt) struct hfi_packet *pkt)
{ {
@@ -1338,17 +1472,23 @@ static int handle_port_settings_change(struct msm_vidc_inst *inst,
__func__, pkt->port); __func__, pkt->port);
if (pkt->port == HFI_PORT_RAW) { if (pkt->port == HFI_PORT_RAW) {
print_psc_properties("OUTPUT_PSC", inst, inst->subcr_params[OUTPUT_PORT]); rc = handle_output_port_settings_change(inst);
rc = msm_vdec_output_port_settings_change(inst); if (rc)
goto exit;
} else if (pkt->port == HFI_PORT_BITSTREAM) { } else if (pkt->port == HFI_PORT_BITSTREAM) {
print_psc_properties("INPUT_PSC", inst, inst->subcr_params[INPUT_PORT]); rc = handle_input_port_settings_change(inst);
rc = msm_vdec_input_port_settings_change(inst); if (rc)
goto exit;
} else { } else {
i_vpr_e(inst, "%s: invalid port type: %#x\n", i_vpr_e(inst, "%s: invalid port type: %#x\n",
__func__, pkt->port); __func__, pkt->port);
rc = -EINVAL; rc = -EINVAL;
goto exit;
} }
exit:
if (rc)
msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
return rc; return rc;
} }
@@ -1368,6 +1508,14 @@ static int handle_session_delivery_mode(struct msm_vidc_inst *inst,
return 0; return 0;
} }
static int handle_session_pause(struct msm_vidc_inst *inst,
struct hfi_packet *pkt)
{
if (pkt->flags & HFI_FW_FLAGS_SUCCESS)
i_vpr_h(inst, "%s: successful\n", __func__);
return 0;
}
static int handle_session_resume(struct msm_vidc_inst *inst, static int handle_session_resume(struct msm_vidc_inst *inst,
struct hfi_packet *pkt) struct hfi_packet *pkt)
{ {
@@ -1398,6 +1546,7 @@ static int handle_session_command(struct msm_vidc_inst *inst,
{HFI_CMD_SETTINGS_CHANGE, handle_port_settings_change }, {HFI_CMD_SETTINGS_CHANGE, handle_port_settings_change },
{HFI_CMD_SUBSCRIBE_MODE, handle_session_subscribe_mode }, {HFI_CMD_SUBSCRIBE_MODE, handle_session_subscribe_mode },
{HFI_CMD_DELIVERY_MODE, handle_session_delivery_mode }, {HFI_CMD_DELIVERY_MODE, handle_session_delivery_mode },
{HFI_CMD_PAUSE, handle_session_pause },
{HFI_CMD_RESUME, handle_session_resume }, {HFI_CMD_RESUME, handle_session_resume },
{HFI_CMD_STABILITY, handle_session_stability }, {HFI_CMD_STABILITY, handle_session_stability },
}; };
@@ -1437,7 +1586,7 @@ static int handle_dpb_list_property(struct msm_vidc_inst *inst,
i_vpr_e(inst, i_vpr_e(inst,
"%s: dpb list payload size %d exceeds expected max size %d\n", "%s: dpb list payload size %d exceeds expected max size %d\n",
__func__, payload_size, MAX_DPB_LIST_PAYLOAD_SIZE); __func__, payload_size, MAX_DPB_LIST_PAYLOAD_SIZE);
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
} }
memcpy(inst->dpb_list_payload, payload_start, payload_size); memcpy(inst->dpb_list_payload, payload_start, payload_size);
@@ -1764,7 +1913,7 @@ static int __handle_session_response(struct msm_vidc_inst *inst,
dequeue |= (packet->type == HFI_CMD_BUFFER); dequeue |= (packet->type == HFI_CMD_BUFFER);
rc = be[i].handle(inst, packet); rc = be[i].handle(inst, packet);
if (rc) if (rc)
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
} }
pkt += packet->size; pkt += packet->size;
} }
@@ -1780,163 +1929,14 @@ static int __handle_session_response(struct msm_vidc_inst *inst,
return rc; return rc;
} }
int handle_session_response_work(struct msm_vidc_inst *inst,
struct response_work *resp_work)
{
int rc = 0;
struct hfi_header *hdr = NULL;
if (!inst || !inst->core || !resp_work) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
hdr = (struct hfi_header *)resp_work->data;
if (!hdr) {
i_vpr_e(inst, "%s: invalid params\n", __func__);
return -EINVAL;
}
if (resp_work->type == RESP_WORK_INPUT_PSC)
msm_vdec_init_input_subcr_params(inst);
rc = __handle_session_response(inst, hdr);
if (rc)
return rc;
return 0;
}
void handle_session_response_work_handler(struct work_struct *work)
{
int rc = 0;
struct msm_vidc_inst *inst;
struct response_work *resp_work, *dummy = NULL;
inst = container_of(work, struct msm_vidc_inst, response_work.work);
inst = get_inst_ref(g_core, inst);
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return;
}
inst_lock(inst, __func__);
list_for_each_entry_safe(resp_work, dummy, &inst->response_works, list) {
switch (resp_work->type) {
case RESP_WORK_INPUT_PSC:
{
enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
allow = msm_vidc_allow_input_psc(inst);
if (allow == MSM_VIDC_DISALLOW) {
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
break;
} else if (allow == MSM_VIDC_DEFER) {
/* continue to next entry processing */
continue;
} else if (allow == MSM_VIDC_DISCARD) {
/* if ipsc is discarded then override the psc properties again */
inst->ipsc_properties_set = false;
/* discard current entry processing */
break;
} else if (allow == MSM_VIDC_ALLOW) {
rc = handle_session_response_work(inst, resp_work);
if (!rc)
rc = msm_vidc_state_change_input_psc(inst);
/* either handle input psc or state change failed */
if (rc)
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
}
break;
}
case RESP_WORK_OUTPUT_PSC:
rc = handle_session_response_work(inst, resp_work);
if (rc)
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
break;
case RESP_WORK_LAST_FLAG:
rc = handle_session_response_work(inst, resp_work);
if (rc) {
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
break;
}
if (msm_vidc_allow_last_flag(inst)) {
rc = msm_vidc_state_change_last_flag(inst);
if (rc)
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
}
break;
default:
i_vpr_e(inst, "%s: invalid response work type %d\n", __func__,
resp_work->type);
break;
}
list_del(&resp_work->list);
msm_vidc_vmem_free((void **)&resp_work->data);
msm_vidc_vmem_free((void **)&resp_work);
}
inst_unlock(inst, __func__);
put_inst(inst);
}
static int queue_response_work(struct msm_vidc_inst *inst,
enum response_work_type type, void *hdr, u32 hdr_size)
{
struct response_work *work = NULL;
if (msm_vidc_vmem_alloc(sizeof(struct response_work), (void **)&work, __func__))
return -ENOMEM;
INIT_LIST_HEAD(&work->list);
work->type = type;
work->data_size = hdr_size;
if (msm_vidc_vmem_alloc(hdr_size, (void **)&work->data, "Work data"))
return -ENOMEM;
memcpy(work->data, hdr, hdr_size);
list_add_tail(&work->list, &inst->response_works);
queue_delayed_work(inst->response_workq,
&inst->response_work, msecs_to_jiffies(0));
return 0;
}
int cancel_response_work(struct msm_vidc_inst *inst)
{
struct response_work *work, *dummy_work = NULL;
if (!inst) {
d_vpr_e("%s: Invalid arguments\n", __func__);
return -EINVAL;
}
cancel_delayed_work(&inst->response_work);
list_for_each_entry_safe(work, dummy_work, &inst->response_works, list) {
list_del(&work->list);
msm_vidc_vmem_free((void **)&work->data);
msm_vidc_vmem_free((void **)&work);
}
return 0;
}
int cancel_response_work_sync(struct msm_vidc_inst *inst)
{
if (!inst || !inst->response_workq) {
d_vpr_e("%s: Invalid arguments\n", __func__);
return -EINVAL;
}
cancel_delayed_work_sync(&inst->response_work);
return 0;
}
static int handle_session_response(struct msm_vidc_core *core, static int handle_session_response(struct msm_vidc_core *core,
struct hfi_header *hdr) struct hfi_header *hdr)
{ {
struct msm_vidc_inst *inst; struct msm_vidc_inst *inst;
struct hfi_packet *packet; struct hfi_packet *packet;
u8 *pkt; u8 *pkt;
enum response_work_type type;
int i, rc = 0; int i, rc = 0;
bool offload = false; bool found_ipsc = false;
if (!core || !hdr) { if (!core || !hdr) {
d_vpr_e("%s: Invalid params\n", __func__); d_vpr_e("%s: Invalid params\n", __func__);
@@ -1950,42 +1950,22 @@ static int handle_session_response(struct msm_vidc_core *core,
} }
inst_lock(inst, __func__); inst_lock(inst, __func__);
/* search for special pkt */ /* search for cmd settings change pkt */
pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header)); pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header));
for (i = 0; i < hdr->num_packets; i++) { for (i = 0; i < hdr->num_packets; i++) {
packet = (struct hfi_packet *)pkt; packet = (struct hfi_packet *)pkt;
if (packet->type == HFI_CMD_SETTINGS_CHANGE) { if (packet->type == HFI_CMD_SETTINGS_CHANGE) {
if (packet->port == HFI_PORT_BITSTREAM) { if (packet->port == HFI_PORT_BITSTREAM) {
offload = true; found_ipsc = true;
type = RESP_WORK_INPUT_PSC; break;
} else if (packet->port == HFI_PORT_RAW) {
offload = true;
type = RESP_WORK_OUTPUT_PSC;
}
} else if (packet->type == HFI_CMD_BUFFER &&
vidc_port_from_hfi(inst, packet->port) ==
OUTPUT_PORT) {
if (check_last_flag(inst, packet)) {
offload = true;
type = RESP_WORK_LAST_FLAG;
} }
} }
if (offload)
break;
pkt += packet->size; pkt += packet->size;
} }
if (offload) { /* if ipsc packet is found, initialise subsc_params */
i_vpr_h(inst, "%s: queue response work %#x\n", __func__, type); if (found_ipsc)
rc = queue_response_work(inst, type, (void *)hdr, hdr->size); msm_vdec_init_input_subcr_params(inst);
if (rc)
i_vpr_e(inst, "%s: Offload response work failed\n", __func__);
goto exit;
}
rc = __handle_session_response(inst, hdr); rc = __handle_session_response(inst, hdr);
if (rc) if (rc)

View File

@@ -268,6 +268,9 @@ enum v4l2_h264_encode_delivery_mode {
#define V4L2_CID_MPEG_VIDC_CLIENT_ID \ #define V4L2_CID_MPEG_VIDC_CLIENT_ID \
(V4L2_CID_MPEG_VIDC_BASE + 0x41) (V4L2_CID_MPEG_VIDC_BASE + 0x41)
#define V4L2_CID_MPEG_VIDC_LAST_FLAG_EVENT_ENABLE \
(V4L2_CID_MPEG_VIDC_BASE + 0x42)
/* add new controls above this line */ /* add new controls above this line */
/* Deprecate below controls once availble in gki and gsi bionic header */ /* Deprecate below controls once availble in gki and gsi bionic header */
#ifndef V4L2_CID_MPEG_VIDEO_BASELAYER_PRIORITY_ID #ifndef V4L2_CID_MPEG_VIDEO_BASELAYER_PRIORITY_ID
@@ -461,6 +464,19 @@ struct v4l2_event_vidc_metadata {
__u32 offset; __u32 offset;
__u8 reserved[44]; __u8 reserved[44];
}; };
#define V4L2_EVENT_VIDC_LAST_FLAG \
(V4L2_EVENT_PRIVATE_START + 0x2)
enum v4l2_event_last_flag {
LAST_FLAG_DRC = (1 << 0),
LAST_FLAG_DRAIN = (1 << 1),
};
struct v4l2_event_vidc_last_flag {
enum v4l2_event_last_flag flag_type;
};
/* vendor events end */ /* vendor events end */
/* Default metadata size (align to 4KB) */ /* Default metadata size (align to 4KB) */