From: Shashank Sharma <shashank.sharma@xxxxxxxxx> This patch adds new functions for BXT clock and PLL programming. They are: 1. configure_dsi_pll for BXT. This function does the basic math and generates the divider ratio based on requested pixclock, and program clock registers. 2. enable_dsi_pll function. This function programs the calculated clock values on the PLL. 3. intel_enable_dsi_pll Wrapper function to use same code for multiple platforms. It checks the platform and calls appropriate core pll enable function. Signed-off-by: Shashank Sharma <shashank.sharma@xxxxxxxxx> Signed-off-by: Uma Shankar <uma.shankar@xxxxxxxxx> --- drivers/gpu/drm/i915/i915_reg.h | 35 ++++++++++++++ drivers/gpu/drm/i915/intel_dsi.c | 2 +- drivers/gpu/drm/i915/intel_dsi.h | 2 +- drivers/gpu/drm/i915/intel_dsi_pll.c | 85 +++++++++++++++++++++++++++++++++- 4 files changed, 121 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 46ef269..b63bdce 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7352,6 +7352,41 @@ enum skl_disp_power_wells { /* MIPI DSI registers */ +/* BXT DSI PLL Control */ +#define BXT_DSI_PLL_CTL 0x161000 +#define BXT_DSI_PLL_MASK_PVD_RATIO (3 << 16) +#define BXT_DSI_PLL_PVD_RATIO_1 (1<<16) +#define BXT_DSIC_16X_BY2 (1 << 10) +#define BXT_DSIC_16X_BY3 (1 << 11) +#define BXT_DSIC_16X_BY4 (3 << 10) +#define BXT_DSIA_16X_BY2 (1 << 8) +#define BXT_DSIA_16X_BY3 (1 << 9) +#define BXT_DSIA_16X_BY4 (3 << 8) + +#define BXT_DSI_MASK_FREQ_SEL (0xF << 8) + +#define BXT_DSI_PLL_RATIO_MAX 0x7D +#define BXT_DSI_PLL_RATIO_MIN 0x22 +#define BXT_DSI_MASK_PLL_RATIO 0x7F +#define BXT_REF_CLOCK_KHZ 19500 + +#define BXT_DSI_PLL_ENABLE 0x46080 +#define BXT_DSI_PLL_DO_ENABLE (1 << 31) +#define BXT_DSI_PLL_LOCKED (1 << 30) + +/* BXT power well control2, for driver */ +#define BXT_PWR_WELL_CTL2 0x45404 +#define BXT_PWR_WELL_2_ENABLE (1 << 31) +#define BXT_PWR_WELL_2_ENABLED (1 << 30) +#define BXT_PWR_WELL_1_ENABLE (1 << 29) +#define BXT_PWR_WELL_1_ENABLED (1 << 28) +#define BXT_PWR_WELL_ENABLED (BXT_PWR_WELL_1_ENABLED | \ + BXT_PWR_WELL_2_ENABLED) +#define GEN9_FUSE_STATUS 0x42000 +#define GEN9_FUSE_PG2_ENABLED (1 << 25) +#define GEN9_FUSE_PG1_ENABLED (1 << 26) +#define GEN9_FUSE_PG0_ENABLED (1 << 27) + #define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, c) /* ports A and C only */ #define _MIPIA_PORT_CTRL (VLV_DISPLAY_BASE + 0x61190) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 2419929e..1927546 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -903,8 +903,8 @@ static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder) DRM_DEBUG_KMS("\n"); intel_dsi_prepare(encoder); + intel_enable_dsi_pll(encoder); - vlv_enable_dsi_pll(encoder); } static enum drm_connector_status diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 2784ac4..20cfcf07 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -121,7 +121,7 @@ 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 void intel_enable_dsi_pll(struct intel_encoder *encoder); extern void vlv_disable_dsi_pll(struct intel_encoder *encoder); extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp); diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index 9688d99..a58f0a1 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -237,7 +237,7 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder) vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp.dsi_pll_ctrl); } -void vlv_enable_dsi_pll(struct intel_encoder *encoder) +static void vlv_enable_dsi_pll(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; u32 tmp; @@ -368,3 +368,86 @@ u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp) return pclk; } + +static bool bxt_configure_dsi_pll(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + u8 dsi_ratio; + u32 dsi_clk; + u32 val = 0; + + dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format, + intel_dsi->lane_count); + + /* + * From clock diagram, to get PLL ratio divider, divide double of DSI + * link rate (i.e., 2*8x=16x frequency value) by ref clock. Make sure to + * round 'up' the result + */ + dsi_ratio = DIV_ROUND_UP(dsi_clk * 2, BXT_REF_CLOCK_KHZ); + if (dsi_ratio < BXT_DSI_PLL_RATIO_MIN || + dsi_ratio > BXT_DSI_PLL_RATIO_MAX) { + DRM_ERROR("Cant get a suitable ratio from DSI PLL ratios\n"); + return false; + } + + /* + * Program DSI ratio and Select MIPIC and MIPIA PLL output as 8x + * Spec says both have to be programmed, even if one is not getting + * used. Configure MIPI_CLOCK_CTL dividers in modeset + */ + val = I915_READ(BXT_DSI_PLL_CTL); + val &= ~BXT_DSI_PLL_MASK_PVD_RATIO; + val &= ~BXT_DSI_MASK_FREQ_SEL; + val &= ~BXT_DSI_MASK_PLL_RATIO; + val |= (dsi_ratio | BXT_DSIA_16X_BY2 | BXT_DSIC_16X_BY2); + + /* Prog PVD ratio =1 if ratio <= 50 */ + if (dsi_ratio <= 50) { + val &= ~BXT_DSI_PLL_MASK_PVD_RATIO; + val |= BXT_DSI_PLL_PVD_RATIO_1; + } + + I915_WRITE(BXT_DSI_PLL_CTL, val); + return true; +} + +static void bxt_enable_dsi_pll(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + u32 val = 0; + + DRM_DEBUG_KMS("\n"); + + /* Configure PLL vales */ + if (!bxt_configure_dsi_pll(encoder)) { + DRM_ERROR("Configure DSI PLL failed, abort PLL enable\n"); + return; + } + + /* Enable DSI PLL */ + val = I915_READ(BXT_DSI_PLL_ENABLE); + val |= BXT_DSI_PLL_DO_ENABLE; + I915_WRITE(BXT_DSI_PLL_ENABLE, val); + + /* Timeout and fail if PLL not locked */ + if (wait_for(I915_READ(BXT_DSI_PLL_ENABLE) & BXT_DSI_PLL_LOCKED, 1)) { + DRM_ERROR("DSI PLL not locked\n"); + return; + } + + DRM_DEBUG_KMS("DSI PLL locked\n"); +} + +void intel_enable_dsi_pll(struct intel_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + + if (IS_VALLEYVIEW(dev)) + vlv_enable_dsi_pll(encoder); + else if (IS_BROXTON(dev)) + bxt_enable_dsi_pll(encoder); + else + DRM_ERROR("Invalid DSI device to pre_pll_enable\n"); +} -- 1.7.9.5 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx