From 16e94fc70e2594e886b7d84eaeb8d86b147e4cf3 Mon Sep 17 00:00:00 2001 From: Manikanta Kanamarlapudi Date: Wed, 8 May 2019 17:11:02 +0530 Subject: [PATCH] msm_vidc: Add support for Cx ipeak limitation Make a vote call whenever the clock frequency driver computes crosses a threshold mark. This vote call handles the situation when many subsystems are in turbo and where a need arises to throttle the CDSP current. CRs-Fixed: 2330072 Change-Id: Id10c02749b00fd5a1b1980923c5034648bd35985 Signed-off-by: shubham gupta Signed-off-by: Manikanta Kanamarlapudi --- msm/vidc/hfi_common.c | 57 ++++++++++++++++++++++++++++----- msm/vidc/msm_vidc_res_parse.c | 59 ++++++++++++++++++++++++++++++++++- msm/vidc/msm_vidc_resources.h | 3 ++ 3 files changed, 110 insertions(+), 9 deletions(-) diff --git a/msm/vidc/hfi_common.c b/msm/vidc/hfi_common.c index 32bd91c9503f..a7945cc563de 100644 --- a/msm/vidc/hfi_common.c +++ b/msm/vidc/hfi_common.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1263,6 +1264,51 @@ static enum hal_default_properties venus_hfi_get_default_properties(void *dev) return prop; } +static int __set_clk_rate(struct venus_hfi_device *device, + struct clock_info *cl, u64 rate) +{ + int rc = 0; + u64 threshold_freq = device->res->clk_freq_threshold; + struct cx_ipeak_client *ipeak = device->res->cx_ipeak_context; + struct clk *clk = cl->clk; + + if (ipeak && device->clk_freq < threshold_freq && rate >= threshold_freq) { + rc = cx_ipeak_update(ipeak, true); + if (rc) { + dprintk(VIDC_ERR, + "%s: cx_ipeak_update failed!\n", __func__); + return rc; + } + dprintk(VIDC_PROF, + "cx_ipeak_update: up, clk freq = %lu rate = %lu threshold_freq = %lu\n", + device->clk_freq, rate, threshold_freq); + } + + rc = clk_set_rate(clk, rate); + if (rc) { + dprintk(VIDC_ERR, + "%s: Failed to set clock rate %llu %s: %d\n", + __func__, rate, cl->name, rc); + return rc; + } + + device->clk_freq = rate; + + if (device->clk_freq >= threshold_freq && rate < threshold_freq) { + rc = cx_ipeak_update(ipeak, false); + if (rc) { + dprintk(VIDC_ERR, + "cx_ipeak_update failed! ipeak %pK\n", ipeak); + return rc; + } + dprintk(VIDC_PROF, + "cx_ipeak_update: up, clk freq = %lu rate = %lu threshold_freq = %lu\n", + device->clk_freq, rate, threshold_freq); + } + + return rc; +} + static int __set_clocks(struct venus_hfi_device *device, u32 freq) { struct clock_info *cl; @@ -1270,14 +1316,9 @@ static int __set_clocks(struct venus_hfi_device *device, u32 freq) venus_hfi_for_each_clock(device, cl) { if (cl->has_scaling) {/* has_scaling */ - device->clk_freq = freq; - rc = clk_set_rate(cl->clk, freq); - if (rc) { - dprintk(VIDC_ERR, - "Failed to set clock rate %u %s: %d %s\n", - freq, cl->name, rc, __func__); + rc = __set_clk_rate(device, cl, freq); + if (rc) return rc; - } trace_msm_vidc_perf_clock_scale(cl->name, freq); dprintk(VIDC_PROF, "Scaling clock %s to %u\n", @@ -3776,7 +3817,7 @@ static inline int __prepare_enable_clks(struct venus_hfi_device *device) * it to the lowest frequency possible */ if (cl->has_scaling) - clk_set_rate(cl->clk, clk_round_rate(cl->clk, 0)); + __set_clk_rate(device, cl, clk_round_rate(cl->clk, 0)); rc = clk_set_flags(cl->clk, CLKFLAG_RETAIN_PERIPH); if (rc) { diff --git a/msm/vidc/msm_vidc_res_parse.c b/msm/vidc/msm_vidc_res_parse.c index de1d60a124b7..b1e46a5db018 100644 --- a/msm/vidc/msm_vidc_res_parse.c +++ b/msm/vidc/msm_vidc_res_parse.c @@ -111,6 +111,13 @@ static inline void msm_vidc_free_clock_table( res->clock_set.count = 0; } +static inline void msm_vidc_free_cx_ipeak_context( + struct msm_vidc_platform_resources *res) +{ + cx_ipeak_unregister(res->cx_ipeak_context); + res->cx_ipeak_context = NULL; +} + void msm_vidc_free_platform_resources( struct msm_vidc_platform_resources *res) { @@ -121,6 +128,7 @@ void msm_vidc_free_platform_resources( msm_vidc_free_qdss_addr_table(res); msm_vidc_free_bus_vectors(res); msm_vidc_free_buffer_usage_table(res); + msm_vidc_free_cx_ipeak_context(res); } static int msm_vidc_load_reg_table(struct msm_vidc_platform_resources *res) @@ -832,6 +840,46 @@ int read_platform_resources_from_drv_data( } +static int msm_vidc_populate_cx_ipeak_context( + struct msm_vidc_platform_resources *res) +{ + struct platform_device *pdev = res->pdev; + int rc = 0; + + if (of_find_property(pdev->dev.of_node, + "qcom,cx-ipeak-data", NULL)) + res->cx_ipeak_context = cx_ipeak_register( + pdev->dev.of_node, "qcom,cx-ipeak-data"); + else + return rc; + + if (IS_ERR(res->cx_ipeak_context)) { + rc = PTR_ERR(res->cx_ipeak_context); + if (rc == -EPROBE_DEFER) + dprintk(VIDC_INFO, + "cx-ipeak register failed. Deferring probe!"); + else + dprintk(VIDC_ERR, + "cx-ipeak register failed. rc: %d", rc); + + res->cx_ipeak_context = NULL; + return rc; + } + + if (res->cx_ipeak_context) + dprintk(VIDC_INFO, "cx-ipeak register successful"); + else + dprintk(VIDC_INFO, "cx-ipeak register not implemented"); + + of_property_read_u32(pdev->dev.of_node, + "qcom,clock-freq-threshold", + &res->clk_freq_threshold); + dprintk(VIDC_DBG, "cx ipeak threshold frequency = %u\n", + res->clk_freq_threshold); + + return rc; +} + int read_platform_resources_from_dt( struct msm_vidc_platform_resources *res) { @@ -916,10 +964,19 @@ int read_platform_resources_from_dt( goto err_setup_legacy_cb; } + rc = msm_vidc_populate_cx_ipeak_context(res); + if (rc) { + dprintk(VIDC_ERR, + "Failed to setup cx-ipeak %d\n", rc); + goto err_register_cx_ipeak; + } + return rc; -err_load_reset_table: +err_register_cx_ipeak: + msm_vidc_free_cx_ipeak_context(res); err_setup_legacy_cb: +err_load_reset_table: msm_vidc_free_allowed_clocks_table(res); err_load_allowed_clocks_table: msm_vidc_free_clock_table(res); diff --git a/msm/vidc/msm_vidc_resources.h b/msm/vidc/msm_vidc_resources.h index c6ea445d14f3..59847ea39a6b 100644 --- a/msm/vidc/msm_vidc_resources.h +++ b/msm/vidc/msm_vidc_resources.h @@ -9,6 +9,7 @@ #include #include "msm_vidc.h" #include +#include "soc/qcom/cx_ipeak.h" #define MAX_BUFFER_TYPES 32 @@ -206,6 +207,8 @@ struct msm_vidc_platform_resources { uint32_t fw_cycles; uint32_t fw_vpp_cycles; struct msm_vidc_ubwc_config_data *ubwc_config; + uint32_t clk_freq_threshold; + struct cx_ipeak_client *cx_ipeak_context; }; static inline bool is_iommu_present(struct msm_vidc_platform_resources *res)