In the case of HDMI clocks, we want to bypass the RCG's ability to divide the output clock and pass through the parent HDMI PLL rate through. Add a simple set of clk_ops to configure the RCG to do this. This removes the need to keep adding more frequency entries to the tv_src clock whenever we want to support a new rate. Signed-off-by: Stephen Boyd <sboyd@xxxxxxxxxxxxxx> --- On 07/11, Rob Clark wrote: > It would probably be better to get rid of the fixed table, which > duplicates the set of fixed frequences in the hdmi pll clk (in > drm/msm/hdmi). But I'll leave that as an exercise for someone > who knows the clk driver better than myself. Until then, this > trivial fix is useful. Here's a quick attempt at that. Let me know if this works. drivers/clk/qcom/clk-rcg.c | 51 +++++++++++++++++++++++++++++++++++------ drivers/clk/qcom/clk-rcg.h | 1 + drivers/clk/qcom/mmcc-msm8960.c | 9 ++------ 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c index abfc2b675aea..b638c5846dbf 100644 --- a/drivers/clk/qcom/clk-rcg.c +++ b/drivers/clk/qcom/clk-rcg.c @@ -417,20 +417,25 @@ static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p); } -static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) +static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *p_rate, struct clk **p) { struct clk_rcg *rcg = to_clk_rcg(hw); - const struct freq_tbl *f; + const struct freq_tbl *f = rcg->freq_tbl; + + *p = clk_get_parent_by_index(hw->clk, f->src); + *p_rate = __clk_round_rate(*p, rate); + + return *p_rate; +} + +static int __clk_rcg_set_rate(struct clk_rcg *rcg, const struct freq_tbl *f) +{ u32 ns, md, ctl; struct mn *mn = &rcg->mn; u32 mask = 0; unsigned int reset_reg; - f = find_freq(rcg->freq_tbl, rate); - if (!f) - return -EINVAL; - if (rcg->mn.reset_in_cc) reset_reg = rcg->clkr.enable_reg; else @@ -466,6 +471,27 @@ static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate, return 0; } +static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_rcg *rcg = to_clk_rcg(hw); + const struct freq_tbl *f; + + f = find_freq(rcg->freq_tbl, rate); + if (!f) + return -EINVAL; + + return __clk_rcg_set_rate(rcg, f); +} + +static int clk_rcg_bypass_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_rcg *rcg = to_clk_rcg(hw); + + return __clk_rcg_set_rate(rcg, rcg->freq_tbl); +} + static int __clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate) { struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); @@ -503,6 +529,17 @@ const struct clk_ops clk_rcg_ops = { }; EXPORT_SYMBOL_GPL(clk_rcg_ops); +const struct clk_ops clk_rcg_bypass_ops = { + .enable = clk_enable_regmap, + .disable = clk_disable_regmap, + .get_parent = clk_rcg_get_parent, + .set_parent = clk_rcg_set_parent, + .recalc_rate = clk_rcg_recalc_rate, + .determine_rate = clk_rcg_bypass_determine_rate, + .set_rate = clk_rcg_bypass_set_rate, +}; +EXPORT_SYMBOL_GPL(clk_rcg_bypass_ops); + const struct clk_ops clk_dyn_rcg_ops = { .enable = clk_enable_regmap, .is_enabled = clk_is_enabled_regmap, diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index b9ec11dfd1b4..ba0523cefd2e 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -95,6 +95,7 @@ struct clk_rcg { }; extern const struct clk_ops clk_rcg_ops; +extern const struct clk_ops clk_rcg_bypass_ops; #define to_clk_rcg(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg, clkr) diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c index 12f3c0b64fcd..14eeeba005f3 100644 --- a/drivers/clk/qcom/mmcc-msm8960.c +++ b/drivers/clk/qcom/mmcc-msm8960.c @@ -1218,12 +1218,7 @@ static const char *mmcc_pxo_hdmi[] = { }; static struct freq_tbl clk_tbl_tv[] = { - { 25200000, P_HDMI_PLL, 1, 0, 0 }, - { 27000000, P_HDMI_PLL, 1, 0, 0 }, - { 27030000, P_HDMI_PLL, 1, 0, 0 }, - { 74250000, P_HDMI_PLL, 1, 0, 0 }, - { 108000000, P_HDMI_PLL, 1, 0, 0 }, - { 148500000, P_HDMI_PLL, 1, 0, 0 }, + { .src = P_HDMI_PLL, .pre_div = 1 }, { } }; @@ -1254,7 +1249,7 @@ static struct clk_rcg tv_src = { .name = "tv_src", .parent_names = mmcc_pxo_hdmi, .num_parents = 2, - .ops = &clk_rcg_ops, + .ops = &clk_rcg_bypass_ops, .flags = CLK_SET_RATE_PARENT, }, }, -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html