Message ID | 1366239301-11954-6-git-send-email-jbarnes@virtuousgeek.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, Apr 17, 2013 at 03:55:01PM -0700, Jesse Barnes wrote: > In Valleyview voltage swing, pre-emphasis and lane control registers can > be programmed only through the h/w side band fabric. Update > vlv_update_pll, i9xx_crtc_enable, and intel_enable_pll with the > appropriate programming. > > We need to make sure that the tx lane reset occurs in both the full mode > set and DPMS paths, so factor things out to allow that. > > v2: use different DPIO_DIVISOR values for VGA and DisplayPort > v3: Fix update pll logic to use same DPIO_DIVISOR & DPIO_REFSFR values > for all display interfaces > v4: collapse with various updates > v5: squash with crtc enable/pll enable bits > v6: split out DP code (jbarnes) > put phyready check under IS_VALLEYVIEW (jbarnes) > remove unneeded check in 9xx pll div update (Jani) > wrap VLV pll update call in IS_VALLEYVIEW (Jani) > move port enable back to end of crtc enable (jbarnes) > put phyready check under IS_VALLEYVIEW (jbarnes) > v7: fix up conflicts against latest drm-intel-next-queued > v8: use DPIO reg names, fix pipes (Jani) > from mPhy_registers_VLV2_ww20p5 doc > v9: update to latest info from driver enabling notes doc > driver_vbios_notes_9 > v10: fixup a bit of pipe/port confusion to allow eDP and HDMI to work > simultaneously (Jesse) > > Signed-off-by: Pallavi G <pallavi.g@intel.com> > Signed-off-by: Vijay Purushothaman <vijay.a.purushothaman@intel.com> > Signed-off-by: Gajanan Bhat <gajanan.bhat@intel.com> > Signed-off-by: Ben Widawsky <benjamin.widawsky@intel.com> > Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> > > Conflicts: > drivers/gpu/drm/i915/intel_display.c Nope. I realize that you've yelled at this patch for way too long, and tbh I've given up on expecting readable vlv pll. But this patch has still tons of other cruft which is either plain broken or should at least be split up. I'll do that for you, with per-patch commentary. Patches 1-2 merged to dinq. -Daniel > --- > drivers/gpu/drm/i915/i915_reg.h | 118 +++++++++++- > drivers/gpu/drm/i915/intel_display.c | 351 +++++++++++++++++++++++++++------- > 2 files changed, 399 insertions(+), 70 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 66fb8dd..fb1a4fa 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -353,6 +353,8 @@ > * 0x8100: fast clock controls > * > * DPIO is VLV only. > + * > + * Note: digital port B is DDI0, digital pot C is DDI1 > */ > #define DPIO_PKT (VLV_DISPLAY_BASE + 0x2100) > #define DPIO_RID (0<<24) > @@ -369,8 +371,20 @@ > #define DPIO_SFR_BYPASS (1<<1) > #define DPIO_RESET (1<<0) > > +#define _DPIO_TX3_SWING_CTL4_A 0x690 > +#define _DPIO_TX3_SWING_CTL4_B 0x2a90 > +#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX_SWING_CTL4_A, \ > + _DPIO_TX3_SWING_CTL4_B) > + > +/* > + * Per pipe/PLL DPIO regs > + */ > #define _DPIO_DIV_A 0x800c > #define DPIO_POST_DIV_SHIFT (28) /* 3 bits */ > +#define DPIO_POST_DIV_DAC 0 > +#define DPIO_POST_DIV_HDMIDP 1 /* DAC 225-400M rate */ > +#define DPIO_POST_DIV_LVDS1 2 > +#define DPIO_POST_DIV_LVDS2 3 > #define DPIO_K_SHIFT (24) /* 4 bits */ > #define DPIO_P1_SHIFT (21) /* 3 bits */ > #define DPIO_P2_SHIFT (16) /* 5 bits */ > @@ -396,14 +410,111 @@ > #define _DPIO_CORE_CLK_B 0x803c > #define DPIO_CORE_CLK(pipe) _PIPE(pipe, _DPIO_CORE_CLK_A, _DPIO_CORE_CLK_B) > > +#define _DPIO_IREF_CTL_A 0x8040 > +#define _DPIO_IREF_CTL_B 0x8060 > +#define DPIO_IREF_CTL(pipe) _PIPE(pipe, _DPIO_IREF_CTL_A, _DPIO_IREF_CTL_B) > + > +#define DPIO_IREF_BCAST 0xc044 > +#define _DPIO_IREF_A 0x8044 > +#define _DPIO_IREF_B 0x8064 > +#define DPIO_IREF(pipe) _PIPE(pipe, _DPIO_IREF_A, _DPIO_IREF_B) > + > +#define _DPIO_PLL_CML_A 0x804c > +#define _DPIO_PLL_CML_B 0x806c > +#define DPIO_PLL_CML(pipe) _PIPE(pipe, _DPIO_PLL_CML_A, _DPIO_PLL_CML_B) > + > #define _DPIO_LFP_COEFF_A 0x8048 > #define _DPIO_LFP_COEFF_B 0x8068 > #define DPIO_LFP_COEFF(pipe) _PIPE(pipe, _DPIO_LFP_COEFF_A, _DPIO_LFP_COEFF_B) > > +#define DPIO_CALIBRATION 0x80ac > + > #define DPIO_FASTCLK_DISABLE 0x8100 > > -#define DPIO_DATA_CHANNEL1 0x8220 > -#define DPIO_DATA_CHANNEL2 0x8420 > +/* > + * Per DDI channel DPIO regs > + */ > + > +#define _DPIO_PCS_TX_0 0x8200 > +#define _DPIO_PCS_TX_1 0x8400 > +#define DPIO_PCS_TX_LANE2_RESET (1<<16) > +#define DPIO_PCS_TX_LANE1_RESET (1<<7) > +#define DPIO_PCS_TX(port) _PORT(port, _DPIO_PCS_TX_0, _DPIO_PCS_TX_1) > + > +#define _DPIO_PCS_CLK_0 0x8204 > +#define _DPIO_PCS_CLK_1 0x8404 > +#define DPIO_PCS_CLK_CRI_RXEB_EIOS_EN (1<<22) > +#define DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN (1<<21) > +#define DPIO_PCS_CLK_DATAWIDTH_SHIFT (6) > +#define DPIO_PCS_CLK_SOFT_RESET (1<<5) > +#define DPIO_PCS_CLK(port) _PORT(port, _DPIO_PCS_CLK_0, _DPIO_PCS_CLK_1) > + > +#define _DPIO_PCS_CTL_OVR1_A 0x8224 > +#define _DPIO_PCS_CTL_OVR1_B 0x8424 > +#define DPIO_PCS_CTL_OVER1(port) _PORT(port, _DPIO_PCS_CTL_OVR1_A, \ > + _DPIO_PCS_CTL_OVR1_B) > + > +#define _DPIO_PCS_STAGGER0_A 0x822c > +#define _DPIO_PCS_STAGGER0_B 0x842c > +#define DPIO_PCS_STAGGER0(port) _PORT(port, _DPIO_PCS_STAGGER0_A, \ > + _DPIO_PCS_STAGGER0_B) > + > +#define _DPIO_PCS_STAGGER1_A 0x8230 > +#define _DPIO_PCS_STAGGER1_B 0x8430 > +#define DPIO_PCS_STAGGER1(port) _PORT(port, _DPIO_PCS_STAGGER1_A, \ > + _DPIO_PCS_STAGGER1_B) > + > +#define _DPIO_PCS_CLOCKBUF0_A 0x8238 > +#define _DPIO_PCS_CLOCKBUF0_B 0x8438 > +#define DPIO_PCS_CLOCKBUF0(port) _PORT(port, _DPIO_PCS_CLOCKBUF0_A, \ > + _DPIO_PCS_CLOCKBUF0_B) > + > +#define _DPIO_PCS_CLOCKBUF8_A 0x825c > +#define _DPIO_PCS_CLOCKBUF8_B 0x845c > +#define DPIO_PCS_CLOCKBUF8(port) _PORT(port, _DPIO_PCS_CLOCKBUF8_A, \ > + _DPIO_PCS_CLOCKBUF8_B) > + > +#define _DPIO_TX_SWING_CTL2_A 0x8288 > +#define _DPIO_TX_SWING_CTL2_B 0x8488 > +#define DPIO_TX_SWING_CTL2(port) _PORT(port, _DPIO_TX_SWING_CTL2_A, \ > + _DPIO_TX_SWING_CTL2_B) > + > +#define _DPIO_TX_SWING_CTL3_A 0x828c > +#define _DPIO_TX_SWING_CTL3_B 0x848c > +#define DPIO_TX_SWING_CTL3(port) _PORT(port, _DPIO_TX_SWING_CTL3_A, \ > + _DPIO_TX_SWING_CTL3_B) > + > +#define _DPIO_TX_SWING_CTL4_A 0x8290 > +#define _DPIO_TX_SWING_CTL4_B 0x8490 > +#define DPIO_TX_SWING_CTL4(port) _PORT(port, _DPIO_TX_SWING_CTL4_A, \ > + _DPIO_TX_SWING_CTL4_B) > + > +#define _DPIO_TX_OCALINIT_0 0x8294 > +#define _DPIO_TX_OCALINIT_1 0x8494 > +#define DPIO_TX_OCALINIT_EN (1<<31) > +#define DPIO_TX_OCALINIT(port) _PORT(port, _DPIO_TX_OCALINIT_0, \ > + _DPIO_TX_OCALINIT_1) > + > +#define _DPIO_TX_CTL_0 0x82ac > +#define _DPIO_TX_CTL_1 0x84ac > +#define DPIO_TX_CTL(port) _PORT(port, _DPIO_TX_CTL_0, _DPIO_TX_CTL_1) > + > +#define _DPIO_TX_LANE_0 0x82b8 > +#define _DPIO_TX_LANE_1 0x84b8 > +#define DPIO_TX_LANE(port) _PORT(port, _DPIO_TX_LANE_0, _DPIO_TX_LANE_1) > + > +#define _DPIO_DATA_CHANNEL1 0x8220 > +#define _DPIO_DATA_CHANNEL2 0x8420 > +#define DPIO_DATA_CHANNEL(port) _PORT(port, _DPIO_DATA_CHANNEL1, _DPIO_DATA_CHANNEL2) > + > +#define _DPIO_PORT0_PCS0 0x0220 > +#define _DPIO_PORT0_PCS1 0x0420 > +#define _DPIO_PORT1_PCS2 0x2620 > +#define _DPIO_PORT1_PCS3 0x2820 > +#define DPIO_DATA_LANE_A(port) _PORT(port, _DPIO_PORT0_PCS0, _DPIO_PORT1_PCS2) > +#define DPIO_DATA_LANE_B(port) _PORT(port, _DPIO_PORT0_PCS1, _DPIO_PORT1_PCS3) > +#define DPIO_DATA_CHANNEL1 0x8220 > +#define DPIO_DATA_CHANNEL2 0x8420 > > /* > * Fence registers > @@ -965,7 +1076,10 @@ > #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ > #define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ > #define DPLL_LOCK_VLV (1<<15) > +#define DPLL_INTEGRATED_CRI_CLK_VLV (1<<14) > #define DPLL_INTEGRATED_CLOCK_VLV (1<<13) > +#define DPLL_PORTC_READY_MASK (0xf << 4) > +#define DPLL_PORTB_READY_MASK (0xf) > > #define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 > /* > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index f3aa24f4..56c13b6 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -404,14 +404,14 @@ static const intel_limit_t intel_limits_vlv_dac = { > }; > > static const intel_limit_t intel_limits_vlv_hdmi = { > - .dot = { .min = 25000, .max = 180000 }, > - .vco = { .min = 4040000, .max = 5960000 }, > - .n = { .min = 1, .max = 5 }, > + .dot = { .min = 25000, .max = 270000 }, > + .vco = { .min = 4000000, .max = 6000000 }, > + .n = { .min = 1, .max = 7 }, > .m = { .min = 60, .max = 300 }, /* guess */ > .m1 = { .min = 2, .max = 3 }, > - .m2 = { .min = 15, .max = 149 }, > + .m2 = { .min = 11, .max = 156 }, > .p = { .min = 10, .max = 30 }, > - .p1 = { .min = 1, .max = 3 }, > + .p1 = { .min = 2, .max = 3 }, > .p2 = { .dot_limit = 270000, > .p2_slow = 2, .p2_fast = 20 }, > .find_pll = intel_vlv_find_best_pll, > @@ -2591,7 +2591,6 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) > DRM_ERROR("FDI train 2 fail!\n"); > > DRM_DEBUG_KMS("FDI train done\n"); > - > } > > static const int snb_b_fdi_train_param[] = { > @@ -3694,6 +3693,117 @@ g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe) > } > } > > +static void vlv_pll_pre_enable(struct drm_crtc *crtc) > +{ > + struct drm_device *dev = crtc->dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + > + WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock)); > + > + /* Assume eDP on port C and HDMI/DP on port B */ > + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { > + /* Program Tx lane resets to default */ > + intel_dpio_write(dev_priv, DPIO_PCS_TX(0), > + DPIO_PCS_TX_LANE2_RESET | > + DPIO_PCS_TX_LANE1_RESET); > + intel_dpio_write(dev_priv, DPIO_PCS_CLK(0), > + DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | > + DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | > + (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) | > + DPIO_PCS_CLK_SOFT_RESET); > + > + /* Fix up inter-pair skew failure */ > + intel_dpio_write(dev_priv, DPIO_PCS_STAGGER1(0), 0x00750f00); > + intel_dpio_write(dev_priv, DPIO_TX_CTL(0), 0x00001500); > + intel_dpio_write(dev_priv, DPIO_TX_LANE(0), 0x40400000); > + > + intel_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(0), > + 0x00002000); > + intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(0), > + DPIO_TX_OCALINIT_EN); > + } > + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || > + intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { > + /* Program Tx lane resets to default */ > + intel_dpio_write(dev_priv, DPIO_PCS_TX(1), > + DPIO_PCS_TX_LANE2_RESET | > + DPIO_PCS_TX_LANE1_RESET); > + intel_dpio_write(dev_priv, DPIO_PCS_CLK(1), > + DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | > + DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | > + (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) | > + DPIO_PCS_CLK_SOFT_RESET); > + > + /* Fix up inter-pair skew failure */ > + intel_dpio_write(dev_priv, DPIO_PCS_STAGGER1(1), 0x00750f00); > + intel_dpio_write(dev_priv, DPIO_TX_CTL(1), 0x00001500); > + intel_dpio_write(dev_priv, DPIO_TX_LANE(1), 0x40400000); > + } > +} > + > +static void vlv_pll_post_enable(struct drm_crtc *crtc) > +{ > + struct drm_device *dev = crtc->dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > + int pipe = intel_crtc->pipe; > + > + WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock)); > + > + /* Assume eDP on port C and HDMI/DP on port B */ > + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { > + /* Enable clock channels for this port */ > + u32 val; > + val = intel_dpio_read(dev_priv, DPIO_DATA_LANE_A(0)); > + val = 0; > + if (pipe) > + val |= (1<<21); > + else > + val &= ~(1<<21); > + val |= 0x001000c4; > + intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL(0), val); > + > + /* HDMI 1.0V-2dB */ > + intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(0), 0); > + intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(0), > + 0x2b245f5f); > + intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(0), > + 0x5578b83a); > + intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(0), > + 0x0c782040); > + intel_dpio_write(dev_priv, DPIO_TX3_SWING_CTL4(0), > + 0x2b247878); > + intel_dpio_write(dev_priv, DPIO_PCS_STAGGER0(0), 0x00030000); > + intel_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(0), > + 0x00002000); > + intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(0), > + DPIO_TX_OCALINIT_EN); > + > + /* Program lane clock */ > + intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(0), > + 0x00760018); > + intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(0), > + 0x00400888); > + } > + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || > + intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { > + u32 val; > + val = intel_dpio_read(dev_priv, DPIO_DATA_LANE_A(1)); > + val = 0; > + if (pipe) > + val |= (1<<21); > + else > + val &= ~(1<<21); > + val |= 0x001000c4; > + intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL(1), val); > + > + intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(1), > + 0x00760018); > + intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(1), > + 0x00400888); > + } > +} > + > static void i9xx_crtc_enable(struct drm_crtc *crtc) > { > struct drm_device *dev = crtc->dev; > @@ -3702,6 +3812,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) > struct intel_encoder *encoder; > int pipe = intel_crtc->pipe; > int plane = intel_crtc->plane; > + u32 port_mask; > > WARN_ON(!crtc->enabled); > > @@ -3711,12 +3822,44 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) > intel_crtc->active = true; > intel_update_watermarks(dev); > > + if (IS_VALLEYVIEW(dev)) { > + mutex_lock(&dev_priv->dpio_lock); > + vlv_pll_pre_enable(crtc); > + mutex_unlock(&dev_priv->dpio_lock); > + } > + > intel_enable_pll(dev_priv, pipe); > > + if (IS_VALLEYVIEW(dev)) { > + mutex_lock(&dev_priv->dpio_lock); > + vlv_pll_post_enable(crtc); > + mutex_unlock(&dev_priv->dpio_lock); > + } > + > for_each_encoder_on_crtc(dev, crtc, encoder) > if (encoder->pre_enable) > encoder->pre_enable(encoder); > > + for_each_encoder_on_crtc(dev, crtc, encoder) > + encoder->enable(encoder); > + > + if (IS_VALLEYVIEW(dev)) { > + char port; > + > + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || > + intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { > + port_mask = DPLL_PORTB_READY_MASK; > + port = 'B'; > + } else { > + port_mask = DPLL_PORTC_READY_MASK; /* eDP on port C */ > + port = 'C'; > + } > + > + if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 1000)) > + WARN(1, "timed out waiting for port %c ready: 0x%08x\n", > + port, I915_READ(DPLL(0))); > + } > + > intel_enable_pipe(dev_priv, pipe, false); > intel_enable_plane(dev_priv, plane, pipe); > if (IS_G4X(dev)) > @@ -3728,9 +3871,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) > /* Give the overlay scaler a chance to enable if it's on this pipe */ > intel_crtc_dpms_overlay(intel_crtc, true); > intel_crtc_update_cursor(crtc, true); > - > - for_each_encoder_on_crtc(dev, crtc, encoder) > - encoder->enable(encoder); > } > > static void i9xx_pfit_disable(struct intel_crtc *crtc) > @@ -3782,6 +3922,27 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) > > i9xx_pfit_disable(intel_crtc); > > + for_each_encoder_on_crtc(dev, crtc, encoder) > + if (encoder->post_disable) > + encoder->post_disable(encoder); > + > + /* Reset lane for VLV platform*/ > + if (IS_VALLEYVIEW(dev)) { > + mutex_lock(&dev_priv->dpio_lock); > + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { > + intel_dpio_write(dev_priv, DPIO_PCS_TX(0), > + 0x00000000); > + intel_dpio_write(dev_priv, DPIO_PCS_CLK(0), > + 0x00e00060); > + } else { > + intel_dpio_write(dev_priv, DPIO_PCS_TX(1), > + 0x00000000); > + intel_dpio_write(dev_priv, DPIO_PCS_CLK(1), > + 0x00e00060); > + } > + mutex_unlock(&dev_priv->dpio_lock); > + } > + > intel_disable_pll(dev_priv, pipe); > > intel_crtc->active = false; > @@ -4012,7 +4173,7 @@ static bool intel_crtc_compute_config(struct drm_crtc *crtc, > adjusted_mode->hsync_start == adjusted_mode->hdisplay) > return false; > > - if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) && pipe_config->pipe_bpp > 10) { > + if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) && pipe_config->pipe_bpp > 30) { > pipe_config->pipe_bpp = 10*3; /* 12bpc is gen5+ */ > } else if (INTEL_INFO(dev)->gen <= 4 && pipe_config->pipe_bpp > 8) { > /* only a 8bpc pipe, with 6bpc dither through the panel fitter > @@ -4224,6 +4385,34 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc, > } > } > > +static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv) > +{ > + u32 reg_val; > + > + /* > + * PLLB opamp always calibrates to max value of 0x3f, force enable it > + * and set it to a reasonable value instead. > + */ > + reg_val = intel_dpio_read(dev_priv, DPIO_IREF(1)); > + reg_val &= 0xffffff00; > + reg_val |= 0x00000030; > + intel_dpio_write(dev_priv, DPIO_IREF(1), reg_val); > + > + reg_val = intel_dpio_read(dev_priv, DPIO_CALIBRATION); > + reg_val &= 0x8cffffff; > + reg_val = 0x8c000000; > + intel_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val); > + > + reg_val = intel_dpio_read(dev_priv, DPIO_IREF(1)); > + reg_val &= 0xffffff00; > + intel_dpio_write(dev_priv, DPIO_IREF(1), reg_val); > + > + reg_val = intel_dpio_read(dev_priv, DPIO_CALIBRATION); > + reg_val &= 0x00ffffff; > + reg_val |= 0xb0000000; > + intel_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val); > +} > + > static void intel_dp_set_m_n(struct intel_crtc *crtc) > { > if (crtc->config.has_pch_encoder) > @@ -4236,24 +4425,17 @@ static void vlv_update_pll(struct intel_crtc *crtc) > { > struct drm_device *dev = crtc->base.dev; > struct drm_i915_private *dev_priv = dev->dev_private; > + struct drm_display_mode *adjusted_mode = > + &crtc->config.adjusted_mode; > int pipe = crtc->pipe; > - u32 dpll, mdiv, pdiv; > + u32 dpll, mdiv; > u32 bestn, bestm1, bestm2, bestp1, bestp2; > - bool is_sdvo; > - u32 temp; > + bool is_hdmi; > + u32 coreclk, reg_val, temp; > > mutex_lock(&dev_priv->dpio_lock); > > - is_sdvo = intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_SDVO) || > - intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI); > - > - dpll = DPLL_VGA_MODE_DIS; > - dpll |= DPLL_EXT_BUFFER_ENABLE_VLV; > - dpll |= DPLL_REFA_CLK_ENABLE_VLV; > - dpll |= DPLL_INTEGRATED_CLOCK_VLV; > - > - I915_WRITE(DPLL(pipe), dpll); > - POSTING_READ(DPLL(pipe)); > + is_hdmi = intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI); > > bestn = crtc->config.dpll.n; > bestm1 = crtc->config.dpll.m1; > @@ -4261,70 +4443,106 @@ static void vlv_update_pll(struct intel_crtc *crtc) > bestp1 = crtc->config.dpll.p1; > bestp2 = crtc->config.dpll.p2; > > - /* > - * In Valleyview PLL and program lane counter registers are exposed > - * through DPIO interface > - */ > + /* See eDP HDMI DPIO driver vbios notes doc */ > + > + /* PLL B needs special handling */ > + if (pipe) > + vlv_pllb_recal_opamp(dev_priv); > + > + /* Set up Tx target for periodic Rcomp update */ > + intel_dpio_write(dev_priv, DPIO_IREF_BCAST, 0x0100000f); > + > + /* Disable target IRef on PLL */ > + reg_val = intel_dpio_read(dev_priv, DPIO_IREF_CTL(pipe)); > + reg_val &= 0x00ffffff; > + intel_dpio_write(dev_priv, DPIO_IREF_CTL(pipe), reg_val); > + > + vlv_pll_pre_enable(&crtc->base); > + > + /* Disable fast lock */ > + intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x610); > + > + /* Set idtafcrecal before PLL is enabled */ > mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK)); > mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT)); > mdiv |= ((bestn << DPIO_N_SHIFT)); > - mdiv |= (1 << DPIO_POST_DIV_SHIFT); > mdiv |= (1 << DPIO_K_SHIFT); > + if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI) || > + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) || > + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) > + mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT); > + intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); > + > mdiv |= DPIO_ENABLE_CALIBRATION; > intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); > > - intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), 0x01000000); > + /* Set HBR and RBR LPF coefficients */ > + if (adjusted_mode->clock == 162000 || > + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI)) > + intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), > + 0x005f0021); > + else > + intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), > + 0x00d0000f); > + > + if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) || > + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) { > + /* Use SSC source */ > + if (!pipe) > + intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), > + 0x0df40000); > + else > + intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), > + 0x0df70000); > + } else { /* HDMI or VGA */ > + /* Use bend source */ > + if (!pipe) > + intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), > + 0x0df70000); > + else > + intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), > + 0x0df40000); > + } > + > + coreclk = intel_dpio_read(dev_priv, DPIO_CORE_CLK(pipe)); > + coreclk = (coreclk & 0x0000ff00) | 0x01c00000; > + if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) || > + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) > + coreclk |= 0x01000000; > + intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), coreclk); > > - pdiv = (1 << DPIO_REFSEL_OVERRIDE) | (5 << DPIO_PLL_MODESEL_SHIFT) | > - (3 << DPIO_BIAS_CURRENT_CTL_SHIFT) | (1<<20) | > - (7 << DPIO_PLL_REFCLK_SEL_SHIFT) | (8 << DPIO_DRIVER_CTL_SHIFT) | > - (5 << DPIO_CLK_BIAS_CTL_SHIFT); > - intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), pdiv); > + intel_dpio_write(dev_priv, DPIO_PLL_CML(pipe), 0x87871000); > > - intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), 0x005f003b); > + /* Enable DPIO clock input */ > + dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV | > + DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV; > + if (pipe) > + dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; > > dpll |= DPLL_VCO_ENABLE; > I915_WRITE(DPLL(pipe), dpll); > POSTING_READ(DPLL(pipe)); > + udelay(150); > + > if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1)) > DRM_ERROR("DPLL %d failed to lock\n", pipe); > > - intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x620); > - > - if (crtc->config.has_dp_encoder) > - intel_dp_set_m_n(crtc); > - > - I915_WRITE(DPLL(pipe), dpll); > + vlv_pll_post_enable(&crtc->base); > > - /* Wait for the clocks to stabilize. */ > - POSTING_READ(DPLL(pipe)); > - udelay(150); > - > - temp = 0; > - if (is_sdvo) { > + if (is_hdmi) { > temp = 0; > if (crtc->config.pixel_multiplier > 1) { > temp = (crtc->config.pixel_multiplier - 1) > << DPLL_MD_UDI_MULTIPLIER_SHIFT; > } > - } > - I915_WRITE(DPLL_MD(pipe), temp); > - POSTING_READ(DPLL_MD(pipe)); > > - /* Now program lane control registers */ > - if(intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) > - || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI)) { > - temp = 0x1000C4; > - if(pipe == 1) > - temp |= (1 << 21); > - intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL1, temp); > + I915_WRITE(DPLL_MD(pipe), temp); > + POSTING_READ(DPLL_MD(pipe)); > } > > - if(intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) { > - temp = 0x1000C4; > - if(pipe == 1) > - temp |= (1 << 21); > - intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL2, temp); > + if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) || > + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) { > + intel_dp_set_m_n(crtc); > } > > mutex_unlock(&dev_priv->dpio_lock); > @@ -4713,9 +4931,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, > else if (IS_VALLEYVIEW(dev)) > vlv_update_pll(intel_crtc); > else > - i9xx_update_pll(intel_crtc, > - has_reduced_clock ? &reduced_clock : NULL, > - num_connectors); > + i9xx_update_pll(intel_crtc, has_reduced_clock ? &reduced_clock : NULL, > + num_connectors); > > /* Set up the display plane register */ > dspcntr = DISPPLANE_GAMMA_ENABLE; > @@ -8560,6 +8777,7 @@ static void intel_setup_outputs(struct drm_device *dev) > if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED) > intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B); > } > + vlv_init_dpio(dev); > } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { > bool found = false; > > @@ -9434,9 +9652,6 @@ void intel_modeset_cleanup(struct drm_device *dev) > > ironlake_teardown_rc6(dev); > > - if (IS_VALLEYVIEW(dev)) > - vlv_init_dpio(dev); > - > mutex_unlock(&dev->struct_mutex); > > /* Disable the irq before mode object teardown, for the irq might > -- > 1.7.10.4 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 66fb8dd..fb1a4fa 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -353,6 +353,8 @@ * 0x8100: fast clock controls * * DPIO is VLV only. + * + * Note: digital port B is DDI0, digital pot C is DDI1 */ #define DPIO_PKT (VLV_DISPLAY_BASE + 0x2100) #define DPIO_RID (0<<24) @@ -369,8 +371,20 @@ #define DPIO_SFR_BYPASS (1<<1) #define DPIO_RESET (1<<0) +#define _DPIO_TX3_SWING_CTL4_A 0x690 +#define _DPIO_TX3_SWING_CTL4_B 0x2a90 +#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX_SWING_CTL4_A, \ + _DPIO_TX3_SWING_CTL4_B) + +/* + * Per pipe/PLL DPIO regs + */ #define _DPIO_DIV_A 0x800c #define DPIO_POST_DIV_SHIFT (28) /* 3 bits */ +#define DPIO_POST_DIV_DAC 0 +#define DPIO_POST_DIV_HDMIDP 1 /* DAC 225-400M rate */ +#define DPIO_POST_DIV_LVDS1 2 +#define DPIO_POST_DIV_LVDS2 3 #define DPIO_K_SHIFT (24) /* 4 bits */ #define DPIO_P1_SHIFT (21) /* 3 bits */ #define DPIO_P2_SHIFT (16) /* 5 bits */ @@ -396,14 +410,111 @@ #define _DPIO_CORE_CLK_B 0x803c #define DPIO_CORE_CLK(pipe) _PIPE(pipe, _DPIO_CORE_CLK_A, _DPIO_CORE_CLK_B) +#define _DPIO_IREF_CTL_A 0x8040 +#define _DPIO_IREF_CTL_B 0x8060 +#define DPIO_IREF_CTL(pipe) _PIPE(pipe, _DPIO_IREF_CTL_A, _DPIO_IREF_CTL_B) + +#define DPIO_IREF_BCAST 0xc044 +#define _DPIO_IREF_A 0x8044 +#define _DPIO_IREF_B 0x8064 +#define DPIO_IREF(pipe) _PIPE(pipe, _DPIO_IREF_A, _DPIO_IREF_B) + +#define _DPIO_PLL_CML_A 0x804c +#define _DPIO_PLL_CML_B 0x806c +#define DPIO_PLL_CML(pipe) _PIPE(pipe, _DPIO_PLL_CML_A, _DPIO_PLL_CML_B) + #define _DPIO_LFP_COEFF_A 0x8048 #define _DPIO_LFP_COEFF_B 0x8068 #define DPIO_LFP_COEFF(pipe) _PIPE(pipe, _DPIO_LFP_COEFF_A, _DPIO_LFP_COEFF_B) +#define DPIO_CALIBRATION 0x80ac + #define DPIO_FASTCLK_DISABLE 0x8100 -#define DPIO_DATA_CHANNEL1 0x8220 -#define DPIO_DATA_CHANNEL2 0x8420 +/* + * Per DDI channel DPIO regs + */ + +#define _DPIO_PCS_TX_0 0x8200 +#define _DPIO_PCS_TX_1 0x8400 +#define DPIO_PCS_TX_LANE2_RESET (1<<16) +#define DPIO_PCS_TX_LANE1_RESET (1<<7) +#define DPIO_PCS_TX(port) _PORT(port, _DPIO_PCS_TX_0, _DPIO_PCS_TX_1) + +#define _DPIO_PCS_CLK_0 0x8204 +#define _DPIO_PCS_CLK_1 0x8404 +#define DPIO_PCS_CLK_CRI_RXEB_EIOS_EN (1<<22) +#define DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN (1<<21) +#define DPIO_PCS_CLK_DATAWIDTH_SHIFT (6) +#define DPIO_PCS_CLK_SOFT_RESET (1<<5) +#define DPIO_PCS_CLK(port) _PORT(port, _DPIO_PCS_CLK_0, _DPIO_PCS_CLK_1) + +#define _DPIO_PCS_CTL_OVR1_A 0x8224 +#define _DPIO_PCS_CTL_OVR1_B 0x8424 +#define DPIO_PCS_CTL_OVER1(port) _PORT(port, _DPIO_PCS_CTL_OVR1_A, \ + _DPIO_PCS_CTL_OVR1_B) + +#define _DPIO_PCS_STAGGER0_A 0x822c +#define _DPIO_PCS_STAGGER0_B 0x842c +#define DPIO_PCS_STAGGER0(port) _PORT(port, _DPIO_PCS_STAGGER0_A, \ + _DPIO_PCS_STAGGER0_B) + +#define _DPIO_PCS_STAGGER1_A 0x8230 +#define _DPIO_PCS_STAGGER1_B 0x8430 +#define DPIO_PCS_STAGGER1(port) _PORT(port, _DPIO_PCS_STAGGER1_A, \ + _DPIO_PCS_STAGGER1_B) + +#define _DPIO_PCS_CLOCKBUF0_A 0x8238 +#define _DPIO_PCS_CLOCKBUF0_B 0x8438 +#define DPIO_PCS_CLOCKBUF0(port) _PORT(port, _DPIO_PCS_CLOCKBUF0_A, \ + _DPIO_PCS_CLOCKBUF0_B) + +#define _DPIO_PCS_CLOCKBUF8_A 0x825c +#define _DPIO_PCS_CLOCKBUF8_B 0x845c +#define DPIO_PCS_CLOCKBUF8(port) _PORT(port, _DPIO_PCS_CLOCKBUF8_A, \ + _DPIO_PCS_CLOCKBUF8_B) + +#define _DPIO_TX_SWING_CTL2_A 0x8288 +#define _DPIO_TX_SWING_CTL2_B 0x8488 +#define DPIO_TX_SWING_CTL2(port) _PORT(port, _DPIO_TX_SWING_CTL2_A, \ + _DPIO_TX_SWING_CTL2_B) + +#define _DPIO_TX_SWING_CTL3_A 0x828c +#define _DPIO_TX_SWING_CTL3_B 0x848c +#define DPIO_TX_SWING_CTL3(port) _PORT(port, _DPIO_TX_SWING_CTL3_A, \ + _DPIO_TX_SWING_CTL3_B) + +#define _DPIO_TX_SWING_CTL4_A 0x8290 +#define _DPIO_TX_SWING_CTL4_B 0x8490 +#define DPIO_TX_SWING_CTL4(port) _PORT(port, _DPIO_TX_SWING_CTL4_A, \ + _DPIO_TX_SWING_CTL4_B) + +#define _DPIO_TX_OCALINIT_0 0x8294 +#define _DPIO_TX_OCALINIT_1 0x8494 +#define DPIO_TX_OCALINIT_EN (1<<31) +#define DPIO_TX_OCALINIT(port) _PORT(port, _DPIO_TX_OCALINIT_0, \ + _DPIO_TX_OCALINIT_1) + +#define _DPIO_TX_CTL_0 0x82ac +#define _DPIO_TX_CTL_1 0x84ac +#define DPIO_TX_CTL(port) _PORT(port, _DPIO_TX_CTL_0, _DPIO_TX_CTL_1) + +#define _DPIO_TX_LANE_0 0x82b8 +#define _DPIO_TX_LANE_1 0x84b8 +#define DPIO_TX_LANE(port) _PORT(port, _DPIO_TX_LANE_0, _DPIO_TX_LANE_1) + +#define _DPIO_DATA_CHANNEL1 0x8220 +#define _DPIO_DATA_CHANNEL2 0x8420 +#define DPIO_DATA_CHANNEL(port) _PORT(port, _DPIO_DATA_CHANNEL1, _DPIO_DATA_CHANNEL2) + +#define _DPIO_PORT0_PCS0 0x0220 +#define _DPIO_PORT0_PCS1 0x0420 +#define _DPIO_PORT1_PCS2 0x2620 +#define _DPIO_PORT1_PCS3 0x2820 +#define DPIO_DATA_LANE_A(port) _PORT(port, _DPIO_PORT0_PCS0, _DPIO_PORT1_PCS2) +#define DPIO_DATA_LANE_B(port) _PORT(port, _DPIO_PORT0_PCS1, _DPIO_PORT1_PCS3) +#define DPIO_DATA_CHANNEL1 0x8220 +#define DPIO_DATA_CHANNEL2 0x8420 /* * Fence registers @@ -965,7 +1076,10 @@ #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ #define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ #define DPLL_LOCK_VLV (1<<15) +#define DPLL_INTEGRATED_CRI_CLK_VLV (1<<14) #define DPLL_INTEGRATED_CLOCK_VLV (1<<13) +#define DPLL_PORTC_READY_MASK (0xf << 4) +#define DPLL_PORTB_READY_MASK (0xf) #define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 /* diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f3aa24f4..56c13b6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -404,14 +404,14 @@ static const intel_limit_t intel_limits_vlv_dac = { }; static const intel_limit_t intel_limits_vlv_hdmi = { - .dot = { .min = 25000, .max = 180000 }, - .vco = { .min = 4040000, .max = 5960000 }, - .n = { .min = 1, .max = 5 }, + .dot = { .min = 25000, .max = 270000 }, + .vco = { .min = 4000000, .max = 6000000 }, + .n = { .min = 1, .max = 7 }, .m = { .min = 60, .max = 300 }, /* guess */ .m1 = { .min = 2, .max = 3 }, - .m2 = { .min = 15, .max = 149 }, + .m2 = { .min = 11, .max = 156 }, .p = { .min = 10, .max = 30 }, - .p1 = { .min = 1, .max = 3 }, + .p1 = { .min = 2, .max = 3 }, .p2 = { .dot_limit = 270000, .p2_slow = 2, .p2_fast = 20 }, .find_pll = intel_vlv_find_best_pll, @@ -2591,7 +2591,6 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) DRM_ERROR("FDI train 2 fail!\n"); DRM_DEBUG_KMS("FDI train done\n"); - } static const int snb_b_fdi_train_param[] = { @@ -3694,6 +3693,117 @@ g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe) } } +static void vlv_pll_pre_enable(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock)); + + /* Assume eDP on port C and HDMI/DP on port B */ + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { + /* Program Tx lane resets to default */ + intel_dpio_write(dev_priv, DPIO_PCS_TX(0), + DPIO_PCS_TX_LANE2_RESET | + DPIO_PCS_TX_LANE1_RESET); + intel_dpio_write(dev_priv, DPIO_PCS_CLK(0), + DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | + DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | + (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) | + DPIO_PCS_CLK_SOFT_RESET); + + /* Fix up inter-pair skew failure */ + intel_dpio_write(dev_priv, DPIO_PCS_STAGGER1(0), 0x00750f00); + intel_dpio_write(dev_priv, DPIO_TX_CTL(0), 0x00001500); + intel_dpio_write(dev_priv, DPIO_TX_LANE(0), 0x40400000); + + intel_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(0), + 0x00002000); + intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(0), + DPIO_TX_OCALINIT_EN); + } + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || + intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { + /* Program Tx lane resets to default */ + intel_dpio_write(dev_priv, DPIO_PCS_TX(1), + DPIO_PCS_TX_LANE2_RESET | + DPIO_PCS_TX_LANE1_RESET); + intel_dpio_write(dev_priv, DPIO_PCS_CLK(1), + DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | + DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | + (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) | + DPIO_PCS_CLK_SOFT_RESET); + + /* Fix up inter-pair skew failure */ + intel_dpio_write(dev_priv, DPIO_PCS_STAGGER1(1), 0x00750f00); + intel_dpio_write(dev_priv, DPIO_TX_CTL(1), 0x00001500); + intel_dpio_write(dev_priv, DPIO_TX_LANE(1), 0x40400000); + } +} + +static void vlv_pll_post_enable(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + + WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock)); + + /* Assume eDP on port C and HDMI/DP on port B */ + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { + /* Enable clock channels for this port */ + u32 val; + val = intel_dpio_read(dev_priv, DPIO_DATA_LANE_A(0)); + val = 0; + if (pipe) + val |= (1<<21); + else + val &= ~(1<<21); + val |= 0x001000c4; + intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL(0), val); + + /* HDMI 1.0V-2dB */ + intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(0), 0); + intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(0), + 0x2b245f5f); + intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(0), + 0x5578b83a); + intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(0), + 0x0c782040); + intel_dpio_write(dev_priv, DPIO_TX3_SWING_CTL4(0), + 0x2b247878); + intel_dpio_write(dev_priv, DPIO_PCS_STAGGER0(0), 0x00030000); + intel_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(0), + 0x00002000); + intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(0), + DPIO_TX_OCALINIT_EN); + + /* Program lane clock */ + intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(0), + 0x00760018); + intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(0), + 0x00400888); + } + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || + intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { + u32 val; + val = intel_dpio_read(dev_priv, DPIO_DATA_LANE_A(1)); + val = 0; + if (pipe) + val |= (1<<21); + else + val &= ~(1<<21); + val |= 0x001000c4; + intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL(1), val); + + intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(1), + 0x00760018); + intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(1), + 0x00400888); + } +} + static void i9xx_crtc_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -3702,6 +3812,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) struct intel_encoder *encoder; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; + u32 port_mask; WARN_ON(!crtc->enabled); @@ -3711,12 +3822,44 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) intel_crtc->active = true; intel_update_watermarks(dev); + if (IS_VALLEYVIEW(dev)) { + mutex_lock(&dev_priv->dpio_lock); + vlv_pll_pre_enable(crtc); + mutex_unlock(&dev_priv->dpio_lock); + } + intel_enable_pll(dev_priv, pipe); + if (IS_VALLEYVIEW(dev)) { + mutex_lock(&dev_priv->dpio_lock); + vlv_pll_post_enable(crtc); + mutex_unlock(&dev_priv->dpio_lock); + } + for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->pre_enable) encoder->pre_enable(encoder); + for_each_encoder_on_crtc(dev, crtc, encoder) + encoder->enable(encoder); + + if (IS_VALLEYVIEW(dev)) { + char port; + + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || + intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { + port_mask = DPLL_PORTB_READY_MASK; + port = 'B'; + } else { + port_mask = DPLL_PORTC_READY_MASK; /* eDP on port C */ + port = 'C'; + } + + if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 1000)) + WARN(1, "timed out waiting for port %c ready: 0x%08x\n", + port, I915_READ(DPLL(0))); + } + intel_enable_pipe(dev_priv, pipe, false); intel_enable_plane(dev_priv, plane, pipe); if (IS_G4X(dev)) @@ -3728,9 +3871,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) /* Give the overlay scaler a chance to enable if it's on this pipe */ intel_crtc_dpms_overlay(intel_crtc, true); intel_crtc_update_cursor(crtc, true); - - for_each_encoder_on_crtc(dev, crtc, encoder) - encoder->enable(encoder); } static void i9xx_pfit_disable(struct intel_crtc *crtc) @@ -3782,6 +3922,27 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) i9xx_pfit_disable(intel_crtc); + for_each_encoder_on_crtc(dev, crtc, encoder) + if (encoder->post_disable) + encoder->post_disable(encoder); + + /* Reset lane for VLV platform*/ + if (IS_VALLEYVIEW(dev)) { + mutex_lock(&dev_priv->dpio_lock); + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { + intel_dpio_write(dev_priv, DPIO_PCS_TX(0), + 0x00000000); + intel_dpio_write(dev_priv, DPIO_PCS_CLK(0), + 0x00e00060); + } else { + intel_dpio_write(dev_priv, DPIO_PCS_TX(1), + 0x00000000); + intel_dpio_write(dev_priv, DPIO_PCS_CLK(1), + 0x00e00060); + } + mutex_unlock(&dev_priv->dpio_lock); + } + intel_disable_pll(dev_priv, pipe); intel_crtc->active = false; @@ -4012,7 +4173,7 @@ static bool intel_crtc_compute_config(struct drm_crtc *crtc, adjusted_mode->hsync_start == adjusted_mode->hdisplay) return false; - if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) && pipe_config->pipe_bpp > 10) { + if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) && pipe_config->pipe_bpp > 30) { pipe_config->pipe_bpp = 10*3; /* 12bpc is gen5+ */ } else if (INTEL_INFO(dev)->gen <= 4 && pipe_config->pipe_bpp > 8) { /* only a 8bpc pipe, with 6bpc dither through the panel fitter @@ -4224,6 +4385,34 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc, } } +static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv) +{ + u32 reg_val; + + /* + * PLLB opamp always calibrates to max value of 0x3f, force enable it + * and set it to a reasonable value instead. + */ + reg_val = intel_dpio_read(dev_priv, DPIO_IREF(1)); + reg_val &= 0xffffff00; + reg_val |= 0x00000030; + intel_dpio_write(dev_priv, DPIO_IREF(1), reg_val); + + reg_val = intel_dpio_read(dev_priv, DPIO_CALIBRATION); + reg_val &= 0x8cffffff; + reg_val = 0x8c000000; + intel_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val); + + reg_val = intel_dpio_read(dev_priv, DPIO_IREF(1)); + reg_val &= 0xffffff00; + intel_dpio_write(dev_priv, DPIO_IREF(1), reg_val); + + reg_val = intel_dpio_read(dev_priv, DPIO_CALIBRATION); + reg_val &= 0x00ffffff; + reg_val |= 0xb0000000; + intel_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val); +} + static void intel_dp_set_m_n(struct intel_crtc *crtc) { if (crtc->config.has_pch_encoder) @@ -4236,24 +4425,17 @@ static void vlv_update_pll(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_display_mode *adjusted_mode = + &crtc->config.adjusted_mode; int pipe = crtc->pipe; - u32 dpll, mdiv, pdiv; + u32 dpll, mdiv; u32 bestn, bestm1, bestm2, bestp1, bestp2; - bool is_sdvo; - u32 temp; + bool is_hdmi; + u32 coreclk, reg_val, temp; mutex_lock(&dev_priv->dpio_lock); - is_sdvo = intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_SDVO) || - intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI); - - dpll = DPLL_VGA_MODE_DIS; - dpll |= DPLL_EXT_BUFFER_ENABLE_VLV; - dpll |= DPLL_REFA_CLK_ENABLE_VLV; - dpll |= DPLL_INTEGRATED_CLOCK_VLV; - - I915_WRITE(DPLL(pipe), dpll); - POSTING_READ(DPLL(pipe)); + is_hdmi = intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI); bestn = crtc->config.dpll.n; bestm1 = crtc->config.dpll.m1; @@ -4261,70 +4443,106 @@ static void vlv_update_pll(struct intel_crtc *crtc) bestp1 = crtc->config.dpll.p1; bestp2 = crtc->config.dpll.p2; - /* - * In Valleyview PLL and program lane counter registers are exposed - * through DPIO interface - */ + /* See eDP HDMI DPIO driver vbios notes doc */ + + /* PLL B needs special handling */ + if (pipe) + vlv_pllb_recal_opamp(dev_priv); + + /* Set up Tx target for periodic Rcomp update */ + intel_dpio_write(dev_priv, DPIO_IREF_BCAST, 0x0100000f); + + /* Disable target IRef on PLL */ + reg_val = intel_dpio_read(dev_priv, DPIO_IREF_CTL(pipe)); + reg_val &= 0x00ffffff; + intel_dpio_write(dev_priv, DPIO_IREF_CTL(pipe), reg_val); + + vlv_pll_pre_enable(&crtc->base); + + /* Disable fast lock */ + intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x610); + + /* Set idtafcrecal before PLL is enabled */ mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK)); mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT)); mdiv |= ((bestn << DPIO_N_SHIFT)); - mdiv |= (1 << DPIO_POST_DIV_SHIFT); mdiv |= (1 << DPIO_K_SHIFT); + if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI) || + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) || + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) + mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT); + intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); + mdiv |= DPIO_ENABLE_CALIBRATION; intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); - intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), 0x01000000); + /* Set HBR and RBR LPF coefficients */ + if (adjusted_mode->clock == 162000 || + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI)) + intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), + 0x005f0021); + else + intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), + 0x00d0000f); + + if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) || + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) { + /* Use SSC source */ + if (!pipe) + intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), + 0x0df40000); + else + intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), + 0x0df70000); + } else { /* HDMI or VGA */ + /* Use bend source */ + if (!pipe) + intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), + 0x0df70000); + else + intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), + 0x0df40000); + } + + coreclk = intel_dpio_read(dev_priv, DPIO_CORE_CLK(pipe)); + coreclk = (coreclk & 0x0000ff00) | 0x01c00000; + if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) || + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) + coreclk |= 0x01000000; + intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), coreclk); - pdiv = (1 << DPIO_REFSEL_OVERRIDE) | (5 << DPIO_PLL_MODESEL_SHIFT) | - (3 << DPIO_BIAS_CURRENT_CTL_SHIFT) | (1<<20) | - (7 << DPIO_PLL_REFCLK_SEL_SHIFT) | (8 << DPIO_DRIVER_CTL_SHIFT) | - (5 << DPIO_CLK_BIAS_CTL_SHIFT); - intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), pdiv); + intel_dpio_write(dev_priv, DPIO_PLL_CML(pipe), 0x87871000); - intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), 0x005f003b); + /* Enable DPIO clock input */ + dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV | + DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV; + if (pipe) + dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; dpll |= DPLL_VCO_ENABLE; I915_WRITE(DPLL(pipe), dpll); POSTING_READ(DPLL(pipe)); + udelay(150); + if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1)) DRM_ERROR("DPLL %d failed to lock\n", pipe); - intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x620); - - if (crtc->config.has_dp_encoder) - intel_dp_set_m_n(crtc); - - I915_WRITE(DPLL(pipe), dpll); + vlv_pll_post_enable(&crtc->base); - /* Wait for the clocks to stabilize. */ - POSTING_READ(DPLL(pipe)); - udelay(150); - - temp = 0; - if (is_sdvo) { + if (is_hdmi) { temp = 0; if (crtc->config.pixel_multiplier > 1) { temp = (crtc->config.pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; } - } - I915_WRITE(DPLL_MD(pipe), temp); - POSTING_READ(DPLL_MD(pipe)); - /* Now program lane control registers */ - if(intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) - || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI)) { - temp = 0x1000C4; - if(pipe == 1) - temp |= (1 << 21); - intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL1, temp); + I915_WRITE(DPLL_MD(pipe), temp); + POSTING_READ(DPLL_MD(pipe)); } - if(intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) { - temp = 0x1000C4; - if(pipe == 1) - temp |= (1 << 21); - intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL2, temp); + if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) || + intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) { + intel_dp_set_m_n(crtc); } mutex_unlock(&dev_priv->dpio_lock); @@ -4713,9 +4931,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, else if (IS_VALLEYVIEW(dev)) vlv_update_pll(intel_crtc); else - i9xx_update_pll(intel_crtc, - has_reduced_clock ? &reduced_clock : NULL, - num_connectors); + i9xx_update_pll(intel_crtc, has_reduced_clock ? &reduced_clock : NULL, + num_connectors); /* Set up the display plane register */ dspcntr = DISPPLANE_GAMMA_ENABLE; @@ -8560,6 +8777,7 @@ static void intel_setup_outputs(struct drm_device *dev) if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED) intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B); } + vlv_init_dpio(dev); } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { bool found = false; @@ -9434,9 +9652,6 @@ void intel_modeset_cleanup(struct drm_device *dev) ironlake_teardown_rc6(dev); - if (IS_VALLEYVIEW(dev)) - vlv_init_dpio(dev); - mutex_unlock(&dev->struct_mutex); /* Disable the irq before mode object teardown, for the irq might