Xe3's power well handling is similar to previous platforms, but there
are a few changes that need to be handled to ensure optimal power
management:
- PGB now only depends on PG1, not PG2
- Transcoder B is now in PG1 (was previously in PGB)
- Transcoders C & D are now in PG2 (were previously in PGC/PGD)
- DC states now require PG2 to be off (whereas on Xe2 it could remain
on as a dependency of PGB, although the features inside of it could
not be used).
Bspec: 72519, 68851
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Matt Atwood <matthew.s.atwood@intel.com>
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241010224311.50133-4-matthew.s.atwood@intel.com
A registered eDP connector is considered to be always connected, so it's
unnecessary to poll it for a connect/disconnect event. Polling it
involves AUX accesses toggling the panel power, which in turn can
generate a spurious short HPD pulse and possibly a new poll cycle via
the short HPD handler runtime resuming the device. Avoid this by
disabling the polling for eDP connectors.
This avoids IGT tests timing out while waiting for the device to runtime
suspend, the timeout caused by the above runtime resume->poll->suspend->
resume cycle keeping the device in the resumed state.
Testcase: igt/kms_pm_rpm/unverisal-planes
Reviewed-by: Jonathan Cavitt <jonathan.cavitt@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241009194358.1321200-3-imre.deak@intel.com
If the device is runtime suspended the eDP panel power is also off.
Ignore a short HPD on eDP if the device is suspended accordingly,
instead of checking the panel power state via the PPS registers for the
same purpose. The latter involves runtime resuming the device
unnecessarily, in a frequent scenario where the panel generates a
spurious short HPD after disabling the panel power and the device is
runtime suspended.
Reviewed-by: Jonathan Cavitt <jonathan.cavitt@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241009194358.1321200-2-imre.deak@intel.com
Push regular plane/color management updates to the DSB,
if other constraints allow it.
The first part of the sequence will go as follows:
- CPU will kick off DSB0 immediately
- DSB0 writes double bufferd non-arming registers
- DSB0 evades the vblank
- DSB0 writes double buffered arming registers
If no color management updates is needed we follow that up with:
- DSB0 waits for the undelayed vblank
- DSB0 waits for the delayed vblank (usec wait)
- DSB0 emits an interrupt which will cause the CPU to complete the commit
If color management update is needed:
- DSB0 will start DSB1 with wait for undelayed vblank
- DSB0 will in parallel perform the force DEwake tricks
- DSB1 writes single buffered LUT registers
- DSB1 waits for the delayed vblank (usec wait)
- DSB1 emits an interrupt which will cause the CPU to complete the commit
With this sequence we don't need to increase the vblank delay
to make room for register programming during vblank, which is
a good thing for high refresh rate display. But I'll need to
still think of some way to eliminate VRR commit completion
related races under this scheme.
Stuff that isn't ready for DSB yet:
- modesets (potentially we could do
at least the plane enabling via DSB)
- fastsets
- VRR
- PSR
- scalers
- async flips
Reviewed-by: Animesh Manna <animesh.manna@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240930170415.23841-14-ville.syrjala@linux.intel.com
We need to be able to do both MMIO and DSB based pipe/plane
programming. To that end plumb the 'dsb' all way from the top
into the plane commit hooks.
The compiler appears smart enough to combine the branches from
all the back-to-back register writes into a single branch.
So the generated asm ends up looking more or less like this:
plane_hook()
{
if (dsb) {
intel_dsb_reg_write();
intel_dsb_reg_write();
...
} else {
intel_de_write_fw();
intel_de_write_fw();
...
}
}
which seems like a reasonably efficient way to do this.
An alternative I was also considering is some kind of closure
(register write function + display vs. dsb pointer passed to it).
That does result is smaller code as there are no branches anymore,
but having each register access go via function pointer sounds
less efficient.
Not that I actually measured the overhead of either approach yet.
Also the reg_rw tracepoint seems to be making a huge mess of the
generated code for the mmio path. And additionally there's some
kind of IS_GSI_REG() hack in __raw_uncore_read() which ends up
generating a pointless branch for every mmio register access.
So looks like there might be quite a bit of room for improvement
in the mmio path still.
Reviewed-by: Animesh Manna <animesh.manna@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240930170415.23841-12-ville.syrjala@linux.intel.com
Introduce intel_scanlines_to_usecs() as a counterpart to
intel_usecs_to_scanlines().
We'll have some use for this in DSB code as we want to do
relative scanline waits to evade the delayed vblank, but
unfortunately DSB can't do relative scanline waits (only
absolute). So we'll instead convert the relative scanline
count to usec and do a relative usec wait instead (which the
DSB knows how to do).
Reviewed-by: Animesh Manna <animesh.manna@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240930170415.23841-9-ville.syrjala@linux.intel.com
Add a helper for performing vblank evasion on the DSB. DSB based
plane updates will need this to guarantee all the double buffered
arming registers will get programmed atomically within the same
frame.
With VRR we more or less have two vblanks to worry about:
- vmax vblank start in case no push was sent
- vmin vblank start in case a push was already sent during
the vertical active. Only a concern for mailbox updates,
which I suppose could happen if the legacy cursor updates
take the non-fastpath without setting
state->legacy_cursor_update to false.
Since we don't know which case is relevant we'll just evade
both.
We must also make sure to evade both the delayed vblank
(for pipe/plane registers) and the undelayed vblank
(for transcoder registers and chained DSBs w/
DSB_WAIT_FOR_VBLANK).
TODO: come up with a sensible usec number for the evasion...
Reviewed-by: Animesh Manna <animesh.manna@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240930170415.23841-6-ville.syrjala@linux.intel.com
The DSB can signal a programmable interrupt in response to
a specific DSB command getting executed. Hook that up.
For now we'll just use this to signal the completion of the
commit via a vblank event. If, in the future, we'll need to
do other things in response to DSB interrupts we may need to
come up with some kind of fancier DSB interrupt framework where
the caller can specify a custom handler...
Reviewed-by: Animesh Manna <animesh.manna@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240930170415.23841-5-ville.syrjala@linux.intel.com
Once we start using DSB for plane updates we'll need to defer
generating the DSB buffer until the clear color has been
read out. So we need to move at some of the DSB stuff into
commit_tail(). That is perhaps a better place for it anyway
as the ioctl thread can move on immediately without spending
time building the DSB commands.
We always have the MMIO fallback (in case the DSB buffer
allocation fails), so there's no real reason to keep any
of this in the synchronous part of the ioctl.
Because the DSB LUT programming doesn't depend on the plane
clear color we can still do that part before waiting for
fences/etc. which should help paralleize things a bit more.
The DSB plane programming will need to happen after those
however as that depends on the clear color.
Reviewed-by: Animesh Manna <animesh.manna@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240930170415.23841-4-ville.syrjala@linux.intel.com
Turns out CRC interrupts also fail to wake up i915gm/i945gm from
C2+. I suppose this is a generic problem, but for most other
interrupts the system will be busy enough already prior to
the irq being issued. But CRC interrupts are like vblank interrupts
and only fire once per frame, so plenty of time to fall asleep
in between them.
Apply the same core clock gating trick to CRC interrupts
that we use for vblank interrupts.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241001195803.3371-5-ville.syrjala@linux.intel.com
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
The .is_lp member of struct intel_device_info and its wrapper IS_LP()
are used to identify just four platforms, VLV/CHV/BXT/GLK. It didn't
become as important as it was perhaps originally planned. Just remove
it, and replace with exact platform identification. In a few places this
becomes slightly verbose, but in many places it improves clarity to
immediately see the exact platforms.
Additionally, this lets us remove the xe compat macro.
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240930124056.3541988-1-jani.nikula@intel.com
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
The only real reason why we have the gen2 vs. gen3+ split
in irq handling is that bspec claims that IIR/IMR/IER/ISR
and EMR are only 16 bits on gen2, as opposed to being 32
bits on gen3+. That doesn't seem to be a meaningful
distinction as 32bit access to these registers works
perfectly fine on gen2
Interestingly the 16 msbs of IMR are in fact hardcoded
to 1 on gen2, which to me indicates that 32bit access
was the plan all along, and perhaps someone just forgot
to update the spec.
Nuke the special 16bit gen2 irq code and switch over to
the gen3 code.
Gen2 doesn't have the ASLE interrupt, which just needs
a small tweak in i915_irq_postinstall().
And so far we've not had a codepath that could enable the
legacy BLC interrupt on gen2. Now we do, but we'll never
actually do it since gen2 machines don't have OpRegion.
(and neither do i915/i945 machines btw). On these older
platforms the legacy BLC interrupt is meant to be used
in conjunction with the LBPC backlight stuff, but we
never actually switch off the legacy/combination mode
and thus don't use the interrupt either.
This was quickly smoke tested on all gen2 variants.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240927143545.8665-5-ville.syrjala@linux.intel.com
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
i915_has_asle() is a bit of a mess. It does some kind of
partial check whether the platform has the legacy BLC
interrupt or not, and then it checks whether OpRegion
ASLE is present.
Let's split the legacy BLC interrupt check into its
own thing, and while at it let's make it accurate.
Currently it misses i85x (not a problem since gen2
never has OpRegion, nor do we currently call
i915_enable_asle_pipestat() on gen2), and it
doesn't reject ILK-M (not that anyone should call
this on ILK). The exlusion of VLV/CHV (where one
might even consider calling this, being gmch
platforms) only happens due to .is_mobile==false.
List the platforms that actually do have the legacy
BLC interrupt in a bit more explicit fashion.
i915gm/i945gm/i965gm/gm45 we can cover with a
display_ver+is_mobile check, pnv needs an exception
due to having a variant with is_mobile==false, and
i85x is the only relevant gen2 platform so easier to
handle on its own.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240927143545.8665-2-ville.syrjala@linux.intel.com
Reviewed-by: Jani Nikula <jani.nikula@intel.com>