Panel Self Refresh PSR (PSR/SRD)¶
Since Haswell Display controller supports Panel Self-Refresh on display panels witch have a remote frame buffer (RFB) implemented according to PSR spec in eDP1.3. PSR feature allows the display to go to lower standby states when system is idle but display is on as it eliminates display refresh request to DDR memory completely as long as the frame buffer for that display is unchanged.
Panel Self Refresh must be supported by both Hardware (source) and Panel (sink).
PSR saves power by caching the framebuffer in the panel RFB, which allows us to power down the link and memory controller. For DSI panels the same idea is called “manual mode”.
The implementation uses the hardware-based PSR support which automatically
enters/exits self-refresh mode. The hardware takes care of sending the
required DP aux message and could even retrain the link (that part isn’t
enabled yet though). The hardware also keeps track of any frontbuffer
changes to know when to exit self-refresh mode again. Unfortunately that
part doesn’t work too well, hence why the i915 PSR support uses the
software frontbuffer tracking to make sure it doesn’t miss a screen
update. For this integration intel_psr_invalidate() and intel_psr_flush()
get called by the frontbuffer tracking code. Note that because of locking
issues the self-refresh re-enable code is done from a work queue, which
must be correctly synchronized/cancelled when shutting down the pipe.”
DC3CO (DC3 clock off)
On top of PSR2, GEN12 adds a intermediate power savings state that turns clock off automatically during PSR2 idle state. The smaller overhead of DC3co entry/exit vs. the overhead of PSR2 deep sleep entry/exit allows the HW to enter a low-power state even when page flipping periodically (for instance a 30fps video playback scenario).
Every time a flips occurs PSR2 will get out of deep sleep state(if it was), so DC3CO is enabled and tgl_dc3co_disable_work is schedule to run after 6 frames, if no other flip occurs and the function above is executed, DC3CO is disabled and PSR2 is configured to enter deep sleep, resetting again in case of another flip. Front buffer modifications do not trigger DC3CO activation on purpose as it would bring a lot of complexity and most of the moderns systems will only use page flips.
-
void intel_psr_disable(struct intel_dp *intel_dp, const struct intel_crtc_state *old_crtc_state)¶
Disable PSR
Parameters
struct intel_dp *intel_dpIntel DP
const struct intel_crtc_state *old_crtc_stateold CRTC state
Description
This function needs to be called before disabling pipe.
Parameters
struct intel_dp *intel_dpIntel DP
Description
This function need to be called after enabling psr.
Parameters
struct intel_dp *intel_dpIntel DP
Description
This function need to be called after pausing psr.
-
bool intel_psr_needs_vblank_notification(const struct intel_crtc_state *crtc_state)¶
Check if PSR need vblank enable/disable notification.
Parameters
const struct intel_crtc_state *crtc_stateCRTC status
Description
We need to block DC6 entry in case of Panel Replay as enabling VBI doesn’t prevent it in case of Panel Replay. Panel Replay switches main link off on DC entry. This means vblank interrupts are not fired and is a problem if user-space is polling for vblank events. Also Wa_16025596647 needs information when vblank is enabled/disabled.
-
void intel_psr_trigger_frame_change_event(struct intel_dsb *dsb, struct intel_atomic_state *state, struct intel_crtc *crtc)¶
Trigger “Frame Change” event
Parameters
struct intel_dsb *dsbDSB context
struct intel_atomic_state *statethe atomic state
struct intel_crtc *crtcthe CRTC
Description
Generate PSR “Frame Change” event.
-
int intel_psr_min_set_context_latency(const struct intel_crtc_state *crtc_state)¶
Minimum ‘set context latency’ lines needed by PSR
Parameters
const struct intel_crtc_state *crtc_statethe crtc state
Description
Return minimum SCL lines/delay needed by PSR.
-
void intel_psr_wait_for_idle_locked(const struct intel_crtc_state *new_crtc_state)¶
wait for PSR be ready for a pipe update
Parameters
const struct intel_crtc_state *new_crtc_statenew CRTC state
Description
This function is expected to be called from pipe_update_start() where it is
not expected to race with PSR enable or disable.
-
void intel_psr_invalidate(struct intel_display *display, unsigned frontbuffer_bits, enum fb_op_origin origin)¶
Invalidate PSR
Parameters
struct intel_display *displaydisplay device
unsigned frontbuffer_bitsfrontbuffer plane tracking bits
enum fb_op_origin originwhich operation caused the invalidate
Description
Since the hardware frontbuffer tracking has gaps we need to integrate with the software frontbuffer tracking. This function gets called every time frontbuffer rendering starts and a buffer gets dirtied. PSR must be disabled if the frontbuffer mask contains a buffer relevant to PSR.
Dirty frontbuffers relevant to PSR are tracked in busy_frontbuffer_bits.”
-
void intel_psr_flush(struct intel_display *display, unsigned frontbuffer_bits, enum fb_op_origin origin)¶
Flush PSR
Parameters
struct intel_display *displaydisplay device
unsigned frontbuffer_bitsfrontbuffer plane tracking bits
enum fb_op_origin originwhich operation caused the flush
Description
Since the hardware frontbuffer tracking has gaps we need to integrate with the software frontbuffer tracking. This function gets called every time frontbuffer rendering has completed and flushed out to memory. PSR can be enabled again if no other frontbuffer relevant to PSR is dirty.
Dirty frontbuffers relevant to PSR are tracked in busy_frontbuffer_bits.
Parameters
struct intel_dp *intel_dpIntel DP
Description
This function is called after the initializing connector. (the initializing of connector treats the handling of connector capabilities) And it initializes basic PSR stuff for each DP Encoder.
Parameters
struct intel_dp *intel_dpstruct intel_dp
Description
We are seeing unexpected link re-trainings with some panels. This is caused by panel stating bad link status after PSR is enabled. Code checking link status can call this to ensure it can ignore bad link status stated by the panel I.e. if panel is stating bad link and intel_psr_link_ok is stating link is ok caller should rely on latter.
Return value of link_ok
-
void intel_psr_lock(const struct intel_crtc_state *crtc_state)¶
grab PSR lock
Parameters
const struct intel_crtc_state *crtc_statethe crtc state
Description
This is initially meant to be used by around CRTC update, when vblank sensitive registers are updated and we need grab the lock before it to avoid vblank evasion.
-
void intel_psr_unlock(const struct intel_crtc_state *crtc_state)¶
release PSR lock
Parameters
const struct intel_crtc_state *crtc_statethe crtc state
Description
Release the PSR lock that was held during pipe update.
-
void intel_psr_notify_dc5_dc6(struct intel_display *display)¶
Notify PSR about enable/disable dc5/dc6
Parameters
struct intel_display *displayintel atomic state
Description
This is targeted for underrun on idle PSR HW bug (Wa_16025596647) to schedule psr_dc5_dc6_wa_work used for applying/removing the workaround.
-
void intel_psr_dc5_dc6_wa_init(struct intel_display *display)¶
Init work for underrun on idle PSR HW bug wa
Parameters
struct intel_display *displayintel atomic state
Description
This is targeted for underrun on idle PSR HW bug (Wa_16025596647) to init psr_dc5_dc6_wa_work used for applying the workaround.
-
void intel_psr_notify_pipe_change(struct intel_atomic_state *state, struct intel_crtc *crtc, bool enable)¶
Notify PSR about enable/disable of a pipe
Parameters
struct intel_atomic_state *stateintel atomic state
struct intel_crtc *crtcintel crtc
bool enableenable/disable
Description
This is targeted for underrun on idle PSR HW bug (Wa_16025596647) to apply remove the workaround when pipe is getting enabled/disabled
-
void intel_psr_notify_vblank_enable_disable(struct intel_display *display, bool enable)¶
Notify PSR about enable/disable of vblank
Parameters
struct intel_display *displayintel display struct
bool enableenable/disable
Description
This is targeted for underrun on idle PSR HW bug (Wa_16025596647) to apply remove the workaround when vblank is getting enabled/disabled