From d59f9f4d68ca82985a3b4578caa0485a9cb2b71b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 11 Apr 2013 16:29:07 +0200 Subject: drm/i915: don't enable the plane too early in i9xx_crtc_mode_set This is horrible lore and we should be able to get rid of it now that the lvds/pfit handling code actually does the right thing. Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6e423e04c35..8b1cfc92849 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4733,8 +4733,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, i9xx_set_pipeconf(intel_crtc); - intel_enable_pipe(dev_priv, pipe, false); - intel_wait_for_vblank(dev, pipe); I915_WRITE(DSPCNTR(plane), dspcntr); -- cgit v1.2.3-18-g5258 From 4667730163a6d0afb04cefae9805ca1cdad1df46 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 11 Apr 2013 16:29:08 +0200 Subject: drm/i915: drop redundant vblank waits Just blows through 50ms for naught, since the pipe is off. Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8b1cfc92849..5a904ddbb0d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4733,8 +4733,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, i9xx_set_pipeconf(intel_crtc); - intel_wait_for_vblank(dev, pipe); - I915_WRITE(DSPCNTR(plane), dspcntr); POSTING_READ(DSPCNTR(plane)); @@ -5704,8 +5702,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ironlake_set_pipeconf(crtc, adjusted_mode, dither); - intel_wait_for_vblank(dev, pipe); - /* Set up the display plane register */ I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE); POSTING_READ(DSPCNTR(plane)); -- cgit v1.2.3-18-g5258 From 58c6eaa24dbd8c97ef5f643324f087271aa79d64 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 11 Apr 2013 16:29:09 +0200 Subject: drm/i915: add pipe asserts for the crtc enable sequence The i9xx modeset sequence is currently pretty fishy, so tight it all up with some good assert-sprinkling. We already have good coverage on the disable side, but the enable side is spotty (since until recently it was wrong). Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5a904ddbb0d..62fd5eae61c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1474,6 +1474,8 @@ static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) int reg; u32 val; + assert_pipe_disabled(dev_priv, pipe); + /* No really, not for ILK+ */ BUG_ON(!IS_VALLEYVIEW(dev_priv->dev) && dev_priv->info->gen >= 5); @@ -1835,6 +1837,9 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, int reg; u32 val; + assert_planes_disabled(dev_priv, pipe); + assert_sprites_disabled(dev_priv, pipe); + if (HAS_PCH_LPT(dev_priv->dev)) pch_transcoder = TRANSCODER_A; else -- cgit v1.2.3-18-g5258 From e29a18faaa18470f313b570fdf2d0f75c35e6cb2 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 11 Apr 2013 16:29:10 +0200 Subject: drm/i915: add i9xx pfit pipe asserts We can only enable the pfit if the pipe is disabled. Ensure that this is obeyed with a neat assert. Also check whether the pfit is off before enabling it - if not we've lost track of things somewhere since the pfit is only ever used by the lvds output. v2: Fix spell fail in the commit message pointed out by Ville&Jani. Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lvds.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index f36f1baabd5..563f5052fcf 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -159,6 +159,9 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder) if (HAS_PCH_SPLIT(dev) || !enc->pfit_control) return; + WARN_ON(I915_READ(PFIT_CONTROL) & PFIT_ENABLE); + assert_pipe_disabled(dev_priv, to_intel_crtc(encoder->base.crtc)->pipe); + /* * Enable automatic panel scaling so that non-native modes * fill the screen. The panel fitter should only be -- cgit v1.2.3-18-g5258 From e3641d3f77bb9aea8442dc25018d651d3a348d76 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 11 Apr 2013 19:49:07 +0200 Subject: drm/i915: move debug output back to the right place When adding the pipe config computation step I've accidentally moved this a bit away. Which momentarily confused me since the pipe config step rejected some modesetting operations I expected and so left me looking in vain for that debug output. v2: Move the debug output into the right function to prevent this from happening again. v3: Make it compile (Ville). Also reorder the patch so that the two bugfixes are first. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 62fd5eae61c..ae7c3779bae 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7744,6 +7744,9 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes, */ *modeset_pipes &= 1 << intel_crtc->pipe; *prepare_pipes &= 1 << intel_crtc->pipe; + + DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n", + *modeset_pipes, *prepare_pipes, *disable_pipes); } static bool intel_crtc_in_use(struct drm_crtc *crtc) @@ -7974,9 +7977,6 @@ static int __intel_set_mode(struct drm_crtc *crtc, } } - DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n", - modeset_pipes, prepare_pipes, disable_pipes); - for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc) intel_crtc_disable(&intel_crtc->base); -- cgit v1.2.3-18-g5258 From 2582a8504dbdc80b6e16ac8dfd6a7f9d03bece73 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 17 Apr 2013 17:48:47 +0300 Subject: drm/i915: Use pipe_name() and port_name() where appropriate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get rid of the few remaining open coded copies of pipe_name() and port_name(). Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ae7c3779bae..462c81a871a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4723,7 +4723,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, dspcntr |= DISPPLANE_SEL_PIPE_B; } - DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); + DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe_name(pipe)); drm_mode_debug_printmodeline(mode); intel_set_pipe_timings(intel_crtc, mode, adjusted_mode); @@ -6109,7 +6109,7 @@ static void ironlake_write_eld(struct drm_connector *connector, eldv |= IBX_ELD_VALIDB << 4; eldv |= IBX_ELD_VALIDB << 8; } else { - DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i); + DRM_DEBUG_DRIVER("ELD on port %c\n", port_name(i)); eldv = IBX_ELD_VALIDB << ((i - 1) * 4); } -- cgit v1.2.3-18-g5258 From cfc33bf75bfbf8f95bffe040ee1a5ab1cda8c34c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 17 Apr 2013 17:48:48 +0300 Subject: drm/i915: Use port_name() in PCH port audio power change message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 0aa2ef0d2ae..3af983fad67 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -763,10 +763,12 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir) ibx_hpd_irq_setup(dev); queue_work(dev_priv->wq, &dev_priv->hotplug_work); } - if (pch_iir & SDE_AUDIO_POWER_MASK) + if (pch_iir & SDE_AUDIO_POWER_MASK) { + int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >> + SDE_AUDIO_POWER_SHIFT); DRM_DEBUG_DRIVER("PCH audio power change on port %d\n", - (pch_iir & SDE_AUDIO_POWER_MASK) >> - SDE_AUDIO_POWER_SHIFT); + port_name(port)); + } if (pch_iir & SDE_AUX_MASK) dp_aux_irq_handler(dev); @@ -812,10 +814,12 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) ibx_hpd_irq_setup(dev); queue_work(dev_priv->wq, &dev_priv->hotplug_work); } - if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) - DRM_DEBUG_DRIVER("PCH audio power change on port %d\n", - (pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> - SDE_AUDIO_POWER_SHIFT_CPT); + if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) { + int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> + SDE_AUDIO_POWER_SHIFT_CPT); + DRM_DEBUG_DRIVER("PCH audio power change on port %c\n", + port_name(port)); + } if (pch_iir & SDE_AUX_MASK_CPT) dp_aux_irq_handler(dev); -- cgit v1.2.3-18-g5258 From 84f44ce795b3da9a08dc2041ecd60550d34c123e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 17 Apr 2013 17:48:49 +0300 Subject: drm/i915: Print plane, pipe, port names as alphabetical insted of decimal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Alway use the alphabetical names in debug/error messages for planes, pipes and ports, instead of using decimal numbers occasionally. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 10 ++++----- drivers/gpu/drm/i915/intel_display.c | 42 ++++++++++++++++++------------------ drivers/gpu/drm/i915/intel_pm.c | 26 +++++++++++----------- 3 files changed, 39 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 26a0a570f92..e14fe5f569e 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -748,8 +748,8 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc) } if (num_encoders != 1) - WARN(1, "%d encoders on crtc for pipe %d\n", num_encoders, - intel_crtc->pipe); + WARN(1, "%d encoders on crtc for pipe %c\n", num_encoders, + pipe_name(intel_crtc->pipe)); BUG_ON(ret == NULL); return ret; @@ -1047,8 +1047,8 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) } } else { - WARN(1, "Invalid encoder type %d for pipe %d\n", - intel_encoder->type, pipe); + WARN(1, "Invalid encoder type %d for pipe %c\n", + intel_encoder->type, pipe_name(pipe)); } I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp); @@ -1148,7 +1148,7 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder, } } - DRM_DEBUG_KMS("No pipe for ddi port %i found\n", port); + DRM_DEBUG_KMS("No pipe for ddi port %c found\n", port_name(port)); return false; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 462c81a871a..e472488394a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2101,7 +2101,7 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, case 1: break; default: - DRM_ERROR("Can't update plane %d in SAREA\n", plane); + DRM_ERROR("Can't update plane %c in SAREA\n", plane_name(plane)); return -EINVAL; } @@ -2198,7 +2198,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc, case 2: break; default: - DRM_ERROR("Can't update plane %d in SAREA\n", plane); + DRM_ERROR("Can't update plane %c in SAREA\n", plane_name(plane)); return -EINVAL; } @@ -2389,9 +2389,9 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, } if (intel_crtc->plane > INTEL_INFO(dev)->num_pipes) { - DRM_ERROR("no plane for crtc: plane %d, num_pipes %d\n", - intel_crtc->plane, - INTEL_INFO(dev)->num_pipes); + DRM_ERROR("no plane for crtc: plane %c, num_pipes %d\n", + plane_name(intel_crtc->plane), + INTEL_INFO(dev)->num_pipes); return -EINVAL; } @@ -3299,7 +3299,7 @@ static struct intel_pch_pll *intel_get_pch_pll(struct intel_crtc *intel_crtc, u3 found: intel_crtc->pch_pll = pll; pll->refcount++; - DRM_DEBUG_DRIVER("using pll %d for pipe %d\n", i, intel_crtc->pipe); + DRM_DEBUG_DRIVER("using pll %d for pipe %c\n", i, pipe_name(intel_crtc->pipe)); prepare: /* separate function? */ DRM_DEBUG_DRIVER("switching PLL %x off\n", pll->pll_reg); @@ -3324,7 +3324,7 @@ void intel_cpt_verify_modeset(struct drm_device *dev, int pipe) udelay(500); if (wait_for(I915_READ(dslreg) != temp, 5)) { if (wait_for(I915_READ(dslreg) != temp, 5)) - DRM_ERROR("mode set failed: pipe %d stuck\n", pipe); + DRM_ERROR("mode set failed: pipe %c stuck\n", pipe_name(pipe)); } } @@ -5344,11 +5344,11 @@ static bool ironlake_check_fdi_lanes(struct intel_crtc *intel_crtc) struct intel_crtc *pipe_B_crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]); - DRM_DEBUG_KMS("checking fdi config on pipe %i, lanes %i\n", - intel_crtc->pipe, intel_crtc->fdi_lanes); + DRM_DEBUG_KMS("checking fdi config on pipe %c, lanes %i\n", + pipe_name(intel_crtc->pipe), intel_crtc->fdi_lanes); if (intel_crtc->fdi_lanes > 4) { - DRM_DEBUG_KMS("invalid fdi lane config on pipe %i: %i lanes\n", - intel_crtc->pipe, intel_crtc->fdi_lanes); + DRM_DEBUG_KMS("invalid fdi lane config on pipe %c: %i lanes\n", + pipe_name(intel_crtc->pipe), intel_crtc->fdi_lanes); /* Clamp lanes to avoid programming the hw with bogus values. */ intel_crtc->fdi_lanes = 4; @@ -5364,8 +5364,8 @@ static bool ironlake_check_fdi_lanes(struct intel_crtc *intel_crtc) case PIPE_B: if (dev_priv->pipe_to_crtc_mapping[PIPE_C]->enabled && intel_crtc->fdi_lanes > 2) { - DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %i: %i lanes\n", - intel_crtc->pipe, intel_crtc->fdi_lanes); + DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n", + pipe_name(intel_crtc->pipe), intel_crtc->fdi_lanes); /* Clamp lanes to avoid programming the hw with bogus values. */ intel_crtc->fdi_lanes = 2; @@ -5381,8 +5381,8 @@ static bool ironlake_check_fdi_lanes(struct intel_crtc *intel_crtc) case PIPE_C: if (!pipe_B_crtc->base.enabled || pipe_B_crtc->fdi_lanes <= 2) { if (intel_crtc->fdi_lanes > 2) { - DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %i: %i lanes\n", - intel_crtc->pipe, intel_crtc->fdi_lanes); + DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n", + pipe_name(intel_crtc->pipe), intel_crtc->fdi_lanes); /* Clamp lanes to avoid programming the hw with bogus values. */ intel_crtc->fdi_lanes = 2; @@ -5647,7 +5647,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, dpll = ironlake_compute_dpll(intel_crtc, &clock, &fp, &reduced_clock, has_reduced_clock ? &fp2 : NULL); - DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe); + DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe_name(pipe)); drm_mode_debug_printmodeline(mode); /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */ @@ -5656,8 +5656,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, pll = intel_get_pch_pll(intel_crtc, dpll, fp); if (pll == NULL) { - DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n", - pipe); + DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", + pipe_name(pipe)); return -EINVAL; } } else @@ -5821,7 +5821,7 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc, /* determine panel color depth */ dither = intel_crtc->config.dither; - DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe); + DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe_name(pipe)); drm_mode_debug_printmodeline(mode); if (intel_crtc->config.has_dp_encoder) @@ -9051,8 +9051,8 @@ void intel_modeset_init(struct drm_device *dev) for (j = 0; j < dev_priv->num_plane; j++) { ret = intel_plane_init(dev, i, j); if (ret) - DRM_DEBUG_KMS("pipe %d plane %d init failed: %d\n", - i, j, ret); + DRM_DEBUG_KMS("pipe %c plane %d init failed: %d\n", + pipe_name(i), j, ret); } } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e34ad964251..413877d4afe 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -113,8 +113,8 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) fbc_ctl |= obj->fence_reg; I915_WRITE(FBC_CONTROL, fbc_ctl); - DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ", - cfb_pitch, crtc->y, intel_crtc->plane); + DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %c, ", + cfb_pitch, crtc->y, plane_name(intel_crtc->plane)); } static bool i8xx_fbc_enabled(struct drm_device *dev) @@ -148,7 +148,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) /* enable it... */ I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN); - DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); + DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane)); } static void g4x_disable_fbc(struct drm_device *dev) @@ -228,7 +228,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) sandybridge_blit_fbc_update(dev); } - DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); + DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane)); } static void ironlake_disable_fbc(struct drm_device *dev) @@ -2146,15 +2146,15 @@ static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe, &sandybridge_display_wm_info, latency, &sprite_wm); if (!ret) { - DRM_DEBUG_KMS("failed to compute sprite wm for pipe %d\n", - pipe); + DRM_DEBUG_KMS("failed to compute sprite wm for pipe %c\n", + pipe_name(pipe)); return; } val = I915_READ(reg); val &= ~WM0_PIPE_SPRITE_MASK; I915_WRITE(reg, val | (sprite_wm << WM0_PIPE_SPRITE_SHIFT)); - DRM_DEBUG_KMS("sprite watermarks For pipe %d - %d\n", pipe, sprite_wm); + DRM_DEBUG_KMS("sprite watermarks For pipe %c - %d\n", pipe_name(pipe), sprite_wm); ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, @@ -2163,8 +2163,8 @@ static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe, SNB_READ_WM1_LATENCY() * 500, &sprite_wm); if (!ret) { - DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %d\n", - pipe); + DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %c\n", + pipe_name(pipe)); return; } I915_WRITE(WM1S_LP_ILK, sprite_wm); @@ -2179,8 +2179,8 @@ static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe, SNB_READ_WM2_LATENCY() * 500, &sprite_wm); if (!ret) { - DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %d\n", - pipe); + DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %c\n", + pipe_name(pipe)); return; } I915_WRITE(WM2S_LP_IVB, sprite_wm); @@ -2191,8 +2191,8 @@ static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe, SNB_READ_WM3_LATENCY() * 500, &sprite_wm); if (!ret) { - DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %d\n", - pipe); + DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %c\n", + pipe_name(pipe)); return; } I915_WRITE(WM3S_LP_IVB, sprite_wm); -- cgit v1.2.3-18-g5258 From 4bb6f1f3270923cdcd57293ea736955d5c35db72 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 17 Apr 2013 17:48:50 +0300 Subject: drm/i915: Use alphabetical names for transcoders too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print the alphabetical name for transcoders. The code already used the pipe_name() macro for transcoders, so I did the same. But we do have the (unused) transcoder_name() macro which could be used instead. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e472488394a..81ae89b9c79 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1097,14 +1097,14 @@ static void assert_pch_pll(struct drm_i915_private *dev_priv, pch_dpll = I915_READ(PCH_DPLL_SEL); cur_state = pll->pll_reg == _PCH_DPLL_B; if (!WARN(((pch_dpll >> (4 * crtc->pipe)) & 1) != cur_state, - "PLL[%d] not attached to this transcoder %d: %08x\n", - cur_state, crtc->pipe, pch_dpll)) { + "PLL[%d] not attached to this transcoder %c: %08x\n", + cur_state, pipe_name(crtc->pipe), pch_dpll)) { cur_state = !!(val >> (4*crtc->pipe + 3)); WARN(cur_state != state, - "PLL[%d] not %s on this transcoder %d: %08x\n", + "PLL[%d] not %s on this transcoder %c: %08x\n", pll->pll_reg == _PCH_DPLL_B, state_string(state), - crtc->pipe, + pipe_name(crtc->pipe), val); } } @@ -1733,7 +1733,7 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, I915_WRITE(reg, val | TRANS_ENABLE); if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100)) - DRM_ERROR("failed to enable transcoder %d\n", pipe); + DRM_ERROR("failed to enable transcoder %c\n", pipe_name(pipe)); } static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv, @@ -1786,7 +1786,7 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv, I915_WRITE(reg, val); /* wait for PCH transcoder off, transcoder state */ if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50)) - DRM_ERROR("failed to disable transcoder %d\n", pipe); + DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe)); if (!HAS_PCH_IBX(dev)) { /* Workaround: Clear the timing override chicken bit again. */ -- cgit v1.2.3-18-g5258 From 06da8da2b014d6cc98fa86e72b605e525e6d6884 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 17 Apr 2013 17:48:51 +0300 Subject: drm/i915: Use alphabetical names for sprites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add sprite_name() macro which should be used with the kind of sprites that are fixed to pipes (gen4.5+). Also use dev_priv->num_plane to calculate the sprite index insted assuming two sprites per pipe. This should make it print the right name. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_display.c | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d5dcf7fe1ee..15d0a3a8f31 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -76,6 +76,8 @@ enum plane { }; #define plane_name(p) ((p) + 'A') +#define sprite_name(p, s) ((p) * dev_priv->num_plane + (s) + 'A') + enum port { PORT_A = 0, PORT_B, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 81ae89b9c79..02faba0263d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1302,8 +1302,8 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv, reg = SPCNTR(pipe, i); val = I915_READ(reg); WARN((val & SP_ENABLE), - "sprite %d assertion failure, should be off on pipe %c but is still active\n", - pipe * 2 + i, pipe_name(pipe)); + "sprite %c assertion failure, should be off on pipe %c but is still active\n", + sprite_name(pipe, i), pipe_name(pipe)); } } @@ -9051,8 +9051,8 @@ void intel_modeset_init(struct drm_device *dev) for (j = 0; j < dev_priv->num_plane; j++) { ret = intel_plane_init(dev, i, j); if (ret) - DRM_DEBUG_KMS("pipe %c plane %d init failed: %d\n", - pipe_name(i), j, ret); + DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n", + pipe_name(i), sprite_name(i, j), ret); } } -- cgit v1.2.3-18-g5258 From 855ba3be12badf6228151ca3ccf54632cfdd463d Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 17 Apr 2013 15:54:57 -0700 Subject: drm/i915: VLV GPU frequency to opcode functions When requesting frequency changes or querying status from the Punit, we need to use an opcode that corresponds to the frequency, taking into account the memory frequency. Signed-off-by: Jesse Barnes Acked-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 56 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 15d0a3a8f31..abb065502de 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1887,6 +1887,8 @@ int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val) int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val); int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val); int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val); +int vlv_gpu_freq(int ddr_freq, int val); +int vlv_freq_opcode(int ddr_freq, int val); #define __i915_read(x, y) \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 413877d4afe..f802368e8e9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4620,3 +4620,59 @@ int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val) { return vlv_punit_rw(dev_priv, PUNIT_OPCODE_REG_WRITE, addr, &val); } + +int vlv_gpu_freq(int ddr_freq, int val) +{ + int mult, base; + + switch (ddr_freq) { + case 800: + mult = 20; + base = 120; + break; + case 1066: + mult = 22; + base = 133; + break; + case 1333: + mult = 21; + base = 125; + break; + default: + return -1; + } + + return ((val - 0xbd) * mult) + base; +} + +int vlv_freq_opcode(int ddr_freq, int val) +{ + int mult, base; + + switch (ddr_freq) { + case 800: + mult = 20; + base = 120; + break; + case 1066: + mult = 22; + base = 133; + break; + case 1333: + mult = 21; + base = 125; + break; + default: + return -1; + } + + val /= mult; + val -= base / mult; + val += 0xbd; + + if (val > 0xea) + val = 0xea; + + return val; +} + -- cgit v1.2.3-18-g5258 From 0a073b843bcd9a660f76e497182aac97cafddc4c Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 17 Apr 2013 15:54:58 -0700 Subject: drm/i915: turbo & RC6 support for VLV v7 Uses slightly different interfaces than other platforms. v2: track actual set freq, not requested (Rohit) fix debug prints in init code (Jesse) v3: don't write sleep reg (Jesse) re-add RC6 wake limit write (Ben) fixup thresholds to match other platforms (Ben) clean up mem freq calculation (Ben) clean up debug prints (Ben) v4: move defines from punit patch (Ville) v5: remove writes to nonexistent regs (Jesse) put RP and RC regs together (Jesse) fix RC6 enable (Jesse) v6: use correct fuse reads from NC (Jesse) split out min/max funcs for use in sysfs (Jesse) add debugfs & sysfs freq controls (Jesse) v7: update with Ben's hw_max changes (Jesse) Signed-off-by: Jesse Barnes Reviewed-by: Ben Widawsky (v6) [danvet: Follow checkpatch sugggestion to use min_t to avoid casting fun.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 58 +++++++++-- drivers/gpu/drm/i915/i915_drv.h | 5 + drivers/gpu/drm/i915/i915_irq.c | 5 +- drivers/gpu/drm/i915/i915_reg.h | 21 ++++ drivers/gpu/drm/i915/i915_sysfs.c | 71 +++++++++---- drivers/gpu/drm/i915/intel_pm.c | 199 ++++++++++++++++++++++++++++++++++-- 6 files changed, 320 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e913d325d5b..367b534d226 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -941,7 +941,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) MEMSTAT_VID_SHIFT); seq_printf(m, "Current P-state: %d\n", (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT); - } else if (IS_GEN6(dev) || IS_GEN7(dev)) { + } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS); u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); @@ -1009,6 +1009,25 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) seq_printf(m, "Max overclocked frequency: %dMHz\n", dev_priv->rps.hw_max * GT_FREQUENCY_MULTIPLIER); + } else if (IS_VALLEYVIEW(dev)) { + u32 freq_sts, val; + + valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, + &freq_sts); + seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); + seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq); + + valleyview_punit_read(dev_priv, PUNIT_FUSE_BUS1, &val); + seq_printf(m, "max GPU freq: %d MHz\n", + vlv_gpu_freq(dev_priv->mem_freq, val)); + + valleyview_punit_read(dev_priv, PUNIT_REG_GPU_LFM, &val); + seq_printf(m, "min GPU freq: %d MHz\n", + vlv_gpu_freq(dev_priv->mem_freq, val)); + + seq_printf(m, "current GPU freq: %d MHz\n", + vlv_gpu_freq(dev_priv->mem_freq, + (freq_sts >> 8) & 0xff)); } else { seq_printf(m, "no P-state info available\n"); } @@ -1812,7 +1831,11 @@ i915_max_freq_get(void *data, u64 *val) if (ret) return ret; - *val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; + if (IS_VALLEYVIEW(dev)) + *val = vlv_gpu_freq(dev_priv->mem_freq, + dev_priv->rps.max_delay); + else + *val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; mutex_unlock(&dev_priv->rps.hw_lock); return 0; @@ -1837,9 +1860,16 @@ i915_max_freq_set(void *data, u64 val) /* * Turbo will still be enabled, but won't go above the set value. */ - do_div(val, GT_FREQUENCY_MULTIPLIER); - dev_priv->rps.max_delay = val; - gen6_set_rps(dev, val); + if (IS_VALLEYVIEW(dev)) { + val = vlv_freq_opcode(dev_priv->mem_freq, val); + dev_priv->rps.max_delay = val; + gen6_set_rps(dev, val); + } else { + do_div(val, GT_FREQUENCY_MULTIPLIER); + dev_priv->rps.max_delay = val; + gen6_set_rps(dev, val); + } + mutex_unlock(&dev_priv->rps.hw_lock); return 0; @@ -1863,7 +1893,11 @@ i915_min_freq_get(void *data, u64 *val) if (ret) return ret; - *val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; + if (IS_VALLEYVIEW(dev)) + *val = vlv_gpu_freq(dev_priv->mem_freq, + dev_priv->rps.min_delay); + else + *val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; mutex_unlock(&dev_priv->rps.hw_lock); return 0; @@ -1888,9 +1922,15 @@ i915_min_freq_set(void *data, u64 val) /* * Turbo will still be enabled, but won't go below the set value. */ - do_div(val, GT_FREQUENCY_MULTIPLIER); - dev_priv->rps.min_delay = val; - gen6_set_rps(dev, val); + if (IS_VALLEYVIEW(dev)) { + val = vlv_freq_opcode(dev_priv->mem_freq, val); + dev_priv->rps.min_delay = val; + valleyview_set_rps(dev, val); + } else { + do_div(val, GT_FREQUENCY_MULTIPLIER); + dev_priv->rps.min_delay = val; + gen6_set_rps(dev, val); + } mutex_unlock(&dev_priv->rps.hw_lock); return 0; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index abb065502de..bd2d7f17393 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1856,6 +1856,9 @@ extern void intel_disable_fbc(struct drm_device *dev); extern bool ironlake_set_drps(struct drm_device *dev, u8 val); extern void intel_init_pch_refclk(struct drm_device *dev); extern void gen6_set_rps(struct drm_device *dev, u8 val); +extern void valleyview_set_rps(struct drm_device *dev, u8 val); +extern int valleyview_rps_max_freq(struct drm_i915_private *dev_priv); +extern int valleyview_rps_min_freq(struct drm_i915_private *dev_priv); extern void intel_detect_pch(struct drm_device *dev); extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); extern int intel_enable_rc6(const struct drm_device *dev); @@ -1887,6 +1890,8 @@ int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val) int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val); int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val); int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val); +int valleyview_nc_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val); + int vlv_gpu_freq(int ddr_freq, int val); int vlv_freq_opcode(int ddr_freq, int val); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 3af983fad67..932e7f8b6d5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -482,7 +482,10 @@ static void gen6_pm_rps_work(struct work_struct *work) */ if (!(new_delay > dev_priv->rps.max_delay || new_delay < dev_priv->rps.min_delay)) { - gen6_set_rps(dev_priv->dev, new_delay); + if (IS_VALLEYVIEW(dev_priv->dev)) + valleyview_set_rps(dev_priv->dev, new_delay); + else + gen6_set_rps(dev_priv->dev, new_delay); } mutex_unlock(&dev_priv->rps.hw_lock); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 31de7e4b1f3..66fb8dd2822 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4315,6 +4315,7 @@ #define GEN6_RC_CTL_RC6_ENABLE (1<<18) #define GEN6_RC_CTL_RC1e_ENABLE (1<<20) #define GEN6_RC_CTL_RC7_ENABLE (1<<22) +#define GEN7_RC_CTL_TO_MODE (1<<28) #define GEN6_RC_CTL_EI_MODE(x) ((x)<<27) #define GEN6_RC_CTL_HW_ENABLE (1<<31) #define GEN6_RP_DOWN_TIMEOUT 0xA010 @@ -4406,12 +4407,32 @@ #define IOSF_BAR_SHIFT 1 #define IOSF_SB_BUSY (1<<0) #define IOSF_PORT_PUNIT 0x4 +#define IOSF_PORT_NC 0x11 #define VLV_IOSF_DATA 0x182104 #define VLV_IOSF_ADDR 0x182108 #define PUNIT_OPCODE_REG_READ 6 #define PUNIT_OPCODE_REG_WRITE 7 +#define PUNIT_REG_GPU_LFM 0xd3 +#define PUNIT_REG_GPU_FREQ_REQ 0xd4 +#define PUNIT_REG_GPU_FREQ_STS 0xd8 +#define PUNIT_REG_MEDIA_TURBO_FREQ_REQ 0xdc + +#define PUNIT_FUSE_BUS2 0xf6 /* bits 47:40 */ +#define PUNIT_FUSE_BUS1 0xf5 /* bits 55:48 */ + +#define IOSF_NC_FB_GFX_FREQ_FUSE 0x1c +#define FB_GFX_MAX_FREQ_FUSE_SHIFT 3 +#define FB_GFX_MAX_FREQ_FUSE_MASK 0x000007f8 +#define FB_GFX_FGUARANTEED_FREQ_FUSE_SHIFT 11 +#define FB_GFX_FGUARANTEED_FREQ_FUSE_MASK 0x0007f800 +#define IOSF_NC_FB_GFX_FMAX_FUSE_HI 0x34 +#define FB_FMAX_VMIN_FREQ_HI_MASK 0x00000007 +#define IOSF_NC_FB_GFX_FMAX_FUSE_LO 0x30 +#define FB_FMAX_VMIN_FREQ_LO_SHIFT 27 +#define FB_FMAX_VMIN_FREQ_LO_MASK 0xf8000000 + #define GEN6_GT_CORE_STATUS 0x138060 #define GEN6_CORE_CPD_STATE_MASK (7<<4) #define GEN6_RCn_MASK 7 diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index d5e1890678f..ca00df2de07 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -212,7 +212,10 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev, int ret; mutex_lock(&dev_priv->rps.hw_lock); - ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER; + if (IS_VALLEYVIEW(dev_priv->dev)) + ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.cur_delay); + else + ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER; mutex_unlock(&dev_priv->rps.hw_lock); return snprintf(buf, PAGE_SIZE, "%d\n", ret); @@ -226,7 +229,10 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute int ret; mutex_lock(&dev_priv->rps.hw_lock); - ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; + if (IS_VALLEYVIEW(dev_priv->dev)) + ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.max_delay); + else + ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; mutex_unlock(&dev_priv->rps.hw_lock); return snprintf(buf, PAGE_SIZE, "%d\n", ret); @@ -246,16 +252,25 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, if (ret) return ret; - val /= GT_FREQUENCY_MULTIPLIER; - mutex_lock(&dev_priv->rps.hw_lock); - rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); - hw_max = dev_priv->rps.hw_max; - non_oc_max = (rp_state_cap & 0xff); - hw_min = ((rp_state_cap & 0xff0000) >> 16); + if (IS_VALLEYVIEW(dev_priv->dev)) { + val = vlv_freq_opcode(dev_priv->mem_freq, val); + + hw_max = valleyview_rps_max_freq(dev_priv); + hw_min = valleyview_rps_min_freq(dev_priv); + non_oc_max = hw_max; + } else { + val /= GT_FREQUENCY_MULTIPLIER; - if (val < hw_min || val > hw_max || val < dev_priv->rps.min_delay) { + rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); + hw_max = dev_priv->rps.hw_max; + non_oc_max = (rp_state_cap & 0xff); + hw_min = ((rp_state_cap & 0xff0000) >> 16); + } + + if (val < hw_min || val > hw_max || + val < dev_priv->rps.min_delay) { mutex_unlock(&dev_priv->rps.hw_lock); return -EINVAL; } @@ -264,8 +279,12 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, DRM_DEBUG("User requested overclocking to %d\n", val * GT_FREQUENCY_MULTIPLIER); - if (dev_priv->rps.cur_delay > val) - gen6_set_rps(dev_priv->dev, val); + if (dev_priv->rps.cur_delay > val) { + if (IS_VALLEYVIEW(dev_priv->dev)) + valleyview_set_rps(dev_priv->dev, val); + else + gen6_set_rps(dev_priv->dev, val); + } dev_priv->rps.max_delay = val; @@ -282,7 +301,10 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute int ret; mutex_lock(&dev_priv->rps.hw_lock); - ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; + if (IS_VALLEYVIEW(dev_priv->dev)) + ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.min_delay); + else + ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; mutex_unlock(&dev_priv->rps.hw_lock); return snprintf(buf, PAGE_SIZE, "%d\n", ret); @@ -302,21 +324,32 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, if (ret) return ret; - val /= GT_FREQUENCY_MULTIPLIER; - mutex_lock(&dev_priv->rps.hw_lock); - rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); - hw_max = dev_priv->rps.hw_max; - hw_min = ((rp_state_cap & 0xff0000) >> 16); + if (IS_VALLEYVIEW(dev)) { + val = vlv_freq_opcode(dev_priv->mem_freq, val); + + hw_max = valleyview_rps_max_freq(dev_priv); + hw_min = valleyview_rps_min_freq(dev_priv); + } else { + val /= GT_FREQUENCY_MULTIPLIER; + + rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); + hw_max = dev_priv->rps.hw_max; + hw_min = ((rp_state_cap & 0xff0000) >> 16); + } if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) { mutex_unlock(&dev_priv->rps.hw_lock); return -EINVAL; } - if (dev_priv->rps.cur_delay < val) - gen6_set_rps(dev_priv->dev, val); + if (dev_priv->rps.cur_delay < val) { + if (IS_VALLEYVIEW(dev)) + valleyview_set_rps(dev, val); + else + gen6_set_rps(dev_priv->dev, val); + } dev_priv->rps.min_delay = val; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f802368e8e9..2557926553b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2481,6 +2481,52 @@ void gen6_set_rps(struct drm_device *dev, u8 val) trace_intel_gpu_freq_change(val * 50); } +void valleyview_set_rps(struct drm_device *dev, u8 val) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long timeout = jiffies + msecs_to_jiffies(10); + u32 limits = gen6_rps_limits(dev_priv, &val); + u32 pval; + + WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + WARN_ON(val > dev_priv->rps.max_delay); + WARN_ON(val < dev_priv->rps.min_delay); + + DRM_DEBUG_DRIVER("gpu freq request from %d to %d\n", + vlv_gpu_freq(dev_priv->mem_freq, + dev_priv->rps.cur_delay), + vlv_gpu_freq(dev_priv->mem_freq, val)); + + if (val == dev_priv->rps.cur_delay) + return; + + valleyview_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val); + + do { + valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, &pval); + if (time_after(jiffies, timeout)) { + DRM_DEBUG_DRIVER("timed out waiting for Punit\n"); + break; + } + udelay(10); + } while (pval & 1); + + valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, &pval); + if ((pval >> 8) != val) + DRM_DEBUG_DRIVER("punit overrode freq: %d requested, but got %d\n", + val, pval >> 8); + + /* Make sure we continue to get interrupts + * until we hit the minimum or maximum frequencies. + */ + I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits); + + dev_priv->rps.cur_delay = pval >> 8; + + trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv->mem_freq, val)); +} + + static void gen6_disable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -2742,6 +2788,127 @@ static void gen6_update_ring_freq(struct drm_device *dev) } } +int valleyview_rps_max_freq(struct drm_i915_private *dev_priv) +{ + u32 val, rp0; + + valleyview_nc_read(dev_priv, IOSF_NC_FB_GFX_FREQ_FUSE, &val); + + rp0 = (val & FB_GFX_MAX_FREQ_FUSE_MASK) >> FB_GFX_MAX_FREQ_FUSE_SHIFT; + /* Clamp to max */ + rp0 = min_t(u32, rp0, 0xea); + + return rp0; +} + +static int valleyview_rps_rpe_freq(struct drm_i915_private *dev_priv) +{ + u32 val, rpe; + + valleyview_nc_read(dev_priv, IOSF_NC_FB_GFX_FMAX_FUSE_LO, &val); + rpe = (val & FB_FMAX_VMIN_FREQ_LO_MASK) >> FB_FMAX_VMIN_FREQ_LO_SHIFT; + valleyview_nc_read(dev_priv, IOSF_NC_FB_GFX_FMAX_FUSE_HI, &val); + rpe |= (val & FB_FMAX_VMIN_FREQ_HI_MASK) << 5; + + return rpe; +} + +int valleyview_rps_min_freq(struct drm_i915_private *dev_priv) +{ + u32 val; + + valleyview_punit_read(dev_priv, PUNIT_REG_GPU_LFM, &val); + + return val & 0xff; +} + +static void valleyview_enable_rps(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring; + u32 gtfifodbg, val, rpe; + int i; + + WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + + if ((gtfifodbg = I915_READ(GTFIFODBG))) { + DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg); + I915_WRITE(GTFIFODBG, gtfifodbg); + } + + gen6_gt_force_wake_get(dev_priv); + + I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); + I915_WRITE(GEN6_RP_UP_EI, 66000); + I915_WRITE(GEN6_RP_DOWN_EI, 350000); + + I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); + + I915_WRITE(GEN6_RP_CONTROL, + GEN6_RP_MEDIA_TURBO | + GEN6_RP_MEDIA_HW_NORMAL_MODE | + GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_ENABLE | + GEN6_RP_UP_BUSY_AVG | + GEN6_RP_DOWN_IDLE_CONT); + + I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 0x00280000); + I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); + I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); + + for_each_ring(ring, dev_priv, i) + I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); + + I915_WRITE(GEN6_RC6_THRESHOLD, 0xc350); + + /* allows RC6 residency counter to work */ + I915_WRITE(0x138104, _MASKED_BIT_ENABLE(0x3)); + I915_WRITE(GEN6_RC_CONTROL, + GEN7_RC_CTL_TO_MODE); + + valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, &val); + dev_priv->mem_freq = 800 + (266 * (val >> 6) & 3); + DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); + + DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no"); + DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val); + + DRM_DEBUG_DRIVER("current GPU freq: %d\n", + vlv_gpu_freq(dev_priv->mem_freq, (val >> 8) & 0xff)); + dev_priv->rps.cur_delay = (val >> 8) & 0xff; + + dev_priv->rps.max_delay = valleyview_rps_max_freq(dev_priv); + dev_priv->rps.hw_max = dev_priv->rps.max_delay; + DRM_DEBUG_DRIVER("max GPU freq: %d\n", vlv_gpu_freq(dev_priv->mem_freq, + dev_priv->rps.max_delay)); + + rpe = valleyview_rps_rpe_freq(dev_priv); + DRM_DEBUG_DRIVER("RPe GPU freq: %d\n", + vlv_gpu_freq(dev_priv->mem_freq, rpe)); + + val = valleyview_rps_min_freq(dev_priv); + DRM_DEBUG_DRIVER("min GPU freq: %d\n", vlv_gpu_freq(dev_priv->mem_freq, + val)); + dev_priv->rps.min_delay = val; + + DRM_DEBUG_DRIVER("setting GPU freq to %d\n", + vlv_gpu_freq(dev_priv->mem_freq, rpe)); + + valleyview_set_rps(dev_priv->dev, rpe); + + /* requires MSI enabled */ + I915_WRITE(GEN6_PMIER, GEN6_PM_DEFERRED_EVENTS); + spin_lock_irq(&dev_priv->rps.lock); + WARN_ON(dev_priv->rps.pm_iir != 0); + I915_WRITE(GEN6_PMIMR, 0); + spin_unlock_irq(&dev_priv->rps.lock); + /* enable all PM interrupts */ + I915_WRITE(GEN6_PMINTRMSK, 0); + + gen6_gt_force_wake_put(dev_priv); +} + void ironlake_teardown_rc6(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3468,7 +3635,7 @@ void intel_disable_gt_powersave(struct drm_device *dev) if (IS_IRONLAKE_M(dev)) { ironlake_disable_drps(dev); ironlake_disable_rc6(dev); - } else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) { + } else if (INTEL_INFO(dev)->gen >= 6) { cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work); mutex_lock(&dev_priv->rps.hw_lock); gen6_disable_rps(dev); @@ -3484,8 +3651,13 @@ static void intel_gen6_powersave_work(struct work_struct *work) struct drm_device *dev = dev_priv->dev; mutex_lock(&dev_priv->rps.hw_lock); - gen6_enable_rps(dev); - gen6_update_ring_freq(dev); + + if (IS_VALLEYVIEW(dev)) { + valleyview_enable_rps(dev); + } else { + gen6_enable_rps(dev); + gen6_update_ring_freq(dev); + } mutex_unlock(&dev_priv->rps.hw_lock); } @@ -3497,7 +3669,7 @@ void intel_enable_gt_powersave(struct drm_device *dev) ironlake_enable_drps(dev); ironlake_enable_rc6(dev); intel_init_emon(dev); - } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { + } else if (IS_GEN6(dev) || IS_GEN7(dev)) { /* * PCU communication is slow and this doesn't need to be * done at any specific time, so do this out of our fast path @@ -4568,14 +4740,13 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val) return 0; } -static int vlv_punit_rw(struct drm_i915_private *dev_priv, u8 opcode, +static int vlv_punit_rw(struct drm_i915_private *dev_priv, u32 port, u8 opcode, u8 addr, u32 *val) { - u32 cmd, devfn, port, be, bar; + u32 cmd, devfn, be, bar; bar = 0; be = 0xf; - port = IOSF_PORT_PUNIT; devfn = PCI_DEVFN(2, 0); cmd = (devfn << IOSF_DEVFN_SHIFT) | (opcode << IOSF_OPCODE_SHIFT) | @@ -4597,7 +4768,7 @@ static int vlv_punit_rw(struct drm_i915_private *dev_priv, u8 opcode, I915_WRITE(VLV_IOSF_DOORBELL_REQ, cmd); if (wait_for((I915_READ(VLV_IOSF_DOORBELL_REQ) & IOSF_SB_BUSY) == 0, - 500)) { + 5)) { DRM_ERROR("timeout waiting for pcode %s (%d) to finish\n", opcode == PUNIT_OPCODE_REG_READ ? "read" : "write", addr); @@ -4613,12 +4784,20 @@ static int vlv_punit_rw(struct drm_i915_private *dev_priv, u8 opcode, int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val) { - return vlv_punit_rw(dev_priv, PUNIT_OPCODE_REG_READ, addr, val); + return vlv_punit_rw(dev_priv, IOSF_PORT_PUNIT, PUNIT_OPCODE_REG_READ, + addr, val); } int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val) { - return vlv_punit_rw(dev_priv, PUNIT_OPCODE_REG_WRITE, addr, &val); + return vlv_punit_rw(dev_priv, IOSF_PORT_PUNIT, PUNIT_OPCODE_REG_WRITE, + addr, &val); +} + +int valleyview_nc_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val) +{ + return vlv_punit_rw(dev_priv, IOSF_PORT_NC, PUNIT_OPCODE_REG_READ, + addr, val); } int vlv_gpu_freq(int ddr_freq, int val) -- cgit v1.2.3-18-g5258 From 75e539864a133c4d8d6a4aac9f409e0a23d7bc3f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 18 Apr 2013 21:10:43 +0200 Subject: drm/i915: fix VLV limits Magic updates. v2: use 64 bit types and math (Ville) v3: Trim out all the m/n/p calculation changes since they are still under discussion. Instead squash in a fixup for hdmi limits which slipped into a different patch. Signed-off-by: Pallavi G Signed-off-by: Vijay Purushothaman Signed-off-by: Yogesh M Signed-off-by: Gajanan Bhat Signed-off-by: Jesse Barnes (v2) Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 02faba0263d..bdbad762134 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -396,15 +396,15 @@ static const intel_limit_t intel_limits_vlv_dac = { .m1 = { .min = 2, .max = 3 }, .m2 = { .min = 11, .max = 156 }, .p = { .min = 10, .max = 30 }, - .p1 = { .min = 2, .max = 3 }, + .p1 = { .min = 1, .max = 3 }, .p2 = { .dot_limit = 270000, .p2_slow = 2, .p2_fast = 20 }, .find_pll = intel_vlv_find_best_pll, }; static const intel_limit_t intel_limits_vlv_hdmi = { - .dot = { .min = 20000, .max = 165000 }, - .vco = { .min = 4000000, .max = 5994000}, + .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 }, @@ -424,7 +424,7 @@ static const intel_limit_t intel_limits_vlv_dp = { .m1 = { .min = 2, .max = 3 }, .m2 = { .min = 11, .max = 156 }, .p = { .min = 10, .max = 30 }, - .p1 = { .min = 2, .max = 3 }, + .p1 = { .min = 1, .max = 3 }, .p2 = { .dot_limit = 270000, .p2_slow = 2, .p2_fast = 20 }, .find_pll = intel_vlv_find_best_pll, -- cgit v1.2.3-18-g5258 From 598fac6bf8299ed7ae1852426660be3c265047a4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 18 Apr 2013 22:01:46 +0200 Subject: drm/i915: magic VLV PLL registers in the dpio sideband Stolen from a patch with the below impressive sob-section. Signed-off-by: Pallavi G Signed-off-by: Vijay Purushothaman Signed-off-by: Gajanan Bhat Signed-off-by: Ben Widawsky Signed-off-by: Jesse Barnes [danvet: Drop everything but the header #defines.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 118 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 66fb8dd2822..fb1a4fa68d5 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 /* -- cgit v1.2.3-18-g5258 From e2fa6fba3d2fa03a5efdedf0b6f045fcc3428a80 Mon Sep 17 00:00:00 2001 From: Pallavi G Date: Thu, 18 Apr 2013 14:44:28 -0700 Subject: drm/i915/dp: program VSwing and Preemphasis control settings on VLV v2 Program few Tx buffer Swing control settings through DPIO. v2: fix up codingstyle (Daniel) call from set_signal_levels (Ville, Daniel) use proper port numbers (Jesse) Signed-off-by: Pallavi G Signed-off-by: Yogesh M Signed-off-by: Gajanan Bhat Signed-off-by: Jesse Barnes (v2 changes) [danvet: Reorder if-ladder to avoid two IS_VLV checks.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 3 +- drivers/gpu/drm/i915/intel_dp.c | 128 ++++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_drv.h | 2 + 3 files changed, 128 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bdbad762134..9ff992aabcd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -450,8 +450,7 @@ u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg) return I915_READ(DPIO_DATA); } -static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg, - u32 val) +void intel_dpio_write(struct drm_i915_private *dev_priv, int reg, u32 val) { WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock)); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 89f89b72790..9e16b0ca8dd 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1461,7 +1461,9 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); - if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) + if (IS_VALLEYVIEW(dev)) + return DP_TRAIN_VOLTAGE_SWING_1200; + else if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) return DP_TRAIN_VOLTAGE_SWING_800; else if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) return DP_TRAIN_VOLTAGE_SWING_1200; @@ -1486,7 +1488,19 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) default: return DP_TRAIN_PRE_EMPHASIS_0; } - } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev)) { + switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + return DP_TRAIN_PRE_EMPHASIS_9_5; + case DP_TRAIN_VOLTAGE_SWING_600: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_800: + return DP_TRAIN_PRE_EMPHASIS_3_5; + case DP_TRAIN_VOLTAGE_SWING_1200: + default: + return DP_TRAIN_PRE_EMPHASIS_0; + } + } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) { switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { case DP_TRAIN_VOLTAGE_SWING_400: return DP_TRAIN_PRE_EMPHASIS_6; @@ -1511,6 +1525,111 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) } } +static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp) +{ + struct drm_device *dev = intel_dp_to_dev(intel_dp); + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_digital_port *dport = dp_to_dig_port(intel_dp); + unsigned long demph_reg_value, preemph_reg_value, + uniqtranscale_reg_value; + uint8_t train_set = intel_dp->train_set[0]; + int port; + + if (dport->port == PORT_B) + port = 0; + else if (dport->port == PORT_C) + port = 1; + else + BUG(); + + switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { + case DP_TRAIN_PRE_EMPHASIS_0: + preemph_reg_value = 0x0004000; + switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + demph_reg_value = 0x2B405555; + uniqtranscale_reg_value = 0x552AB83A; + break; + case DP_TRAIN_VOLTAGE_SWING_600: + demph_reg_value = 0x2B404040; + uniqtranscale_reg_value = 0x5548B83A; + break; + case DP_TRAIN_VOLTAGE_SWING_800: + demph_reg_value = 0x2B245555; + uniqtranscale_reg_value = 0x5560B83A; + break; + case DP_TRAIN_VOLTAGE_SWING_1200: + demph_reg_value = 0x2B405555; + uniqtranscale_reg_value = 0x5598DA3A; + break; + default: + return 0; + } + break; + case DP_TRAIN_PRE_EMPHASIS_3_5: + preemph_reg_value = 0x0002000; + switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + demph_reg_value = 0x2B404040; + uniqtranscale_reg_value = 0x5552B83A; + break; + case DP_TRAIN_VOLTAGE_SWING_600: + demph_reg_value = 0x2B404848; + uniqtranscale_reg_value = 0x5580B83A; + break; + case DP_TRAIN_VOLTAGE_SWING_800: + demph_reg_value = 0x2B404040; + uniqtranscale_reg_value = 0x55ADDA3A; + break; + default: + return 0; + } + break; + case DP_TRAIN_PRE_EMPHASIS_6: + preemph_reg_value = 0x0000000; + switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + demph_reg_value = 0x2B305555; + uniqtranscale_reg_value = 0x5570B83A; + break; + case DP_TRAIN_VOLTAGE_SWING_600: + demph_reg_value = 0x2B2B4040; + uniqtranscale_reg_value = 0x55ADDA3A; + break; + default: + return 0; + } + break; + case DP_TRAIN_PRE_EMPHASIS_9_5: + preemph_reg_value = 0x0006000; + switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + demph_reg_value = 0x1B405555; + uniqtranscale_reg_value = 0x55ADDA3A; + break; + default: + return 0; + } + break; + default: + return 0; + } + + /* eDP is only on port C */ + mutex_lock(&dev_priv->dpio_lock); + intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x00000000); + intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(port), demph_reg_value); + intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(port), + uniqtranscale_reg_value); + intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(port), 0x0C782040); + intel_dpio_write(dev_priv, DPIO_PCS_STAGGER0(port), 0x00030000); + intel_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port), preemph_reg_value); + intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x80000000); + mutex_unlock(&dev_priv->dpio_lock); + + return 0; +} + static void intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]) { @@ -1685,7 +1804,10 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) if (HAS_DDI(dev)) { signal_levels = intel_hsw_signal_levels(train_set); mask = DDI_BUF_EMP_MASK; - } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev)) { + signal_levels = intel_vlv_signal_levels(intel_dp); + mask = 0; + } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) { signal_levels = intel_gen7_edp_signal_levels(train_set); mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; } else if (IS_GEN6(dev) && is