From ce33dc74e8c6eb426ed5913990fa0cfc6e7de614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Sun, 8 Jun 2014 01:05:28 +0300 Subject: [PATCH] drm/i915: Populate pipe_config.pixel_multiplier even for disabled pipes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On certain platforms pixel_multiplier is read out in .get_pipe_config(), but it also gets used to calculate the pixel clock in intel_sdvo_get_config(). If the pipe is disable but some SDVO outputs are active, we may end up dividing by zero in intel_sdvo_get_config(). To avoid the problem, populate pipe_config->pixel_multiplier to 1 even for disabled pipes in {i9xx,ironlake}_get_pipe_config(). The "divide by pixel_multiplier" operation got introduced here: commit 18442d08786472c63a0a80c27f92b033dffc26de Author: Ville Syrjälä Date: Fri Sep 13 16:00:08 2013 +0300 drm/i915: Fix port_clock and adjusted_mode.clock readout all over and it has caused a regression on certain machines since they would hit the div-by-zero during resume. XXX: Remove debug WARN_ON() from intel_sdvo_get_hw_state() It's just included to confirm the theory that the port is disabled while outputs are active Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76520 Cc: # 3.13+ Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++++++++ drivers/gpu/drm/i915/intel_sdvo.c | 2 ++ 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 98b7049..c18a62f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6164,6 +6164,12 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, struct drm_i915_private *dev_priv = dev->dev_private; uint32_t tmp; + /* + * Avoids a div-by-zero in intel_sdvo_get_config() in + * case the encoder was enabled, but the pipe wasn't. + */ + pipe_config->pixel_multiplier = 1; + if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_PIPE(crtc->pipe))) return false; @@ -7156,6 +7162,12 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; pipe_config->shared_dpll = DPLL_ID_PRIVATE; + /* + * Avoids a div-by-zero in intel_sdvo_get_config() in + * case an encoder was enabled, but the pipe wasn't. + */ + pipe_config->pixel_multiplier = 1; + tmp = I915_READ(PIPECONF(crtc->pipe)); if (!(tmp & PIPECONF_ENABLE)) return false; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 6a4d5bc..ddbfa3a 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1329,6 +1329,8 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder, if (!(tmp & SDVO_ENABLE) && (active_outputs == 0)) return false; + WARN_ON(!(tmp & SDVO_ENABLE)); + if (HAS_PCH_CPT(dev)) *pipe = PORT_TO_PIPE_CPT(tmp); else -- 1.8.3.2