diff --git a/msm/dp/dp_ctrl.c b/msm/dp/dp_ctrl.c index 2c6b6a1c7d..7a53e7923d 100644 --- a/msm/dp/dp_ctrl.c +++ b/msm/dp/dp_ctrl.c @@ -647,6 +647,9 @@ static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl, u32 num = ctrl->parser->mp[clk_type].num_clk; struct dss_clk *cfg = ctrl->parser->mp[clk_type].clk_config; + /* convert to HZ for byte2 ops */ + rate *= ctrl->pll->clk_factor; + while (num && strcmp(cfg->clk_name, name)) { num--; cfg++; diff --git a/msm/dp/dp_pll.h b/msm/dp/dp_pll.h index bd4006688d..529670569a 100644 --- a/msm/dp/dp_pll.h +++ b/msm/dp/dp_pll.h @@ -95,6 +95,7 @@ struct dp_pll { struct dp_pll_io io; struct clk_onecell_data *clk_data; u32 dp_core_revision; + u32 clk_factor; int (*pll_cfg)(struct dp_pll *pll, unsigned long rate); int (*pll_prepare)(struct dp_pll *pll); diff --git a/msm/dp/dp_pll_4nm.c b/msm/dp/dp_pll_4nm.c index 46f15102ee..0785df72ac 100644 --- a/msm/dp/dp_pll_4nm.c +++ b/msm/dp/dp_pll_4nm.c @@ -737,8 +737,7 @@ static unsigned long dp_pll_link_clk_recalc_rate(struct clk_hw *hw, pll_link = to_dp_vco_hw(hw); pll = pll_link->priv; - rate = pll->vco_rate; - rate = pll->vco_rate / 10; + rate = pll->vco_rate * pll->clk_factor / 10; return rate; } @@ -757,7 +756,7 @@ static long dp_pll_link_clk_round(struct clk_hw *hw, unsigned long rate, pll_link = to_dp_vco_hw(hw); pll = pll_link->priv; - rate = pll->vco_rate / 10; + rate = pll->vco_rate * pll->clk_factor / 10; return rate; } @@ -765,11 +764,11 @@ static long dp_pll_link_clk_round(struct clk_hw *hw, unsigned long rate, static unsigned long dp_pll_vco_div_clk_get_rate(struct dp_pll *pll) { if (pll->vco_rate == DP_VCO_HSCLK_RATE_8100MHZDIV1000) - return (pll->vco_rate / 6); + return (pll->vco_rate / (6 * pll->clk_factor)); else if (pll->vco_rate == DP_VCO_HSCLK_RATE_5400MHZDIV1000) - return (pll->vco_rate / 4); + return (pll->vco_rate / (4 * pll->clk_factor)); else - return (pll->vco_rate / 2); + return (pll->vco_rate / (2 * pll->clk_factor)); } static unsigned long dp_pll_vco_div_clk_recalc_rate(struct clk_hw *hw, diff --git a/msm/dp/dp_pll_5nm.c b/msm/dp/dp_pll_5nm.c index 0af078d8e9..9ddd9ae35d 100644 --- a/msm/dp/dp_pll_5nm.c +++ b/msm/dp/dp_pll_5nm.c @@ -719,8 +719,7 @@ static unsigned long dp_pll_link_clk_recalc_rate(struct clk_hw *hw, pll_link = to_dp_vco_hw(hw); pll = pll_link->priv; - rate = pll->vco_rate; - rate = pll->vco_rate / 10; + rate = pll->vco_rate * pll->clk_factor / 10; return rate; } @@ -739,7 +738,7 @@ static long dp_pll_link_clk_round(struct clk_hw *hw, unsigned long rate, pll_link = to_dp_vco_hw(hw); pll = pll_link->priv; - rate = pll->vco_rate / 10; + rate = pll->vco_rate * pll->clk_factor / 10; return rate; } @@ -747,11 +746,11 @@ static long dp_pll_link_clk_round(struct clk_hw *hw, unsigned long rate, static unsigned long dp_pll_vco_div_clk_get_rate(struct dp_pll *pll) { if (pll->vco_rate == DP_VCO_HSCLK_RATE_8100MHZDIV1000) - return (pll->vco_rate / 6); + return (pll->vco_rate / (6 * pll->clk_factor)); else if (pll->vco_rate == DP_VCO_HSCLK_RATE_5400MHZDIV1000) - return (pll->vco_rate / 4); + return (pll->vco_rate / (4 * pll->clk_factor)); else - return (pll->vco_rate / 2); + return (pll->vco_rate / (2 * pll->clk_factor)); } static unsigned long dp_pll_vco_div_clk_recalc_rate(struct clk_hw *hw, diff --git a/msm/dp/dp_power.c b/msm/dp/dp_power.c index de8ba05b2f..0ae2cf5097 100644 --- a/msm/dp/dp_power.c +++ b/msm/dp/dp_power.c @@ -22,6 +22,8 @@ struct dp_power_private { struct clk *pixel_parent; struct clk *pixel1_clk_rcg; struct clk *xo_clk; + struct clk *link_clk_rcg; + struct clk *link_parent; struct dp_power dp_power; @@ -245,6 +247,25 @@ static int dp_power_clk_init(struct dp_power_private *power, bool enable) goto err_pixel1_clk_rcg; } } + + power->link_clk_rcg = clk_get(dev, "link_clk_src"); + if (IS_ERR(power->link_clk_rcg)) { + DP_ERR("Unable to get DP link clk RCG: %ld\n", + PTR_ERR(power->link_clk_rcg)); + rc = PTR_ERR(power->link_clk_rcg); + power->link_clk_rcg = NULL; + goto err_link_clk_rcg; + } + + /* If link_parent node is available, convert clk rates to HZ for byte2 ops */ + power->pll->clk_factor = 1000; + power->link_parent = clk_get(dev, "link_parent"); + if (IS_ERR(power->link_parent)) { + DP_WARN("Unable to get DP link parent: %ld\n", + PTR_ERR(power->link_parent)); + power->link_parent = NULL; + power->pll->clk_factor = 1; + } } else { if (power->pixel1_clk_rcg) clk_put(power->pixel1_clk_rcg); @@ -255,10 +276,19 @@ static int dp_power_clk_init(struct dp_power_private *power, bool enable) if (power->pixel_clk_rcg) clk_put(power->pixel_clk_rcg); + if (power->link_parent) + clk_put(power->link_parent); + + if (power->link_clk_rcg) + clk_put(power->link_clk_rcg); + dp_power_clk_put(power); } return rc; +err_link_clk_rcg: + if (power->pixel1_clk_rcg) + clk_put(power->pixel1_clk_rcg); err_pixel1_clk_rcg: clk_put(power->xo_clk); err_xo_clk: @@ -363,6 +393,29 @@ exit: return rc; } +static bool dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type) +{ + struct dp_power_private *power; + + if (!dp_power) { + DP_ERR("invalid power data\n"); + return false; + } + + power = container_of(dp_power, struct dp_power_private, dp_power); + + if (pm_type == DP_LINK_PM) + return power->link_clks_on; + else if (pm_type == DP_CORE_PM) + return power->core_clks_on; + else if (pm_type == DP_STREAM0_PM) + return power->strm0_clks_on; + else if (pm_type == DP_STREAM1_PM) + return power->strm1_clks_on; + else + return false; +} + static int dp_power_clk_enable(struct dp_power *dp_power, enum dp_pm_type pm_type, bool enable) { @@ -387,18 +440,8 @@ static int dp_power_clk_enable(struct dp_power *dp_power, } if (enable) { - if (pm_type == DP_CORE_PM && power->core_clks_on) { - DP_DEBUG("core clks already enabled\n"); - return 0; - } - - if ((pm_type == DP_STREAM0_PM) && (power->strm0_clks_on)) { - DP_DEBUG("strm0 clks already enabled\n"); - return 0; - } - - if ((pm_type == DP_STREAM1_PM) && (power->strm1_clks_on)) { - DP_DEBUG("strm1 clks already enabled\n"); + if (dp_power_clk_status(dp_power, pm_type)) { + DP_DEBUG("%s clks already enabled\n", dp_parser_pm_name(pm_type)); return 0; } @@ -415,9 +458,12 @@ static int dp_power_clk_enable(struct dp_power *dp_power, } } - if (pm_type == DP_LINK_PM && power->link_clks_on) { - DP_DEBUG("links clks already enabled\n"); - return 0; + if (pm_type == DP_LINK_PM && power->link_parent) { + rc = clk_set_parent(power->link_clk_rcg, power->link_parent); + if (rc) { + DP_ERR("failed to set link parent\n"); + goto error; + } } } @@ -458,29 +504,6 @@ error: return rc; } -static bool dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type) -{ - struct dp_power_private *power; - - if (!dp_power) { - DP_ERR("invalid power data\n"); - return false; - } - - power = container_of(dp_power, struct dp_power_private, dp_power); - - if (pm_type == DP_LINK_PM) - return power->link_clks_on; - else if (pm_type == DP_CORE_PM) - return power->core_clks_on; - else if (pm_type == DP_STREAM0_PM) - return power->strm0_clks_on; - else if (pm_type == DP_STREAM1_PM) - return power->strm1_clks_on; - else - return false; -} - static int dp_power_request_gpios(struct dp_power_private *power) { int rc = 0, i;