Repository navigation
Conversation
IOMFB 26.x takes setPowerState (A473) on the out-of-band channel, the older contexts' +4, which the T8132 words carry as stream 1 (bit 10): the AP packet goes at shared-memory offset 0x8000, the firmware answers on the same stream, and the callbacks it makes meanwhile arrive at 0x68000 with bit 10 set. The J713 backend so far admitted stream 0 only. Let a top-level AP call name stream 1, and while it is outstanding, decode incoming words with bit 10 as stream-1 packets. Calls nested in one of its callbacks stay on stream 1, at the next aligned offset after the outstanding packet, as on stream 0. Stream-0 traffic is unchanged. The first user is system sleep. Signed-off-by: Erik Bourget <erik@ebourget.net>
Powering the J713 display down and up with setPowerState (A473), the 26.6.2 firmware calls back into the AP: acknowledgeSetPowerState (D106), will_power_off_signal (D002), get_calendar_time_ms (D209), powerUpDART (D572), swap_complete_intent (D592), set_kernel_power_assert (D700), aot_supported_peek (D203), set_power_trace_enable (D008), set_idle_caching_state_ap (D117) and enable_backlight_message_ap_gated (D594). The exact-shape table refused them, which quarantines the session. Add their shapes and answer them for this machine: the notifications and setters with an ACK, the status-returning calls with success, AOT support with false, and the calendar time in milliseconds. The DART and the power assertion are the AP's to hold: the J713 keeps the display domains on across suspend-to-idle. Signed-off-by: Erik Bourget <erik@ebourget.net>
The J713 DCP refused system sleep: the retained T8132 session had no
qualified handshake. setPowerState (A473) out of band is that handshake
on IOMFB 26.x: with the panel blanked, setPowerState(0) powers the
display pipeline down (the firmware logs "power on -> off" and disables
its M3 helpers) and setPowerState(1) brings it back, after which the
next present scans out again.
apple-drm is a consumer of the DCP, so its suspend handler has blanked
the panel when the DCP suspends, and its resume handler restores the
CRTC after the DCP resumed. Power the display down in between, with the
coprocessor running and its power domains kept on through the wakeup
path, as on the older DCPs; refuse sleep should the panel still scan
out. Presents while the display is down are refused.
The request is the 16-byte {u64 state; u8 flags[4]; u8 result_null;
u8 pad[3]}, the reply {u32 value; u32 status}; a nonzero status fails
the transition and the session.
Signed-off-by: Erik Bourget <erik@ebourget.net>
The J713's retained DMA owners refuse system sleep: the radio's DART with managed streams, and the display DARTs, which borrow the running DCP's live page-table root. Neither has a suspend boundary of its own, and their state cannot be restored from a copy. Suspend-to-idle does not need one. These DARTs have no power domain of their own in the tree, and the DCP keeps the display domains on across s2idle, so their state stays where it is. Let them through for suspend-to-idle only, saving their registers solely for resume to check that nothing moved. Every other sleep state is still refused. A DART whose retained state changed cannot be trusted with its live DMA, and a resume error does not stop the PM core from resuming consumers. Quarantine the managed streams and the borrowed display consumers through the same paths as a translation fault before failing resume, so that their later maps are refused. A host test exercises the extracted check, quarantine and map functions. Signed-off-by: Erik Bourget <erik@ebourget.net>
The J713's radio port, whose streams the OS adopts from the boot loader's handoff, refuses system sleep in its noirq phase. It has no suspend boundary of its own, but suspend-to-idle does not need one: the port has no power domain in the tree, so it stays up as any other internal port does, whose resume does nothing. Let it through for suspend-to-idle only; every other sleep state is still refused. Signed-off-by: Erik Bourget <erik@ebourget.net>
A coprocessor can keep running in its power domain across system sleep without system-sleep callbacks of its own, as the J713's GPU firmware does. Describe such a domain, which the OS keeps on during system sleep; runtime power management is unaffected. Signed-off-by: Erik Bourget <erik@ebourget.net>
…tem sleep The J713's G16 GPU has no system-sleep callbacks, so in the noirq phase genpd powers its GFX domain off, and the TVM gate above it, under the running GPU firmware; the power-on at resume then times out. Let a domain marked apple,sleep-retained decline its power-off while the system sleeps: genpd then keeps it and its parents on. Runtime power management is unchanged. Signed-off-by: Erik Bourget <erik@ebourget.net>
Some coprocessors message the AP periodically while idle: the J713's GPU firmware asks for ring service about twice a second, and its AOP sends a report every second. Describe a mailbox whose messages need not wake the system, so the OS can leave them in the FIFO while it sleeps and handle them at resume. Signed-off-by: Erik Bourget <erik@ebourget.net>
…uest The receive IRQ of the ASC mailboxes is IRQF_NO_SUSPEND, so every coprocessor message wakes a CPU out of suspend-to-idle. On the J713 the GPU firmware's idle ring-service kicks and an AOP report every second wake it about three times a second: in 938 s of s2idle, 1472 wakeups and only 512 s in deep idle. For a mailbox marked apple,hold-rx-in-sleep, mask the receive IRQ from noirq suspend to noirq resume, so its messages wait in the FIFO and the consumer handles them on resume. The mailbox is a supplier of its consumer, so this runs after the consumer suspended and before it resumes. The firmware throttles once its outbox fills: after 148 s of s2idle, 11 GPU and 3 AOP messages were waiting, with 3 wakeups and 146.9 s in deep idle. Signed-off-by: Erik Bourget <erik@ebourget.net>
The G16 firmware keeps running across suspend-to-idle: keep its GFX domain on through system sleep, and hold its idle ring-service kicks in the mailbox instead of waking the system about twice a second. Signed-off-by: Erik Bourget <erik@ebourget.net>
With DPMS off, the J713 display was only blanked: the swap to no surface stops presenting, but the display pipeline stays powered. A blanked panel is the state in which system sleep powers the display down with setPowerState(0), and the same works here. After a successful blank, power the display down, and power it back up with setPowerState(1) before the next present, so the first frame after DPMS on brings the panel back. System sleep with the display already down leaves it down and skips its own setPowerState(0); after resume the next present powers it up. A refused transition fails the session, as in system sleep. debugfs reports whether the display is down, how often it went down, and how long the last and longest power-down and power-up took. On the J713, idle on battery with the backlight off, DPMS off saved 346 mW before this change (3.04 -> 2.69 W) and saves 1.20 W with it (2.93 -> 1.73 W), each measured within one run. Over 200 blank/wake cycles, power-down took 128-132 ms and power-up 55-56 ms. Signed-off-by: Erik Bourget <erik@ebourget.net>
With a static image on the J713 panel, the display keeps scanning the frame out of memory 60 times a second. The DCP can instead cache it (IdleCachingMethod 2), but only after the host registers a cache surface: a swap with intent 8 whose sole surface is a separate surface object. Setting the method alone does nothing. Once no flip has followed for idle_cache_ms (default 1000, 0 disables), set the method and submit that swap with a dedicated, retained surface of the panel geometry, which the host never writes. The DCP keeps presenting the frame on screen, steps through its idle states (D117) and asks for a fence (D578) on entry and on each later refresh of the cache, granted for the surface this host registered; the next present, brightness change or blank leaves the cache (D579, then state 0). The surface stays registered across exits, so later entries resubmit it. After a rollback without a flip, entry is retried after ten quiet periods. The surface is allocated at startup; without it, or if the DCP refuses the method, the cache stays off. debugfs reports the idle state, open fences and the number of entries. On the J713, idle on battery with the backlight off, this saves 335 mW (3.27 -> 2.93 W) within one run. Brightness changes, DPMS off/on and suspend-to-idle leave and re-enter the cache. Signed-off-by: Erik Bourget <erik@ebourget.net>
This was referenced Nov 2, 2026
Author
|
Superseded by #830, where this is commit 5. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on #501. This branch is #501's head (
c76eb68dd50f) plus one commit,drm/apple: m4: Cache a static frame while nothing is flipping. Only that last commit is for review here.With a static image, the J713 panel keeps being scanned out of memory 60 times a
second. This registers a DCP idle-cache surface once no flip has happened for
appledrm.idle_cache_ms(default 1000 ms, 0 disables, max 60000), and leavesthe cache on the next present, brightness change or blank.
Power (J713, battery, backlight 0, 180 s per phase, same boot):
Tested on the J713:
the frame on screen, and the first swap after leaving the cache takes
5-10 ms (ordinary swaps 12-14 ms).
cache.
updates live while cached.
entries; out-of-range values are rejected.
This change was developed and tested by Claude (Anthropic), working with me on the J713.