diff --git a/driver/platform/waipio/src/msm_vidc_waipio.c b/driver/platform/waipio/src/msm_vidc_waipio.c index eb71a37032..899fe5f060 100644 --- a/driver/platform/waipio/src/msm_vidc_waipio.c +++ b/driver/platform/waipio/src/msm_vidc_waipio.c @@ -1146,10 +1146,10 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { {PRIORITY, DEC|ENC, CODECS_ALL, 0, 2, 1, 1, V4L2_CID_MPEG_VIDC_PRIORITY, - HFI_PROP_REALTIME, - CAP_FLAG_ROOT, + HFI_PROP_SESSION_PRIORITY, + CAP_FLAG_ROOT | CAP_FLAG_DYNAMIC_ALLOWED, {0}, {0}, - NULL, NULL}, + msm_vidc_adjust_session_priority, msm_vidc_set_session_priority}, {ENC_IP_CR, ENC, CODECS_ALL, 0, S32_MAX, 1, 0, @@ -1395,6 +1395,12 @@ static struct msm_vidc_ubwc_config_data ubwc_config_waipio[] = { UBWC_CONFIG(8, 32, 16, 0, 1, 1, 1), }; +/* Default bus bandwidth for non_real time session based on priority */ +static u32 bus_bw_nrt[] = { + 15000000, + 11000000, +}; + static struct msm_vidc_platform_data waipio_data = { .core_data = core_data_waipio, .core_data_size = ARRAY_SIZE(core_data_waipio), @@ -1404,6 +1410,7 @@ static struct msm_vidc_platform_data waipio_data = { .csc_data.vpe_csc_custom_matrix_coeff = vpe_csc_custom_matrix_coeff, .csc_data.vpe_csc_custom_limit_coeff = vpe_csc_custom_limit_coeff, .ubwc_config = ubwc_config_waipio, + .bus_bw_nrt = bus_bw_nrt, }; static int msm_vidc_init_data(struct msm_vidc_core *core) diff --git a/driver/variant/iris2/src/msm_vidc_power_iris2.c b/driver/variant/iris2/src/msm_vidc_power_iris2.c index bdba6cf42c..e7619512eb 100644 --- a/driver/variant/iris2/src/msm_vidc_power_iris2.c +++ b/driver/variant/iris2/src/msm_vidc_power_iris2.c @@ -8,6 +8,7 @@ #include "msm_vidc_core.h" #include "msm_vidc_driver.h" #include "msm_vidc_debug.h" +#include "msm_vidc_dt.h" u64 msm_vidc_calc_freq_iris2(struct msm_vidc_inst *inst, u32 data_size) { @@ -21,15 +22,29 @@ u64 msm_vidc_calc_freq_iris2(struct msm_vidc_inst *inst, u32 data_size) u32 operating_rate, vsp_factor_num = 1, vsp_factor_den = 1; u32 base_cycles = 0; u32 fps; + u32 prio_val; if (!inst || !inst->core || !inst->capabilities) { d_vpr_e("%s: invalid params\n", __func__); return freq; } - core = inst->core; - power = &inst->power; - mbs_per_second = msm_vidc_get_inst_load(inst, LOAD_POWER); + power = &inst->power; + core = inst->core; + if (!core->dt) { + d_vpr_e("%s: invalid params\n", __func__); + return freq; + } + + if (!is_realtime_session(inst)) { + prio_val = inst->capabilities->cap[PRIORITY].value; + if (!prio_val || prio_val > core->dt->allowed_clks_tbl_size) + prio_val = core->dt->allowed_clks_tbl_size; + + return core->dt->allowed_clks_tbl[prio_val-1].clock_rate; + } + + mbs_per_second = msm_vidc_get_inst_load(inst); fps = msm_vidc_get_fps(inst); /* diff --git a/driver/vidc/inc/hfi_property.h b/driver/vidc/inc/hfi_property.h index e89d5f3b35..a6cb9ad6cf 100644 --- a/driver/vidc/inc/hfi_property.h +++ b/driver/vidc/inc/hfi_property.h @@ -83,7 +83,7 @@ enum hfi_color_format { #define HFI_BITMASK_CROP_TOP_OFFSET 0x0000ffff #define HFI_PROP_CROP_OFFSETS 0x03000105 -#define HFI_PROP_REALTIME 0x03000106 +#define HFI_PROP_SESSION_PRIORITY 0x03000106 enum hfi_avc_profile_type { HFI_AVC_PROFILE_BASELINE = 0, diff --git a/driver/vidc/inc/msm_vidc_control.h b/driver/vidc/inc/msm_vidc_control.h index be8a307604..383f9a1252 100644 --- a/driver/vidc/inc/msm_vidc_control.h +++ b/driver/vidc/inc/msm_vidc_control.h @@ -37,6 +37,7 @@ 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_frame_qp(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_v4l2_properties(struct msm_vidc_inst *inst); +int msm_vidc_adjust_session_priority(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_set_header_mode(void *instance, enum msm_vidc_inst_capability_type cap_id); @@ -74,6 +75,8 @@ 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_s32(void *instance, enum msm_vidc_inst_capability_type cap_id); int msm_vidc_set_array(void *instance, diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index 4ed1f9cc0f..522626a743 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/driver/vidc/inc/msm_vidc_driver.h @@ -180,7 +180,7 @@ static inline bool is_low_power_session(struct msm_vidc_inst *inst) static inline bool is_realtime_session(struct msm_vidc_inst *inst) { - return !inst->capabilities->cap[PRIORITY].value; + return inst->capabilities->cap[PRIORITY].value == 0 ? true : false; } static inline bool is_lowlatency_session(struct msm_vidc_inst *inst) @@ -353,6 +353,7 @@ int msm_vidc_deinit_instance_caps(struct msm_vidc_core* core); int msm_vidc_update_debug_str(struct msm_vidc_inst *inst); bool msm_vidc_allow_decode_batch(struct msm_vidc_inst *inst); int msm_vidc_check_session_supported(struct msm_vidc_inst *inst); +int msm_vidc_check_mbps_supported(struct msm_vidc_inst *inst); int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst); #endif // _MSM_VIDC_DRIVER_H_ diff --git a/driver/vidc/inc/msm_vidc_inst.h b/driver/vidc/inc/msm_vidc_inst.h index 0b2a9e3bf4..ec172220f7 100644 --- a/driver/vidc/inc/msm_vidc_inst.h +++ b/driver/vidc/inc/msm_vidc_inst.h @@ -136,6 +136,7 @@ struct msm_vidc_inst { struct debug_buf_count debug_count; struct msm_vidc_inst_capability *capabilities; struct completion completions[MAX_SIGNAL]; + enum priority_level priority_level; bool active; u64 last_qbuf_time_ns; bool vb2q_init; diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index 10b0ac9b7d..bba38613cc 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -124,6 +124,11 @@ enum msm_vidc_codec_type { MSM_VIDC_HEIC = BIT(3), }; +enum priority_level { + MSM_VIDC_PRIORITY_LOW, + MSM_VIDC_PRIORITY_HIGH, +}; + enum msm_vidc_colorformat_type { MSM_VIDC_FMT_NONE = 0, MSM_VIDC_FMT_NV12 = BIT(0), @@ -686,11 +691,6 @@ struct msm_vidc_decode_batch { struct delayed_work work; }; -enum load_calc_quirks { - LOAD_POWER = 0, - LOAD_ADMISSION_CONTROL = 1, -}; - enum msm_vidc_power_mode { VIDC_POWER_NORMAL = 0, VIDC_POWER_LOW, diff --git a/driver/vidc/inc/msm_vidc_platform.h b/driver/vidc/inc/msm_vidc_platform.h index 08e225dc56..28bf5e11cb 100644 --- a/driver/vidc/inc/msm_vidc_platform.h +++ b/driver/vidc/inc/msm_vidc_platform.h @@ -68,6 +68,7 @@ struct msm_vidc_platform_data { u32 allowed_clks_tbl_size; struct msm_vidc_csc_coeff csc_data; struct msm_vidc_ubwc_config_data *ubwc_config; + u32 *bus_bw_nrt; }; struct msm_vidc_platform { diff --git a/driver/vidc/inc/msm_vidc_power.h b/driver/vidc/inc/msm_vidc_power.h index 7848b3477a..744c9a75d2 100644 --- a/driver/vidc/inc/msm_vidc_power.h +++ b/driver/vidc/inc/msm_vidc_power.h @@ -247,8 +247,7 @@ static inline int __bpp(enum msm_vidc_colorformat_type f) } u64 msm_vidc_max_freq(struct msm_vidc_inst* inst); -int msm_vidc_get_inst_load(struct msm_vidc_inst* inst, - enum load_calc_quirks quirks); +int msm_vidc_get_inst_load(struct msm_vidc_inst *inst); int msm_vidc_scale_power(struct msm_vidc_inst *inst, bool scale_buses); #endif diff --git a/driver/vidc/src/msm_vdec.c b/driver/vidc/src/msm_vdec.c index 95cb2fd42a..f5aecee6c5 100644 --- a/driver/vidc/src/msm_vdec.c +++ b/driver/vidc/src/msm_vdec.c @@ -681,32 +681,6 @@ static int msm_vdec_set_thumbnail_mode(struct msm_vidc_inst *inst, return rc; } -static int msm_vdec_set_realtime(struct msm_vidc_inst *inst, - enum msm_vidc_port_type port) -{ - int rc = 0; - u32 realtime = 1; //todo - - if (port != INPUT_PORT) { - i_vpr_e(inst, "%s: invalid port %d\n", __func__, port); - return -EINVAL; - } - - realtime = inst->capabilities->cap[PRIORITY].value; - i_vpr_h(inst, "%s: priority: %d", __func__, realtime); - rc = venus_hfi_session_property(inst, - HFI_PROP_REALTIME, - HFI_HOST_FLAGS_NONE, - get_hfi_port(inst, port), - HFI_PAYLOAD_U32, - &realtime, - sizeof(u32)); - if (rc) - i_vpr_e(inst, "%s: set property failed\n", __func__); - - return rc; -} - static int msm_vdec_set_conceal_color_8bit(struct msm_vidc_inst *inst, enum msm_vidc_port_type port) { @@ -786,10 +760,6 @@ static int msm_vdec_set_input_properties(struct msm_vidc_inst *inst) if (rc) return rc; - rc = msm_vdec_set_realtime(inst, INPUT_PORT); - if (rc) - return rc; - rc = msm_vdec_set_conceal_color_8bit(inst, INPUT_PORT); if (rc) return rc; @@ -2158,13 +2128,36 @@ int msm_vdec_s_param(struct msm_vidc_inst *inst, set_default: q16_rate = (u32)input_rate << 16; - i_vpr_h(inst, "%s: type %u value %#x\n", - __func__, s_parm->type, q16_rate); + i_vpr_h(inst, "%s: %s value %d\n", + __func__, is_frame_rate ? "frame rate" : "operating rate", input_rate); msm_vidc_update_cap_value(inst, is_frame_rate ? FRAME_RATE : OPERATING_RATE, q16_rate, __func__); + if ((s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && + inst->vb2q[INPUT_PORT].streaming) || + (s_parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && + inst->vb2q[OUTPUT_PORT].streaming)) { + if (msm_vidc_check_mbps_supported(inst)) { + i_vpr_e(inst, + "%s: Unsupported load with rate %d, setting default rate %d\n", + __func__, input_rate, default_rate); + msm_vidc_update_cap_value(inst, + is_frame_rate ? FRAME_RATE : OPERATING_RATE, + default_rate << 16, __func__); + return -ENOMEM; + } + } + + if (!is_realtime_session(inst)) + inst->priority_level = MSM_VIDC_PRIORITY_HIGH; + + if (is_frame_rate) + capability->cap[FRAME_RATE].flags |= CAP_FLAG_CLIENT_SET; + else + capability->cap[OPERATING_RATE].flags |= CAP_FLAG_CLIENT_SET; + exit: return rc; } diff --git a/driver/vidc/src/msm_venc.c b/driver/vidc/src/msm_venc.c index 7e60b45ed2..6d0e1b5fe0 100644 --- a/driver/vidc/src/msm_venc.c +++ b/driver/vidc/src/msm_venc.c @@ -1603,6 +1603,28 @@ set_default: is_frame_rate ? FRAME_RATE : OPERATING_RATE, q16_rate, __func__); + if ((s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && + inst->vb2q[INPUT_PORT].streaming) || + (s_parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && + inst->vb2q[OUTPUT_PORT].streaming)) { + if (msm_vidc_check_mbps_supported(inst)) { + i_vpr_e(inst, + "%s: Unsupported load with rate %d, setting default rate %d\n", + __func__, input_rate, default_rate); + msm_vidc_update_cap_value(inst, + is_frame_rate ? FRAME_RATE : OPERATING_RATE, + default_rate << 16, __func__); + return -ENOMEM; + } + } + + if (!is_realtime_session(inst)) + inst->priority_level = MSM_VIDC_PRIORITY_HIGH; + + if (is_frame_rate) + capability->cap[FRAME_RATE].flags |= CAP_FLAG_CLIENT_SET; + else + capability->cap[OPERATING_RATE].flags |= CAP_FLAG_CLIENT_SET; /* * In static case, frame rate is set via * inst database set function mentioned in diff --git a/driver/vidc/src/msm_vidc_control.c b/driver/vidc/src/msm_vidc_control.c index 904def341c..22617ef04e 100644 --- a/driver/vidc/src/msm_vidc_control.c +++ b/driver/vidc/src/msm_vidc_control.c @@ -655,6 +655,13 @@ int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl) if (rc) return rc; } + + if (ctrl->id == V4L2_CID_MPEG_VIDC_PRIORITY) { + rc = msm_vidc_adjust_session_priority(inst, ctrl); + if (rc) + return rc; + } + if (is_meta_ctrl(ctrl->id)) { rc = msm_vidc_update_meta_port_settings(inst); if (rc) @@ -1421,6 +1428,52 @@ int msm_vidc_adjust_hevc_frame_qp(void *instance, struct v4l2_ctrl *ctrl) return rc; } +int msm_vidc_adjust_session_priority(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + int adjusted_value; + bool rate_by_client = false; + 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; + adjusted_value = ctrl ? ctrl->val : + capability->cap[PRIORITY].value; + + if (capability->cap[FRAME_RATE].flags & CAP_FLAG_CLIENT_SET || + capability->cap[OPERATING_RATE].flags & CAP_FLAG_CLIENT_SET) + rate_by_client = true; + + /* + * For RT, check for resource feasability if rate is set by client. + * For RT, move to NRT, if rate is not set by client. + * For NRT, sessions with rate set by client takes higher order + * among NRT sessions. They are constraint RT or low priority RT. + */ + if (adjusted_value == 0 && rate_by_client) { + rc = msm_vidc_check_mbps_supported(inst); + if (rc) { + d_vpr_e("%s: priority 0 not feasible due to resource\n", __func__); + return rc; + } + } + if (adjusted_value == 0 && !rate_by_client) { + adjusted_value = 1; + inst->priority_level = MSM_VIDC_PRIORITY_LOW; + } + + if (adjusted_value > 0 && rate_by_client) + inst->priority_level = MSM_VIDC_PRIORITY_HIGH; + + msm_vidc_update_cap_value(inst, PRIORITY, adjusted_value, __func__); + + return rc; +} + /* * Loop over instance capabilities with CAP_FLAG_ROOT * and call adjust function, where @@ -2098,6 +2151,26 @@ exit: 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 * 2) + inst->priority_level; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + + return rc; +} + /* TODO int msm_vidc_set_flip(void *instance, enum msm_vidc_inst_capability_type cap_id) diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index 9f6e66d959..45c71a5492 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -3855,7 +3855,7 @@ int msm_vidc_update_debug_str(struct msm_vidc_inst *inst) return 0; } -static int msm_vidc_check_mbps_supported(struct msm_vidc_inst *inst) +int msm_vidc_check_mbps_supported(struct msm_vidc_inst *inst) { u32 mbps = 0; struct msm_vidc_core *core; @@ -3879,7 +3879,7 @@ static int msm_vidc_check_mbps_supported(struct msm_vidc_inst *inst) !is_realtime_session(instance)) continue; - mbps += msm_vidc_get_inst_load(instance, LOAD_ADMISSION_CONTROL); + mbps += msm_vidc_get_inst_load(instance); } core_unlock(core, __func__); diff --git a/driver/vidc/src/msm_vidc_power.c b/driver/vidc/src/msm_vidc_power.c index c887defc49..8158268433 100644 --- a/driver/vidc/src/msm_vidc_power.c +++ b/driver/vidc/src/msm_vidc_power.c @@ -45,8 +45,7 @@ u64 msm_vidc_max_freq(struct msm_vidc_inst *inst) return freq; } -static int msm_vidc_get_mbps(struct msm_vidc_inst *inst, - enum load_calc_quirks quirks) +static int msm_vidc_get_mbps(struct msm_vidc_inst *inst) { int input_port_mbs, output_port_mbs; int fps, operating_rate, frame_rate; @@ -63,11 +62,7 @@ static int msm_vidc_get_mbps(struct msm_vidc_inst *inst, frame_rate = inst->capabilities->cap[FRAME_RATE].value; operating_rate = inst->capabilities->cap[OPERATING_RATE].value; - fps = frame_rate; - - /* For admission control operating rate is ignored */ - if (quirks == LOAD_POWER) - fps = max(operating_rate, frame_rate); + fps = max(operating_rate, frame_rate); /* In case of fps < 1 we assume 1 */ fps = max(fps >> 16, 1); @@ -75,8 +70,7 @@ static int msm_vidc_get_mbps(struct msm_vidc_inst *inst, return max(input_port_mbs, output_port_mbs) * fps; } -int msm_vidc_get_inst_load(struct msm_vidc_inst *inst, - enum load_calc_quirks quirks) +int msm_vidc_get_inst_load(struct msm_vidc_inst *inst) { int load = 0; @@ -85,34 +79,18 @@ int msm_vidc_get_inst_load(struct msm_vidc_inst *inst, return -EINVAL; } - if (inst->state == MSM_VIDC_OPEN || - inst->state == MSM_VIDC_ERROR) + if (inst->state == MSM_VIDC_ERROR) goto exit; /* - * Clock and Load calculations for REALTIME/NON-REALTIME - * Operating rate will either Default or Client value. - * Session admission control will be based on Load. - * Power requests based of calculated Clock/Freq. - * ----------------|----------------------------| - * REALTIME | Admission Control Load = | - * | res * fps | - * | Power Request Load = | - * | res * max(op, fps)| - * ----------------|----------------------------| - * NON-REALTIME/ | Admission Control Load = 0 | - * THUMBNAIL/ | Power Request Load = | - * IMAGE | res * max(op, fps)| - * | | - * ----------------|----------------------------| + * NRT sessions - clock scaling is based on OPP table. + * - No load based rejection. + * RT sessions - clock scaling and session admission based on load. */ - if (is_thumbnail_session(inst) || is_image_session(inst)) - goto exit; - - if (!is_realtime_session(inst) && quirks == LOAD_ADMISSION_CONTROL) - goto exit; - - load = msm_vidc_get_mbps(inst, quirks); + if (is_thumbnail_session(inst) || !is_realtime_session(inst)) + load = 0; + else + load = msm_vidc_get_mbps(inst); exit: return load; @@ -174,7 +152,12 @@ static int msm_vidc_set_buses(struct msm_vidc_inst* inst) d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } + core = inst->core; + if (!core || !core->platform || !core->platform->data.bus_bw_nrt) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } mutex_lock(&core->lock); curr_time_ns = ktime_get_ns(); @@ -198,6 +181,12 @@ static int msm_vidc_set_buses(struct msm_vidc_inst* inst) total_bw_ddr = total_bw_llcc = INT_MAX; break; } + + if (!is_realtime_session(inst)) { + temp->power.ddr_bw = core->platform->data.bus_bw_nrt[0]; + temp->power.sys_cache_bw = 0; + } + total_bw_ddr += temp->power.ddr_bw; total_bw_llcc += temp->power.sys_cache_bw; }