From ee21554ca4bad77c7c4be7ee0787cac3ac7e14d6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 11 Oct 2012 11:09:56 +0200 Subject: [PATCH] drm/i915/dvo-ch7xxx: fix get_hw_state The boot-up state seems to be all-zeros, so it's safer to check for the bits that need to be set when the dvo encoder is in the dpms on state, than checking the bits we set when it's in the off state. v2: Also unconditionally disable the entire encoder if an active connector or encoder doesn't have an active pipe. We need this to disable encoders with separate connector state (like dvo, sdvo and crt). ... also some debug printks in case I've wrong, again. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55047 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/dvo_ch7xxx.c | 16 +++++++++++++--- drivers/gpu/drm/i915/intel_display.c | 19 ++++++++++--------- drivers/gpu/drm/i915/intel_dvo.c | 2 ++ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c index 38f3a6c..f61f93e 100644 --- a/drivers/gpu/drm/i915/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c @@ -291,10 +291,18 @@ static void ch7xxx_mode_set(struct intel_dvo_device *dvo, /* set the CH7xxx power state */ static void ch7xxx_dpms(struct intel_dvo_device *dvo, bool enable) { + u8 val; + + ch7xxx_readb(dvo, CH7xxx_PM, &val); + printk("before dpms: ch7xxx PM reg: 0x%02x\n", val); + if (enable) ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_DVIL | CH7xxx_PM_DVIP); else ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_FPD); + + ch7xxx_readb(dvo, CH7xxx_PM, &val); + printk("after dpms: ch7xxx PM reg: 0x%02x\n", val); } static bool ch7xxx_get_hw_state(struct intel_dvo_device *dvo) @@ -303,10 +311,12 @@ static bool ch7xxx_get_hw_state(struct intel_dvo_device *dvo) ch7xxx_readb(dvo, CH7xxx_PM, &val); - if (val & CH7xxx_PM_FPD) - return false; - else + printk("get_hw_state: ch7xxx PM reg: 0x%02x\n", val); + + if (val & (CH7xxx_PM_DVIL | CH7xxx_PM_DVIP)) return true; + else + return false; } static void ch7xxx_dump_regs(struct intel_dvo_device *dvo) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e6649b3..26af5df 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8171,15 +8171,16 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) encoder->base.base.id, drm_get_encoder_name(&encoder->base)); - /* Connector is active, but has no active pipe. This is - * fallout from our resume register restoring. Disable - * the encoder manually again. */ - if (encoder->base.crtc) { - DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n", - encoder->base.base.id, - drm_get_encoder_name(&encoder->base)); - encoder->disable(encoder); - } + /* Unconditionally disable the encoder, even if the encoder + * itself might be off. We need this since there's no other way + * to only disable connectors for encoders with separate + * connector state (dvo, sdvo and crt). For all encoders where + * double-disable could anger the hw (dp) there's no such + * mismatch. */ + DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n", + encoder->base.base.id, + drm_get_encoder_name(&encoder->base)); + encoder->disable(encoder); /* Inconsistent output/port/pipe state happens presumably due to * a bug in one of the get_hw_state functions. Or someplace else diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 4f1fdcc..8128a5f 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -137,6 +137,8 @@ static void intel_disable_dvo(struct intel_encoder *encoder) u32 dvo_reg = intel_dvo->dev.dvo_reg; u32 temp = I915_READ(dvo_reg); + printk("disable dvo called\n"); + intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false); I915_WRITE(dvo_reg, temp & ~DVO_ENABLE); I915_READ(dvo_reg); -- 1.7.10.4