From patchwork Thu Oct 7 23:01:12 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jesse Barnes X-Patchwork-Id: 239181 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o97N5E6t028731 for ; Thu, 7 Oct 2010 23:05:34 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E1B13A09BC for ; Thu, 7 Oct 2010 16:05:13 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from cpoproxy3-pub.bluehost.com (cpoproxy3-pub.bluehost.com [67.222.54.6]) by gabe.freedesktop.org (Postfix) with SMTP id C283D9ED01 for ; Thu, 7 Oct 2010 16:02:05 -0700 (PDT) Received: (qmail 11093 invoked by uid 0); 7 Oct 2010 23:02:05 -0000 Received: from unknown (HELO box514.bluehost.com) (74.220.219.114) by cpoproxy3.bluehost.com with SMTP; 7 Oct 2010 23:02:05 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=virtuousgeek.org; h=Received:From:To:Cc:Subject:Date:Message-Id:X-Mailer:In-Reply-To:References:X-Identified-User; b=oahzLIXs4AmaCEq1CLRormLBJLmCi++d3Dbl3NT1ggXPksobyvXePM0kBghtOJDtQExvHmk4hvxgzae+kqAg/OSZcXx9kriGdMJfd8MnL1SnQrRJEe5TKDNxA8kN3ouu; Received: from c-67-174-193-198.hsd1.ca.comcast.net ([67.174.193.198] helo=localhost.localdomain) by box514.bluehost.com with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.69) (envelope-from ) id 1P3zTQ-0002wH-5N; Thu, 07 Oct 2010 17:02:04 -0600 From: Jesse Barnes To: intel-gfx@lists.freedesktop.org Date: Thu, 7 Oct 2010 16:01:12 -0700 Message-Id: <1286492485-18145-8-git-send-email-jbarnes@virtuousgeek.org> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1286492485-18145-1-git-send-email-jbarnes@virtuousgeek.org> References: <1286492485-18145-1-git-send-email-jbarnes@virtuousgeek.org> X-Identified-User: {10642:box514.bluehost.com:virtuous:virtuousgeek.org} {sentby:smtp auth 67.174.193.198 authed with jbarnes@virtuousgeek.org} Subject: [Intel-gfx] [PATCH 07/20] drm/i915/dp: eDP power sequencing fixes X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Thu, 07 Oct 2010 23:05:34 +0000 (UTC) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d02de21..a72335e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1373,6 +1373,9 @@ #define PP_SEQUENCE_ON (1 << 28) #define PP_SEQUENCE_OFF (2 << 28) #define PP_SEQUENCE_MASK 0x30000000 +#define PP_CYCLE_DELAY_ACTIVE (1 << 27) +#define PP_SEQUENCE_STATE_ON_IDLE (1 << 3) +#define PP_SEQUENCE_STATE_MASK 0x0000000f #define PP_CONTROL 0x61204 #define POWER_TARGET_ON (1 << 0) #define PP_ON_DELAYS 0x61208 diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 57bfc3e..e5f183f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -788,10 +788,11 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, } /* Returns true if the panel was already on when called */ -static bool ironlake_edp_panel_on (struct drm_device *dev) +static bool ironlake_edp_panel_on (struct intel_dp *intel_dp) { + struct drm_device *dev = intel_dp->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 pp; + u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE; if (I915_READ(PCH_PP_STATUS) & PP_ON) return true; @@ -803,19 +804,20 @@ static bool ironlake_edp_panel_on (struct drm_device *dev) I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); - pp |= POWER_TARGET_ON; + pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON; I915_WRITE(PCH_PP_CONTROL, pp); + POSTING_READ(PCH_PP_CONTROL); /* Ouch. We need to wait here for some panels, like Dell e6510 * https://bugs.freedesktop.org/show_bug.cgi?id=29278i */ msleep(300); - if (wait_for(I915_READ(PCH_PP_STATUS) & PP_ON, 5000)) + if (wait_for(I915_READ(PCH_PP_STATUS) == idle_on_mask, + 5000)) DRM_ERROR("panel on wait timed out: 0x%08x\n", I915_READ(PCH_PP_STATUS)); - pp &= ~(PANEL_UNLOCK_REGS); pp |= PANEL_POWER_RESET; /* restore panel reset bit */ I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); @@ -826,7 +828,8 @@ static bool ironlake_edp_panel_on (struct drm_device *dev) static void ironlake_edp_panel_off (struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 pp; + u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK | + PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK; pp = I915_READ(PCH_PP_CONTROL); @@ -837,12 +840,12 @@ static void ironlake_edp_panel_off (struct drm_device *dev) pp &= ~POWER_TARGET_ON; I915_WRITE(PCH_PP_CONTROL, pp); + POSTING_READ(PCH_PP_CONTROL); - if (wait_for((I915_READ(PCH_PP_STATUS) & PP_ON) == 0, 5000)) + if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000)) DRM_ERROR("panel off wait timed out: 0x%08x\n", I915_READ(PCH_PP_STATUS)); - /* Make sure VDD is enabled so DP AUX will work */ pp |= PANEL_POWER_RESET; /* restore panel reset bit */ I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); @@ -853,36 +856,19 @@ static void ironlake_edp_panel_off (struct drm_device *dev) msleep(300); } -static void ironlake_edp_panel_vdd_on(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u32 pp; - - pp = I915_READ(PCH_PP_CONTROL); - pp |= EDP_FORCE_VDD; - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); - msleep(300); -} - -static void ironlake_edp_panel_vdd_off(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u32 pp; - - pp = I915_READ(PCH_PP_CONTROL); - pp &= ~EDP_FORCE_VDD; - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); - msleep(300); -} - static void ironlake_edp_backlight_on (struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 pp; DRM_DEBUG_KMS("\n"); + /* + * If we enable the backlight right away following a panel power + * on, we may see slight flicker as the panel syncs with the eDP + * link. So delay a bit to make sure the image is solid before + * allowing it to appear. + */ + msleep(300); pp = I915_READ(PCH_PP_CONTROL); pp |= EDP_BLC_ENABLE; I915_WRITE(PCH_PP_CONTROL, pp); @@ -932,10 +918,12 @@ static void intel_dp_prepare(struct drm_encoder *encoder) uint32_t dp_reg = I915_READ(intel_dp->output_reg); if (is_edp(intel_dp)) { - ironlake_edp_panel_off(dev); ironlake_edp_backlight_off(dev); - ironlake_edp_panel_vdd_on(dev); - ironlake_edp_pll_on(encoder); + ironlake_edp_panel_on(intel_dp); + if (!is_pch_edp(intel_dp)) + ironlake_edp_pll_on(encoder); + else + ironlake_edp_pll_off(encoder); } if (dp_reg & DP_PORT_EN) intel_dp_link_down(intel_dp); @@ -949,7 +937,7 @@ static void intel_dp_commit(struct drm_encoder *encoder) intel_dp_start_link_train(intel_dp); if (is_edp(intel_dp)) - ironlake_edp_panel_on(dev); + ironlake_edp_panel_on(intel_dp); intel_dp_complete_link_train(intel_dp); @@ -966,19 +954,20 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) uint32_t dp_reg = I915_READ(intel_dp->output_reg); if (mode != DRM_MODE_DPMS_ON) { - if (is_edp(intel_dp)) { + if (is_edp(intel_dp)) ironlake_edp_backlight_off(dev); - ironlake_edp_panel_off(dev); - } - if (dp_reg & DP_PORT_EN) + if (dp_reg & DP_PORT_EN) { intel_dp_link_down(intel_dp); + } if (is_edp(intel_dp)) + ironlake_edp_panel_off(dev); + if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) ironlake_edp_pll_off(encoder); } else { if (!(dp_reg & DP_PORT_EN)) { - intel_dp_start_link_train(intel_dp); if (is_edp(intel_dp)) - ironlake_edp_panel_on(dev); + ironlake_edp_panel_on(intel_dp); + intel_dp_start_link_train(intel_dp); intel_dp_complete_link_train(intel_dp); if (is_edp(intel_dp)) ironlake_edp_backlight_on(dev); @@ -1445,9 +1434,10 @@ ironlake_dp_detect(struct drm_connector *connector) struct intel_dp *intel_dp = intel_attached_dp(connector); enum drm_connector_status status; - /* Panel needs power for AUX to work */ + /* Can't disconnect eDP */ if (is_edp(intel_dp)) - ironlake_edp_panel_vdd_on(connector->dev); + return connector_status_connected; + status = connector_status_disconnected; if (intel_dp_aux_native_read(intel_dp, 0x000, intel_dp->dpcd, @@ -1458,8 +1448,6 @@ ironlake_dp_detect(struct drm_connector *connector) } DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0], intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]); - if (is_edp(intel_dp)) - ironlake_edp_panel_vdd_off(connector->dev); return status; }