Re: [PATCH 2/6] drm/i915/icl: add the main CDCLK functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Feb 05, 2018 at 01:40:42PM -0200, Paulo Zanoni wrote:
> This commit adds the basic CDCLK functions, but it's still missing
> pieces of the display initialization sequence.
>
> v2:
>  - Implement the voltage levels.
>  - Rebase.
> v3:
>  - Adjust to the new "bypass" clock (Imre).
>  - Call intel_dump_cdclk_state() too.
>  - Rename a variable to avoid confusion.
>  - Simplify the DVFS part.
     ^^^^^^^
Shouldn't this be something more like

"Drop DVFS part and replace with a TODO"?

"Simplify" makes it sound like it's still there, but it's not, unless
I'm missing something?


> v4:
>  - Remove wrong bit definition (James).
>  - Also drive-by fix the coding style for the register definition we
>    touched.
>
> Cc: James Ausmus <james.ausmus@xxxxxxxxx>
> Cc: Imre Deak <imre.deak@xxxxxxxxx>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx>
> ---
>  drivers/gpu/drm/i915/i915_reg.h    |  35 +++---
>  drivers/gpu/drm/i915/intel_cdclk.c | 235 ++++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_drv.h   |   2 +
>  3 files changed, 255 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index f6e1677e8211..2b6a908056d6 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -7182,8 +7182,12 @@ enum {
>  #define SKL_DFSM_PIPE_B_DISABLE (1 << 21)
>  #define SKL_DFSM_PIPE_C_DISABLE (1 << 28)
>  
> -#define SKL_DSSM _MMIO(0x51004)
> -#define CNL_DSSM_CDCLK_PLL_REFCLK_24MHz (1 << 31)
> +#define SKL_DSSM _MMIO(0x51004)
> +#define CNL_DSSM_CDCLK_PLL_REFCLK_24MHz (1 << 31)
> +#define ICL_DSSM_CDCLK_PLL_REFCLK_MASK (7 << 29)
> +#define ICL_DSSM_CDCLK_PLL_REFCLK_24MHz (0 << 29)
> +#define ICL_DSSM_CDCLK_PLL_REFCLK_19_2MHz (1 << 29)
> +#define ICL_DSSM_CDCLK_PLL_REFCLK_38_4MHz (2 << 29)
>  
>  #define GEN7_FF_SLICE_CS_CHICKEN1 _MMIO(0x20e0)
>  #define   GEN9_FFSC_PERCTX_PREEMPT_CTRL (1<<14)
> @@ -8816,20 +8820,21 @@ enum skl_power_gate {
>  
>  /* CDCLK_CTL */
>  #define CDCLK_CTL _MMIO(0x46000)
> -#define  CDCLK_FREQ_SEL_MASK (3<<26)
> -#define  CDCLK_FREQ_450_432 (0<<26)
> -#define  CDCLK_FREQ_540 (1<<26)
> -#define  CDCLK_FREQ_337_308 (2<<26)
> -#define  CDCLK_FREQ_675_617 (3<<26)
> -#define  BXT_CDCLK_CD2X_DIV_SEL_MASK (3<<22)
> -#define  BXT_CDCLK_CD2X_DIV_SEL_1 (0<<22)
> -#define  BXT_CDCLK_CD2X_DIV_SEL_1_5 (1<<22)
> -#define  BXT_CDCLK_CD2X_DIV_SEL_2 (2<<22)
> -#define  BXT_CDCLK_CD2X_DIV_SEL_4 (3<<22)
> -#define  BXT_CDCLK_CD2X_PIPE(pipe) ((pipe)<<20)
> -#define  CDCLK_DIVMUX_CD_OVERRIDE (1<<19)
> +#define  CDCLK_FREQ_SEL_MASK (3 << 26)
> +#define  CDCLK_FREQ_450_432 (0 << 26)
> +#define  CDCLK_FREQ_540 (1 << 26)
> +#define  CDCLK_FREQ_337_308 (2 << 26)
> +#define  CDCLK_FREQ_675_617 (3 << 26)
> +#define  BXT_CDCLK_CD2X_DIV_SEL_MASK (3 << 22)
> +#define  BXT_CDCLK_CD2X_DIV_SEL_1 (0 << 22)
> +#define  BXT_CDCLK_CD2X_DIV_SEL_1_5 (1 << 22)
> +#define  BXT_CDCLK_CD2X_DIV_SEL_2 (2 << 22)
> +#define  BXT_CDCLK_CD2X_DIV_SEL_4 (3 << 22)
> +#define  BXT_CDCLK_CD2X_PIPE(pipe) ((pipe) << 20)
> +#define  CDCLK_DIVMUX_CD_OVERRIDE (1 << 19)
>  #define  BXT_CDCLK_CD2X_PIPE_NONE BXT_CDCLK_CD2X_PIPE(3)
> -#define  BXT_CDCLK_SSA_PRECHARGE_ENABLE (1<<16)
> +#define  ICL_CDCLK_CD2X_PIPE_NONE (7 << 19)
> +#define  BXT_CDCLK_SSA_PRECHARGE_ENABLE (1 << 16)
>  #define  CDCLK_FREQ_DECIMAL_MASK (0x7ff)
>  
>  /* LCPLL_CTL */
> diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
> index ee788d5be5e3..52a15d0eaae9 100644
> --- a/drivers/gpu/drm/i915/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> @@ -1778,6 +1778,197 @@ static void cnl_sanitize_cdclk(struct drm_i915_private *dev_priv)
>   dev_priv->cdclk.hw.vco = -1;
>  }
>  
> +static int icl_calc_cdclk(int min_cdclk, unsigned int ref)
> +{
> + int ranges_24[] = { 312000, 552000, 648000 };
> + int ranges_19_38[] = { 307200, 556800, 652800 };
> + int *ranges;
> +
> + switch (ref) {
> + default:
> + MISSING_CASE(ref);
> + case 24000:
> + ranges = ranges_24;
> + break;
> + case 19200:
> + case 38400:
> + ranges = ranges_19_38;
> + break;
> + }
> +
> + if (min_cdclk > ranges[1])
> + return ranges[2];
> + else if (min_cdclk > ranges[0])
> + return ranges[1];
> + else
> + return ranges[0];
> +}
> +
> +static int icl_calc_cdclk_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
> +{
> + int ratio;
> +
> + if (cdclk == dev_priv->cdclk.hw.bypass)
> + return 0;
> +
> + switch (cdclk) {
> + default:
> + MISSING_CASE(cdclk);
> + case 307200:
> + case 556800:
> + case 652800:
> + WARN_ON(dev_priv->cdclk.hw.ref != 19200 &&
> + dev_priv->cdclk.hw.ref != 38400);
> + break;
> + case 312000:
> + case 552000:
> + case 648000:
> + WARN_ON(dev_priv->cdclk.hw.ref != 24000);
> + }
> +
> + ratio = cdclk / (dev_priv->cdclk.hw.ref / 2);
> +
> + return dev_priv->cdclk.hw.ref * ratio;
> +}
> +
> +static void icl_set_cdclk(struct drm_i915_private *dev_priv,
> +  const struct intel_cdclk_state *cdclk_state)
> +{
> + unsigned int cdclk = cdclk_state->cdclk;
> + unsigned int vco = cdclk_state->vco;
> + int ret;
> +
> + mutex_lock(&dev_priv->pcu_lock);
> + ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
> + SKL_CDCLK_PREPARE_FOR_CHANGE,
> + SKL_CDCLK_READY_FOR_CHANGE,
> + SKL_CDCLK_READY_FOR_CHANGE, 3);
> + mutex_unlock(&dev_priv->pcu_lock);
> + if (ret) {
> + DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
> +  ret);
> + return;
> + }
> +
> + if (dev_priv->cdclk.hw.vco != 0 &&
> +    dev_priv->cdclk.hw.vco != vco)
> + cnl_cdclk_pll_disable(dev_priv);
> +
> + if (dev_priv->cdclk.hw.vco != vco)
> + cnl_cdclk_pll_enable(dev_priv, vco);
> +
> + I915_WRITE(CDCLK_CTL, ICL_CDCLK_CD2X_PIPE_NONE |
> +      skl_cdclk_decimal(cdclk));
> +
> + mutex_lock(&dev_priv->pcu_lock);
> + /* TODO: add proper DVFS support. */
> + sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, 2);
> + mutex_unlock(&dev_priv->pcu_lock);
> +
> + intel_update_cdclk(dev_priv);
> +}
> +
> +static void icl_get_cdclk(struct drm_i915_private *dev_priv,
> +  struct intel_cdclk_state *cdclk_state)
> +{
> + u32 val;
> +
> + cdclk_state->bypass = 50000;
> +
> + val = I915_READ(SKL_DSSM);
> + switch (val & ICL_DSSM_CDCLK_PLL_REFCLK_MASK) {
> + default:
> + MISSING_CASE(val);
> + case ICL_DSSM_CDCLK_PLL_REFCLK_24MHz:
> + cdclk_state->ref = 24000;
> + break;
> + case ICL_DSSM_CDCLK_PLL_REFCLK_19_2MHz:
> + cdclk_state->ref = 19200;
> + break;
> + case ICL_DSSM_CDCLK_PLL_REFCLK_38_4MHz:
> + cdclk_state->ref = 38400;
> + break;
> + }
> +
> + val = I915_READ(BXT_DE_PLL_ENABLE);
> + if ((val & BXT_DE_PLL_PLL_ENABLE) == 0 ||
> +    (val & BXT_DE_PLL_LOCK) == 0) {
> + /* CDCLK PLL is disabled, the VCO/ratio doesn't matter, but
> + * setting it to zero is a way to signal that. */

checkpatch throws a warn on this comment:

WARNING: Block comments use a trailing */ on a separate line
#211: FILE: drivers/gpu/drm/i915/intel_cdclk.c:1897:
+                * setting it to zero is a way to signal that. */

total: 0 errors, 1 warnings, 317 lines checked

> + cdclk_state->vco = 0;
> + cdclk_state->cdclk = cdclk_state->bypass;
> + return;
> + }
> +
> + cdclk_state->vco = (val & BXT_DE_PLL_RATIO_MASK) * cdclk_state->ref;
> +
> + val = I915_READ(CDCLK_CTL);
> + WARN_ON((val & BXT_CDCLK_CD2X_DIV_SEL_MASK) != 0);
> +
> + cdclk_state->cdclk = cdclk_state->vco / 2;
> +}
> +
> +/**
> + * icl_init_cdclk - Initialize CDCLK on ICL
> + * @dev_priv: i915 device
> + *
> + * Initialize CDCLK for ICL. This consists mainly of initializing
> + * dev_priv->cdclk.hw and sanitizing the state of the hardware if needed. This
> + * is generally done only during the display core initialization sequence, after
> + * which the DMC will take care of turning CDCLK off/on as needed.
> + */
> +void icl_init_cdclk(struct drm_i915_private *dev_priv)
> +{
> + struct intel_cdclk_state sanitized_state;
> + u32 val;
> +
> + /* This sets dev_priv->cdclk.hw. */
> + intel_update_cdclk(dev_priv);
> + intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK");
> +
> + /* This means CDCLK disabled. */
> + if (dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.bypass)
> + goto sanitize;
> +
> + val = I915_READ(CDCLK_CTL);
> +
> + if ((val & BXT_CDCLK_CD2X_DIV_SEL_MASK) != 0)
> + goto sanitize;
> +
> + if ((val & CDCLK_FREQ_DECIMAL_MASK) !=
> +    skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk))
> + goto sanitize;
> +
> + return;
> +
> +sanitize:
> + DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
> +
> + sanitized_state.ref = dev_priv->cdclk.hw.ref;
> + sanitized_state.cdclk = icl_calc_cdclk(0, sanitized_state.ref);
> + sanitized_state.vco = icl_calc_cdclk_pll_vco(dev_priv,
> +     sanitized_state.cdclk);
> +
> + icl_set_cdclk(dev_priv, &sanitized_state);
> +}
> +
> +/**
> + * icl_uninit_cdclk - Uninitialize CDCLK on ICL
> + * @dev_priv: i915 device
> + *
> + * Uninitialize CDCLK for ICL. This is done only during the display core
> + * uninitialization sequence.
> + */
> +void icl_uninit_cdclk(struct drm_i915_private *dev_priv)
> +{
> + struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
> +
> + cdclk_state.cdclk = cdclk_state.bypass;
> + cdclk_state.vco = 0;
> +
> + icl_set_cdclk(dev_priv, &cdclk_state);
> +}
> +
>  /**
>   * cnl_init_cdclk - Initialize CDCLK on CNL
>   * @dev_priv: i915 device
> @@ -2216,6 +2407,36 @@ static int cnl_modeset_calc_cdclk(struct drm_atomic_state *state)
>   return 0;
>  }
>  
> +static int icl_modeset_calc_cdclk(struct drm_atomic_state *state)
> +{
> + struct drm_i915_private *dev_priv = to_i915(state->dev);
> + struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
> + unsigned int ref = intel_state->cdclk.logical.ref;
> + int min_cdclk, cdclk, vco;
> +
> + min_cdclk = intel_compute_min_cdclk(state);
> + if (min_cdclk < 0)
> + return min_cdclk;
> +
> + cdclk = icl_calc_cdclk(min_cdclk, ref);
> + vco = icl_calc_cdclk_pll_vco(dev_priv, cdclk);
> +
> + intel_state->cdclk.logical.vco = vco;
> + intel_state->cdclk.logical.cdclk = cdclk;
> +
> + if (!intel_state->active_crtcs) {
> + cdclk = icl_calc_cdclk(0, ref);
> + vco = icl_calc_cdclk_pll_vco(dev_priv, cdclk);
> +
> + intel_state->cdclk.actual.vco = vco;
> + intel_state->cdclk.actual.cdclk = cdclk;
> + } else {
> + intel_state->cdclk.actual = intel_state->cdclk.logical;
> + }
> +
> + return 0;
> +}
> +
>  static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
>  {
>   int max_cdclk_freq = dev_priv->max_cdclk_freq;
> @@ -2249,7 +2470,12 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
>   */
>  void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
>  {
> - if (IS_CANNONLAKE(dev_priv)) {
> + if (IS_ICELAKE(dev_priv)) {
> + if (dev_priv->cdclk.hw.ref == 24000)
> + dev_priv->max_cdclk_freq = 648000;
> + else
> + dev_priv->max_cdclk_freq = 652800;
> + } else if (IS_CANNONLAKE(dev_priv)) {
>   dev_priv->max_cdclk_freq = 528000;
>   } else if (IS_GEN9_BC(dev_priv)) {
>   u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
> @@ -2473,9 +2699,14 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
>   dev_priv->display.set_cdclk = cnl_set_cdclk;
>   dev_priv->display.modeset_calc_cdclk =
>   cnl_modeset_calc_cdclk;
> + } else if (IS_ICELAKE(dev_priv)) {
> + dev_priv->display.set_cdclk = icl_set_cdclk;
> + dev_priv->display.modeset_calc_cdclk = icl_modeset_calc_cdclk;
>   }
>  
> - if (IS_CANNONLAKE(dev_priv))
> + if (IS_ICELAKE(dev_priv))
> + dev_priv->display.get_cdclk = icl_get_cdclk;
> + else if (IS_CANNONLAKE(dev_priv))
>   dev_priv->display.get_cdclk = cnl_get_cdclk;
>   else if (IS_GEN9_BC(dev_priv))
>   dev_priv->display.get_cdclk = skl_get_cdclk;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d6a808374dfb..cca7ecae5cce 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1403,6 +1403,8 @@ void cnl_init_cdclk(struct drm_i915_private *dev_priv);
>  void cnl_uninit_cdclk(struct drm_i915_private *dev_priv);
>  void bxt_init_cdclk(struct drm_i915_private *dev_priv);
>  void bxt_uninit_cdclk(struct drm_i915_private *dev_priv);
> +void icl_init_cdclk(struct drm_i915_private *dev_priv);
> +void icl_uninit_cdclk(struct drm_i915_private *dev_priv);
>  void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv);
>  void intel_update_max_cdclk(struct drm_i915_private *dev_priv);
>  void intel_update_cdclk(struct drm_i915_private *dev_priv);
> --
> 2.14.3
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux