From patchwork Thu Feb 16 18:07:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= X-Patchwork-Id: 9577955 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1DD6460244 for ; Thu, 16 Feb 2017 18:08:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1186E28659 for ; Thu, 16 Feb 2017 18:08:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 061E02865B; Thu, 16 Feb 2017 18:08:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7AABB28659 for ; Thu, 16 Feb 2017 18:08:13 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D4EBE6EBFC; Thu, 16 Feb 2017 18:08:12 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by gabe.freedesktop.org (Postfix) with ESMTPS id 8E4F96EBFC for ; Thu, 16 Feb 2017 18:08:11 +0000 (UTC) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga105.fm.intel.com with ESMTP; 16 Feb 2017 10:08:11 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.35,169,1484035200"; d="scan'208"; a="1128504868" Received: from stinkbox.fi.intel.com (HELO stinkbox) ([10.237.72.174]) by fmsmga002.fm.intel.com with SMTP; 16 Feb 2017 10:08:09 -0800 Received: by stinkbox (sSMTP sendmail emulation); Thu, 16 Feb 2017 20:08:08 +0200 From: ville.syrjala@linux.intel.com To: intel-gfx@lists.freedesktop.org Date: Thu, 16 Feb 2017 20:07:39 +0200 Message-Id: <20170216180751.3097-7-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20170216180751.3097-1-ville.syrjala@linux.intel.com> References: <20170216180751.3097-1-ville.syrjala@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 06/18] drm/i915: Compute VLV/CHV FIFO sizes based on the PM2 watermarks X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP From: Ville Syrjälä Let's compute the watermarks first and the FIFO size second. This way we can make sure the FIFO split is the most accommodating to the watermarks. Previously we could have potentially computed a FIFO split that couldn't accommodate the PM2 watermarks simply due to a bad split even if the total FIFO size would have been sufficient. It'll also allow us to avoid recomputing the wms for all planes whenever the FIFO split would change. Thus we don't have to add any extra planes to the state when the FIFO needs to be repartitioned. To help with this we'll keep around copies of the non-inverted watermarks in the crtc state. For now that doesn't help too much, but once we start to do the watermark computation only for the planes that change we'll need the non-inverted values around for the other planes. Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_pm.c | 116 +++++++++++++++++++-------------------- 2 files changed, 57 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 493a37b089fb..ada5fd3fdeab 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -534,6 +534,8 @@ struct intel_crtc_wm_state { } skl; struct { + /* non-inverted optimal watermarks */ + struct vlv_pipe_wm noninverted[NUM_VLV_WM_LEVELS]; struct vlv_fifo_state fifo_state; /* inverted optimal watermarks */ struct vlv_wm_state optimal; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9371b9645c9d..ad02edb11ca2 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1018,73 +1018,70 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state, return min_t(int, wm, USHRT_MAX); } -static void vlv_compute_fifo(struct intel_crtc_state *crtc_state) +static int vlv_compute_fifo(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal; + const struct vlv_pipe_wm *noninverted = + &crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM2]; struct vlv_fifo_state *fifo_state = &crtc_state->wm.vlv.fifo_state; - struct drm_device *dev = crtc->base.dev; - struct intel_plane *plane; - unsigned int total_rate = 0; - const int fifo_size = 512 - 1; + unsigned int active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR); + int num_active_planes = hweight32(active_planes); + const int fifo_size = 511; int fifo_extra, fifo_left = fifo_size; + unsigned int total_rate; + enum plane_id plane_id; - for_each_intel_plane_on_crtc(dev, crtc, plane) { - struct intel_plane_state *state = - to_intel_plane_state(plane->base.state); + total_rate = noninverted->plane[PLANE_PRIMARY] + + noninverted->plane[PLANE_SPRITE0] + + noninverted->plane[PLANE_SPRITE1]; - if (plane->id == PLANE_CURSOR) - continue; + if (total_rate > fifo_size) + return -EINVAL; - if (state->base.visible) { - wm_state->num_active_planes++; - total_rate += state->base.fb->format->cpp[0]; - } - } + if (total_rate == 0) + total_rate = 1; - for_each_intel_plane_on_crtc(dev, crtc, plane) { - struct intel_plane_state *state = - to_intel_plane_state(plane->base.state); + for_each_plane_id_on_crtc(crtc, plane_id) { unsigned int rate; - if (plane->id == PLANE_CURSOR) { - fifo_state->plane[plane->id] = 63; + if ((active_planes & BIT(plane_id)) == 0) { + fifo_state->plane[plane_id] = 0; continue; } - if (!state->base.visible) { - fifo_state->plane[plane->id] = 0; - continue; - } - - rate = state->base.fb->format->cpp[0]; - fifo_state->plane[plane->id] = fifo_size * rate / total_rate; - fifo_left -= fifo_state->plane[plane->id]; + rate = noninverted->plane[plane_id]; + fifo_state->plane[plane_id] = fifo_size * rate / total_rate; + fifo_left -= fifo_state->plane[plane_id]; } - fifo_extra = DIV_ROUND_UP(fifo_left, wm_state->num_active_planes ?: 1); + fifo_state->plane[PLANE_CURSOR] = 63; + + fifo_extra = DIV_ROUND_UP(fifo_left, num_active_planes ?: 1); /* spread the remainder evenly */ - for_each_intel_plane_on_crtc(dev, crtc, plane) { + for_each_plane_id_on_crtc(crtc, plane_id) { int plane_extra; if (fifo_left == 0) break; - if (plane->id == PLANE_CURSOR) - continue; - - /* give it all to the first plane if none are active */ - if (fifo_state->plane[plane->id] == 0 && - wm_state->num_active_planes) + if ((active_planes & BIT(plane_id)) == 0) continue; plane_extra = min(fifo_extra, fifo_left); - fifo_state->plane[plane->id] += plane_extra; + fifo_state->plane[plane_id] += plane_extra; fifo_left -= plane_extra; } - WARN_ON(fifo_left != 0); + WARN_ON(active_planes != 0 && fifo_left != 0); + + /* give it all to the first plane if none are active */ + if (active_planes == 0) { + WARN_ON(fifo_left != fifo_size); + fifo_state->plane[PLANE_PRIMARY] = fifo_left; + } + + return 0; } static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size) @@ -1129,35 +1126,33 @@ static void vlv_compute_wm(struct intel_crtc_state *crtc_state) struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal; - const struct vlv_fifo_state *fifo_state = - &crtc_state->wm.vlv.fifo_state; struct intel_plane *plane; int level; memset(wm_state, 0, sizeof(*wm_state)); + memset(crtc_state->wm.vlv.noninverted, 0, + sizeof(crtc_state->wm.vlv.noninverted)); wm_state->cxsr = crtc->pipe != PIPE_C && crtc->wm.cxsr_allowed; wm_state->num_levels = dev_priv->wm.max_level + 1; wm_state->num_active_planes = 0; - vlv_compute_fifo(crtc_state); - if (wm_state->num_active_planes != 1) wm_state->cxsr = false; for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) { struct intel_plane_state *state = to_intel_plane_state(plane->base.state); - int level; if (!state->base.visible) continue; - /* normal watermarks */ for (level = 0; level < wm_state->num_levels; level++) { + struct vlv_pipe_wm *noninverted = + &crtc_state->wm.vlv.noninverted[level]; int wm = vlv_compute_wm_level(crtc_state, state, level); - int max_wm = fifo_state->plane[plane->id]; + int max_wm = plane->id == PLANE_CURSOR ? 63 : 511; /* hack */ if (WARN_ON(level == 0 && wm > max_wm)) @@ -1166,25 +1161,24 @@ static void vlv_compute_wm(struct intel_crtc_state *crtc_state) if (wm > max_wm) break; - wm_state->wm[level].plane[plane->id] = wm; + noninverted->plane[plane->id] = wm; } wm_state->num_levels = level; + } - if (!wm_state->cxsr) - continue; - - /* maxfifo watermarks */ - if (plane->id == PLANE_CURSOR) { - for (level = 0; level < wm_state->num_levels; level++) - wm_state->sr[level].cursor = - wm_state->wm[level].plane[PLANE_CURSOR]; - } else { - for (level = 0; level < wm_state->num_levels; level++) - wm_state->sr[level].plane = - max(wm_state->sr[level].plane, - wm_state->wm[level].plane[plane->id]); - } + vlv_compute_fifo(crtc_state); + + for (level = 0; level < wm_state->num_levels; level++) { + struct vlv_pipe_wm *noninverted = + &crtc_state->wm.vlv.noninverted[level]; + + wm_state->wm[level] = *noninverted; + + wm_state->sr[level].plane = max3(noninverted->plane[PLANE_PRIMARY], + noninverted->plane[PLANE_SPRITE0], + noninverted->plane[PLANE_SPRITE1]); + wm_state->sr[level].cursor = noninverted->plane[PLANE_CURSOR]; } /* clear any (partially) filled invalid levels */