> -----Original Message-----
> From: Deak, Imre <imre.d...@intel.com>
> Sent: Wednesday, 12 February 2025 16.40
> To: Kahola, Mika <mika.kah...@intel.com>; intel-gfx@lists.freedesktop.org; 
> intel-
> x...@lists.freedesktop.org; jani.nik...@linux.intel.com
> Subject: Re: [PATCH v2 2/2] drm/i915/display: Allow display PHYs to reset 
> power
> state
> 
> On Wed, Feb 12, 2025 at 04:38:33PM +0200, Imre Deak wrote:
> > On Tue, Feb 04, 2025 at 12:53:58PM +0200, Mika Kahola wrote:
> > > The dedicated display PHYs reset to a power state that blocks S0ix,
> > > increasing idle system power. After a system reset (cold boot,
> > > S3/4/5, warm reset) if a dedicated PHY is not being brought up
> > > shortly, use these steps to move the PHY to the lowest power state
> > > to save power.
> > >
> > > 1. Follow the PLL Enable Sequence, using any valid frequency such as DP 
> > > 1.62
> GHz.
> > >    This brings lanes out of reset and enables the PLL to allow powerdown 
> > > to be
> moved
> > >    to the Disable state.
> > > 2. Follow PLL Disable Sequence. This moves powerdown to the Disable state
> and disables the PLL.
> > >
> > > v2: Rename WA function to more descriptive (Jani)
> > >     For PTL, only port A needs this wa
> > >     Add helpers to check presence of C10 phy and pll enabling (Imre)
> > >
> > > Signed-off-by: Mika Kahola <mika.kah...@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 45
> > > +++++++++++++++++++  drivers/gpu/drm/i915/display/intel_cx0_phy.h  |  1 +
> > >  .../drm/i915/display/intel_display_reset.c    |  2 +
> > >  drivers/gpu/drm/i915/display/intel_dpll_mgr.c |  2 +
> > >  4 files changed, 50 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > > b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > > index bffe3d4bbe8b..bd33ebb8c71e 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > > @@ -3559,3 +3559,48 @@ void intel_cx0pll_state_verify(struct
> intel_atomic_state *state,
> > >   else
> > >           intel_c20pll_state_verify(new_crtc_state, crtc, encoder,
> > > &mpll_hw_state.c20);  }
> > > +
> > > +static bool intel_cx0_pll_is_enabled(struct intel_display *display,
> > > +enum port port) {
> > > + u32 val = intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display,
> > > +port));
> > > +
> > > + if (REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val) ==
> XELPDP_DDI_CLOCK_SELECT_NONE)
> > > +         return false;
> >
> > Shouldn't this check if the PLL request for either lane is set in
> > XELPDP_PORT_CLOCK_CTL? AFAICS that's what actually enables the PLL,
> > while the above is just some configuration.
> >
> > > +
> > > + return true;
> > > +}
> > > +/*
> > > + * WA 14022081154
> > > + * The dedicated display PHYs reset to a power state that blocks
> > > +S0ix, increasing idle
> > > + * system power. After a system reset (cold boot, S3/4/5, warm
> > > +reset) if a dedicated
> > > + * PHY is not being brought up shortly, use these steps to move the
> > > +PHY to the lowest
> > > + * power state to save power. For PTL the workaround is needed only
> > > +for port A. Port B
> > > + * is not connected.
> > > + *
> > > + * 1. Follow the PLL Enable Sequence, using any valid frequency such as 
> > > DP
> 1.62 GHz.
> > > + *    This brings lanes out of reset and enables the PLL to allow 
> > > powerdown to
> be moved
> > > + *    to the Disable state.
> > > + * 2. Follow PLL Disable Sequence. This moves powerdown to the Disable
> state and disables the PLL.
> > > + */
> > > +void ptl_power_save_wa(struct intel_display *display)
> >
> > I'd call it intel_cx0_pll_power_save_wa() following the naming rule
> > for exported functions.
> >
> > > +{
> > > + struct intel_encoder *encoder;
> > > +
> > > + if (DISPLAY_VER(display) != 30)
> > > +         return;
> > > +
> > > + for_each_intel_encoder(display->drm, encoder) {
> > > +         struct intel_cx0pll_state pll_state = {};
> > > +         int port_clock = 162000;
> > > +
> > > +         if (!intel_encoder_is_c10phy(encoder))
> > > +                 continue;
> > > +
> > > +         if (intel_cx0_pll_is_enabled(display, encoder->port))
> > > +                 continue;
> > > +
> > > +         intel_c10pll_calc_state_from_table(encoder,
> mtl_c10_edp_tables,
> > > +port_clock, true, &pll_state);
> 
> This should check for error return.
I will add an error check.

> 
> > > +         __intel_cx0pll_enable(encoder, &pll_state, true, port_clock, 4);
> > > +         intel_cx0pll_disable(encoder);
> > > + }
> > > +}
> > > diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
> > > b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
> > > index 573fa7d3e88f..06346e4c5079 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
> > > +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
> > > @@ -42,5 +42,6 @@ bool intel_cx0pll_compare_hw_state(const struct
> > > intel_cx0pll_state *a,  void intel_cx0_phy_set_signal_levels(struct
> intel_encoder *encoder,
> > >                                const struct intel_crtc_state 
> > > *crtc_state);  int
> > > intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
> > > +void ptl_power_save_wa(struct intel_display *display);
> > >
> > >  #endif /* __INTEL_CX0_PHY_H__ */
> > > diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.c
> > > b/drivers/gpu/drm/i915/display/intel_display_reset.c
> > > index 093b386c95e8..b75827ff9c7e 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_display_reset.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_display_reset.c
> > > @@ -7,6 +7,7 @@
> > >
> > >  #include "i915_drv.h"
> > >  #include "intel_clock_gating.h"
> > > +#include "intel_cx0_phy.h"
> > >  #include "intel_display_driver.h"
> > >  #include "intel_display_reset.h"
> > >  #include "intel_display_types.h"
> > > @@ -116,6 +117,7 @@ void intel_display_reset_finish(struct
> drm_i915_private *i915)
> > >           intel_pps_unlock_regs_wa(display);
> > >           intel_display_driver_init_hw(display);
> > >           intel_clock_gating_init(i915);
> > > +         ptl_power_save_wa(display);
> > >           intel_hpd_init(i915);
> > >
> > >           ret = __intel_display_driver_resume(display, state, ctx); diff
> > > --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
> > > b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
> > > index b8fa04d3cd5c..24893d2f79e3 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
> > > @@ -27,6 +27,7 @@
> > >  #include "bxt_dpio_phy_regs.h"
> > >  #include "i915_drv.h"
> > >  #include "i915_reg.h"
> > > +#include "intel_cx0_phy.h"
> > >  #include "intel_de.h"
> > >  #include "intel_display_types.h"
> > >  #include "intel_dkl_phy.h"
> > > @@ -4552,6 +4553,7 @@ static void sanitize_dpll_state(struct
> drm_i915_private *i915,
> > >           return;
> > >
> > >   adlp_cmtg_clock_gating_wa(i915, pll);
> > > + ptl_power_save_wa(&i915->display);
> >
> > The WA is applied if the PLL is not on, so at least logically it
> > should be applied before the !pll->on check above.
> >
> > >
> > >   if (pll->active_mask)
> > >           return;
> > > --
> > > 2.43.0
> > >

Reply via email to