Em Seg, 2018-02-05 às 15:13 -0800, Ausmus, James escreveu: > 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? We now always set the voltage to maximum (2) instead of picking a possibly wrong value (due to not considering the DDI clocks), so in a way we do the DVFS thing, just always with the safest value. The patch that picks the best value will come later. > > > > 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