aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_dp.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2016-12-20 11:51:17 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-12 05:39:08 -0500
commitf0f7f38e80688776a21e6a91025a4851c06c6ee3 (patch)
tree5cddbdc645870398d91579ad6119ea6d4acbe27e /drivers/gpu/drm/i915/intel_dp.c
parent73d4256359899b239a8bb58546369afebeb4fc40 (diff)
drm/i915: Force VDD off on the new power seqeuencer before starting to use it
commit 8581f1b5ee0837e55197f036406bc99746ac94b2 upstream. Apparently some VLV BIOSen like to leave the VDD force bit enabled even for power seqeuncers that aren't properly hooked up to any port. That will result in a imbalance in the AUX power domain refcount when we stat to use said power sequencer as edp_panel_vdd_on() will not grab the power domain reference if it sees that the VDD is already on. To fix this let's make sure we turn off the VDD force bit when we initialize the power sequencer registers. That is, unless it's being done from the init path since there we are actually initializing the registers for the current power sequencer and we don't want to turn VDD off needlessly as that would require waiting for the power cycle delay before we turn it back on. This fixes the following kind of warnings: WARNING: CPU: 0 PID: 123 at ../drivers/gpu/drm/i915/intel_runtime_pm.c:1455 intel_display_power_put+0x13a/0x170 [i915]() WARN_ON(!power_domains->domain_use_count[domain]) ... v2: Fix typos in comment (David) Cc: Matwey V. Kornilov <matwey.kornilov@gmail.com> Tested-by: Matwey V. Kornilov <matwey.kornilov@gmail.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98695 Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20161220165117.24801-1-ville.syrjala@linux.intel.com Reviewed-by: David Weinehall <david.weinehall@linux.intel.com> (cherry picked from commit 5d5ab2d26f32bdaa5872b938658e0bf8d341bc4c) Signed-off-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index bf344d08356a..13ae67cc6b8a 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -280,7 +280,8 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
280 struct intel_dp *intel_dp); 280 struct intel_dp *intel_dp);
281static void 281static void
282intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, 282intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
283 struct intel_dp *intel_dp); 283 struct intel_dp *intel_dp,
284 bool force_disable_vdd);
284static void 285static void
285intel_dp_pps_init(struct drm_device *dev, struct intel_dp *intel_dp); 286intel_dp_pps_init(struct drm_device *dev, struct intel_dp *intel_dp);
286 287
@@ -442,7 +443,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
442 443
443 /* init power sequencer on this pipe and port */ 444 /* init power sequencer on this pipe and port */
444 intel_dp_init_panel_power_sequencer(dev, intel_dp); 445 intel_dp_init_panel_power_sequencer(dev, intel_dp);
445 intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); 446 intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, true);
446 447
447 /* 448 /*
448 * Even vdd force doesn't work until we've made 449 * Even vdd force doesn't work until we've made
@@ -479,7 +480,7 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp)
479 * Only the HW needs to be reprogrammed, the SW state is fixed and 480 * Only the HW needs to be reprogrammed, the SW state is fixed and
480 * has been setup during connector init. 481 * has been setup during connector init.
481 */ 482 */
482 intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); 483 intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, false);
483 484
484 return 0; 485 return 0;
485} 486}
@@ -562,7 +563,7 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
562 port_name(port), pipe_name(intel_dp->pps_pipe)); 563 port_name(port), pipe_name(intel_dp->pps_pipe));
563 564
564 intel_dp_init_panel_power_sequencer(dev, intel_dp); 565 intel_dp_init_panel_power_sequencer(dev, intel_dp);
565 intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); 566 intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, false);
566} 567}
567 568
568void intel_power_sequencer_reset(struct drm_i915_private *dev_priv) 569void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
@@ -2924,7 +2925,7 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
2924 2925
2925 /* init power sequencer on this pipe and port */ 2926 /* init power sequencer on this pipe and port */
2926 intel_dp_init_panel_power_sequencer(dev, intel_dp); 2927 intel_dp_init_panel_power_sequencer(dev, intel_dp);
2927 intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); 2928 intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, true);
2928} 2929}
2929 2930
2930static void vlv_pre_enable_dp(struct intel_encoder *encoder, 2931static void vlv_pre_enable_dp(struct intel_encoder *encoder,
@@ -5054,7 +5055,8 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
5054 5055
5055static void 5056static void
5056intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, 5057intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
5057 struct intel_dp *intel_dp) 5058 struct intel_dp *intel_dp,
5059 bool force_disable_vdd)
5058{ 5060{
5059 struct drm_i915_private *dev_priv = to_i915(dev); 5061 struct drm_i915_private *dev_priv = to_i915(dev);
5060 u32 pp_on, pp_off, pp_div, port_sel = 0; 5062 u32 pp_on, pp_off, pp_div, port_sel = 0;
@@ -5067,6 +5069,31 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
5067 5069
5068 intel_pps_get_registers(dev_priv, intel_dp, &regs); 5070 intel_pps_get_registers(dev_priv, intel_dp, &regs);
5069 5071
5072 /*
5073 * On some VLV machines the BIOS can leave the VDD
5074 * enabled even on power seqeuencers which aren't
5075 * hooked up to any port. This would mess up the
5076 * power domain tracking the first time we pick
5077 * one of these power sequencers for use since
5078 * edp_panel_vdd_on() would notice that the VDD was
5079 * already on and therefore wouldn't grab the power
5080 * domain reference. Disable VDD first to avoid this.
5081 * This also avoids spuriously turning the VDD on as
5082 * soon as the new power seqeuencer gets initialized.
5083 */
5084 if (force_disable_vdd) {
5085 u32 pp = ironlake_get_pp_control(intel_dp);
5086
5087 WARN(pp & PANEL_POWER_ON, "Panel power already on\n");
5088
5089 if (pp & EDP_FORCE_VDD)
5090 DRM_DEBUG_KMS("VDD already on, disabling first\n");
5091
5092 pp &= ~EDP_FORCE_VDD;
5093
5094 I915_WRITE(regs.pp_ctrl, pp);
5095 }
5096
5070 pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | 5097 pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
5071 (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT); 5098 (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
5072 pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) | 5099 pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
@@ -5119,7 +5146,7 @@ static void intel_dp_pps_init(struct drm_device *dev,
5119 vlv_initial_power_sequencer_setup(intel_dp); 5146 vlv_initial_power_sequencer_setup(intel_dp);
5120 } else { 5147 } else {
5121 intel_dp_init_panel_power_sequencer(dev, intel_dp); 5148 intel_dp_init_panel_power_sequencer(dev, intel_dp);
5122 intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); 5149 intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, false);
5123 } 5150 }
5124} 5151}
5125 5152