Commit dccbea3b authored by Imre Deak's avatar Imre Deak Committed by Daniel Vetter

drm/i915: calculate the port clock rate along with other PLL params

Depending on the platform the port clock fed to the pipe can be the PLL's
post-divided fast clock rate or a /5 divided version of it. To make this
more obvious across the platforms calculate this port clock along with
the rest of the PLL parameters.

This is also needed by the next patch where we can reuse the CHV helper
for the BXT PLL HW readout code; so export the corresponding helper.

While at it also add a more descriptive name to the helpers and a
comment explaining what's being calculated.

No functional change.
Suggested-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarImre Deak <imre.deak@intel.com>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 589eca67
...@@ -553,15 +553,25 @@ intel_limit(struct intel_crtc_state *crtc_state, int refclk) ...@@ -553,15 +553,25 @@ intel_limit(struct intel_crtc_state *crtc_state, int refclk)
return limit; return limit;
} }
/*
* Platform specific helpers to calculate the port PLL loopback- (clock.m),
* and post-divider (clock.p) values, pre- (clock.vco) and post-divided fast
* (clock.dot) clock rates. This fast dot clock is fed to the port's IO logic.
* The helpers' return value is the rate of the clock that is fed to the
* display engine's pipe which can be the above fast dot clock rate or a
* divided-down version of it.
*/
/* m1 is reserved as 0 in Pineview, n is a ring counter */ /* m1 is reserved as 0 in Pineview, n is a ring counter */
static void pineview_clock(int refclk, intel_clock_t *clock) static int pnv_calc_dpll_params(int refclk, intel_clock_t *clock)
{ {
clock->m = clock->m2 + 2; clock->m = clock->m2 + 2;
clock->p = clock->p1 * clock->p2; clock->p = clock->p1 * clock->p2;
if (WARN_ON(clock->n == 0 || clock->p == 0)) if (WARN_ON(clock->n == 0 || clock->p == 0))
return; return 0;
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n); clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
return clock->dot;
} }
static uint32_t i9xx_dpll_compute_m(struct dpll *dpll) static uint32_t i9xx_dpll_compute_m(struct dpll *dpll)
...@@ -569,35 +579,41 @@ static uint32_t i9xx_dpll_compute_m(struct dpll *dpll) ...@@ -569,35 +579,41 @@ static uint32_t i9xx_dpll_compute_m(struct dpll *dpll)
return 5 * (dpll->m1 + 2) + (dpll->m2 + 2); return 5 * (dpll->m1 + 2) + (dpll->m2 + 2);
} }
static void i9xx_clock(int refclk, intel_clock_t *clock) static int i9xx_calc_dpll_params(int refclk, intel_clock_t *clock)
{ {
clock->m = i9xx_dpll_compute_m(clock); clock->m = i9xx_dpll_compute_m(clock);
clock->p = clock->p1 * clock->p2; clock->p = clock->p1 * clock->p2;
if (WARN_ON(clock->n + 2 == 0 || clock->p == 0)) if (WARN_ON(clock->n + 2 == 0 || clock->p == 0))
return; return 0;
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2); clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
return clock->dot;
} }
static void vlv_clock(int refclk, intel_clock_t *clock) static int vlv_calc_dpll_params(int refclk, intel_clock_t *clock)
{ {
clock->m = clock->m1 * clock->m2; clock->m = clock->m1 * clock->m2;
clock->p = clock->p1 * clock->p2; clock->p = clock->p1 * clock->p2;
if (WARN_ON(clock->n == 0 || clock->p == 0)) if (WARN_ON(clock->n == 0 || clock->p == 0))
return; return 0;
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n); clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
return clock->dot / 5;
} }
static void chv_clock(int refclk, intel_clock_t *clock) int chv_calc_dpll_params(int refclk, intel_clock_t *clock)
{ {
clock->m = clock->m1 * clock->m2; clock->m = clock->m1 * clock->m2;
clock->p = clock->p1 * clock->p2; clock->p = clock->p1 * clock->p2;
if (WARN_ON(clock->n == 0 || clock->p == 0)) if (WARN_ON(clock->n == 0 || clock->p == 0))
return; return 0;
clock->vco = DIV_ROUND_CLOSEST_ULL((uint64_t)refclk * clock->m, clock->vco = DIV_ROUND_CLOSEST_ULL((uint64_t)refclk * clock->m,
clock->n << 22); clock->n << 22);
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
return clock->dot / 5;
} }
#define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) #define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0)
...@@ -692,7 +708,7 @@ i9xx_find_best_dpll(const intel_limit_t *limit, ...@@ -692,7 +708,7 @@ i9xx_find_best_dpll(const intel_limit_t *limit,
clock.p1 <= limit->p1.max; clock.p1++) { clock.p1 <= limit->p1.max; clock.p1++) {
int this_err; int this_err;
i9xx_clock(refclk, &clock); i9xx_calc_dpll_params(refclk, &clock);
if (!intel_PLL_is_valid(dev, limit, if (!intel_PLL_is_valid(dev, limit,
&clock)) &clock))
continue; continue;
...@@ -737,7 +753,7 @@ pnv_find_best_dpll(const intel_limit_t *limit, ...@@ -737,7 +753,7 @@ pnv_find_best_dpll(const intel_limit_t *limit,
clock.p1 <= limit->p1.max; clock.p1++) { clock.p1 <= limit->p1.max; clock.p1++) {
int this_err; int this_err;
pineview_clock(refclk, &clock); pnv_calc_dpll_params(refclk, &clock);
if (!intel_PLL_is_valid(dev, limit, if (!intel_PLL_is_valid(dev, limit,
&clock)) &clock))
continue; continue;
...@@ -787,7 +803,7 @@ g4x_find_best_dpll(const intel_limit_t *limit, ...@@ -787,7 +803,7 @@ g4x_find_best_dpll(const intel_limit_t *limit,
clock.p1 >= limit->p1.min; clock.p1--) { clock.p1 >= limit->p1.min; clock.p1--) {
int this_err; int this_err;
i9xx_clock(refclk, &clock); i9xx_calc_dpll_params(refclk, &clock);
if (!intel_PLL_is_valid(dev, limit, if (!intel_PLL_is_valid(dev, limit,
&clock)) &clock))
continue; continue;
...@@ -877,7 +893,7 @@ vlv_find_best_dpll(const intel_limit_t *limit, ...@@ -877,7 +893,7 @@ vlv_find_best_dpll(const intel_limit_t *limit,
clock.m2 = DIV_ROUND_CLOSEST(target * clock.p * clock.n, clock.m2 = DIV_ROUND_CLOSEST(target * clock.p * clock.n,
refclk * clock.m1); refclk * clock.m1);
vlv_clock(refclk, &clock); vlv_calc_dpll_params(refclk, &clock);
if (!intel_PLL_is_valid(dev, limit, if (!intel_PLL_is_valid(dev, limit,
&clock)) &clock))
...@@ -940,7 +956,7 @@ chv_find_best_dpll(const intel_limit_t *limit, ...@@ -940,7 +956,7 @@ chv_find_best_dpll(const intel_limit_t *limit,
clock.m2 = m2; clock.m2 = m2;
chv_clock(refclk, &clock); chv_calc_dpll_params(refclk, &clock);
if (!intel_PLL_is_valid(dev, limit, &clock)) if (!intel_PLL_is_valid(dev, limit, &clock))
continue; continue;
...@@ -7925,10 +7941,7 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc, ...@@ -7925,10 +7941,7 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc,
clock.p1 = (mdiv >> DPIO_P1_SHIFT) & 7; clock.p1 = (mdiv >> DPIO_P1_SHIFT) & 7;
clock.p2 = (mdiv >> DPIO_P2_SHIFT) & 0x1f; clock.p2 = (mdiv >> DPIO_P2_SHIFT) & 0x1f;
vlv_clock(refclk, &clock); pipe_config->port_clock = vlv_calc_dpll_params(refclk, &clock);
/* clock.dot is the fast clock */
pipe_config->port_clock = clock.dot / 5;
} }
static void static void
...@@ -8024,10 +8037,7 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc, ...@@ -8024,10 +8037,7 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc,
clock.p1 = (cmn_dw13 >> DPIO_CHV_P1_DIV_SHIFT) & 0x7; clock.p1 = (cmn_dw13 >> DPIO_CHV_P1_DIV_SHIFT) & 0x7;
clock.p2 = (cmn_dw13 >> DPIO_CHV_P2_DIV_SHIFT) & 0x1f; clock.p2 = (cmn_dw13 >> DPIO_CHV_P2_DIV_SHIFT) & 0x1f;
chv_clock(refclk, &clock); pipe_config->port_clock = chv_calc_dpll_params(refclk, &clock);
/* clock.dot is the fast clock */
pipe_config->port_clock = clock.dot / 5;
} }
static bool i9xx_get_pipe_config(struct intel_crtc *crtc, static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
...@@ -10464,6 +10474,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, ...@@ -10464,6 +10474,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
u32 dpll = pipe_config->dpll_hw_state.dpll; u32 dpll = pipe_config->dpll_hw_state.dpll;
u32 fp; u32 fp;
intel_clock_t clock; intel_clock_t clock;
int port_clock;
int refclk = i9xx_pll_refclk(dev, pipe_config); int refclk = i9xx_pll_refclk(dev, pipe_config);
if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
...@@ -10504,9 +10515,9 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, ...@@ -10504,9 +10515,9 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
} }
if (IS_PINEVIEW(dev)) if (IS_PINEVIEW(dev))
pineview_clock(refclk, &clock); port_clock = pnv_calc_dpll_params(refclk, &clock);
else else
i9xx_clock(refclk, &clock); port_clock = i9xx_calc_dpll_params(refclk, &clock);
} else { } else {
u32 lvds = IS_I830(dev) ? 0 : I915_READ(LVDS); u32 lvds = IS_I830(dev) ? 0 : I915_READ(LVDS);
bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN); bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN);
...@@ -10532,7 +10543,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, ...@@ -10532,7 +10543,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
clock.p2 = 2; clock.p2 = 2;
} }
i9xx_clock(refclk, &clock); port_clock = i9xx_calc_dpll_params(refclk, &clock);
} }
/* /*
...@@ -10540,7 +10551,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, ...@@ -10540,7 +10551,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
* port_clock to compute adjusted_mode.crtc_clock in the * port_clock to compute adjusted_mode.crtc_clock in the
* encoder's get_config() function. * encoder's get_config() function.
*/ */
pipe_config->port_clock = clock.dot; pipe_config->port_clock = port_clock;
} }
int intel_dotclock_calculate(int link_freq, int intel_dotclock_calculate(int link_freq,
......
...@@ -1140,6 +1140,8 @@ ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config, ...@@ -1140,6 +1140,8 @@ ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config,
int dotclock); int dotclock);
bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock, bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock,
intel_clock_t *best_clock); intel_clock_t *best_clock);
int chv_calc_dpll_params(int refclk, intel_clock_t *pll_clock);
bool intel_crtc_active(struct drm_crtc *crtc); bool intel_crtc_active(struct drm_crtc *crtc);
void hsw_enable_ips(struct intel_crtc *crtc); void hsw_enable_ips(struct intel_crtc *crtc);
void hsw_disable_ips(struct intel_crtc *crtc); void hsw_disable_ips(struct intel_crtc *crtc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment