Commit d288f65f authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Daniel Vetter

drm/i915: Make sure DPLL is enabled when kicking the power sequencer on VLV/CHV

The power seqeuencer kick procedure requires the DPLL to be running
in order to complete successfully. In case the DPLL isn't currently
running when we need to kick the power seqeuncer enable it
temporarily. This can happen eg. during ->detect() when the pipe is
not already active.

To avoid needlessly duplicating the DPLL programming re-use the already
existing functions by passing a temporary pipe config to them instead
of having them consult the current pipe config at crtc->config.

v2: Introduce vlv_force_pll_{on,off}() (Daniel)
v3: Rebase due to drm_crtc vs. intel_crtc changes
    Fix a typo in commit msg (checkpatch)
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com> (v1)
[danvet: Appease checkpatch.]
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 034e43c6
...@@ -94,8 +94,10 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc, ...@@ -94,8 +94,10 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
static void ironlake_set_pipeconf(struct drm_crtc *crtc); static void ironlake_set_pipeconf(struct drm_crtc *crtc);
static void haswell_set_pipeconf(struct drm_crtc *crtc); static void haswell_set_pipeconf(struct drm_crtc *crtc);
static void intel_set_pipe_csc(struct drm_crtc *crtc); static void intel_set_pipe_csc(struct drm_crtc *crtc);
static void vlv_prepare_pll(struct intel_crtc *crtc); static void vlv_prepare_pll(struct intel_crtc *crtc,
static void chv_prepare_pll(struct intel_crtc *crtc); const struct intel_crtc_config *pipe_config);
static void chv_prepare_pll(struct intel_crtc *crtc,
const struct intel_crtc_config *pipe_config);
static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe) static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
{ {
...@@ -1484,12 +1486,13 @@ static void intel_init_dpio(struct drm_device *dev) ...@@ -1484,12 +1486,13 @@ static void intel_init_dpio(struct drm_device *dev)
} }
} }
static void vlv_enable_pll(struct intel_crtc *crtc) static void vlv_enable_pll(struct intel_crtc *crtc,
const struct intel_crtc_config *pipe_config)
{ {
struct drm_device *dev = crtc->base.dev; struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int reg = DPLL(crtc->pipe); int reg = DPLL(crtc->pipe);
u32 dpll = crtc->config.dpll_hw_state.dpll; u32 dpll = pipe_config->dpll_hw_state.dpll;
assert_pipe_disabled(dev_priv, crtc->pipe); assert_pipe_disabled(dev_priv, crtc->pipe);
...@@ -1507,7 +1510,7 @@ static void vlv_enable_pll(struct intel_crtc *crtc) ...@@ -1507,7 +1510,7 @@ static void vlv_enable_pll(struct intel_crtc *crtc)
if (wait_for(((I915_READ(reg) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1)) if (wait_for(((I915_READ(reg) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
DRM_ERROR("DPLL %d failed to lock\n", crtc->pipe); DRM_ERROR("DPLL %d failed to lock\n", crtc->pipe);
I915_WRITE(DPLL_MD(crtc->pipe), crtc->config.dpll_hw_state.dpll_md); I915_WRITE(DPLL_MD(crtc->pipe), pipe_config->dpll_hw_state.dpll_md);
POSTING_READ(DPLL_MD(crtc->pipe)); POSTING_READ(DPLL_MD(crtc->pipe));
/* We do this three times for luck */ /* We do this three times for luck */
...@@ -1522,7 +1525,8 @@ static void vlv_enable_pll(struct intel_crtc *crtc) ...@@ -1522,7 +1525,8 @@ static void vlv_enable_pll(struct intel_crtc *crtc)
udelay(150); /* wait for warmup */ udelay(150); /* wait for warmup */
} }
static void chv_enable_pll(struct intel_crtc *crtc) static void chv_enable_pll(struct intel_crtc *crtc,
const struct intel_crtc_config *pipe_config)
{ {
struct drm_device *dev = crtc->base.dev; struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -1547,14 +1551,14 @@ static void chv_enable_pll(struct intel_crtc *crtc) ...@@ -1547,14 +1551,14 @@ static void chv_enable_pll(struct intel_crtc *crtc)
udelay(1); udelay(1);
/* Enable PLL */ /* Enable PLL */
I915_WRITE(DPLL(pipe), crtc->config.dpll_hw_state.dpll); I915_WRITE(DPLL(pipe), pipe_config->dpll_hw_state.dpll);
/* Check PLL is locked */ /* Check PLL is locked */
if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1)) if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
DRM_ERROR("PLL %d failed to lock\n", pipe); DRM_ERROR("PLL %d failed to lock\n", pipe);
/* not sure when this should be written */ /* not sure when this should be written */
I915_WRITE(DPLL_MD(pipe), crtc->config.dpll_hw_state.dpll_md); I915_WRITE(DPLL_MD(pipe), pipe_config->dpll_hw_state.dpll_md);
POSTING_READ(DPLL_MD(pipe)); POSTING_READ(DPLL_MD(pipe));
mutex_unlock(&dev_priv->dpio_lock); mutex_unlock(&dev_priv->dpio_lock);
...@@ -4842,9 +4846,9 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) ...@@ -4842,9 +4846,9 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
if (!is_dsi) { if (!is_dsi) {
if (IS_CHERRYVIEW(dev)) if (IS_CHERRYVIEW(dev))
chv_prepare_pll(intel_crtc); chv_prepare_pll(intel_crtc, &intel_crtc->config);
else else
vlv_prepare_pll(intel_crtc); vlv_prepare_pll(intel_crtc, &intel_crtc->config);
} }
if (intel_crtc->config.has_dp_encoder) if (intel_crtc->config.has_dp_encoder)
...@@ -4864,9 +4868,9 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) ...@@ -4864,9 +4868,9 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
if (!is_dsi) { if (!is_dsi) {
if (IS_CHERRYVIEW(dev)) if (IS_CHERRYVIEW(dev))
chv_enable_pll(intel_crtc); chv_enable_pll(intel_crtc, &intel_crtc->config);
else else
vlv_enable_pll(intel_crtc); vlv_enable_pll(intel_crtc, &intel_crtc->config);
} }
for_each_encoder_on_crtc(dev, crtc, encoder) for_each_encoder_on_crtc(dev, crtc, encoder)
...@@ -5747,7 +5751,8 @@ void intel_dp_set_m_n(struct intel_crtc *crtc) ...@@ -5747,7 +5751,8 @@ void intel_dp_set_m_n(struct intel_crtc *crtc)
&crtc->config.dp_m2_n2); &crtc->config.dp_m2_n2);
} }
static void vlv_update_pll(struct intel_crtc *crtc) static void vlv_update_pll(struct intel_crtc *crtc,
struct intel_crtc_config *pipe_config)
{ {
u32 dpll, dpll_md; u32 dpll, dpll_md;
...@@ -5762,14 +5767,15 @@ static void vlv_update_pll(struct intel_crtc *crtc) ...@@ -5762,14 +5767,15 @@ static void vlv_update_pll(struct intel_crtc *crtc)
if (crtc->pipe == PIPE_B) if (crtc->pipe == PIPE_B)
dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
dpll |= DPLL_VCO_ENABLE; dpll |= DPLL_VCO_ENABLE;
crtc->config.dpll_hw_state.dpll = dpll; pipe_config->dpll_hw_state.dpll = dpll;
dpll_md = (crtc->config.pixel_multiplier - 1) dpll_md = (pipe_config->pixel_multiplier - 1)
<< DPLL_MD_UDI_MULTIPLIER_SHIFT; << DPLL_MD_UDI_MULTIPLIER_SHIFT;
crtc->config.dpll_hw_state.dpll_md = dpll_md; pipe_config->dpll_hw_state.dpll_md = dpll_md;
} }
static void vlv_prepare_pll(struct intel_crtc *crtc) static void vlv_prepare_pll(struct intel_crtc *crtc,
const struct intel_crtc_config *pipe_config)
{ {
struct drm_device *dev = crtc->base.dev; struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -5780,11 +5786,11 @@ static void vlv_prepare_pll(struct intel_crtc *crtc) ...@@ -5780,11 +5786,11 @@ static void vlv_prepare_pll(struct intel_crtc *crtc)
mutex_lock(&dev_priv->dpio_lock); mutex_lock(&dev_priv->dpio_lock);
bestn = crtc->config.dpll.n; bestn = pipe_config->dpll.n;
bestm1 = crtc->config.dpll.m1; bestm1 = pipe_config->dpll.m1;
bestm2 = crtc->config.dpll.m2; bestm2 = pipe_config->dpll.m2;
bestp1 = crtc->config.dpll.p1; bestp1 = pipe_config->dpll.p1;
bestp2 = crtc->config.dpll.p2; bestp2 = pipe_config->dpll.p2;
/* See eDP HDMI DPIO driver vbios notes doc */ /* See eDP HDMI DPIO driver vbios notes doc */
...@@ -5821,7 +5827,7 @@ static void vlv_prepare_pll(struct intel_crtc *crtc) ...@@ -5821,7 +5827,7 @@ static void vlv_prepare_pll(struct intel_crtc *crtc)
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv); vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv);
/* Set HBR and RBR LPF coefficients */ /* Set HBR and RBR LPF coefficients */
if (crtc->config.port_clock == 162000 || if (pipe_config->port_clock == 162000 ||
intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG) || intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG) ||
intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI))
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe), vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
...@@ -5860,19 +5866,21 @@ static void vlv_prepare_pll(struct intel_crtc *crtc) ...@@ -5860,19 +5866,21 @@ static void vlv_prepare_pll(struct intel_crtc *crtc)
mutex_unlock(&dev_priv->dpio_lock); mutex_unlock(&dev_priv->dpio_lock);
} }
static void chv_update_pll(struct intel_crtc *crtc) static void chv_update_pll(struct intel_crtc *crtc,
struct intel_crtc_config *pipe_config)
{ {
crtc->config.dpll_hw_state.dpll = DPLL_SSC_REF_CLOCK_CHV | pipe_config->dpll_hw_state.dpll = DPLL_SSC_REF_CLOCK_CHV |
DPLL_REFA_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS | DPLL_REFA_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS |
DPLL_VCO_ENABLE; DPLL_VCO_ENABLE;
if (crtc->pipe != PIPE_A) if (crtc->pipe != PIPE_A)
crtc->config.dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; pipe_config->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
crtc->config.dpll_hw_state.dpll_md = pipe_config->dpll_hw_state.dpll_md =
(crtc->config.pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; (pipe_config->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
} }
static void chv_prepare_pll(struct intel_crtc *crtc) static void chv_prepare_pll(struct intel_crtc *crtc,
const struct intel_crtc_config *pipe_config)
{ {
struct drm_device *dev = crtc->base.dev; struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -5883,18 +5891,18 @@ static void chv_prepare_pll(struct intel_crtc *crtc) ...@@ -5883,18 +5891,18 @@ static void chv_prepare_pll(struct intel_crtc *crtc)
u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac; u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
int refclk; int refclk;
bestn = crtc->config.dpll.n; bestn = pipe_config->dpll.n;
bestm2_frac = crtc->config.dpll.m2 & 0x3fffff; bestm2_frac = pipe_config->dpll.m2 & 0x3fffff;
bestm1 = crtc->config.dpll.m1; bestm1 = pipe_config->dpll.m1;
bestm2 = crtc->config.dpll.m2 >> 22; bestm2 = pipe_config->dpll.m2 >> 22;
bestp1 = crtc->config.dpll.p1; bestp1 = pipe_config->dpll.p1;
bestp2 = crtc->config.dpll.p2; bestp2 = pipe_config->dpll.p2;
/* /*
* Enable Refclk and SSC * Enable Refclk and SSC
*/ */
I915_WRITE(dpll_reg, I915_WRITE(dpll_reg,
crtc->config.dpll_hw_state.dpll & ~DPLL_VCO_ENABLE); pipe_config->dpll_hw_state.dpll & ~DPLL_VCO_ENABLE);
mutex_lock(&dev_priv->dpio_lock); mutex_lock(&dev_priv->dpio_lock);
...@@ -5942,6 +5950,53 @@ static void chv_prepare_pll(struct intel_crtc *crtc) ...@@ -5942,6 +5950,53 @@ static void chv_prepare_pll(struct intel_crtc *crtc)
mutex_unlock(&dev_priv->dpio_lock); mutex_unlock(&dev_priv->dpio_lock);
} }
/**
* vlv_force_pll_on - forcibly enable just the PLL
* @dev_priv: i915 private structure
* @pipe: pipe PLL to enable
* @dpll: PLL configuration
*
* Enable the PLL for @pipe using the supplied @dpll config. To be used
* in cases where we need the PLL enabled even when @pipe is not going to
* be enabled.
*/
void vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
const struct dpll *dpll)
{
struct intel_crtc *crtc =
to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
struct intel_crtc_config pipe_config = {
.pixel_multiplier = 1,
.dpll = *dpll,
};
if (IS_CHERRYVIEW(dev)) {
chv_update_pll(crtc, &pipe_config);
chv_prepare_pll(crtc, &pipe_config);
chv_enable_pll(crtc, &pipe_config);
} else {
vlv_update_pll(crtc, &pipe_config);
vlv_prepare_pll(crtc, &pipe_config);
vlv_enable_pll(crtc, &pipe_config);
}
}
/**
* vlv_force_pll_off - forcibly disable just the PLL
* @dev_priv: i915 private structure
* @pipe: pipe PLL to disable
*
* Disable the PLL for @pipe. To be used in cases where we need
* the PLL enabled even when @pipe is not going to be enabled.
*/
void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe)
{
if (IS_CHERRYVIEW(dev))
chv_disable_pll(to_i915(dev), pipe);
else
vlv_disable_pll(to_i915(dev), pipe);
}
static void i9xx_update_pll(struct intel_crtc *crtc, static void i9xx_update_pll(struct intel_crtc *crtc,
intel_clock_t *reduced_clock, intel_clock_t *reduced_clock,
int num_connectors) int num_connectors)
...@@ -6323,9 +6378,9 @@ static int i9xx_crtc_mode_set(struct intel_crtc *crtc, ...@@ -6323,9 +6378,9 @@ static int i9xx_crtc_mode_set(struct intel_crtc *crtc,
has_reduced_clock ? &reduced_clock : NULL, has_reduced_clock ? &reduced_clock : NULL,
num_connectors); num_connectors);
} else if (IS_CHERRYVIEW(dev)) { } else if (IS_CHERRYVIEW(dev)) {
chv_update_pll(crtc); chv_update_pll(crtc, &crtc->config);
} else if (IS_VALLEYVIEW(dev)) { } else if (IS_VALLEYVIEW(dev)) {
vlv_update_pll(crtc); vlv_update_pll(crtc, &crtc->config);
} else { } else {
i9xx_update_pll(crtc, i9xx_update_pll(crtc,
has_reduced_clock ? &reduced_clock : NULL, has_reduced_clock ? &reduced_clock : NULL,
......
...@@ -330,6 +330,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) ...@@ -330,6 +330,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
enum pipe pipe = intel_dp->pps_pipe; enum pipe pipe = intel_dp->pps_pipe;
bool pll_enabled;
uint32_t DP; uint32_t DP;
if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN, if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN,
...@@ -353,6 +354,16 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) ...@@ -353,6 +354,16 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
else if (pipe == PIPE_B) else if (pipe == PIPE_B)
DP |= DP_PIPEB_SELECT; DP |= DP_PIPEB_SELECT;
pll_enabled = I915_READ(DPLL(pipe)) & DPLL_VCO_ENABLE;
/*
* The DPLL for the pipe must be enabled for this to work.
* So enable temporarily it if it's not already enabled.
*/
if (!pll_enabled)
vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ?
&chv_dpll[0].dpll : &vlv_dpll[0].dpll);
/* /*
* Similar magic as in intel_dp_enable_port(). * Similar magic as in intel_dp_enable_port().
* We _must_ do this port enable + disable trick * We _must_ do this port enable + disable trick
...@@ -367,6 +378,9 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) ...@@ -367,6 +378,9 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
POSTING_READ(intel_dp->output_reg); POSTING_READ(intel_dp->output_reg);
if (!pll_enabled)
vlv_force_pll_off(dev, pipe);
} }
static enum pipe static enum pipe
......
...@@ -918,6 +918,10 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, ...@@ -918,6 +918,10 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc); struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc);
void intel_put_shared_dpll(struct intel_crtc *crtc); void intel_put_shared_dpll(struct intel_crtc *crtc);
void vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
const struct dpll *dpll);
void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe);
/* modesetting asserts */ /* modesetting asserts */
void assert_panel_unlocked(struct drm_i915_private *dev_priv, void assert_panel_unlocked(struct drm_i915_private *dev_priv,
enum pipe pipe); enum pipe pipe);
......
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