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 <shubgupt@codeaurora.org>
Signed-off-by: Manikanta Kanamarlapudi <kmanikan@codeaurora.org>
This commit is contained in:
Manikanta Kanamarlapudi 2019-05-08 17:11:02 +05:30 • committed by Gerrit - the friendly Code Review server
commit 16e94fc70e
3 changed files with 110 additions and 9 deletions

View file

@ -20,6 +20,7 @@
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/soc/qcom/llcc-qcom.h>
#include <soc/qcom/cx_ipeak.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/socinfo.h>
#include <linux/soc/qcom/smem.h>
@ -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) {

View file

@ -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);

View file

@ -9,6 +9,7 @@
#include <linux/platform_device.h>
#include "msm_vidc.h"
#include <linux/soc/qcom/llcc-qcom.h>
#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)