From patchwork Fri May 16 00:13:05 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rodrigo Vivi X-Patchwork-Id: 4186521 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 70C8C9FBDB for ; Fri, 16 May 2014 00:13:32 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5C6472039C for ; Fri, 16 May 2014 00:13:31 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 2F20C20397 for ; Fri, 16 May 2014 00:13:30 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8BB4F6EF3F; Thu, 15 May 2014 17:13:29 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-pb0-f43.google.com (mail-pb0-f43.google.com [209.85.160.43]) by gabe.freedesktop.org (Postfix) with ESMTP id EFD996EF3F for ; Thu, 15 May 2014 17:13:27 -0700 (PDT) Received: by mail-pb0-f43.google.com with SMTP id up15so1771870pbc.2 for ; Thu, 15 May 2014 17:13:27 -0700 (PDT) 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; bh=QlRjkmpO2IhKEKfeDkeFKIF0Hhr3lOUkOs8h7tBFImI=; b=mTg9cjsqRfRo81+xFP+P5xHxnJIkVo3G/nUCBR2V+E+lXHgnzfkKBGMLFdEC6JnPnB GifZC5Wc2bn8RITaRukGmr19e909AkbZO1TJiUlTkobjJXvVEx6c70dZ3AtxN3PLxz+V jiL/fTx2CHNRC6vKgVFUAMK7N0PF7PI15Coude+UUlKFTFOVOLwNK3HpFHJ/arfESpV+ apkCRuqY0x5uLWtWPpvlWLDkTNow7bUzXqG/cFiF00qPY9S15GkjtL7APx5WhivwJXDL p/dzq+Fp6+MEFziQWto7rJazPVMSztiFFBg+B5fisz8/I9dwdNVHO0ZD2o7m0m+gfV6z bGfA== X-Received: by 10.66.240.197 with SMTP id wc5mr16336086pac.78.1400199207756; Thu, 15 May 2014 17:13:27 -0700 (PDT) Received: from localhost (jfdmzpr05-ext.jf.intel.com. [134.134.139.74]) by mx.google.com with ESMTPSA id hk5sm11172331pbb.86.2014.05.15.17.13.26 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 15 May 2014 17:13:27 -0700 (PDT) From: Rodrigo Vivi To: intel-gfx@lists.freedesktop.org Date: Thu, 15 May 2014 20:13:05 -0400 Message-Id: <1400199190-2424-7-git-send-email-rodrigo.vivi@gmail.com> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1400199190-2424-1-git-send-email-rodrigo.vivi@gmail.com> References: <1400199190-2424-1-git-send-email-rodrigo.vivi@gmail.com> Subject: [Intel-gfx] [PATCH 06/11] drm/i915: Force PSR exit by inactivating it. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.7 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 The perfect solution for psr_exit is the hardware tracking the changes and doing the psr exit by itself. This scenario works for HSW and BDW with some environments like Gnome and Wayland. However there are many other scenarios that this isn't true. Mainly one right now is KDE users on HSW and BDW with PSR on. User would miss many screen updates. For instances any key typed could be seen only when mouse cursor is moved. So this patch introduces the ability of trigger PSR exit on kernel side on some common cases that. Most of the cases are coverred by psr_exit at set_domain. The remaining cases are coverred by triggering it at set_domain, busy_ioctl, sw_finish and mark_busy. The downside here might be reducing the residency time on the cases this already work very wall like Gnome environment. But so far let's get focused on fixinge issues sio PSR couild be used for everybody and we could even get it enabled by default. Later we can add some alternatives to choose the level of PSR efficiency over boot flag of even over crtc property. Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 3 ++ drivers/gpu/drm/i915/i915_gem.c | 6 +++ drivers/gpu/drm/i915/intel_display.c | 20 +++++++- drivers/gpu/drm/i915/intel_dp.c | 91 ++++++++++++++++++++++++++++++++---- drivers/gpu/drm/i915/intel_drv.h | 3 ++ 5 files changed, 111 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d6fba46..173114c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -641,6 +641,9 @@ struct i915_psr { bool sink_support; bool source_ok; bool setup_done; + bool enabled; + bool active; + struct delayed_work work; }; enum intel_pch { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a000a8b..da66405 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1275,6 +1275,8 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, goto unlock; } + intel_edp_psr_exit(dev, true); + /* Try to flush the object off the GPU without holding the lock. * We will repeat the flush holding the lock in the normal manner * to catch cases where we are gazumped. @@ -1320,6 +1322,8 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, if (ret) return ret; + intel_edp_psr_exit(dev, true); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); if (&obj->base == NULL) { ret = -ENOENT; @@ -4018,6 +4022,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, if (ret) return ret; + intel_edp_psr_exit(dev, true); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); if (&obj->base == NULL) { ret = -ENOENT; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 767ca96..b8b288f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4801,6 +4801,8 @@ static void intel_connector_check_state(struct intel_connector *connector) * consider. */ void intel_connector_dpms(struct drm_connector *connector, int mode) { + struct drm_device *dev = connector->dev; + struct intel_encoder *intel_encoder; /* All the simple cases only support two dpms states. */ if (mode != DRM_MODE_DPMS_ON) mode = DRM_MODE_DPMS_OFF; @@ -4811,9 +4813,15 @@ void intel_connector_dpms(struct drm_connector *connector, int mode) connector->dpms = mode; /* Only need to change hw state when actually enabled */ - if (connector->encoder) - intel_encoder_dpms(to_intel_encoder(connector->encoder), mode); + if (connector->encoder) { + + intel_encoder = to_intel_encoder(connector->encoder); + intel_encoder_dpms(intel_encoder, mode); + if (intel_encoder->type == INTEL_OUTPUT_EDP && + mode == DRM_MODE_DPMS_OFF) + intel_edp_psr_exit(dev, false); + } intel_modeset_check_state(connector->dev); } @@ -8712,12 +8720,15 @@ out: intel_runtime_pm_put(dev_priv); } + void intel_mark_fb_busy(struct drm_i915_gem_object *obj, struct intel_ring_buffer *ring) { struct drm_device *dev = obj->base.dev; struct drm_crtc *crtc; + intel_edp_psr_exit(dev, true); + if (!i915.powersave) return; @@ -9196,6 +9207,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (work == NULL) return -ENOMEM; + /* Exit PSR early in page flip */ + intel_edp_psr_exit(dev, true); + work->event = event; work->crtc = crtc; work->old_fb_obj = to_intel_framebuffer(old_fb)->obj; @@ -11072,6 +11086,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 8b2f1a4..59baee5 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1789,10 +1789,11 @@ 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; - if (!intel_edp_psr_match_conditions(intel_dp) || - intel_edp_is_psr_enabled(dev)) + if (intel_edp_is_psr_enabled(dev)) return; /* Enable PSR on the panel */ @@ -1800,6 +1801,9 @@ static void intel_edp_psr_do_enable(struct intel_dp *intel_dp) /* Enable PSR on the host */ intel_edp_psr_enable_source(intel_dp); + + dev_priv->psr.enabled = true; + dev_priv->psr.active = true; } void intel_edp_psr_enable(struct intel_dp *intel_dp) @@ -1819,8 +1823,7 @@ void intel_edp_psr_enable(struct intel_dp *intel_dp) /* Setup PSR once */ intel_edp_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); } @@ -1829,7 +1832,7 @@ void intel_edp_psr_disable(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 (!intel_edp_is_psr_enabled(dev)) + if (!dev_priv->psr.enabled) return; I915_WRITE(EDP_PSR_CTL(dev), @@ -1839,13 +1842,13 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp) if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) & EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10)) DRM_ERROR("Timed out waiting for PSR Idle State\n"); + + dev_priv->psr.enabled = false; } void intel_edp_psr_update(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_encoder *encoder; - struct intel_dp *intel_dp = NULL; if (!HAS_PSR(dev)) return; @@ -1853,6 +1856,17 @@ void intel_edp_psr_update(struct drm_device *dev) if (!dev_priv->psr.setup_done) return; + intel_edp_psr_exit(dev, true); +} + +void intel_edp_psr_work(struct work_struct *work) +{ + struct drm_i915_private *dev_priv = + container_of(work, typeof(*dev_priv), psr.work.work); + struct drm_device *dev = dev_priv->dev; + struct intel_encoder *encoder; + struct intel_dp *intel_dp = NULL; + list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) if (encoder->type == INTEL_OUTPUT_EDP) { intel_dp = enc_to_intel_dp(&encoder->base); @@ -1860,9 +1874,66 @@ void intel_edp_psr_update(struct drm_device *dev) if (!intel_edp_psr_match_conditions(intel_dp)) 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_inactivate(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_connector *connector; + struct intel_encoder *encoder; + struct intel_crtc *intel_crtc; + struct intel_dp *intel_dp = NULL; + + list_for_each_entry(connector, &dev->mode_config.connector_list, + base.head) { + + if (connector->base.dpms != DRM_MODE_DPMS_ON) + continue; + + encoder = to_intel_encoder(connector->base.encoder); + if (encoder->type == INTEL_OUTPUT_EDP) { + + intel_dp = enc_to_intel_dp(&encoder->base); + intel_crtc = to_intel_crtc(encoder->base.crtc); + + dev_priv->psr.active = false; + + I915_WRITE(EDP_PSR_CTL(dev), I915_READ(EDP_PSR_CTL(dev)) + & ~EDP_PSR_ENABLE); } + } +} + +void intel_edp_psr_exit(struct drm_device *dev, bool schedule_back) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (!HAS_PSR(dev)) + return; + + if (!dev_priv->psr.setup_done) + return; + + cancel_delayed_work_sync(&dev_priv->psr.work); + + if (dev_priv->psr.active) + intel_edp_psr_inactivate(dev); + + if (schedule_back) + schedule_delayed_work(&dev_priv->psr.work, + msecs_to_jiffies(100)); +} + +void intel_edp_psr_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (!HAS_PSR(dev)) + return; + + INIT_DELAYED_WORK(&dev_priv->psr.work, intel_edp_psr_work); } static void intel_disable_dp(struct intel_encoder *encoder) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e72d45a..92164d6 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -815,6 +815,9 @@ 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_dp_set_drrs_state(struct drm_device *dev, int refresh_rate); +void intel_edp_psr_exit(struct drm_device *dev, bool schedule_back); +void intel_edp_psr_init(struct drm_device *dev); + /* intel_dsi.c */ bool intel_dsi_init(struct drm_device *dev);