aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2014-05-29 08:10:22 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-07-07 13:48:52 -0400
commitfabf6e513f640dac89645e1a98376eb8064394ee (patch)
tree4452025c3551de4d74913d03c888651a9d407cf5
parentb3f9ad93b7621364ed51f9c37b9cf9abc9855991 (diff)
drm/i915: Support pf CRC source on haswell transcoder edp
The always-on power well pixel path on haswell is routed such that it bypasses the panel fitter when we use is. Which means the pfit CRC source won't work in that configuration. Add a new disallow-bypass flags to the pfit pipe config state and set it when we want to use the pf CRC. Results in a bit of flicker, but should get the job done. We'll also undo do it afterwards to make sure other tests arent' negatively affected. Totally untested due to lack of hsw laptops around here. v2: s/disallow_bypass/force_power_well_on/ to avoid a double negative (Damien). v3: force_thru because roadsigns. v4: Don't forget the power wells! Also note that until the runtime pm for DPMS series is fully merged the simple disable/enable trick won't work since the ->crtc_mode_set callback is still required to do nasty things. This stuff is tricky, but I think by both fixing up get_crtc_power_domains and the debugfs wa code we should always grab/drop the additional power well correctly. v5: Wrap in () as suggested by Damien to avoid setting reserved values for the edp transcoder path on bdw+ References: https://bugs.freedesktop.org/show_bug.cgi?id=72864 Cc: Damien Lespiau <damien.lespiau@intel.com> Reviewed-by: Damien Lespiau <damien.lespiau@intel.com> Tested-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c64
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c4
-rw-r--r--drivers/gpu/drm/i915/intel_display.c4
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
4 files changed, 67 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 8cc99369c794..bfd0d4130450 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2867,7 +2867,60 @@ static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
2867 return 0; 2867 return 0;
2868} 2868}
2869 2869
2870static int ivb_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, 2870static void hsw_trans_edp_pipe_A_crc_wa(struct drm_device *dev)
2871{
2872 struct drm_i915_private *dev_priv = dev->dev_private;
2873 struct intel_crtc *crtc =
2874 to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]);
2875
2876 drm_modeset_lock_all(dev);
2877 /*
2878 * If we use the eDP transcoder we need to make sure that we don't
2879 * bypass the pfit, since otherwise the pipe CRC source won't work. Only
2880 * relevant on hsw with pipe A when using the always-on power well
2881 * routing.
2882 */
2883 if (crtc->config.cpu_transcoder == TRANSCODER_EDP &&
2884 !crtc->config.pch_pfit.enabled) {
2885 crtc->config.pch_pfit.force_thru = true;
2886
2887 intel_display_power_get(dev_priv,
2888 POWER_DOMAIN_PIPE_PANEL_FITTER(PIPE_A));
2889
2890 dev_priv->display.crtc_disable(&crtc->base);
2891 dev_priv->display.crtc_enable(&crtc->base);
2892 }
2893 drm_modeset_unlock_all(dev);
2894}
2895
2896static void hsw_undo_trans_edp_pipe_A_crc_wa(struct drm_device *dev)
2897{
2898 struct drm_i915_private *dev_priv = dev->dev_private;
2899 struct intel_crtc *crtc =
2900 to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]);
2901
2902 drm_modeset_lock_all(dev);
2903 /*
2904 * If we use the eDP transcoder we need to make sure that we don't
2905 * bypass the pfit, since otherwise the pipe CRC source won't work. Only
2906 * relevant on hsw with pipe A when using the always-on power well
2907 * routing.
2908 */
2909 if (crtc->config.pch_pfit.force_thru) {
2910 crtc->config.pch_pfit.force_thru = false;
2911
2912 dev_priv->display.crtc_disable(&crtc->base);
2913 dev_priv->display.crtc_enable(&crtc->base);
2914
2915 intel_display_power_put(dev_priv,
2916 POWER_DOMAIN_PIPE_PANEL_FITTER(PIPE_A));
2917 }
2918 drm_modeset_unlock_all(dev);
2919}
2920
2921static int ivb_pipe_crc_ctl_reg(struct drm_device *dev,
2922 enum pipe pipe,
2923 enum intel_pipe_crc_source *source,
2871 uint32_t *val) 2924 uint32_t *val)
2872{ 2925{
2873 if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) 2926 if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
@@ -2881,6 +2934,9 @@ static int ivb_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
2881 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB; 2934 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB;
2882 break; 2935 break;
2883 case INTEL_PIPE_CRC_SOURCE_PF: 2936 case INTEL_PIPE_CRC_SOURCE_PF:
2937 if (IS_HASWELL(dev) && pipe == PIPE_A)
2938 hsw_trans_edp_pipe_A_crc_wa(dev);
2939
2884 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB; 2940 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB;
2885 break; 2941 break;
2886 case INTEL_PIPE_CRC_SOURCE_NONE: 2942 case INTEL_PIPE_CRC_SOURCE_NONE:
@@ -2913,11 +2969,11 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
2913 else if (INTEL_INFO(dev)->gen < 5) 2969 else if (INTEL_INFO(dev)->gen < 5)
2914 ret = i9xx_pipe_crc_ctl_reg(dev, pipe, &source, &val); 2970 ret = i9xx_pipe_crc_ctl_reg(dev, pipe, &source, &val);
2915 else if (IS_VALLEYVIEW(dev)) 2971 else if (IS_VALLEYVIEW(dev))
2916 ret = vlv_pipe_crc_ctl_reg(dev,pipe, &source, &val); 2972 ret = vlv_pipe_crc_ctl_reg(dev, pipe, &source, &val);
2917 else if (IS_GEN5(dev) || IS_GEN6(dev)) 2973 else if (IS_GEN5(dev) || IS_GEN6(dev))
2918 ret = ilk_pipe_crc_ctl_reg(&source, &val); 2974 ret = ilk_pipe_crc_ctl_reg(&source, &val);
2919 else 2975 else
2920 ret = ivb_pipe_crc_ctl_reg(&source, &val); 2976 ret = ivb_pipe_crc_ctl_reg(dev, pipe, &source, &val);
2921 2977
2922 if (ret != 0) 2978 if (ret != 0)
2923 return ret; 2979 return ret;
@@ -2969,6 +3025,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
2969 g4x_undo_pipe_scramble_reset(dev, pipe); 3025 g4x_undo_pipe_scramble_reset(dev, pipe);
2970 else if (IS_VALLEYVIEW(dev)) 3026 else if (IS_VALLEYVIEW(dev))
2971 vlv_undo_pipe_scramble_reset(dev, pipe); 3027 vlv_undo_pipe_scramble_reset(dev, pipe);
3028 else if (IS_HASWELL(dev) && pipe == PIPE_A)
3029 hsw_undo_trans_edp_pipe_A_crc_wa(dev);
2972 } 3030 }
2973 3031
2974 return 0; 3032 return 0;
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index efaf44b5ff25..6cc79c83772c 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -995,7 +995,9 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
995 * eDP when not using the panel fitter, and when not 995 * eDP when not using the panel fitter, and when not
996 * using motion blur mitigation (which we don't 996 * using motion blur mitigation (which we don't
997 * support). */ 997 * support). */
998 if (IS_HASWELL(dev) && intel_crtc->config.pch_pfit.enabled) 998 if (IS_HASWELL(dev) &&
999 (intel_crtc->config.pch_pfit.enabled ||
1000 intel_crtc->config.pch_pfit.force_thru))
999 temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; 1001 temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
1000 else 1002 else
1001 temp |= TRANS_DDI_EDP_INPUT_A_ON; 1003 temp |= TRANS_DDI_EDP_INPUT_A_ON;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b961122ad515..8043e4b51ecd 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4350,7 +4350,6 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
4350 struct intel_encoder *intel_encoder; 4350 struct intel_encoder *intel_encoder;
4351 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 4351 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
4352 enum pipe pipe = intel_crtc->pipe; 4352 enum pipe pipe = intel_crtc->pipe;
4353 bool pfit_enabled = intel_crtc->config.pch_pfit.enabled;
4354 unsigned long mask; 4353 unsigned long mask;
4355 enum transcoder transcoder; 4354 enum transcoder transcoder;
4356 4355
@@ -4358,7 +4357,8 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
4358 4357
4359 mask = BIT(POWER_DOMAIN_PIPE(pipe)); 4358 mask = BIT(POWER_DOMAIN_PIPE(pipe));
4360 mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder)); 4359 mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
4361 if (pfit_enabled) 4360 if (intel_crtc->config.pch_pfit.enabled ||
4361 intel_crtc->config.pch_pfit.force_thru)
4362 mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe)); 4362 mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
4363 4363
4364 for_each_encoder_on_crtc(dev, crtc, intel_encoder) 4364 for_each_encoder_on_crtc(dev, crtc, intel_encoder)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 45afd25f9362..9da665a1cd31 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -338,6 +338,7 @@ struct intel_crtc_config {
338 u32 pos; 338 u32 pos;
339 u32 size; 339 u32 size;
340 bool enabled; 340 bool enabled;
341 bool force_thru;
341 } pch_pfit; 342 } pch_pfit;
342 343
343 /* FDI configuration, only valid if has_pch_encoder is set. */ 344 /* FDI configuration, only valid if has_pch_encoder is set. */