From: Ville Syrjälä <[email protected]>

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ä <[email protected]>
---
 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);
-- 
2.4.6

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to