Message ID | 20180202195702.20008-1-paulo.r.zanoni@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Fri, Feb 02, 2018 at 05:57:02PM -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. > > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> > --- > drivers/gpu/drm/i915/i915_reg.h | 10 +- > drivers/gpu/drm/i915/intel_cdclk.c | 235 ++++++++++++++++++++++++++++++++++++- > drivers/gpu/drm/i915/intel_drv.h | 2 + > 3 files changed, 243 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index f6e1677e8211..856e88c6ee97 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) > @@ -8831,6 +8835,8 @@ enum skl_power_gate { > #define BXT_CDCLK_CD2X_PIPE_NONE BXT_CDCLK_CD2X_PIPE(3) > #define BXT_CDCLK_SSA_PRECHARGE_ENABLE (1<<16) > #define CDCLK_FREQ_DECIMAL_MASK (0x7ff) > +#define ICL_CDCLK_CD2X_PIPE(pipe) ((pipe) << 19) This is still wrong :) > +#define ICL_CDCLK_CD2X_PIPE_NONE ICL_CDCLK_CD2X_PIPE(7) > > /* LCPLL_CTL */ > #define LCPLL1_CTL _MMIO(0x46010) > 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. */ > + 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@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f6e1677e8211..856e88c6ee97 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) @@ -8831,6 +8835,8 @@ enum skl_power_gate { #define BXT_CDCLK_CD2X_PIPE_NONE BXT_CDCLK_CD2X_PIPE(3) #define BXT_CDCLK_SSA_PRECHARGE_ENABLE (1<<16) #define CDCLK_FREQ_DECIMAL_MASK (0x7ff) +#define ICL_CDCLK_CD2X_PIPE(pipe) ((pipe) << 19) +#define ICL_CDCLK_CD2X_PIPE_NONE ICL_CDCLK_CD2X_PIPE(7) /* LCPLL_CTL */ #define LCPLL1_CTL _MMIO(0x46010) 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. */ + 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);
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. Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> --- drivers/gpu/drm/i915/i915_reg.h | 10 +- drivers/gpu/drm/i915/intel_cdclk.c | 235 ++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_drv.h | 2 + 3 files changed, 243 insertions(+), 4 deletions(-)