Skip to content

Commit a119130

Browse files
committed
fix(2michat-v2): run mixer tune every boot, propagate amixer failures
Address review feedback on florian-asche#41: drop the first-boot guard so the mixer tuning runs on every boot. PipeWire / WirePlumber manage ALSA state per session and can reset controls to 0% between reboots, which would leave users stuck silent if the service only ran once. Also make configure_audio.sh surface amixer set failures (previously swallowed by unconditional return 0), so that a broken tuning exits non-zero and the systemd Restart=on-failure path actually retries instead of falsely claiming success and persisting the broken state via alsactl store. Verified with a shim-based test harness (5 cases: happy path, single amixer set failure, missing control, multiple failures, card timeout).
1 parent dbbf003 commit a119130

3 files changed

Lines changed: 26 additions & 11 deletions

File tree

02-stage-audiodriver-2michat-v2/02-set-audio-volume/files/configure_audio.service

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@
22
Description=PiCompose - Configure Audio volume setting (ReSpeaker 2-Mic HAT V2.0)
33
After=sound.target alsa-restore.service
44
Wants=sound.target alsa-restore.service
5-
ConditionPathExists=!/var/lib/configure_audio/success
65

76
[Service]
87
Type=oneshot
98
ExecStart=/usr/bin/configure_audio.sh
10-
ExecStartPost=/usr/bin/mkdir -p /var/lib/configure_audio
11-
ExecStartPost=/usr/bin/touch /var/lib/configure_audio/success
129
RemainAfterExit=yes
1310
Restart=on-failure
1411
RestartSec=30s

02-stage-audiodriver-2michat-v2/02-set-audio-volume/files/configure_audio.sh

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ set -u
66
# tuning these three separate gain stages, end users report "silent card"
77
# even with HA / LVA output at maximum.
88
#
9+
# Runs on every boot via configure_audio.service — PipeWire / WirePlumber
10+
# manages ALSA mixer state per session and can reset controls to 0% between
11+
# reboots, so a first-boot-only guard would let users end up stuck silent.
12+
#
913
# Values below are the safe defaults calibrated against JST-connected
1014
# speakers (peaks clip at 100% PCM). Tune further in-field with `amixer`
1115
# and persist via `alsactl store`.
@@ -36,15 +40,22 @@ wait_for_card_and_control() {
3640
return 1
3741
}
3842

43+
# Returns 0 on success OR when the control is absent (expected on hardware
44+
# variants without that stage). Returns 1 only when `amixer set` actually
45+
# failed for a control that exists — so a broken tuning surfaces as a
46+
# non-zero exit from the script and triggers the systemd retry.
3947
set_control_if_exists() {
4048
local card="$1"
4149
local control="$2"
4250
shift 2
4351

4452
if amixer -c "$card" scontrols | grep -Fq "'$control'"; then
4553
echo "Setting $control on $card to $*"
46-
amixer -c "$card" set "$control" "$@"
47-
return 0
54+
if amixer -c "$card" set "$control" "$@"; then
55+
return 0
56+
fi
57+
echo "amixer set failed for '$control' on $card" >&2
58+
return 1
4859
fi
4960

5061
echo "Control '$control' not found on $card, skipping"
@@ -60,16 +71,23 @@ if ! wait_for_card_and_control seeed2micvoicec PCM; then
6071
fi
6172
CARD="seeed2micvoicec"
6273

74+
FAIL=0
75+
6376
# Digital pre-DAC attenuator. 100% clips on typical speakers; 85% keeps
6477
# headroom while still being clearly audible.
65-
set_control_if_exists "$CARD" "PCM" 85%
78+
set_control_if_exists "$CARD" "PCM" 85% || FAIL=1
6679

6780
# DAC output gains (ship at -23.5 dB by default — main source of quietness).
68-
set_control_if_exists "$CARD" "HP DAC" 100%
69-
set_control_if_exists "$CARD" "Line DAC" 100%
81+
set_control_if_exists "$CARD" "HP DAC" 100% || FAIL=1
82+
set_control_if_exists "$CARD" "Line DAC" 100% || FAIL=1
7083

7184
# Analog output amps (ship slightly below max and muted on some units).
72-
set_control_if_exists "$CARD" "HP" 100% unmute
73-
set_control_if_exists "$CARD" "Line" 100% unmute
85+
set_control_if_exists "$CARD" "HP" 100% unmute || FAIL=1
86+
set_control_if_exists "$CARD" "Line" 100% unmute || FAIL=1
87+
88+
if [ "$FAIL" -ne 0 ]; then
89+
echo "One or more amixer set calls failed; not storing state." >&2
90+
exit 1
91+
fi
7492

7593
alsactl store

docs/hardware_2mic_v2.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Unlike v1 — which needs an out-of-tree DKMS kernel module — v2 uses the main
3333
2. `dtparam=i2c_arm=on` in `/boot/firmware/config.txt`.
3434
3. Mixer tuning on first boot — the TLV320 ships with three separate attenuators all well below 100 % (`HP DAC` at -23.5 dB in particular), producing a card that appears to work but is inaudible at typical application volumes.
3535

36-
The PiCompose `02-stage-audiodriver-2michat-v2` stage performs all three steps automatically. The mixer tuning runs once on first boot (guarded by `/var/lib/configure_audio/success`) so that subsequent manual `amixer` adjustments via `alsactl store` are preserved across reboots.
36+
The PiCompose `02-stage-audiodriver-2michat-v2` stage performs all three steps automatically. The mixer tuning is applied by `configure_audio.service` on every boot: PipeWire / WirePlumber manage ALSA state per session and can reset the mixer between reboots, so a first-boot-only guard would let users end up stuck at 0%. Customization via `amixer` is still possible at runtime — it just won't survive a reboot.
3737

3838
## Additional information
3939

0 commit comments

Comments
 (0)