summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/qcom/mdss/mdss-dp-pll-14nm-util.c1
-rw-r--r--drivers/clk/qcom/mdss/mdss-dp-pll-14nm.c47
2 files changed, 47 insertions, 1 deletions
diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll-14nm-util.c b/drivers/clk/qcom/mdss/mdss-dp-pll-14nm-util.c
index 0965d5590a28..f0d4e1ff52be 100644
--- a/drivers/clk/qcom/mdss/mdss-dp-pll-14nm-util.c
+++ b/drivers/clk/qcom/mdss/mdss-dp-pll-14nm-util.c
@@ -600,6 +600,7 @@ unsigned long dp_vco_recalc_rate_14nm(struct clk_hw *hw,
mdss_pll_resource_enable(dp_res, false);
+ dp_res->vco_cached_rate = vco->rate = vco_rate;
return (unsigned long)vco_rate;
}
diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.c b/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.c
index ffe8286cfaaa..d74584850259 100644
--- a/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.c
+++ b/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.c
@@ -62,6 +62,7 @@ v----------+----------v | divsel_two | | divsel_four |
#include "mdss-dp-pll-14nm.h"
static struct dp_pll_db dp_pdb;
+static struct clk_ops mux_clk_ops;
static struct regmap_config dp_pll_14nm_cfg = {
.reg_bits = 32,
@@ -137,6 +138,47 @@ static struct clk_fixed_factor dp_vco_divsel_four_clk_src = {
},
};
+static int clk_mux_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ int ret = 0;
+
+ ret = __clk_mux_determine_rate_closest(hw, req);
+ if (ret)
+ return ret;
+
+ /* Set the new parent of mux if there is a new valid parent */
+ if (hw->clk && req->best_parent_hw->clk)
+ clk_set_parent(hw->clk, req->best_parent_hw->clk);
+
+ return 0;
+}
+
+
+static unsigned long mux_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk *div_clk = NULL, *vco_clk = NULL;
+ struct dp_pll_vco_clk *vco = NULL;
+
+ div_clk = clk_get_parent(hw->clk);
+ if (!div_clk)
+ return 0;
+
+ vco_clk = clk_get_parent(div_clk);
+ if (!vco_clk)
+ return 0;
+
+ vco = to_dp_vco_hw(__clk_get_hw(vco_clk));
+ if (!vco)
+ return 0;
+
+ if (vco->rate == DP_VCO_HSCLK_RATE_5400MHZDIV1000)
+ return (vco->rate / 4);
+ else
+ return (vco->rate / 2);
+}
+
static struct clk_regmap_mux dp_vco_divided_clk_src_mux = {
.reg = 0x64,
.shift = 0,
@@ -149,7 +191,7 @@ static struct clk_regmap_mux dp_vco_divided_clk_src_mux = {
(const char *[]){"dp_vco_divsel_two_clk_src",
"dp_vco_divsel_four_clk_src"},
.num_parents = 2,
- .ops = &clk_regmap_mux_closest_ops,
+ .ops = &mux_clk_ops,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
},
},
@@ -202,6 +244,9 @@ int dp_pll_clock_register_14nm(struct platform_device *pdev,
regmap = devm_regmap_init(&pdev->dev, &dp_pixel_mux_regmap_ops,
pll_res, &dp_pll_14nm_cfg);
dp_vco_divided_clk_src_mux.clkr.regmap = regmap;
+ mux_clk_ops = clk_regmap_mux_closest_ops;
+ mux_clk_ops.determine_rate = clk_mux_determine_rate;
+ mux_clk_ops.recalc_rate = mux_recalc_rate;
dp_vco_clk.priv = pll_res;