Repository navigation
Conversation
|
This head adds the AOP mailbox hold flag only on J713. The reported 112-second s2idle run and working AOP audio after resume are the board evidence. The parent commits from #434 are already part of this branch and must be applied only once. The stacked kernel at No separate issue found in the one-line follow-up. Merge after both #434 and #449. It inherits #449's lost-retention review hold and the combined kernel's shared-code boot requirement. |
The T8132 (M4) AOP runs the same firmware transport as the T6041 one, and its bootloader hands it over the same way. It also programs the AOP DART's address filter (DAPF) and reserves the filter's windows, which the firmware reaches through its DART at their physical addresses. The windows come in memory-region with the firmware segments, up to 16 of them. Signed-off-by: Erik Bourget <erik@ebourget.net>
The T8132 (M4) AOP takes the T6040 boot arguments (EC0p 0x100_0000_0000, nCal 0, alig 64, AOPt 0): iBoot leaves the boot-argument table at its defaults in the AOP SRAM and the AOP halted, and the ADT gives __ETEXT the DART address 0x100_0000_0000. The bootloader programs the AOP DART's DAPF and reserves the firmware segments and the DAPF windows, so the T6040 configuration applies unchanged. Tested on J713 (MacBook Air 13" M4) with m1n1 handing the AOP over (its memory-region holds __ETEXT, __OS_LOG and the 15 DAPF windows): the AOP starts, and the microphones capture (3 channels, 48 kHz) through aop_audio. Signed-off-by: Erik Bourget <erik@ebourget.net>
The T8132 AOP audio service is the T6041 one: the same LPAI microphone flow, and the same ADMAC channel map for the speakers and the jack. Allow "apple,t8132-aop-audio" in front of the T6041 compatible. A machine brought up in steps lists only the streams it has so far, so allow the microphones alone, and the microphones with the jack, besides the speaker layouts. Signed-off-by: Erik Bourget <erik@ebourget.net>
Describe the T8132 AOP with its mailbox and DART, and the audio fabric's two ADMACs (admac-leap-ns on DART stream 10, admac-base-ns on stream 8), all disabled. Addresses and interrupts are the ADT's; the ADMAC channel map is the T6041 one: the microphones on LEAP channel 1. Signed-off-by: Erik Bourget <erik@ebourget.net>
Enable the AOP, its DART and mailbox, and the ADMACs on the MacBook Air 13" M4, with the AOP audio service for the three microphones. /chosen already asks for the AOP's handoff: m1n1 programs the AOP DART's DAPF and adds the firmware segments and the DAPF windows to the AOP's memory-region, or disables the AOP. Signed-off-by: Erik Bourget <erik@ebourget.net>
The jack component was only registered along with the speaker one, so a machine whose audio node lists the jack's DMA channels but not yet the speakers' got no jack. Register the speaker component only where the node lists "spkr", and the jack's where it lists "cout" and "cin", each on its own. Creating the services does not reach the firmware; nothing changes for the J616s, which lists all of them. Signed-off-by: Erik Bourget <erik@ebourget.net>
The MacBook Air 13" M4 (J713) headphone jack is a card of its own on the AOP, like the J616s one. Signed-off-by: Erik Bourget <erik@ebourget.net>
The J713 jack runs on the AOP firmware's MCA cluster 2 with the same CS42L84 setup as the J616s jack. Use the J616s jack configuration, including its -6 dB cap on the headphone DAC: this board's analog full scale is unmeasured too. Signed-off-by: Erik Bourget <erik@ebourget.net>
Add the CS42L84 on i2c1 (reset on nub GPIO 17, interrupt on AP GPIO 98, from the ADT), the jack's ADMAC channels on the AOP audio node (base-ns TX2 and RX2, as on the J616s) and the jack's own card. The codec is the first consumer of the i2c1 power domain, so the J713 power-domain policy now enables it; it has no parent domains. Signed-off-by: Erik Bourget <erik@ebourget.net>
The MacBook Air 13" M4 (J713) speakers are a card of their own on the AOP's speaker stream, like the J616s ones. Signed-off-by: Erik Bourget <erik@ebourget.net>
The MacBook Air 13" M4 (J713) runs its four SN012776 amps, a woofer and a tweeter per side, on the AOP's speaker stream exactly like the J616s: the same 250-bit frame, I2S with an inverted frame clock, six playback and twelve sense slots, of which the four amps take the first four and eight. Amp gain 15 and the -20 dB safe volume as on the other SN012776 machines. The speaker front-end's channel count was one per amp; add speaker_fe_channels for a CPU stream with more slots than amps, and give the J713 six. Its last two channels are silent. Signed-off-by: Erik Bourget <erik@ebourget.net>
Add the four SN012776 amps on i2c3 from the ADT (audio-speaker at 0x38 and its speaker1..3: left woofer 0x38, right woofer 0x3b, left tweeter 0x39, right tweeter 0x3c), each with its sense slots from speaker-config (imon at RX byte 4i, vmon at 4i + 2), the shared interrupt on AP GPIO 14 and the shared shutdown line on AP GPIO 15 as the fail-closed SDZ group's fixed regulator. The speaker card lists the amps in the ADT provider order, so each takes its native playback slot, with the amp-tx-zd-config idle masks. The AOP audio node gets the speaker and sense channels (base-ns TX0 and RX0): the J616s stream, of which the four amps take the first four playback and eight sense slots. The amps are the first consumer of the i2c3 power domain. Signed-off-by: Erik Bourget <erik@ebourget.net>
On an AOP-fed speaker stream the TDM bus keeps running for a while after the playback stream stops, and the amplifiers' current and voltage sense slots are still sampled in that time. An amplifier put in software shutdown then can leave garbage in its sense slots. Add a property for such amplifiers: they must not enter software shutdown until the bus has stopped. Signed-off-by: Erik Bourget <erik@ebourget.net>
On the J713 the AOP keeps the speaker TDM bus running for a while after a playback stream stops, and the speaker protection still reads the amplifiers' I/V sense words in that time. Each amp is muted and then shut down in turn as the stream ends, so the shutdowns land in that tail. The right tweeter's voltage sense slot then reads full scale for about 20 samples at every stream stop, even for a stream of digital silence played with the volume locked; the protection daemons charge that as power. With apple,deferred-shutdown, mute the amp at the stream's end as before, but put it in software shutdown only 150 ms later, after the bus has stopped (it ran on for up to 73 ms on the J713). A stream that starts in between cancels it. Suspend and removal shut the amp down at once. Such an amp sees the bus clock stop while it waits, and may see it latched again after its shutdown; that clock-only fault is expected then and no longer logged. Amps without the property keep the current behaviour. On a J713 the full-scale words in the stream tails go from about 90 per test (three silent streams and a chord) to none, with no fault logged, and every amp still ends in software shutdown. Signed-off-by: Erik Bourget <erik@ebourget.net>
The J713's AOP keeps the speaker bus running briefly after a stream stops, and the speaker protection reads the amps' sense words in that time. Have the four amps wait for the bus clock to stop before they go to software shutdown. Signed-off-by: Erik Bourget <erik@ebourget.net>
With apple,deferred-shutdown the muted amp stays powered after a stream until the bus clock stops, and keeps latching TDM clock faults while it waits; the fault handler ignores them while stream_stopped is set. The amps share one fault line and each handler reads six latches over I2C, so a latch can reach its handler several milliseconds late. When the next stream unmutes the amp in that window, stream_stopped is already clear and the stale latch is reported as a fault on the new stream. On the J713 this hit the first amp the link unmutes on 9 of 32 silent streams that started within 140 ms of the end of the last one, and on none of 32 that started later. At unmute, clear the latches before clearing stream_stopped when the first latch register holds only the clock fault (the clear takes every latch, so any other fault there is left for the handler), and hold a lock across the handler's read and judgement of the latches so that the unmute cannot fall between them. With this, none of 96 silent streams logged a fault, 48 of them started within 140 ms of the last. Signed-off-by: Erik Bourget <erik@ebourget.net>
…leep Since the speaker volumes are locked from suspend-prepare, the speakers stay silent after the first system sleep. Locking clips every speaker volume to the lock's ceiling (1, -100 dB on the SN012776), and unlocking only lifts the ceiling again. After a lost lease that is fine: speakersafetyd gets -ETIMEDOUT, restarts and sets the volumes itself. The system-sleep lock is deliberately not reported as a lost lease, so the daemon keeps its state and never writes the volumes again. They stay at -100 dB until the daemon restarts. alsactl then stores them that way at shutdown and restores them at the next boot, where they stay unless the daemon's cold start sets the volumes again after that restore. Keep the speaker volumes at suspend-prepare, before the lock clips them, and set them again at the first unlock after it. That is the daemon's first ping after the resume, which in practice comes when playback next starts. These are the values the daemon set and still assumes. The daemon may not ping between two sleeps. A suspend-prepare that finds the volumes locked already keeps what an earlier one saved, so a second sleep before any playback doesn't lose them. Hold the card's controls for reading from keeping the volumes until they are clipped, so a volume the daemon writes meanwhile can't be overwritten by an older, higher one at the unlock. Hold them as well in the work that can unlock after a back-end starts or stops, so setting the volumes again there doesn't race a volume write either. Control writes hold them for writing and take volume_lock_mutex inside, in the same order. A new owner of the lock, such as a restarted daemon, sets the volumes itself: drop what was kept then, and when the card is removed. Nothing is kept for a card that is shutting down. The card's remove waits for the unlock work, which takes the card's controls, while the snd_card still exists. Tested on a J713: after a suspend-to-idle the four speaker volumes are back at 0 dB and the speakers play, without restarting speakersafetyd. The KUnit cases go through the lock control and the PM notifier: one sleep, two sleeps before the daemon pings, and a new owner after a sleep. Fixes: 1cbce20 ("ASoC: apple: macaudio: lock the speaker volumes before userspace freezes") Signed-off-by: Erik Bourget <erik@ebourget.net>
The AOP firmware keeps a device attachment for as long as it runs, and the driver has no way to drop one at removal. When the module is loaded again, the probe's attach calls for the microphone devices get kIOReturnBusy back and the probe fails. The machine then has no audio until it reboots: with the T6040 flow the speaker and jack streams are registered by the same probe and are lost as well. The speaker and jack services already treat that return as attached. Do the same in the probe, and share the constant with aop_spkr. The probe's property writes that follow are accepted by the still attached devices. Signed-off-by: Erik Bourget <erik@ebourget.net>
The component probe resets the amp and reinitialises the register cache, which clears the SDOUT idle slot mask and the force-0 enable. The idle slot setup cached in the driver data survives the reset, though, so when the card binds again and set_tdm_idle() asks for the same mask and mode, it returns early and the force-0 enable is never written. set_bclk_ratio() writes the mask again but not the enable. On the J713 every rebind of the speaker card left the two amps that force their idle slots to zero without the enable, and the other two amps' voltage sense words then came back with the top bit set in about a quarter of the frames. The speaker protection daemon reads those as a voltage without current and holds the speakers at a safe level. Clear the cached setup after the reset, so that the next set_tdm_idle() writes it. Signed-off-by: Erik Bourget <erik@ebourget.net>
The component probe requests the fault IRQ as a devres of the I2C device, which stays bound when the sound card is torn down. Every rebind of the card probes the component again and adds another handler for the same amp on the line: after two rebinds the J713's four amps had twelve handlers on their shared IRQ, each fault interrupt ran every one of them, and each does six I2C reads. Free the IRQ in the component remove. Request it as the probe's last step, so that a probe that fails later does not leave a handler behind either. Signed-off-by: Erik Bourget <erik@ebourget.net>
tas2764_codec_probe() enables the SDZ supply and raises the shutdown GPIO before it resets the amp and writes its setup. When one of those writes fails, or an amp in an SDZ group can't get its fault IRQ, the probe returns with the supply still enabled. ASoC doesn't call the component's remove after a failed probe, so nothing balances that enable, and every later probe attempt adds another. The supply then stays on after the card is removed and, for an amp outside an SDZ group, through system sleep as well. Undo the power-up on those failures: lower the shutdown GPIO and drop the supply enable, unless the group failed and its supply was already forced off, as the remove does. Signed-off-by: Erik Bourget <erik@ebourget.net>
The AOP sends a report every second; hold it in the mailbox across suspend-to-idle instead of waking the system. Signed-off-by: Erik Bourget <erik@ebourget.net>
5d519c2 to
1bee5ac
Compare
Holds the J713 AOP's once-a-second report in its mailbox during suspend-to-idle, so the report no longer wakes the CPUs.
Depends on #820 and #831.
aop_mboxnode this commit sets the flag on. The first 21 commits here are ASoC: apple: J713 (M4 MacBook Air) microphones, headphone jack and speakers #820's; only the last commit is new.apple,hold-rx-in-sleep(binding and mailbox driver), as part of the J713 suspend-to-idle series. Until it lands, the flag is inert.This was split out of the suspend-to-idle series (first #449, now #831), because that series doesn't depend on the AOP series. Rebased from the closed #434 onto #820, so the AOP commits are carried only once. The commit itself is unchanged.
Commit
Testing
On the J713, on integration/aurora 41c4055 with #820, the suspend-to-idle series (now #830 and #831), #432 and #429:
over 222 s of s2idle, the AOP mailbox (
390608000.mailbox-recv) took 3 interrupts. It took 10 in the first 10 s awake after resume.Again with the whole J713 PR stack (#830–#833, #819/#820, #531, #825): over 82 s of s2idle, the AOP mailbox took 5 interrupts.
Earlier, with the suspend-to-idle series (then #449) on 26.6.2 firmware: over 112 s of s2idle, the AOP mailbox (
390608000.mailbox-recv) took 3 interrupts, against 946 in 938 s without the flag. The AOP audio worked after resume.This change was developed and tested by Claude (Anthropic), working with me on the J713.