diff --git a/driver/platform/common/inc/msm_vidc_platform.h b/driver/platform/common/inc/msm_vidc_platform.h index 30fe32be26..9c24618eaf 100644 --- a/driver/platform/common/inc/msm_vidc_platform.h +++ b/driver/platform/common/inc/msm_vidc_platform.h @@ -238,4 +238,128 @@ static inline bool is_regulator_supported(struct msm_vidc_core *core) int msm_vidc_init_platform(struct platform_device *pdev); int msm_vidc_deinit_platform(struct platform_device *pdev); +/* control framework support functions */ + +enum msm_vidc_inst_capability_type msm_vidc_get_cap_id( + struct msm_vidc_inst *inst, u32 id); +int msm_vidc_update_cap_value(struct msm_vidc_inst *inst, u32 cap, + s32 adjusted_val, const char *func); +bool is_parent_available(struct msm_vidc_inst *inst, + u32 cap_id, u32 check_parent, const char *func); +int msm_vidc_get_parent_value(struct msm_vidc_inst *inst, u32 cap, u32 parent, + s32 *value, const char *func); +u32 msm_vidc_get_port_info(struct msm_vidc_inst *inst, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_v4l2_menu_to_hfi(struct msm_vidc_inst *inst, + enum msm_vidc_inst_capability_type cap_id, u32 *value); +int msm_vidc_v4l2_to_hfi_enum(struct msm_vidc_inst *inst, + enum msm_vidc_inst_capability_type cap_id, u32 *value); +int msm_vidc_packetize_control(struct msm_vidc_inst *inst, + enum msm_vidc_inst_capability_type cap_id, u32 payload_type, + void *hfi_val, u32 payload_size, const char *func); + +int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_dynamic_layer_bitrate(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_bitrate_mode(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_entropy_mode(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_profile(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_ltr_count(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_use_ltr(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_mark_ltr(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_delta_based_rc(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_output_order(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_input_buf_host_max_count(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_output_buf_host_max_count(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_chroma_qp_index_offset(void *instance, + struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_slice_count(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_layer_count(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_gop_size(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_b_frame(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_peak_bitrate(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_hevc_min_qp(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_hevc_max_qp(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_hevc_i_frame_qp(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_hevc_p_frame_qp(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_hevc_b_frame_qp(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_blur_type(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_blur_resolution(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_brs(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_enc_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_dec_lowlatency_mode(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_all_intra(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_dec_outbuf_fence(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_dec_slice_mode(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_preprocess(void *instance, struct v4l2_ctrl *ctrl); + +int msm_vidc_set_header_mode(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_deblock_mode(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_min_qp(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_max_qp(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_frame_qp(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_req_sync_frame(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_chroma_qp_index_offset(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_slice_count(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_layer_count_and_type(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_gop_size(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_bitrate(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_dynamic_layer_bitrate(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_u32(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_u32_packed(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_u32_enum(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_constant_quality(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_vbr_related_properties( + void *instance, enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_cbr_related_properties(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_use_and_mark_ltr(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_nal_length(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_session_priority(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_flip(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_rotation(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_blur_resolution(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_stage(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_pipe(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_csc_custom_matrix(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_level(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_preprocess(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_reserve_duration(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_q16(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_vui_timing_info(void *instance, + enum msm_vidc_inst_capability_type cap_id); + #endif // _MSM_VIDC_PLATFORM_H_ diff --git a/driver/platform/common/src/msm_vidc_platform.c b/driver/platform/common/src/msm_vidc_platform.c index a0a6b8fca5..d2074faa18 100644 --- a/driver/platform/common/src/msm_vidc_platform.c +++ b/driver/platform/common/src/msm_vidc_platform.c @@ -11,11 +11,15 @@ #include "msm_vidc_debug.h" #include "msm_vidc_v4l2.h" #include "msm_vidc_vb2.h" -#include "msm_vidc_control.h" #include "msm_vidc_core.h" #include "msm_vidc_debug.h" #include "msm_vidc_internal.h" #include "msm_vidc_memory.h" +#include "hfi_packet.h" +#include "hfi_property.h" +#include "venus_hfi.h" +#include "msm_vidc_control.h" +#include "msm_vidc_driver.h" #if defined(CONFIG_MSM_VIDC_WAIPIO) #include "msm_vidc_waipio.h" @@ -38,6 +42,12 @@ #if defined(CONFIG_MSM_VIDC_IRIS33) #include "msm_vidc_iris33.h" #endif + +#define CAP_TO_8BIT_QP(a) { \ + if ((a) < MIN_QP_8BIT) \ + (a) = MIN_QP_8BIT; \ +} + /* * Custom conversion coefficients for resolution: 176x144 negative * coeffs are converted to s4.9 format @@ -449,3 +459,3353 @@ int msm_vidc_init_platform(struct platform_device *pdev) return rc; } + +/****************** control framework utility functions **********************/ + +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_id; + break; + } + i++; + } while (i < INST_CAP_MAX); + + return cap_id; +} + +int msm_vidc_update_cap_value(struct msm_vidc_inst *inst, u32 cap_id, + s32 adjusted_val, const char *func) +{ + int prev_value = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + prev_value = inst->capabilities->cap[cap_id].value; + + if (is_meta_cap(inst, cap_id)) { + /* + * cumulative control value if client set same metadata + * control multiple times. + */ + if (adjusted_val & MSM_VIDC_META_ENABLE) { + /* enable metadata */ + inst->capabilities->cap[cap_id].value |= adjusted_val; + } else { + /* disable metadata */ + inst->capabilities->cap[cap_id].value &= ~adjusted_val; + } + } else { + inst->capabilities->cap[cap_id].value = adjusted_val; + } + + if (prev_value != inst->capabilities->cap[cap_id].value) { + i_vpr_h(inst, + "%s: updated database: name: %s, value: %#x -> %#x\n", + func, cap_name(cap_id), + prev_value, inst->capabilities->cap[cap_id].value); + } + + return 0; +} + +bool is_parent_available(struct msm_vidc_inst *inst, + u32 cap_id, u32 check_parent, const char *func) +{ + int i = 0; + u32 cap_parent; + + while (i < MAX_CAP_PARENTS && + inst->capabilities->cap[cap_id].parents[i]) { + cap_parent = inst->capabilities->cap[cap_id].parents[i]; + if (cap_parent == check_parent) + return true; + i++; + } + + i_vpr_e(inst, + "%s: missing parent %s for %s\n", + func, cap_name(check_parent), cap_name(cap_id)); + return false; +} + +int msm_vidc_get_parent_value(struct msm_vidc_inst *inst, + u32 cap_id, u32 parent, s32 *value, const char *func) +{ + int rc = 0; + + if (is_parent_available(inst, cap_id, parent, func)) { + switch (parent) { + case BITRATE_MODE: + *value = inst->hfi_rc_type; + break; + case LAYER_TYPE: + *value = inst->hfi_layer_type; + break; + default: + *value = inst->capabilities->cap[parent].value; + break; + } + } else { + rc = -EINVAL; + } + + return rc; +} + +u32 msm_vidc_get_port_info(struct msm_vidc_inst *inst, + enum msm_vidc_inst_capability_type cap_id) +{ + struct msm_vidc_inst_capability *capability = inst->capabilities; + + if (capability->cap[cap_id].flags & CAP_FLAG_INPUT_PORT && + capability->cap[cap_id].flags & CAP_FLAG_OUTPUT_PORT) { + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) + return get_hfi_port(inst, INPUT_PORT); + else + return get_hfi_port(inst, OUTPUT_PORT); + } + + if (capability->cap[cap_id].flags & CAP_FLAG_INPUT_PORT) + return get_hfi_port(inst, INPUT_PORT); + else if (capability->cap[cap_id].flags & CAP_FLAG_OUTPUT_PORT) + return get_hfi_port(inst, OUTPUT_PORT); + else + return HFI_PORT_NONE; +} + +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 (cap_id) { + case 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; + goto set_default; + } + return 0; + default: + i_vpr_e(inst, + "%s: mapping not specified for ctrl_id: %#x\n", + __func__, capability->cap[cap_id].v4l2_id); + return -EINVAL; + } + +set_default: + i_vpr_e(inst, + "%s: invalid value %d for ctrl id: %#x. Set default: %u\n", + __func__, capability->cap[cap_id].value, + capability->cap[cap_id].v4l2_id, *value); + return 0; +} + +int msm_vidc_v4l2_to_hfi_enum(struct msm_vidc_inst *inst, + enum msm_vidc_inst_capability_type cap_id, u32 *value) +{ + struct msm_vidc_inst_capability *capability = inst->capabilities; + + switch (cap_id) { + case BITRATE_MODE: + *value = inst->hfi_rc_type; + return 0; + case PROFILE: + case LEVEL: + case HEVC_TIER: + case AV1_TIER: + case BLUR_TYPES: + *value = capability->cap[cap_id].value; + return 0; + case LAYER_TYPE: + if (inst->codec == MSM_VIDC_HEVC) { + switch (capability->cap[cap_id].value) { + case V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B: + *value = HFI_HIER_B; + break; + case V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P: + //TODO (AS): check if this is right mapping + *value = HFI_HIER_P_SLIDING_WINDOW; + break; + default: + *value = HFI_HIER_P_SLIDING_WINDOW; + goto set_default; + } + } + return 0; + case ROTATION: + switch (capability->cap[cap_id].value) { + case 0: + *value = HFI_ROTATION_NONE; + break; + case 90: + *value = HFI_ROTATION_90; + break; + case 180: + *value = HFI_ROTATION_180; + break; + case 270: + *value = HFI_ROTATION_270; + break; + default: + *value = HFI_ROTATION_NONE; + goto set_default; + } + return 0; + case LF_MODE: + if (inst->codec == MSM_VIDC_HEVC) { + switch (capability->cap[cap_id].value) { + case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED: + *value = HFI_DEBLOCK_ALL_BOUNDARY; + break; + case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED: + *value = HFI_DEBLOCK_DISABLE; + break; + case DB_HEVC_DISABLE_SLICE_BOUNDARY: + *value = HFI_DEBLOCK_DISABLE_AT_SLICE_BOUNDARY; + break; + default: + *value = HFI_DEBLOCK_ALL_BOUNDARY; + goto set_default; + } + } else if (inst->codec == MSM_VIDC_H264) { + switch (capability->cap[cap_id].value) { + case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED: + *value = HFI_DEBLOCK_ALL_BOUNDARY; + break; + case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED: + *value = HFI_DEBLOCK_DISABLE; + break; + case DB_H264_DISABLE_SLICE_BOUNDARY: + *value = HFI_DEBLOCK_DISABLE_AT_SLICE_BOUNDARY; + break; + default: + *value = HFI_DEBLOCK_ALL_BOUNDARY; + goto set_default; + } + } + return 0; + case NAL_LENGTH_FIELD: + switch (capability->cap[cap_id].value) { + case V4L2_MPEG_VIDEO_HEVC_SIZE_4: + *value = HFI_NAL_LENGTH_SIZE_4; + break; + default: + *value = HFI_NAL_LENGTH_STARTCODES; + goto set_default; + } + return 0; + default: + i_vpr_e(inst, + "%s: mapping not specified for ctrl_id: %#x\n", + __func__, capability->cap[cap_id].v4l2_id); + return -EINVAL; + } + +set_default: + i_vpr_e(inst, + "%s: invalid value %d for ctrl id: %#x. Set default: %u\n", + __func__, capability->cap[cap_id].value, + capability->cap[cap_id].v4l2_id, *value); + return 0; +} + +int msm_vidc_packetize_control(struct msm_vidc_inst *inst, + enum msm_vidc_inst_capability_type cap_id, u32 payload_type, + void *hfi_val, u32 payload_size, const char *func) +{ + int rc = 0; + u64 payload = 0; + + if (payload_size > sizeof(u32)) { + i_vpr_e(inst, "%s: payload size is more than u32 for cap[%d] %s\n", + func, cap_id, cap_name(cap_id)); + return -EINVAL; + } + + if (payload_size == sizeof(u32)) + payload = *(u32 *)hfi_val; + else if (payload_size == sizeof(u8)) + payload = *(u8 *)hfi_val; + else if (payload_size == sizeof(u16)) + payload = *(u16 *)hfi_val; + + i_vpr_h(inst, FMT_STRING_SET_CAP, + cap_name(cap_id), inst->capabilities->cap[cap_id].value, payload); + + rc = venus_hfi_session_property(inst, + inst->capabilities->cap[cap_id].hfi_id, + HFI_HOST_FLAGS_NONE, + msm_vidc_get_port_info(inst, cap_id), + payload_type, + hfi_val, + payload_size); + if (rc) { + i_vpr_e(inst, "%s: failed to set cap[%d] %s to fw\n", + func, cap_id, cap_name(cap_id)); + return rc; + } + + return 0; +} + +/*************** End of control framework utility functions ******************/ + +/*********************** Control Adjust functions ****************************/ + +int msm_vidc_adjust_entropy_mode(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 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 */ + adjusted_value = ctrl ? ctrl->val : + capability->cap[ENTROPY_MODE].value; + + if (inst->codec != MSM_VIDC_H264) { + i_vpr_e(inst, + "%s: incorrect entry in database. fix the database\n", + __func__); + return 0; + } + + if (msm_vidc_get_parent_value(inst, ENTROPY_MODE, + PROFILE, &profile, __func__)) + return -EINVAL; + + if (profile == V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE || + profile == V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) + adjusted_value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC; + + msm_vidc_update_cap_value(inst, ENTROPY_MODE, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_bitrate_mode(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + int lossless, frame_rc, bitrate_mode, frame_skip; + u32 hfi_value = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + bitrate_mode = capability->cap[BITRATE_MODE].value; + lossless = capability->cap[LOSSLESS].value; + frame_rc = capability->cap[FRAME_RC_ENABLE].value; + frame_skip = capability->cap[FRAME_SKIP_MODE].value; + + if (lossless || (msm_vidc_lossless_encode && + inst->codec == MSM_VIDC_HEVC)) { + hfi_value = HFI_RC_LOSSLESS; + goto update; + } + + if (!frame_rc && !is_image_session(inst)) { + hfi_value = HFI_RC_OFF; + goto update; + } + + if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { + hfi_value = HFI_RC_VBR_CFR; + } else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) { + if (frame_skip) + hfi_value = HFI_RC_CBR_VFR; + else + hfi_value = HFI_RC_CBR_CFR; + } else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) { + hfi_value = HFI_RC_CQ; + } + +update: + inst->hfi_rc_type = hfi_value; + i_vpr_h(inst, "%s: hfi rc type: %#x\n", + __func__, inst->hfi_rc_type); + + return 0; +} + +int msm_vidc_adjust_profile(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 pix_fmt = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : capability->cap[PROFILE].value; + + /* PIX_FMTS dependency is common across all chipsets. + * Hence, PIX_FMTS must be specified as Parent for HEVC profile. + * Otherwise it would be a database error that should be fixed. + */ + if (msm_vidc_get_parent_value(inst, PROFILE, PIX_FMTS, + &pix_fmt, __func__)) + return -EINVAL; + + /* 10 bit profile for 10 bit color format */ + if (pix_fmt == MSM_VIDC_FMT_TP10C || pix_fmt == MSM_VIDC_FMT_P010) { + if (is_image_session(inst)) + adjusted_value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10_STILL_PICTURE; + else + adjusted_value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10; + } else { + /* 8 bit profile for 8 bit color format */ + if (is_image_session(inst)) + adjusted_value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE; + else + adjusted_value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN; + } + + msm_vidc_update_cap_value(inst, PROFILE, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_ltr_count(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 rc_type = -1, all_intra = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : capability->cap[LTR_COUNT].value; + + if (msm_vidc_get_parent_value(inst, LTR_COUNT, BITRATE_MODE, + &rc_type, __func__) || + msm_vidc_get_parent_value(inst, LTR_COUNT, ALL_INTRA, + &all_intra, __func__)) + return -EINVAL; + + if ((rc_type != HFI_RC_OFF && + rc_type != HFI_RC_CBR_CFR && + rc_type != HFI_RC_CBR_VFR) || + all_intra) { + adjusted_value = 0; + i_vpr_h(inst, + "%s: ltr count unsupported, rc_type: %#x, all_intra %d\n", + __func__, rc_type, all_intra); + } + + msm_vidc_update_cap_value(inst, LTR_COUNT, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_use_ltr(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value, ltr_count; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : capability->cap[USE_LTR].value; + + /* + * Since USE_LTR is only set dynamically, and LTR_COUNT is static + * control, no need to make LTR_COUNT as parent for USE_LTR as + * LTR_COUNT value will always be updated when dynamically USE_LTR + * is set + */ + ltr_count = capability->cap[LTR_COUNT].value; + if (!ltr_count) + return 0; + + if (adjusted_value <= 0 || + adjusted_value > ((1 << ltr_count) - 1)) { + /* + * USE_LTR is bitmask value, hence should be + * > 0 and <= (2 ^ LTR_COUNT) - 1 + */ + i_vpr_e(inst, "%s: invalid value %d\n", + __func__, adjusted_value); + return 0; + } + + /* USE_LTR value is a bitmask value */ + msm_vidc_update_cap_value(inst, USE_LTR, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_mark_ltr(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value, ltr_count; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : capability->cap[MARK_LTR].value; + + /* + * Since MARK_LTR is only set dynamically, and LTR_COUNT is static + * control, no need to make LTR_COUNT as parent for MARK_LTR as + * LTR_COUNT value will always be updated when dynamically MARK_LTR + * is set + */ + ltr_count = capability->cap[LTR_COUNT].value; + if (!ltr_count) + return 0; + + if (adjusted_value < 0 || + adjusted_value > (ltr_count - 1)) { + /* MARK_LTR value should be >= 0 and <= (LTR_COUNT - 1) */ + i_vpr_e(inst, "%s: invalid value %d\n", + __func__, adjusted_value); + return 0; + } + + msm_vidc_update_cap_value(inst, MARK_LTR, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_delta_based_rc(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 rc_type = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[TIME_DELTA_BASED_RC].value; + + if (msm_vidc_get_parent_value(inst, TIME_DELTA_BASED_RC, + BITRATE_MODE, &rc_type, __func__)) + return -EINVAL; + + if (rc_type == HFI_RC_OFF || + rc_type == HFI_RC_CQ) + adjusted_value = 0; + + msm_vidc_update_cap_value(inst, TIME_DELTA_BASED_RC, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_output_order(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + struct msm_vidc_inst_capability *capability; + s32 tn_mode = -1, display_delay = -1, display_delay_enable = -1; + u32 adjusted_value; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[OUTPUT_ORDER].value; + + if (msm_vidc_get_parent_value(inst, OUTPUT_ORDER, THUMBNAIL_MODE, + &tn_mode, __func__) || + msm_vidc_get_parent_value(inst, OUTPUT_ORDER, DISPLAY_DELAY, + &display_delay, __func__) || + msm_vidc_get_parent_value(inst, OUTPUT_ORDER, DISPLAY_DELAY_ENABLE, + &display_delay_enable, __func__)) + return -EINVAL; + + if (tn_mode || (display_delay_enable && !display_delay)) + adjusted_value = 1; + + msm_vidc_update_cap_value(inst, OUTPUT_ORDER, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_input_buf_host_max_count(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + struct msm_vidc_inst_capability *capability; + u32 adjusted_value; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[INPUT_BUF_HOST_MAX_COUNT].value; + + if (msm_vidc_is_super_buffer(inst) || is_image_session(inst)) + adjusted_value = DEFAULT_MAX_HOST_BURST_BUF_COUNT; + + msm_vidc_update_cap_value(inst, INPUT_BUF_HOST_MAX_COUNT, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_output_buf_host_max_count(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + struct msm_vidc_inst_capability *capability; + u32 adjusted_value; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[OUTPUT_BUF_HOST_MAX_COUNT].value; + + if (msm_vidc_is_super_buffer(inst) || is_image_session(inst) || + is_enc_slice_delivery_mode(inst)) + adjusted_value = DEFAULT_MAX_HOST_BURST_BUF_COUNT; + + msm_vidc_update_cap_value(inst, OUTPUT_BUF_HOST_MAX_COUNT, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 profile = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[TRANSFORM_8X8].value; + + if (inst->codec != MSM_VIDC_H264) { + i_vpr_e(inst, + "%s: incorrect entry in database. fix the database\n", + __func__); + return 0; + } + + if (msm_vidc_get_parent_value(inst, TRANSFORM_8X8, + PROFILE, &profile, __func__)) + return -EINVAL; + + if (profile != V4L2_MPEG_VIDEO_H264_PROFILE_HIGH && + profile != V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) + adjusted_value = 0; + + msm_vidc_update_cap_value(inst, TRANSFORM_8X8, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_chroma_qp_index_offset(void *instance, + struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[CHROMA_QP_INDEX_OFFSET].value; + + if (adjusted_value != MIN_CHROMA_QP_OFFSET) + adjusted_value = MAX_CHROMA_QP_OFFSET; + + msm_vidc_update_cap_value(inst, CHROMA_QP_INDEX_OFFSET, + adjusted_value, __func__); + + return 0; +} + +static bool msm_vidc_check_all_layer_bitrate_set(struct msm_vidc_inst *inst) +{ + bool layer_bitrate_set = true; + u32 cap_id = 0, i, enh_layer_count; + u32 layer_br_caps[6] = {L0_BR, L1_BR, L2_BR, L3_BR, L4_BR, L5_BR}; + + enh_layer_count = inst->capabilities->cap[ENH_LAYER_COUNT].value; + + for (i = 0; i <= enh_layer_count; i++) { + if (i >= ARRAY_SIZE(layer_br_caps)) + break; + cap_id = layer_br_caps[i]; + if (!(inst->capabilities->cap[cap_id].flags & CAP_FLAG_CLIENT_SET)) { + layer_bitrate_set = false; + break; + } + } + + return layer_bitrate_set; +} + +static u32 msm_vidc_get_cumulative_bitrate(struct msm_vidc_inst *inst) +{ + int i; + u32 cap_id = 0; + u32 cumulative_br = 0; + s32 enh_layer_count; + u32 layer_br_caps[6] = {L0_BR, L1_BR, L2_BR, L3_BR, L4_BR, L5_BR}; + + enh_layer_count = inst->capabilities->cap[ENH_LAYER_COUNT].value; + + for (i = 0; i <= enh_layer_count; i++) { + if (i >= ARRAY_SIZE(layer_br_caps)) + break; + cap_id = layer_br_caps[i]; + cumulative_br += inst->capabilities->cap[cap_id].value; + } + + return cumulative_br; +} + +int msm_vidc_adjust_slice_count(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + struct msm_vidc_inst_capability *capability; + struct v4l2_format *output_fmt; + s32 adjusted_value, rc_type = -1, slice_mode, all_intra, enh_layer_count = 0; + u32 slice_val, mbpf = 0, mbps = 0, max_mbpf = 0, max_mbps = 0, bitrate = 0; + u32 update_cap, max_avg_slicesize, output_width, output_height; + u32 min_width, min_height, max_width, max_height, fps; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + slice_mode = ctrl ? ctrl->val : + capability->cap[SLICE_MODE].value; + + if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) + return 0; + + if (msm_vidc_get_parent_value(inst, SLICE_MODE, + BITRATE_MODE, &rc_type, __func__) || + msm_vidc_get_parent_value(inst, SLICE_MODE, + ALL_INTRA, &all_intra, __func__) || + msm_vidc_get_parent_value(inst, SLICE_MODE, + ENH_LAYER_COUNT, &enh_layer_count, __func__)) + return -EINVAL; + + if (capability->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) { + bitrate = capability->cap[BIT_RATE].value; + } else if (msm_vidc_check_all_layer_bitrate_set(inst)) { + bitrate = msm_vidc_get_cumulative_bitrate(inst); + } else { + adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; + update_cap = SLICE_MODE; + i_vpr_h(inst, + "%s: client did not set bitrate & layerwise bitrates\n", + __func__); + goto exit; + } + + fps = capability->cap[FRAME_RATE].value >> 16; + if (fps > MAX_SLICES_FRAME_RATE || + (rc_type != HFI_RC_OFF && + rc_type != HFI_RC_CBR_CFR && + rc_type != HFI_RC_CBR_VFR && + rc_type != HFI_RC_VBR_CFR) || + all_intra) { + adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; + update_cap = SLICE_MODE; + i_vpr_h(inst, + "%s: slice unsupported, fps: %u, rc_type: %#x, all_intra %d\n", + __func__, fps, rc_type, all_intra); + goto exit; + } + + output_fmt = &inst->fmts[OUTPUT_PORT]; + output_width = output_fmt->fmt.pix_mp.width; + output_height = output_fmt->fmt.pix_mp.height; + + max_width = (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) ? + MAX_MB_SLICE_WIDTH : MAX_BYTES_SLICE_WIDTH; + max_height = (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) ? + MAX_MB_SLICE_HEIGHT : MAX_BYTES_SLICE_HEIGHT; + min_width = (inst->codec == MSM_VIDC_HEVC) ? + MIN_HEVC_SLICE_WIDTH : MIN_AVC_SLICE_WIDTH; + min_height = MIN_SLICE_HEIGHT; + + /* + * For V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB: + * - width >= 384 and height >= 128 + * - width and height <= 4096 + * For V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES: + * - width >= 192 and height >= 128 + * - width and height <= 1920 + */ + if (output_width < min_width || output_height < min_height || + output_width > max_width || output_height > max_width) { + adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; + update_cap = SLICE_MODE; + i_vpr_h(inst, + "%s: slice unsupported, codec: %#x wxh: [%dx%d]\n", + __func__, inst->codec, output_width, output_height); + goto exit; + } + + mbpf = NUM_MBS_PER_FRAME(output_height, output_width); + mbps = NUM_MBS_PER_SEC(output_height, output_width, fps); + max_mbpf = NUM_MBS_PER_FRAME(max_height, max_width); + max_mbps = NUM_MBS_PER_SEC(max_height, max_width, MAX_SLICES_FRAME_RATE); + + if (mbpf > max_mbpf || mbps > max_mbps) { + adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; + update_cap = SLICE_MODE; + i_vpr_h(inst, + "%s: Unsupported, mbpf[%u] > max[%u], mbps[%u] > max[%u]\n", + __func__, mbpf, max_mbpf, mbps, max_mbps); + goto exit; + } + + if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) { + update_cap = SLICE_MAX_MB; + slice_val = capability->cap[SLICE_MAX_MB].value; + slice_val = max(slice_val, mbpf / MAX_SLICES_PER_FRAME); + } else { + slice_val = capability->cap[SLICE_MAX_BYTES].value; + update_cap = SLICE_MAX_BYTES; + if (rc_type != HFI_RC_OFF) { + max_avg_slicesize = ((bitrate / fps) / 8) / + MAX_SLICES_PER_FRAME; + slice_val = max(slice_val, max_avg_slicesize); + } + } + adjusted_value = slice_val; + +exit: + msm_vidc_update_cap_value(inst, update_cap, + adjusted_value, __func__); + + return 0; +} + +static int msm_vidc_adjust_static_layer_count_and_type(struct msm_vidc_inst *inst, + s32 layer_count) +{ + bool hb_requested = false; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (!layer_count) { + i_vpr_h(inst, "client not enabled layer encoding\n"); + goto exit; + } + + if (inst->hfi_rc_type == HFI_RC_CQ) { + i_vpr_h(inst, "rc type is CQ, disabling layer encoding\n"); + layer_count = 0; + goto exit; + } + + if (inst->codec == MSM_VIDC_H264) { + if (!inst->capabilities->cap[LAYER_ENABLE].value) { + layer_count = 0; + goto exit; + } + + hb_requested = (inst->capabilities->cap[LAYER_TYPE].value == + V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B) ? + true : false; + } else if (inst->codec == MSM_VIDC_HEVC) { + hb_requested = (inst->capabilities->cap[LAYER_TYPE].value == + V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) ? + true : false; + } + + if (hb_requested && inst->hfi_rc_type != HFI_RC_VBR_CFR) { + i_vpr_h(inst, + "%s: HB layer encoding is supported for VBR rc only\n", + __func__); + layer_count = 0; + goto exit; + } + + if (!is_meta_tx_inp_enabled(inst, META_EVA_STATS) && + hb_requested && (layer_count > 1)) { + layer_count = 1; + i_vpr_h(inst, + "%s: cvp disable supports only one enh layer HB\n", + __func__); + } + + /* decide hfi layer type */ + if (hb_requested) { + inst->hfi_layer_type = HFI_HIER_B; + } else { + /* HP requested */ + inst->hfi_layer_type = HFI_HIER_P_SLIDING_WINDOW; + if (inst->codec == MSM_VIDC_H264 && + inst->hfi_rc_type == HFI_RC_VBR_CFR) + inst->hfi_layer_type = HFI_HIER_P_HYBRID_LTR; + } + + /* sanitize layer count based on layer type and codec, and rc type */ + if (inst->hfi_layer_type == HFI_HIER_B) { + if (layer_count > MAX_ENH_LAYER_HB) + layer_count = MAX_ENH_LAYER_HB; + } else if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR) { + if (layer_count > MAX_AVC_ENH_LAYER_HYBRID_HP) + layer_count = MAX_AVC_ENH_LAYER_HYBRID_HP; + } else if (inst->hfi_layer_type == HFI_HIER_P_SLIDING_WINDOW) { + if (inst->codec == MSM_VIDC_H264) { + if (layer_count > MAX_AVC_ENH_LAYER_SLIDING_WINDOW) + layer_count = MAX_AVC_ENH_LAYER_SLIDING_WINDOW; + } else if (inst->codec == MSM_VIDC_HEVC) { + if (inst->hfi_rc_type == HFI_RC_VBR_CFR) { + if (layer_count > MAX_HEVC_VBR_ENH_LAYER_SLIDING_WINDOW) + layer_count = MAX_HEVC_VBR_ENH_LAYER_SLIDING_WINDOW; + } else { + if (layer_count > MAX_HEVC_NON_VBR_ENH_LAYER_SLIDING_WINDOW) + layer_count = MAX_HEVC_NON_VBR_ENH_LAYER_SLIDING_WINDOW; + } + } + } + +exit: + msm_vidc_update_cap_value(inst, ENH_LAYER_COUNT, + layer_count, __func__); + inst->capabilities->cap[ENH_LAYER_COUNT].max = layer_count; + return 0; +} + +int msm_vidc_adjust_layer_count(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + struct msm_vidc_inst_capability *capability; + s32 client_layer_count; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + client_layer_count = ctrl ? ctrl->val : + capability->cap[ENH_LAYER_COUNT].value; + + if (!is_parent_available(inst, ENH_LAYER_COUNT, + BITRATE_MODE, __func__) || + !is_parent_available(inst, ENH_LAYER_COUNT, + META_EVA_STATS, __func__)) + return -EINVAL; + + if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) { + rc = msm_vidc_adjust_static_layer_count_and_type(inst, + client_layer_count); + if (rc) + goto exit; + } else { + if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR || + inst->hfi_layer_type == HFI_HIER_P_SLIDING_WINDOW) { + /* dynamic layer count change is only supported for HP */ + if (client_layer_count > + inst->capabilities->cap[ENH_LAYER_COUNT].max) + client_layer_count = + inst->capabilities->cap[ENH_LAYER_COUNT].max; + + msm_vidc_update_cap_value(inst, ENH_LAYER_COUNT, + client_layer_count, __func__); + } + } + +exit: + return rc; +} + +int msm_vidc_adjust_gop_size(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + s32 adjusted_value, enh_layer_count = -1; + u32 min_gop_size, num_subgops; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : capability->cap[GOP_SIZE].value; + + if (msm_vidc_get_parent_value(inst, GOP_SIZE, + ENH_LAYER_COUNT, &enh_layer_count, __func__)) + return -EINVAL; + + if (!enh_layer_count) + goto exit; + + /* + * Layer encoding needs GOP size to be multiple of subgop size + * And subgop size is 2 ^ number of enhancement layers. + */ + + /* v4l2 layer count is the number of enhancement layers */ + min_gop_size = 1 << enh_layer_count; + num_subgops = (adjusted_value + (min_gop_size >> 1)) / + min_gop_size; + if (num_subgops) + adjusted_value = num_subgops * min_gop_size; + else + adjusted_value = min_gop_size; + +exit: + msm_vidc_update_cap_value(inst, GOP_SIZE, adjusted_value, __func__); + return 0; +} + +int msm_vidc_adjust_b_frame(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + s32 adjusted_value, enh_layer_count = -1; + const u32 max_bframe_size = 7; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : capability->cap[B_FRAME].value; + + if (msm_vidc_get_parent_value(inst, B_FRAME, + ENH_LAYER_COUNT, &enh_layer_count, __func__)) + return -EINVAL; + + if (!enh_layer_count || inst->hfi_layer_type != HFI_HIER_B) { + adjusted_value = 0; + goto exit; + } + + adjusted_value = (1 << enh_layer_count) - 1; + /* Allowed Bframe values are 0, 1, 3, 7 */ + if (adjusted_value > max_bframe_size) + adjusted_value = max_bframe_size; + +exit: + msm_vidc_update_cap_value(inst, B_FRAME, adjusted_value, __func__); + return 0; +} + +int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl) +{ + int i, rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + struct msm_vidc_inst_capability *capability; + s32 adjusted_value, enh_layer_count; + u32 cumulative_bitrate = 0, cap_id = 0, cap_value = 0; + u32 layer_br_caps[6] = {L0_BR, L1_BR, L2_BR, L3_BR, L4_BR, L5_BR}; + u32 max_bitrate = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + /* ignore layer bitrate when total bitrate is set */ + if (capability->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) { + /* + * For static case, ctrl is null. + * For dynamic case, only BIT_RATE cap uses this adjust function. + * Hence, no need to check for ctrl id to be BIT_RATE control, and not + * any of layer bitrate controls. + */ + adjusted_value = ctrl ? ctrl->val : capability->cap[BIT_RATE].value; + msm_vidc_update_cap_value(inst, BIT_RATE, adjusted_value, __func__); + + return 0; + } + + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) + return 0; + + if (msm_vidc_get_parent_value(inst, BIT_RATE, + ENH_LAYER_COUNT, &enh_layer_count, __func__)) + return -EINVAL; + + /* get max bit rate for current session config*/ + max_bitrate = msm_vidc_get_max_bitrate(inst); + if (inst->capabilities->cap[BIT_RATE].value > max_bitrate) + msm_vidc_update_cap_value(inst, BIT_RATE, max_bitrate, __func__); + + /* + * ENH_LAYER_COUNT cap max is positive only if + * layer encoding is enabled during streamon. + */ + if (capability->cap[ENH_LAYER_COUNT].max) { + if (!msm_vidc_check_all_layer_bitrate_set(inst)) { + i_vpr_h(inst, + "%s: client did not set all layer bitrates\n", + __func__); + return 0; + } + + cumulative_bitrate = msm_vidc_get_cumulative_bitrate(inst); + + /* cap layer bitrates to max supported bitrate */ + if (cumulative_bitrate > max_bitrate) { + u32 decrement_in_value = 0; + u32 decrement_in_percent = ((cumulative_bitrate - max_bitrate) * 100) / + max_bitrate; + + cumulative_bitrate = 0; + for (i = 0; i <= enh_layer_count; i++) { + if (i >= ARRAY_SIZE(layer_br_caps)) + break; + cap_id = layer_br_caps[i]; + cap_value = inst->capabilities->cap[cap_id].value; + + decrement_in_value = (cap_value * + decrement_in_percent) / 100; + cumulative_bitrate += (cap_value - decrement_in_value); + + /* + * cap value for the L*_BR is changed. Hence, update cap, + * and add to FW_LIST to set new values to firmware. + */ + msm_vidc_update_cap_value(inst, cap_id, + (cap_value - decrement_in_value), __func__); + } + } + + i_vpr_h(inst, + "%s: update BIT_RATE with cumulative bitrate\n", + __func__); + msm_vidc_update_cap_value(inst, BIT_RATE, + cumulative_bitrate, __func__); + } + + return rc; +} + +int msm_vidc_adjust_dynamic_layer_bitrate(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + struct msm_vidc_inst_capability *capability; + u32 cumulative_bitrate = 0; + u32 client_set_cap_id = INST_CAP_NONE; + u32 old_br = 0, new_br = 0, exceeded_br = 0; + s32 max_bitrate; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + if (!ctrl) + return 0; + + /* ignore layer bitrate when total bitrate is set */ + if (capability->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) + return 0; + + if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) + return 0; + + /* + * ENH_LAYER_COUNT cap max is positive only if + * layer encoding is enabled during streamon. + */ + if (!capability->cap[ENH_LAYER_COUNT].max) { + i_vpr_e(inst, "%s: layers not enabled\n", __func__); + return -EINVAL; + } + + if (!msm_vidc_check_all_layer_bitrate_set(inst)) { + i_vpr_h(inst, + "%s: client did not set all layer bitrates\n", + __func__); + return 0; + } + + client_set_cap_id = msm_vidc_get_cap_id(inst, ctrl->id); + if (client_set_cap_id == INST_CAP_NONE) { + i_vpr_e(inst, "%s: could not find cap_id for ctrl %s\n", + __func__, ctrl->name); + return -EINVAL; + } + + cumulative_bitrate = msm_vidc_get_cumulative_bitrate(inst); + max_bitrate = inst->capabilities->cap[BIT_RATE].max; + old_br = capability->cap[client_set_cap_id].value; + new_br = ctrl->val; + + /* + * new bitrate is not supposed to cause cumulative bitrate to + * exceed max supported bitrate + */ + + if ((cumulative_bitrate - old_br + new_br) > max_bitrate) { + /* adjust new bitrate */ + exceeded_br = (cumulative_bitrate - old_br + new_br) - max_bitrate; + new_br = ctrl->val - exceeded_br; + } + msm_vidc_update_cap_value(inst, client_set_cap_id, new_br, __func__); + + /* adjust totol bitrate cap */ + i_vpr_h(inst, + "%s: update BIT_RATE with cumulative bitrate\n", + __func__); + msm_vidc_update_cap_value(inst, BIT_RATE, + msm_vidc_get_cumulative_bitrate(inst), __func__); + + return rc; +} + +int msm_vidc_adjust_peak_bitrate(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 rc_type = -1, bitrate = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[PEAK_BITRATE].value; + + if (msm_vidc_get_parent_value(inst, PEAK_BITRATE, + BITRATE_MODE, &rc_type, __func__)) + return -EINVAL; + + if (rc_type != HFI_RC_CBR_CFR && + rc_type != HFI_RC_CBR_VFR) + return 0; + + if (msm_vidc_get_parent_value(inst, PEAK_BITRATE, + BIT_RATE, &bitrate, __func__)) + return -EINVAL; + + /* Peak Bitrate should be larger than or equal to avg bitrate */ + if (capability->cap[PEAK_BITRATE].flags & CAP_FLAG_CLIENT_SET) { + if (adjusted_value < bitrate) + adjusted_value = bitrate; + } else { + adjusted_value = capability->cap[BIT_RATE].value; + } + + msm_vidc_update_cap_value(inst, PEAK_BITRATE, + adjusted_value, __func__); + + return 0; +} + +static int msm_vidc_adjust_hevc_qp(struct msm_vidc_inst *inst, + enum msm_vidc_inst_capability_type cap_id) +{ + struct msm_vidc_inst_capability *capability; + s32 pix_fmt = -1; + + capability = inst->capabilities; + + if (!(inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)) { + i_vpr_e(inst, + "%s: incorrect cap[%d] %s entry in database, fix database\n", + __func__, cap_id, cap_name(cap_id)); + return -EINVAL; + } + + if (msm_vidc_get_parent_value(inst, cap_id, + PIX_FMTS, &pix_fmt, __func__)) + return -EINVAL; + + if (pix_fmt == MSM_VIDC_FMT_P010 || pix_fmt == MSM_VIDC_FMT_TP10C) + goto exit; + + CAP_TO_8BIT_QP(capability->cap[cap_id].value); + if (cap_id == MIN_FRAME_QP) { + CAP_TO_8BIT_QP(capability->cap[I_FRAME_MIN_QP].value); + CAP_TO_8BIT_QP(capability->cap[P_FRAME_MIN_QP].value); + CAP_TO_8BIT_QP(capability->cap[B_FRAME_MIN_QP].value); + } else if (cap_id == MAX_FRAME_QP) { + CAP_TO_8BIT_QP(capability->cap[I_FRAME_MAX_QP].value); + CAP_TO_8BIT_QP(capability->cap[P_FRAME_MAX_QP].value); + CAP_TO_8BIT_QP(capability->cap[B_FRAME_MAX_QP].value); + } + +exit: + return 0; +} + +int msm_vidc_adjust_hevc_min_qp(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + if (ctrl) + msm_vidc_update_cap_value(inst, MIN_FRAME_QP, + ctrl->val, __func__); + + rc = msm_vidc_adjust_hevc_qp(inst, MIN_FRAME_QP); + + return rc; +} + +int msm_vidc_adjust_hevc_max_qp(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + if (ctrl) + msm_vidc_update_cap_value(inst, MAX_FRAME_QP, + ctrl->val, __func__); + + rc = msm_vidc_adjust_hevc_qp(inst, MAX_FRAME_QP); + + return rc; +} + +int msm_vidc_adjust_hevc_i_frame_qp(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + if (ctrl) + msm_vidc_update_cap_value(inst, I_FRAME_QP, + ctrl->val, __func__); + + rc = msm_vidc_adjust_hevc_qp(inst, I_FRAME_QP); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_adjust_hevc_p_frame_qp(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + if (ctrl) + msm_vidc_update_cap_value(inst, P_FRAME_QP, + ctrl->val, __func__); + + rc = msm_vidc_adjust_hevc_qp(inst, P_FRAME_QP); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_adjust_hevc_b_frame_qp(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + if (ctrl) + msm_vidc_update_cap_value(inst, B_FRAME_QP, + ctrl->val, __func__); + + rc = msm_vidc_adjust_hevc_qp(inst, B_FRAME_QP); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_adjust_blur_type(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 rc_type = -1, roi_enable = -1; + s32 pix_fmts = -1, min_quality = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[BLUR_TYPES].value; + + if (adjusted_value == MSM_VIDC_BLUR_NONE) + return 0; + + if (msm_vidc_get_parent_value(inst, BLUR_TYPES, BITRATE_MODE, + &rc_type, __func__) || + msm_vidc_get_parent_value(inst, BLUR_TYPES, PIX_FMTS, + &pix_fmts, __func__) || + msm_vidc_get_parent_value(inst, BLUR_TYPES, MIN_QUALITY, + &min_quality, __func__) || + msm_vidc_get_parent_value(inst, BLUR_TYPES, META_ROI_INFO, + &roi_enable, __func__)) + return -EINVAL; + + if (adjusted_value == MSM_VIDC_BLUR_EXTERNAL) { + if (is_scaling_enabled(inst) || min_quality) + adjusted_value = MSM_VIDC_BLUR_NONE; + } else if (adjusted_value == MSM_VIDC_BLUR_ADAPTIVE) { + if (is_scaling_enabled(inst) || min_quality || + (rc_type != HFI_RC_VBR_CFR && + rc_type != HFI_RC_CBR_CFR && + rc_type != HFI_RC_CBR_VFR) || + is_10bit_colorformat(pix_fmts) || roi_enable) { + adjusted_value = MSM_VIDC_BLUR_NONE; + } + } + + msm_vidc_update_cap_value(inst, BLUR_TYPES, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_all_intra(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_core *core; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 gop_size = -1, bframe = -1; + u32 width, height, fps, mbps, max_mbps; + + if (!inst || !inst->capabilities || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = capability->cap[ALL_INTRA].value; + + if (msm_vidc_get_parent_value(inst, ALL_INTRA, GOP_SIZE, + &gop_size, __func__) || + msm_vidc_get_parent_value(inst, ALL_INTRA, B_FRAME, + &bframe, __func__)) + return -EINVAL; + + width = inst->crop.width; + height = inst->crop.height; + fps = msm_vidc_get_fps(inst); + mbps = NUM_MBS_PER_SEC(height, width, fps); + core = inst->core; + max_mbps = core->capabilities[MAX_MBPS_ALL_INTRA].value; + + if (mbps > max_mbps) { + adjusted_value = 0; + i_vpr_h(inst, "%s: mbps %d exceeds max supported mbps %d\n", + __func__, mbps, max_mbps); + goto exit; + } + + if (!gop_size && !bframe) + adjusted_value = 1; + +exit: + msm_vidc_update_cap_value(inst, ALL_INTRA, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_blur_resolution(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 blur_type = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[BLUR_RESOLUTION].value; + + if (msm_vidc_get_parent_value(inst, BLUR_RESOLUTION, BLUR_TYPES, + &blur_type, __func__)) + return -EINVAL; + + if (blur_type != MSM_VIDC_BLUR_EXTERNAL) + return 0; + + msm_vidc_update_cap_value(inst, BLUR_RESOLUTION, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_brs(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 rc_type = -1, layer_enabled = -1, layer_type = -1; + bool hp_requested = false; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[CONTENT_ADAPTIVE_CODING].value; + + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) + return 0; + + if (msm_vidc_get_parent_value(inst, CONTENT_ADAPTIVE_CODING, + BITRATE_MODE, &rc_type, __func__) || + msm_vidc_get_parent_value(inst, CONTENT_ADAPTIVE_CODING, + LAYER_ENABLE, &layer_enabled, __func__) || + msm_vidc_get_parent_value(inst, CONTENT_ADAPTIVE_CODING, + LAYER_TYPE, &layer_type, __func__)) + return -EINVAL; + + /* + * -BRS is supported only for VBR rc type. + * Hence, do not adjust or set to firmware for non VBR rc's + * -If HP is enabled then BRS is not allowed. + */ + if (rc_type != HFI_RC_VBR_CFR) { + adjusted_value = 0; + goto adjust; + } + + if (inst->codec == MSM_VIDC_H264) + layer_type = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P; + else if (inst->codec == MSM_VIDC_HEVC) + layer_type = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P; + + hp_requested = (inst->capabilities->cap[LAYER_TYPE].value == layer_type); + + /* + * Disable BRS in case of HP encoding + * Hence set adjust value to 0. + */ + if (layer_enabled == 1 && hp_requested) { + adjusted_value = 0; + goto adjust; + } + +adjust: + msm_vidc_update_cap_value(inst, CONTENT_ADAPTIVE_CODING, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_bitrate_boost(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 min_quality = -1, rc_type = -1; + u32 max_bitrate = 0, bitrate = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[BITRATE_BOOST].value; + + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) + return 0; + + if (msm_vidc_get_parent_value(inst, BITRATE_BOOST, + MIN_QUALITY, &min_quality, __func__) || + msm_vidc_get_parent_value(inst, BITRATE_BOOST, + BITRATE_MODE, &rc_type, __func__)) + return -EINVAL; + + /* + * Bitrate Boost are supported only for VBR rc type. + * Hence, do not adjust or set to firmware for non VBR rc's + */ + if (rc_type != HFI_RC_VBR_CFR) { + adjusted_value = 0; + goto adjust; + } + + if (min_quality) { + adjusted_value = MAX_BITRATE_BOOST; + goto adjust; + } + + max_bitrate = msm_vidc_get_max_bitrate(inst); + bitrate = inst->capabilities->cap[BIT_RATE].value; + if (adjusted_value) { + if ((bitrate + bitrate / (100 / adjusted_value)) > max_bitrate) { + i_vpr_h(inst, + "%s: bitrate %d is beyond max bitrate %d, remove bitrate boost\n", + __func__, max_bitrate, bitrate); + adjusted_value = 0; + } + } + +adjust: + msm_vidc_update_cap_value(inst, BITRATE_BOOST, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_min_quality(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 roi_enable = -1, rc_type = -1, enh_layer_count = -1, pix_fmts = -1; + u32 width, height, frame_rate; + struct v4l2_format *f; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : capability->cap[MIN_QUALITY].value; + + /* + * Although MIN_QUALITY is static, one of its parents, + * ENH_LAYER_COUNT is dynamic cap. Hence, dynamic call + * may be made for MIN_QUALITY via ENH_LAYER_COUNT. + * Therefore, below streaming check is required to avoid + * runtime modification of MIN_QUALITY. + */ + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) + return 0; + + if (msm_vidc_get_parent_value(inst, MIN_QUALITY, + BITRATE_MODE, &rc_type, __func__) || + msm_vidc_get_parent_value(inst, MIN_QUALITY, + META_ROI_INFO, &roi_enable, __func__) || + msm_vidc_get_parent_value(inst, MIN_QUALITY, + ENH_LAYER_COUNT, &enh_layer_count, __func__)) + return -EINVAL; + + /* + * Min Quality is supported only for VBR rc type. + * Hence, do not adjust or set to firmware for non VBR rc's + */ + if (rc_type != HFI_RC_VBR_CFR) { + adjusted_value = 0; + goto update_and_exit; + } + + frame_rate = inst->capabilities->cap[FRAME_RATE].value >> 16; + f = &inst->fmts[OUTPUT_PORT]; + width = f->fmt.pix_mp.width; + height = f->fmt.pix_mp.height; + + /* + * VBR Min Quality not supported for: + * - HEVC 10bit + * - ROI support + * - HP encoding + * - External Blur + * - Resolution beyond 1080P + * (It will fall back to CQCAC 25% or 0% (CAC) or CQCAC-OFF) + */ + if (inst->codec == MSM_VIDC_HEVC) { + if (msm_vidc_get_parent_value(inst, MIN_QUALITY, + PIX_FMTS, &pix_fmts, __func__)) + return -EINVAL; + + if (is_10bit_colorformat(pix_fmts)) { + i_vpr_h(inst, + "%s: min quality is supported only for 8 bit\n", + __func__); + adjusted_value = 0; + goto update_and_exit; + } + } + + if (res_is_greater_than(width, height, 1920, 1080)) { + i_vpr_h(inst, "%s: unsupported res, wxh %ux%u\n", + __func__, width, height); + adjusted_value = 0; + goto update_and_exit; + } + + if (frame_rate > 60) { + i_vpr_h(inst, "%s: unsupported fps %u\n", + __func__, frame_rate); + adjusted_value = 0; + goto update_and_exit; + } + + if (is_meta_tx_inp_enabled(inst, META_ROI_INFO)) { + i_vpr_h(inst, + "%s: min quality not supported with roi metadata\n", + __func__); + adjusted_value = 0; + goto update_and_exit; + } + + if (enh_layer_count > 0 && inst->hfi_layer_type != HFI_HIER_B) { + i_vpr_h(inst, + "%s: min quality not supported for HP encoding\n", + __func__); + adjusted_value = 0; + goto update_and_exit; + } + + /* Above conditions are met. Hence enable min quality */ + adjusted_value = MAX_SUPPORTED_MIN_QUALITY; + +update_and_exit: + msm_vidc_update_cap_value(inst, MIN_QUALITY, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_preprocess(void *instance, struct v4l2_ctrl *ctrl) +{ + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 brs = -1, eva_status = -1; + u32 width, height, frame_rate, operating_rate, max_fps; + struct v4l2_format *f; + + if (!inst || !inst->capabilities || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + adjusted_value = inst->capabilities->cap[REQUEST_PREPROCESS].value; + + if (msm_vidc_get_parent_value(inst, REQUEST_PREPROCESS, CONTENT_ADAPTIVE_CODING, + &brs, __func__) || + msm_vidc_get_parent_value(inst, REQUEST_PREPROCESS, META_EVA_STATS, + &eva_status, __func__)) + return -EINVAL; + + width = inst->crop.width; + height = inst->crop.height; + frame_rate = msm_vidc_get_frame_rate(inst); + operating_rate = msm_vidc_get_operating_rate(inst); + + max_fps = max(frame_rate, operating_rate); + f = &inst->fmts[OUTPUT_PORT]; + + /* + * enable preprocess if + * client did not enable EVA metadata statistics and + * BRS enabled and upto 4k @ 60 fps + */ + if (!is_meta_tx_inp_enabled(inst, META_EVA_STATS) && + brs == 1 && + res_is_less_than_or_equal_to(width, height, 3840, 2160) && + max_fps <= 60) + adjusted_value = 1; + else + adjusted_value = 0; + + msm_vidc_update_cap_value(inst, REQUEST_PREPROCESS, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_enc_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 rc_type = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[LOWLATENCY_MODE].value; + + if (msm_vidc_get_parent_value(inst, LOWLATENCY_MODE, BITRATE_MODE, + &rc_type, __func__)) + return -EINVAL; + + if (rc_type == HFI_RC_CBR_CFR || + rc_type == HFI_RC_CBR_VFR || + is_enc_slice_delivery_mode(inst)) + adjusted_value = 1; + + msm_vidc_update_cap_value(inst, LOWLATENCY_MODE, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_dec_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 outbuf_fence = MSM_VIDC_META_DISABLE; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[LOWLATENCY_MODE].value; + + if (msm_vidc_get_parent_value(inst, LOWLATENCY_MODE, META_OUTBUF_FENCE, + &outbuf_fence, __func__)) + return -EINVAL; + + /* enable lowlatency if outbuf fence is enabled */ + if (outbuf_fence & MSM_VIDC_META_ENABLE && + outbuf_fence & MSM_VIDC_META_RX_INPUT) + adjusted_value = 1; + + msm_vidc_update_cap_value(inst, LOWLATENCY_MODE, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_session_priority(void *instance, struct v4l2_ctrl *ctrl) +{ + int adjusted_value; + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + /* + * Priority handling + * Client will set 0 (realtime), 1+ (non-realtime) + * Driver adds NRT_PRIORITY_OFFSET (2) to clients non-realtime priority + * and hence PRIORITY values in the driver become 0, 3+. + * Driver may move decode realtime sessions to non-realtime by + * increasing priority by 1 to RT sessions in HW overloaded cases. + * So driver PRIORITY values can be 0, 1, 3+. + * When driver setting priority to firmware, driver adds + * FIRMWARE_PRIORITY_OFFSET (1) for all sessions except + * non-critical sessions. So finally firmware priority values ranges + * from 0 (Critical session), 1 (realtime session), + * 2+ (non-realtime session) + */ + if (ctrl) { + /* add offset when client sets non-realtime */ + if (ctrl->val) + adjusted_value = ctrl->val + NRT_PRIORITY_OFFSET; + else + adjusted_value = ctrl->val; + } else { + adjusted_value = capability->cap[PRIORITY].value; + } + + msm_vidc_update_cap_value(inst, PRIORITY, adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_roi_info(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 rc_type = -1, pix_fmt = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : capability->cap[META_ROI_INFO].value; + + if (msm_vidc_get_parent_value(inst, META_ROI_INFO, BITRATE_MODE, + &rc_type, __func__)) + return -EINVAL; + + if (msm_vidc_get_parent_value(inst, META_ROI_INFO, PIX_FMTS, + &pix_fmt, __func__)) + return -EINVAL; + + if ((rc_type != HFI_RC_VBR_CFR && rc_type != HFI_RC_CBR_CFR + && rc_type != HFI_RC_CBR_VFR) || !is_8bit_colorformat(pix_fmt) + || is_scaling_enabled(inst) || is_rotation_90_or_270(inst)) + adjusted_value = 0; + + msm_vidc_update_cap_value(inst, META_ROI_INFO, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_dec_outbuf_fence(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + u32 adjusted_value = 0; + s32 picture_order = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : capability->cap[META_OUTBUF_FENCE].value; + + if (msm_vidc_get_parent_value(inst, META_OUTBUF_FENCE, OUTPUT_ORDER, + &picture_order, __func__)) + return -EINVAL; + + if (picture_order == 0) { + /* disable outbuf fence */ + adjusted_value = MSM_VIDC_META_DISABLE | + MSM_VIDC_META_RX_INPUT; + } + + msm_vidc_update_cap_value(inst, META_OUTBUF_FENCE, + adjusted_value, __func__); + + return 0; +} + +int msm_vidc_adjust_dec_slice_mode(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + u32 adjusted_value = 0; + s32 low_latency = -1; + s32 picture_order = -1; + s32 outbuf_fence = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : capability->cap[SLICE_DECODE].value; + + if (msm_vidc_get_parent_value(inst, SLICE_DECODE, LOWLATENCY_MODE, + &low_latency, __func__) || + msm_vidc_get_parent_value(inst, SLICE_DECODE, OUTPUT_ORDER, + &picture_order, __func__) || + msm_vidc_get_parent_value(inst, SLICE_DECODE, META_OUTBUF_FENCE, + &outbuf_fence, __func__)) + return -EINVAL; + + if (!low_latency || !picture_order || + !is_meta_rx_inp_enabled(inst, META_OUTBUF_FENCE)) + adjusted_value = 0; + + msm_vidc_update_cap_value(inst, SLICE_DECODE, + adjusted_value, __func__); + + return 0; +} + +/******************* End of Control Adjust functions *************************/ + +/************************* Control Set functions *****************************/ + +int msm_vidc_set_header_mode(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + int header_mode, prepend_sps_pps; + u32 hfi_value = 0; + struct msm_vidc_inst_capability *capability; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + header_mode = capability->cap[cap_id].value; + prepend_sps_pps = capability->cap[PREPEND_SPSPPS_TO_IDR].value; + + /* prioritize PREPEND_SPSPPS_TO_IDR mode over other header modes */ + if (prepend_sps_pps) + hfi_value = HFI_SEQ_HEADER_PREFIX_WITH_SYNC_FRAME; + else if (header_mode == V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME) + hfi_value = HFI_SEQ_HEADER_JOINED_WITH_1ST_FRAME; + else + hfi_value = HFI_SEQ_HEADER_SEPERATE_FRAME; + + if (is_meta_rx_out_enabled(inst, META_SEQ_HDR_NAL)) + hfi_value |= HFI_SEQ_HEADER_METADATA; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_deblock_mode(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 alpha = 0, beta = 0; + u32 lf_mode, hfi_value = 0, lf_offset = 6; + struct msm_vidc_inst_capability *capability; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + rc = msm_vidc_v4l2_to_hfi_enum(inst, LF_MODE, &lf_mode); + if (rc) + return -EINVAL; + + beta = inst->capabilities->cap[LF_BETA].value + lf_offset; + alpha = inst->capabilities->cap[LF_ALPHA].value + lf_offset; + hfi_value = (alpha << 16) | (beta << 8) | lf_mode; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_constant_quality(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 = 0; + s32 rc_type = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (msm_vidc_get_parent_value(inst, cap_id, + BITRATE_MODE, &rc_type, __func__)) + return -EINVAL; + + if (rc_type != HFI_RC_CQ) + return 0; + + hfi_value = inst->capabilities->cap[cap_id].value; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_vbr_related_properties(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 = 0; + s32 rc_type = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (msm_vidc_get_parent_value(inst, cap_id, + BITRATE_MODE, &rc_type, __func__)) + return -EINVAL; + + if (rc_type != HFI_RC_VBR_CFR) + return 0; + + hfi_value = inst->capabilities->cap[cap_id].value; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_cbr_related_properties(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 = 0; + s32 rc_type = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (msm_vidc_get_parent_value(inst, cap_id, + BITRATE_MODE, &rc_type, __func__)) + return -EINVAL; + + if (rc_type != HFI_RC_CBR_VFR && + rc_type != HFI_RC_CBR_CFR) + return 0; + + hfi_value = inst->capabilities->cap[cap_id].value; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_use_and_mark_ltr(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 = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (!inst->capabilities->cap[LTR_COUNT].value || + (inst->capabilities->cap[cap_id].value == + INVALID_DEFAULT_MARK_OR_USE_LTR)) { + i_vpr_h(inst, + "%s: LTR_COUNT: %d %s: %d, cap %s is not set\n", + __func__, inst->capabilities->cap[LTR_COUNT].value, + cap_name(cap_id), + inst->capabilities->cap[cap_id].value, + cap_name(cap_id)); + return 0; + } + + hfi_value = inst->capabilities->cap[cap_id].value; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_min_qp(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + struct msm_vidc_inst_capability *capability; + s32 i_frame_qp = 0, p_frame_qp = 0, b_frame_qp = 0, min_qp_enable = 0; + u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0; + u32 client_qp_enable = 0, hfi_value = 0, offset = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + if (capability->cap[MIN_FRAME_QP].flags & CAP_FLAG_CLIENT_SET) + min_qp_enable = 1; + + if (min_qp_enable || + (capability->cap[I_FRAME_MIN_QP].flags & CAP_FLAG_CLIENT_SET)) + i_qp_enable = 1; + if (min_qp_enable || + (capability->cap[P_FRAME_MIN_QP].flags & CAP_FLAG_CLIENT_SET)) + p_qp_enable = 1; + if (min_qp_enable || + (capability->cap[B_FRAME_MIN_QP].flags & CAP_FLAG_CLIENT_SET)) + b_qp_enable = 1; + + client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; + if (!client_qp_enable) { + i_vpr_h(inst, + "%s: client did not set min qp, cap %s is not set\n", + __func__, cap_name(cap_id)); + return 0; + } + + if (is_10bit_colorformat(capability->cap[PIX_FMTS].value)) + offset = 12; + + /* + * I_FRAME_MIN_QP, P_FRAME_MIN_QP, B_FRAME_MIN_QP, + * MIN_FRAME_QP caps have default value as MIN_QP_10BIT values. + * Hence, if client sets either one among MIN_FRAME_QP + * and (I_FRAME_MIN_QP or P_FRAME_MIN_QP or B_FRAME_MIN_QP), + * max of both caps will result into client set value. + */ + i_frame_qp = max(capability->cap[I_FRAME_MIN_QP].value, + capability->cap[MIN_FRAME_QP].value) + offset; + p_frame_qp = max(capability->cap[P_FRAME_MIN_QP].value, + capability->cap[MIN_FRAME_QP].value) + offset; + b_frame_qp = max(capability->cap[B_FRAME_MIN_QP].value, + capability->cap[MIN_FRAME_QP].value) + offset; + + hfi_value = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | + client_qp_enable << 24; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_max_qp(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + struct msm_vidc_inst_capability *capability; + s32 i_frame_qp = 0, p_frame_qp = 0, b_frame_qp = 0, max_qp_enable = 0; + u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0; + u32 client_qp_enable = 0, hfi_value = 0, offset = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + if (capability->cap[MAX_FRAME_QP].flags & CAP_FLAG_CLIENT_SET) + max_qp_enable = 1; + + if (max_qp_enable || + (capability->cap[I_FRAME_MAX_QP].flags & CAP_FLAG_CLIENT_SET)) + i_qp_enable = 1; + if (max_qp_enable || + (capability->cap[P_FRAME_MAX_QP].flags & CAP_FLAG_CLIENT_SET)) + p_qp_enable = 1; + if (max_qp_enable || + (capability->cap[B_FRAME_MAX_QP].flags & CAP_FLAG_CLIENT_SET)) + b_qp_enable = 1; + + client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; + if (!client_qp_enable) { + i_vpr_h(inst, + "%s: client did not set max qp, cap %s is not set\n", + __func__, cap_name(cap_id)); + return 0; + } + + if (is_10bit_colorformat(capability->cap[PIX_FMTS].value)) + offset = 12; + + /* + * I_FRAME_MAX_QP, P_FRAME_MAX_QP, B_FRAME_MAX_QP, + * MAX_FRAME_QP caps have default value as MAX_QP values. + * Hence, if client sets either one among MAX_FRAME_QP + * and (I_FRAME_MAX_QP or P_FRAME_MAX_QP or B_FRAME_MAX_QP), + * min of both caps will result into client set value. + */ + i_frame_qp = min(capability->cap[I_FRAME_MAX_QP].value, + capability->cap[MAX_FRAME_QP].value) + offset; + p_frame_qp = min(capability->cap[P_FRAME_MAX_QP].value, + capability->cap[MAX_FRAME_QP].value) + offset; + b_frame_qp = min(capability->cap[B_FRAME_MAX_QP].value, + capability->cap[MAX_FRAME_QP].value) + offset; + + hfi_value = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | + client_qp_enable << 24; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_frame_qp(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + struct msm_vidc_inst_capability *capab; + s32 i_frame_qp = 0, p_frame_qp = 0, b_frame_qp = 0; + u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0; + u32 client_qp_enable = 0, hfi_value = 0, offset = 0; + s32 rc_type = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capab = inst->capabilities; + + if (msm_vidc_get_parent_value(inst, cap_id, + BITRATE_MODE, &rc_type, __func__)) + return -EINVAL; + + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) { + if (rc_type != HFI_RC_OFF) { + i_vpr_h(inst, + "%s: dynamic qp not allowed for rc type %d\n", + __func__, rc_type); + return 0; + } + } + + if (rc_type == HFI_RC_OFF) { + /* Mandatorily set for rc off case */ + i_qp_enable = p_qp_enable = b_qp_enable = 1; + } else { + /* Set only if client has set for NON rc off case */ + if (capab->cap[I_FRAME_QP].flags & CAP_FLAG_CLIENT_SET) + i_qp_enable = 1; + if (capab->cap[P_FRAME_QP].flags & CAP_FLAG_CLIENT_SET) + p_qp_enable = 1; + if (capab->cap[B_FRAME_QP].flags & CAP_FLAG_CLIENT_SET) + b_qp_enable = 1; + } + + client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; + if (!client_qp_enable) { + i_vpr_h(inst, + "%s: client did not set frame qp, cap %s is not set\n", + __func__, cap_name(cap_id)); + return 0; + } + + if (is_10bit_colorformat(capab->cap[PIX_FMTS].value)) + offset = 12; + + i_frame_qp = capab->cap[I_FRAME_QP].value + offset; + p_frame_qp = capab->cap[P_FRAME_QP].value + offset; + b_frame_qp = capab->cap[B_FRAME_QP].value + offset; + + hfi_value = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | + client_qp_enable << 24; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_req_sync_frame(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + s32 prepend_spspps; + u32 hfi_value = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + prepend_spspps = inst->capabilities->cap[PREPEND_SPSPPS_TO_IDR].value; + if (prepend_spspps) + hfi_value = HFI_SYNC_FRAME_REQUEST_WITH_PREFIX_SEQ_HDR; + else + hfi_value = HFI_SYNC_FRAME_REQUEST_WITHOUT_SEQ_HDR; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_chroma_qp_index_offset(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 = 0, chroma_qp_offset_mode = 0, chroma_qp = 0; + u32 offset = 12; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (inst->capabilities->cap[cap_id].flags & CAP_FLAG_CLIENT_SET) + chroma_qp_offset_mode = HFI_FIXED_CHROMAQP_OFFSET; + else + chroma_qp_offset_mode = HFI_ADAPTIVE_CHROMAQP_OFFSET; + + chroma_qp = inst->capabilities->cap[cap_id].value + offset; + hfi_value = chroma_qp_offset_mode | chroma_qp << 8 | chroma_qp << 16; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_slice_count(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + s32 slice_mode = -1; + u32 hfi_value = 0, set_cap_id = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + slice_mode = inst->capabilities->cap[SLICE_MODE].value; + + if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) { + i_vpr_h(inst, "%s: slice mode is: %u, ignore setting to fw\n", + __func__, slice_mode); + return 0; + } + if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) { + hfi_value = (inst->codec == MSM_VIDC_HEVC) ? + ((inst->capabilities->cap[SLICE_MAX_MB].value + 3) / 4) : + inst->capabilities->cap[SLICE_MAX_MB].value; + set_cap_id = SLICE_MAX_MB; + } else if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) { + hfi_value = inst->capabilities->cap[SLICE_MAX_BYTES].value; + set_cap_id = SLICE_MAX_BYTES; + } + + rc = msm_vidc_packetize_control(inst, set_cap_id, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_nal_length(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 = HFI_NAL_LENGTH_STARTCODES; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (!inst->capabilities->cap[WITHOUT_STARTCODE].value) { + hfi_value = HFI_NAL_LENGTH_STARTCODES; + } else { + rc = msm_vidc_v4l2_to_hfi_enum(inst, NAL_LENGTH_FIELD, &hfi_value); + if (rc) + return -EINVAL; + } + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_layer_count_and_type(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_layer_count, hfi_layer_type = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) { + /* set layer type */ + hfi_layer_type = inst->hfi_layer_type; + cap_id = LAYER_TYPE; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, + &hfi_layer_type, sizeof(u32), __func__); + if (rc) + goto exit; + } else { + if (inst->hfi_layer_type == HFI_HIER_B) { + i_vpr_l(inst, + "%s: HB dyn layers change is not supported\n", + __func__); + return 0; + } + } + + /* set layer count */ + cap_id = ENH_LAYER_COUNT; + /* hfi baselayer starts from 1 */ + hfi_layer_count = inst->capabilities->cap[ENH_LAYER_COUNT].value + 1; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &hfi_layer_count, sizeof(u32), __func__); + if (rc) + goto exit; + +exit: + return rc; +} + +int msm_vidc_set_gop_size(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; + } + + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) { + if (inst->hfi_layer_type == HFI_HIER_B) { + i_vpr_l(inst, + "%s: HB dyn GOP setting is not supported\n", + __func__); + return 0; + } + } + + hfi_value = inst->capabilities->cap[GOP_SIZE].value; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_bitrate(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0, i; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + u32 hfi_value = 0; + s32 rc_type = -1, enh_layer_count = -1; + u32 layer_br_caps[6] = {L0_BR, L1_BR, L2_BR, L3_BR, L4_BR, L5_BR}; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + /* set Total Bitrate */ + if (inst->capabilities->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) + goto set_total_bitrate; + + /* + * During runtime, if BIT_RATE cap CLIENT_SET flag is not set, + * then this function will be called due to change in ENH_LAYER_COUNT. + * In this case, client did not change bitrate, hence, no need to set + * to fw. + */ + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) + return 0; + + if (msm_vidc_get_parent_value(inst, BIT_RATE, + BITRATE_MODE, &rc_type, __func__)) + return -EINVAL; + + if (rc_type != HFI_RC_CBR_CFR && rc_type != HFI_RC_CBR_VFR) { + i_vpr_h(inst, "%s: set total bitrate for non CBR rc type\n", + __func__); + goto set_total_bitrate; + } + + if (msm_vidc_get_parent_value(inst, BIT_RATE, + ENH_LAYER_COUNT, &enh_layer_count, __func__)) + return -EINVAL; + + /* + * ENH_LAYER_COUNT cap max is positive only if + * layer encoding is enabled during streamon. + */ + if (inst->capabilities->cap[ENH_LAYER_COUNT].max) { + if (!msm_vidc_check_all_layer_bitrate_set(inst)) + goto set_total_bitrate; + + /* set Layer Bitrate */ + for (i = 0; i <= enh_layer_count; i++) { + if (i >= ARRAY_SIZE(layer_br_caps)) + break; + cap_id = layer_br_caps[i]; + hfi_value = inst->capabilities->cap[cap_id].value; + rc = msm_vidc_packetize_control(inst, cap_id, + HFI_PAYLOAD_U32, &hfi_value, + sizeof(u32), __func__); + if (rc) + return rc; + } + goto exit; + } + +set_total_bitrate: + hfi_value = inst->capabilities->cap[BIT_RATE].value; + rc = msm_vidc_packetize_control(inst, BIT_RATE, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; +exit: + return rc; +} + +int msm_vidc_set_dynamic_layer_bitrate(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 = 0; + s32 rc_type = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) + return 0; + + /* set Total Bitrate */ + if (inst->capabilities->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) { + i_vpr_h(inst, + "%s: Total bitrate is set, ignore layer bitrate\n", + __func__); + return 0; + } + + /* + * ENH_LAYER_COUNT cap max is positive only if + * layer encoding is enabled during streamon. + */ + if (!inst->capabilities->cap[ENH_LAYER_COUNT].max || + !msm_vidc_check_all_layer_bitrate_set(inst)) { + i_vpr_h(inst, + "%s: invalid layer bitrate, ignore setting to fw\n", + __func__); + return 0; + } + + if (inst->hfi_rc_type == HFI_RC_CBR_CFR || + rc_type == HFI_RC_CBR_VFR) { + /* set layer bitrate for the client set layer */ + hfi_value = inst->capabilities->cap[cap_id].value; + rc = msm_vidc_packetize_control(inst, cap_id, + HFI_PAYLOAD_U32, &hfi_value, + sizeof(u32), __func__); + if (rc) + return rc; + } else { + /* + * All layer bitartes set for unsupported rc type. + * Hence accept layer bitrates, but set total bitrate prop + * with cumulative bitrate. + */ + hfi_value = inst->capabilities->cap[BIT_RATE].value; + rc = msm_vidc_packetize_control(inst, BIT_RATE, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + } + + return rc; +} + +int msm_vidc_set_session_priority(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + u32 hfi_value = 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; + } + + hfi_value = inst->capabilities->cap[cap_id].value; + if (!is_critical_priority_session(inst)) + hfi_value = inst->capabilities->cap[cap_id].value + + inst->capabilities->cap[FIRMWARE_PRIORITY_OFFSET].value; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_flip(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + u32 hflip, vflip, hfi_value = HFI_DISABLE_FLIP; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + hflip = inst->capabilities->cap[HFLIP].value; + vflip = inst->capabilities->cap[VFLIP].value; + + if (hflip) + hfi_value |= HFI_HORIZONTAL_FLIP; + + if (vflip) + hfi_value |= HFI_VERTICAL_FLIP; + + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) { + if (hfi_value != HFI_DISABLE_FLIP) { + rc = msm_vidc_set_req_sync_frame(inst, + REQUEST_I_FRAME); + if (rc) + return rc; + } + } + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_preprocess(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_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_rotation(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_to_hfi_enum(inst, cap_id, &hfi_value); + if (rc) + return -EINVAL; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_blur_resolution(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + s32 blur_type = -1; + u32 hfi_value, blur_width, blur_height; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (msm_vidc_get_parent_value(inst, cap_id, + BLUR_TYPES, &blur_type, __func__)) + return -EINVAL; + + if (blur_type != MSM_VIDC_BLUR_EXTERNAL) + return 0; + + hfi_value = inst->capabilities->cap[cap_id].value; + + blur_width = (hfi_value & 0xFFFF0000) >> 16; + blur_height = hfi_value & 0xFFFF; + + if (blur_width > inst->crop.width || + blur_height > inst->crop.height) { + i_vpr_e(inst, + "%s: blur wxh: %dx%d exceeds crop wxh: %dx%d\n", + __func__, blur_width, blur_height, + inst->crop.width, inst->crop.height); + hfi_value = 0; + } + + if (blur_width == inst->crop.width && + blur_height == inst->crop.height) { + i_vpr_e(inst, + "%s: blur wxh: %dx%d is equal to crop wxh: %dx%d\n", + __func__, blur_width, blur_height, + inst->crop.width, inst->crop.height); + hfi_value = 0; + } + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +static int msm_venc_set_csc_coeff(struct msm_vidc_inst *inst, + const char *prop_name, u32 hfi_id, void *payload, + u32 payload_size, u32 row_count, u32 column_count) +{ + int rc = 0; + + i_vpr_h(inst, + "set cap: name: %24s, hard coded %dx%d matrix array\n", + prop_name, row_count, column_count); + rc = venus_hfi_session_property(inst, + hfi_id, + HFI_HOST_FLAGS_NONE, + HFI_PORT_BITSTREAM, + HFI_PAYLOAD_S32_ARRAY, + payload, + payload_size); + if (rc) { + i_vpr_e(inst, + "%s: failed to set %s to fw\n", + __func__, prop_name); + } + + return rc; +} +int msm_vidc_set_csc_custom_matrix(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + int i; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + struct msm_vidc_core *core; + struct msm_vidc_csc_coeff *csc_coeff; + s32 matrix_payload[MAX_MATRIX_COEFFS + 2]; + s32 csc_bias_payload[MAX_BIAS_COEFFS + 2]; + s32 csc_limit_payload[MAX_LIMIT_COEFFS + 2]; + + if (!inst || !inst->capabilities || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + core = inst->core; + if (!core->platform) { + d_vpr_e("%s: invalid core platform\n", __func__); + return -EINVAL; + } + csc_coeff = &core->platform->data.csc_data; + + if (!inst->capabilities->cap[cap_id].value || + !inst->capabilities->cap[CSC].value) { + i_vpr_h(inst, + "%s: ignored as custom martix %u, csc %u\n", + __func__, inst->capabilities->cap[cap_id].value, + inst->capabilities->cap[CSC].value); + return 0; + } + + /* + * first 2 u32's of payload in each case are for + * row and column count, next remaining u32's are + * for the actual payload values. + */ + + /* set custom matrix */ + matrix_payload[0] = 3; + matrix_payload[1] = 3; + + for (i = 0; i < MAX_MATRIX_COEFFS; i++) { + if ((i + 2) >= ARRAY_SIZE(matrix_payload)) + break; + matrix_payload[i + 2] = + csc_coeff->vpe_csc_custom_matrix_coeff[i]; + } + + rc = msm_venc_set_csc_coeff(inst, "CSC_CUSTOM_MATRIX", + HFI_PROP_CSC_MATRIX, &matrix_payload[0], + ARRAY_SIZE(matrix_payload) * sizeof(s32), + matrix_payload[0], matrix_payload[1]); + if (rc) + return rc; + + /* set csc bias */ + csc_bias_payload[0] = 1; + csc_bias_payload[1] = 3; + + for (i = 0; i < MAX_BIAS_COEFFS; i++) { + if ((i + 2) >= ARRAY_SIZE(csc_bias_payload)) + break; + csc_bias_payload[i + 2] = + csc_coeff->vpe_csc_custom_bias_coeff[i]; + } + + rc = msm_venc_set_csc_coeff(inst, "CSC_BIAS", + HFI_PROP_CSC_BIAS, &csc_bias_payload[0], + ARRAY_SIZE(csc_bias_payload) * sizeof(s32), + csc_bias_payload[0], csc_bias_payload[1]); + if (rc) + return rc; + + /* set csc limit */ + csc_limit_payload[0] = 1; + csc_limit_payload[1] = 6; + + for (i = 0; i < MAX_LIMIT_COEFFS; i++) { + if ((i + 2) >= ARRAY_SIZE(csc_limit_payload)) + break; + csc_limit_payload[i + 2] = + csc_coeff->vpe_csc_custom_limit_coeff[i]; + } + + rc = msm_venc_set_csc_coeff(inst, "CSC_LIMIT", + HFI_PROP_CSC_LIMIT, &csc_limit_payload[0], + ARRAY_SIZE(csc_limit_payload) * sizeof(s32), + csc_limit_payload[0], csc_limit_payload[1]); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_reserve_duration(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + u32 hfi_value = 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; + } + + /* reserve hardware only when input port is streaming*/ + if (!inst->bufq[INPUT_PORT].vb2q->streaming) + return 0; + + if (!(inst->capabilities->cap[cap_id].flags & CAP_FLAG_CLIENT_SET)) + return 0; + + inst->capabilities->cap[cap_id].flags &= (~CAP_FLAG_CLIENT_SET); + + if (!is_critical_priority_session(inst)) { + i_vpr_h(inst, "%s: reserve duration allowed only for critical session\n", __func__); + return 0; + } + + hfi_value = inst->capabilities->cap[cap_id].value; + + rc = venus_hfi_reserve_hardware(inst, hfi_value); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_level(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 = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + hfi_value = inst->capabilities->cap[cap_id].value; + if (!(inst->capabilities->cap[cap_id].flags & CAP_FLAG_CLIENT_SET)) + hfi_value = HFI_LEVEL_NONE; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_q16(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 = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + hfi_value = inst->capabilities->cap[cap_id].value; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_Q16, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + 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; + } + + if (inst->capabilities->cap[cap_id].flags & CAP_FLAG_MENU) { + rc = msm_vidc_v4l2_menu_to_hfi(inst, cap_id, &hfi_value); + if (rc) + return -EINVAL; + } else { + hfi_value = inst->capabilities->cap[cap_id].value; + } + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_u32_packed(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; + } + + if (inst->capabilities->cap[cap_id].flags & CAP_FLAG_MENU) { + rc = msm_vidc_v4l2_menu_to_hfi(inst, cap_id, &hfi_value); + if (rc) + return -EINVAL; + } else { + hfi_value = inst->capabilities->cap[cap_id].value; + } + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_u32_enum(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_to_hfi_enum(inst, cap_id, &hfi_value); + if (rc) + return -EINVAL; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + 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; + s32 hfi_value = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + hfi_value = inst->capabilities->cap[cap_id].value; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_S32, + &hfi_value, sizeof(s32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_stage(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + u32 stage = 0; + struct msm_vidc_core *core; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + + if (!inst || !inst->capabilities || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + core = inst->core; + + rc = call_session_op(core, decide_work_mode, inst); + if (rc) { + i_vpr_e(inst, "%s: decide_work_mode failed\n", __func__); + return -EINVAL; + } + + stage = inst->capabilities->cap[STAGE].value; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &stage, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_pipe(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + u32 pipe; + struct msm_vidc_core *core; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + + if (!inst || !inst->capabilities || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + core = inst->core; + + rc = call_session_op(core, decide_work_route, inst); + if (rc) { + i_vpr_e(inst, "%s: decide_work_route failed\n", + __func__); + return -EINVAL; + } + + pipe = inst->capabilities->cap[PIPE].value; + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &pipe, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_set_vui_timing_info(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; + } + + /* + * hfi is HFI_PROP_DISABLE_VUI_TIMING_INFO and v4l2 cap is + * V4L2_CID_MPEG_VIDC_VUI_TIMING_INFO and hence reverse + * the hfi_value from cap_id value. + */ + if (inst->capabilities->cap[cap_id].value == 1) + hfi_value = 0; + else + hfi_value = 1; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + if (rc) + return rc; + + return rc; +} + +/********************* End of Control Set functions **************************/ diff --git a/driver/variant/iris2/src/msm_vidc_buffer_iris2.c b/driver/variant/iris2/src/msm_vidc_buffer_iris2.c index 96e4feaa78..c0b3a5d78a 100644 --- a/driver/variant/iris2/src/msm_vidc_buffer_iris2.c +++ b/driver/variant/iris2/src/msm_vidc_buffer_iris2.c @@ -12,7 +12,7 @@ #include "msm_vidc_driver.h" #include "msm_vidc_debug.h" #include "msm_media_info.h" -#include "msm_vidc_control.h" +#include "msm_vidc_platform.h" static u32 msm_vidc_decoder_bin_size_iris2(struct msm_vidc_inst *inst) { diff --git a/driver/variant/iris2/src/msm_vidc_iris2.c b/driver/variant/iris2/src/msm_vidc_iris2.c index af9c582b29..133d8657b5 100644 --- a/driver/variant/iris2/src/msm_vidc_iris2.c +++ b/driver/variant/iris2/src/msm_vidc_iris2.c @@ -9,11 +9,10 @@ #include "msm_vidc_inst.h" #include "msm_vidc_core.h" #include "msm_vidc_driver.h" -#include "msm_vidc_control.h" +#include "msm_vidc_plaform.h" #include "msm_vidc_internal.h" #include "msm_vidc_buffer.h" #include "msm_vidc_debug.h" -#include "msm_vidc_control.h" #include "msm_vidc_variant.h" #define VIDEO_ARCH_LX 1 diff --git a/driver/variant/iris3/src/msm_vidc_buffer_iris3.c b/driver/variant/iris3/src/msm_vidc_buffer_iris3.c index 5fb631f554..329781217b 100644 --- a/driver/variant/iris3/src/msm_vidc_buffer_iris3.c +++ b/driver/variant/iris3/src/msm_vidc_buffer_iris3.c @@ -13,7 +13,7 @@ #include "msm_vidc_driver.h" #include "msm_vidc_debug.h" #include "msm_media_info.h" -#include "msm_vidc_control.h" +#include "msm_vidc_platform.h" static u32 msm_vidc_decoder_bin_size_iris3(struct msm_vidc_inst *inst) { diff --git a/driver/variant/iris3/src/msm_vidc_iris3.c b/driver/variant/iris3/src/msm_vidc_iris3.c index 0890c9f300..07ce667187 100644 --- a/driver/variant/iris3/src/msm_vidc_iris3.c +++ b/driver/variant/iris3/src/msm_vidc_iris3.c @@ -11,7 +11,7 @@ #include "msm_vidc_inst.h" #include "msm_vidc_core.h" #include "msm_vidc_driver.h" -#include "msm_vidc_control.h" +#include "msm_vidc_platform.h" #include "msm_vidc_internal.h" #include "msm_vidc_buffer.h" #include "msm_vidc_debug.h" diff --git a/driver/variant/iris33/src/msm_vidc_buffer_iris33.c b/driver/variant/iris33/src/msm_vidc_buffer_iris33.c index 931fe85255..9fb9ba882c 100644 --- a/driver/variant/iris33/src/msm_vidc_buffer_iris33.c +++ b/driver/variant/iris33/src/msm_vidc_buffer_iris33.c @@ -13,7 +13,7 @@ #include "msm_vidc_driver.h" #include "msm_vidc_debug.h" #include "msm_media_info.h" -#include "msm_vidc_control.h" +#include "msm_vidc_platform.h" static u32 msm_vidc_decoder_bin_size_iris33(struct msm_vidc_inst *inst) { diff --git a/driver/variant/iris33/src/msm_vidc_iris33.c b/driver/variant/iris33/src/msm_vidc_iris33.c index dd863cfd7d..d0d54d0271 100644 --- a/driver/variant/iris33/src/msm_vidc_iris33.c +++ b/driver/variant/iris33/src/msm_vidc_iris33.c @@ -11,7 +11,7 @@ #include "msm_vidc_inst.h" #include "msm_vidc_core.h" #include "msm_vidc_driver.h" -#include "msm_vidc_control.h" +#include "msm_vidc_platform.h" #include "msm_vidc_internal.h" #include "msm_vidc_buffer.h" #include "msm_vidc_debug.h" diff --git a/driver/vidc/inc/msm_vidc_control.h b/driver/vidc/inc/msm_vidc_control.h index 277db6da37..ac549e05dd 100644 --- a/driver/vidc/inc/msm_vidc_control.h +++ b/driver/vidc/inc/msm_vidc_control.h @@ -14,128 +14,9 @@ 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_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_dynamic_layer_bitrate(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_bitrate_mode(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_entropy_mode(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_profile(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_ltr_count(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_use_ltr(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_mark_ltr(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_delta_based_rc(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_output_order(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_input_buf_host_max_count(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_output_buf_host_max_count(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_chroma_qp_index_offset(void *instance, - struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_slice_count(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_layer_count(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_gop_size(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_b_frame(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_peak_bitrate(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_hevc_min_qp(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_hevc_max_qp(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_hevc_i_frame_qp(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_hevc_p_frame_qp(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_hevc_b_frame_qp(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_blur_type(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_blur_resolution(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_brs(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_enc_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_dec_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl); -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_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_all_intra(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_dec_outbuf_fence(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_dec_slice_mode(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_preprocess(void *instance, struct v4l2_ctrl *ctrl); - -int msm_vidc_set_header_mode(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_deblock_mode(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_min_qp(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_max_qp(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_frame_qp(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_req_sync_frame(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_chroma_qp_index_offset(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_slice_count(void* instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_layer_count_and_type(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_gop_size(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_bitrate(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_dynamic_layer_bitrate(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_u32(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_u32_packed(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_u32_enum(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_constant_quality(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_vbr_related_properties( - void *instance, enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_cbr_related_properties(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_use_and_mark_ltr(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_nal_length(void* instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_session_priority(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_flip(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_rotation(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_blur_resolution(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_stage(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_pipe(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_csc_custom_matrix(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_level(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_preprocess(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_reserve_duration(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_q16(void *instance, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_v4l2_menu_to_hfi(struct msm_vidc_inst *inst, - enum msm_vidc_inst_capability_type cap_id, u32 *value); -int msm_vidc_packetize_control(struct msm_vidc_inst *inst, - enum msm_vidc_inst_capability_type cap_id, u32 payload_type, - void *hfi_val, u32 payload_size, const char *func); -bool is_parent_available(struct msm_vidc_inst *inst, - u32 cap_id, u32 check_parent, const char *func); +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); enum msm_vidc_inst_capability_type msm_vidc_get_cap_id( struct msm_vidc_inst *inst, u32 id); -int msm_vidc_v4l2_to_hfi_enum(struct msm_vidc_inst *inst, - enum msm_vidc_inst_capability_type cap_id, u32 *value); -int msm_vidc_update_cap_value(struct msm_vidc_inst *inst, u32 cap, - s32 adjusted_val, const char *func); -int msm_vidc_get_parent_value(struct msm_vidc_inst* inst, u32 cap, u32 parent, - s32 *value, const char *func); -u32 msm_vidc_get_port_info(struct msm_vidc_inst *inst, - enum msm_vidc_inst_capability_type cap_id); -int msm_vidc_set_vui_timing_info(void *instance, - enum msm_vidc_inst_capability_type cap_id); - #endif diff --git a/driver/vidc/src/msm_vdec.c b/driver/vidc/src/msm_vdec.c index 2d4ee6de2b..c20d6e04b1 100644 --- a/driver/vidc/src/msm_vdec.c +++ b/driver/vidc/src/msm_vdec.c @@ -15,7 +15,7 @@ #include "msm_vidc_control.h" #include "msm_vidc_debug.h" #include "msm_vidc_power.h" -#include "msm_vidc_control.h" +#include "msm_vidc_platform.h" #include "msm_vidc_memory.h" #include "venus_hfi.h" #include "hfi_packet.h" diff --git a/driver/vidc/src/msm_venc.c b/driver/vidc/src/msm_venc.c index 73a9213518..0f4d6303ab 100644 --- a/driver/vidc/src/msm_venc.c +++ b/driver/vidc/src/msm_venc.c @@ -15,6 +15,7 @@ #include "msm_vidc_power.h" #include "venus_hfi.h" #include "hfi_packet.h" +#include "msm_vidc_platform.h" static const u32 msm_venc_input_set_prop[] = { HFI_PROP_COLOR_FORMAT, diff --git a/driver/vidc/src/msm_vidc_control.c b/driver/vidc/src/msm_vidc_control.c index 0075500197..31049ec769 100644 --- a/driver/vidc/src/msm_vidc_control.c +++ b/driver/vidc/src/msm_vidc_control.c @@ -4,21 +4,12 @@ */ /* Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. */ -#include "msm_vidc_control.h" #include "msm_vidc_debug.h" -#include "hfi_packet.h" -#include "hfi_property.h" -#include "venus_hfi.h" #include "msm_vidc_internal.h" #include "msm_vidc_driver.h" #include "msm_venc.h" #include "msm_vidc_platform.h" -#define CAP_TO_8BIT_QP(a) { \ - if ((a) < MIN_QP_8BIT) \ - (a) = MIN_QP_8BIT; \ -} - extern struct msm_vidc_core *g_core; static bool is_priv_ctrl(u32 id) @@ -111,27 +102,6 @@ static const char *const mpeg_video_vidc_ir_type[] = { NULL, }; -u32 msm_vidc_get_port_info(struct msm_vidc_inst *inst, - enum msm_vidc_inst_capability_type cap_id) -{ - struct msm_vidc_inst_capability *capability = inst->capabilities; - - if (capability->cap[cap_id].flags & CAP_FLAG_INPUT_PORT && - capability->cap[cap_id].flags & CAP_FLAG_OUTPUT_PORT) { - if (inst->bufq[OUTPUT_PORT].vb2q->streaming) - return get_hfi_port(inst, INPUT_PORT); - else - return get_hfi_port(inst, OUTPUT_PORT); - } - - if (capability->cap[cap_id].flags & CAP_FLAG_INPUT_PORT) - return get_hfi_port(inst, INPUT_PORT); - else if (capability->cap[cap_id].flags & CAP_FLAG_OUTPUT_PORT) - return get_hfi_port(inst, OUTPUT_PORT); - else - return HFI_PORT_NONE; -} - static const char * const * msm_vidc_get_qmenu_type( struct msm_vidc_inst *inst, u32 cap_id) { @@ -281,64 +251,6 @@ static int swap_node(struct msm_vidc_inst_cap *rcap, return 0; } -int msm_vidc_packetize_control(struct msm_vidc_inst *inst, - enum msm_vidc_inst_capability_type cap_id, u32 payload_type, - void *hfi_val, u32 payload_size, const char *func) -{ - int rc = 0; - u64 payload = 0; - - if (payload_size > sizeof(u32)) { - i_vpr_e(inst, "%s: payload size is more than u32 for cap[%d] %s\n", - func, cap_id, cap_name(cap_id)); - return -EINVAL; - } - - if (payload_size == sizeof(u32)) - payload = *(u32 *)hfi_val; - else if (payload_size == sizeof(u8)) - payload = *(u8 *)hfi_val; - else if (payload_size == sizeof(u16)) - payload = *(u16 *)hfi_val; - - i_vpr_h(inst, FMT_STRING_SET_CAP, - cap_name(cap_id), inst->capabilities->cap[cap_id].value, payload); - - rc = venus_hfi_session_property(inst, - inst->capabilities->cap[cap_id].hfi_id, - HFI_HOST_FLAGS_NONE, - msm_vidc_get_port_info(inst, cap_id), - payload_type, - hfi_val, - payload_size); - if (rc) { - i_vpr_e(inst, "%s: failed to set cap[%d] %s to fw\n", - func, cap_id, cap_name(cap_id)); - return rc; - } - - return 0; -} - -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_id; - break; - } - i++; - } while (i < INST_CAP_MAX); - - return cap_id; -} - static int msm_vidc_add_capid_to_fw_list(struct msm_vidc_inst *inst, enum msm_vidc_inst_capability_type cap_id) { @@ -385,126 +297,6 @@ static int msm_vidc_add_children(struct msm_vidc_inst *inst, return rc; } -bool is_parent_available(struct msm_vidc_inst *inst, - u32 cap_id, u32 check_parent, const char *func) -{ - int i = 0; - u32 cap_parent; - - while (i < MAX_CAP_PARENTS && - inst->capabilities->cap[cap_id].parents[i]) { - cap_parent = inst->capabilities->cap[cap_id].parents[i]; - if (cap_parent == check_parent) { - return true; - } - i++; - } - - i_vpr_e(inst, - "%s: missing parent %s for %s\n", - func, cap_name(check_parent), cap_name(cap_id)); - return false; -} - -int msm_vidc_update_cap_value(struct msm_vidc_inst *inst, u32 cap_id, - s32 adjusted_val, const char *func) -{ - int prev_value = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - prev_value = inst->capabilities->cap[cap_id].value; - - if (is_meta_cap(inst, cap_id)) { - /* - * cumulative control value if client set same metadata - * control multiple times. - */ - if (adjusted_val & MSM_VIDC_META_ENABLE) { - /* enable metadata */ - inst->capabilities->cap[cap_id].value |= adjusted_val; - } else { - /* disable metadata */ - inst->capabilities->cap[cap_id].value &= ~adjusted_val; - } - } else { - inst->capabilities->cap[cap_id].value = adjusted_val; - } - - if (prev_value != inst->capabilities->cap[cap_id].value) { - i_vpr_h(inst, - "%s: updated database: name: %s, value: %#x -> %#x\n", - func, cap_name(cap_id), - prev_value, inst->capabilities->cap[cap_id].value); - } - - return 0; -} - -int msm_vidc_get_parent_value(struct msm_vidc_inst* inst, - u32 cap_id, u32 parent, s32 *value, const char *func) -{ - int rc = 0; - - if (is_parent_available(inst, cap_id, parent, func)) { - switch (parent) { - case BITRATE_MODE: - *value = inst->hfi_rc_type; - break; - case LAYER_TYPE: - *value = inst->hfi_layer_type; - break; - default: - *value = inst->capabilities->cap[parent].value; - break; - } - } else { - rc = -EINVAL; - } - - return rc; -} - -static int msm_vidc_adjust_hevc_qp(struct msm_vidc_inst *inst, - enum msm_vidc_inst_capability_type cap_id) -{ - struct msm_vidc_inst_capability *capability; - s32 pix_fmt = -1; - - capability = inst->capabilities; - - if (!(inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)) { - i_vpr_e(inst, - "%s: incorrect cap[%d] %s entry in database, fix database\n", - __func__, cap_id, cap_name(cap_id)); - return -EINVAL; - } - - if (msm_vidc_get_parent_value(inst, cap_id, - PIX_FMTS, &pix_fmt, __func__)) - return -EINVAL; - - if (pix_fmt == MSM_VIDC_FMT_P010 || pix_fmt == MSM_VIDC_FMT_TP10C) - goto exit; - - CAP_TO_8BIT_QP(capability->cap[cap_id].value); - if (cap_id == MIN_FRAME_QP) { - CAP_TO_8BIT_QP(capability->cap[I_FRAME_MIN_QP].value); - CAP_TO_8BIT_QP(capability->cap[P_FRAME_MIN_QP].value); - CAP_TO_8BIT_QP(capability->cap[B_FRAME_MIN_QP].value); - } else if (cap_id == MAX_FRAME_QP) { - CAP_TO_8BIT_QP(capability->cap[I_FRAME_MAX_QP].value); - CAP_TO_8BIT_QP(capability->cap[P_FRAME_MAX_QP].value); - CAP_TO_8BIT_QP(capability->cap[B_FRAME_MAX_QP].value); - } - -exit: - return 0; -} - static int msm_vidc_adjust_cap(struct msm_vidc_inst *inst, enum msm_vidc_inst_capability_type cap_id, struct v4l2_ctrl *ctrl, const char *func) @@ -1159,1731 +951,6 @@ unlock: return rc; } -int msm_vidc_adjust_entropy_mode(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 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 */ - adjusted_value = ctrl ? ctrl->val : - capability->cap[ENTROPY_MODE].value; - - if (inst->codec != MSM_VIDC_H264) { - i_vpr_e(inst, - "%s: incorrect entry in database. fix the database\n", - __func__); - return 0; - } - - if (msm_vidc_get_parent_value(inst, ENTROPY_MODE, - PROFILE, &profile, __func__)) - return -EINVAL; - - if (profile == V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE || - profile == V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) - adjusted_value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC; - - msm_vidc_update_cap_value(inst, ENTROPY_MODE, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_bitrate_mode(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - int lossless, frame_rc, bitrate_mode, frame_skip; - u32 hfi_value = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - bitrate_mode = capability->cap[BITRATE_MODE].value; - lossless = capability->cap[LOSSLESS].value; - frame_rc = capability->cap[FRAME_RC_ENABLE].value; - frame_skip = capability->cap[FRAME_SKIP_MODE].value; - - if (lossless || (msm_vidc_lossless_encode && - inst->codec == MSM_VIDC_HEVC)) { - hfi_value = HFI_RC_LOSSLESS; - goto update; - } - - if (!frame_rc && !is_image_session(inst)) { - hfi_value = HFI_RC_OFF; - goto update; - } - - if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { - hfi_value = HFI_RC_VBR_CFR; - } else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) { - if (frame_skip) - hfi_value = HFI_RC_CBR_VFR; - else - hfi_value = HFI_RC_CBR_CFR; - } else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) { - hfi_value = HFI_RC_CQ; - } - -update: - inst->hfi_rc_type = hfi_value; - i_vpr_h(inst, "%s: hfi rc type: %#x\n", - __func__, inst->hfi_rc_type); - - return 0; -} - -int msm_vidc_adjust_profile(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 pix_fmt = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : capability->cap[PROFILE].value; - - /* PIX_FMTS dependency is common across all chipsets. - * Hence, PIX_FMTS must be specified as Parent for HEVC profile. - * Otherwise it would be a database error that should be fixed. - */ - if (msm_vidc_get_parent_value(inst, PROFILE, PIX_FMTS, - &pix_fmt, __func__)) - return -EINVAL; - - /* 10 bit profile for 10 bit color format */ - if (pix_fmt == MSM_VIDC_FMT_TP10C || pix_fmt == MSM_VIDC_FMT_P010) { - if (is_image_session(inst)) - adjusted_value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10_STILL_PICTURE; - else - adjusted_value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10; - } else { - /* 8 bit profile for 8 bit color format */ - if (is_image_session(inst)) - adjusted_value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE; - else - adjusted_value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN; - } - - msm_vidc_update_cap_value(inst, PROFILE, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_ltr_count(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 rc_type = -1, all_intra = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : capability->cap[LTR_COUNT].value; - - if (msm_vidc_get_parent_value(inst, LTR_COUNT, BITRATE_MODE, - &rc_type, __func__) || - msm_vidc_get_parent_value(inst, LTR_COUNT, ALL_INTRA, - &all_intra, __func__)) - return -EINVAL; - - if ((rc_type != HFI_RC_OFF && - rc_type != HFI_RC_CBR_CFR && - rc_type != HFI_RC_CBR_VFR) || - all_intra) { - adjusted_value = 0; - i_vpr_h(inst, - "%s: ltr count unsupported, rc_type: %#x, all_intra %d\n", - __func__,rc_type, all_intra); - } - - msm_vidc_update_cap_value(inst, LTR_COUNT, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_use_ltr(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value, ltr_count; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : capability->cap[USE_LTR].value; - - /* - * Since USE_LTR is only set dynamically, and LTR_COUNT is static - * control, no need to make LTR_COUNT as parent for USE_LTR as - * LTR_COUNT value will always be updated when dynamically USE_LTR - * is set - */ - ltr_count = capability->cap[LTR_COUNT].value; - if (!ltr_count) - return 0; - - if (adjusted_value <= 0 || - adjusted_value > ((1 << ltr_count) - 1)) { - /* - * USE_LTR is bitmask value, hence should be - * > 0 and <= (2 ^ LTR_COUNT) - 1 - */ - i_vpr_e(inst, "%s: invalid value %d\n", - __func__, adjusted_value); - return 0; - } - - /* USE_LTR value is a bitmask value */ - msm_vidc_update_cap_value(inst, USE_LTR, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_mark_ltr(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value, ltr_count; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : capability->cap[MARK_LTR].value; - - /* - * Since MARK_LTR is only set dynamically, and LTR_COUNT is static - * control, no need to make LTR_COUNT as parent for MARK_LTR as - * LTR_COUNT value will always be updated when dynamically MARK_LTR - * is set - */ - ltr_count = capability->cap[LTR_COUNT].value; - if (!ltr_count) - return 0; - - if (adjusted_value < 0 || - adjusted_value > (ltr_count - 1)) { - /* MARK_LTR value should be >= 0 and <= (LTR_COUNT - 1) */ - i_vpr_e(inst, "%s: invalid value %d\n", - __func__, adjusted_value); - return 0; - } - - msm_vidc_update_cap_value(inst, MARK_LTR, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_delta_based_rc(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 rc_type = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : - capability->cap[TIME_DELTA_BASED_RC].value; - - if (msm_vidc_get_parent_value(inst, TIME_DELTA_BASED_RC, - BITRATE_MODE, &rc_type, __func__)) - return -EINVAL; - - if (rc_type == HFI_RC_OFF || - rc_type == HFI_RC_CQ) - adjusted_value = 0; - - msm_vidc_update_cap_value(inst, TIME_DELTA_BASED_RC, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_output_order(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - struct msm_vidc_inst_capability *capability; - s32 tn_mode = -1, display_delay = -1, display_delay_enable = -1; - u32 adjusted_value; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : - capability->cap[OUTPUT_ORDER].value; - - if (msm_vidc_get_parent_value(inst, OUTPUT_ORDER, THUMBNAIL_MODE, - &tn_mode, __func__) || - msm_vidc_get_parent_value(inst, OUTPUT_ORDER, DISPLAY_DELAY, - &display_delay, __func__) || - msm_vidc_get_parent_value(inst, OUTPUT_ORDER, DISPLAY_DELAY_ENABLE, - &display_delay_enable, __func__)) - return -EINVAL; - - if (tn_mode || (display_delay_enable && !display_delay)) - adjusted_value = 1; - - msm_vidc_update_cap_value(inst, OUTPUT_ORDER, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_input_buf_host_max_count(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - struct msm_vidc_inst_capability *capability; - u32 adjusted_value; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : - capability->cap[INPUT_BUF_HOST_MAX_COUNT].value; - - if (msm_vidc_is_super_buffer(inst) || is_image_session(inst)) - adjusted_value = DEFAULT_MAX_HOST_BURST_BUF_COUNT; - - msm_vidc_update_cap_value(inst, INPUT_BUF_HOST_MAX_COUNT, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_output_buf_host_max_count(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - struct msm_vidc_inst_capability *capability; - u32 adjusted_value; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : - capability->cap[OUTPUT_BUF_HOST_MAX_COUNT].value; - - if (msm_vidc_is_super_buffer(inst) || is_image_session(inst) || - is_enc_slice_delivery_mode(inst)) - adjusted_value = DEFAULT_MAX_HOST_BURST_BUF_COUNT; - - msm_vidc_update_cap_value(inst, OUTPUT_BUF_HOST_MAX_COUNT, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 profile = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : - capability->cap[TRANSFORM_8X8].value; - - if (inst->codec != MSM_VIDC_H264) { - i_vpr_e(inst, - "%s: incorrect entry in database. fix the database\n", - __func__); - return 0; - } - - if (msm_vidc_get_parent_value(inst, TRANSFORM_8X8, - PROFILE, &profile, __func__)) - return -EINVAL; - - if (profile != V4L2_MPEG_VIDEO_H264_PROFILE_HIGH && - profile != V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) - adjusted_value = 0; - - msm_vidc_update_cap_value(inst, TRANSFORM_8X8, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_chroma_qp_index_offset(void *instance, - struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : - capability->cap[CHROMA_QP_INDEX_OFFSET].value; - - if (adjusted_value != MIN_CHROMA_QP_OFFSET) - adjusted_value = MAX_CHROMA_QP_OFFSET; - - msm_vidc_update_cap_value(inst, CHROMA_QP_INDEX_OFFSET, - adjusted_value, __func__); - - return 0; -} - -static bool msm_vidc_check_all_layer_bitrate_set(struct msm_vidc_inst *inst) -{ - bool layer_bitrate_set = true; - u32 cap_id = 0, i, enh_layer_count; - u32 layer_br_caps[6] = {L0_BR, L1_BR, L2_BR, L3_BR, L4_BR, L5_BR}; - - enh_layer_count = inst->capabilities->cap[ENH_LAYER_COUNT].value; - - for (i = 0; i <= enh_layer_count; i++) { - if (i >= ARRAY_SIZE(layer_br_caps)) - break; - cap_id = layer_br_caps[i]; - if (!(inst->capabilities->cap[cap_id].flags & CAP_FLAG_CLIENT_SET)) { - layer_bitrate_set = false; - break; - } - } - - return layer_bitrate_set; -} - -static u32 msm_vidc_get_cumulative_bitrate(struct msm_vidc_inst *inst) -{ - int i; - u32 cap_id = 0; - u32 cumulative_br = 0; - s32 enh_layer_count; - u32 layer_br_caps[6] = {L0_BR, L1_BR, L2_BR, L3_BR, L4_BR, L5_BR}; - - enh_layer_count = inst->capabilities->cap[ENH_LAYER_COUNT].value; - - for (i = 0; i <= enh_layer_count; i++) { - if (i >= ARRAY_SIZE(layer_br_caps)) - break; - cap_id = layer_br_caps[i]; - cumulative_br += inst->capabilities->cap[cap_id].value; - } - - return cumulative_br; -} - -int msm_vidc_adjust_slice_count(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - struct msm_vidc_inst_capability *capability; - struct v4l2_format *output_fmt; - s32 adjusted_value, rc_type = -1, slice_mode, all_intra, enh_layer_count = 0; - u32 slice_val, mbpf = 0, mbps = 0, max_mbpf = 0, max_mbps = 0, bitrate = 0; - u32 update_cap, max_avg_slicesize, output_width, output_height; - u32 min_width, min_height, max_width, max_height, fps; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - slice_mode = ctrl ? ctrl->val : - capability->cap[SLICE_MODE].value; - - if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) - return 0; - - if (msm_vidc_get_parent_value(inst, SLICE_MODE, - BITRATE_MODE, &rc_type, __func__) || - msm_vidc_get_parent_value(inst, SLICE_MODE, - ALL_INTRA, &all_intra, __func__) || - msm_vidc_get_parent_value(inst, SLICE_MODE, - ENH_LAYER_COUNT, &enh_layer_count, __func__)) - return -EINVAL; - - if (capability->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) { - bitrate = capability->cap[BIT_RATE].value; - } else if (msm_vidc_check_all_layer_bitrate_set(inst)) { - bitrate = msm_vidc_get_cumulative_bitrate(inst); - } else { - adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; - update_cap = SLICE_MODE; - i_vpr_h(inst, - "%s: client did not set bitrate & layerwise bitrates\n", - __func__); - goto exit; - } - - fps = capability->cap[FRAME_RATE].value >> 16; - if (fps > MAX_SLICES_FRAME_RATE || - (rc_type != HFI_RC_OFF && - rc_type != HFI_RC_CBR_CFR && - rc_type != HFI_RC_CBR_VFR && - rc_type != HFI_RC_VBR_CFR) || - all_intra) { - adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; - update_cap = SLICE_MODE; - i_vpr_h(inst, - "%s: slice unsupported, fps: %u, rc_type: %#x, all_intra %d\n", - __func__, fps, rc_type, all_intra); - goto exit; - } - - output_fmt = &inst->fmts[OUTPUT_PORT]; - output_width = output_fmt->fmt.pix_mp.width; - output_height = output_fmt->fmt.pix_mp.height; - - max_width = (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) ? - MAX_MB_SLICE_WIDTH : MAX_BYTES_SLICE_WIDTH; - max_height = (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) ? - MAX_MB_SLICE_HEIGHT : MAX_BYTES_SLICE_HEIGHT; - min_width = (inst->codec == MSM_VIDC_HEVC) ? - MIN_HEVC_SLICE_WIDTH : MIN_AVC_SLICE_WIDTH; - min_height = MIN_SLICE_HEIGHT; - - /* - * For V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB: - * - width >= 384 and height >= 128 - * - width and height <= 4096 - * For V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES: - * - width >= 192 and height >= 128 - * - width and height <= 1920 - */ - if (output_width < min_width || output_height < min_height || - output_width > max_width || output_height > max_width) { - adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; - update_cap = SLICE_MODE; - i_vpr_h(inst, - "%s: slice unsupported, codec: %#x wxh: [%dx%d]\n", - __func__, inst->codec, output_width, output_height); - goto exit; - } - - mbpf = NUM_MBS_PER_FRAME(output_height, output_width); - mbps = NUM_MBS_PER_SEC(output_height, output_width, fps); - max_mbpf = NUM_MBS_PER_FRAME(max_height, max_width); - max_mbps = NUM_MBS_PER_SEC(max_height, max_width, MAX_SLICES_FRAME_RATE); - - if (mbpf > max_mbpf || mbps > max_mbps) { - adjusted_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; - update_cap = SLICE_MODE; - i_vpr_h(inst, - "%s: Unsupported, mbpf[%u] > max[%u], mbps[%u] > max[%u]\n", - __func__, mbpf, max_mbpf, mbps, max_mbps); - goto exit; - } - - if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) { - update_cap = SLICE_MAX_MB; - slice_val = capability->cap[SLICE_MAX_MB].value; - slice_val = max(slice_val, mbpf / MAX_SLICES_PER_FRAME); - } else { - slice_val = capability->cap[SLICE_MAX_BYTES].value; - update_cap = SLICE_MAX_BYTES; - if (rc_type != HFI_RC_OFF) { - max_avg_slicesize = ((bitrate / fps) / 8) / - MAX_SLICES_PER_FRAME; - slice_val = max(slice_val, max_avg_slicesize); - } - } - adjusted_value = slice_val; - -exit: - msm_vidc_update_cap_value(inst, update_cap, - adjusted_value, __func__); - - return 0; -} - -static int msm_vidc_adjust_static_layer_count_and_type(struct msm_vidc_inst *inst, - s32 layer_count) -{ - bool hb_requested = false; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (!layer_count) { - i_vpr_h(inst, "client not enabled layer encoding\n"); - goto exit; - } - - if (inst->hfi_rc_type == HFI_RC_CQ) { - i_vpr_h(inst, "rc type is CQ, disabling layer encoding\n"); - layer_count = 0; - goto exit; - } - - if (inst->codec == MSM_VIDC_H264) { - if (!inst->capabilities->cap[LAYER_ENABLE].value) { - layer_count = 0; - goto exit; - } - - hb_requested = (inst->capabilities->cap[LAYER_TYPE].value == - V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B) ? - true : false; - } else if (inst->codec == MSM_VIDC_HEVC) { - hb_requested = (inst->capabilities->cap[LAYER_TYPE].value == - V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) ? - true : false; - } - - if (hb_requested && inst->hfi_rc_type != HFI_RC_VBR_CFR) { - i_vpr_h(inst, - "%s: HB layer encoding is supported for VBR rc only\n", - __func__); - layer_count = 0; - goto exit; - } - - if (!is_meta_tx_inp_enabled(inst, META_EVA_STATS) && - hb_requested && (layer_count > 1)) { - layer_count = 1; - i_vpr_h(inst, - "%s: cvp disable supports only one enh layer HB\n", - __func__); - } - - /* decide hfi layer type */ - if (hb_requested) { - inst->hfi_layer_type = HFI_HIER_B; - } else { - /* HP requested */ - inst->hfi_layer_type = HFI_HIER_P_SLIDING_WINDOW; - if (inst->codec == MSM_VIDC_H264 && - inst->hfi_rc_type == HFI_RC_VBR_CFR) - inst->hfi_layer_type = HFI_HIER_P_HYBRID_LTR; - } - - /* sanitize layer count based on layer type and codec, and rc type */ - if (inst->hfi_layer_type == HFI_HIER_B) { - if (layer_count > MAX_ENH_LAYER_HB) - layer_count = MAX_ENH_LAYER_HB; - } else if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR) { - if (layer_count > MAX_AVC_ENH_LAYER_HYBRID_HP) - layer_count = MAX_AVC_ENH_LAYER_HYBRID_HP; - } else if (inst->hfi_layer_type == HFI_HIER_P_SLIDING_WINDOW) { - if (inst->codec == MSM_VIDC_H264) { - if (layer_count > MAX_AVC_ENH_LAYER_SLIDING_WINDOW) - layer_count = MAX_AVC_ENH_LAYER_SLIDING_WINDOW; - } else if (inst->codec == MSM_VIDC_HEVC) { - if (inst->hfi_rc_type == HFI_RC_VBR_CFR) { - if (layer_count > MAX_HEVC_VBR_ENH_LAYER_SLIDING_WINDOW) - layer_count = MAX_HEVC_VBR_ENH_LAYER_SLIDING_WINDOW; - } else { - if (layer_count > MAX_HEVC_NON_VBR_ENH_LAYER_SLIDING_WINDOW) - layer_count = MAX_HEVC_NON_VBR_ENH_LAYER_SLIDING_WINDOW; - } - } - } - -exit: - msm_vidc_update_cap_value(inst, ENH_LAYER_COUNT, - layer_count, __func__); - inst->capabilities->cap[ENH_LAYER_COUNT].max = layer_count; - return 0; -} - -int msm_vidc_adjust_layer_count(void *instance, struct v4l2_ctrl *ctrl) -{ - int rc = 0; - struct msm_vidc_inst_capability *capability; - s32 client_layer_count; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - client_layer_count = ctrl ? ctrl->val : - capability->cap[ENH_LAYER_COUNT].value; - - if (!is_parent_available(inst, ENH_LAYER_COUNT, - BITRATE_MODE, __func__) || - !is_parent_available(inst, ENH_LAYER_COUNT, - META_EVA_STATS, __func__)) - return -EINVAL; - - if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) { - rc = msm_vidc_adjust_static_layer_count_and_type(inst, - client_layer_count); - if (rc) - goto exit; - } else { - if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR || - inst->hfi_layer_type == HFI_HIER_P_SLIDING_WINDOW) { - /* dynamic layer count change is only supported for HP */ - if (client_layer_count > - inst->capabilities->cap[ENH_LAYER_COUNT].max) - client_layer_count = - inst->capabilities->cap[ENH_LAYER_COUNT].max; - - msm_vidc_update_cap_value(inst, ENH_LAYER_COUNT, - client_layer_count, __func__); - } - } - -exit: - return rc; -} - -int msm_vidc_adjust_gop_size(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - s32 adjusted_value, enh_layer_count = -1; - u32 min_gop_size, num_subgops; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : capability->cap[GOP_SIZE].value; - - if (msm_vidc_get_parent_value(inst, GOP_SIZE, - ENH_LAYER_COUNT, &enh_layer_count, __func__)) - return -EINVAL; - - if (!enh_layer_count) - goto exit; - - /* - * Layer encoding needs GOP size to be multiple of subgop size - * And subgop size is 2 ^ number of enhancement layers. - */ - - /* v4l2 layer count is the number of enhancement layers */ - min_gop_size = 1 << enh_layer_count; - num_subgops = (adjusted_value + (min_gop_size >> 1)) / - min_gop_size; - if (num_subgops) - adjusted_value = num_subgops * min_gop_size; - else - adjusted_value = min_gop_size; - -exit: - msm_vidc_update_cap_value(inst, GOP_SIZE, adjusted_value, __func__); - return 0; -} - -int msm_vidc_adjust_b_frame(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - s32 adjusted_value, enh_layer_count = -1; - const u32 max_bframe_size = 7; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : capability->cap[B_FRAME].value; - - if (msm_vidc_get_parent_value(inst, B_FRAME, - ENH_LAYER_COUNT, &enh_layer_count, __func__)) - return -EINVAL; - - if (!enh_layer_count || inst->hfi_layer_type != HFI_HIER_B) { - adjusted_value = 0; - goto exit; - } - - adjusted_value = (1 << enh_layer_count) - 1; - /* Allowed Bframe values are 0, 1, 3, 7 */ - if (adjusted_value > max_bframe_size) - adjusted_value = max_bframe_size; - -exit: - msm_vidc_update_cap_value(inst, B_FRAME, adjusted_value, __func__); - return 0; -} - -int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl) -{ - int i, rc = 0; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - struct msm_vidc_inst_capability *capability; - s32 adjusted_value, enh_layer_count; - u32 cumulative_bitrate = 0, cap_id = 0, cap_value = 0; - u32 layer_br_caps[6] = {L0_BR, L1_BR, L2_BR, L3_BR, L4_BR, L5_BR}; - u32 max_bitrate = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - /* ignore layer bitrate when total bitrate is set */ - if (capability->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) { - /* - * For static case, ctrl is null. - * For dynamic case, only BIT_RATE cap uses this adjust function. - * Hence, no need to check for ctrl id to be BIT_RATE control, and not - * any of layer bitrate controls. - */ - adjusted_value = ctrl ? ctrl->val : capability->cap[BIT_RATE].value; - msm_vidc_update_cap_value(inst, BIT_RATE, adjusted_value, __func__); - - return 0; - } - - if (inst->bufq[OUTPUT_PORT].vb2q->streaming) - return 0; - - if (msm_vidc_get_parent_value(inst, BIT_RATE, - ENH_LAYER_COUNT, &enh_layer_count, __func__)) - return -EINVAL; - - /* get max bit rate for current session config*/ - max_bitrate = msm_vidc_get_max_bitrate(inst); - if (inst->capabilities->cap[BIT_RATE].value > max_bitrate) - msm_vidc_update_cap_value(inst, BIT_RATE, max_bitrate, __func__); - - /* - * ENH_LAYER_COUNT cap max is positive only if - * layer encoding is enabled during streamon. - */ - if (capability->cap[ENH_LAYER_COUNT].max) { - if (!msm_vidc_check_all_layer_bitrate_set(inst)) { - i_vpr_h(inst, - "%s: client did not set all layer bitrates\n", - __func__); - return 0; - } - - cumulative_bitrate = msm_vidc_get_cumulative_bitrate(inst); - - /* cap layer bitrates to max supported bitrate */ - if (cumulative_bitrate > max_bitrate) { - u32 decrement_in_value = 0; - u32 decrement_in_percent = ((cumulative_bitrate - max_bitrate) * 100) / - max_bitrate; - - cumulative_bitrate = 0; - for (i = 0; i <= enh_layer_count; i++) { - if (i >= ARRAY_SIZE(layer_br_caps)) - break; - cap_id = layer_br_caps[i]; - cap_value = inst->capabilities->cap[cap_id].value; - - decrement_in_value = (cap_value * - decrement_in_percent) / 100; - cumulative_bitrate += (cap_value - decrement_in_value); - - /* - * cap value for the L*_BR is changed. Hence, update cap, - * and add to FW_LIST to set new values to firmware. - */ - msm_vidc_update_cap_value(inst, cap_id, - (cap_value - decrement_in_value), __func__); - } - } - - i_vpr_h(inst, - "%s: update BIT_RATE with cumulative bitrate\n", - __func__); - msm_vidc_update_cap_value(inst, BIT_RATE, - cumulative_bitrate, __func__); - } - - return rc; -} - -int msm_vidc_adjust_dynamic_layer_bitrate(void *instance, struct v4l2_ctrl *ctrl) -{ - int rc = 0; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - struct msm_vidc_inst_capability *capability; - u32 cumulative_bitrate = 0; - u32 client_set_cap_id = INST_CAP_NONE; - u32 old_br = 0, new_br = 0, exceeded_br = 0; - s32 max_bitrate; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - if (!ctrl) - return 0; - - /* ignore layer bitrate when total bitrate is set */ - if (capability->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) - return 0; - - if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) - return 0; - - /* - * ENH_LAYER_COUNT cap max is positive only if - * layer encoding is enabled during streamon. - */ - if (!capability->cap[ENH_LAYER_COUNT].max) { - i_vpr_e(inst, "%s: layers not enabled\n", __func__); - return -EINVAL; - } - - if (!msm_vidc_check_all_layer_bitrate_set(inst)) { - i_vpr_h(inst, - "%s: client did not set all layer bitrates\n", - __func__); - return 0; - } - - client_set_cap_id = msm_vidc_get_cap_id(inst, ctrl->id); - if (client_set_cap_id == INST_CAP_NONE) { - i_vpr_e(inst, "%s: could not find cap_id for ctrl %s\n", - __func__, ctrl->name); - return -EINVAL; - } - - cumulative_bitrate = msm_vidc_get_cumulative_bitrate(inst); - max_bitrate = inst->capabilities->cap[BIT_RATE].max; - old_br = capability->cap[client_set_cap_id].value; - new_br = ctrl->val; - - /* - * new bitrate is not supposed to cause cumulative bitrate to - * exceed max supported bitrate - */ - - if ((cumulative_bitrate - old_br + new_br) > max_bitrate) { - /* adjust new bitrate */ - exceeded_br = (cumulative_bitrate - old_br + new_br) - max_bitrate; - new_br = ctrl->val - exceeded_br; - } - msm_vidc_update_cap_value(inst, client_set_cap_id, new_br, __func__); - - /* adjust totol bitrate cap */ - i_vpr_h(inst, - "%s: update BIT_RATE with cumulative bitrate\n", - __func__); - msm_vidc_update_cap_value(inst, BIT_RATE, - msm_vidc_get_cumulative_bitrate(inst), __func__); - - return rc; -} - -int msm_vidc_adjust_peak_bitrate(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 rc_type = -1, bitrate = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : - capability->cap[PEAK_BITRATE].value; - - if (msm_vidc_get_parent_value(inst, PEAK_BITRATE, - BITRATE_MODE, &rc_type, __func__)) - return -EINVAL; - - if (rc_type != HFI_RC_CBR_CFR && - rc_type != HFI_RC_CBR_VFR) - return 0; - - if (msm_vidc_get_parent_value(inst, PEAK_BITRATE, - BIT_RATE, &bitrate, __func__)) - return -EINVAL; - - /* Peak Bitrate should be larger than or equal to avg bitrate */ - if (capability->cap[PEAK_BITRATE].flags & CAP_FLAG_CLIENT_SET) { - if (adjusted_value < bitrate) - adjusted_value = bitrate; - } else { - adjusted_value = capability->cap[BIT_RATE].value; - } - - msm_vidc_update_cap_value(inst, PEAK_BITRATE, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_hevc_min_qp(void *instance, struct v4l2_ctrl *ctrl) -{ - int rc = 0; - struct msm_vidc_inst_capability *capability; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - if (ctrl) - msm_vidc_update_cap_value(inst, MIN_FRAME_QP, - ctrl->val, __func__); - - rc = msm_vidc_adjust_hevc_qp(inst, MIN_FRAME_QP); - - return rc; -} - -int msm_vidc_adjust_hevc_max_qp(void *instance, struct v4l2_ctrl *ctrl) -{ - int rc = 0; - struct msm_vidc_inst_capability *capability; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - if (ctrl) - msm_vidc_update_cap_value(inst, MAX_FRAME_QP, - ctrl->val, __func__); - - rc = msm_vidc_adjust_hevc_qp(inst, MAX_FRAME_QP); - - return rc; -} - -int msm_vidc_adjust_hevc_i_frame_qp(void *instance, struct v4l2_ctrl *ctrl) -{ - int rc = 0; - struct msm_vidc_inst_capability *capability; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - if (ctrl) - msm_vidc_update_cap_value(inst, I_FRAME_QP, - ctrl->val, __func__); - - rc = msm_vidc_adjust_hevc_qp(inst, I_FRAME_QP); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_adjust_hevc_p_frame_qp(void *instance, struct v4l2_ctrl *ctrl) -{ - int rc = 0; - struct msm_vidc_inst_capability *capability; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - if (ctrl) - msm_vidc_update_cap_value(inst, P_FRAME_QP, - ctrl->val, __func__); - - rc = msm_vidc_adjust_hevc_qp(inst, P_FRAME_QP); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_adjust_hevc_b_frame_qp(void *instance, struct v4l2_ctrl *ctrl) -{ - int rc = 0; - struct msm_vidc_inst_capability *capability; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - if (ctrl) - msm_vidc_update_cap_value(inst, B_FRAME_QP, - ctrl->val, __func__); - - rc = msm_vidc_adjust_hevc_qp(inst, B_FRAME_QP); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_adjust_blur_type(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 rc_type = -1, roi_enable = -1; - s32 pix_fmts = -1, min_quality = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : - capability->cap[BLUR_TYPES].value; - - if (adjusted_value == MSM_VIDC_BLUR_NONE) - return 0; - - if (msm_vidc_get_parent_value(inst, BLUR_TYPES, BITRATE_MODE, - &rc_type, __func__) || - msm_vidc_get_parent_value(inst, BLUR_TYPES, PIX_FMTS, - &pix_fmts, __func__) || - msm_vidc_get_parent_value(inst, BLUR_TYPES, MIN_QUALITY, - &min_quality, __func__) || - msm_vidc_get_parent_value(inst, BLUR_TYPES, META_ROI_INFO, - &roi_enable, __func__)) - return -EINVAL; - - if (adjusted_value == MSM_VIDC_BLUR_EXTERNAL) { - if (is_scaling_enabled(inst) || min_quality) { - adjusted_value = MSM_VIDC_BLUR_NONE; - } - } else if (adjusted_value == MSM_VIDC_BLUR_ADAPTIVE) { - if (is_scaling_enabled(inst) || min_quality || - (rc_type != HFI_RC_VBR_CFR && - rc_type != HFI_RC_CBR_CFR && - rc_type != HFI_RC_CBR_VFR) || - is_10bit_colorformat(pix_fmts) || roi_enable) { - adjusted_value = MSM_VIDC_BLUR_NONE; - } - } - - msm_vidc_update_cap_value(inst, BLUR_TYPES, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_all_intra(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_core *core; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 gop_size = -1, bframe = -1; - u32 width, height, fps, mbps, max_mbps; - - if (!inst || !inst->capabilities || !inst->core) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = capability->cap[ALL_INTRA].value; - - if (msm_vidc_get_parent_value(inst, ALL_INTRA, GOP_SIZE, - &gop_size, __func__) || - msm_vidc_get_parent_value(inst, ALL_INTRA, B_FRAME, - &bframe, __func__)) - return -EINVAL; - - width = inst->crop.width; - height = inst->crop.height; - fps = msm_vidc_get_fps(inst); - mbps = NUM_MBS_PER_SEC(height, width, fps); - core = inst->core; - max_mbps = core->capabilities[MAX_MBPS_ALL_INTRA].value; - - if (mbps > max_mbps) { - adjusted_value = 0; - i_vpr_h(inst, "%s: mbps %d exceeds max supported mbps %d\n", - __func__, mbps, max_mbps); - goto exit; - } - - if (!gop_size && !bframe) - adjusted_value = 1; - -exit: - msm_vidc_update_cap_value(inst, ALL_INTRA, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_blur_resolution(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 blur_type = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : - capability->cap[BLUR_RESOLUTION].value; - - if (msm_vidc_get_parent_value(inst, BLUR_RESOLUTION, BLUR_TYPES, - &blur_type, __func__)) - return -EINVAL; - - if (blur_type != MSM_VIDC_BLUR_EXTERNAL) - return 0; - - msm_vidc_update_cap_value(inst, BLUR_RESOLUTION, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_brs(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 rc_type = -1, layer_enabled = -1, layer_type = -1; - bool hp_requested = false; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : - capability->cap[CONTENT_ADAPTIVE_CODING].value; - - if (inst->bufq[OUTPUT_PORT].vb2q->streaming) - return 0; - - if (msm_vidc_get_parent_value(inst, CONTENT_ADAPTIVE_CODING, - BITRATE_MODE, &rc_type, __func__) || - msm_vidc_get_parent_value(inst, CONTENT_ADAPTIVE_CODING, - LAYER_ENABLE, &layer_enabled, __func__) || - msm_vidc_get_parent_value(inst, CONTENT_ADAPTIVE_CODING, - LAYER_TYPE, &layer_type, __func__)) - return -EINVAL; - - /* - * -BRS is supported only for VBR rc type. - * Hence, do not adjust or set to firmware for non VBR rc's - * -If HP is enabled then BRS is not allowed. - */ - if (rc_type != HFI_RC_VBR_CFR) { - adjusted_value = 0; - goto adjust; - } - - if (inst->codec == MSM_VIDC_H264) { - layer_type = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P; - } else if (inst->codec == MSM_VIDC_HEVC) { - layer_type = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P; - } - hp_requested = (inst->capabilities->cap[LAYER_TYPE].value == layer_type); - - /* - * Disable BRS in case of HP encoding - * Hence set adjust value to 0. - */ - if (layer_enabled == 1 && hp_requested) { - adjusted_value = 0; - goto adjust; - } - -adjust: - msm_vidc_update_cap_value(inst, CONTENT_ADAPTIVE_CODING, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_bitrate_boost(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 min_quality = -1, rc_type = -1; - u32 max_bitrate = 0, bitrate = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : - capability->cap[BITRATE_BOOST].value; - - if (inst->bufq[OUTPUT_PORT].vb2q->streaming) - return 0; - - if (msm_vidc_get_parent_value(inst, BITRATE_BOOST, - MIN_QUALITY, &min_quality, __func__) || - msm_vidc_get_parent_value(inst, BITRATE_BOOST, - BITRATE_MODE, &rc_type, __func__)) - return -EINVAL; - - /* - * Bitrate Boost are supported only for VBR rc type. - * Hence, do not adjust or set to firmware for non VBR rc's - */ - if (rc_type != HFI_RC_VBR_CFR) { - adjusted_value = 0; - goto adjust; - } - - if (min_quality) { - adjusted_value = MAX_BITRATE_BOOST; - goto adjust; - } - - max_bitrate = msm_vidc_get_max_bitrate(inst); - bitrate = inst->capabilities->cap[BIT_RATE].value; - if (adjusted_value) { - if ((bitrate + bitrate / (100 / adjusted_value)) > max_bitrate) { - i_vpr_h(inst, - "%s: bitrate %d is beyond max bitrate %d, remove bitrate boost\n", - __func__, max_bitrate, bitrate); - adjusted_value = 0; - } - } - -adjust: - msm_vidc_update_cap_value(inst, BITRATE_BOOST, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_min_quality(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 roi_enable = -1, rc_type = -1, enh_layer_count = -1, pix_fmts = -1; - u32 width, height, frame_rate; - struct v4l2_format *f; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : capability->cap[MIN_QUALITY].value; - - /* - * Although MIN_QUALITY is static, one of its parents, - * ENH_LAYER_COUNT is dynamic cap. Hence, dynamic call - * may be made for MIN_QUALITY via ENH_LAYER_COUNT. - * Therefore, below streaming check is required to avoid - * runtime modification of MIN_QUALITY. - */ - if (inst->bufq[OUTPUT_PORT].vb2q->streaming) - return 0; - - if (msm_vidc_get_parent_value(inst, MIN_QUALITY, - BITRATE_MODE, &rc_type, __func__) || - msm_vidc_get_parent_value(inst, MIN_QUALITY, - META_ROI_INFO, &roi_enable, __func__) || - msm_vidc_get_parent_value(inst, MIN_QUALITY, - ENH_LAYER_COUNT, &enh_layer_count, __func__)) - return -EINVAL; - - /* - * Min Quality is supported only for VBR rc type. - * Hence, do not adjust or set to firmware for non VBR rc's - */ - if (rc_type != HFI_RC_VBR_CFR) { - adjusted_value = 0; - goto update_and_exit; - } - - frame_rate = inst->capabilities->cap[FRAME_RATE].value >> 16; - f = &inst->fmts[OUTPUT_PORT]; - width = f->fmt.pix_mp.width; - height = f->fmt.pix_mp.height; - - /* - * VBR Min Quality not supported for: - * - HEVC 10bit - * - ROI support - * - HP encoding - * - External Blur - * - Resolution beyond 1080P - * (It will fall back to CQCAC 25% or 0% (CAC) or CQCAC-OFF) - */ - if (inst->codec == MSM_VIDC_HEVC) { - if (msm_vidc_get_parent_value(inst, MIN_QUALITY, - PIX_FMTS, &pix_fmts, __func__)) - return -EINVAL; - - if (is_10bit_colorformat(pix_fmts)) { - i_vpr_h(inst, - "%s: min quality is supported only for 8 bit\n", - __func__); - adjusted_value = 0; - goto update_and_exit; - } - } - - if (res_is_greater_than(width, height, 1920, 1080)) { - i_vpr_h(inst, "%s: unsupported res, wxh %ux%u\n", - __func__, width, height); - adjusted_value = 0; - goto update_and_exit; - } - - if (frame_rate > 60) { - i_vpr_h(inst, "%s: unsupported fps %u\n", - __func__, frame_rate); - adjusted_value = 0; - goto update_and_exit; - } - - if (is_meta_tx_inp_enabled(inst, META_ROI_INFO)) { - i_vpr_h(inst, - "%s: min quality not supported with roi metadata\n", - __func__); - adjusted_value = 0; - goto update_and_exit; - } - - if (enh_layer_count > 0 && inst->hfi_layer_type != HFI_HIER_B) { - i_vpr_h(inst, - "%s: min quality not supported for HP encoding\n", - __func__); - adjusted_value = 0; - goto update_and_exit; - } - - /* Above conditions are met. Hence enable min quality */ - adjusted_value = MAX_SUPPORTED_MIN_QUALITY; - -update_and_exit: - msm_vidc_update_cap_value(inst, MIN_QUALITY, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_preprocess(void *instance, struct v4l2_ctrl *ctrl) -{ - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 brs = -1, eva_status = -1; - u32 width, height, frame_rate, operating_rate, max_fps; - struct v4l2_format *f; - - if (!inst || !inst->capabilities || !inst->core) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - adjusted_value = inst->capabilities->cap[REQUEST_PREPROCESS].value; - - if (msm_vidc_get_parent_value(inst, REQUEST_PREPROCESS, CONTENT_ADAPTIVE_CODING, - &brs, __func__) || - msm_vidc_get_parent_value(inst, REQUEST_PREPROCESS, META_EVA_STATS, - &eva_status, __func__)) - return -EINVAL; - - width = inst->crop.width; - height = inst->crop.height; - frame_rate = msm_vidc_get_frame_rate(inst);; - operating_rate = msm_vidc_get_operating_rate(inst);; - - max_fps = max(frame_rate, operating_rate); - f= &inst->fmts[OUTPUT_PORT]; - - /* - * enable preprocess if - * client did not enable EVA metadata statistics and - * BRS enabled and upto 4k @ 60 fps - */ - if (!is_meta_tx_inp_enabled(inst, META_EVA_STATS) && - brs == 1 && - res_is_less_than_or_equal_to(width, height, 3840, 2160) && - max_fps <= 60) - adjusted_value = 1; - else - adjusted_value = 0; - - msm_vidc_update_cap_value(inst, REQUEST_PREPROCESS, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_enc_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 rc_type = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : - capability->cap[LOWLATENCY_MODE].value; - - if (msm_vidc_get_parent_value(inst, LOWLATENCY_MODE, BITRATE_MODE, - &rc_type, __func__)) - return -EINVAL; - - if (rc_type == HFI_RC_CBR_CFR || - rc_type == HFI_RC_CBR_VFR || - is_enc_slice_delivery_mode(inst)) - adjusted_value = 1; - - msm_vidc_update_cap_value(inst, LOWLATENCY_MODE, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_dec_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 outbuf_fence = MSM_VIDC_META_DISABLE; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : - capability->cap[LOWLATENCY_MODE].value; - - if (msm_vidc_get_parent_value(inst, LOWLATENCY_MODE, META_OUTBUF_FENCE, - &outbuf_fence, __func__)) - return -EINVAL; - - /* enable lowlatency if outbuf fence is enabled */ - if (outbuf_fence & MSM_VIDC_META_ENABLE && - outbuf_fence & MSM_VIDC_META_RX_INPUT) - adjusted_value = 1; - - msm_vidc_update_cap_value(inst, LOWLATENCY_MODE, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_session_priority(void *instance, struct v4l2_ctrl *ctrl) -{ - int adjusted_value; - struct msm_vidc_inst_capability *capability; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - /* - * Priority handling - * Client will set 0 (realtime), 1+ (non-realtime) - * Driver adds NRT_PRIORITY_OFFSET (2) to clients non-realtime priority - * and hence PRIORITY values in the driver become 0, 3+. - * Driver may move decode realtime sessions to non-realtime by - * increasing priority by 1 to RT sessions in HW overloaded cases. - * So driver PRIORITY values can be 0, 1, 3+. - * When driver setting priority to firmware, driver adds - * FIRMWARE_PRIORITY_OFFSET (1) for all sessions except - * non-critical sessions. So finally firmware priority values ranges - * from 0 (Critical session), 1 (realtime session), - * 2+ (non-realtime session) - */ - if (ctrl) { - /* add offset when client sets non-realtime */ - if (ctrl->val) - adjusted_value = ctrl->val + NRT_PRIORITY_OFFSET; - else - adjusted_value = ctrl->val; - } else { - adjusted_value = capability->cap[PRIORITY].value; - } - - msm_vidc_update_cap_value(inst, PRIORITY, adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_roi_info(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - s32 adjusted_value; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 rc_type = -1, pix_fmt = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : capability->cap[META_ROI_INFO].value; - - if (msm_vidc_get_parent_value(inst, META_ROI_INFO, BITRATE_MODE, - &rc_type, __func__)) - return -EINVAL; - - if (msm_vidc_get_parent_value(inst, META_ROI_INFO, PIX_FMTS, - &pix_fmt, __func__)) - return -EINVAL; - - if ((rc_type != HFI_RC_VBR_CFR && rc_type != HFI_RC_CBR_CFR - && rc_type != HFI_RC_CBR_VFR) || !is_8bit_colorformat(pix_fmt) - || is_scaling_enabled(inst) || is_rotation_90_or_270(inst)) - adjusted_value = 0; - - msm_vidc_update_cap_value(inst, META_ROI_INFO, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_dec_outbuf_fence(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - u32 adjusted_value = 0; - s32 picture_order = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : capability->cap[META_OUTBUF_FENCE].value; - - if (msm_vidc_get_parent_value(inst, META_OUTBUF_FENCE, OUTPUT_ORDER, - &picture_order, __func__)) - return -EINVAL; - - if (picture_order == 0) { - /* disable outbuf fence */ - adjusted_value = MSM_VIDC_META_DISABLE | - MSM_VIDC_META_RX_INPUT; - } - - msm_vidc_update_cap_value(inst, META_OUTBUF_FENCE, - adjusted_value, __func__); - - return 0; -} - -int msm_vidc_adjust_dec_slice_mode(void *instance, struct v4l2_ctrl *ctrl) -{ - struct msm_vidc_inst_capability *capability; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - u32 adjusted_value = 0; - s32 low_latency = -1; - s32 picture_order = -1; - s32 outbuf_fence = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - adjusted_value = ctrl ? ctrl->val : capability->cap[SLICE_DECODE].value; - - if (msm_vidc_get_parent_value(inst, SLICE_DECODE, LOWLATENCY_MODE, - &low_latency, __func__) || - msm_vidc_get_parent_value(inst, SLICE_DECODE, OUTPUT_ORDER, - &picture_order, __func__) || - msm_vidc_get_parent_value(inst, SLICE_DECODE, META_OUTBUF_FENCE, - &outbuf_fence, __func__)) - return -EINVAL; - - if (!low_latency || !picture_order || - !is_meta_rx_inp_enabled(inst, META_OUTBUF_FENCE)) - adjusted_value = 0; - - msm_vidc_update_cap_value(inst, SLICE_DECODE, - adjusted_value, __func__); - - return 0; -} - int msm_vidc_prepare_dependency_list(struct msm_vidc_inst *inst) { struct list_head root_list, opt_list; @@ -3077,1419 +1144,3 @@ int msm_vidc_adjust_set_v4l2_properties(struct msm_vidc_inst *inst) return rc; } - -int msm_vidc_set_header_mode(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - int header_mode, prepend_sps_pps; - u32 hfi_value = 0; - struct msm_vidc_inst_capability *capability; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - header_mode = capability->cap[cap_id].value; - prepend_sps_pps = capability->cap[PREPEND_SPSPPS_TO_IDR].value; - - /* prioritize PREPEND_SPSPPS_TO_IDR mode over other header modes */ - if (prepend_sps_pps) - hfi_value = HFI_SEQ_HEADER_PREFIX_WITH_SYNC_FRAME; - else if (header_mode == V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME) - hfi_value = HFI_SEQ_HEADER_JOINED_WITH_1ST_FRAME; - else - hfi_value = HFI_SEQ_HEADER_SEPERATE_FRAME; - - if (is_meta_rx_out_enabled(inst, META_SEQ_HDR_NAL)) - hfi_value |= HFI_SEQ_HEADER_METADATA; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_deblock_mode(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; - s32 alpha = 0, beta = 0; - u32 lf_mode, hfi_value = 0, lf_offset = 6; - struct msm_vidc_inst_capability *capability; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - rc = msm_vidc_v4l2_to_hfi_enum(inst, LF_MODE, &lf_mode); - if (rc) - return -EINVAL; - - beta = inst->capabilities->cap[LF_BETA].value + lf_offset; - alpha = inst->capabilities->cap[LF_ALPHA].value + lf_offset; - hfi_value = (alpha << 16) | (beta << 8) | lf_mode; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_constant_quality(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 = 0; - s32 rc_type = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (msm_vidc_get_parent_value(inst, cap_id, - BITRATE_MODE, &rc_type, __func__)) - return -EINVAL; - - if (rc_type != HFI_RC_CQ) - return 0; - - hfi_value = inst->capabilities->cap[cap_id].value; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_vbr_related_properties(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 = 0; - s32 rc_type = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (msm_vidc_get_parent_value(inst, cap_id, - BITRATE_MODE, &rc_type, __func__)) - return -EINVAL; - - if (rc_type != HFI_RC_VBR_CFR) - return 0; - - hfi_value = inst->capabilities->cap[cap_id].value; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_cbr_related_properties(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 = 0; - s32 rc_type = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (msm_vidc_get_parent_value(inst, cap_id, - BITRATE_MODE, &rc_type, __func__)) - return -EINVAL; - - if (rc_type != HFI_RC_CBR_VFR && - rc_type != HFI_RC_CBR_CFR) - return 0; - - hfi_value = inst->capabilities->cap[cap_id].value; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_use_and_mark_ltr(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 = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (!inst->capabilities->cap[LTR_COUNT].value || - (inst->capabilities->cap[cap_id].value == - INVALID_DEFAULT_MARK_OR_USE_LTR)) { - i_vpr_h(inst, - "%s: LTR_COUNT: %d %s: %d, cap %s is not set\n", - __func__, inst->capabilities->cap[LTR_COUNT].value, - cap_name(cap_id), - inst->capabilities->cap[cap_id].value, - cap_name(cap_id)); - return 0; - } - - hfi_value = inst->capabilities->cap[cap_id].value; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_min_qp(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - struct msm_vidc_inst_capability *capability; - s32 i_frame_qp = 0, p_frame_qp = 0, b_frame_qp = 0, min_qp_enable = 0; - u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0; - u32 client_qp_enable = 0, hfi_value = 0, offset = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - if (capability->cap[MIN_FRAME_QP].flags & CAP_FLAG_CLIENT_SET) - min_qp_enable = 1; - - if (min_qp_enable || - (capability->cap[I_FRAME_MIN_QP].flags & CAP_FLAG_CLIENT_SET)) - i_qp_enable = 1; - if (min_qp_enable || - (capability->cap[P_FRAME_MIN_QP].flags & CAP_FLAG_CLIENT_SET)) - p_qp_enable = 1; - if (min_qp_enable || - (capability->cap[B_FRAME_MIN_QP].flags & CAP_FLAG_CLIENT_SET)) - b_qp_enable = 1; - - client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; - if (!client_qp_enable) { - i_vpr_h(inst, - "%s: client did not set min qp, cap %s is not set\n", - __func__, cap_name(cap_id)); - return 0; - } - - if (is_10bit_colorformat(capability->cap[PIX_FMTS].value)) - offset = 12; - - /* - * I_FRAME_MIN_QP, P_FRAME_MIN_QP, B_FRAME_MIN_QP, - * MIN_FRAME_QP caps have default value as MIN_QP_10BIT values. - * Hence, if client sets either one among MIN_FRAME_QP - * and (I_FRAME_MIN_QP or P_FRAME_MIN_QP or B_FRAME_MIN_QP), - * max of both caps will result into client set value. - */ - i_frame_qp = max(capability->cap[I_FRAME_MIN_QP].value, - capability->cap[MIN_FRAME_QP].value) + offset; - p_frame_qp = max(capability->cap[P_FRAME_MIN_QP].value, - capability->cap[MIN_FRAME_QP].value) + offset; - b_frame_qp = max(capability->cap[B_FRAME_MIN_QP].value, - capability->cap[MIN_FRAME_QP].value) + offset; - - hfi_value = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | - client_qp_enable << 24; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_max_qp(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - struct msm_vidc_inst_capability *capability; - s32 i_frame_qp = 0, p_frame_qp = 0, b_frame_qp = 0, max_qp_enable = 0; - u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0; - u32 client_qp_enable = 0, hfi_value = 0, offset = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capability = inst->capabilities; - - if (capability->cap[MAX_FRAME_QP].flags & CAP_FLAG_CLIENT_SET) - max_qp_enable = 1; - - if (max_qp_enable || - (capability->cap[I_FRAME_MAX_QP].flags & CAP_FLAG_CLIENT_SET)) - i_qp_enable = 1; - if (max_qp_enable || - (capability->cap[P_FRAME_MAX_QP].flags & CAP_FLAG_CLIENT_SET)) - p_qp_enable = 1; - if (max_qp_enable || - (capability->cap[B_FRAME_MAX_QP].flags & CAP_FLAG_CLIENT_SET)) - b_qp_enable = 1; - - client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; - if (!client_qp_enable) { - i_vpr_h(inst, - "%s: client did not set max qp, cap %s is not set\n", - __func__, cap_name(cap_id)); - return 0; - } - - if (is_10bit_colorformat(capability->cap[PIX_FMTS].value)) - offset = 12; - - /* - * I_FRAME_MAX_QP, P_FRAME_MAX_QP, B_FRAME_MAX_QP, - * MAX_FRAME_QP caps have default value as MAX_QP values. - * Hence, if client sets either one among MAX_FRAME_QP - * and (I_FRAME_MAX_QP or P_FRAME_MAX_QP or B_FRAME_MAX_QP), - * min of both caps will result into client set value. - */ - i_frame_qp = min(capability->cap[I_FRAME_MAX_QP].value, - capability->cap[MAX_FRAME_QP].value) + offset; - p_frame_qp = min(capability->cap[P_FRAME_MAX_QP].value, - capability->cap[MAX_FRAME_QP].value) + offset; - b_frame_qp = min(capability->cap[B_FRAME_MAX_QP].value, - capability->cap[MAX_FRAME_QP].value) + offset; - - hfi_value = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | - client_qp_enable << 24; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_frame_qp(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - struct msm_vidc_inst_capability *capab; - s32 i_frame_qp = 0, p_frame_qp = 0, b_frame_qp = 0; - u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0; - u32 client_qp_enable = 0, hfi_value = 0, offset = 0; - s32 rc_type = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - capab = inst->capabilities; - - if (msm_vidc_get_parent_value(inst, cap_id, - BITRATE_MODE, &rc_type, __func__)) - return -EINVAL; - - if (inst->bufq[OUTPUT_PORT].vb2q->streaming) { - if (rc_type != HFI_RC_OFF) { - i_vpr_h(inst, - "%s: dynamic qp not allowed for rc type %d\n", - __func__, rc_type); - return 0; - } - } - - if (rc_type == HFI_RC_OFF) { - /* Mandatorily set for rc off case */ - i_qp_enable = p_qp_enable = b_qp_enable = 1; - } else { - /* Set only if client has set for NON rc off case */ - if (capab->cap[I_FRAME_QP].flags & CAP_FLAG_CLIENT_SET) - i_qp_enable = 1; - if (capab->cap[P_FRAME_QP].flags & CAP_FLAG_CLIENT_SET) - p_qp_enable = 1; - if (capab->cap[B_FRAME_QP].flags & CAP_FLAG_CLIENT_SET) - b_qp_enable = 1; - } - - client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; - if (!client_qp_enable) { - i_vpr_h(inst, - "%s: client did not set frame qp, cap %s is not set\n", - __func__, cap_name(cap_id)); - return 0; - } - - if (is_10bit_colorformat(capab->cap[PIX_FMTS].value)) - offset = 12; - - i_frame_qp = capab->cap[I_FRAME_QP].value + offset; - p_frame_qp = capab->cap[P_FRAME_QP].value + offset; - b_frame_qp = capab->cap[B_FRAME_QP].value + offset; - - hfi_value = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | - client_qp_enable << 24; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_req_sync_frame(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - s32 prepend_spspps; - u32 hfi_value = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - prepend_spspps = inst->capabilities->cap[PREPEND_SPSPPS_TO_IDR].value; - if (prepend_spspps) - hfi_value = HFI_SYNC_FRAME_REQUEST_WITH_PREFIX_SEQ_HDR; - else - hfi_value = HFI_SYNC_FRAME_REQUEST_WITHOUT_SEQ_HDR; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_chroma_qp_index_offset(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 = 0, chroma_qp_offset_mode = 0, chroma_qp = 0; - u32 offset = 12; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (inst->capabilities->cap[cap_id].flags & CAP_FLAG_CLIENT_SET) - chroma_qp_offset_mode = HFI_FIXED_CHROMAQP_OFFSET; - else - chroma_qp_offset_mode = HFI_ADAPTIVE_CHROMAQP_OFFSET; - - chroma_qp = inst->capabilities->cap[cap_id].value + offset; - hfi_value = chroma_qp_offset_mode | chroma_qp << 8 | chroma_qp << 16 ; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_slice_count(void* instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - struct msm_vidc_inst* inst = (struct msm_vidc_inst*)instance; - s32 slice_mode = -1; - u32 hfi_value = 0, set_cap_id = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - slice_mode = inst->capabilities->cap[SLICE_MODE].value; - - if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) { - i_vpr_h(inst, "%s: slice mode is: %u, ignore setting to fw\n", - __func__, slice_mode); - return 0; - } - if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) { - hfi_value = (inst->codec == MSM_VIDC_HEVC) ? - ((inst->capabilities->cap[SLICE_MAX_MB].value + 3) / 4) : - inst->capabilities->cap[SLICE_MAX_MB].value; - set_cap_id = SLICE_MAX_MB; - } else if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) { - hfi_value = inst->capabilities->cap[SLICE_MAX_BYTES].value; - set_cap_id = SLICE_MAX_BYTES; - } - - rc = msm_vidc_packetize_control(inst, set_cap_id, HFI_PAYLOAD_U32, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_nal_length(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 = HFI_NAL_LENGTH_STARTCODES; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (!inst->capabilities->cap[WITHOUT_STARTCODE].value) { - hfi_value = HFI_NAL_LENGTH_STARTCODES; - } else { - rc = msm_vidc_v4l2_to_hfi_enum(inst, NAL_LENGTH_FIELD, &hfi_value); - if (rc) - return -EINVAL; - } - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_layer_count_and_type(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_layer_count, hfi_layer_type = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) { - /* set layer type */ - hfi_layer_type = inst->hfi_layer_type; - cap_id = LAYER_TYPE; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, - &hfi_layer_type, sizeof(u32), __func__); - if (rc) - goto exit; - } else { - if (inst->hfi_layer_type == HFI_HIER_B) { - i_vpr_l(inst, - "%s: HB dyn layers change is not supported\n", - __func__); - return 0; - } - } - - /* set layer count */ - cap_id = ENH_LAYER_COUNT; - /* hfi baselayer starts from 1 */ - hfi_layer_count = inst->capabilities->cap[ENH_LAYER_COUNT].value + 1; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, - &hfi_layer_count, sizeof(u32), __func__); - if (rc) - goto exit; - -exit: - return rc; -} - -int msm_vidc_set_gop_size(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; - } - - if (inst->bufq[OUTPUT_PORT].vb2q->streaming) { - if (inst->hfi_layer_type == HFI_HIER_B) { - i_vpr_l(inst, - "%s: HB dyn GOP setting is not supported\n", - __func__); - return 0; - } - } - - hfi_value = inst->capabilities->cap[GOP_SIZE].value; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_bitrate(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0, i; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - u32 hfi_value = 0; - s32 rc_type = -1, enh_layer_count = -1; - u32 layer_br_caps[6] = {L0_BR, L1_BR, L2_BR, L3_BR, L4_BR, L5_BR}; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - /* set Total Bitrate */ - if (inst->capabilities->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) - goto set_total_bitrate; - - /* - * During runtime, if BIT_RATE cap CLIENT_SET flag is not set, - * then this function will be called due to change in ENH_LAYER_COUNT. - * In this case, client did not change bitrate, hence, no need to set - * to fw. - */ - if (inst->bufq[OUTPUT_PORT].vb2q->streaming) - return 0; - - if (msm_vidc_get_parent_value(inst, BIT_RATE, - BITRATE_MODE, &rc_type, __func__)) - return -EINVAL; - - if (rc_type != HFI_RC_CBR_CFR && rc_type != HFI_RC_CBR_VFR) { - i_vpr_h(inst, "%s: set total bitrate for non CBR rc type\n", - __func__); - goto set_total_bitrate; - } - - if (msm_vidc_get_parent_value(inst, BIT_RATE, - ENH_LAYER_COUNT, &enh_layer_count, __func__)) - return -EINVAL; - - /* - * ENH_LAYER_COUNT cap max is positive only if - * layer encoding is enabled during streamon. - */ - if (inst->capabilities->cap[ENH_LAYER_COUNT].max) { - if (!msm_vidc_check_all_layer_bitrate_set(inst)) - goto set_total_bitrate; - - /* set Layer Bitrate */ - for (i = 0; i <= enh_layer_count; i++) { - if (i >= ARRAY_SIZE(layer_br_caps)) - break; - cap_id = layer_br_caps[i]; - hfi_value = inst->capabilities->cap[cap_id].value; - rc = msm_vidc_packetize_control(inst, cap_id, - HFI_PAYLOAD_U32, &hfi_value, - sizeof(u32), __func__); - if (rc) - return rc; - } - goto exit; - } - -set_total_bitrate: - hfi_value = inst->capabilities->cap[BIT_RATE].value; - rc = msm_vidc_packetize_control(inst, BIT_RATE, HFI_PAYLOAD_U32, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; -exit: - return rc; -} - -int msm_vidc_set_dynamic_layer_bitrate(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 = 0; - s32 rc_type = -1; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) - return 0; - - /* set Total Bitrate */ - if (inst->capabilities->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) { - i_vpr_h(inst, - "%s: Total bitrate is set, ignore layer bitrate\n", - __func__); - return 0; - } - - /* - * ENH_LAYER_COUNT cap max is positive only if - * layer encoding is enabled during streamon. - */ - if (!inst->capabilities->cap[ENH_LAYER_COUNT].max || - !msm_vidc_check_all_layer_bitrate_set(inst)) { - i_vpr_h(inst, - "%s: invalid layer bitrate, ignore setting to fw\n", - __func__); - return 0; - } - - if (inst->hfi_rc_type == HFI_RC_CBR_CFR || - rc_type == HFI_RC_CBR_VFR) { - /* set layer bitrate for the client set layer */ - hfi_value = inst->capabilities->cap[cap_id].value; - rc = msm_vidc_packetize_control(inst, cap_id, - HFI_PAYLOAD_U32, &hfi_value, - sizeof(u32), __func__); - if (rc) - return rc; - } else { - /* - * All layer bitartes set for unsupported rc type. - * Hence accept layer bitrates, but set total bitrate prop - * with cumulative bitrate. - */ - hfi_value = inst->capabilities->cap[BIT_RATE].value; - rc = msm_vidc_packetize_control(inst, BIT_RATE, HFI_PAYLOAD_U32, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - } - - return rc; -} - -int msm_vidc_set_session_priority(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - u32 hfi_value = 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; - } - - hfi_value = inst->capabilities->cap[cap_id].value; - if (!is_critical_priority_session(inst)) - hfi_value = inst->capabilities->cap[cap_id].value + - inst->capabilities->cap[FIRMWARE_PRIORITY_OFFSET].value; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_flip(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - u32 hflip, vflip, hfi_value = HFI_DISABLE_FLIP; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - hflip = inst->capabilities->cap[HFLIP].value; - vflip = inst->capabilities->cap[VFLIP].value; - - if (hflip) - hfi_value |= HFI_HORIZONTAL_FLIP; - - if (vflip) - hfi_value |= HFI_VERTICAL_FLIP; - - if (inst->bufq[OUTPUT_PORT].vb2q->streaming) { - if (hfi_value != HFI_DISABLE_FLIP) { - rc = msm_vidc_set_req_sync_frame(inst, - REQUEST_I_FRAME); - if (rc) - return rc; - } - } - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_preprocess(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_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_rotation(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_to_hfi_enum(inst, cap_id, &hfi_value); - if (rc) - return -EINVAL; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_blur_resolution(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - s32 blur_type = -1; - u32 hfi_value, blur_width, blur_height; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (msm_vidc_get_parent_value(inst, cap_id, - BLUR_TYPES, &blur_type, __func__)) - return -EINVAL; - - if (blur_type != MSM_VIDC_BLUR_EXTERNAL) - return 0; - - hfi_value = inst->capabilities->cap[cap_id].value; - - blur_width = (hfi_value & 0xFFFF0000) >> 16; - blur_height = hfi_value & 0xFFFF; - - if (blur_width > inst->crop.width || - blur_height > inst->crop.height) { - i_vpr_e(inst, - "%s: blur wxh: %dx%d exceeds crop wxh: %dx%d\n", - __func__, blur_width, blur_height, - inst->crop.width, inst->crop.height); - hfi_value = 0; - } - - if (blur_width == inst->crop.width && - blur_height == inst->crop.height) { - i_vpr_e(inst, - "%s: blur wxh: %dx%d is equal to crop wxh: %dx%d\n", - __func__, blur_width, blur_height, - inst->crop.width, inst->crop.height); - hfi_value = 0; - } - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -static int msm_venc_set_csc_coeff(struct msm_vidc_inst *inst, - const char *prop_name, u32 hfi_id, void *payload, - u32 payload_size, u32 row_count, u32 column_count) -{ - int rc = 0; - - i_vpr_h(inst, - "set cap: name: %24s, hard coded %dx%d matrix array\n", - prop_name, row_count, column_count); - rc = venus_hfi_session_property(inst, - hfi_id, - HFI_HOST_FLAGS_NONE, - HFI_PORT_BITSTREAM, - HFI_PAYLOAD_S32_ARRAY, - payload, - payload_size); - if (rc) { - i_vpr_e(inst, - "%s: failed to set %s to fw\n", - __func__, prop_name); - } - - return rc; -} -int msm_vidc_set_csc_custom_matrix(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - int i; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - struct msm_vidc_core *core; - struct msm_vidc_csc_coeff *csc_coeff; - s32 matrix_payload[MAX_MATRIX_COEFFS + 2]; - s32 csc_bias_payload[MAX_BIAS_COEFFS + 2]; - s32 csc_limit_payload[MAX_LIMIT_COEFFS + 2]; - - if (!inst || !inst->capabilities || !inst->core) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - core = inst->core; - if (!core->platform) { - d_vpr_e("%s: invalid core platform\n", __func__); - return -EINVAL; - } - csc_coeff = &core->platform->data.csc_data; - - if (!inst->capabilities->cap[cap_id].value || - !inst->capabilities->cap[CSC].value) { - i_vpr_h(inst, - "%s: ignored as custom martix %u, csc %u\n", - __func__, inst->capabilities->cap[cap_id].value, - inst->capabilities->cap[CSC].value); - return 0; - } - - /* - * first 2 u32's of payload in each case are for - * row and column count, next remaining u32's are - * for the actual payload values. - */ - - /* set custom matrix */ - matrix_payload[0] = 3; - matrix_payload[1] = 3; - - for(i = 0; i < MAX_MATRIX_COEFFS; i++) { - if ((i + 2) >= ARRAY_SIZE(matrix_payload)) - break; - matrix_payload[i + 2] = - csc_coeff->vpe_csc_custom_matrix_coeff[i]; - } - - rc = msm_venc_set_csc_coeff(inst, "CSC_CUSTOM_MATRIX", - HFI_PROP_CSC_MATRIX, &matrix_payload[0], - ARRAY_SIZE(matrix_payload) * sizeof(s32), - matrix_payload[0], matrix_payload[1]); - if (rc) - return rc; - - /* set csc bias */ - csc_bias_payload[0] = 1; - csc_bias_payload[1] = 3; - - for(i = 0; i < MAX_BIAS_COEFFS; i++) { - if ((i + 2) >= ARRAY_SIZE(csc_bias_payload)) - break; - csc_bias_payload[i + 2] = - csc_coeff->vpe_csc_custom_bias_coeff[i]; - } - - rc = msm_venc_set_csc_coeff(inst, "CSC_BIAS", - HFI_PROP_CSC_BIAS, &csc_bias_payload[0], - ARRAY_SIZE(csc_bias_payload) * sizeof(s32), - csc_bias_payload[0], csc_bias_payload[1]); - if (rc) - return rc; - - /* set csc limit */ - csc_limit_payload[0] = 1; - csc_limit_payload[1] = 6; - - for(i = 0; i < MAX_LIMIT_COEFFS; i++) { - if ((i + 2) >= ARRAY_SIZE(csc_limit_payload)) - break; - csc_limit_payload[i + 2] = - csc_coeff->vpe_csc_custom_limit_coeff[i]; - } - - rc = msm_venc_set_csc_coeff(inst, "CSC_LIMIT", - HFI_PROP_CSC_LIMIT, &csc_limit_payload[0], - ARRAY_SIZE(csc_limit_payload) * sizeof(s32), - csc_limit_payload[0], csc_limit_payload[1]); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_reserve_duration(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - u32 hfi_value = 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; - } - - /* reserve hardware only when input port is streaming*/ - if (!inst->bufq[INPUT_PORT].vb2q->streaming) - return 0; - - if (!(inst->capabilities->cap[cap_id].flags & CAP_FLAG_CLIENT_SET)) - return 0; - - inst->capabilities->cap[cap_id].flags &= (~CAP_FLAG_CLIENT_SET); - - if (!is_critical_priority_session(inst)) { - i_vpr_h(inst, "%s: reserve duration allowed only for critical session\n", __func__); - return 0; - } - - hfi_value = inst->capabilities->cap[cap_id].value; - - rc = venus_hfi_reserve_hardware(inst, hfi_value); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_level(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 = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - hfi_value = inst->capabilities->cap[cap_id].value; - if (!(inst->capabilities->cap[cap_id].flags & CAP_FLAG_CLIENT_SET)) - hfi_value = HFI_LEVEL_NONE; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_q16(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 = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - hfi_value = inst->capabilities->cap[cap_id].value; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_Q16, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - 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; - } - - if (inst->capabilities->cap[cap_id].flags & CAP_FLAG_MENU) { - rc = msm_vidc_v4l2_menu_to_hfi(inst, cap_id, &hfi_value); - if (rc) - return -EINVAL; - } else { - hfi_value = inst->capabilities->cap[cap_id].value; - } - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_u32_packed(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; - } - - if (inst->capabilities->cap[cap_id].flags & CAP_FLAG_MENU) { - rc = msm_vidc_v4l2_menu_to_hfi(inst, cap_id, &hfi_value); - if (rc) - return -EINVAL; - } else { - hfi_value = inst->capabilities->cap[cap_id].value; - } - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_u32_enum(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_to_hfi_enum(inst, cap_id, &hfi_value); - if (rc) - return -EINVAL; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - 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; - s32 hfi_value = 0; - - if (!inst || !inst->capabilities) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - hfi_value = inst->capabilities->cap[cap_id].value; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_S32, - &hfi_value, sizeof(s32), __func__); - if (rc) - return rc; - - 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 (cap_id) { - case 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; - goto set_default; - } - return 0; - default: - i_vpr_e(inst, - "%s: mapping not specified for ctrl_id: %#x\n", - __func__, capability->cap[cap_id].v4l2_id); - return -EINVAL; - } - -set_default: - i_vpr_e(inst, - "%s: invalid value %d for ctrl id: %#x. Set default: %u\n", - __func__, capability->cap[cap_id].value, - capability->cap[cap_id].v4l2_id, *value); - return 0; -} - -int msm_vidc_v4l2_to_hfi_enum(struct msm_vidc_inst *inst, - enum msm_vidc_inst_capability_type cap_id, u32 *value) -{ - struct msm_vidc_inst_capability *capability = inst->capabilities; - - switch (cap_id) { - case BITRATE_MODE: - *value = inst->hfi_rc_type; - return 0; - case PROFILE: - case LEVEL: - case HEVC_TIER: - case AV1_TIER: - case BLUR_TYPES: - *value = capability->cap[cap_id].value; - return 0; - case LAYER_TYPE: - if (inst->codec == MSM_VIDC_HEVC) { - switch (capability->cap[cap_id].value) { - case V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B: - *value = HFI_HIER_B; - break; - case V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P: - //TODO (AS): check if this is right mapping - *value = HFI_HIER_P_SLIDING_WINDOW; - break; - default: - *value = HFI_HIER_P_SLIDING_WINDOW; - goto set_default; - } - } - return 0; - case ROTATION: - switch (capability->cap[cap_id].value) { - case 0: - *value = HFI_ROTATION_NONE; - break; - case 90: - *value = HFI_ROTATION_90; - break; - case 180: - *value = HFI_ROTATION_180; - break; - case 270: - *value = HFI_ROTATION_270; - break; - default: - *value = HFI_ROTATION_NONE; - goto set_default; - } - return 0; - case LF_MODE: - if (inst->codec == MSM_VIDC_HEVC) { - switch (capability->cap[cap_id].value) { - case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED: - *value = HFI_DEBLOCK_ALL_BOUNDARY; - break; - case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED: - *value = HFI_DEBLOCK_DISABLE; - break; - case DB_HEVC_DISABLE_SLICE_BOUNDARY: - *value = HFI_DEBLOCK_DISABLE_AT_SLICE_BOUNDARY; - break; - default: - *value = HFI_DEBLOCK_ALL_BOUNDARY; - goto set_default; - } - } else if (inst->codec == MSM_VIDC_H264) { - switch (capability->cap[cap_id].value) { - case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED: - *value = HFI_DEBLOCK_ALL_BOUNDARY; - break; - case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED: - *value = HFI_DEBLOCK_DISABLE; - break; - case DB_H264_DISABLE_SLICE_BOUNDARY: - *value = HFI_DEBLOCK_DISABLE_AT_SLICE_BOUNDARY; - break; - default: - *value = HFI_DEBLOCK_ALL_BOUNDARY; - goto set_default; - } - } - return 0; - case NAL_LENGTH_FIELD: - switch (capability->cap[cap_id].value) { - case V4L2_MPEG_VIDEO_HEVC_SIZE_4: - *value = HFI_NAL_LENGTH_SIZE_4; - break; - default: - *value = HFI_NAL_LENGTH_STARTCODES; - goto set_default; - } - return 0; - default: - i_vpr_e(inst, - "%s: mapping not specified for ctrl_id: %#x\n", - __func__, capability->cap[cap_id].v4l2_id); - return -EINVAL; - } - -set_default: - i_vpr_e(inst, - "%s: invalid value %d for ctrl id: %#x. Set default: %u\n", - __func__, capability->cap[cap_id].value, - capability->cap[cap_id].v4l2_id, *value); - return 0; -} - -int msm_vidc_set_stage(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - u32 stage = 0; - struct msm_vidc_core *core; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - - if (!inst || !inst->capabilities || !inst->core) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - core = inst->core; - - rc = call_session_op(core, decide_work_mode, inst); - if (rc) { - i_vpr_e(inst, "%s: decide_work_mode failed\n", __func__); - return -EINVAL; - } - - stage = inst->capabilities->cap[STAGE].value; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, - &stage, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_pipe(void *instance, - enum msm_vidc_inst_capability_type cap_id) -{ - int rc = 0; - u32 pipe; - struct msm_vidc_core *core; - struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - - if (!inst || !inst->capabilities || !inst->core) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - core = inst->core; - - rc = call_session_op(core, decide_work_route, inst); - if (rc) { - i_vpr_e(inst, "%s: decide_work_route failed\n", - __func__); - return -EINVAL; - } - - pipe = inst->capabilities->cap[PIPE].value; - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, - &pipe, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} - -int msm_vidc_set_vui_timing_info(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; - } - - /* - * hfi is HFI_PROP_DISABLE_VUI_TIMING_INFO and v4l2 cap is - * V4L2_CID_MPEG_VIDC_VUI_TIMING_INFO and hence reverse - * the hfi_value from cap_id value. - */ - if (inst->capabilities->cap[cap_id].value == 1) - hfi_value = 0; - else - hfi_value = 1; - - rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, - &hfi_value, sizeof(u32), __func__); - if (rc) - return rc; - - return rc; -} diff --git a/driver/vidc/src/msm_vidc_control_ext.c b/driver/vidc/src/msm_vidc_control_ext.c index ba127cc076..b526f2df19 100644 --- a/driver/vidc/src/msm_vidc_control_ext.c +++ b/driver/vidc/src/msm_vidc_control_ext.c @@ -12,6 +12,7 @@ #include "msm_vidc_internal.h" #include "msm_vidc_driver.h" #include "msm_venc.h" +#include "msm_vidc_platform.h" int msm_vidc_adjust_ir_period(void *instance, struct v4l2_ctrl *ctrl) { diff --git a/driver/vidc/src/venus_hfi_response.c b/driver/vidc/src/venus_hfi_response.c index c7f3ab82fc..6c1b9e2a07 100644 --- a/driver/vidc/src/venus_hfi_response.c +++ b/driver/vidc/src/venus_hfi_response.c @@ -12,7 +12,6 @@ #include "msm_vidc_debug.h" #include "msm_vidc_driver.h" #include "msm_vdec.h" -#include "msm_vidc_control.h" #include "msm_vidc_memory.h" #include "msm_vidc_fence.h" #include "msm_vidc_platform.h"