From patchwork Thu Sep 3 18:50:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ville Syrjala X-Patchwork-Id: 7118641 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 3484EBEEC1 for ; Thu, 3 Sep 2015 18:51:06 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 11C052046F for ; Thu, 3 Sep 2015 18:51:05 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id ABD65203AB for ; Thu, 3 Sep 2015 18:51:03 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 44D627A163; Thu, 3 Sep 2015 11:51:03 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by gabe.freedesktop.org (Postfix) with ESMTP id B93DA7A163 for ; Thu, 3 Sep 2015 11:51:01 -0700 (PDT) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga103.fm.intel.com with ESMTP; 03 Sep 2015 11:50:45 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.17,463,1437462000"; d="scan'208";a="761790567" Received: from stinkbox.fi.intel.com (HELO stinkbox) ([10.237.72.174]) by orsmga001.jf.intel.com with SMTP; 03 Sep 2015 11:50:44 -0700 Received: by stinkbox (sSMTP sendmail emulation); Thu, 03 Sep 2015 21:50:41 +0300 From: ville.syrjala@linux.intel.com To: intel-gfx@lists.freedesktop.org Date: Thu, 3 Sep 2015 21:50:10 +0300 Message-Id: <1441306216-6581-9-git-send-email-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 2.4.6 In-Reply-To: <1441306216-6581-1-git-send-email-ville.syrjala@linux.intel.com> References: <1441306216-6581-1-git-send-email-ville.syrjala@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 08/14] drm/i915: Compute DSI PLL parameters during .compute_config() 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-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: Ville Syrjälä Compute the DSI PLL parameters during .compute_config() rather than .pre_pll_enable() so that we can fail gracefully if we can't find suitable parameters. In order to do that we need to store the DSI PLL parameters in pipe_config. Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 3 ++ drivers/gpu/drm/i915/intel_drv.h | 5 ++++ drivers/gpu/drm/i915/intel_dsi.c | 16 +++++++---- drivers/gpu/drm/i915/intel_dsi.h | 8 ++++-- drivers/gpu/drm/i915/intel_dsi_pll.c | 56 +++++++++++++++++++++--------------- 5 files changed, 57 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1ec39b0..9a77ca5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12488,6 +12488,9 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1); PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2); + PIPE_CONF_CHECK_X(dsi_pll.ctrl); + PIPE_CONF_CHECK_X(dsi_pll.div); + if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) PIPE_CONF_CHECK_I(pipe_bpp); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index cf971ef..8bb74eb 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -407,6 +407,11 @@ struct intel_crtc_state { /* Actual register state of the dpll, for shared dpll cross-checking. */ struct intel_dpll_hw_state dpll_hw_state; + /* DSI PLL registers */ + struct { + u32 ctrl, div; + } dsi_pll; + int pipe_bpp; struct intel_link_m_n dp_m_n; diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index e0ccaf1..4cf6c0d 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -270,6 +270,7 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder, struct intel_connector *intel_connector = intel_dsi->attached_connector; struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; struct drm_display_mode *adjusted_mode = &config->base.adjusted_mode; + int ret; DRM_DEBUG_KMS("\n"); @@ -279,10 +280,10 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder, /* DSI uses short packets for sync events, so clear mode flags for DSI */ adjusted_mode->flags = 0; - /* - * FIXME move the DSI PLL calc from vlv_enable_dsi_pll() - * to .compute_config(). - */ + ret = vlv_compute_dsi_pll(encoder, config); + if (ret) + return false; + config->clock_set = true; return true; @@ -629,7 +630,8 @@ static void intel_dsi_get_config(struct intel_encoder *encoder, u32 pclk; DRM_DEBUG_KMS("\n"); - pclk = vlv_get_dsi_pclk(encoder, pipe_config->pipe_bpp); + pclk = vlv_get_dsi_pclk(encoder, pipe_config->pipe_bpp, + pipe_config); if (!pclk) return; @@ -900,6 +902,8 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder) { + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); + DRM_DEBUG_KMS("\n"); intel_dsi_prepare(encoder); @@ -909,7 +913,7 @@ static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder) * lock. It needs to be fully powered down to fix it. */ vlv_disable_dsi_pll(encoder); - vlv_enable_dsi_pll(encoder); + vlv_enable_dsi_pll(encoder, intel_crtc->config); } static enum drm_connector_status diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 42a6859..58c39b4 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -124,9 +124,13 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder) return container_of(encoder, struct intel_dsi, base.base); } -extern void vlv_enable_dsi_pll(struct intel_encoder *encoder); +extern int vlv_compute_dsi_pll(struct intel_encoder *encoder, + struct intel_crtc_state *config); +extern void vlv_enable_dsi_pll(struct intel_encoder *encoder, + const struct intel_crtc_state *config); extern void vlv_disable_dsi_pll(struct intel_encoder *encoder); -extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp); +extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp, + struct intel_crtc_state *config); struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id); diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index c6a8975..79c18a0 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -59,10 +59,6 @@ static int dsi_pixel_format_bpp(int pixel_format) return bpp; } -struct dsi_mnp { - u32 dsi_pll_ctrl; - u32 dsi_pll_div; -}; static const u32 lfsr_converts[] = { 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 62 - 70 */ @@ -158,7 +154,8 @@ static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count) #endif static int dsi_calc_mnp(struct drm_i915_private *dev_priv, - struct dsi_mnp *dsi_mnp, int target_dsi_clk) + struct intel_crtc_state *config, + int target_dsi_clk) { unsigned int calc_m = 0, calc_p = 0; unsigned int m_min, m_max, p_min = 2, p_max = 6; @@ -204,8 +201,8 @@ static int dsi_calc_mnp(struct drm_i915_private *dev_priv, /* register has log2(N1), this works fine for powers of two */ n = ffs(n) - 1; m_seed = lfsr_converts[calc_m - 62]; - dsi_mnp->dsi_pll_ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + calc_p - 2); - dsi_mnp->dsi_pll_div = n << DSI_PLL_N1_DIV_SHIFT | + config->dsi_pll.ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + calc_p - 2); + config->dsi_pll.div = n << DSI_PLL_N1_DIV_SHIFT | m_seed << DSI_PLL_M1_DIV_SHIFT; return 0; @@ -215,54 +212,63 @@ static int dsi_calc_mnp(struct drm_i915_private *dev_priv, * XXX: The muxing and gating is hard coded for now. Need to add support for * sharing PLLs with two DSI outputs. */ -static void vlv_configure_dsi_pll(struct intel_encoder *encoder) +int vlv_compute_dsi_pll(struct intel_encoder *encoder, + struct intel_crtc_state *config) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); int ret; - struct dsi_mnp dsi_mnp; u32 dsi_clk; dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format, intel_dsi->lane_count); - ret = dsi_calc_mnp(dev_priv, &dsi_mnp, dsi_clk); + ret = dsi_calc_mnp(dev_priv, config, dsi_clk); if (ret) { DRM_DEBUG_KMS("dsi_calc_mnp failed\n"); - return; + return ret; } if (intel_dsi->ports & (1 << PORT_A)) - dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL; + config->dsi_pll.ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL; if (intel_dsi->ports & (1 << PORT_C)) - dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI1_DSIPLL; + config->dsi_pll.ctrl |= DSI_PLL_CLK_GATE_DSI1_DSIPLL; + + config->dsi_pll.ctrl |= DSI_PLL_VCO_EN; DRM_DEBUG_KMS("dsi pll div %08x, ctrl %08x\n", - dsi_mnp.dsi_pll_div, dsi_mnp.dsi_pll_ctrl); + config->dsi_pll.div, config->dsi_pll.ctrl); + + return 0; +} + +static void vlv_configure_dsi_pll(struct intel_encoder *encoder, + const struct intel_crtc_state *config) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0); - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, dsi_mnp.dsi_pll_div); - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp.dsi_pll_ctrl); + vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, config->dsi_pll.div); + vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, + config->dsi_pll.ctrl & ~DSI_PLL_VCO_EN); } -void vlv_enable_dsi_pll(struct intel_encoder *encoder) +void vlv_enable_dsi_pll(struct intel_encoder *encoder, + const struct intel_crtc_state *config) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; - u32 tmp; DRM_DEBUG_KMS("\n"); mutex_lock(&dev_priv->sb_lock); - vlv_configure_dsi_pll(encoder); + vlv_configure_dsi_pll(encoder, config); /* wait at least 0.5 us after ungating before enabling VCO */ usleep_range(1, 10); - tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); - tmp |= DSI_PLL_VCO_EN; - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp); + vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl); if (wait_for(vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL) & DSI_PLL_LOCK, 20)) { @@ -302,7 +308,8 @@ static void assert_bpp_mismatch(int pixel_format, int pipe_bpp) bpp, pipe_bpp); } -u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp) +u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp, + struct intel_crtc_state *config) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); @@ -319,6 +326,9 @@ u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp) pll_div = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_DIVIDER); mutex_unlock(&dev_priv->sb_lock); + config->dsi_pll.ctrl = pll_ctl & ~DSI_PLL_LOCK; + config->dsi_pll.div = pll_div; + /* mask out other bits and extract the P1 divisor */ pll_ctl &= DSI_PLL_P1_POST_DIV_MASK; pll_ctl = pll_ctl >> (DSI_PLL_P1_POST_DIV_SHIFT - 2);