From patchwork Mon Jun 1 10:49:59 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maarten Lankhorst X-Patchwork-Id: 6520561 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 1F108C0433 for ; Mon, 1 Jun 2015 10:50:40 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BD542205FA for ; Mon, 1 Jun 2015 10:50:38 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 5B782205F7 for ; Mon, 1 Jun 2015 10:50:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C7F856E5AE; Mon, 1 Jun 2015 03:50:33 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mblankhorst.nl (mblankhorst.nl [141.105.120.124]) by gabe.freedesktop.org (Postfix) with ESMTP id 8F8D86E5B3 for ; Mon, 1 Jun 2015 03:50:32 -0700 (PDT) Received: from patser.lan (5ED48611.cm-7-5c.dynamic.ziggo.nl [94.212.134.17]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: mlankhorst) by mblankhorst.nl (Postfix) with ESMTPSA id CD8E918C022; Mon, 1 Jun 2015 12:50:30 +0200 (CEST) From: Maarten Lankhorst To: intel-gfx@lists.freedesktop.org Date: Mon, 1 Jun 2015 12:49:59 +0200 Message-Id: <1433155811-9671-16-git-send-email-maarten.lankhorst@linux.intel.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1433155811-9671-1-git-send-email-maarten.lankhorst@linux.intel.com> References: <1433155811-9671-1-git-send-email-maarten.lankhorst@linux.intel.com> Cc: Ander Conselvan de Oliveira Subject: [Intel-gfx] [PATCH v4 15/27] drm/i915: Use global atomic state for staged pll config, v2. 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: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_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 From: Ander Conselvan de Oliveira Now that we can subclass drm_atomic_state we can also use it to keep track of all the pll settings. atomic_state is a better place to hold all shared state than keeping pll->new_config everywhere. Changes since v1: - Assert connection_mutex is held. Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Maarten Lankhorst Reviewed-by: Matt Roper --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_atomic.c | 51 ++++++++++++++++ drivers/gpu/drm/i915/intel_display.c | 111 +++++++++++------------------------ drivers/gpu/drm/i915/intel_drv.h | 13 ++++ 4 files changed, 97 insertions(+), 79 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 862bb9d4b08d..0cdc81c0e6e1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -376,7 +376,6 @@ struct intel_shared_dpll_config { struct intel_shared_dpll { struct intel_shared_dpll_config config; - struct intel_shared_dpll_config *new_config; int active; /* count of number of active CRTCs (i.e. DPMS on) */ bool on; /* is the PLL actually active? Disabled during modeset */ diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 7ed8033aae60..6ab82dc56cea 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -421,3 +421,54 @@ int intel_atomic_setup_scalers(struct drm_device *dev, return 0; } + +static void +intel_atomic_duplicate_dpll_state(struct drm_i915_private *dev_priv, + struct intel_shared_dpll_config *shared_dpll) +{ + enum intel_dpll_id i; + + /* Copy shared dpll state */ + for (i = 0; i < dev_priv->num_shared_dpll; i++) { + struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; + + shared_dpll[i] = pll->config; + } +} + +struct intel_shared_dpll_config * +intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) +{ + struct intel_atomic_state *state = to_intel_atomic_state(s); + + WARN_ON(!drm_modeset_is_locked(&s->dev->mode_config.connection_mutex)); + + if (!state->dpll_set) { + state->dpll_set = true; + + intel_atomic_duplicate_dpll_state(to_i915(s->dev), + state->shared_dpll); + } + + return state->shared_dpll; +} + +struct drm_atomic_state * +intel_atomic_state_alloc(struct drm_device *dev) +{ + struct intel_atomic_state *state = kzalloc(GFP_KERNEL, sizeof(*state)); + + if (!state || drm_atomic_state_init(dev, &state->base) < 0) { + kfree(state); + return NULL; + } + + return &state->base; +} + +void intel_atomic_state_clear(struct drm_atomic_state *s) +{ + struct intel_atomic_state *state = to_intel_atomic_state(s); + drm_atomic_state_default_clear(&state->base); + state->dpll_set = false; +} diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3ec324651b8a..3538a1059db0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4186,8 +4186,11 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_shared_dpll *pll; + struct intel_shared_dpll_config *shared_dpll; enum intel_dpll_id i; + shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state); + if (HAS_PCH_IBX(dev_priv->dev)) { /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */ i = (enum intel_dpll_id) crtc->pipe; @@ -4196,7 +4199,7 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", crtc->base.base.id, pll->name); - WARN_ON(pll->new_config->crtc_mask); + WARN_ON(shared_dpll[i].crtc_mask); goto found; } @@ -4216,7 +4219,7 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, pll = &dev_priv->shared_dplls[i]; DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", crtc->base.base.id, pll->name); - WARN_ON(pll->new_config->crtc_mask); + WARN_ON(shared_dpll[i].crtc_mask); goto found; } @@ -4225,15 +4228,15 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, pll = &dev_priv->shared_dplls[i]; /* Only want to check enabled timings first */ - if (pll->new_config->crtc_mask == 0) + if (shared_dpll[i].crtc_mask == 0) continue; if (memcmp(&crtc_state->dpll_hw_state, - &pll->new_config->hw_state, - sizeof(pll->new_config->hw_state)) == 0) { + &shared_dpll[i].hw_state, + sizeof(crtc_state->dpll_hw_state)) == 0) { DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, ative %d)\n", crtc->base.base.id, pll->name, - pll->new_config->crtc_mask, + shared_dpll[i].crtc_mask, pll->active); goto found; } @@ -4242,7 +4245,7 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, /* Ok no matching timings, maybe there's a free one? */ for (i = 0; i < dev_priv->num_shared_dpll; i++) { pll = &dev_priv->shared_dplls[i]; - if (pll->new_config->crtc_mask == 0) { + if (shared_dpll[i].crtc_mask == 0) { DRM_DEBUG_KMS("CRTC:%d allocated %s\n", crtc->base.base.id, pll->name); goto found; @@ -4252,83 +4255,33 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, return NULL; found: - if (pll->new_config->crtc_mask == 0) - pll->new_config->hw_state = crtc_state->dpll_hw_state; + if (shared_dpll[i].crtc_mask == 0) + shared_dpll[i].hw_state = + crtc_state->dpll_hw_state; crtc_state->shared_dpll = i; DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name, pipe_name(crtc->pipe)); - pll->new_config->crtc_mask |= 1 << crtc->pipe; + shared_dpll[i].crtc_mask |= 1 << crtc->pipe; return pll; } -/** - * intel_shared_dpll_start_config - start a new PLL staged config - * @dev_priv: DRM device - * @clear_pipes: mask of pipes that will have their PLLs freed - * - * Starts a new PLL staged config, copying the current config but - * releasing the references of pipes specified in clear_pipes. - */ -static int intel_shared_dpll_start_config(struct drm_i915_private *dev_priv, - unsigned clear_pipes) -{ - struct intel_shared_dpll *pll; - enum intel_dpll_id i; - - for (i = 0; i < dev_priv->num_shared_dpll; i++) { - pll = &dev_priv->shared_dplls[i]; - - pll->new_config = kmemdup(&pll->config, sizeof pll->config, - GFP_KERNEL); - if (!pll->new_config) - goto cleanup; - - pll->new_config->crtc_mask &= ~clear_pipes; - } - - return 0; - -cleanup: - while (--i >= 0) { - pll = &dev_priv->shared_dplls[i]; - kfree(pll->new_config); - pll->new_config = NULL; - } - - return -ENOMEM; -} - -static void intel_shared_dpll_commit(struct drm_i915_private *dev_priv) +static void intel_shared_dpll_commit(struct drm_atomic_state *state) { + struct drm_i915_private *dev_priv = to_i915(state->dev); + struct intel_shared_dpll_config *shared_dpll; struct intel_shared_dpll *pll; enum intel_dpll_id i; - for (i = 0; i < dev_priv->num_shared_dpll; i++) { - pll = &dev_priv->shared_dplls[i]; - - WARN_ON(pll->new_config == &pll->config); - - pll->config = *pll->new_config; - kfree(pll->new_config); - pll->new_config = NULL; - } -} - -static void intel_shared_dpll_abort_config(struct drm_i915_private *dev_priv) -{ - struct intel_shared_dpll *pll; - enum intel_dpll_id i; + if (!to_intel_atomic_state(state)->dpll_set) + return; + shared_dpll = to_intel_atomic_state(state)->shared_dpll; for (i = 0; i < dev_priv->num_shared_dpll; i++) { pll = &dev_priv->shared_dplls[i]; - - WARN_ON(pll->new_config == &pll->config); - - kfree(pll->new_config); - pll->new_config = NULL; + pll->config = shared_dpll[i]; } } @@ -11975,13 +11928,12 @@ static void intel_modeset_update_state(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *intel_encoder; struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; struct drm_connector *connector; - intel_shared_dpll_commit(dev_priv); + intel_shared_dpll_commit(state); drm_atomic_helper_swap_state(state->dev, state); for_each_intel_encoder(dev, intel_encoder) { @@ -12610,9 +12562,13 @@ static int __intel_set_mode_setup_plls(struct drm_atomic_state *state) } } - ret = intel_shared_dpll_start_config(dev_priv, clear_pipes); - if (ret) - goto done; + if (clear_pipes) { + struct intel_shared_dpll_config *shared_dpll = + intel_atomic_get_shared_dpll_state(state); + + for (i = 0; i < dev_priv->num_shared_dpll; i++) + shared_dpll[i].crtc_mask &= ~clear_pipes; + } for_each_crtc_in_state(state, crtc, crtc_state, i) { if (!needs_modeset(crtc_state) || !crtc_state->enable) @@ -12623,13 +12579,10 @@ static int __intel_set_mode_setup_plls(struct drm_atomic_state *state) ret = dev_priv->display.crtc_compute_clock(intel_crtc, intel_crtc_state); - if (ret) { - intel_shared_dpll_abort_config(dev_priv); - goto done; - } + if (ret) + return ret; } -done: return ret; } @@ -14324,6 +14277,8 @@ static const struct drm_mode_config_funcs intel_mode_funcs = { .output_poll_changed = intel_fbdev_output_poll_changed, .atomic_check = intel_atomic_check, .atomic_commit = intel_atomic_commit, + .atomic_state_alloc = intel_atomic_state_alloc, + .atomic_state_clear = intel_atomic_state_clear, }; /* Set up chip specific display functions */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b9082fd16792..ddae28ac4e6f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -241,6 +241,13 @@ typedef struct dpll { int p; } intel_clock_t; +struct intel_atomic_state { + struct drm_atomic_state base; + + bool dpll_set; + struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS]; +}; + struct intel_plane_state { struct drm_plane_state base; struct drm_rect src; @@ -628,6 +635,7 @@ struct cxsr_latency { unsigned long cursor_hpll_disable; }; +#define to_intel_atomic_state(x) container_of(x, struct intel_atomic_state, base) #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) #define to_intel_crtc_state(x) container_of(x, struct intel_crtc_state, base) #define to_intel_connector(x) container_of(x, struct intel_connector, base) @@ -1405,6 +1413,11 @@ int intel_connector_atomic_get_property(struct drm_connector *connector, struct drm_crtc_state *intel_crtc_duplicate_state(struct drm_crtc *crtc); void intel_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state); +struct drm_atomic_state *intel_atomic_state_alloc(struct drm_device *dev); +void intel_atomic_state_clear(struct drm_atomic_state *); +struct intel_shared_dpll_config * +intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s); + static inline struct intel_crtc_state * intel_atomic_get_crtc_state(struct drm_atomic_state *state, struct intel_crtc *crtc)