On Fri, Aug 15, 2014 at 01:22:05AM +0300, ville.syrjala@xxxxxxxxxxxxxxx wrote: > From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > > The spec says: > "For the correct operation of the muxed DVO pins (GDEVSELB/ I2Cdata, > GIRDBY/I2CClk) and (GFRAMEB/DVI_Data, GTRDYB/DVI_Clk): Bit 31 > (DPLL VCO Enable) and Bit 30 (2X Clock Enable) must be set to “1” in > both the DPLL A Control Register (06014h-06017h) and DPLL B Control > Register (06018h-0601Bh)." > > The pipe A and B force quirks take care of DPLL_VCO_ENABLE, so we > just need a bit of special care to handle DPLL_DVO_2X_MODE. > > Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > --- > drivers/gpu/drm/i915/i915_drv.h | 3 +++ > drivers/gpu/drm/i915/intel_display.c | 47 +++++++++++++++++++++++++++++++++--- > 2 files changed, 46 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 541fb6f..54895a6 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -1561,6 +1561,9 @@ struct drm_i915_private { > > u16 orig_clock; > > + /* used to control DVO 2x clock enable on 830M */ > + uint8_t dvo_pipes; > + > bool mchbar_need_disable; > > struct intel_l3_parity l3_parity; > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 3eeb5ce..6462bcf 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -1548,6 +1548,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) > { > struct drm_device *dev = crtc->base.dev; > struct drm_i915_private *dev_priv = dev->dev_private; > + enum pipe pipe = crtc->pipe; > int reg = DPLL(crtc->pipe); > u32 dpll = crtc->config.dpll_hw_state.dpll; > > @@ -1560,7 +1561,16 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) > if (IS_MOBILE(dev) && !IS_I830(dev)) > assert_panel_unlocked(dev_priv, crtc->pipe); > > - I915_WRITE(reg, dpll); > + /* enable DVO 2x clock on both PLLs if necessary */ > + if (IS_I830(dev)) { > + if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO)) > + dev_priv->dvo_pipes |= 1 << pipe; > + > + if (dev_priv->dvo_pipes) { > + dpll |= DPLL_DVO_2X_MODE; > + I915_WRITE(DPLL(!pipe), I915_READ(DPLL(!pipe)) | DPLL_DVO_2X_MODE); > + } > + } > > /* Wait for the clocks to stabilize. */ > POSTING_READ(reg); > @@ -1599,8 +1609,23 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) > * > * Note! This is for pre-ILK only. > */ > -static void i9xx_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) > +static void i9xx_disable_pll(struct intel_crtc *crtc) > { > + struct drm_device *dev = crtc->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + enum pipe pipe = crtc->pipe; > + > + /* disable DVO 2x clock on both PLLs if necessary */ > + if (IS_I830(dev)) { > + if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO)) > + dev_priv->dvo_pipes &= ~(1 << pipe); > + > + if (!dev_priv->dvo_pipes) { > + I915_WRITE(DPLL(pipe), I915_READ(DPLL(pipe)) & ~DPLL_DVO_2X_MODE); > + I915_WRITE(DPLL(!pipe), I915_READ(DPLL(!pipe)) & ~DPLL_DVO_2X_MODE); Bikeshed: I'd just use explicit PIPE_A and PIPE_B here, except when we really have to turn of our pipe first before the other. > + } > + } > + > /* Don't disable pipe A or pipe A PLLs if needed */ > if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) > return; > @@ -4788,7 +4813,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) > else if (IS_VALLEYVIEW(dev)) > vlv_disable_pll(dev_priv, pipe); > else > - i9xx_disable_pll(dev_priv, pipe); > + i9xx_disable_pll(intel_crtc); > } > > if (!IS_GEN2(dev)) > @@ -5792,7 +5817,7 @@ static void i8xx_update_pll(struct intel_crtc *crtc, > dpll |= PLL_P2_DIVIDE_BY_4; > } > > - if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO)) > + if (!IS_I830(dev) && intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO)) > dpll |= DPLL_DVO_2X_MODE; > > if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) && > @@ -6298,6 +6323,9 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, > } > pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe)); > if (!IS_VALLEYVIEW(dev)) { > + if (IS_I830(dev)) > + pipe_config->dpll_hw_state.dpll &= ~DPLL_DVO_2X_MODE; > + > pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(crtc->pipe)); > pipe_config->dpll_hw_state.fp1 = I915_READ(FP1(crtc->pipe)); > } else { > @@ -13021,6 +13049,17 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, > } > } > > + /* update dvo_pipes */ > + if (IS_I830(dev)) { > + dev_priv->dvo_pipes = 0; > + > + for_each_intel_crtc(dev, crtc) { > + if (crtc->active && > + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO)) > + dev_priv->dvo_pipes |= 1 << crtc->pipe; > + } > + } This puts gunk into the modeset hw state stuff. Imo just loop over all pipes and recompute the i830_needs_dvo_2x everywhere you need it, instead of adding a new dev_priv->dvo_pipes state which might get out of sync eventually. I'll punt on this for now. -Daniel > + > /* HW state is read out, now we need to sanitize this mess. */ > for_each_intel_encoder(dev, encoder) { > intel_sanitize_encoder(encoder); > -- > 1.8.5.5 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx