On Mon, Mar 24, 2025 at 03:59:50PM +0200, Jani Nikula wrote: > On Mon, 24 Mar 2025, Imre Deak <imre.d...@intel.com> wrote: > > On Mon, Mar 24, 2025 at 02:28:35PM +0200, Jani Nikula wrote: > >> On Mon, 24 Mar 2025, Imre Deak <imre.d...@intel.com> wrote: > >> > On Mon, Mar 24, 2025 at 12:33:22PM +0200, Jani Nikula wrote: > >> >> On Fri, 21 Mar 2025, Imre Deak <imre.d...@intel.com> wrote: > >> >> > Factor out from the DP AUX transfer function the logic to lock/unlock > >> >> > the Panel Power Sequencer state and enable/disable the VDD power > >> >> > required for the AUX transfer, adding these to helpers in intel_pps.c > >> >> > . > >> >> > This prepares for a follow-up change making these steps dependent on > >> >> > the > >> >> > platform and output type. > >> >> > > >> >> > Signed-off-by: Imre Deak <imre.d...@intel.com> > >> >> > --- > >> >> > drivers/gpu/drm/i915/display/intel_dp_aux.c | 16 ++---------- > >> >> > drivers/gpu/drm/i915/display/intel_pps.c | 29 > >> >> > ++++++++++++++++++++- > >> >> > drivers/gpu/drm/i915/display/intel_pps.h | 3 ++- > >> >> > 3 files changed, 32 insertions(+), 16 deletions(-) > >> >> > > >> >> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c > >> >> > b/drivers/gpu/drm/i915/display/intel_dp_aux.c > >> >> > index ec27bbd70bcf0..bf5ccfa24ca0b 100644 > >> >> > --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c > >> >> > +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c > >> >> > @@ -272,15 +272,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, > >> >> > aux_domain = intel_aux_power_domain(dig_port); > >> >> > > >> >> > aux_wakeref = intel_display_power_get(display, aux_domain); > >> >> > - pps_wakeref = intel_pps_lock(intel_dp); > >> >> > - > >> >> > - /* > >> >> > - * We will be called with VDD already enabled for dpcd/edid/oui > >> >> > reads. > >> >> > - * In such cases we want to leave VDD enabled and it's up to > >> >> > upper layers > >> >> > - * to turn it off. But for eg. i2c-dev access we need to turn > >> >> > it on/off > >> >> > - * ourselves. > >> >> > - */ > >> >> > - vdd = intel_pps_vdd_on_unlocked(intel_dp); > >> >> > + pps_wakeref = intel_pps_lock_for_aux(intel_dp, &vdd); > >> >> > > >> >> > /* > >> >> > * dp aux is extremely sensitive to irq latency, hence request > >> >> > the > >> >> > @@ -289,8 +281,6 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, > >> >> > */ > >> >> > cpu_latency_qos_update_request(&intel_dp->pm_qos, 0); > >> >> > > >> >> > - intel_pps_check_power_unlocked(intel_dp); > >> >> > - > >> >> > /* > >> >> > * FIXME PSR should be disabled here to prevent > >> >> > * it using the same AUX CH simultaneously > >> >> > @@ -427,10 +417,8 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, > >> >> > out: > >> >> > cpu_latency_qos_update_request(&intel_dp->pm_qos, > >> >> > PM_QOS_DEFAULT_VALUE); > >> >> > > >> >> > - if (vdd) > >> >> > - intel_pps_vdd_off_unlocked(intel_dp, false); > >> >> > + intel_pps_unlock_for_aux(intel_dp, pps_wakeref, vdd); > >> >> > > >> >> > - intel_pps_unlock(intel_dp, pps_wakeref); > >> >> > intel_display_power_put_async(display, aux_domain, aux_wakeref); > >> >> > out_unlock: > >> >> > intel_digital_port_unlock(encoder); > >> >> > diff --git a/drivers/gpu/drm/i915/display/intel_pps.c > >> >> > b/drivers/gpu/drm/i915/display/intel_pps.c > >> >> > index 617ce49931726..3c078fd53fbfa 100644 > >> >> > --- a/drivers/gpu/drm/i915/display/intel_pps.c > >> >> > +++ b/drivers/gpu/drm/i915/display/intel_pps.c > >> >> > @@ -571,7 +571,7 @@ static bool edp_have_panel_vdd(struct intel_dp > >> >> > *intel_dp) > >> >> > return intel_de_read(display, _pp_ctrl_reg(intel_dp)) & > >> >> > EDP_FORCE_VDD; > >> >> > } > >> >> > > >> >> > -void intel_pps_check_power_unlocked(struct intel_dp *intel_dp) > >> >> > +static void intel_pps_check_power_unlocked(struct intel_dp *intel_dp) > >> >> > { > >> >> > struct intel_display *display = to_intel_display(intel_dp); > >> >> > struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > >> >> > @@ -955,6 +955,33 @@ void intel_pps_vdd_off(struct intel_dp *intel_dp) > >> >> > intel_pps_vdd_off_unlocked(intel_dp, false); > >> >> > } > >> >> > > >> >> > +intel_wakeref_t intel_pps_lock_for_aux(struct intel_dp *intel_dp, > >> >> > bool *vdd_ref) > >> >> > +{ > >> >> > + intel_wakeref_t wakeref; > >> >> > + > >> >> > + wakeref = intel_pps_lock(intel_dp); > >> >> > + > >> >> > + /* > >> >> > + * We will be called with VDD already enabled for dpcd/edid/oui > >> >> > reads. > >> >> > + * In such cases we want to leave VDD enabled and it's up to > >> >> > upper layers > >> >> > + * to turn it off. But for eg. i2c-dev access we need to turn > >> >> > it on/off > >> >> > + * ourselves. > >> >> > + */ > >> >> > + *vdd_ref = intel_pps_vdd_on_unlocked(intel_dp); > >> >> > + > >> >> > + intel_pps_check_power_unlocked(intel_dp); > >> >> > + > >> >> > + return wakeref; > >> >> > +} > >> >> > + > >> >> > +void intel_pps_unlock_for_aux(struct intel_dp *intel_dp, > >> >> > intel_wakeref_t wakeref, bool vdd_ref) > >> >> > +{ > >> >> > + if (vdd_ref) > >> >> > + intel_pps_vdd_off_unlocked(intel_dp, false); > >> >> > + > >> >> > + intel_pps_unlock(intel_dp, wakeref); > >> >> > +} > >> >> > >> >> It took me a while to pinpoint what exactly I don't like about this > >> >> interface. > >> >> > >> >> And I mean the whole intel_pps.h interface is already really difficult > >> >> to understand. > >> >> > >> >> This flips the lock/unlock and vdd on/off logic inside out. > >> >> > >> >> Normally you have functions for doing vdd or power or backlight, or > >> >> anything PPS really, and they're either unlocked (assuming the caller > >> >> handles PPS lock) or locked (the function itself takes the lock). > >> > > >> > The PPS and VDD handling steps are dependent (PPS must be locked for > >> > enabling VDD) and both are skipped for the same reason during AUX > >> > transfers. So I thought it makes sense to move these to a separate > >> > function and skip both based on the same platform/output type check. > >> > >> On the contrary, I think the reasons are different. > >> > >> VDD is only needed for eDP. > >> > >> The PPS must be locked for VDD change (IOW for eDP) and for VLV/CHV pipe > >> based PPS. But these two cases are independent. > > > > The case requiring VDD (eDP) is a subset of the cases requring PPS to be > > locked (eDP or VLV/CHV). These are not independent cases. > > Logically, they are. VLV/CHV requires the PPS lock also for > non-eDP.
Yes, that is what I meant. 1. Cases needing PPS lock: eDP or non-eDP on VLV/CHV. 2. Case needing VDD: eDP. 2. is a subset of 1. > It's not a subset. > > BR, > Jani. > > > > > > >> >> This one purports to be an interface for lock/unlock, but in reality it > >> >> also does VDD internally. And that feels really quite wrong to me. > >> >> > >> >> --- > >> >> > >> >> These are a single-use interface that I think make intel_pps.[ch] more > >> >> difficult to understand. I'd suggest checking how you'd implement this > >> >> logic inside intel_dp_aux_xfer() *without* changing the intel_pps.[ch] > >> >> interface at all. > >> >> > >> >> Okay, took a quick stab at it, and unless I'm missing something it's > >> >> super easy: > >> > > >> > I still think it'd be better to have a separate function for both > >> > locking PPS and enabling VDD for the reason I described above, that is > >> > to clarify that the PPS state must be locked to enable VDD. > >> > >> But there's no requirement that they must be done at the same time. > > > > There is also no reason not do them at the same time for AUX. A benefit > > of doing that would be to clarify the dependency of VDD on PPS and also > > simplify intel_dp_aux_xfer(). > > > >> The PPS lock could be held for a much longer period or for other > >> things than just VDD. And in this case, the PPS lock may indeed > >> protect *other* things than just VDD. Adding the separate function > >> ties these unrelated cases together for IMO not good enough reason. > >> intel_pps_vdd_on_unlocked() does check that it's called with the PPS > >> lock held. > >> > >> But I realize it needs to be relaxed a bit like this: > > > > Yes, noticed this too. It was one reason I opted for skipping PPS > > locking / VDD enabling from one spot. > > > >> diff --git a/drivers/gpu/drm/i915/display/intel_pps.c > >> b/drivers/gpu/drm/i915/display/intel_pps.c > >> index 617ce4993172..c883e872c9c8 100644 > >> --- a/drivers/gpu/drm/i915/display/intel_pps.c > >> +++ b/drivers/gpu/drm/i915/display/intel_pps.c > >> @@ -744,11 +744,11 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp > >> *intel_dp) > >> i915_reg_t pp_stat_reg, pp_ctrl_reg; > >> bool need_to_disable = !intel_dp->pps.want_panel_vdd; > >> > >> - lockdep_assert_held(&display->pps.mutex); > >> - > >> if (!intel_dp_is_edp(intel_dp)) > >> return false; > >> > >> + lockdep_assert_held(&display->pps.mutex); > >> + > >> cancel_delayed_work(&intel_dp->pps.panel_vdd_work); > >> intel_dp->pps.want_panel_vdd = true; > >> > >> @@ -925,11 +925,11 @@ void intel_pps_vdd_off_unlocked(struct intel_dp > >> *intel_dp, bool sync) > >> { > >> struct intel_display *display = to_intel_display(intel_dp); > >> > >> - lockdep_assert_held(&display->pps.mutex); > >> - > >> if (!intel_dp_is_edp(intel_dp)) > >> return; > >> > >> + lockdep_assert_held(&display->pps.mutex); > >> + > >> INTEL_DISPLAY_STATE_WARN(display, !intel_dp->pps.want_panel_vdd, > >> "[ENCODER:%d:%s] %s VDD not forced on", > >> dp_to_dig_port(intel_dp)->base.base.base.id, > >> > >> > >> > I guess the above could be done separately later in any case, so I can > >> > inline the fix as you suggest. > >> > > >> >> diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c > >> >> b/drivers/gpu/drm/i915/display/intel_dp_aux.c > >> >> index ec27bbd70bcf..a5608659df59 100644 > >> >> --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c > >> >> +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c > >> >> @@ -247,7 +247,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, > >> >> u32 aux_clock_divider; > >> >> enum intel_display_power_domain aux_domain; > >> >> intel_wakeref_t aux_wakeref; > >> >> - intel_wakeref_t pps_wakeref; > >> >> + intel_wakeref_t pps_wakeref = NULL; > >> >> int i, ret, recv_bytes; > >> >> int try, clock = 0; > >> >> u32 status; > >> >> @@ -272,7 +272,10 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, > >> >> aux_domain = intel_aux_power_domain(dig_port); > >> >> > >> >> aux_wakeref = intel_display_power_get(display, aux_domain); > >> >> - pps_wakeref = intel_pps_lock(intel_dp); > >> >> + > >> >> + if (intel_dp_is_edp(intel_dp) || > >> >> + (display->platform.valleyview || > >> >> display->platform.cherryview)) > >> >> + pps_wakeref = intel_pps_lock(intel_dp); > >> >> > >> >> /* > >> >> * We will be called with VDD already enabled for dpcd/edid/oui > >> >> reads. > >> >> @@ -430,7 +433,8 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, > >> >> if (vdd) > >> >> intel_pps_vdd_off_unlocked(intel_dp, false); > >> >> > >> >> - intel_pps_unlock(intel_dp, pps_wakeref); > >> >> + if (pps_wakeref) > >> >> + intel_pps_unlock(intel_dp, pps_wakeref); > >> >> intel_display_power_put_async(display, aux_domain, aux_wakeref); > >> >> out_unlock: > >> >> intel_digital_port_unlock(encoder); > >> >> > >> >> > >> >> Please let's not make intel_pps.[ch] harder to understand. > >> >> > >> >> > >> >> BR, > >> >> Jani. > >> >> > >> >> > >> >> > + > >> >> > void intel_pps_on_unlocked(struct intel_dp *intel_dp) > >> >> > { > >> >> > struct intel_display *display = to_intel_display(intel_dp); > >> >> > diff --git a/drivers/gpu/drm/i915/display/intel_pps.h > >> >> > b/drivers/gpu/drm/i915/display/intel_pps.h > >> >> > index c83007152f07d..4390d05892325 100644 > >> >> > --- a/drivers/gpu/drm/i915/display/intel_pps.h > >> >> > +++ b/drivers/gpu/drm/i915/display/intel_pps.h > >> >> > @@ -31,10 +31,11 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp > >> >> > *intel_dp); > >> >> > void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool > >> >> > sync); > >> >> > void intel_pps_on_unlocked(struct intel_dp *intel_dp); > >> >> > void intel_pps_off_unlocked(struct intel_dp *intel_dp); > >> >> > -void intel_pps_check_power_unlocked(struct intel_dp *intel_dp); > >> >> > > >> >> > void intel_pps_vdd_on(struct intel_dp *intel_dp); > >> >> > void intel_pps_vdd_off(struct intel_dp *intel_dp); > >> >> > +intel_wakeref_t intel_pps_lock_for_aux(struct intel_dp *intel_dp, > >> >> > bool *vdd_ref); > >> >> > +void intel_pps_unlock_for_aux(struct intel_dp *intel_dp, > >> >> > intel_wakeref_t wakeref, bool vdd_ref); > >> >> > void intel_pps_on(struct intel_dp *intel_dp); > >> >> > void intel_pps_off(struct intel_dp *intel_dp); > >> >> > void intel_pps_vdd_off_sync(struct intel_dp *intel_dp); > >> >> > >> >> -- > >> >> Jani Nikula, Intel > >> > >> -- > >> Jani Nikula, Intel > > -- > Jani Nikula, Intel