From patchwork Sun Jan 19 12:47:13 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ramalingam C X-Patchwork-Id: 3509561 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 5DB249F2D6 for ; Sun, 19 Jan 2014 12:47:29 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 627EB2011E for ; Sun, 19 Jan 2014 12:47:28 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 6B1D82010B for ; Sun, 19 Jan 2014 12:47:27 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 5C09AFA263; Sun, 19 Jan 2014 04:47:25 -0800 (PST) X-Original-To: Intel-gfx@lists.freedesktop.org Delivered-To: Intel-gfx@lists.freedesktop.org Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by gabe.freedesktop.org (Postfix) with ESMTP id 09600FA263 for ; Sun, 19 Jan 2014 04:47:22 -0800 (PST) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP; 19 Jan 2014 04:47:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.95,684,1384329600"; d="scan'208";a="461243531" Received: from ramaling-desktop.iind.intel.com ([10.223.25.129]) by fmsmga001.fm.intel.com with ESMTP; 19 Jan 2014 04:47:21 -0800 From: Ramalingam C To: Intel-gfx@lists.freedesktop.org Date: Sun, 19 Jan 2014 18:17:13 +0530 Message-Id: <1390135633-10465-1-git-send-email-ramalingam.c@intel.com> X-Mailer: git-send-email 1.7.9.5 Subject: [Intel-gfx] [PATCH] drm/i915: deferring the HSW IPS enable at plane switch 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: , MIME-Version: 1.0 Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, 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 To remove the wait_for_vblank from the plane switch execution path, this change implements a function which will add a delayed work to defer the IPS enable. The delay is nothing but frame length, which is calculated based on vrefresh of the hwmode. i.e IPS enable will be scheduled after a frame. If mode is not set during the plane switch (__unlikely__), delay will fallback to a default value 100mSec (can handle the FPS >= 10). Signed-off-by: Ramalingam C --- drivers/gpu/drm/i915/intel_display.c | 58 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 8 +++++ drivers/gpu/drm/i915/intel_sprite.c | 3 +- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e77d4b8..9aa66d5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -52,6 +52,7 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc, static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *old_fb); +#define IPS_DEFAULT_SCHEDULED_DELAY_MSECS 100 /* For >=10FPS */ typedef struct { int min, max; @@ -3452,6 +3453,53 @@ void hsw_enable_ips(struct intel_crtc *crtc) } } +void intel_ips_deferred_work_fn(struct work_struct *__work) +{ + struct intel_ips_deferred_work *work = container_of( + to_delayed_work(__work), struct intel_ips_deferred_work, + delayed_work); + struct intel_crtc *intel_crtc = to_intel_crtc(work->crtc); + + hsw_enable_ips(intel_crtc); + kfree(work); + intel_crtc->ips_deferred_work = NULL; +} + +int hsw_deferred_ips_enable(struct drm_crtc *crtc) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_ips_deferred_work *work; + int delay = 0; + + /* Canceling any previous pending IPS deferred work, if any */ + if (intel_crtc->ips_deferred_work) { + work = intel_crtc->ips_deferred_work; + cancel_delayed_work_sync(&work->delayed_work); + kfree(work); + intel_crtc->ips_deferred_work = NULL; + } + + /* Awaits unnecessary load to wq */ + if (!intel_crtc->primary_enabled) + return -EPERM; + + work = kzalloc(sizeof(*work), GFP_KERNEL); + if (work == NULL) + return -ENOMEM; + + work->crtc = crtc; + INIT_DELAYED_WORK(&work->delayed_work, intel_ips_deferred_work_fn); + intel_crtc->ips_deferred_work = work; + + /* If mode is set, frame length is calculated, else default delay + * is used */ + delay = crtc->hwmode.vrefresh ? (1000 / crtc->hwmode.vrefresh) : + IPS_DEFAULT_SCHEDULED_DELAY_MSECS; + schedule_delayed_work(&work->delayed_work, msecs_to_jiffies(delay)); + + return 0; +} + void hsw_disable_ips(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; @@ -8218,6 +8266,7 @@ static void intel_crtc_destroy(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_device *dev = crtc->dev; struct intel_unpin_work *work; + struct intel_ips_deferred_work *ips_deferred_work; unsigned long flags; spin_lock_irqsave(&dev->event_lock, flags); @@ -8230,6 +8279,13 @@ static void intel_crtc_destroy(struct drm_crtc *crtc) kfree(work); } + if (intel_crtc->ips_deferred_work) { + ips_deferred_work = intel_crtc->ips_deferred_work; + cancel_delayed_work_sync(&(ips_deferred_work->delayed_work)); + kfree(ips_deferred_work); + intel_crtc->ips_deferred_work = NULL; + } + intel_crtc_cursor_set(crtc, NULL, 0, 0, 0); drm_crtc_cleanup(crtc); @@ -10193,6 +10249,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc->plane = !pipe; } + intel_crtc->ips_deferred_work = NULL; + BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL); dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8754db9..aad4cf5 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -347,6 +347,8 @@ struct intel_crtc { atomic_t unpin_work_count; + struct intel_ips_deferred_work *ips_deferred_work; + /* Display surface base address adjustement for pageflips. Note that on * gen4+ this only adjusts up to a tile, offsets within a tile are * handled in the hw itself (with the TILEOFF register). */ @@ -524,6 +526,11 @@ intel_get_crtc_for_plane(struct drm_device *dev, int plane) return dev_priv->plane_to_crtc_mapping[plane]; } +struct intel_ips_deferred_work { + struct delayed_work delayed_work; + struct drm_crtc *crtc; +}; + struct intel_unpin_work { struct work_struct work; struct drm_crtc *crtc; @@ -707,6 +714,7 @@ ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config, bool intel_crtc_active(struct drm_crtc *crtc); void hsw_enable_ips(struct intel_crtc *crtc); void hsw_disable_ips(struct intel_crtc *crtc); +int hsw_deferred_ips_enable(struct drm_crtc *crtc); void intel_display_set_init_power(struct drm_device *dev, bool enable); int valleyview_get_vco(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index fe4de89..e2c71c8 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -541,8 +541,7 @@ intel_enable_primary(struct drm_crtc *crtc) * versa. */ if (intel_crtc->config.ips_enabled) { - intel_wait_for_vblank(dev, intel_crtc->pipe); - hsw_enable_ips(intel_crtc); + hsw_deferred_ips_enable(crtc); } mutex_lock(&dev->struct_mutex);