Add Audio_Hamoa: ALSA-based audio playback and recording tests for Ha…#477
Add Audio_Hamoa: ALSA-based audio playback and recording tests for Ha…#477Teja Swaroop (tmoida) wants to merge 3 commits into
Conversation
e479130 to
21606a2
Compare
Srikanth Muppandam (smuppand)
left a comment
There was a problem hiding this comment.
The Hamoa mixer details are useful, but I do not think we should add a new separate Audio_Hamoa test suite. Existing AudioPlayback and AudioRecord already provide most of the orchestration this PR reimplements: clip/config discovery, result suffixes, LAVA testcase IDs, backend/bootstrap handling, and standard result reporting.
The better approach is to add a Hamoa ALSA mixer/profile layer and reuse the existing tests:
AudioPlayback --backend alsa --alsa-profile hamoa --device handset|headset
AudioRecord --backend alsa --alsa-profile hamoa --device handset|headset
This also aligns with PR #461, where check_dependencies() can recover missing commands through the active package manager. We can add mappings for aplay/arecord/amixer to alsa-utils and let the existing tests recover dependencies instead of creating a separate suite.
Recommendation:
Extract the Hamoa mixer commands into a reusable ALSA Hamoa profile helper.
Extend existing AudioPlayback and AudioRecord with a Hamoa ALSA profile and dependency recovery through PR Add provider-based package dependency recovery #461.
1343228 to
e4fd164
Compare
|
Srikanth Muppandam (@smuppand) Thank you for the feedback. I've implemented the recommended approach: Implementation SummaryIntegrated Hamoa into existing AudioPlayback/AudioRecord tests - no separate test suite created. Architecture Changes
Please review it and let me know your feedback. |
Srikanth Muppandam (smuppand)
left a comment
There was a problem hiding this comment.
This should not stay as one commit in its current form. It mixes three different types of change. Suggested commit split inside the same PR
audio: move common helpers under utils/audio
audio: add Hamoa ALSA profile helpers
audio: add Hamoa playback and capture LAVA tests
|
|
||
| # ---------------- Defaults / CLI ---------------- | ||
| AUDIO_BACKEND="" | ||
| ALSA_PROFILE="${ALSA_PROFILE:-generic}" # ALSA profile (hamoa, generic) |
There was a problem hiding this comment.
ALSA_PROFILE is introduced here, but AudioRecord does not apply the same backend coercion that AudioPlayback uses for non-generic ALSA profiles. --alsa-profile hamoa can still go through backend auto-detection and select PipeWire/PulseAudio instead of direct ALSA, so the Hamoa path may not actually be tested.
Recommended fix: before backend detection, mirror AudioPlayback’s logic: if ALSA_PROFILE is non-generic and AUDIO_BACKEND is unset, set AUDIO_BACKEND=alsa.
| SRC_ID="$AUDIO_ALSA_CAPTURE_DEVICE" | ||
| # Hardware-specific ALSA profiles (e.g., Hamoa) configure mixer controls | ||
| # and provide explicit device paths for different audio paths | ||
| if [ "$ALSA_PROFILE" != "generic" ] && [ -n "$DEVICE" ]; then |
There was a problem hiding this comment.
The Hamoa profile setup is only reached later in the ALSA source-selection block, after the earlier backend readiness check has already required the generic ALSA capture probe. If valid Hamoa capture paths can be skipped before setup_alsa_profile_hamoa_capture_* configures the mixer/device.
Recommended fix: make the earlier backend check profile-aware, or move Hamoa profile setup/device validation before the generic audio_probe_alsa_capture_profile gate.
| if [ -n "$SRC_ID" ]; then | ||
| SRC_LABEL="$(pw_source_label_safe "$SRC_ID")" | ||
| pw_set_default_source "$SRC_ID" >/dev/null 2>&1 || true | ||
| wpctl set-default "$SRC_ID" >/dev/null 2>&1 || true |
There was a problem hiding this comment.
This replaces the existing pw_set_default_source helper with a direct wpctl set-default call. It bypasses the repo’s existing PipeWire helper abstraction, so future compatibility/error handling fixes in the helper will not apply here.
Recommended fix: keep using pw_set_default_source "$SRC_ID" >/dev/null 2>&1 || true unless there is a specific helper bug being fixed in the same PR.
| if [ "$retry_alsa" -eq 1 ]; then | ||
| if printf '%s\n' "$SRC_ID" | grep -q '^hw:'; then | ||
| alt_dev="plughw:${SRC_ID#hw:}" | ||
| bytes="$(file_size_bytes "$record_out" 2>/dev/null || echo 0)" |
There was a problem hiding this comment.
bytes is now assigned only inside the if [ "$rc" -ne 0 ] branch. When the first arecord succeeds with rc=0, the later pass check can still see ${bytes:-0} as 0 and falsely fail a valid recording.
Recommended fix: assign bytes="$(file_size_bytes "$record_out" 2>/dev/null || echo 0)" immediately after rc=$?, before the if [ "$rc" -ne 0 ] block.
| . "$TOOLS/audio_common.sh" | ||
| . "$TOOLS/audio/audio_common.sh" | ||
| # shellcheck disable=SC1091 | ||
| . "$TOOLS/audio/alsa_common.sh" |
There was a problem hiding this comment.
audio_common.sh already sources alsa_common.sh, but this runner also sources alsa_common.sh directly. Helper loading is duplicated and can become unsafe if alsa_common.sh later adds non-idempotent initialization.
Recommended fix: pick one convention: either let audio_common.sh source ALSA helpers, or require callers to source both explicitly, but do not do both.
|
|
||
| # Source ALSA-specific helpers (includes Hamoa profile functions) | ||
| # Use BASH_SOURCE to get the directory of this script file when sourced | ||
| if [ -n "${BASH_SOURCE:-}" ]; then |
There was a problem hiding this comment.
The code says it uses BASH_SOURCE, but it still resolves the directory using dirname "$0". When this file is sourced, $0 points to the parent shell/script, not audio_common.sh, so alsa_common.sh can be sourced from the wrong directory or fail to load.
Recommended fix: use ${BASH_SOURCE[0]} in the bash branch, and for POSIX shells prefer $TOOLS/audio or a caller-provided helper directory.
| return 1 | ||
| fi | ||
|
|
||
| if aplay -l 2>/dev/null | grep -q "card 0"; then |
There was a problem hiding this comment.
check_alsa_device() ignores the requested $device and only checks whether aplay -l contains card 0. Impact: plughw:0,1, plughw:0,2, or plughw:0,3 may be reported accessible even if that specific PCM does not exist capture devices are also validated using playback enumeration.
Recommended fix: parse the requested card/device and validate the exact PCM, using aplay -l for playback and arecord -l for capture, or validate against /proc/asound/pcm with direction.
|
|
||
| validate_audio_file "$file" || return 1 | ||
|
|
||
| size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null || echo 0) |
There was a problem hiding this comment.
validate_recording() repeats direct stat size logic instead of reusing the existing file_size_bytes helper used by the audio runners. Impact: file-size behavior can drift across helpers and scripts.
Recommended fix: use file_size_bytes "$file" here so size handling remains consistent across Runner/utils audio code.
|
|
||
| # Hamoa profile wrapper for handset playback | ||
| # Args: $1 - optional log directory path | ||
| setup_alsa_profile_hamoa_playback_handset() { |
There was a problem hiding this comment.
The Hamoa profile wrappers only call the mixer setup function and return its status. The runners log that profile/device validation is handled by the profile, but the profile wrapper does not validate the selected PCM device or verify mixer state.
Recommended fix: after mixer setup, call exact ALSA device validation and validate_mixer_state for the expected profile before returning success.
|
|
||
| # Get ALSA device for Hamoa handset playback | ||
| get_alsa_device_hamoa_playback_handset() { | ||
| echo "plughw:0,1" |
There was a problem hiding this comment.
The profile-specific device getters hard-code the same device mappings already defined in the ALSA_DEVICE_* constants and exposed through get_alsa_device(). The device mappings can drift in two places.
Recommended fix: delegate these getters to get_alsa_device handset_playback, headset_playback, handset_capture, and headset_capture, or remove the profile-specific getters and call the generic helper directly.
Reorganize audio utilities by moving audio_common.sh to the audio/ subdirectory alongside alsa_common.sh. Update sourcing to use \$TOOLS/audio path for reliable loading when audio_common.sh is sourced from any script location. - Reorganized audio utilities: Moved audio_common.sh to audio/ subdirectory - Updated path structure: All scripts now use audio/audio_common.sh Signed-off-by: Teja Swaroop Moida <tmoida@qti.qualcomm.com>
Add ALSA mixer configuration and device management for Hamoa platform. Provides hardware-specific audio path setup for: - Handset playback (plughw:0,1): 4-way speaker system via WSA2/WSA amplifiers with 44 mixer controls Audio path: AIF1_PB -> WSA2/WSA RX0/RX1 -> WooferLeft/Right + TweeterLeft/Right - Headset playback (plughw:0,0): Stereo headphones via RX codec with 22 mixer controls in Class-H High Fidelity mode Audio path: AIF1_PB -> RX_MACRO RX0/RX1 -> RX INT0/INT1 -> HPHL/HPHR - Handset capture (plughw:0,3): Built-in VA_DMIC with 8 mixer controls Audio path: DMIC0/DMIC1 -> VA DMIC MUX0/MUX1 -> VA DEC0/DEC1 -> VA_AIF1_CAP - Headset capture (plughw:0,2): SoundWire microphone with 10 mixer controls Audio path: SWR_MIC -> ADC2 -> TX SMIC MUX0 -> TX DEC0 -> TX_AIF1_CAP Profile functions validate PCM device availability and mixer state after configuration before returning success. - Added ALSA profile support with --alsa-profile and --device options - Hardware-specific mixer configuration for Hamoa handset and headset devices - Mixer validation verifies all mixer settings before audio operations Signed-off-by: Teja Swaroop Moida <tmoida@qti.qualcomm.com>
e4fd164 to
a704af8
Compare
Fixes qualcomm-linux#454 Add YAML test definitions and extend AudioPlayback/AudioRecord run.sh scripts to support Hamoa ALSA profile testing on X1E80100-EVK. Tests audio playback on two output devices: - Handset (plughw:0,1): 4-way speaker system using WSA2/WSA amplifiers - Headset (plughw:0,0): Stereo headphones using RX codec Tests audio recording on two input devices: - Handset (plughw:0,3): Built-in VA_DMIC (Voice Activation DMIC) - Headset (plughw:0,2): External microphone using TX codec Key features: - Dual device support: Test handset, headset, or both devices - Clip/config-based testing: Auto-discovery of audio clips and configurations - CI/LAVA integration: - Unique result file suffixes prevent file collisions in parallel runs - Unique testcase IDs prevent LAVA testcase ID collisions - Comprehensive logging: Mixer dumps, playback/recording logs per test case - Recording validation: File size and format verification Implementation changes: - Moved Hamoa YAML files to main AudioPlayback/AudioRecord directories - Integrated Hamoa support into main run.sh scripts via ALSA profile system - Removed --verbose flag from YAML files to eliminate warnings - Add ALSA_PROFILE backend coercion in AudioRecord/run.sh to mirror AudioPlayback behavior for hardware-specific profiles - Make backend_ok check profile-aware to skip generic ALSA probe when a hardware profile handles device validation - Restore pw_set_default_source helper in AudioRecord/run.sh - Fix bytes variable scope to prevent false failures on successful arecord when rc=0 Comprehensive README updates for both AudioPlayback and AudioRecord: - Dedicated Hamoa ALSA Profile Support section - Hamoa usage examples with sample output from actual device - Device mapping table (handset/headset to hardware paths) - CI/LAVA integration guidelines" Signed-off-by: Teja Swaroop Moida <tmoida@qti.qualcomm.com>
a704af8 to
f3074f4
Compare
|
Srikanth Muppandam (@smuppand) Thank you for the detailed review. All comments have been addressed in the latest push. Changes MadeCommit 1:
Commit 2:
Commit 3:
Please review and let me know your feedback. |
|
|
||
| # Source ALSA-specific helpers (includes Hamoa profile functions) | ||
| # shellcheck disable=SC1091 | ||
| . "$TOOLS/audio/alsa_common.sh" |
There was a problem hiding this comment.
This moves the shared audio library from "$TOOLS/audio_common.sh" to "$TOOLS/audio/audio_common.sh"
Retain "Runner/utils/audio_common.sh" as a compatibility shim that sources the new file:
shellcheck disable=SC1091
. "$TOOLS/audio/audio_common.sh"
The compatibility entry point can be removed later through a separate, repository-wide migration.
| # These map logical device names to ALSA plughw device identifiers | ||
| ALSA_DEVICE_HANDSET_PLAYBACK="plughw:0,1" # 4-way speaker system (WSA2 + WSA) | ||
| ALSA_DEVICE_HEADSET_PLAYBACK="plughw:0,0" # Stereo headphones (RX codec) | ||
| ALSA_DEVICE_HANDSET_CAPTURE="plughw:0,3" # Built-in microphone (MSM_DMIC) |
There was a problem hiding this comment.
Card index "0" is registration-order dependent. HDMI, USB audio, virtual cards, or another sound card can cause the Hamoa card to be assigned a different index. PCM numbers are also target-topology data rather than global Hamoa constants.
Resolve the target and ALSA card dynamically:
- Detect the target from an explicit override, "PLATFORM_TARGET", DT compatible, or DT model.
- Select a target-specific audio profile.
- Resolve the ALSA card using a stable card ID or card name.
- Read the route-specific PCM number from the selected profile.
- Construct "plughw:${card_index},${pcm_device}" at runtime.
- Reject ambiguous card matches instead of selecting the first card.
Reuse the existing audio card discovery helpers rather than introducing fixed card indices.
| # Get the full control output to check both enum index and string value | ||
| control_output=$(amixer -c 0 cget iface=MIXER,name="$control" 2>/dev/null) | ||
|
|
||
| if [ -z "$control_output" ]; then |
There was a problem hiding this comment.
The complete ENUM output contains all supported values, not only the currently selected value. For example:
Items: 'Off' 'On'
Item0: 'Off'
Searching the full output for "On" returns success even though the selected value is "Off". Numeric and boolean values are also checked through substring matching, so expected "1" may match "10" or "100".
Recommended fix: check_mixer_control "$card_index" "$control" "$expected_value"
Parse only the active "Item0:" field for ENUM controls and the current "values=" field for boolean/integer controls. Compare exact normalized values rather than searching the complete output.
| # Checks key mixer controls to ensure audio path is configured correctly | ||
| # Args: $1 - device type (handset_playback, headset_playback, handset_capture, headset_capture) | ||
| # Returns: 0 if mixer state is valid, 1 otherwise | ||
| validate_mixer_state() { |
There was a problem hiding this comment.
"validate_mixer_state()" checks only two controls per route, while the setup functions configure approximately 44 handset playback controls, 22 headset playback controls, 8 handset capture controls, and 10 headset capture controls.
Use the selected target profile as the single source of truth. Every profile entry marked "required" should be:
- checked for existence before setup;
- applied to the resolved card;
- read back after setup;
- compared against the exact expected value.
Do not maintain a large setup list and a separate two-control validation list.
| # Sets up 4-way speaker system using WSA2 and WSA amplifiers | ||
| # Audio path: AIF1_PB -> WSA2/WSA RX0/RX1 -> WooferLeft/Right + TweeterLeft/Right | ||
| # Returns: 0 on success, 1 on failure | ||
| setup_handset_playback_mixer() { |
There was a problem hiding this comment.
Resolve the mixer configuration dynamically based on the detected target, direction, and endpoint:
target + playback|capture + handset|headset
Keep target-specific controls in declarative profile files, for example:
MIXER|WSA2 WSA RX0 MUX|AIF1_PB|required
MIXER|WSA2 WSA_RX0 INP0|RX0|required
MIXER|WSA2 WSA_RX0 Digital Volume|84|required
Use one common executor:
setup_audio_route "$target" playback handset "$logdir"
Mixer-control names must come from a profile explicitly associated with the detected target. They should not be synthesized from the target name.
| rc=$? | ||
| bytes="$(file_size_bytes "$record_out" 2>/dev/null || echo 0)" | ||
|
|
||
| retry_alsa=0 |
There was a problem hiding this comment.
The modified retry logic enters the alternate-device path only when "arecord" returns non-zero.
"arecord" can return "0" while producing an empty, header-only, or undersized WAV. In that case, no alternate-device or fallback-format attempt is made.
Recommended fix: Retry when either the command fails or the output is invalid:
retry_alsa=0
if [ "$rc" -ne 0 ] ||
[ "${bytes:-0}" -le 1024 ] 2>/dev/null; then
retry_alsa=1
fi
Validate the output after every attempt. Do not convert a non-zero command result to PASS based only on file size; validate the WAV structure and expected data size first.
| [INFO] 2026-04-15 19:24:12 - [play_16KHz_16b_2ch] loop 1/1 start=2026-04-15T19:24:12Z clip=yesterday_16KHz_30s_16b_2ch.wav backend=alsa sink=speakers(plughw:0,1) | ||
| [INFO] 2026-04-15 19:24:12 - [play_16KHz_16b_2ch] exec: aplay -D "plughw:0,1" "/home/AudioClips/yesterday_16KHz_30s_16b_2ch.wav" | ||
| [INFO] 2026-04-15 19:24:24 - [play_16KHz_16b_2ch] evidence: pw_streaming=0 pa_streaming=1 alsa_running=0 asoc_path_on=0 pw_log=0 | ||
| [WARN] 2026-04-15 19:24:24 - [play_16KHz_16b_2ch] nonzero rc=1 but evidence indicates playback - PASS |
There was a problem hiding this comment.
Fix backend-specific playback validation and replace this sample with a run where:
- "aplay" succeeds or terminates through the expected timeout path;
- elapsed playback time is valid;
- ALSA/ASoC evidence is present when required;
- PipeWire/PulseAudio activity is not used to validate direct ALSA playback.
| [INFO] 2026-04-15 19:31:45 - Using ALSA profile: hamoa for device: handset | ||
| [INFO] 2026-04-15 19:31:45 - Configuring mixer for handset capture (mic)... | ||
| [INFO] 2026-04-15 19:31:45 - Handset capture mixer configured successfully | ||
| [INFO] 2026-04-15 19:31:45 - ALSA profile configured successfully, device: plughw:0,0 |
There was a problem hiding this comment.
Regenerate the sample from current HEAD after target and card discovery are implemented. Include the detected target, matched ALSA card ID/index, selected route, PCM device, and final command.
| ### Hamoa Device Mapping | ||
| | Device | Hardware | ALSA Device | Mixer Profile | | ||
| |----------|-----------------------------|--------------|------------------------| | ||
| | handset | Internal microphones | plughw:0,0 | handset_capture | |
There was a problem hiding this comment.
Correct the mapping and provide execution logs for both routes. After dynamic card discovery is implemented, document route-specific PCM numbers and describe the card index as runtime-resolved rather than permanently fixed to "0".
| AUDIO_CLIPS_BASE_DIR: "/home/AudioClips" # Path to audio clips directory, default: /home/AudioClips | ||
| LOOPS: 1 # Number of playback loops, default: 1 | ||
| TIMEOUT: "10s" # Playback timeout per loop (e.g., 15s, 0=none), default: 10s | ||
| DMESG_SCAN: 1 # Scan dmesg for errors after playback, default: 1 |
There was a problem hiding this comment.
Wire the values to the runner or remove them. For flag-based arguments:
- "DMESG_SCAN=0" should add "--no-dmesg";
- "VERBOSE=1" should add "--verbose".
Apply the same fix to all four new Hamoa YAML files.
Add Audio_Hamoa: ALSA-based audio playback and recording tests for Hamoa platform
Fixes #454
This PR introduces comprehensive audio testing for Qualcomm Hamoa platforms using
ALSA-based mixer configurations. The implementation provides automated validation
of audio playback and recording capabilities across multiple devices.
New Test Suites
AudioPlayback_Hamoa
Tests audio playback on two output devices:
AudioRecord_Hamoa
Tests audio recording on two input devices:
Key Features
Documentation
Comprehensive README files included for both test suites: