aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJani Nikula <jani.nikula@intel.com>2013-01-16 03:53:40 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-01-16 04:23:01 -0500
commitf30d26e468322b50d5e376bec40658683aff8ece (patch)
treedfcb6c81c81d29aab7bb1cc19b57c52d7cd9b5f2
parent0f3b6849dd55943d915f4b461d7db5e8308d4083 (diff)
drm/i915/eDP: do not write power sequence registers for ghost eDP
Some machines detect an eDP port even if it's not really there, and eDP initialization has a fail path for this. Typically such machines have an LVDS display instead. A regression introduced in commit 82ed61fa1a4e08d5f9e86fb1b715b50ed678b6ac Author: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Sat Oct 20 20:57:41 2012 +0200 drm/i915: make edp panel power sequence setup more robust updated the power sequence registers PCH_PP_ON_DELAYS, PCH_PP_OFF_DELAYS, and PCH_PP_DIVISOR also in the ghost eDP case, messing up the LVDS display. Split the power sequencer initialization into two, delaying the register updates until after we know the eDP is real. Note: Keep the PP_CONTROL unlocking in the first part, even if it does not update registers, per the commit message of the above mentioned commit. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=52601 Reported-and-tested-by: Ryan Coe <ryan@rycomotorsports.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c47
1 files changed, 32 insertions, 15 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1b63d55318a0..fb3715b4b09d 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2579,7 +2579,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
2579 2579
2580static void 2580static void
2581intel_dp_init_panel_power_sequencer(struct drm_device *dev, 2581intel_dp_init_panel_power_sequencer(struct drm_device *dev,
2582 struct intel_dp *intel_dp) 2582 struct intel_dp *intel_dp,
2583 struct edp_power_seq *out)
2583{ 2584{
2584 struct drm_i915_private *dev_priv = dev->dev_private; 2585 struct drm_i915_private *dev_priv = dev->dev_private;
2585 struct edp_power_seq cur, vbt, spec, final; 2586 struct edp_power_seq cur, vbt, spec, final;
@@ -2650,16 +2651,35 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
2650 intel_dp->panel_power_cycle_delay = get_delay(t11_t12); 2651 intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
2651#undef get_delay 2652#undef get_delay
2652 2653
2654 DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
2655 intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
2656 intel_dp->panel_power_cycle_delay);
2657
2658 DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
2659 intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
2660
2661 if (out)
2662 *out = final;
2663}
2664
2665static void
2666intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
2667 struct intel_dp *intel_dp,
2668 struct edp_power_seq *seq)
2669{
2670 struct drm_i915_private *dev_priv = dev->dev_private;
2671 u32 pp_on, pp_off, pp_div;
2672
2653 /* And finally store the new values in the power sequencer. */ 2673 /* And finally store the new values in the power sequencer. */
2654 pp_on = (final.t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | 2674 pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
2655 (final.t8 << PANEL_LIGHT_ON_DELAY_SHIFT); 2675 (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
2656 pp_off = (final.t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) | 2676 pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
2657 (final.t10 << PANEL_POWER_DOWN_DELAY_SHIFT); 2677 (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
2658 /* Compute the divisor for the pp clock, simply match the Bspec 2678 /* Compute the divisor for the pp clock, simply match the Bspec
2659 * formula. */ 2679 * formula. */
2660 pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1) 2680 pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1)
2661 << PP_REFERENCE_DIVIDER_SHIFT; 2681 << PP_REFERENCE_DIVIDER_SHIFT;
2662 pp_div |= (DIV_ROUND_UP(final.t11_t12, 1000) 2682 pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000)
2663 << PANEL_POWER_CYCLE_DELAY_SHIFT); 2683 << PANEL_POWER_CYCLE_DELAY_SHIFT);
2664 2684
2665 /* Haswell doesn't have any port selection bits for the panel 2685 /* Haswell doesn't have any port selection bits for the panel
@@ -2675,14 +2695,6 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
2675 I915_WRITE(PCH_PP_OFF_DELAYS, pp_off); 2695 I915_WRITE(PCH_PP_OFF_DELAYS, pp_off);
2676 I915_WRITE(PCH_PP_DIVISOR, pp_div); 2696 I915_WRITE(PCH_PP_DIVISOR, pp_div);
2677 2697
2678
2679 DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
2680 intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
2681 intel_dp->panel_power_cycle_delay);
2682
2683 DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
2684 intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
2685
2686 DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n", 2698 DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
2687 I915_READ(PCH_PP_ON_DELAYS), 2699 I915_READ(PCH_PP_ON_DELAYS),
2688 I915_READ(PCH_PP_OFF_DELAYS), 2700 I915_READ(PCH_PP_OFF_DELAYS),
@@ -2699,6 +2711,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
2699 struct drm_device *dev = intel_encoder->base.dev; 2711 struct drm_device *dev = intel_encoder->base.dev;
2700 struct drm_i915_private *dev_priv = dev->dev_private; 2712 struct drm_i915_private *dev_priv = dev->dev_private;
2701 struct drm_display_mode *fixed_mode = NULL; 2713 struct drm_display_mode *fixed_mode = NULL;
2714 struct edp_power_seq power_seq = { 0 };
2702 enum port port = intel_dig_port->port; 2715 enum port port = intel_dig_port->port;
2703 const char *name = NULL; 2716 const char *name = NULL;
2704 int type; 2717 int type;
@@ -2771,7 +2784,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
2771 } 2784 }
2772 2785
2773 if (is_edp(intel_dp)) 2786 if (is_edp(intel_dp))
2774 intel_dp_init_panel_power_sequencer(dev, intel_dp); 2787 intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
2775 2788
2776 intel_dp_i2c_init(intel_dp, intel_connector, name); 2789 intel_dp_i2c_init(intel_dp, intel_connector, name);
2777 2790
@@ -2798,6 +2811,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
2798 return; 2811 return;
2799 } 2812 }
2800 2813
2814 /* We now know it's not a ghost, init power sequence regs. */
2815 intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
2816 &power_seq);
2817
2801 ironlake_edp_panel_vdd_on(intel_dp); 2818 ironlake_edp_panel_vdd_on(intel_dp);
2802 edid = drm_get_edid(connector, &intel_dp->adapter); 2819 edid = drm_get_edid(connector, &intel_dp->adapter);
2803 if (edid) { 2820 if (edid) {