diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2017-02-27 23:37:24 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-02-27 23:37:23 -0800 |
commit | 598d0c01b1708c2cb840930f709f258364429c15 (patch) | |
tree | 42c393294e9c09cbacb1e6a5a0f726488a80a9c8 | |
parent | a19f132f6eec8cba607cd3ce17df87b39ba1c79a (diff) | |
parent | 7d740729a1c7e352a174db9dff6a7d6d8401c213 (diff) |
Merge "msm: mdss: add support for Cx iPeak limit management"
-rw-r--r-- | drivers/video/fbdev/msm/mdss.h | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.c | 46 |
2 files changed, 43 insertions, 5 deletions
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index bf4dc39f57ee..d9a4bd91f3eb 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -27,6 +27,7 @@ #include <linux/msm-bus.h> #include <linux/file.h> #include <linux/dma-direction.h> +#include <soc/qcom/cx_ipeak.h> #include "mdss_panel.h" @@ -535,6 +536,7 @@ struct mdss_data_type { u32 sec_cam_en; u32 sec_session_cnt; wait_queue_head_t secure_waitq; + struct cx_ipeak_client *mdss_cx_ipeak; }; extern struct mdss_data_type *mdss_res; diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 21728c5dee45..3cadfa4ecef7 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -1173,6 +1173,31 @@ irqreturn_t mdss_mdp_isr(int irq, void *ptr) return IRQ_HANDLED; } +static void mdss_mdp_cxipeak_vote(bool set_vote, unsigned long new_rate, + unsigned long prev_rate) +{ + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + int ret = 0; + + if (!mdata->mdss_cx_ipeak) + return; + + /* fmax threshold for mdp in sdm660 is max MDP clk */ + if (set_vote) { + if ((new_rate >= mdata->max_mdp_clk_rate) && + (prev_rate < mdata->max_mdp_clk_rate)) + ret = cx_ipeak_update(mdata->mdss_cx_ipeak, true); + } else { + if ((new_rate < mdata->max_mdp_clk_rate) && + (prev_rate >= mdata->max_mdp_clk_rate)) + ret = cx_ipeak_update(mdata->mdss_cx_ipeak, false); + } + if (ret) { + pr_err("cxipeak api fail ret:%d set_vote :%d new_rate:%lu prev_rate:%lu\n", + ret, (int)set_vote, new_rate, prev_rate); + } +} + static int mdss_mdp_clk_update(u32 clk_idx, u32 enable) { int ret = -ENODEV; @@ -1234,7 +1259,7 @@ void mdss_mdp_set_clk_rate(unsigned long rate, bool locked) struct mdss_data_type *mdata = mdss_res; unsigned long clk_rate; struct clk *clk = mdss_mdp_get_clk(MDSS_CLK_MDP_CORE); - unsigned long min_clk_rate; + unsigned long min_clk_rate, curr_clk_rate; min_clk_rate = max(rate, mdata->perf_tune.min_mdp_clk); @@ -1246,15 +1271,20 @@ void mdss_mdp_set_clk_rate(unsigned long rate, bool locked) clk_rate = clk_round_rate(clk, min_clk_rate); else clk_rate = mdata->max_mdp_clk_rate; + + curr_clk_rate = clk_get_rate(clk); if (IS_ERR_VALUE(clk_rate)) { pr_err("unable to round rate err=%ld\n", clk_rate); - } else if (clk_rate != clk_get_rate(clk)) { - + } else if (clk_rate != curr_clk_rate) { + mdss_mdp_cxipeak_vote(true, clk_rate, curr_clk_rate); mdata->mdp_clk_rate = clk_rate; - if (IS_ERR_VALUE(clk_set_rate(clk, clk_rate))) + if (IS_ERR_VALUE(clk_set_rate(clk, clk_rate))) { pr_err("clk_set_rate failed\n"); - else + } else { + mdss_mdp_cxipeak_vote(false, clk_rate, + curr_clk_rate); pr_debug("mdp clk rate=%lu\n", clk_rate); + } } if (!locked) mutex_unlock(&mdp_clk_lock); @@ -4538,6 +4568,10 @@ static int mdss_mdp_parse_dt_misc(struct platform_device *pdev) pr_debug("max pipe width not specified. Using default value\n"); mdata->max_pipe_width = DEFAULT_MDP_PIPE_WIDTH; } + + if (of_find_property(pdev->dev.of_node, "qcom,mdss-cx-ipeak", NULL)) + mdata->mdss_cx_ipeak = cx_ipeak_register(pdev->dev.of_node, + "qcom,mdss-cx-ipeak"); return 0; } @@ -5523,6 +5557,8 @@ static int mdss_mdp_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); mdss_mdp_pp_term(&pdev->dev); mdss_mdp_bus_scale_unregister(mdata); + if (mdata->mdss_cx_ipeak) + cx_ipeak_unregister(mdata->mdss_cx_ipeak); mdss_debugfs_remove(mdata); if (mdata->regulator_notif_register) regulator_unregister_notifier(mdata->fs, &(mdata->gdsc_cb)); |