video: driver: fix static and dynamic property setting sequence

Added changes to reuse caps_list for setting static properties
and also modified dynamic property setting sequence. Removed
redundant implementations.

Change-Id: I5829d3c98b0159916d7794f43e445a6191050182
Signed-off-by: Govindaraj Rajagopal <quic_grajagop@quicinc.com>
This commit is contained in:
Govindaraj Rajagopal
2022-02-04 21:16:37 +05:30
parent 2d2e07aee9
commit 0fde3a9aca
6 changed files with 384 additions and 361 deletions

View File

@@ -43,7 +43,7 @@ int msm_vidc_adjust_cac(void *instance, struct v4l2_ctrl *ctrl);
int msm_vidc_adjust_bitrate_boost(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_bitrate_boost(void *instance, struct v4l2_ctrl *ctrl);
int msm_vidc_adjust_min_quality(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_min_quality(void *instance, struct v4l2_ctrl *ctrl);
int msm_vidc_adjust_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl);
int msm_vidc_adjust_v4l2_properties(struct msm_vidc_inst *inst); int msm_vidc_adjust_set_v4l2_properties(struct msm_vidc_inst *inst);
int msm_vidc_prepare_dependency_list(struct msm_vidc_inst *inst); int msm_vidc_prepare_dependency_list(struct msm_vidc_inst *inst);
int msm_vidc_adjust_session_priority(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_session_priority(void *instance, struct v4l2_ctrl *ctrl);
int msm_vidc_adjust_roi_info(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_roi_info(void *instance, struct v4l2_ctrl *ctrl);
@@ -109,7 +109,6 @@ int msm_vidc_set_s32(void *instance,
enum msm_vidc_inst_capability_type cap_id); enum msm_vidc_inst_capability_type cap_id);
int msm_vidc_set_q16(void *instance, int msm_vidc_set_q16(void *instance,
enum msm_vidc_inst_capability_type cap_id); enum msm_vidc_inst_capability_type cap_id);
int msm_vidc_set_v4l2_properties(struct msm_vidc_inst *inst);
int msm_vidc_v4l2_menu_to_hfi(struct msm_vidc_inst *inst, int msm_vidc_v4l2_menu_to_hfi(struct msm_vidc_inst *inst,
enum msm_vidc_inst_capability_type cap_id, u32 *value); enum msm_vidc_inst_capability_type cap_id, u32 *value);
int msm_vidc_v4l2_to_hfi_enum(struct msm_vidc_inst *inst, int msm_vidc_v4l2_to_hfi_enum(struct msm_vidc_inst *inst,

View File

@@ -441,8 +441,6 @@ int msm_vidc_ts_reorder_remove_timestamp(struct msm_vidc_inst *inst, u64 timesta
int msm_vidc_ts_reorder_get_first_timestamp(struct msm_vidc_inst *inst, u64 *timestamp); int msm_vidc_ts_reorder_get_first_timestamp(struct msm_vidc_inst *inst, u64 *timestamp);
int msm_vidc_ts_reorder_flush(struct msm_vidc_inst *inst); int msm_vidc_ts_reorder_flush(struct msm_vidc_inst *inst);
const char *buf_name(enum msm_vidc_buffer_type type); const char *buf_name(enum msm_vidc_buffer_type type);
void msm_vidc_free_capabililty_list(struct msm_vidc_inst *inst,
enum msm_vidc_ctrl_list_type list_type);
bool res_is_greater_than(u32 width, u32 height, bool res_is_greater_than(u32 width, u32 height,
u32 ref_width, u32 ref_height); u32 ref_width, u32 ref_height);
bool res_is_greater_than_or_equal_to(u32 width, u32 height, bool res_is_greater_than_or_equal_to(u32 width, u32 height,

View File

@@ -291,11 +291,6 @@ enum msm_vidc_matrix_coefficients {
MSM_VIDC_MATRIX_COEFF_BT2100 = 14, MSM_VIDC_MATRIX_COEFF_BT2100 = 14,
}; };
enum msm_vidc_ctrl_list_type {
CHILD_LIST = BIT(0),
FW_LIST = BIT(1),
};
enum msm_vidc_core_capability_type { enum msm_vidc_core_capability_type {
CORE_CAP_NONE = 0, CORE_CAP_NONE = 0,
ENC_CODECS, ENC_CODECS,

View File

@@ -1002,15 +1002,11 @@ int msm_venc_streamon_output(struct msm_vidc_inst *inst)
return -EINVAL; return -EINVAL;
} }
rc = msm_vidc_adjust_v4l2_properties(inst);
if (rc)
goto error;
rc = msm_venc_set_output_properties(inst); rc = msm_venc_set_output_properties(inst);
if (rc) if (rc)
goto error; goto error;
rc = msm_vidc_set_v4l2_properties(inst); rc = msm_vidc_adjust_set_v4l2_properties(inst);
if (rc) if (rc)
goto error; goto error;

View File

@@ -214,6 +214,81 @@ static const char * const * msm_vidc_get_qmenu_type(
} }
} }
static inline bool has_parents(struct msm_vidc_inst_cap *cap)
{
return !!cap->parents[0];
}
static inline bool has_childrens(struct msm_vidc_inst_cap *cap)
{
return !!cap->children[0];
}
static inline bool is_root(struct msm_vidc_inst_cap *cap)
{
return !has_parents(cap);
}
static inline bool is_valid_cap_id(enum msm_vidc_inst_capability_type cap_id)
{
return cap_id > INST_CAP_NONE && cap_id < INST_CAP_MAX;
}
static inline bool is_valid_cap(struct msm_vidc_inst_cap *cap)
{
return is_valid_cap_id(cap->cap_id);
}
static inline bool is_all_parents_visited(
struct msm_vidc_inst_cap *cap, bool lookup[INST_CAP_MAX]) {
bool found = true;
int i;
for (i = 0; i < MAX_CAP_PARENTS; i++) {
if (cap->parents[i] == INST_CAP_NONE)
continue;
if (!lookup[cap->parents[i]]) {
found = false;
break;
}
}
return found;
}
static int add_node_list(struct list_head *list, enum msm_vidc_inst_capability_type cap_id)
{
struct msm_vidc_inst_cap_entry *entry;
entry = kzalloc(sizeof(struct msm_vidc_inst_cap_entry), GFP_KERNEL);
if (!entry) {
d_vpr_e("%s: msm_vidc_inst_cap_entry alloc failed\n", __func__);
return -EINVAL;
}
INIT_LIST_HEAD(&entry->list);
entry->cap_id = cap_id;
list_add_tail(&entry->list, list);
return 0;
}
static int add_node(
struct list_head *list, struct msm_vidc_inst_cap *rcap, bool lookup[INST_CAP_MAX])
{
int rc = 0;
if (lookup[rcap->cap_id])
return 0;
rc = add_node_list(list, rcap->cap_id);
if (rc)
return rc;
lookup[rcap->cap_id] = true;
return 0;
}
static int msm_vidc_packetize_control(struct msm_vidc_inst *inst, static int msm_vidc_packetize_control(struct msm_vidc_inst *inst,
enum msm_vidc_inst_capability_type cap_id, u32 payload_type, enum msm_vidc_inst_capability_type cap_id, u32 payload_type,
void *hfi_val, u32 payload_size, const char *func) void *hfi_val, u32 payload_size, const char *func)
@@ -274,34 +349,25 @@ static enum msm_vidc_inst_capability_type msm_vidc_get_cap_id(
return cap_id; return cap_id;
} }
static int msm_vidc_add_capid_to_list(struct msm_vidc_inst *inst, static int msm_vidc_add_capid_to_fw_list(struct msm_vidc_inst *inst,
enum msm_vidc_inst_capability_type cap_id, enum msm_vidc_inst_capability_type cap_id)
enum msm_vidc_ctrl_list_type type)
{ {
struct msm_vidc_inst_cap_entry *entry = NULL, *curr_node = NULL; struct msm_vidc_inst_cap_entry *entry = NULL;
int rc = 0;
/* skip adding if cap_id already present in list */ /* skip adding if cap_id already present in firmware list */
if (type & FW_LIST) { list_for_each_entry(entry, &inst->firmware_list, list) {
list_for_each_entry(curr_node, &inst->firmware_list, list) { if (entry->cap_id == cap_id) {
if (curr_node->cap_id == cap_id) { i_vpr_l(inst,
i_vpr_l(inst, "%s: cap[%d] %s already present in fw list\n",
"%s: cap[%d] %s already present in FW_LIST\n", __func__, cap_id, cap_name(cap_id));
__func__, cap_id, cap_name(cap_id)); return 0;
return 0;
}
} }
} }
entry = kzalloc(sizeof(*entry), GFP_ATOMIC); rc = add_node_list(&inst->firmware_list, cap_id);
if (!entry) { if (rc)
i_vpr_e(inst, "%s: alloc failed\n", __func__); return rc;
return -ENOMEM;
}
entry->cap_id = cap_id;
if (type & CHILD_LIST)
list_add_tail(&entry->list, &inst->children_list);
if (type & FW_LIST)
list_add_tail(&entry->list, &inst->firmware_list);
return 0; return 0;
} }
@@ -309,19 +375,23 @@ static int msm_vidc_add_capid_to_list(struct msm_vidc_inst *inst,
static int msm_vidc_add_children(struct msm_vidc_inst *inst, static int msm_vidc_add_children(struct msm_vidc_inst *inst,
enum msm_vidc_inst_capability_type cap_id) enum msm_vidc_inst_capability_type cap_id)
{ {
int rc = 0; struct msm_vidc_inst_cap *cap;
int i = 0; int i, rc = 0;
struct msm_vidc_inst_capability *capability = inst->capabilities;
while (i < MAX_CAP_CHILDREN && cap = &inst->capabilities->cap[cap_id];
capability->cap[cap_id].children[i]) {
rc = msm_vidc_add_capid_to_list(inst, for (i = 0; i < MAX_CAP_CHILDREN; i++) {
capability->cap[cap_id].children[i], if (!cap->children[i])
CHILD_LIST); break;
if (!is_valid_cap_id(cap->children[i]))
continue;
rc = add_node_list(&inst->children_list, cap->children[i]);
if (rc) if (rc)
return rc; return rc;
i++;
} }
return rc; return rc;
} }
@@ -426,107 +496,208 @@ exit:
return 0; return 0;
} }
static int msm_vidc_adjust_property(struct msm_vidc_inst *inst, static int msm_vidc_adjust_cap(struct msm_vidc_inst *inst,
enum msm_vidc_inst_capability_type cap_id) enum msm_vidc_inst_capability_type cap_id,
struct v4l2_ctrl *ctrl, const char *func)
{ {
struct msm_vidc_inst_cap *cap;
int rc = 0; int rc = 0;
struct msm_vidc_inst_capability *capability;
capability = inst->capabilities; /* validate cap_id */
if (!is_valid_cap_id(cap_id))
/*
* skip for uninitialized cap properties.
* Eg: Skip Tramform 8x8 cap that is uninitialized for HEVC codec
*/
if (!capability->cap[cap_id].cap_id)
return 0; return 0;
if (capability->cap[cap_id].adjust) { /* validate cap */
rc = capability->cap[cap_id].adjust(inst, NULL); cap = &inst->capabilities->cap[cap_id];
if (rc) if (!is_valid_cap(cap))
goto exit; return 0;
/* check if adjust supported */
if (!cap->adjust) {
if (ctrl)
msm_vidc_update_cap_value(inst, cap_id, ctrl->val, func);
return 0;
} }
/* add children cap_id's to chidren list */ /* call adjust */
rc = msm_vidc_add_children(inst, cap_id); rc = cap->adjust(inst, ctrl);
if (rc) if (rc) {
goto exit; i_vpr_e(inst, "%s: adjust cap failed for %s\n", func, cap_name(cap_id));
return rc;
}
/* add cap_id to firmware list */ return rc;
rc = msm_vidc_add_capid_to_list(inst, cap_id, FW_LIST); }
if (rc)
goto exit;
return 0; static int msm_vidc_set_cap(struct msm_vidc_inst *inst,
enum msm_vidc_inst_capability_type cap_id,
const char *func)
{
struct msm_vidc_inst_cap *cap;
int rc = 0;
/* validate cap_id */
if (!is_valid_cap_id(cap_id))
return 0;
/* validate cap */
cap = &inst->capabilities->cap[cap_id];
if (!is_valid_cap(cap))
return 0;
/* check if set supported */
if (!cap->set)
return 0;
/* call set */
rc = cap->set(inst, cap_id);
if (rc) {
i_vpr_e(inst, "%s: set cap failed for %s\n", func, cap_name(cap_id));
return rc;
}
exit:
return rc; return rc;
} }
static int msm_vidc_adjust_dynamic_property(struct msm_vidc_inst *inst, static int msm_vidc_adjust_dynamic_property(struct msm_vidc_inst *inst,
enum msm_vidc_inst_capability_type cap_id, struct v4l2_ctrl *ctrl) enum msm_vidc_inst_capability_type cap_id, struct v4l2_ctrl *ctrl)
{ {
int rc = 0; struct msm_vidc_inst_cap_entry *entry = NULL, *temp = NULL;
struct msm_vidc_inst_capability *capability; struct msm_vidc_inst_capability *capability;
s32 prev_value; s32 prev_value;
int rc = 0;
if (!inst || !inst->capabilities || !ctrl) {
d_vpr_e("%s: invalid param\n", __func__);
return -EINVAL;
}
capability = inst->capabilities; capability = inst->capabilities;
/*
* ctrl is NULL for children adjustment calls /* sanitize cap_id */
* When a dynamic control having children is adjusted, check if dynamic if (!is_valid_cap_id(cap_id)) {
* adjustment is allowed for its children. i_vpr_e(inst, "%s: invalid cap_id %u\n", __func__, cap_id);
*/ return -EINVAL;
}
if (!(capability->cap[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED)) { if (!(capability->cap[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED)) {
i_vpr_h(inst, i_vpr_h(inst,
"%s: dynamic setting of cap[%d] %s is not allowed\n", "%s: dynamic setting of cap[%d] %s is not allowed\n",
__func__, cap_id, cap_name(cap_id)); __func__, cap_id, cap_name(cap_id));
return 0; return -EBUSY;
} }
i_vpr_h(inst, "%s: cap[%d] %s\n", __func__, cap_id, cap_name(cap_id));
/*
* if ctrl is NULL, it is children of some parent, and hence,
* must have an adjust function defined
*/
if (!ctrl && !capability->cap[cap_id].adjust) {
i_vpr_e(inst,
"%s: child cap[%d] %s must have ajdust function\n",
__func__, capability->cap[cap_id].cap_id,
cap_name(capability->cap[cap_id].cap_id));
return -EINVAL;
}
prev_value = capability->cap[cap_id].value; prev_value = capability->cap[cap_id].value;
rc = msm_vidc_adjust_cap(inst, cap_id, ctrl, __func__);
if (capability->cap[cap_id].adjust) { if (rc)
rc = capability->cap[cap_id].adjust(inst, ctrl); return rc;
if (rc)
goto exit;
} else if (ctrl) {
msm_vidc_update_cap_value(inst, cap_id, ctrl->val, __func__);
}
/* add children if cap value modified */
if (capability->cap[cap_id].value != prev_value) {
rc = msm_vidc_add_children(inst, cap_id);
if (rc)
goto exit;
}
if (capability->cap[cap_id].value == prev_value && cap_id == GOP_SIZE) { if (capability->cap[cap_id].value == prev_value && cap_id == GOP_SIZE) {
/* /*
* Ignore setting same GOP size value to firmware to avoid * Ignore setting same GOP size value to firmware to avoid
* unnecessary generation of IDR frame. * unnecessary generation of IDR frame.
*/ */
goto exit; return 0;
} }
/* add cap_id to firmware list always */ /* add cap_id to firmware list always */
rc = msm_vidc_add_capid_to_list(inst, cap_id, FW_LIST); rc = msm_vidc_add_capid_to_fw_list(inst, cap_id);
if (rc) if (rc)
goto exit; goto error;
/* add children only if cap value modified */
if (capability->cap[cap_id].value == prev_value)
return 0;
rc = msm_vidc_add_children(inst, cap_id);
if (rc)
goto error;
list_for_each_entry_safe(entry, temp, &inst->children_list, list) {
if (!is_valid_cap_id(entry->cap_id)) {
rc = -EINVAL;
goto error;
}
if (!capability->cap[entry->cap_id].adjust) {
i_vpr_e(inst, "%s: child cap must have ajdust function %s\n",
__func__, cap_name(entry->cap_id));
rc = -EINVAL;
goto error;
}
prev_value = capability->cap[entry->cap_id].value;
rc = msm_vidc_adjust_cap(inst, entry->cap_id, NULL, __func__);
if (rc)
goto error;
/* add children if cap value modified */
if (capability->cap[entry->cap_id].value != prev_value) {
/* add cap_id to firmware list always */
rc = msm_vidc_add_capid_to_fw_list(inst, entry->cap_id);
if (rc)
goto error;
rc = msm_vidc_add_children(inst, entry->cap_id);
if (rc)
goto error;
}
list_del_init(&entry->list);
kfree(entry);
}
/* expecting children_list to be empty */
if (!list_empty(&inst->children_list)) {
i_vpr_e(inst, "%s: child_list is not empty\n", __func__);
rc = -EINVAL;
goto error;
}
return 0; return 0;
error:
list_for_each_entry_safe(entry, temp, &inst->children_list, list) {
i_vpr_e(inst, "%s: child list: %s\n", __func__, cap_name(entry->cap_id));
list_del_init(&entry->list);
kfree(entry);
}
list_for_each_entry_safe(entry, temp, &inst->firmware_list, list) {
i_vpr_e(inst, "%s: fw list: %s\n", __func__, cap_name(entry->cap_id));
list_del_init(&entry->list);
kfree(entry);
}
return rc;
}
static int msm_vidc_set_dynamic_property(struct msm_vidc_inst *inst)
{
struct msm_vidc_inst_cap_entry *entry = NULL, *temp = NULL;
int rc = 0;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
i_vpr_h(inst, "%s()\n", __func__);
list_for_each_entry_safe(entry, temp, &inst->firmware_list, list) {
rc = msm_vidc_set_cap(inst, entry->cap_id, __func__);
if (rc)
goto error;
list_del_init(&entry->list);
kfree(entry);
}
return 0;
error:
list_for_each_entry_safe(entry, temp, &inst->firmware_list, list) {
i_vpr_e(inst, "%s: fw list: %s\n", __func__, cap_name(entry->cap_id));
list_del_init(&entry->list);
kfree(entry);
}
exit:
return rc; return rc;
} }
@@ -818,12 +989,86 @@ int msm_v4l2_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
return rc; return rc;
} }
static int msm_vidc_update_static_property(struct msm_vidc_inst *inst,
enum msm_vidc_inst_capability_type cap_id, struct v4l2_ctrl *ctrl)
{
int rc = 0;
if (!inst || !ctrl) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
/* update value to db */
msm_vidc_update_cap_value(inst, cap_id, ctrl->val, __func__);
if (ctrl->id == V4L2_CID_MPEG_VIDC_SECURE) {
if (ctrl->val) {
rc = msm_vidc_allow_secure_session(inst);
if (rc)
return rc;
}
}
if (ctrl->id == V4L2_CID_ROTATE) {
struct v4l2_format *output_fmt;
output_fmt = &inst->fmts[OUTPUT_PORT];
rc = msm_venc_s_fmt_output(inst, output_fmt);
if (rc)
return rc;
}
if (ctrl->id == V4L2_CID_MPEG_VIDC_MIN_BITSTREAM_SIZE_OVERWRITE) {
rc = msm_vidc_update_bitstream_buffer_size(inst);
if (rc)
return rc;
}
if (ctrl->id == V4L2_CID_MPEG_VIDC_PRIORITY) {
rc = msm_vidc_adjust_session_priority(inst, ctrl);
if (rc)
return rc;
/**
* This is the last static s_ctrl from client(commit point). So update
* input & output counts to reflect final buffer counts based on dcvs
* & decoder_batching enable/disable. So client is expected to query
* for final counts after setting priority control.
*/
if (is_decode_session(inst))
inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
msm_vidc_allow_dcvs(inst);
}
if (is_meta_ctrl(ctrl->id)) {
if (cap_id == META_DPB_TAG_LIST) {
/*
* To subscribe HFI_PROP_DPB_TAG_LIST
* data in FBD, HFI_PROP_BUFFER_TAG data
* must be delivered via FTB. Hence, update
* META_OUTPUT_BUF_TAG when META_DPB_TAG_LIST
* is updated.
*/
msm_vidc_update_cap_value(inst, META_OUTPUT_BUF_TAG,
ctrl->val, __func__);
}
rc = msm_vidc_update_meta_port_settings(inst);
if (rc)
return rc;
}
rc = msm_vidc_update_buffer_count_if_needed(inst, ctrl);
if (rc)
return rc;
return rc;
}
int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl) int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
{ {
int rc = 0; int rc = 0;
struct msm_vidc_inst *inst; struct msm_vidc_inst *inst;
enum msm_vidc_inst_capability_type cap_id; enum msm_vidc_inst_capability_type cap_id;
struct msm_vidc_inst_cap_entry *curr_node = NULL, *tmp_node = NULL;
struct msm_vidc_inst_capability *capability; struct msm_vidc_inst_capability *capability;
if (!ctrl) { if (!ctrl) {
@@ -841,14 +1086,14 @@ int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
capability = inst->capabilities; capability = inst->capabilities;
i_vpr_h(inst, "%s: state %d, name %s, id 0x%x value %d\n", i_vpr_h(inst, "%s: state %s, name %s, id 0x%x value %d\n",
__func__, inst->state, ctrl->name, ctrl->id, ctrl->val); __func__, state_name(inst->state), ctrl->name, ctrl->id, ctrl->val);
if (!msm_vidc_allow_s_ctrl(inst, ctrl->id)) if (!msm_vidc_allow_s_ctrl(inst, ctrl->id))
return -EINVAL; return -EINVAL;
cap_id = msm_vidc_get_cap_id(inst, ctrl->id); cap_id = msm_vidc_get_cap_id(inst, ctrl->id);
if (cap_id == INST_CAP_NONE) { if (!is_valid_cap_id(cap_id)) {
i_vpr_e(inst, "%s: could not find cap_id for ctrl %s\n", i_vpr_e(inst, "%s: could not find cap_id for ctrl %s\n",
__func__, ctrl->name); __func__, ctrl->name);
return -EINVAL; return -EINVAL;
@@ -865,109 +1110,24 @@ int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
return rc; return rc;
} }
/* mark client set flag */
capability->cap[cap_id].flags |= CAP_FLAG_CLIENT_SET; capability->cap[cap_id].flags |= CAP_FLAG_CLIENT_SET;
/* Static setting */
if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) { if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) {
msm_vidc_update_cap_value(inst, cap_id, ctrl->val, __func__); /* static case */
rc = msm_vidc_update_static_property(inst, cap_id, ctrl);
if (ctrl->id == V4L2_CID_MPEG_VIDC_SECURE) { if (rc)
if (ctrl->val) { return rc;
rc = msm_vidc_allow_secure_session(inst); } else {
if (rc) /* dynamic case */
return rc; rc = msm_vidc_adjust_dynamic_property(inst, cap_id, ctrl);
}
}
if (ctrl->id == V4L2_CID_ROTATE) {
struct v4l2_format *output_fmt;
output_fmt = &inst->fmts[OUTPUT_PORT];
rc = msm_venc_s_fmt_output(inst, output_fmt);
if (rc)
return rc;
}
if (ctrl->id == V4L2_CID_MPEG_VIDC_MIN_BITSTREAM_SIZE_OVERWRITE) {
rc = msm_vidc_update_bitstream_buffer_size(inst);
if (rc)
return rc;
}
if (ctrl->id == V4L2_CID_MPEG_VIDC_PRIORITY) {
rc = msm_vidc_adjust_session_priority(inst, ctrl);
if (rc)
return rc;
/**
* This is the last static s_ctrl from client(commit point). So update
* input & output counts to reflect final buffer counts based on dcvs
* & decoder_batching enable/disable. So client is expected to query
* for final counts after setting priority control.
*/
if (is_decode_session(inst))
inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
msm_vidc_allow_dcvs(inst);
}
if (is_meta_ctrl(ctrl->id)) {
if (cap_id == META_DPB_TAG_LIST) {
/*
* To subscribe HFI_PROP_DPB_TAG_LIST
* data in FBD, HFI_PROP_BUFFER_TAG data
* must be delivered via FTB. Hence, update
* META_OUTPUT_BUF_TAG when META_DPB_TAG_LIST
* is updated.
*/
msm_vidc_update_cap_value(inst, META_OUTPUT_BUF_TAG,
ctrl->val, __func__);
}
rc = msm_vidc_update_meta_port_settings(inst);
if (rc)
return rc;
}
rc = msm_vidc_update_buffer_count_if_needed(inst, ctrl);
if (rc) if (rc)
return rc; return rc;
return 0; rc = msm_vidc_set_dynamic_property(inst);
}
/* check if dynamic adjustment is allowed */
if (inst->bufq[OUTPUT_PORT].vb2q->streaming &&
!(capability->cap[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED)) {
i_vpr_e(inst,
"%s: dynamic setting of cap[%d] %s is not allowed\n",
__func__, cap_id, cap_name(cap_id));
return -EBUSY;
}
rc = msm_vidc_adjust_dynamic_property(inst, cap_id, ctrl);
if (rc)
goto exit;
/* adjust all children if any */
list_for_each_entry_safe(curr_node, tmp_node,
&inst->children_list, list) {
rc = msm_vidc_adjust_dynamic_property(
inst, curr_node->cap_id, NULL);
if (rc) if (rc)
goto exit; return rc;
list_del(&curr_node->list);
kfree(curr_node);
} }
/* Dynamic set control ASAP */
rc = msm_vidc_set_v4l2_properties(inst);
if (rc) {
i_vpr_e(inst, "%s: setting %s failed\n",
__func__, ctrl->name);
goto exit;
}
exit:
if (rc)
msm_vidc_free_capabililty_list(inst, CHILD_LIST | FW_LIST);
return rc; return rc;
} }
@@ -2480,65 +2640,6 @@ int msm_vidc_adjust_roi_info(void *instance, struct v4l2_ctrl *ctrl)
return 0; return 0;
} }
static inline bool has_parents(struct msm_vidc_inst_cap *cap)
{
return !!cap->parents[0];
}
static inline bool has_childrens(struct msm_vidc_inst_cap *cap)
{
return !!cap->children[0];
}
static inline bool is_root(struct msm_vidc_inst_cap *cap)
{
return !has_parents(cap);
}
static inline bool is_valid_cap(struct msm_vidc_inst_cap *cap)
{
return cap->cap_id != INST_CAP_NONE;
}
static inline bool is_all_parents_visited(
struct msm_vidc_inst_cap *cap, bool lookup[INST_CAP_MAX]) {
bool found = true;
int i;
for (i = 0; i < MAX_CAP_PARENTS; i++) {
if (cap->parents[i] == INST_CAP_NONE)
continue;
if (!lookup[cap->parents[i]]) {
found = false;
break;
}
}
return found;
}
static int add_node(
struct list_head *list, struct msm_vidc_inst_cap *rcap, bool lookup[INST_CAP_MAX])
{
struct msm_vidc_inst_cap_entry *entry;
if (lookup[rcap->cap_id])
return 0;
entry = kzalloc(sizeof(struct msm_vidc_inst_cap_entry), GFP_KERNEL);
if (!entry) {
d_vpr_e("%s: msm_vidc_inst_cap_entry alloc failed\n", __func__);
return -EINVAL;
}
INIT_LIST_HEAD(&entry->list);
entry->cap_id = rcap->cap_id;
lookup[rcap->cap_id] = true;
list_add_tail(&entry->list, list);
return 0;
}
int msm_vidc_prepare_dependency_list(struct msm_vidc_inst *inst) int msm_vidc_prepare_dependency_list(struct msm_vidc_inst *inst)
{ {
struct list_head root_list, opt_list; struct list_head root_list, opt_list;
@@ -2599,6 +2700,10 @@ int msm_vidc_prepare_dependency_list(struct msm_vidc_inst *inst)
for (i = 0; i < MAX_CAP_CHILDREN; i++) { for (i = 0; i < MAX_CAP_CHILDREN; i++) {
if (!rcap->children[i]) if (!rcap->children[i])
break; break;
if (!is_valid_cap_id(rcap->children[i]))
continue;
cap = &capability->cap[rcap->children[i]]; cap = &capability->cap[rcap->children[i]];
if (!is_valid_cap(cap)) if (!is_valid_cap(cap))
continue; continue;
@@ -2693,57 +2798,36 @@ error:
/* /*
* Loop over instance capabilities from caps_list * Loop over instance capabilities from caps_list
* and call adjust function, where * and call adjust and set function
* - adjust current capability value
* - update tail of instance children list with capability children
* - update instance firmware list with current capability id
* Now, loop over child list and call its adjust function
*/ */
int msm_vidc_adjust_v4l2_properties(struct msm_vidc_inst *inst) int msm_vidc_adjust_set_v4l2_properties(struct msm_vidc_inst *inst)
{ {
struct msm_vidc_inst_cap_entry *entry = NULL, *temp = NULL;
int rc = 0; int rc = 0;
struct msm_vidc_inst_cap_entry *curr_node = NULL, *tmp_node = NULL;
struct msm_vidc_inst_capability *capability;
if (!inst || !inst->capabilities) { if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
capability = inst->capabilities;
i_vpr_h(inst, "%s()\n", __func__); i_vpr_h(inst, "%s()\n", __func__);
list_for_each_entry_safe(curr_node, tmp_node, &inst->caps_list, list) {
/* adjust all possible caps from caps_list */
list_for_each_entry_safe(entry, temp, &inst->caps_list, list) {
i_vpr_l(inst, "%s: cap: id %3u, name %s\n", __func__, i_vpr_l(inst, "%s: cap: id %3u, name %s\n", __func__,
curr_node->cap_id, cap_name(curr_node->cap_id)); entry->cap_id, cap_name(entry->cap_id));
rc = msm_vidc_adjust_property(inst, curr_node->cap_id);
rc = msm_vidc_adjust_cap(inst, entry->cap_id, NULL, __func__);
if (rc) if (rc)
goto exit; return rc;
} }
/* /* set all caps from caps_list */
* children of all root controls are already list_for_each_entry_safe(entry, temp, &inst->caps_list, list) {
* added to inst->children list at this point rc = msm_vidc_set_cap(inst, entry->cap_id, __func__);
*/
list_for_each_entry_safe(curr_node, tmp_node,
&inst->children_list, list) {
/*
* call adjust for each child. Each child adjust
* will also update child list at the tail with
* its own children list.
* Also, if current control id value is updated,
* its entry should be added to fw list.
*/
rc = msm_vidc_adjust_property(inst, curr_node->cap_id);
if (rc) if (rc)
goto exit; return rc;
list_del(&curr_node->list);
kfree(curr_node);
} }
exit:
if (rc)
msm_vidc_free_capabililty_list(inst, CHILD_LIST | FW_LIST);
return rc; return rc;
} }
@@ -3847,41 +3931,6 @@ int msm_vidc_set_s32(void *instance,
return rc; return rc;
} }
int msm_vidc_set_v4l2_properties(struct msm_vidc_inst *inst)
{
int rc = 0;
struct msm_vidc_inst_capability *capability;
struct msm_vidc_inst_cap_entry *curr_node = NULL, *tmp_node = NULL;
if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
i_vpr_h(inst, "%s()\n", __func__);
capability = inst->capabilities;
list_for_each_entry_safe(curr_node, tmp_node,
&inst->firmware_list, list) {
/* cap_id's like PIX_FMT etc may not have set functions */
if (!capability->cap[curr_node->cap_id].set)
continue;
rc = capability->cap[curr_node->cap_id].set(inst,
curr_node->cap_id);
if (rc)
goto exit;
list_del(&curr_node->list);
kfree(curr_node);
}
exit:
msm_vidc_free_capabililty_list(inst, FW_LIST);
return rc;
}
int msm_vidc_v4l2_menu_to_hfi(struct msm_vidc_inst *inst, int msm_vidc_v4l2_menu_to_hfi(struct msm_vidc_inst *inst,
enum msm_vidc_inst_capability_type cap_id, u32 *value) enum msm_vidc_inst_capability_type cap_id, u32 *value)
{ {

View File

@@ -3080,31 +3080,6 @@ static void msm_vidc_free_input_cr_list(struct msm_vidc_inst *inst)
INIT_LIST_HEAD(&inst->enc_input_crs); INIT_LIST_HEAD(&inst->enc_input_crs);
} }
void msm_vidc_free_capabililty_list(struct msm_vidc_inst *inst,
enum msm_vidc_ctrl_list_type list_type)
{
struct msm_vidc_inst_cap_entry *temp = NULL, *next = NULL;
if (list_type & CHILD_LIST) {
list_for_each_entry_safe(temp, next, &inst->children_list, list) {
list_del(&temp->list);
kfree(temp);
}
INIT_LIST_HEAD(&inst->children_list);
}
temp = NULL;
next = NULL;
if (list_type & FW_LIST) {
list_for_each_entry_safe(temp, next, &inst->firmware_list, list) {
list_del(&temp->list);
kfree(temp);
}
INIT_LIST_HEAD(&inst->firmware_list);
}
}
void msm_vidc_update_stats(struct msm_vidc_inst *inst, void msm_vidc_update_stats(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buf, enum msm_vidc_debugfs_event etype) struct msm_vidc_buffer *buf, enum msm_vidc_debugfs_event etype)
{ {
@@ -5362,6 +5337,18 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst)
kfree(work); kfree(work);
} }
list_for_each_entry_safe(entry, dummy_entry, &inst->firmware_list, list) {
i_vpr_e(inst, "%s: fw list: %s\n", __func__, cap_name(entry->cap_id));
list_del(&entry->list);
kfree(entry);
}
list_for_each_entry_safe(entry, dummy_entry, &inst->children_list, list) {
i_vpr_e(inst, "%s: child list: %s\n", __func__, cap_name(entry->cap_id));
list_del(&entry->list);
kfree(entry);
}
list_for_each_entry_safe(entry, dummy_entry, &inst->caps_list, list) { list_for_each_entry_safe(entry, dummy_entry, &inst->caps_list, list) {
list_del(&entry->list); list_del(&entry->list);
kfree(entry); kfree(entry);
@@ -5392,7 +5379,6 @@ static void msm_vidc_close_helper(struct kref *kref)
else if (is_encode_session(inst)) else if (is_encode_session(inst))
msm_venc_inst_deinit(inst); msm_venc_inst_deinit(inst);
msm_vidc_free_input_cr_list(inst); msm_vidc_free_input_cr_list(inst);
msm_vidc_free_capabililty_list(inst, CHILD_LIST | FW_LIST);
if (inst->response_workq) if (inst->response_workq)
destroy_workqueue(inst->response_workq); destroy_workqueue(inst->response_workq);
msm_vidc_remove_dangling_session(inst); msm_vidc_remove_dangling_session(inst);