diff --git a/driver/platform/waipio/src/msm_vidc_waipio.c b/driver/platform/waipio/src/msm_vidc_waipio.c index b9028c146d..ba04c8a19a 100644 --- a/driver/platform/waipio/src/msm_vidc_waipio.c +++ b/driver/platform/waipio/src/msm_vidc_waipio.c @@ -92,6 +92,7 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { * children, * adjust, set} */ + {CODEC}, {FRAME_WIDTH, ENC|DEC, CODECS_ALL, 128, 8192, 1, 1920}, {FRAME_HEIGHT, ENC|DEC, CODECS_ALL, 128, 8192, 1, 1080}, {PIX_FMTS, ENC, CODECS_ALL, @@ -133,46 +134,86 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { /* ((1920 * 1088) / 256) * 960 fps */ {MBPS, ENC|DEC, CODECS_ALL, 64, 7833600, 1, 7833600}, {FRAME_RATE, ENC|DEC, CODECS_ALL, 1, 960, 1, 30}, + {BIT_RATE, ENC|DEC, CODECS_ALL, 1, 220000000, 1, 20000000, V4L2_CID_MPEG_VIDEO_BITRATE, HFI_PROP_TOTAL_BITRATE, CAP_FLAG_DYNAMIC_ALLOWED, /* TO DO parents */ {0}, - {LAYER_BITRATE, SLICE_BYTE}}, + {LAYER_BITRATE, SLICE_BYTE}, + msm_vidc_adjust_bitrate, msm_vidc_set_s32}, {BIT_RATE, ENC, HEVC, 1, 160000000, 1, 20000000, V4L2_CID_MPEG_VIDEO_BITRATE, HFI_PROP_TOTAL_BITRATE, CAP_FLAG_DYNAMIC_ALLOWED, /* TO DO parents */{0}, - {LAYER_BITRATE, SLICE_BYTE}}, + {LAYER_BITRATE, SLICE_BYTE}, + msm_vidc_adjust_bitrate, msm_vidc_set_s32}, {ENTROPY_MODE, ENC, H264, V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, - V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC | - V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) | + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC), V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, HFI_PROP_CABAC_SESSION, CAP_FLAG_MENU, - {PROFILE}, - {BIT_RATE}}, + {CODEC, PROFILE}, + {BIT_RATE}, + msm_vidc_adjust_entropy_mode, msm_vidc_set_u32}, {PROFILE, ENC|DEC, H264, V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10, - V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE | - V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE | - V4L2_MPEG_VIDEO_H264_PROFILE_MAIN | - V4L2_MPEG_VIDEO_H264_PROFILE_HIGH | - V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10, + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10), V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, V4L2_CID_MPEG_VIDEO_H264_PROFILE, HFI_PROP_PROFILE, CAP_FLAG_ROOT | CAP_FLAG_MENU, {0}, - {ENTROPY_MODE}}, + {ENTROPY_MODE}, + NULL, msm_vidc_set_u32}, + + {LEVEL, ENC|DEC, H264, + V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + V4L2_MPEG_VIDEO_H264_LEVEL_6_2, + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_2), + V4L2_MPEG_VIDEO_H264_LEVEL_6_2, + V4L2_CID_MPEG_VIDEO_H264_LEVEL, HFI_PROP_LEVEL, + /* TO DO(AS) */ + CAP_FLAG_ROOT | CAP_FLAG_MENU, + {0}, + {0}, + NULL, msm_vidc_set_u32}, {CABAC_BITRATE, ENC, H264, 1, 160000000, 1, 20000000}, + {VBV_DELAY, ENC, CODECS_ALL, + 0, 1000, 500, 0, + V4L2_CID_MPEG_VIDEO_VBV_DELAY}, + {SCALE_X, ENC, CODECS_ALL, 8192, 65536, 1, 8192}, {SCALE_Y, ENC, CODECS_ALL, 8192, 65536, 1, 8192}, {SCALE_X, DEC, CODECS_ALL, 65536, 65536, 1, 65536}, diff --git a/driver/vidc/inc/msm_vidc_control.h b/driver/vidc/inc/msm_vidc_control.h index d438d2fc1a..5e9ed8a30e 100644 --- a/driver/vidc/inc/msm_vidc_control.h +++ b/driver/vidc/inc/msm_vidc_control.h @@ -17,5 +17,17 @@ enum msm_vidc_ctrl_list_type { int msm_vidc_ctrl_init(struct msm_vidc_inst *inst); int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_entropy_mode(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_properties(struct msm_vidc_inst *inst); +int msm_vidc_set_u32(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_s32(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_array(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_fw_list(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); #endif diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index 6c8865fa54..18459cbc19 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/driver/vidc/inc/msm_vidc_driver.h @@ -81,7 +81,7 @@ int msm_vidc_release_internal_buffers(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type buffer_type); int msm_vidc_add_session(struct msm_vidc_inst *inst); int msm_vidc_session_open(struct msm_vidc_inst *inst); -int msm_vidc_get_inst_capability(struct msm_vidc_inst *inst, u32 codec); +int msm_vidc_get_inst_capability(struct msm_vidc_inst *inst); int msm_vidc_core_init(struct msm_vidc_core *core); int msm_vidc_smmu_fault_handler(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags, void *data); diff --git a/driver/vidc/inc/msm_vidc_inst.h b/driver/vidc/inc/msm_vidc_inst.h index 39cf7d950d..e8b46f24ca 100644 --- a/driver/vidc/inc/msm_vidc_inst.h +++ b/driver/vidc/inc/msm_vidc_inst.h @@ -89,8 +89,8 @@ struct msm_vidc_inst { struct v4l2_fh event_handler; struct v4l2_ctrl **ctrls; u32 num_ctrls; - struct msm_vidc_inst_cap_entry child_ctrls; - struct msm_vidc_inst_cap_entry fw_ctrls; + struct msm_vidc_inst_cap_entry children; + struct msm_vidc_inst_cap_entry firmware; bool request; struct vb2_queue vb2q[MAX_PORT]; struct msm_vidc_crop crop; diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index ba8f6a69fd..99ba18e6c4 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -171,6 +171,7 @@ enum msm_vidc_core_capability_type { enum msm_vidc_inst_capability_type { INST_CAP_NONE = 0, + CODEC, FRAME_WIDTH, FRAME_HEIGHT, PIX_FMTS, @@ -190,6 +191,7 @@ enum msm_vidc_inst_capability_type { LAYER_BITRATE, ENTROPY_MODE, CABAC_BITRATE, + VBV_DELAY, LTR_COUNT, LCU_SIZE, POWER_SAVE_MBPS, @@ -248,7 +250,6 @@ struct msm_vidc_inst_cap { enum msm_vidc_inst_capability_type parents[MAX_CAP_PARENTS]; enum msm_vidc_inst_capability_type children[MAX_CAP_CHILDREN]; int (*adjust)(void *inst, - enum msm_vidc_inst_capability_type cap_id, struct v4l2_ctrl *ctrl); int (*set)(void *inst, enum msm_vidc_inst_capability_type cap_id); @@ -266,6 +267,7 @@ struct msm_vidc_core_capability { }; struct msm_vidc_inst_cap_entry { + /* list of struct msm_vidc_inst_cap_entry */ struct list_head list; enum msm_vidc_inst_capability_type cap_id; }; diff --git a/driver/vidc/inc/msm_vidc_platform.h b/driver/vidc/inc/msm_vidc_platform.h index 5e67dbe5dc..69769abc1a 100644 --- a/driver/vidc/inc/msm_vidc_platform.h +++ b/driver/vidc/inc/msm_vidc_platform.h @@ -30,7 +30,6 @@ struct msm_platform_inst_capability { enum msm_vidc_inst_capability_type parents[MAX_CAP_PARENTS]; enum msm_vidc_inst_capability_type children[MAX_CAP_CHILDREN]; int (*adjust)(void *inst, - enum msm_vidc_inst_capability_type cap_id, struct v4l2_ctrl *ctrl); int (*set)(void *inst, enum msm_vidc_inst_capability_type cap_id); diff --git a/driver/vidc/src/msm_vdec.c b/driver/vidc/src/msm_vdec.c index ed01898d29..fe1083b9d7 100644 --- a/driver/vidc/src/msm_vdec.c +++ b/driver/vidc/src/msm_vdec.c @@ -22,7 +22,8 @@ static int msm_vdec_codec_change(struct msm_vidc_inst *inst, u32 codec) d_vpr_h("%s()\n", __func__); - rc = msm_vidc_get_inst_capability(inst, codec); + inst->codec = get_vidc_codec_from_v4l2(codec); + rc = msm_vidc_get_inst_capability(inst); return rc; } diff --git a/driver/vidc/src/msm_venc.c b/driver/vidc/src/msm_venc.c index e9b655608f..a6e5007138 100644 --- a/driver/vidc/src/msm_venc.c +++ b/driver/vidc/src/msm_venc.c @@ -20,7 +20,8 @@ static int msm_venc_codec_change(struct msm_vidc_inst *inst, u32 codec) d_vpr_h("%s()\n", __func__); - rc = msm_vidc_get_inst_capability(inst, codec); + inst->codec = get_vidc_codec_from_v4l2(codec); + rc = msm_vidc_get_inst_capability(inst); return rc; } diff --git a/driver/vidc/src/msm_vidc.c b/driver/vidc/src/msm_vidc.c index ffa0d9a4f1..3c8f6630d9 100644 --- a/driver/vidc/src/msm_vidc.c +++ b/driver/vidc/src/msm_vidc.c @@ -699,8 +699,8 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) INIT_LIST_HEAD(&inst->maps.scratch_2.list); INIT_LIST_HEAD(&inst->maps.persist.list); INIT_LIST_HEAD(&inst->maps.persist_1.list); - INIT_LIST_HEAD(&inst->child_ctrls.list); - INIT_LIST_HEAD(&inst->fw_ctrls.list); + INIT_LIST_HEAD(&inst->children.list); + INIT_LIST_HEAD(&inst->firmware.list); inst->domain = session_type; inst->state = MSM_VIDC_OPEN; inst->request = false; diff --git a/driver/vidc/src/msm_vidc_control.c b/driver/vidc/src/msm_vidc_control.c index 5b78475a8b..3fa29e550b 100644 --- a/driver/vidc/src/msm_vidc_control.c +++ b/driver/vidc/src/msm_vidc_control.c @@ -9,6 +9,7 @@ #include "hfi_property.h" #include "venus_hfi.h" #include "msm_vidc_internal.h" +#include "msm_vidc_driver.h" static bool is_priv_ctrl(u32 id) { @@ -62,7 +63,7 @@ static const char * const * msm_vidc_get_qmenu_type( case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: return mpeg_video_stream_format; default: - s_vpr_e(inst->sid, "%s: No available qmenu for ctrl %#x", + s_vpr_e(inst->sid, "%s: No available qmenu for ctrl %#x\n", __func__, control_id); return NULL; } @@ -88,12 +89,173 @@ static const char *msm_vidc_get_priv_ctrl_name(u32 sid, u32 control_id) case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: return "NAL Format"; default: - s_vpr_e(sid, "%s: ctrl name not available for ctrl id %#x", + s_vpr_e(sid, "%s: ctrl name not available for ctrl id %#x\n", __func__, control_id); return NULL; } } +static enum msm_vidc_inst_capability_type msm_vidc_get_cap_id( + struct msm_vidc_inst *inst, u32 id) +{ + enum msm_vidc_inst_capability_type i = INST_CAP_NONE + 1; + struct msm_vidc_inst_capability *capability; + enum msm_vidc_inst_capability_type cap_id = INST_CAP_NONE; + + capability = inst->capabilities; + do { + if (capability->cap[i].v4l2_id == id) { + cap_id = capability->cap[i].cap; + break; + } + i++; + } while (i < INST_CAP_MAX); + + return cap_id; +} + +static int msm_vidc_add_capid_to_list(struct msm_vidc_inst *inst, + 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; + + /* skip adding if cap_id already present in list */ + if (type & FW_LIST) { + list_for_each_entry(curr_node, &inst->firmware.list, list) { + if (curr_node->cap_id == cap_id) { + s_vpr_e(inst->sid, + "%s: cap %d cannot be the child of two parents\n", + __func__, cap_id); + return 0; + } + } + } + + entry = kzalloc(sizeof(*entry), GFP_ATOMIC); + if (!entry) { + s_vpr_e(inst->sid, "%s: alloc failed\n", __func__); + 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; +} + +static int msm_vidc_add_children(struct msm_vidc_inst *inst, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + int i = 0; + struct msm_vidc_inst_capability *capability = inst->capabilities; + + while (i < MAX_CAP_CHILDREN && + capability->cap[cap_id].children[i]) { + rc = msm_vidc_add_capid_to_list(inst, + capability->cap[cap_id].children[i], + CHILD_LIST); + if (rc) + return rc; + i++; + } + return rc; +} + +static int msm_vidc_adjust_property(struct msm_vidc_inst *inst, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst_capability *capability; + + capability = inst->capabilities; + + if (capability->cap[cap_id].adjust) { + rc = capability->cap[cap_id].adjust(inst, NULL); + if (rc) + goto exit; + } + + /* add children cap_id's to chidren list */ + rc = msm_vidc_add_children(inst, cap_id); + if (rc) + goto exit; + + /* add cap_id to firmware list always */ + rc = msm_vidc_add_capid_to_list(inst, cap_id, FW_LIST); + if (rc) + goto exit; + + return 0; + +exit: + return rc; +} + +static int msm_vidc_adjust_dynamic_property(struct msm_vidc_inst *inst, + enum msm_vidc_inst_capability_type cap_id, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + struct msm_vidc_inst_capability *capability; + s32 prev_value; + + capability = inst->capabilities; + + /* + * ctrl is NULL for children adjustment calls + * When a dynamic control having children is adjusted, check if dynamic + * adjustment is allowed for its children. + */ + if (!(capability->cap[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED)) { + s_vpr_e(inst->sid, + "%s: dynamic setting of cap_id %d is not allowed\n", + __func__, cap_id); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); + return -EINVAL; + } + + /* + * 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) { + s_vpr_e(inst->sid, + "%s: child cap %d must have ajdust function\n", + __func__, capability->cap[cap_id].cap); + return -EINVAL; + } + + prev_value = capability->cap[cap_id].value; + + if (capability->cap[cap_id].adjust) { + rc = capability->cap[cap_id].adjust(inst, ctrl); + if (rc) + goto exit; + } else if (ctrl) { + capability->cap[cap_id].value = ctrl->val; + } + + /* 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; + } + + /* add cap_id to firmware list always */ + rc = msm_vidc_add_capid_to_list(inst, cap_id, FW_LIST); + if (rc) + goto exit; + + return 0; + +exit: + return rc; +} + int msm_vidc_ctrl_init(struct msm_vidc_inst *inst) { int rc = 0; @@ -138,7 +300,7 @@ int msm_vidc_ctrl_init(struct msm_vidc_inst *inst) return rc; } - if (core->v4l2_ctrl_ops) { + if (!core->v4l2_ctrl_ops) { s_vpr_e(inst->sid, "%s: no control ops\n", __func__); return -EINVAL; } @@ -248,6 +410,387 @@ int msm_vidc_ctrl_init(struct msm_vidc_inst *inst) int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl) { - return 0; + int rc = 0; + struct msm_vidc_inst *inst; + 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; + + if (!ctrl) { + d_vpr_e("%s: invalid ctrl parameter\n", __func__); + return -EINVAL; + } + + inst = container_of(ctrl->handler, + struct msm_vidc_inst, ctrl_handler); + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid parameters for inst\n", __func__); + return -EINVAL; + } + + if (inst->state == MSM_VIDC_ERROR) { + s_vpr_e(inst->sid, "%s: set ctrl not allowed in error state\n"); + /* (error name TBD); */ + return -EINVAL; + } + + capability = inst->capabilities; + + s_vpr_h(inst->sid, "%s: state %d, name %s, id 0x%x value %d\n", + __func__, inst->state, ctrl->name, ctrl->id, ctrl->val); + + cap_id = msm_vidc_get_cap_id(inst, ctrl->id); + if (cap_id == INST_CAP_NONE) { + s_vpr_e(inst->sid, "%s: could not find cap_id for ctrl %s\n", + __func__, ctrl->name); + return -EINVAL; + } + + /* Static setting */ + if (!inst->vb2q[OUTPUT_PORT].streaming) { + capability->cap[cap_id].value = ctrl->val; + return 0; + } + + /* check if dynamic adjustment is allowed */ + if (inst->vb2q[OUTPUT_PORT].streaming && + !(capability->cap[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED)) { + s_vpr_e(inst->sid, + "%s: dynamic setting of cap_id %d is not allowed\n", + __func__, 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) + goto exit; + list_del(&curr_node->list); + kfree(curr_node); + } + + /* dynamic controls with request will be set along with qbuf */ + if (inst->request) + return 0; + + /* Dynamic set control ASAP */ + rc = msm_vidc_set_fw_list(inst); + if (rc) { + s_vpr_e(inst->sid, "%s: setting %s failed\n", + __func__, ctrl->name); + goto exit; + } + +exit: + return rc; } +int msm_vidc_adjust_entropy_mode(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + int i = 0; + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + enum msm_vidc_inst_capability_type parent_id; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 codec = -1, profile = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + capability = inst->capabilities; + + /* ctrl is always NULL in streamon case */ + if (ctrl) + adjusted_value = ctrl->val; + else + adjusted_value = capability->cap[ENTROPY_MODE].value; + + /* check parents and adjust cabac session value */ + while (i < MAX_CAP_PARENTS && + capability->cap[ENTROPY_MODE].parents[i]) { + parent_id = capability->cap[ENTROPY_MODE].parents[i]; + if (parent_id == CODEC) + codec = inst->codec; + else if (parent_id == profile) + profile = capability->cap[PROFILE].value; + else + s_vpr_e(inst->sid, + "%s: invalid parent %d\n", + __func__, parent_id); + } + + if (codec == -1 || profile == -1) { + s_vpr_e(inst->sid, + "%s: missing parents %d %d\n", + __func__, codec, profile); + return 0; + } + + if (codec == MSM_VIDC_H264 && + (profile == V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE || + profile == V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) && + adjusted_value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC) + adjusted_value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC; + + if (capability->cap[ENTROPY_MODE].value != adjusted_value) { + s_vpr_h(inst->sid, "%s: adjusted from %#x to %#x\n", __func__, + capability->cap[ENTROPY_MODE].value, adjusted_value); + capability->cap[ENTROPY_MODE].value = adjusted_value; + } + + return rc; +} + +int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + // u32 cabac_max_bitrate; + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 new_value; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + capability = inst->capabilities; + + if (ctrl) + new_value = ctrl->val; + else + new_value = capability->cap[BIT_RATE].value; + + /* TO DO */ + return rc; +} + +/* + * Loop over instance capabilities with CAP_FLAG_ROOT + * and call adjust function, where + * - 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_properties(struct msm_vidc_inst *inst) +{ + int rc = 0; + int i; + struct msm_vidc_inst_cap_entry *curr_node = NULL, *tmp_node = NULL; + struct msm_vidc_inst_capability *capability; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + capability = inst->capabilities; + + for (i = 0; i < INST_CAP_MAX; i++) { + if (capability->cap[i].flags & CAP_FLAG_ROOT) { + rc = msm_vidc_adjust_property(inst, + capability->cap[i].cap); + if (rc) + goto exit; + } + } + + /* + * children of all root controls are already + * added to inst->children list at this point + */ + 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) + goto exit; + list_del(&curr_node->list); + kfree(curr_node); + } + +exit: + return rc; +} + +int msm_vidc_set_u32(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + u32 hfi_value; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + rc = msm_vidc_v4l2_menu_to_hfi(inst, cap_id, &hfi_value); + if (rc) + return -EINVAL; + + rc = hfi_packet_session_property(inst, + inst->capabilities->cap[cap_id].hfi_id, + HFI_HOST_FLAGS_NONE, HFI_PORT_NONE, + HFI_PAYLOAD_U32_ENUM, + &hfi_value, + sizeof(u32)); + if (rc) + s_vpr_e(inst->sid, + "%s: failed to set cap_id: %d to fw\n", + __func__, cap_id); + + return rc; +} + +int msm_vidc_set_s32(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + rc = hfi_packet_session_property(inst, + inst->capabilities->cap[cap_id].hfi_id, + HFI_HOST_FLAGS_NONE, HFI_PORT_NONE, + HFI_PAYLOAD_S32, + &inst->capabilities->cap[cap_id].value, + sizeof(s32)); + if (rc) + s_vpr_e(inst->sid, + "%s: failed to set cap_id: %d to fw\n", + __func__, cap_id); + + return rc; +} + +/* Please ignore this function for now. TO DO*/ +int msm_vidc_set_array(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst_capability *capability; + struct msm_vidc_core *core; + + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + + if (!inst || !inst->core || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + capability = inst->capabilities; + core = (struct msm_vidc_core *)inst->core; + + switch (cap_id) { + /* + * Needed if any control needs to be packed into a structure + * and sent for packetization. + * payload types may be: + * STRUCTURE, BLOB, STRING, PACKED, ARRAY, + * + case BITRATE_MODE: + s_vpr_h(inst->sid, "%s: %d\n", __func__, hfi_value); + hfi_create_packet(inst->packet, inst->packet_size, + offset, + capability->cap[cap_id].hfi_id, + HFI_HOST_FLAGS_NONE, HFI_PAYLOAD_ENUM, + HFI_PORT_NONE, core->packet_id++, + &capability->cap[PROFILE].value, sizeof(u32)); + break; + } + */ + default: + s_vpr_e(inst->sid, + "%s: Unknown cap id %d, cannot set to fw\n", + __func__, cap_id); + rc = -EINVAL; + break; + } + + return rc; +} + +int msm_vidc_set_fw_list(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; + } + 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: + return rc; +} + +int msm_vidc_v4l2_menu_to_hfi(struct msm_vidc_inst *inst, + enum msm_vidc_inst_capability_type cap_id, u32 *value) +{ + struct msm_vidc_inst_capability *capability = inst->capabilities; + + switch (capability->cap[cap_id].v4l2_id) { + case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: + switch (capability->cap[cap_id].value) { + case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC: + *value = 1; + break; + case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC: + *value = 0; + break; + default: + *value = 1; + s_vpr_e(inst->sid, + "%s: invalid ctrl %d value %d, default value %u\n", + __func__, capability->cap[cap_id].v4l2_id, + capability->cap[cap_id].value, *value); + } + break; + default: + s_vpr_e(inst->sid, + "%s: invalid ctrl with cap_id\n", cap_id); + return -EINVAL; + } + return 0; +} diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index 9dc5119f3a..e58804b805 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -668,7 +668,7 @@ int msm_vidc_session_open(struct msm_vidc_inst *inst) return 0; } -int msm_vidc_get_inst_capability(struct msm_vidc_inst *inst, u32 codec) +int msm_vidc_get_inst_capability(struct msm_vidc_inst *inst) { int rc = 0; int i; @@ -683,11 +683,10 @@ int msm_vidc_get_inst_capability(struct msm_vidc_inst *inst, u32 codec) for (i = 0; i < core->codecs_count; i++) { if (core->inst_caps[i].domain == inst->domain && - core->inst_caps[i].codec == get_vidc_codec_from_v4l2( - codec)) { + core->inst_caps[i].codec == inst->codec) { s_vpr_h(inst->sid, - "%s: copied capabilities with %#x caps\n", - __func__, codec); + "%s: copied capabilities with %#x codec\n", + __func__, inst->codec); memcpy(inst->capabilities, &core->inst_caps[i], sizeof(struct msm_vidc_inst_capability)); } diff --git a/driver/vidc/src/msm_vidc_vb2.c b/driver/vidc/src/msm_vidc_vb2.c index b95d046728..055e0c4777 100644 --- a/driver/vidc/src/msm_vidc_vb2.c +++ b/driver/vidc/src/msm_vidc_vb2.c @@ -110,6 +110,23 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count) return -EINVAL; } + /* + if (inst->state == MSM_VIDC_START_INPUT || + inst->state == MSM_VIDC_START_OUTPUT) { + rc = msm_vidc_adjust_properties(inst); + if (rc) + return -EINVAL; + } + + if ((inst->state == MSM_VIDC_START_INPUT) || + (inst->state == MSM_VIDC_START && + q->type == INPUT_PLANE)) { + rc = msm_vidc_set_fw_list(inst); + if (rc) + return -EINVAL; + } + */ + if (q->type == INPUT_PLANE) { if (is_decode_session(inst)) rc = msm_vdec_start_input(inst); diff --git a/driver/vidc/src/venus_hfi_response.c b/driver/vidc/src/venus_hfi_response.c index 0fe2ca2bc0..82f66d2472 100644 --- a/driver/vidc/src/venus_hfi_response.c +++ b/driver/vidc/src/venus_hfi_response.c @@ -96,7 +96,7 @@ static int handle_session_error(struct msm_vidc_inst *inst, s_vpr_e(inst->sid, "session error (%#x): %s\n", pkt->type, error); - rc = msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR); + rc = msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); return rc; } @@ -137,7 +137,7 @@ static int handle_session_open(struct msm_vidc_inst *inst, { if (pkt->flags & HFI_FW_FLAGS_SESSION_ERROR) { s_vpr_e(inst->sid, "%s: received session error\n", __func__); - msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); } if (pkt->flags & HFI_FW_FLAGS_SUCCESS) @@ -151,7 +151,7 @@ static int handle_session_close(struct msm_vidc_inst *inst, { if (pkt->flags & HFI_FW_FLAGS_SESSION_ERROR) { s_vpr_e(inst->sid, "%s: received session error\n", __func__); - msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); } if (pkt->flags & HFI_FW_FLAGS_SUCCESS) @@ -166,7 +166,7 @@ static int handle_session_start(struct msm_vidc_inst *inst, { if (pkt->flags & HFI_FW_FLAGS_SESSION_ERROR) { s_vpr_e(inst->sid, "%s: received session error\n", __func__); - msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); } if (pkt->flags & HFI_FW_FLAGS_SUCCESS) @@ -180,7 +180,7 @@ static int handle_session_stop(struct msm_vidc_inst *inst, { if (pkt->flags & HFI_FW_FLAGS_SESSION_ERROR) { s_vpr_e(inst->sid, "%s: received session error\n", __func__); - msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); } if (pkt->flags & HFI_FW_FLAGS_SUCCESS) @@ -195,7 +195,7 @@ static int handle_session_drain(struct msm_vidc_inst *inst, { if (pkt->flags & HFI_FW_FLAGS_SESSION_ERROR) { s_vpr_e(inst->sid, "%s: received session error\n", __func__); - msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); } if (pkt->flags & HFI_FW_FLAGS_SUCCESS) @@ -231,20 +231,20 @@ static int handle_session_buffer(struct msm_vidc_inst *inst, if (pkt->flags & HFI_FW_FLAGS_SESSION_ERROR) { s_vpr_e(inst->sid, "%s: received session error\n", __func__); - msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); return 0; } port_type = pkt->port; if (!is_valid_hfi_port(inst, port_type, __func__)) { - msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); return 0; } buffer = (struct hfi_buffer *)(pkt + sizeof(struct hfi_packet)); buf_type = buffer->type; if (!is_valid_hfi_buffer_type(inst, buf_type, __func__)) { - msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); return 0; }