video: driver: restructure video state machine

Re-structure video driver statemachine to use
event handler. Added event handler support for
event states.

Added change to handle event depending on the
underlying state implementation.

Change-Id: Ib55c12c6cadc4d780797a5aee75d5ea61e95c94f
Signed-off-by: Govindaraj Rajagopal <quic_grajagop@quicinc.com>
Tento commit je obsažen v:
Govindaraj Rajagopal
2022-11-25 21:28:41 +05:30
rodič 68df0645ec
revize 7c365bdb94
19 změnil soubory, kde provedl 1174 přidání a 458 odebrání

Zobrazit soubor

@@ -168,13 +168,13 @@ static struct v4l2_ctrl_ops msm_v4l2_ctrl_ops = {
};
static struct vb2_ops msm_vb2_ops = {
.queue_setup = msm_vidc_queue_setup,
.start_streaming = msm_vidc_start_streaming,
.buf_queue = msm_vidc_buf_queue,
.buf_cleanup = msm_vidc_buf_cleanup,
.stop_streaming = msm_vidc_stop_streaming,
.buf_out_validate = msm_vidc_buf_out_validate,
.buf_request_complete = msm_vidc_buf_request_complete,
.queue_setup = msm_vb2_queue_setup,
.start_streaming = msm_vb2_start_streaming,
.buf_queue = msm_vb2_buf_queue,
.buf_cleanup = msm_vb2_buf_cleanup,
.stop_streaming = msm_vb2_stop_streaming,
.buf_out_validate = msm_vb2_buf_out_validate,
.buf_request_complete = msm_vb2_request_complete,
};
static struct vb2_mem_ops msm_vb2_mem_ops = {

Zobrazit soubor

@@ -28,7 +28,8 @@ int msm_vdec_inst_deinit(struct msm_vidc_inst *inst);
int msm_vdec_init_input_subcr_params(struct msm_vidc_inst *inst);
int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst);
int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst);
int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd);
int msm_vdec_stop_cmd(struct msm_vidc_inst *inst);
int msm_vdec_start_cmd(struct msm_vidc_inst *inst);
int msm_vdec_handle_release_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buf);
int msm_vdec_set_num_comv(struct msm_vidc_inst *inst);

Zobrazit soubor

@@ -15,7 +15,8 @@ int msm_venc_streamon_input(struct msm_vidc_inst *inst);
int msm_venc_streamoff_output(struct msm_vidc_inst *inst);
int msm_venc_streamon_output(struct msm_vidc_inst *inst);
int msm_venc_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd);
int msm_venc_stop_cmd(struct msm_vidc_inst *inst);
int msm_venc_start_cmd(struct msm_vidc_inst *inst);
int msm_venc_try_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
int msm_venc_s_fmt_output(struct msm_vidc_inst *inst, struct v4l2_format *f);

Zobrazit soubor

@@ -41,7 +41,8 @@ int msm_vidc_query_ctrl(void *instance, struct v4l2_queryctrl *ctrl);
int msm_vidc_query_menu(void *instance, struct v4l2_querymenu *qmenu);
int msm_vidc_streamoff(void *instance, enum v4l2_buf_type i);
int msm_vidc_try_cmd(void *instance, union msm_v4l2_cmd *cmd);
int msm_vidc_cmd(void *instance, union msm_v4l2_cmd *cmd);
int msm_vidc_start_cmd(void *instance);
int msm_vidc_stop_cmd(void *instance);
int msm_vidc_poll(void *instance, struct file *filp,
struct poll_table_struct *pt);
int msm_vidc_subscribe_event(void *instance,

Zobrazit soubor

@@ -14,6 +14,7 @@ int msm_vidc_ctrl_init(struct msm_vidc_inst *inst);
int msm_vidc_ctrl_deinit(struct msm_vidc_inst *inst);
int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl);
int msm_v4l2_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl);
int msm_vidc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl);
int msm_vidc_prepare_dependency_list(struct msm_vidc_inst *inst);
int msm_vidc_adjust_set_v4l2_properties(struct msm_vidc_inst *inst);
bool is_valid_cap_id(enum msm_vidc_inst_capability_type cap_id);

Zobrazit soubor

@@ -404,8 +404,8 @@ const char *state_name(enum msm_vidc_state state);
int msm_vidc_change_state(struct msm_vidc_inst *inst,
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);
enum msm_vidc_sub_state clear_sub_state,
enum msm_vidc_sub_state set_sub_state, const char *func);
int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst,
enum msm_vidc_buffer_type buffer_type, u32 index);
int msm_vidc_get_internal_buffers(struct msm_vidc_inst *inst,
@@ -436,6 +436,8 @@ int msm_vidc_change_core_state(struct msm_vidc_core *core,
int msm_vidc_change_core_sub_state(struct msm_vidc_core *core,
enum msm_vidc_core_sub_state clear_sub_states,
enum msm_vidc_core_sub_state set_sub_states, const char *func);
int prepare_sub_state_name(enum msm_vidc_sub_state sub_state,
char *buf, u32 size);
int msm_vidc_core_init(struct msm_vidc_core *core);
int msm_vidc_core_init_wait(struct msm_vidc_core *core);
int msm_vidc_core_deinit(struct msm_vidc_core *core, bool force);
@@ -482,6 +484,7 @@ int cancel_stats_work_sync(struct msm_vidc_inst *inst);
void msm_vidc_print_stats(struct msm_vidc_inst *inst);
enum msm_vidc_buffer_type v4l2_type_to_driver(u32 type,
const char *func);
int msm_vidc_buf_queue(struct msm_vidc_inst *inst, struct msm_vidc_buffer *buf);
int msm_vidc_queue_buffer_single(struct msm_vidc_inst *inst,
struct vb2_buffer *vb2);
int msm_vidc_queue_deferred_buffers(struct msm_vidc_inst *inst,
@@ -501,8 +504,6 @@ struct msm_vidc_inst *get_inst(struct msm_vidc_core *core,
u32 session_id);
void put_inst(struct msm_vidc_inst *inst);
bool msm_vidc_allow_s_fmt(struct msm_vidc_inst *inst, u32 type);
bool msm_vidc_allow_s_ctrl(struct msm_vidc_inst *inst,
enum msm_vidc_inst_capability_type cap_id);
bool msm_vidc_allow_metadata_delivery(struct msm_vidc_inst *inst,
u32 cap_id, u32 port);
bool msm_vidc_allow_metadata_subscription(struct msm_vidc_inst *inst,
@@ -514,8 +515,6 @@ bool msm_vidc_allow_reqbufs(struct msm_vidc_inst *inst, u32 type);
enum msm_vidc_allow msm_vidc_allow_stop(struct msm_vidc_inst *inst);
bool msm_vidc_allow_start(struct msm_vidc_inst *inst);
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_qbuf(struct msm_vidc_inst *inst, u32 type);
enum msm_vidc_allow msm_vidc_allow_input_psc(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);

Zobrazit soubor

@@ -9,12 +9,12 @@
#include "msm_vidc_internal.h"
#include "msm_vidc_memory.h"
#include "msm_vidc_state.h"
#include "hfi_property.h"
struct msm_vidc_inst;
#define FOREACH_STATE(STATE) { \
STATE(NONE) \
STATE(OPEN) \
STATE(INPUT_STREAMING) \
STATE(OUTPUT_STREAMING) \
@@ -97,6 +97,8 @@ struct msm_vidc_inst {
struct mutex request_lock;
struct mutex client_lock;
enum msm_vidc_state state;
int (*event_handle)(struct msm_vidc_inst *inst,
enum msm_vidc_event event, void *data);
enum msm_vidc_sub_state sub_state;
char sub_state_name[MAX_NAME_LENGTH];
enum msm_vidc_domain_type domain;

Zobrazit soubor

@@ -377,7 +377,7 @@ enum msm_vidc_metadata_bits {
BUF_TYPE(INPUT_META) \
BUF_TYPE(OUTPUT_META) \
BUF_TYPE(READ_ONLY) \
BUF_TYPE(QUEUE) \
BUF_TYPE(INTERFACE_QUEUE) \
BUF_TYPE(BIN) \
BUF_TYPE(ARP) \
BUF_TYPE(COMV) \

Zobrazit soubor

@@ -10,6 +10,8 @@
#include "msm_vidc_internal.h"
struct msm_vidc_core;
enum msm_vidc_state;
enum msm_vidc_sub_state;
#define FOREACH_CORE_STATE(CORE_STATE) { \
CORE_STATE(CORE_DEINIT) \
@@ -18,6 +20,17 @@ struct msm_vidc_core;
CORE_STATE(CORE_ERROR) \
}
#define FOREACH_EVENT(EVENT) { \
EVENT(S_FMT) \
EVENT(REQBUFS) \
EVENT(S_CTRL) \
EVENT(STREAMON) \
EVENT(STREAMOFF) \
EVENT(CMD_START) \
EVENT(CMD_STOP) \
EVENT(BUF_QUEUE) \
}
enum msm_vidc_core_state FOREACH_CORE_STATE(GENERATE_MSM_VIDC_ENUM);
enum msm_vidc_core_sub_state {
@@ -37,13 +50,9 @@ enum msm_vidc_core_event_type {
CORE_EVENT_UPDATE_SUB_STATE = BIT(1),
};
struct msm_vidc_core_state_handle {
enum msm_vidc_core_state state;
int (*handle)(struct msm_vidc_core *core,
enum msm_vidc_core_event_type type,
struct msm_vidc_event_data *data);
};
enum msm_vidc_event FOREACH_EVENT(GENERATE_MSM_VIDC_ENUM);
/* core statemachine functions */
enum msm_vidc_allow msm_vidc_allow_core_state_change(
struct msm_vidc_core *core, enum msm_vidc_core_state req_state);
int msm_vidc_update_core_state(struct msm_vidc_core *core,
@@ -55,4 +64,11 @@ bool is_core_sub_state(struct msm_vidc_core *core,
const char *core_state_name(enum msm_vidc_core_state state);
const char *core_sub_state_name(enum msm_vidc_core_sub_state sub_state);
/* inst statemachine functions */
int msm_vidc_update_state(struct msm_vidc_inst *inst,
enum msm_vidc_state request_state, const char *func);
enum msm_vidc_allow msm_vidc_allow_state_change(
struct msm_vidc_inst *inst,
enum msm_vidc_state req_state);
#endif // _MSM_VIDC_STATE_H_

Zobrazit soubor

@@ -35,14 +35,15 @@ int msm_vb2_map_dmabuf(void *buf_priv);
void msm_vb2_unmap_dmabuf(void *buf_priv);
/* vb2_ops */
int msm_vidc_queue_setup(struct vb2_queue *q,
int msm_vb2_queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], struct device *alloc_devs[]);
int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count);
void msm_vidc_stop_streaming(struct vb2_queue *q);
void msm_vidc_buf_queue(struct vb2_buffer *vb2);
void msm_vidc_buf_cleanup(struct vb2_buffer *vb);
int msm_vidc_buf_out_validate(struct vb2_buffer *vb);
void msm_vidc_buf_request_complete(struct vb2_buffer *vb);
int msm_vidc_start_streaming(struct msm_vidc_inst *inst, struct vb2_queue *q);
int msm_vidc_stop_streaming(struct msm_vidc_inst *inst, struct vb2_queue *q);
int msm_vb2_start_streaming(struct vb2_queue *q, unsigned int count);
void msm_vb2_stop_streaming(struct vb2_queue *q);
void msm_vb2_buf_queue(struct vb2_buffer *vb2);
void msm_vb2_buf_cleanup(struct vb2_buffer *vb);
int msm_vb2_buf_out_validate(struct vb2_buffer *vb);
void msm_vb2_request_complete(struct vb2_buffer *vb);
#endif // _MSM_VIDC_VB2_H_

Zobrazit soubor

@@ -1874,11 +1874,8 @@ static int msm_vdec_qbuf_batch(struct msm_vidc_inst *inst,
if (!buf)
return -EINVAL;
allow = msm_vidc_allow_qbuf(inst, vb2->type);
if (allow == MSM_VIDC_DISALLOW) {
i_vpr_e(inst, "%s: qbuf not allowed\n", __func__);
return -EINVAL;
} else if (allow == MSM_VIDC_DEFER) {
if (is_state(inst, MSM_VIDC_OPEN) ||
is_state(inst, MSM_VIDC_INPUT_STREAMING)) {
print_vidc_buffer(VIDC_LOW, "low ", "qbuf deferred", inst, buf);
return 0;
}
@@ -2068,95 +2065,96 @@ static int msm_vdec_alloc_and_queue_additional_dpb_buffers(struct msm_vidc_inst
return 0;
}
int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
int msm_vdec_stop_cmd(struct msm_vidc_inst *inst)
{
int rc = 0;
enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
struct msm_vidc_inst_capability *capability;
int rc = 0;
if (!inst || !inst->core || !inst->capabilities) {
i_vpr_h(inst, "received cmd: drain\n");
allow = msm_vidc_allow_stop(inst);
if (allow == MSM_VIDC_DISALLOW)
return -EBUSY;
else if (allow == MSM_VIDC_IGNORE)
return 0;
else if (allow != MSM_VIDC_ALLOW)
return -EINVAL;
rc = msm_vidc_process_drain(inst);
if (rc)
return rc;
return rc;
}
int msm_vdec_start_cmd(struct msm_vidc_inst *inst)
{
struct msm_vidc_inst_capability *capability;
int rc = 0;
if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
capability = inst->capabilities;
if (cmd == V4L2_DEC_CMD_STOP) {
i_vpr_h(inst, "received cmd: drain\n");
allow = msm_vidc_allow_stop(inst);
if (allow == MSM_VIDC_DISALLOW)
return -EBUSY;
else if (allow == MSM_VIDC_IGNORE)
return 0;
else if (allow != MSM_VIDC_ALLOW)
return -EINVAL;
rc = msm_vidc_process_drain(inst);
if (rc)
return rc;
} else if (cmd == V4L2_DEC_CMD_START) {
i_vpr_h(inst, "received cmd: resume\n");
vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_META_PORT].vb2q);
vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_PORT].vb2q);
i_vpr_h(inst, "received cmd: resume\n");
vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_META_PORT].vb2q);
vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_PORT].vb2q);
if (capability->cap[CODED_FRAMES].value == CODED_FRAMES_INTERLACE &&
!is_ubwc_colorformat(capability->cap[PIX_FMTS].value)) {
i_vpr_e(inst,
"%s: interlace with non-ubwc color format is unsupported\n",
__func__);
return -EINVAL;
}
if (!msm_vidc_allow_start(inst))
return -EBUSY;
/* tune power features */
inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
msm_vidc_allow_dcvs(inst);
msm_vidc_power_data_reset(inst);
/*
* client is completing partial port reconfiguration,
* hence reallocate input internal buffers before input port
* is resumed.
*/
if (is_sub_state(inst, MSM_VIDC_DRC) &&
is_sub_state(inst, MSM_VIDC_DRC_LAST_BUFFER) &&
is_sub_state(inst, MSM_VIDC_INPUT_PAUSE)) {
rc = msm_vidc_alloc_and_queue_input_internal_buffers(inst);
if (rc)
return rc;
rc = msm_vidc_set_stage(inst, STAGE);
if (rc)
return rc;
rc = msm_vidc_set_pipe(inst, PIPE);
if (rc)
return rc;
}
/* allocate and queue extra dpb buffers */
rc = msm_vdec_alloc_and_queue_additional_dpb_buffers(inst);
if (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 */
msm_vidc_print_buffer_info(inst);
rc = msm_vidc_process_resume(inst);
if (rc)
return rc;
} else {
i_vpr_e(inst, "%s: unknown cmd %d\n", __func__, cmd);
if (capability->cap[CODED_FRAMES].value == CODED_FRAMES_INTERLACE &&
!is_ubwc_colorformat(capability->cap[PIX_FMTS].value)) {
i_vpr_e(inst,
"%s: interlace with non-ubwc color format is unsupported\n",
__func__);
return -EINVAL;
}
return 0;
if (!msm_vidc_allow_start(inst))
return -EBUSY;
/* tune power features */
inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
msm_vidc_allow_dcvs(inst);
msm_vidc_power_data_reset(inst);
/*
* client is completing partial port reconfiguration,
* hence reallocate input internal buffers before input port
* is resumed.
*/
if (is_sub_state(inst, MSM_VIDC_DRC) &&
is_sub_state(inst, MSM_VIDC_DRC_LAST_BUFFER) &&
is_sub_state(inst, MSM_VIDC_INPUT_PAUSE)) {
rc = msm_vidc_alloc_and_queue_input_internal_buffers(inst);
if (rc)
return rc;
rc = msm_vidc_set_stage(inst, STAGE);
if (rc)
return rc;
rc = msm_vidc_set_pipe(inst, PIPE);
if (rc)
return rc;
}
/* allocate and queue extra dpb buffers */
rc = msm_vdec_alloc_and_queue_additional_dpb_buffers(inst);
if (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 */
msm_vidc_print_buffer_info(inst);
rc = msm_vidc_process_resume(inst);
if (rc)
return rc;
return rc;
}
int msm_vdec_try_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)

Zobrazit soubor

@@ -881,50 +881,48 @@ int msm_venc_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
return rc;
}
int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
int msm_venc_stop_cmd(struct msm_vidc_inst *inst)
{
enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
int rc = 0;
i_vpr_h(inst, "received cmd: drain\n");
allow = msm_vidc_allow_stop(inst);
if (allow == MSM_VIDC_DISALLOW)
return -EBUSY;
else if (allow == MSM_VIDC_IGNORE)
return 0;
else if (allow != MSM_VIDC_ALLOW)
return -EINVAL;
rc = msm_vidc_process_drain(inst);
if (rc)
return rc;
return rc;
}
int msm_venc_start_cmd(struct msm_vidc_inst *inst)
{
int rc = 0;
enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
i_vpr_h(inst, "received cmd: resume\n");
if (!msm_vidc_allow_start(inst))
return -EBUSY;
vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_META_PORT].vb2q);
vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_PORT].vb2q);
if (cmd == V4L2_ENC_CMD_STOP) {
i_vpr_h(inst, "received cmd: drain\n");
allow = msm_vidc_allow_stop(inst);
if (allow == MSM_VIDC_DISALLOW)
return -EBUSY;
else if (allow == MSM_VIDC_IGNORE)
return 0;
else if (allow != MSM_VIDC_ALLOW)
return -EINVAL;
rc = msm_vidc_process_drain(inst);
if (rc)
return rc;
} else if (cmd == V4L2_ENC_CMD_START) {
i_vpr_h(inst, "received cmd: resume\n");
if (!msm_vidc_allow_start(inst))
return -EBUSY;
vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_META_PORT].vb2q);
vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_PORT].vb2q);
/* tune power features */
msm_vidc_allow_dcvs(inst);
msm_vidc_power_data_reset(inst);
/* tune power features */
msm_vidc_allow_dcvs(inst);
msm_vidc_power_data_reset(inst);
/* print final buffer counts & size details */
msm_vidc_print_buffer_info(inst);
/* print final buffer counts & size details */
msm_vidc_print_buffer_info(inst);
rc = msm_vidc_process_resume(inst);
if (rc)
return rc;
rc = msm_vidc_process_resume(inst);
if (rc)
return rc;
} else {
i_vpr_e(inst, "%s: unknown cmd %d\n", __func__, cmd);
return -EINVAL;
}
return 0;
return rc;
}
int msm_venc_streamoff_output(struct msm_vidc_inst *inst)

Zobrazit soubor

@@ -658,26 +658,53 @@ int msm_vidc_try_cmd(void *instance, union msm_v4l2_cmd *cmd)
}
EXPORT_SYMBOL(msm_vidc_try_cmd);
int msm_vidc_cmd(void *instance, union msm_v4l2_cmd *cmd)
int msm_vidc_start_cmd(void *instance)
{
int rc = 0;
struct msm_vidc_inst *inst = instance;
struct v4l2_decoder_cmd *dec = NULL;
struct v4l2_encoder_cmd *enc = NULL;
int rc = 0;
if (!is_decode_session(inst) && !is_encode_session(inst)) {
i_vpr_e(inst, "%s: invalid session %d\n", __func__, inst->domain);
return -EINVAL;
}
if (is_decode_session(inst)) {
dec = (struct v4l2_decoder_cmd *)cmd;
rc = msm_vdec_process_cmd(inst, dec->cmd);
rc = msm_vdec_start_cmd(inst);
if (rc)
return rc;
} else if (is_encode_session(inst)) {
enc = (struct v4l2_encoder_cmd *)cmd;
rc = msm_venc_process_cmd(inst, enc->cmd);
rc = msm_venc_start_cmd(inst);
if (rc)
return rc;
}
if (rc)
return rc;
return 0;
return rc;
}
EXPORT_SYMBOL(msm_vidc_cmd);
EXPORT_SYMBOL(msm_vidc_start_cmd);
int msm_vidc_stop_cmd(void *instance)
{
struct msm_vidc_inst *inst = instance;
int rc = 0;
if (!is_decode_session(inst) && !is_encode_session(inst)) {
i_vpr_e(inst, "%s: invalid session %d\n", __func__, inst->domain);
return -EINVAL;
}
if (is_decode_session(inst)) {
rc = msm_vdec_stop_cmd(inst);
if (rc)
return rc;
} else if (is_encode_session(inst)) {
rc = msm_venc_stop_cmd(inst);
if (rc)
return rc;
}
return rc;
}
EXPORT_SYMBOL(msm_vidc_stop_cmd);
int msm_vidc_enum_framesizes(void *instance, struct v4l2_frmsizeenum *fsize)
{
@@ -894,7 +921,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
inst->core = core;
inst->domain = session_type;
inst->session_id = hash32_ptr(inst);
msm_vidc_change_state(inst, MSM_VIDC_OPEN, __func__);
msm_vidc_update_state(inst, MSM_VIDC_OPEN, __func__);
inst->sub_state = MSM_VIDC_SUB_STATE_NONE;
strlcpy(inst->sub_state_name, "SUB_STATE_NONE", sizeof(inst->sub_state_name));
inst->active = true;
@@ -1041,6 +1068,9 @@ int msm_vidc_close(void *instance)
msm_vidc_event_queue_deinit(inst);
msm_vidc_vb2_queue_deinit(inst);
msm_vidc_remove_session(inst);
msm_vidc_change_state(inst, MSM_VIDC_CLOSE, __func__);
inst->sub_state = MSM_VIDC_SUB_STATE_NONE;
strscpy(inst->sub_state_name, "SUB_STATE_NONE", sizeof(inst->sub_state_name));
inst_unlock(inst, __func__);
client_unlock(inst, __func__);
cancel_stability_work_sync(inst);

Zobrazit soubor

@@ -841,29 +841,17 @@ static int msm_vidc_update_static_property(struct msm_vidc_inst *inst,
return rc;
}
int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
int msm_vidc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
{
int rc = 0;
struct msm_vidc_inst *inst;
enum msm_vidc_inst_capability_type cap_id;
struct msm_vidc_inst_capability *capability;
int rc = 0;
u32 port;
if (!ctrl) {
d_vpr_e("%s: invalid ctrl parameter\n", __func__);
if (!inst || !inst->capabilities || !ctrl) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
inst = container_of(ctrl->handler,
struct msm_vidc_inst, ctrl_handler);
inst = get_inst_ref(g_core, inst);
if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid parameters for inst\n", __func__);
return -EINVAL;
}
client_lock(inst, __func__);
inst_lock(inst, __func__);
capability = inst->capabilities;
i_vpr_h(inst, FMT_STRING_SET_CTRL,
@@ -871,15 +859,8 @@ int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
cap_id = msm_vidc_get_cap_id(inst, ctrl->id);
if (!is_valid_cap_id(cap_id)) {
i_vpr_e(inst, "%s: could not find cap_id for ctrl %s\n",
__func__, ctrl->name);
rc = -EINVAL;
goto unlock;
}
if (!msm_vidc_allow_s_ctrl(inst, cap_id)) {
rc = -EINVAL;
goto unlock;
i_vpr_e(inst, "%s: invalid cap_id for ctrl %s\n", __func__, ctrl->name);
return -EINVAL;
}
/* mark client set flag */
@@ -890,18 +871,44 @@ int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
/* static case */
rc = msm_vidc_update_static_property(inst, cap_id, ctrl);
if (rc)
goto unlock;
return rc;
} else {
/* dynamic case */
rc = msm_vidc_adjust_dynamic_property(inst, cap_id, ctrl);
if (rc)
goto unlock;
return rc;
rc = msm_vidc_set_dynamic_property(inst);
if (rc)
goto unlock;
return rc;
}
return rc;
}
int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct msm_vidc_inst *inst;
int rc = 0;
if (!ctrl) {
d_vpr_e("%s: invalid ctrl parameter\n", __func__);
return -EINVAL;
}
inst = container_of(ctrl->handler, struct msm_vidc_inst, ctrl_handler);
inst = get_inst_ref(g_core, inst);
if (!inst) {
d_vpr_e("%s: invalid instance\n", __func__);
return -EINVAL;
}
client_lock(inst, __func__);
inst_lock(inst, __func__);
rc = inst->event_handle(inst, MSM_VIDC_S_CTRL, ctrl);
if (rc)
goto unlock;
unlock:
inst_unlock(inst, __func__);
client_unlock(inst, __func__);

Zobrazit soubor

@@ -130,6 +130,28 @@ const char *sub_state_name(enum msm_vidc_sub_state sub_state)
return "SUB_STATE_NONE";
}
int prepare_sub_state_name(enum msm_vidc_sub_state sub_state,
char *buf, u32 size)
{
int i = 0;
if (!buf || !size)
return -EINVAL;
strscpy(buf, "\0", size);
if (sub_state == MSM_VIDC_SUB_STATE_NONE) {
strscpy(buf, "SUB_STATE_NONE", size);
return 0;
}
for (i = 0; i < MSM_VIDC_MAX_SUB_STATES; i++) {
if (sub_state & BIT(i))
strlcat(buf, sub_state_name(BIT(i)), size);
}
return 0;
}
const char *v4l2_type_name(u32 port)
{
switch (port) {
@@ -888,7 +910,7 @@ struct msm_vidc_buffers *msm_vidc_get_buffers(
return &inst->buffers.vpss;
case MSM_VIDC_BUF_PARTIAL_DATA:
return &inst->buffers.partial_data;
case MSM_VIDC_BUF_QUEUE:
case MSM_VIDC_BUF_INTERFACE_QUEUE:
return NULL;
default:
i_vpr_e(inst, "%s: invalid driver buffer type %d\n",
@@ -994,16 +1016,14 @@ int signal_session_msg_receipt(struct msm_vidc_inst *inst,
int msm_vidc_change_state(struct msm_vidc_inst *inst,
enum msm_vidc_state request_state, const char *func)
{
enum msm_vidc_allow allow;
int rc;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (!request_state) {
i_vpr_e(inst, "%s: invalid request state\n", func);
return -EINVAL;
}
if (is_session_error(inst)) {
i_vpr_h(inst,
"%s: inst is in bad state, can not change state to %s\n",
@@ -1011,17 +1031,23 @@ int msm_vidc_change_state(struct msm_vidc_inst *inst,
return 0;
}
if (request_state == MSM_VIDC_ERROR)
i_vpr_e(inst, FMT_STRING_STATE_CHANGE,
func, state_name(request_state), state_name(inst->state));
else
i_vpr_h(inst, FMT_STRING_STATE_CHANGE,
func, state_name(request_state), state_name(inst->state));
/* current and requested state is same */
if (inst->state == request_state)
return 0;
trace_msm_vidc_common_state_change(inst, func, state_name(inst->state),
/* check if requested state movement is allowed */
allow = msm_vidc_allow_state_change(inst, request_state);
if (allow != MSM_VIDC_ALLOW) {
i_vpr_e(inst, "%s: %s state change %s -> %s\n", func,
allow_name(allow), state_name(inst->state),
state_name(request_state));
return (allow == MSM_VIDC_DISALLOW ? -EINVAL : 0);
}
inst->state = request_state;
/* go ahead and update inst state */
rc = msm_vidc_update_state(inst, request_state, func);
if (rc)
return rc;
return 0;
}
@@ -1030,8 +1056,8 @@ int msm_vidc_change_sub_state(struct msm_vidc_inst *inst,
enum msm_vidc_sub_state clear_sub_state,
enum msm_vidc_sub_state set_sub_state, const char *func)
{
int i = 0;
enum msm_vidc_sub_state prev_sub_state;
int rc = 0;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
@@ -1061,18 +1087,11 @@ int msm_vidc_change_sub_state(struct msm_vidc_inst *inst,
/* print substates only when there is a change */
if (inst->sub_state != prev_sub_state) {
strlcpy(inst->sub_state_name, "\0", sizeof(inst->sub_state_name));
for (i = 0; i < MSM_VIDC_MAX_SUB_STATES; i++) {
if (inst->sub_state == MSM_VIDC_SUB_STATE_NONE) {
strlcpy(inst->sub_state_name, "SUB_STATE_NONE",
sizeof(inst->sub_state_name));
break;
}
if (inst->sub_state & BIT(i))
strlcat(inst->sub_state_name, sub_state_name(BIT(i)),
sizeof(inst->sub_state_name));
}
i_vpr_h(inst, "%s: sub state changed to %s\n", func, inst->sub_state_name);
rc = prepare_sub_state_name(inst->sub_state, inst->sub_state_name,
sizeof(inst->sub_state_name));
if (!rc)
i_vpr_h(inst, "%s: state %s and sub state changed to %s\n",
func, state_name(inst->state), inst->sub_state_name);
}
return 0;
@@ -1110,55 +1129,6 @@ exit:
return allow;
}
bool msm_vidc_allow_s_ctrl(struct msm_vidc_inst *inst,
enum msm_vidc_inst_capability_type cap_id)
{
bool allow = false;
if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return false;
}
if (is_state(inst, MSM_VIDC_OPEN)) {
allow = true;
goto exit;
}
if (!inst->capabilities->cap[cap_id].cap_id ||
!inst->capabilities->cap[cap_id].v4l2_id) {
allow = false;
goto exit;
}
if (is_decode_session(inst)) {
if (!inst->bufq[INPUT_PORT].vb2q->streaming) {
allow = true;
goto exit;
}
if (inst->bufq[INPUT_PORT].vb2q->streaming) {
if (inst->capabilities->cap[cap_id].flags &
CAP_FLAG_DYNAMIC_ALLOWED)
allow = true;
}
} else if (is_encode_session(inst)) {
if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) {
allow = true;
goto exit;
}
if (inst->bufq[OUTPUT_PORT].vb2q->streaming) {
if (inst->capabilities->cap[cap_id].flags &
CAP_FLAG_DYNAMIC_ALLOWED)
allow = true;
}
}
exit:
if (!allow)
i_vpr_e(inst, "%s: cap_id %#x not allowed in state %s\n",
__func__, cap_id, state_name(inst->state));
return allow;
}
bool msm_vidc_allow_metadata_delivery(struct msm_vidc_inst *inst, u32 cap_id,
u32 port)
{
@@ -1387,79 +1357,6 @@ bool msm_vidc_allow_streamon(struct msm_vidc_inst *inst, u32 type)
return false;
}
enum msm_vidc_allow msm_vidc_allow_streamoff(struct msm_vidc_inst *inst, u32 type)
{
enum msm_vidc_allow allow = MSM_VIDC_ALLOW;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return MSM_VIDC_DISALLOW;
}
if (type == INPUT_MPLANE) {
if (!inst->bufq[INPUT_PORT].vb2q->streaming)
allow = MSM_VIDC_IGNORE;
} else if (type == INPUT_META_PLANE) {
if (inst->bufq[INPUT_PORT].vb2q->streaming)
allow = MSM_VIDC_DISALLOW;
else if (!inst->bufq[INPUT_META_PORT].vb2q->streaming)
allow = MSM_VIDC_IGNORE;
} else if (type == OUTPUT_MPLANE) {
if (!inst->bufq[OUTPUT_PORT].vb2q->streaming)
allow = MSM_VIDC_IGNORE;
} else if (type == OUTPUT_META_PLANE) {
if (inst->bufq[OUTPUT_PORT].vb2q->streaming)
allow = MSM_VIDC_DISALLOW;
else if (!inst->bufq[OUTPUT_META_PORT].vb2q->streaming)
allow = MSM_VIDC_IGNORE;
}
if (allow != MSM_VIDC_ALLOW)
i_vpr_e(inst, "%s: type %d is %s in state %s\n",
__func__, type, allow_name(allow),
state_name(inst->state));
return allow;
}
enum msm_vidc_allow msm_vidc_allow_qbuf(struct msm_vidc_inst *inst, u32 type)
{
int port = 0;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return MSM_VIDC_DISALLOW;
}
port = v4l2_type_to_driver_port(inst, type, __func__);
if (port < 0)
return MSM_VIDC_DISALLOW;
/* defer queuing if streamon not completed */
if (!inst->bufq[port].vb2q->streaming)
return MSM_VIDC_DEFER;
if (type == INPUT_META_PLANE || type == OUTPUT_META_PLANE)
return MSM_VIDC_DEFER;
if (type == INPUT_MPLANE) {
if (is_state(inst, MSM_VIDC_OPEN) ||
is_state(inst, MSM_VIDC_OUTPUT_STREAMING))
return MSM_VIDC_DEFER;
else
return MSM_VIDC_ALLOW;
} else if (type == OUTPUT_MPLANE) {
if (is_state(inst, MSM_VIDC_OPEN) ||
is_state(inst, MSM_VIDC_INPUT_STREAMING))
return MSM_VIDC_DEFER;
else
return MSM_VIDC_ALLOW;
} else {
i_vpr_e(inst, "%s: unknown buffer type %d\n", __func__, type);
return MSM_VIDC_DISALLOW;
}
return MSM_VIDC_DISALLOW;
}
enum msm_vidc_allow msm_vidc_allow_input_psc(struct msm_vidc_inst *inst)
{
enum msm_vidc_allow allow = MSM_VIDC_ALLOW;
@@ -3339,12 +3236,29 @@ int msm_vidc_queue_deferred_buffers(struct msm_vidc_inst *inst, enum msm_vidc_bu
return 0;
}
int msm_vidc_buf_queue(struct msm_vidc_inst *inst, struct msm_vidc_buffer *buf)
{
int rc = 0;
if (!inst || !buf) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
msm_vidc_scale_power(inst, is_input_buffer(buf->type));
rc = msm_vidc_queue_buffer(inst, buf);
if (rc)
return rc;
return rc;
}
int msm_vidc_queue_buffer_single(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
{
int rc = 0;
struct msm_vidc_buffer *buf = NULL;
struct msm_vidc_fence *fence = NULL;
enum msm_vidc_allow allow;
if (!inst || !vb2 || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
@@ -3363,20 +3277,7 @@ int msm_vidc_queue_buffer_single(struct msm_vidc_inst *inst, struct vb2_buffer *
buf->fence_id = fence->dma_fence.seqno;
}
allow = msm_vidc_allow_qbuf(inst, vb2->type);
if (allow == MSM_VIDC_DISALLOW) {
i_vpr_e(inst, "%s: qbuf not allowed\n", __func__);
rc = -EINVAL;
goto exit;
} else if (allow == MSM_VIDC_DEFER) {
print_vidc_buffer(VIDC_LOW, "low ", "qbuf deferred", inst, buf);
rc = 0;
goto exit;
}
msm_vidc_scale_power(inst, is_input_buffer(buf->type));
rc = msm_vidc_queue_buffer(inst, buf);
rc = inst->event_handle(inst, MSM_VIDC_BUF_QUEUE, buf);
if (rc)
goto exit;
@@ -4198,10 +4099,6 @@ int msm_vidc_session_streamoff(struct msm_vidc_inst *inst,
if (rc)
goto error;
rc = msm_vidc_state_change_streamoff(inst, port);
if (rc)
goto error;
core = inst->core;
i_vpr_h(inst, "%s: wait on port: %d for time: %d ms\n",
__func__, port, core->capabilities[HW_RESPONSE_TIMEOUT].value);
@@ -4241,6 +4138,10 @@ int msm_vidc_session_streamoff(struct msm_vidc_inst *inst,
goto error;
}
rc = msm_vidc_state_change_streamoff(inst, port);
if (rc)
goto error;
/* flush deferred buffers */
msm_vidc_flush_buffers(inst, buffer_type);
msm_vidc_flush_read_only_buffers(inst, buffer_type);
@@ -4290,10 +4191,6 @@ int msm_vidc_session_close(struct msm_vidc_inst *inst)
}
inst_lock(inst, __func__);
msm_vidc_change_state(inst, MSM_VIDC_CLOSE, __func__);
inst->sub_state = MSM_VIDC_SUB_STATE_NONE;
strlcpy(inst->sub_state_name, "SUB_STATE_NONE", sizeof(inst->sub_state_name));
return rc;
}
@@ -5129,7 +5026,6 @@ void msm_vidc_fw_unload_handler(struct work_struct *work)
void msm_vidc_batch_handler(struct work_struct *work)
{
struct msm_vidc_inst *inst;
enum msm_vidc_allow allow;
struct msm_vidc_core *core;
int rc = 0;
@@ -5152,8 +5048,8 @@ void msm_vidc_batch_handler(struct work_struct *work)
goto exit;
}
allow = msm_vidc_allow_qbuf(inst, OUTPUT_MPLANE);
if (allow != MSM_VIDC_ALLOW) {
if (is_state(inst, MSM_VIDC_OPEN) ||
is_state(inst, MSM_VIDC_INPUT_STREAMING)) {
i_vpr_e(inst, "%s: not allowed in state: %s\n", __func__,
state_name(inst->state));
goto exit;

Zobrazit soubor

@@ -4,10 +4,14 @@
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "msm_vidc_control.h"
#include "msm_vidc_driver.h"
#include "msm_vidc_state.h"
#include "msm_vidc_core.h"
#include "msm_vidc_debug.h"
#include "msm_vidc_core.h"
#include "msm_vidc_vb2.h"
#include "msm_vidc.h"
#include "msm_vidc_events.h"
bool core_in_valid_state(struct msm_vidc_core *core)
{
@@ -36,6 +40,22 @@ exit:
return name;
}
static const char * const event_name_arr[] =
FOREACH_EVENT(GENERATE_STRING);
static const char *event_name(enum msm_vidc_event event)
{
const char *name = "UNKNOWN EVENT";
if (event >= ARRAY_SIZE(event_name_arr))
goto exit;
name = event_name_arr[event];
exit:
return name;
}
static int __strict_check(struct msm_vidc_core *core, const char *function)
{
bool fatal = !mutex_is_locked(&core->lock);
@@ -48,6 +68,18 @@ static int __strict_check(struct msm_vidc_core *core, const char *function)
return fatal ? -EINVAL : 0;
}
static int __strict_inst_check(struct msm_vidc_inst *inst, const char *function)
{
bool fatal = !mutex_is_locked(&inst->lock);
WARN_ON(fatal);
if (fatal)
d_vpr_e("%s: strict check failed\n", function);
return fatal ? -EINVAL : 0;
}
static int msm_vidc_core_deinit_state(struct msm_vidc_core *core,
enum msm_vidc_core_event_type type,
struct msm_vidc_event_data *data)
@@ -181,7 +213,14 @@ static int msm_vidc_core_error_state(struct msm_vidc_core *core,
return rc;
}
struct msm_vidc_core_state_handle *msm_vidc_get_core_state_handle(
struct msm_vidc_core_state_handle {
enum msm_vidc_core_state state;
int (*handle)(struct msm_vidc_core *core,
enum msm_vidc_core_event_type type,
struct msm_vidc_event_data *data);
};
static struct msm_vidc_core_state_handle *msm_vidc_get_core_state_handle(
enum msm_vidc_core_state req_state)
{
int cnt;
@@ -456,3 +495,698 @@ int msm_vidc_change_core_sub_state(struct msm_vidc_core *core,
return 0;
}
static int msm_vidc_open_state(struct msm_vidc_inst *inst,
enum msm_vidc_event event, void *data)
{
int rc = 0;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
/* inst must be locked */
rc = __strict_inst_check(inst, __func__);
if (rc) {
i_vpr_e(inst, "%s(): inst was not locked\n", __func__);
return -EINVAL;
}
switch (event) {
case MSM_VIDC_S_FMT:
{
struct v4l2_format *f = (struct v4l2_format *)data;
rc = msm_vidc_s_fmt(inst, f);
if (rc)
return rc;
break;
}
case MSM_VIDC_S_CTRL:
{
struct v4l2_ctrl *ctrl = (struct v4l2_ctrl *)data;
/* allow set_control request in open state */
rc = msm_vidc_s_ctrl(inst, ctrl);
if (rc)
return rc;
break;
}
case MSM_VIDC_REQBUFS:
{
struct v4l2_requestbuffers *b = (struct v4l2_requestbuffers *)data;
rc = msm_vidc_reqbufs(inst, b);
if (rc)
return rc;
break;
}
case MSM_VIDC_STREAMON:
{
struct vb2_queue *q = (struct vb2_queue *)data;
rc = msm_vidc_start_streaming(inst, q);
if (rc)
return rc;
break;
}
case MSM_VIDC_STREAMOFF:
{
struct vb2_queue *q = (struct vb2_queue *)data;
/* ignore streamoff request in open state */
i_vpr_e(inst, "%s: type %d is %s in state %s\n",
__func__, q->type, allow_name(MSM_VIDC_IGNORE),
state_name(inst->state));
break;
}
case MSM_VIDC_CMD_START:
{
rc = msm_vidc_start_cmd(inst);
if (rc)
return rc;
break;
}
case MSM_VIDC_CMD_STOP:
{
rc = msm_vidc_stop_cmd(inst);
if (rc)
return rc;
break;
}
case MSM_VIDC_BUF_QUEUE:
{
struct msm_vidc_buffer *buf = (struct msm_vidc_buffer *)data;
/* defer qbuf request in open state */
print_vidc_buffer(VIDC_LOW, "low ", "qbuf deferred", inst, buf);
break;
}
default:
{
i_vpr_e(inst, "%s: unexpected event %s\n", __func__, event_name(event));
return -EINVAL;
}
}
return rc;
}
static int msm_vidc_input_streaming_state(struct msm_vidc_inst *inst,
enum msm_vidc_event event, void *data)
{
int rc = 0;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
/* inst must be locked */
rc = __strict_inst_check(inst, __func__);
if (rc) {
i_vpr_e(inst, "%s(): inst was not locked\n", __func__);
return -EINVAL;
}
switch (event) {
case MSM_VIDC_S_FMT:
{
struct v4l2_format *f = (struct v4l2_format *)data;
rc = msm_vidc_s_fmt(inst, f);
if (rc)
return rc;
break;
}
case MSM_VIDC_S_CTRL:
{
struct v4l2_ctrl *ctrl = (struct v4l2_ctrl *)data;
u32 cap_id = msm_vidc_get_cap_id(inst, ctrl->id);
if (cap_id == INST_CAP_NONE) {
i_vpr_e(inst, "%s: invalid cap_id %u\n", __func__, cap_id);
return -EINVAL;
}
/* disallow */
if (is_decode_session(inst)) {
/* check dynamic allowed if master port is streaming */
if (!(inst->capabilities->cap[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED)) {
i_vpr_e(inst, "%s: cap_id %#x not allowed in state %s\n",
__func__, cap_id, state_name(inst->state));
return -EINVAL;
}
}
rc = msm_vidc_s_ctrl(inst, ctrl);
if (rc)
return rc;
break;
}
case MSM_VIDC_REQBUFS:
{
struct v4l2_requestbuffers *b = (struct v4l2_requestbuffers *)data;
rc = msm_vidc_reqbufs(inst, b);
if (rc)
return rc;
break;
}
case MSM_VIDC_STREAMON:
{
struct vb2_queue *q = (struct vb2_queue *)data;
rc = msm_vidc_start_streaming(inst, q);
if (rc)
return rc;
break;
}
case MSM_VIDC_STREAMOFF:
{
struct vb2_queue *q = (struct vb2_queue *)data;
enum msm_vidc_allow allow = MSM_VIDC_ALLOW;
/* ignore */
if (q->type == OUTPUT_MPLANE || q->type == OUTPUT_META_PLANE)
allow = MSM_VIDC_IGNORE;
/* disallow */
else if (q->type == INPUT_META_PLANE)
allow = MSM_VIDC_DISALLOW;
if (allow != MSM_VIDC_ALLOW) {
i_vpr_e(inst, "%s: type %d is %s in state %s\n",
__func__, q->type, allow_name(allow),
state_name(inst->state));
return (allow == MSM_VIDC_DISALLOW ? -EINVAL : 0);
}
/* sanitize type field */
if (q->type != INPUT_MPLANE) {
i_vpr_e(inst, "%s: invalid type %d\n", __func__, q->type);
return -EINVAL;
}
rc = msm_vidc_stop_streaming(inst, q);
if (rc)
return rc;
break;
}
case MSM_VIDC_CMD_START:
{
rc = msm_vidc_start_cmd(inst);
if (rc)
return rc;
break;
}
case MSM_VIDC_CMD_STOP:
{
rc = msm_vidc_stop_cmd(inst);
if (rc)
return rc;
break;
}
case MSM_VIDC_BUF_QUEUE:
{
struct msm_vidc_buffer *buf = (struct msm_vidc_buffer *)data;
/* defer meta port */
if (buf->type == MSM_VIDC_BUF_INPUT_META || buf->type == MSM_VIDC_BUF_OUTPUT_META) {
print_vidc_buffer(VIDC_LOW, "low ", "qbuf deferred", inst, buf);
return 0;
}
/* disallow */
if (buf->type != MSM_VIDC_BUF_INPUT && buf->type != MSM_VIDC_BUF_OUTPUT) {
i_vpr_e(inst, "%s: invalid buf type %u\n", __func__, buf->type);
return -EINVAL;
}
/* defer output port */
if (buf->type == MSM_VIDC_BUF_OUTPUT) {
print_vidc_buffer(VIDC_LOW, "low ", "qbuf deferred", inst, buf);
return 0;
}
rc = msm_vidc_buf_queue(inst, buf);
if (rc)
return rc;
break;
}
default:
{
i_vpr_e(inst, "%s: unexpected event %s\n", __func__, event_name(event));
return -EINVAL;
}
}
return rc;
}
static int msm_vidc_output_streaming_state(struct msm_vidc_inst *inst,
enum msm_vidc_event event, void *data)
{
int rc = 0;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
/* inst must be locked */
rc = __strict_inst_check(inst, __func__);
if (rc) {
i_vpr_e(inst, "%s(): inst was not locked\n", __func__);
return -EINVAL;
}
switch (event) {
case MSM_VIDC_S_FMT:
{
struct v4l2_format *f = (struct v4l2_format *)data;
rc = msm_vidc_s_fmt(inst, f);
if (rc)
return rc;
break;
}
case MSM_VIDC_S_CTRL:
{
struct v4l2_ctrl *ctrl = (struct v4l2_ctrl *)data;
u32 cap_id = msm_vidc_get_cap_id(inst, ctrl->id);
if (cap_id == INST_CAP_NONE) {
i_vpr_e(inst, "%s: invalid cap_id %u\n", __func__, cap_id);
return -EINVAL;
}
/* disallow */
if (is_encode_session(inst)) {
/* check dynamic allowed if master port is streaming */
if (!(inst->capabilities->cap[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED)) {
i_vpr_e(inst, "%s: cap_id %#x not allowed in state %s\n",
__func__, cap_id, state_name(inst->state));
return -EINVAL;
}
}
rc = msm_vidc_s_ctrl(inst, ctrl);
if (rc)
return rc;
break;
}
case MSM_VIDC_REQBUFS:
{
struct v4l2_requestbuffers *b = (struct v4l2_requestbuffers *)data;
rc = msm_vidc_reqbufs(inst, b);
if (rc)
return rc;
break;
}
case MSM_VIDC_STREAMON:
{
struct vb2_queue *q = (struct vb2_queue *)data;
rc = msm_vidc_start_streaming(inst, q);
if (rc)
return rc;
break;
}
case MSM_VIDC_STREAMOFF:
{
struct vb2_queue *q = (struct vb2_queue *)data;
enum msm_vidc_allow allow = MSM_VIDC_ALLOW;
/* ignore */
if (q->type == INPUT_MPLANE || q->type == INPUT_META_PLANE)
allow = MSM_VIDC_IGNORE;
/* disallow */
else if (q->type == OUTPUT_META_PLANE)
allow = MSM_VIDC_DISALLOW;
if (allow != MSM_VIDC_ALLOW) {
i_vpr_e(inst, "%s: type %d is %s in state %s\n",
__func__, q->type, allow_name(allow),
state_name(inst->state));
return (allow == MSM_VIDC_DISALLOW ? -EINVAL : 0);
}
/* sanitize type field */
if (q->type != OUTPUT_MPLANE) {
i_vpr_e(inst, "%s: invalid type %d\n", __func__, q->type);
return -EINVAL;
}
rc = msm_vidc_stop_streaming(inst, q);
if (rc)
return rc;
break;
}
case MSM_VIDC_CMD_START:
{
rc = msm_vidc_start_cmd(inst);
if (rc)
return rc;
break;
}
case MSM_VIDC_CMD_STOP:
{
rc = msm_vidc_stop_cmd(inst);
if (rc)
return rc;
break;
}
case MSM_VIDC_BUF_QUEUE:
{
struct msm_vidc_buffer *buf = (struct msm_vidc_buffer *)data;
/* defer meta port */
if (buf->type == MSM_VIDC_BUF_INPUT_META || buf->type == MSM_VIDC_BUF_OUTPUT_META) {
print_vidc_buffer(VIDC_LOW, "low ", "qbuf deferred", inst, buf);
return 0;
}
/* disallow */
if (buf->type != MSM_VIDC_BUF_INPUT && buf->type != MSM_VIDC_BUF_OUTPUT) {
i_vpr_e(inst, "%s: invalid buf type %u\n", __func__, buf->type);
return -EINVAL;
}
/* defer input port */
if (buf->type == MSM_VIDC_BUF_INPUT) {
print_vidc_buffer(VIDC_LOW, "low ", "qbuf deferred", inst, buf);
return 0;
}
rc = msm_vidc_buf_queue(inst, buf);
if (rc)
return rc;
break;
}
default: {
i_vpr_e(inst, "%s: unexpected event %s\n", __func__, event_name(event));
return -EINVAL;
}
}
return rc;
}
static int msm_vidc_streaming_state(struct msm_vidc_inst *inst,
enum msm_vidc_event event, void *data)
{
int rc = 0;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
/* inst must be locked */
rc = __strict_inst_check(inst, __func__);
if (rc) {
i_vpr_e(inst, "%s(): inst was not locked\n", __func__);
return -EINVAL;
}
switch (event) {
case MSM_VIDC_S_CTRL:
{
struct v4l2_ctrl *ctrl = (struct v4l2_ctrl *)data;
u32 cap_id = msm_vidc_get_cap_id(inst, ctrl->id);
if (cap_id == INST_CAP_NONE) {
i_vpr_e(inst, "%s: invalid cap_id %u\n", __func__, cap_id);
return -EINVAL;
}
/* disallow */
if (!(inst->capabilities->cap[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED)) {
i_vpr_e(inst, "%s: cap_id %#x not allowed in state %s\n",
__func__, cap_id, state_name(inst->state));
return -EINVAL;
}
rc = msm_vidc_s_ctrl(inst, ctrl);
if (rc)
return rc;
break;
}
case MSM_VIDC_STREAMOFF:
{
struct vb2_queue *q = (struct vb2_queue *)data;
/* disallow */
if (q->type == INPUT_META_PLANE || q->type == OUTPUT_META_PLANE) {
i_vpr_e(inst, "%s: type %d is %s in state %s\n",
__func__, q->type, allow_name(MSM_VIDC_DISALLOW),
state_name(inst->state));
return -EINVAL;
}
/* sanitize type field */
if (q->type != INPUT_MPLANE && q->type != OUTPUT_MPLANE) {
i_vpr_e(inst, "%s: invalid type %d\n", __func__, q->type);
return -EINVAL;
}
rc = msm_vidc_stop_streaming(inst, q);
if (rc)
return rc;
break;
}
case MSM_VIDC_CMD_START:
{
rc = msm_vidc_start_cmd(inst);
if (rc)
return rc;
break;
}
case MSM_VIDC_CMD_STOP:
{
rc = msm_vidc_stop_cmd(inst);
if (rc)
return rc;
break;
}
case MSM_VIDC_BUF_QUEUE:
{
struct msm_vidc_buffer *buf = (struct msm_vidc_buffer *)data;
/* defer meta port */
if (buf->type == MSM_VIDC_BUF_INPUT_META || buf->type == MSM_VIDC_BUF_OUTPUT_META) {
print_vidc_buffer(VIDC_LOW, "low ", "qbuf deferred", inst, buf);
return 0;
}
/* disallow */
if (buf->type != MSM_VIDC_BUF_INPUT && buf->type != MSM_VIDC_BUF_OUTPUT) {
i_vpr_e(inst, "%s: invalid buf type %u\n", __func__, buf->type);
return -EINVAL;
}
rc = msm_vidc_buf_queue(inst, buf);
if (rc)
return rc;
break;
}
default: {
i_vpr_e(inst, "%s: unexpected event %s\n", __func__, event_name(event));
return -EINVAL;
}
}
return rc;
}
static int msm_vidc_close_state(struct msm_vidc_inst *inst,
enum msm_vidc_event event, void *data)
{
int rc = 0;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
/* inst must be locked */
rc = __strict_inst_check(inst, __func__);
if (rc) {
i_vpr_e(inst, "%s(): inst was not locked\n", __func__);
return -EINVAL;
}
i_vpr_e(inst, "%s: unexpected event %s\n", __func__, event_name(event));
return -EINVAL;
}
static int msm_vidc_error_state(struct msm_vidc_inst *inst,
enum msm_vidc_event event, void *data)
{
int rc = 0;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
/* inst must be locked */
rc = __strict_inst_check(inst, __func__);
if (rc) {
i_vpr_e(inst, "%s(): inst was not locked\n", __func__);
return -EINVAL;
}
switch (event) {
case MSM_VIDC_STREAMOFF:
{
struct vb2_queue *q = (struct vb2_queue *)data;
rc = msm_vidc_stop_streaming(inst, q);
if (rc)
return rc;
break;
}
default: {
i_vpr_e(inst, "%s: unexpected event %s\n", __func__, event_name(event));
return -EINVAL;
}
}
return rc;
}
struct msm_vidc_state_handle {
enum msm_vidc_state state;
int (*handle)(struct msm_vidc_inst *inst,
enum msm_vidc_event event, void *data);
};
static struct msm_vidc_state_handle *msm_vidc_get_state_handle(
struct msm_vidc_inst *inst,
enum msm_vidc_state req_state)
{
int cnt;
struct msm_vidc_state_handle *inst_state_handle = NULL;
static struct msm_vidc_state_handle state_handle[] = {
{MSM_VIDC_OPEN, msm_vidc_open_state },
{MSM_VIDC_INPUT_STREAMING, msm_vidc_input_streaming_state },
{MSM_VIDC_OUTPUT_STREAMING, msm_vidc_output_streaming_state },
{MSM_VIDC_STREAMING, msm_vidc_streaming_state },
{MSM_VIDC_CLOSE, msm_vidc_close_state },
{MSM_VIDC_ERROR, msm_vidc_error_state },
};
for (cnt = 0; cnt < ARRAY_SIZE(state_handle); cnt++) {
if (state_handle[cnt].state == req_state) {
inst_state_handle = &state_handle[cnt];
break;
}
}
/* check if req_state does not exist in the table */
if (cnt == ARRAY_SIZE(state_handle)) {
i_vpr_e(inst, "%s: invalid state %s\n", __func__, state_name(req_state));
return inst_state_handle;
}
return inst_state_handle;
}
int msm_vidc_update_state(struct msm_vidc_inst *inst,
enum msm_vidc_state request_state, const char *func)
{
struct msm_vidc_state_handle *state_handle = NULL;
int rc = 0;
/* get inst state handler for requested state */
state_handle = msm_vidc_get_state_handle(inst, request_state);
if (!state_handle)
return -EINVAL;
if (request_state == MSM_VIDC_ERROR)
i_vpr_e(inst, FMT_STRING_STATE_CHANGE,
func, state_name(request_state), state_name(inst->state));
else
i_vpr_h(inst, FMT_STRING_STATE_CHANGE,
func, state_name(request_state), state_name(inst->state));
trace_msm_vidc_common_state_change(inst, func, state_name(inst->state),
state_name(request_state));
/* finally update inst state and handler */
inst->state = state_handle->state;
inst->event_handle = state_handle->handle;
return rc;
}
struct msm_vidc_state_allow {
enum msm_vidc_state from;
enum msm_vidc_state to;
enum msm_vidc_allow allow;
};
enum msm_vidc_allow msm_vidc_allow_state_change(
struct msm_vidc_inst *inst,
enum msm_vidc_state req_state)
{
int cnt;
enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
static struct msm_vidc_state_allow state[] = {
/* from, to, allow */
{MSM_VIDC_OPEN, MSM_VIDC_OPEN, MSM_VIDC_IGNORE },
{MSM_VIDC_OPEN, MSM_VIDC_INPUT_STREAMING, MSM_VIDC_ALLOW },
{MSM_VIDC_OPEN, MSM_VIDC_OUTPUT_STREAMING, MSM_VIDC_ALLOW },
{MSM_VIDC_OPEN, MSM_VIDC_STREAMING, MSM_VIDC_DISALLOW },
{MSM_VIDC_OPEN, MSM_VIDC_CLOSE, MSM_VIDC_ALLOW },
{MSM_VIDC_OPEN, MSM_VIDC_ERROR, MSM_VIDC_ALLOW },
{MSM_VIDC_INPUT_STREAMING, MSM_VIDC_OPEN, MSM_VIDC_ALLOW },
{MSM_VIDC_INPUT_STREAMING, MSM_VIDC_INPUT_STREAMING, MSM_VIDC_IGNORE },
{MSM_VIDC_INPUT_STREAMING, MSM_VIDC_OUTPUT_STREAMING, MSM_VIDC_DISALLOW },
{MSM_VIDC_INPUT_STREAMING, MSM_VIDC_STREAMING, MSM_VIDC_ALLOW },
{MSM_VIDC_INPUT_STREAMING, MSM_VIDC_CLOSE, MSM_VIDC_ALLOW },
{MSM_VIDC_INPUT_STREAMING, MSM_VIDC_ERROR, MSM_VIDC_ALLOW },
{MSM_VIDC_OUTPUT_STREAMING, MSM_VIDC_OPEN, MSM_VIDC_ALLOW },
{MSM_VIDC_OUTPUT_STREAMING, MSM_VIDC_INPUT_STREAMING, MSM_VIDC_DISALLOW },
{MSM_VIDC_OUTPUT_STREAMING, MSM_VIDC_OUTPUT_STREAMING, MSM_VIDC_IGNORE },
{MSM_VIDC_OUTPUT_STREAMING, MSM_VIDC_STREAMING, MSM_VIDC_ALLOW },
{MSM_VIDC_OUTPUT_STREAMING, MSM_VIDC_CLOSE, MSM_VIDC_ALLOW },
{MSM_VIDC_OUTPUT_STREAMING, MSM_VIDC_ERROR, MSM_VIDC_ALLOW },
{MSM_VIDC_STREAMING, MSM_VIDC_OPEN, MSM_VIDC_DISALLOW },
{MSM_VIDC_STREAMING, MSM_VIDC_INPUT_STREAMING, MSM_VIDC_ALLOW },
{MSM_VIDC_STREAMING, MSM_VIDC_OUTPUT_STREAMING, MSM_VIDC_ALLOW },
{MSM_VIDC_STREAMING, MSM_VIDC_STREAMING, MSM_VIDC_IGNORE },
{MSM_VIDC_STREAMING, MSM_VIDC_CLOSE, MSM_VIDC_ALLOW },
{MSM_VIDC_STREAMING, MSM_VIDC_ERROR, MSM_VIDC_ALLOW },
{MSM_VIDC_CLOSE, MSM_VIDC_OPEN, MSM_VIDC_DISALLOW },
{MSM_VIDC_CLOSE, MSM_VIDC_INPUT_STREAMING, MSM_VIDC_DISALLOW },
{MSM_VIDC_CLOSE, MSM_VIDC_OUTPUT_STREAMING, MSM_VIDC_DISALLOW },
{MSM_VIDC_CLOSE, MSM_VIDC_STREAMING, MSM_VIDC_DISALLOW },
{MSM_VIDC_CLOSE, MSM_VIDC_CLOSE, MSM_VIDC_IGNORE },
{MSM_VIDC_CLOSE, MSM_VIDC_ERROR, MSM_VIDC_IGNORE },
{MSM_VIDC_ERROR, MSM_VIDC_OPEN, MSM_VIDC_IGNORE },
{MSM_VIDC_ERROR, MSM_VIDC_INPUT_STREAMING, MSM_VIDC_IGNORE },
{MSM_VIDC_ERROR, MSM_VIDC_OUTPUT_STREAMING, MSM_VIDC_IGNORE },
{MSM_VIDC_ERROR, MSM_VIDC_STREAMING, MSM_VIDC_IGNORE },
{MSM_VIDC_ERROR, MSM_VIDC_CLOSE, MSM_VIDC_ALLOW },
{MSM_VIDC_ERROR, MSM_VIDC_ERROR, MSM_VIDC_IGNORE },
};
for (cnt = 0; cnt < ARRAY_SIZE(state); cnt++) {
if (state[cnt].from == inst->state && state[cnt].to == req_state) {
allow = state[cnt].allow;
break;
}
}
return allow;
}

Zobrazit soubor

@@ -166,7 +166,7 @@ int msm_v4l2_s_fmt(struct file *filp, void *fh,
rc = -EBUSY;
goto unlock;
}
rc = msm_vidc_s_fmt((void *)inst, f);
rc = inst->event_handle(inst, MSM_VIDC_S_FMT, f);
if (rc)
goto unlock;
@@ -332,7 +332,7 @@ int msm_v4l2_reqbufs(struct file *filp, void *fh,
client_lock(inst, __func__);
inst_lock(inst, __func__);
rc = msm_vidc_reqbufs((void *)inst, b);
rc = inst->event_handle(inst, MSM_VIDC_REQBUFS, b);
if (rc)
goto unlock;
@@ -437,11 +437,11 @@ int msm_v4l2_qbuf(struct file *filp, void *fh,
}
/*
* do not acquire inst lock here. acquire it in msm_vidc_buf_queue.
* for requests, msm_vidc_buf_queue() is not called from here.
* do not acquire inst lock here. acquire it in msm_vb2_buf_queue.
* for requests, msm_vb2_buf_queue() is not called from here.
* instead it's called as part of msm_v4l2_request_queue().
* hence acquire the inst lock in common function i.e
* msm_vidc_buf_queue, to handle both requests and non-request
* msm_vb2_buf_queue, to handle both requests and non-request
* scenarios.
*/
rc = msm_vidc_qbuf(inst, vdev->v4l2_dev->mdev, b);
@@ -618,6 +618,7 @@ int msm_v4l2_decoder_cmd(struct file *filp, void *fh,
struct v4l2_decoder_cmd *dec)
{
struct msm_vidc_inst *inst = get_vidc_inst(filp, fh);
enum msm_vidc_event event;
int rc = 0;
inst = get_inst_ref(g_core, inst);
@@ -633,7 +634,19 @@ int msm_v4l2_decoder_cmd(struct file *filp, void *fh,
rc = -EBUSY;
goto unlock;
}
rc = msm_vidc_cmd((void *)inst, (union msm_v4l2_cmd *)dec);
if (!dec) {
i_vpr_e(inst, "%s: invalid params\n", __func__);
rc = -EINVAL;
goto unlock;
}
if (dec->cmd != V4L2_DEC_CMD_START &&
dec->cmd != V4L2_DEC_CMD_STOP) {
i_vpr_e(inst, "%s: invalid cmd %#x\n", __func__, dec->cmd);
rc = -EINVAL;
goto unlock;
}
event = (dec->cmd == V4L2_DEC_CMD_START ? MSM_VIDC_CMD_START : MSM_VIDC_CMD_STOP);
rc = inst->event_handle(inst, event, NULL);
if (rc)
goto unlock;
@@ -680,6 +693,7 @@ int msm_v4l2_encoder_cmd(struct file *filp, void *fh,
struct v4l2_encoder_cmd *enc)
{
struct msm_vidc_inst *inst = get_vidc_inst(filp, fh);
enum msm_vidc_event event;
int rc = 0;
inst = get_inst_ref(g_core, inst);
@@ -695,7 +709,19 @@ int msm_v4l2_encoder_cmd(struct file *filp, void *fh,
rc = -EBUSY;
goto unlock;
}
rc = msm_vidc_cmd((void *)inst, (union msm_v4l2_cmd *)enc);
if (!enc) {
i_vpr_e(inst, "%s: invalid params\n", __func__);
rc = -EINVAL;
goto unlock;
}
if (enc->cmd != V4L2_ENC_CMD_START &&
enc->cmd != V4L2_ENC_CMD_STOP) {
i_vpr_e(inst, "%s: invalid cmd %#x\n", __func__, enc->cmd);
rc = -EINVAL;
goto unlock;
}
event = (enc->cmd == V4L2_ENC_CMD_START ? MSM_VIDC_CMD_START : MSM_VIDC_CMD_STOP);
rc = inst->event_handle(inst, event, NULL);
if (rc)
goto unlock;

Zobrazit soubor

@@ -239,7 +239,7 @@ exit:
return;
}
int msm_vidc_queue_setup(struct vb2_queue *q,
int msm_vb2_queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], struct device *alloc_devs[])
{
@@ -366,11 +366,10 @@ int msm_vidc_queue_setup(struct vb2_queue *q,
return rc;
}
int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
int msm_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
{
int rc = 0;
struct msm_vidc_inst *inst;
enum msm_vidc_buffer_type buf_type;
if (!q || !q->drv_priv) {
d_vpr_e("%s: invalid input, q = %pK\n", __func__, q);
@@ -391,22 +390,46 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
goto unlock;
}
if (!msm_vidc_allow_streamon(inst, q->type)) {
rc = -EBUSY;
rc = inst->event_handle(inst, MSM_VIDC_STREAMON, q);
if (rc) {
i_vpr_e(inst, "Streamon: %s failed\n", v4l2_type_name(q->type));
msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
goto unlock;
}
unlock:
inst_unlock(inst, __func__);
client_unlock(inst, __func__);
put_inst(inst);
return rc;
}
int msm_vidc_start_streaming(struct msm_vidc_inst *inst, struct vb2_queue *q)
{
enum msm_vidc_buffer_type buf_type;
int rc = 0;
if (!inst || !q) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (!msm_vidc_allow_streamon(inst, q->type))
return -EBUSY;
if (q->type == INPUT_META_PLANE || q->type == OUTPUT_META_PLANE) {
i_vpr_h(inst, "%s: nothing to start on %s\n",
__func__, v4l2_type_name(q->type));
rc = 0;
goto unlock;
return 0;
}
if (q->type != INPUT_MPLANE && q->type != OUTPUT_MPLANE) {
i_vpr_e(inst, "%s: invalid type %d\n", __func__, q->type);
return -EINVAL;
}
if (!is_decode_session(inst) && !is_encode_session(inst)) {
i_vpr_e(inst, "%s: invalid session %d\n",
__func__, inst->domain);
rc = -EINVAL;
goto unlock;
i_vpr_e(inst, "%s: invalid session %d\n", __func__, inst->domain);
return -EINVAL;
}
i_vpr_h(inst, "Streamon: %s\n", v4l2_type_name(q->type));
@@ -414,30 +437,30 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
inst->once_per_session_set = true;
rc = msm_vidc_prepare_dependency_list(inst);
if (rc)
goto unlock;
return rc;
rc = msm_vidc_session_set_codec(inst);
if (rc)
goto unlock;
return rc;
rc = msm_vidc_session_set_secure_mode(inst);
if (rc)
goto unlock;
return rc;
if (is_encode_session(inst)) {
rc = msm_vidc_alloc_and_queue_session_internal_buffers(inst,
MSM_VIDC_BUF_ARP);
if (rc)
goto unlock;
return rc;
} else if(is_decode_session(inst)) {
rc = msm_vidc_session_set_default_header(inst);
if (rc)
goto unlock;
return rc;
rc = msm_vidc_alloc_and_queue_session_internal_buffers(inst,
MSM_VIDC_BUF_PERSIST);
if (rc)
goto unlock;
return rc;
}
}
@@ -452,33 +475,26 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
rc = msm_vdec_streamon_input(inst);
else if (is_encode_session(inst))
rc = msm_venc_streamon_input(inst);
else
goto unlock;
} else if (q->type == OUTPUT_MPLANE) {
if (is_decode_session(inst))
rc = msm_vdec_streamon_output(inst);
else if (is_encode_session(inst))
rc = msm_venc_streamon_output(inst);
else
goto unlock;
} else {
i_vpr_e(inst, "%s: invalid type %d\n", __func__, q->type);
goto unlock;
}
if (rc)
goto unlock;
return rc;
/* print final buffer counts & size details */
msm_vidc_print_buffer_info(inst);
buf_type = v4l2_type_to_driver(q->type, __func__);
if (!buf_type)
goto unlock;
return -EINVAL;
/* queue pending buffers */
rc = msm_vidc_queue_deferred_buffers(inst, buf_type);
if (rc)
goto unlock;
return rc;
/* initialize statistics timer(one time) */
if (!inst->stats.time_ms)
@@ -487,71 +503,40 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
/* schedule to print buffer statistics */
rc = schedule_stats_work(inst);
if (rc)
goto unlock;
return rc;
if ((q->type == INPUT_MPLANE && inst->bufq[OUTPUT_PORT].vb2q->streaming) ||
(q->type == OUTPUT_MPLANE && inst->bufq[INPUT_PORT].vb2q->streaming)) {
rc = msm_vidc_get_properties(inst);
if (rc)
goto unlock;
return rc;
}
i_vpr_h(inst, "Streamon: %s successful\n", v4l2_type_name(q->type));
unlock:
if (rc) {
i_vpr_e(inst, "Streamon: %s failed\n", v4l2_type_name(q->type));
msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
}
inst_unlock(inst, __func__);
client_unlock(inst, __func__);
put_inst(inst);
return rc;
}
void msm_vidc_stop_streaming(struct vb2_queue *q)
int msm_vidc_stop_streaming(struct msm_vidc_inst *inst, struct vb2_queue *q)
{
int rc = 0;
struct msm_vidc_inst *inst;
enum msm_vidc_allow allow;
if (!q || !q->drv_priv) {
d_vpr_e("%s: invalid input, q = %pK\n", __func__, q);
return;
}
inst = q->drv_priv;
inst = get_inst_ref(g_core, inst);
if (!inst || !inst->core) {
if (!inst || !q) {
d_vpr_e("%s: invalid params\n", __func__);
return;
return -EINVAL;
}
client_lock(inst, __func__);
inst_lock(inst, __func__);
if (q->type == INPUT_META_PLANE || q->type == OUTPUT_META_PLANE) {
i_vpr_h(inst, "%s: nothing to stop on %s\n",
__func__, v4l2_type_name(q->type));
rc = 0;
goto unlock;
return 0;
}
allow = msm_vidc_allow_streamoff(inst, q->type);
if (allow == MSM_VIDC_DISALLOW) {
rc = -EBUSY;
goto unlock;
} else if (allow == MSM_VIDC_IGNORE) {
rc = 0;
goto unlock;
} else if (allow != MSM_VIDC_ALLOW) {
rc = -EINVAL;
goto unlock;
if (q->type != INPUT_MPLANE && q->type != OUTPUT_MPLANE) {
i_vpr_e(inst, "%s: invalid type %d\n", __func__, q->type);
return -EINVAL;
}
if (!is_decode_session(inst) && !is_encode_session(inst)) {
i_vpr_e(inst, "%s: invalid session %d\n",
__func__, inst->domain);
rc = -EINVAL;
goto unlock;
i_vpr_e(inst, "%s: invalid session %d\n", __func__, inst->domain);
return -EINVAL;
}
i_vpr_h(inst, "Streamoff: %s\n", v4l2_type_name(q->type));
@@ -565,13 +550,9 @@ void msm_vidc_stop_streaming(struct vb2_queue *q)
rc = msm_vdec_streamoff_output(inst);
else if (is_encode_session(inst))
rc = msm_venc_streamoff_output(inst);
} else {
i_vpr_e(inst, "%s: invalid type %d\n", __func__, q->type);
rc = -EINVAL;
goto unlock;
}
if (rc)
goto unlock;
return rc;
/* Input port streamoff */
if (q->type == INPUT_MPLANE) {
@@ -583,19 +564,43 @@ void msm_vidc_stop_streaming(struct vb2_queue *q)
}
i_vpr_h(inst, "Streamoff: %s successful\n", v4l2_type_name(q->type));
return rc;
}
unlock:
void msm_vb2_stop_streaming(struct vb2_queue *q)
{
struct msm_vidc_inst *inst;
int rc = 0;
if (!q || !q->drv_priv) {
d_vpr_e("%s: invalid input, q = %pK\n", __func__, q);
return;
}
inst = q->drv_priv;
inst = get_inst_ref(g_core, inst);
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return;
}
client_lock(inst, __func__);
inst_lock(inst, __func__);
rc = inst->event_handle(inst, MSM_VIDC_STREAMOFF, q);
if (rc) {
i_vpr_e(inst, "Streamoff: %s failed\n", v4l2_type_name(q->type));
msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
goto unlock;
}
unlock:
inst_unlock(inst, __func__);
client_unlock(inst, __func__);
put_inst(inst);
return;
}
void msm_vidc_buf_queue(struct vb2_buffer *vb2)
void msm_vb2_buf_queue(struct vb2_buffer *vb2)
{
int rc = 0;
struct msm_vidc_inst *inst;
@@ -700,11 +705,11 @@ unlock:
put_inst(inst);
}
void msm_vidc_buf_cleanup(struct vb2_buffer *vb)
void msm_vb2_buf_cleanup(struct vb2_buffer *vb)
{
}
int msm_vidc_buf_out_validate(struct vb2_buffer *vb)
int msm_vb2_buf_out_validate(struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
@@ -712,7 +717,7 @@ int msm_vidc_buf_out_validate(struct vb2_buffer *vb)
return 0;
}
void msm_vidc_buf_request_complete(struct vb2_buffer *vb)
void msm_vb2_request_complete(struct vb2_buffer *vb)
{
struct msm_vidc_inst *inst = vb2_get_drv_priv(vb->vb2_queue);

Zobrazit soubor

@@ -509,7 +509,7 @@ int venus_hfi_queue_init(struct msm_vidc_core *core)
}
memset(&mem, 0, sizeof(mem));
mem.type = MSM_VIDC_BUF_QUEUE;
mem.type = MSM_VIDC_BUF_INTERFACE_QUEUE;
mem.region = MSM_VIDC_NON_SECURE;
mem.size = TOTAL_QSIZE;
mem.secure = false;
@@ -570,7 +570,7 @@ int venus_hfi_queue_init(struct msm_vidc_core *core)
/* sfr buffer */
memset(&mem, 0, sizeof(mem));
mem.type = MSM_VIDC_BUF_QUEUE;
mem.type = MSM_VIDC_BUF_INTERFACE_QUEUE;
mem.region = MSM_VIDC_NON_SECURE;
mem.size = ALIGNED_SFR_SIZE;
mem.secure = false;
@@ -610,7 +610,7 @@ int venus_hfi_queue_init(struct msm_vidc_core *core)
/* allocate 4k buffer for HFI_MMAP_ADDR */
memset(&mem, 0, sizeof(mem));
mem.type = MSM_VIDC_BUF_QUEUE;
mem.type = MSM_VIDC_BUF_INTERFACE_QUEUE;
mem.region = MSM_VIDC_NON_SECURE;
mem.size = ALIGNED_MMAP_BUF_SIZE;
mem.secure = false;