From patchwork Fri Feb 28 23:44:42 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Rodrigo Vivi X-Patchwork-Id: 3745341 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 2E10A9F35F for ; Fri, 28 Feb 2014 23:45:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id EA71A2024D for ; Fri, 28 Feb 2014 23:45:51 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id AF146201BA for ; Fri, 28 Feb 2014 23:45:50 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EDB3EFBDEE; Fri, 28 Feb 2014 15:45:48 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-yk0-f171.google.com (mail-yk0-f171.google.com [209.85.160.171]) by gabe.freedesktop.org (Postfix) with ESMTP id 38100FBDD6 for ; Fri, 28 Feb 2014 15:45:08 -0800 (PST) Received: by mail-yk0-f171.google.com with SMTP id q9so3899183ykb.2 for ; Fri, 28 Feb 2014 15:45:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=vIj/VVKRHXahS0kB2qEYrvGCSYr/LSDIqXOPPz4ei2M=; b=SAz/FgAH8g/JefFnVZLCq3myBYZwmkRvgRr7oTj9drsipp9yHzHSarJWxm3ju8stnw vL944WUfXFMmWo9vVcCZYS7rSMPAqx4VS5AGZ0WL90TnXtirdyqqTCSJB8inSeCVGsSZ 2bBU6QGTNL06S/3hjmOEblLgL0sh1waPAoajCunsp5BkMDGIdPESVKTHulxkOmDFVN/X QLwZFJiPQKvcycBCwHmVS4y4PY6yycEIzUp21x2SoJxGBCW68DD0JSp+XKLstqseXslm U/jMvy0kMXAtdnjc5OG/kElAuZJZNMbuEvTjXuxt8VpjAUxBjp1+g21lJaiMJUr7UpPC KRUA== X-Received: by 10.236.92.132 with SMTP id j4mr432375yhf.128.1393631107871; Fri, 28 Feb 2014 15:45:07 -0800 (PST) Received: from localhost.localdomain ([189.67.129.152]) by mx.google.com with ESMTPSA id h23sm10769779yhc.0.2014.02.28.15.45.06 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 28 Feb 2014 15:45:07 -0800 (PST) From: Rodrigo Vivi To: intel-gfx@lists.freedesktop.org Date: Fri, 28 Feb 2014 20:44:42 -0300 Message-Id: <1393631086-3880-8-git-send-email-rodrigo.vivi@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1393631086-3880-1-git-send-email-rodrigo.vivi@gmail.com> References: <1393631086-3880-1-git-send-email-rodrigo.vivi@gmail.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 07/11] drm/i915: Baytrail PSR: regs setup, enable and disable functions. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch just introduce registers and functions for PSR Baytrail. It is important to highlight this patch doesn't work alone. Baytrail PSR has some critical PSR-exit trigger issues that are fixed on following patches. Also, only on last one we mark baytrail/valleyview as HAS_PSR. Cc: Ville Syrjälä Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 5 ++ drivers/gpu/drm/i915/i915_reg.h | 37 +++++++++ drivers/gpu/drm/i915/intel_display.c | 2 + drivers/gpu/drm/i915/intel_dp.c | 151 +++++++++++++++++++++++++++++++---- drivers/gpu/drm/i915/intel_drv.h | 1 + 5 files changed, 179 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c5abff7..18f457e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -779,10 +779,15 @@ struct i915_fbc { } no_fbc_reason; }; +struct intel_dp; + struct i915_psr { bool sink_support; bool source_ok; bool setup_done; + void (*setup)(struct intel_dp *intel_dp); + void (*enable_sink)(struct intel_dp *intel_dp); + void (*enable_source)(struct intel_dp *intel_dp); }; enum intel_pch { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2f564ce..d6b203f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1984,6 +1984,43 @@ #define VSYNCSHIFT(trans) _TRANSCODER2(trans, _VSYNCSHIFT_A) #define PIPESRC(trans) _TRANSCODER2(trans, _PIPEASRC) +/* VLV eDP PSR registers */ +#define _PSRCTLA (VLV_DISPLAY_BASE + 0x60090) +#define _PSRCTLB (VLV_DISPLAY_BASE + 0x61090) +#define VLV_EDP_PSR_ENABLE (1<<0) +#define VLV_EDP_PSR_RESET (1<<1) +#define VLV_EDP_PSR_MODE_MASK (7<<2) +#define VLV_EDP_PSR_MODE_HW_TIMER (1<<3) +#define VLV_EDP_PSR_MODE_SW_TIMER (1<<2) +#define VLV_EDP_PSR_SINGLE_FRAME_UPDATE (1<<7) +#define VLV_EDP_PSR_ACTIVE_ENTRY (1<<8) +#define VLV_EDP_PSR_SRC_TRANSMITTER_STATE (1<<9) +#define VLV_EDP_PSR_DBL_FRAME (1<<10) +#define VLV_EDP_PSR_FRAME_COUNT_MASK (0xff<<16) +#define VLV_EDP_PSR_IDLE_FRAME_SHIFT 16 +#define VLV_EDP_PSR_INT_TRANSITION (1<<24) +#define VLV_PSRCTL(pipe) _PIPE(pipe, _PSRCTLA, _PSRCTLB) + +#define _VSCSDPA (VLV_DISPLAY_BASE + 0x600a0) +#define _VSCSDPB (VLV_DISPLAY_BASE + 0x610a0) +#define VLV_EDP_PSR_SDP_FREQ_MASK (3<<30) +#define VLV_EDP_PSR_SDP_FREQ_ONCE (1<<31) +#define VLV_EDP_PSR_SDP_FREQ_EVFRAME (1<<30) +#define VLV_VSCSDP(pipe) _PIPE(pipe, _VSCSDPA, _VSCSDPB) + +#define _PSRSTATA (VLV_DISPLAY_BASE + 0x60094) +#define _PSRSTATB (VLV_DISPLAY_BASE + 0x61094) +#define VLV_EDP_PSR_LAST_STATE_MASK (7<<3) +#define VLV_EDP_PSR_CURR_STATE_MASK 7 +#define VLV_EDP_PSR_DISABLED (0<<0) +#define VLV_EDP_PSR_INACTIVE (1<<0) +#define VLV_EDP_PSR_IN_TRANS_TO_ACTIVE (2<<0) +#define VLV_EDP_PSR_ACTIVE_NORFB_UP (3<<0) +#define VLV_EDP_PSR_ACTIVE_SF_UPDATE (4<<0) +#define VLV_EDP_PSR_EXIT (5<<0) +#define VLV_EDP_PSR_IN_TRANS (1<<7) +#define VLV_PSRSTAT(pipe) _PIPE(pipe, _PSRSTATA, _PSRSTATB) + /* HSW+ eDP PSR registers */ #define EDP_PSR_BASE(dev) (IS_HASWELL(dev) ? 0x64800 : 0x6f800) #define EDP_PSR_CTL(dev) (EDP_PSR_BASE(dev) + 0) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e23ff4c..26196b8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10533,6 +10533,8 @@ static void intel_setup_outputs(struct drm_device *dev) if (SUPPORTS_TV(dev)) intel_tv_init(dev); + intel_edp_psr_init(dev); + list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { encoder->base.possible_crtcs = encoder->crtc_mask; encoder->base.possible_clones = diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0799882..aabab25 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1610,14 +1610,30 @@ static bool is_edp_psr(struct intel_dp *intel_dp) return intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED; } +static bool vlv_edp_is_psr_enabled_on_pipe(struct drm_device *dev, int pipe) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t val; + + val = I915_READ(VLV_PSRSTAT(pipe)) & + VLV_EDP_PSR_CURR_STATE_MASK; + return (val == VLV_EDP_PSR_ACTIVE_NORFB_UP) || + (val == VLV_EDP_PSR_ACTIVE_SF_UPDATE); +} + static bool intel_edp_is_psr_enabled(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (!HAS_PSR(dev)) - return false; + if (HAS_PSR(dev)) { + if (IS_VALLEYVIEW(dev)) + return vlv_edp_is_psr_enabled_on_pipe(dev, PIPE_A) || + vlv_edp_is_psr_enabled_on_pipe(dev, PIPE_B); + else + return I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE; + } - return I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE; + return false; } static void intel_edp_psr_write_vsc(struct intel_dp *intel_dp, @@ -1649,6 +1665,29 @@ static void intel_edp_psr_write_vsc(struct intel_dp *intel_dp, POSTING_READ(ctl_reg); } +static void vlv_edp_psr_setup(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t val; + + if (dev_priv->psr.setup_done) + return; + + val = I915_READ(VLV_VSCSDP(PIPE_A)); + val &= ~VLV_EDP_PSR_SDP_FREQ_MASK; + val |= VLV_EDP_PSR_SDP_FREQ_EVFRAME; + I915_WRITE(VLV_VSCSDP(PIPE_A), val); + + val = I915_READ(VLV_VSCSDP(PIPE_B)); + val &= ~VLV_EDP_PSR_SDP_FREQ_MASK; + val |= VLV_EDP_PSR_SDP_FREQ_EVFRAME; + I915_WRITE(VLV_VSCSDP(PIPE_B), val); + + dev_priv->psr.setup_done = true; +} + static void intel_edp_psr_setup(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); @@ -1673,6 +1712,13 @@ static void intel_edp_psr_setup(struct intel_dp *intel_dp) dev_priv->psr.setup_done = true; } +static void vlv_edp_psr_enable_sink(struct intel_dp *intel_dp) +{ + /* Enable PSR in sink */ + intel_dp_aux_native_write_1(intel_dp, DP_PSR_EN_CFG, + DP_PSR_ENABLE); +} + static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); @@ -1703,6 +1749,27 @@ static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp) (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT)); } +static void vlv_edp_psr_enable_source(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = + to_intel_crtc(intel_dig_port->base.base.crtc); + + uint32_t idle_frames = 1; + uint32_t val = 0; + + val |= VLV_EDP_PSR_ENABLE; + val &= ~VLV_EDP_PSR_MODE_MASK; + + val |= VLV_EDP_PSR_MODE_HW_TIMER; + val &= ~VLV_EDP_PSR_FRAME_COUNT_MASK; + val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; + + I915_WRITE(VLV_PSRCTL(intel_crtc->pipe), val); +} + static void intel_edp_psr_enable_source(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); @@ -1739,8 +1806,8 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp) dev_priv->psr.source_ok = false; - if ((intel_encoder->type != INTEL_OUTPUT_EDP) || - (dig_port->port != PORT_A)) { + if (HAS_DDI(dev) && ((intel_encoder->type != INTEL_OUTPUT_EDP) || + (dig_port->port != PORT_A))) { DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n"); return false; } @@ -1791,22 +1858,30 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp) static void intel_edp_psr_do_enable(struct intel_dp *intel_dp) { - struct drm_device *dev = intel_dp_to_dev(intel_dp); + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = + to_intel_crtc(intel_dig_port->base.base.crtc); - if (!intel_edp_psr_match_conditions(intel_dp) || - intel_edp_is_psr_enabled(dev)) - return; + if (IS_VALLEYVIEW(dev)) { + if (vlv_edp_is_psr_enabled_on_pipe(dev, intel_crtc->pipe)) + return; + } else + if (intel_edp_is_psr_enabled(dev)) + return; /* Enable PSR on the panel */ - intel_edp_psr_enable_sink(intel_dp); + dev_priv->psr.enable_sink(intel_dp); /* Enable PSR on the host */ - intel_edp_psr_enable_source(intel_dp); + dev_priv->psr.enable_source(intel_dp); } void intel_edp_psr_enable(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); + struct drm_i915_private *dev_priv = dev->dev_private; if (!HAS_PSR(dev)) { DRM_DEBUG_KMS("PSR not supported on this platform\n"); @@ -1819,13 +1894,35 @@ void intel_edp_psr_enable(struct intel_dp *intel_dp) } /* Setup PSR once */ - intel_edp_psr_setup(intel_dp); + dev_priv->psr.setup(intel_dp); - if (intel_edp_psr_match_conditions(intel_dp) && - !intel_edp_is_psr_enabled(dev)) + if (intel_edp_psr_match_conditions(intel_dp)) intel_edp_psr_do_enable(intel_dp); } +void vlv_edp_psr_disable(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = + to_intel_crtc(intel_dig_port->base.base.crtc); + uint32_t val; + + if (!dev_priv->psr.setup_done) + return; + + if (wait_for((I915_READ(VLV_PSRSTAT(intel_crtc->pipe)) & + VLV_EDP_PSR_IN_TRANS) == 0, 250)) + WARN(1, "PSR transition took longer than expected\n"); + + val = I915_READ(VLV_PSRCTL(intel_crtc->pipe)); + val &= ~VLV_EDP_PSR_ACTIVE_ENTRY; + val &= ~VLV_EDP_PSR_ENABLE; + val &= ~VLV_EDP_PSR_MODE_MASK; + I915_WRITE(VLV_PSRCTL(intel_crtc->pipe), val); +} + void intel_edp_psr_disable(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); @@ -1860,13 +1957,33 @@ void intel_edp_psr_update(struct drm_device *dev) intel_dp = enc_to_intel_dp(&encoder->base); if (!intel_edp_psr_match_conditions(intel_dp)) - intel_edp_psr_disable(intel_dp); + if (IS_VALLEYVIEW(dev)) + vlv_edp_psr_disable(intel_dp); + else + intel_edp_psr_disable(intel_dp); else - if (!intel_edp_is_psr_enabled(dev)) - intel_edp_psr_do_enable(intel_dp); + intel_edp_psr_do_enable(intel_dp); } } +void intel_edp_psr_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (!HAS_PSR(dev)) + return; + + if (IS_VALLEYVIEW(dev)) { + dev_priv->psr.setup = vlv_edp_psr_setup; + dev_priv->psr.enable_sink = vlv_edp_psr_enable_sink; + dev_priv->psr.enable_source = vlv_edp_psr_enable_source; + } else { + dev_priv->psr.setup = intel_edp_psr_setup; + dev_priv->psr.enable_sink = intel_edp_psr_enable_sink; + dev_priv->psr.enable_source = intel_edp_psr_enable_source; + } +} + static void intel_disable_dp(struct intel_encoder *encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 180d602..2e4516d 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -757,6 +757,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp); void intel_edp_psr_enable(struct intel_dp *intel_dp); void intel_edp_psr_disable(struct intel_dp *intel_dp); void intel_edp_psr_update(struct drm_device *dev); +void intel_edp_psr_init(struct drm_device *dev); /* intel_dsi.c */