From dc38176276332bdc1822fbe7d09356e2ff9676ed Mon Sep 17 00:00:00 2001 From: Deepa Guthyappa Madivalara Date: Thu, 24 Feb 2022 12:31:27 -0800 Subject: [PATCH] video driver: calculate power based on input queuing rate Use client input buffer queuing rate for power calculations for non-realtime sessions Change-Id: I498422ba1ae9ae96b782a2096dc0cd0aa7b05798 Signed-off-by: Deepa Guthyappa Madivalara --- driver/platform/kalama/src/msm_vidc_kalama.c | 4 ++ driver/platform/waipio/src/msm_vidc_waipio.c | 4 ++ .../variant/iris2/src/msm_vidc_power_iris2.c | 23 ++++---- .../variant/iris3/src/msm_vidc_power_iris3.c | 23 ++++---- driver/vidc/inc/msm_vidc_driver.h | 2 + driver/vidc/inc/msm_vidc_inst.h | 1 + driver/vidc/inc/msm_vidc_internal.h | 7 +++ driver/vidc/inc/msm_vidc_memory.h | 1 + driver/vidc/src/msm_vidc.c | 1 + driver/vidc/src/msm_vidc_driver.c | 56 ++++++++++++++++++- driver/vidc/src/msm_vidc_memory.c | 1 + driver/vidc/src/msm_vidc_power.c | 26 +++++---- driver/vidc/src/msm_vidc_vb2.c | 10 +++- 13 files changed, 123 insertions(+), 36 deletions(-) diff --git a/driver/platform/kalama/src/msm_vidc_kalama.c b/driver/platform/kalama/src/msm_vidc_kalama.c index a7b2644996..b26cc0ec9a 100644 --- a/driver/platform/kalama/src/msm_vidc_kalama.c +++ b/driver/platform/kalama/src/msm_vidc_kalama.c @@ -255,6 +255,10 @@ static struct msm_platform_inst_capability instance_data_kalama[] = { (MINIMUM_FPS << 16), (MAXIMUM_OVERRIDE_VP9_FPS << 16), 1, (DEFAULT_FPS << 16)}, + {INPUT_RATE, ENC|DEC, CODECS_ALL, + (MINIMUM_FPS << 16), INT_MAX, + 1, (DEFAULT_FPS << 16)}, + {SCALE_FACTOR, ENC, H264|HEVC, 1, 8, 1, 8}, {MB_CYCLES_VSP, ENC, CODECS_ALL, 25, 25, 1, 25}, diff --git a/driver/platform/waipio/src/msm_vidc_waipio.c b/driver/platform/waipio/src/msm_vidc_waipio.c index 49d20188d5..88914ddd45 100644 --- a/driver/platform/waipio/src/msm_vidc_waipio.c +++ b/driver/platform/waipio/src/msm_vidc_waipio.c @@ -241,6 +241,10 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { (MINIMUM_FPS << 16), (MAXIMUM_OVERRIDE_VP9_FPS << 16), 1, (DEFAULT_FPS << 16)}, + {INPUT_RATE, ENC|DEC, CODECS_ALL, + (MINIMUM_FPS << 16), INT_MAX, + 1, (DEFAULT_FPS << 16)}, + {SCALE_FACTOR, ENC, H264|HEVC, 1, 8, 1, 8}, {MB_CYCLES_VSP, ENC, CODECS_ALL, 25, 25, 1, 25}, diff --git a/driver/variant/iris2/src/msm_vidc_power_iris2.c b/driver/variant/iris2/src/msm_vidc_power_iris2.c index 3e830c2c1a..82dd29b767 100644 --- a/driver/variant/iris2/src/msm_vidc_power_iris2.c +++ b/driver/variant/iris2/src/msm_vidc_power_iris2.c @@ -21,8 +21,7 @@ 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; - u32 buf_timetamps_fps, mbpf; + u32 buf_timetamps_fps, mbpf, input_rate; if (!inst || !inst->core || !inst->capabilities) { d_vpr_e("%s: invalid params\n", __func__); @@ -35,14 +34,6 @@ u64 msm_vidc_calc_freq_iris2(struct msm_vidc_inst *inst, u32 data_size) 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; - } - mbpf = msm_vidc_get_mbs_per_frame(inst); fps = msm_vidc_get_fps(inst); @@ -56,7 +47,17 @@ u64 msm_vidc_calc_freq_iris2(struct msm_vidc_inst *inst, u32 data_size) fps = buf_timetamps_fps; inst->priority_level = MSM_VIDC_PRIORITY_LOW; } - + if (!is_realtime_session(inst)) { + input_rate = msm_vidc_get_input_rate(inst); + if (input_rate > fps) { + fps = input_rate; + /* + * add 12.5% more fps to increase power to make firmware + * processing little faster than client queuing rate + */ + fps = fps + fps / 8; + } + } mbs_per_second = mbpf * fps; /* diff --git a/driver/variant/iris3/src/msm_vidc_power_iris3.c b/driver/variant/iris3/src/msm_vidc_power_iris3.c index a64d67c344..7659d9f712 100644 --- a/driver/variant/iris3/src/msm_vidc_power_iris3.c +++ b/driver/variant/iris3/src/msm_vidc_power_iris3.c @@ -22,8 +22,7 @@ u64 msm_vidc_calc_freq_iris3(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; - u32 buf_timetamps_fps, mbpf; + u32 buf_timetamps_fps, mbpf, input_rate; if (!inst || !inst->core || !inst->capabilities) { d_vpr_e("%s: invalid params\n", __func__); @@ -36,14 +35,6 @@ u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size) 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; - } - mbpf = msm_vidc_get_mbs_per_frame(inst); fps = msm_vidc_get_fps(inst); @@ -57,7 +48,17 @@ u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size) fps = buf_timetamps_fps; inst->priority_level = MSM_VIDC_PRIORITY_LOW; } - + if (!is_realtime_session(inst)) { + input_rate = msm_vidc_get_input_rate(inst); + if (input_rate > fps) { + fps = input_rate; + /* + * add 12.5% more fps to increase power to make firmware + * processing little faster than client queuing rate + */ + fps = fps + fps / 8; + } + } mbs_per_second = mbpf * fps; /* diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index 698e6e08c1..0a5529b90d 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/driver/vidc/inc/msm_vidc_driver.h @@ -452,5 +452,7 @@ bool res_is_less_than_or_equal_to(u32 width, u32 height, int msm_vidc_get_properties(struct msm_vidc_inst *inst); int msm_vidc_create_input_metadata_buffer(struct msm_vidc_inst *inst, u32 buf_fd); int msm_vidc_update_input_meta_buffer_index(struct msm_vidc_inst *inst, struct vb2_buffer *vb2); +int msm_vidc_update_input_rate(struct msm_vidc_inst *inst, u64 time_us); +int msm_vidc_get_input_rate(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 4a18c9cad0..130cc4a3af 100644 --- a/driver/vidc/inc/msm_vidc_inst.h +++ b/driver/vidc/inc/msm_vidc_inst.h @@ -142,6 +142,7 @@ struct msm_vidc_inst { struct list_head response_works; /* list of struct response_work */ struct list_head enc_input_crs; struct list_head dmabuf_tracker; /* list of struct msm_memory_dmabuf */ + struct list_head input_timer_list; /* list of struct msm_vidc_input_timer */ struct list_head caps_list; struct list_head children_list; /* struct msm_vidc_inst_cap_entry */ struct list_head firmware_list; /* struct msm_vidc_inst_cap_entry */ diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index 4999e8d306..dc6e4b0a84 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -66,6 +66,7 @@ #define DCVS_WINDOW 16 #define ENC_FPS_WINDOW 3 #define DEC_FPS_WINDOW 10 +#define INPUT_TIMER_LIST_SIZE 30 #define INPUT_MPLANE V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE #define OUTPUT_MPLANE V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE @@ -368,6 +369,7 @@ enum msm_vidc_inst_capability_type { POWER_SAVE_MBPS, FRAME_RATE, OPERATING_RATE, + INPUT_RATE, SCALE_FACTOR, MB_CYCLES_VSP, MB_CYCLES_VPP, @@ -893,6 +895,11 @@ struct msm_vidc_timestamps { u64 rank; }; +struct msm_vidc_input_timer { + struct list_head list; + u64 time_us; +}; + enum msm_vidc_allow { MSM_VIDC_DISALLOW = 0, MSM_VIDC_ALLOW, diff --git a/driver/vidc/inc/msm_vidc_memory.h b/driver/vidc/inc/msm_vidc_memory.h index 69c4acf3c8..88bd991638 100644 --- a/driver/vidc/inc/msm_vidc_memory.h +++ b/driver/vidc/inc/msm_vidc_memory.h @@ -26,6 +26,7 @@ enum msm_memory_pool_type { MSM_MEM_POOL_TIMESTAMP, MSM_MEM_POOL_DMABUF, MSM_MEM_POOL_PACKET, + MSM_MEM_POOL_BUF_TIMER, MSM_MEM_POOL_MAX, }; diff --git a/driver/vidc/src/msm_vidc.c b/driver/vidc/src/msm_vidc.c index b2a6441c58..9ef8a57755 100644 --- a/driver/vidc/src/msm_vidc.c +++ b/driver/vidc/src/msm_vidc.c @@ -932,6 +932,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) INIT_LIST_HEAD(&inst->firmware_list); INIT_LIST_HEAD(&inst->enc_input_crs); INIT_LIST_HEAD(&inst->dmabuf_tracker); + INIT_LIST_HEAD(&inst->input_timer_list); INIT_LIST_HEAD(&inst->pending_pkts); INIT_LIST_HEAD(&inst->fence_list); for (i = 0; i < MAX_SIGNAL; i++) diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index 1f606f2b7f..ac8df4548b 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -75,6 +75,7 @@ static const struct msm_vidc_cap_name cap_name_arr[] = { {POWER_SAVE_MBPS, "POWER_SAVE_MBPS" }, {FRAME_RATE, "FRAME_RATE" }, {OPERATING_RATE, "OPERATING_RATE" }, + {INPUT_RATE, "INPUT_RATE" }, {SCALE_FACTOR, "SCALE_FACTOR" }, {MB_CYCLES_VSP, "MB_CYCLES_VSP" }, {MB_CYCLES_VPP, "MB_CYCLES_VPP" }, @@ -2352,6 +2353,59 @@ int msm_vidc_calc_window_avg_framerate(struct msm_vidc_inst *inst) return ts_ms ? (1000 * counter) / ts_ms : 0; } +int msm_vidc_update_input_rate(struct msm_vidc_inst *inst, u64 time_us) +{ + struct msm_vidc_input_timer *input_timer; + struct msm_vidc_input_timer *prev_timer = NULL; + u64 counter = 0; + u64 input_timer_sum_us = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + input_timer = msm_memory_pool_alloc(inst, MSM_MEM_POOL_BUF_TIMER); + if (!input_timer) + return -ENOMEM; + + input_timer->time_us = time_us; + INIT_LIST_HEAD(&input_timer->list); + list_add_tail(&input_timer->list, &inst->input_timer_list); + list_for_each_entry(input_timer, &inst->input_timer_list, list) { + if (prev_timer) { + input_timer_sum_us += input_timer->time_us - prev_timer->time_us; + counter++; + } + prev_timer = input_timer; + } + + if (input_timer_sum_us) + inst->capabilities->cap[INPUT_RATE].value = + (s32)(DIV64_U64_ROUND_CLOSEST(counter * 1000000, + input_timer_sum_us) << 16); + + /* delete the first entry once counter >= INPUT_TIMER_LIST_SIZE */ + if (counter >= INPUT_TIMER_LIST_SIZE) { + input_timer = list_first_entry(&inst->input_timer_list, + struct msm_vidc_input_timer, list); + list_del_init(&input_timer->list); + msm_memory_pool_free(inst, input_timer); + } + + return 0; +} + +int msm_vidc_get_input_rate(struct msm_vidc_inst *inst) +{ + if (!inst || !inst->capabilities) { + d_vpr_e("%s: Invalid params\n", __func__); + return 0; + } + + return inst->capabilities->cap[INPUT_RATE].value >> 16; +} + static int msm_vidc_insert_sort(struct list_head *head, struct msm_vidc_sort *entry) { @@ -6359,4 +6413,4 @@ int msm_vidc_update_input_meta_buffer_index(struct msm_vidc_inst *inst, rc = -EINVAL; } return rc; -} +} \ No newline at end of file diff --git a/driver/vidc/src/msm_vidc_memory.c b/driver/vidc/src/msm_vidc_memory.c index 8c5ab53a01..1314d3208c 100644 --- a/driver/vidc/src/msm_vidc_memory.c +++ b/driver/vidc/src/msm_vidc_memory.c @@ -592,6 +592,7 @@ static const struct msm_vidc_type_size_name buftype_size_name_arr[] = { {MSM_MEM_POOL_DMABUF, sizeof(struct msm_memory_dmabuf), "MSM_MEM_POOL_DMABUF" }, {MSM_MEM_POOL_PACKET, sizeof(struct hfi_pending_packet) + MSM_MEM_POOL_PACKET_SIZE, "MSM_MEM_POOL_PACKET"}, + {MSM_MEM_POOL_BUF_TIMER, sizeof(struct msm_vidc_input_timer), "MSM_MEM_POOL_BUF_TIMER" }, }; int msm_memory_pools_init(struct msm_vidc_inst *inst) diff --git a/driver/vidc/src/msm_vidc_power.c b/driver/vidc/src/msm_vidc_power.c index 2eb0010375..7b0b118f31 100644 --- a/driver/vidc/src/msm_vidc_power.c +++ b/driver/vidc/src/msm_vidc_power.c @@ -133,12 +133,7 @@ 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(); @@ -154,11 +149,6 @@ static int msm_vidc_set_buses(struct msm_vidc_inst* inst) break; } - if (!is_realtime_session(inst)) { - temp->power.ddr_bw = core->platform->data.bus_bw_nrt[0]; - temp->power.sys_cache_bw = core->platform->data.bus_bw_nrt[0]; - } - total_bw_ddr += temp->power.ddr_bw; total_bw_llcc += temp->power.sys_cache_bw; } @@ -188,7 +178,7 @@ int msm_vidc_scale_buses(struct msm_vidc_inst *inst) struct vidc_bus_vote_data *vote_data; struct v4l2_format *out_f; struct v4l2_format *inp_f; - int codec = 0, frame_rate, buf_ts_fps; + int codec = 0, frame_rate, buf_ts_fps, input_rate; if (!inst || !inst->core || !inst->capabilities) { d_vpr_e("%s: invalid params: %pK\n", __func__, inst); @@ -238,7 +228,19 @@ int msm_vidc_scale_buses(struct msm_vidc_inst *inst) buf_ts_fps, vote_data->fps); vote_data->fps = buf_ts_fps; } - + if (!is_realtime_session(inst)) { + input_rate = msm_vidc_get_input_rate(inst); + if (input_rate > vote_data->fps) { + i_vpr_h(inst, "%s: use input rate %d for fps (%u)\n", __func__, + input_rate, vote_data->fps); + vote_data->fps = input_rate; + /* + * add 12.5% more fps to increase power to make firmware + * processing little faster than client queuing rate + */ + vote_data->fps = vote_data->fps + vote_data->fps / 8; + } + } if (inst->domain == MSM_VIDC_ENCODER) { vote_data->domain = MSM_VIDC_ENCODER; vote_data->bitrate = inst->capabilities->cap[BIT_RATE].value; diff --git a/driver/vidc/src/msm_vidc_vb2.c b/driver/vidc/src/msm_vidc_vb2.c index 7b9d823376..42c28556ba 100644 --- a/driver/vidc/src/msm_vidc_vb2.c +++ b/driver/vidc/src/msm_vidc_vb2.c @@ -378,6 +378,7 @@ void msm_vidc_buf_queue(struct vb2_buffer *vb2) int rc = 0; struct msm_vidc_inst *inst; u64 timestamp_us = 0; + u64 ktime_ns = ktime_get_ns(); inst = vb2_get_drv_priv(vb2->vb2_queue); if (!inst) { @@ -410,7 +411,14 @@ void msm_vidc_buf_queue(struct vb2_buffer *vb2) timestamp_us = div_u64(vb2->timestamp, 1000); msm_vidc_set_auto_framerate(inst, timestamp_us); } - inst->last_qbuf_time_ns = ktime_get_ns(); + inst->last_qbuf_time_ns = ktime_ns; + + if (!is_realtime_session(inst) && vb2->type == INPUT_MPLANE) { + rc = msm_vidc_update_input_rate(inst, div_u64(ktime_ns, 1000)); + if (rc) + goto unlock; + } + /* * As part of every qbuf initalise request to true. * If there are any dynamic controls associated with qbuf,