Skip to content

Add Audio_Hamoa: ALSA-based audio playback and recording tests for Ha… - #477

Closed
Teja Swaroop (tmoida) wants to merge 3 commits into
qualcomm-linux:mainfrom
tmoida:feature/audio-hamoa
Closed

Teja Swaroop (tmoida) wants to merge 3 commits into
qualcomm-linux:mainfrom
tmoida:feature/audio-hamoa

Conversation

@tmoida

Copy link
Copy Markdown
Contributor

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:

  • Handset (plughw:0,1): 4-way speaker system using WSA2/WSA amplifiers
    • Audio path: AIF1_PB → WSA2/WSA RX0/RX1 → WooferLeft/Right + TweeterLeft/Right
    • 44 mixer controls configured
    • Dual WSA codec support with compressor and boost
  • Headset (plughw:0,0): Stereo headphones using RX codec
    • Audio path: AIF1_PB → RX_MACRO RX0/RX1 → RX INT0/INT1 → HPHL/HPHR
    • 22 mixer controls configured
    • Class-H High Fidelity mode for optimal audio quality

AudioRecord_Hamoa

Tests audio recording on two input devices:

  • Handset (plughw:0,3): Built-in VA_DMIC (Voice Activation DMIC)
    • Audio path: DMIC0/DMIC1 → VA DMIC MUX0/MUX1 → VA DEC0/DEC1 → VA_AIF1_CAP
    • 8 mixer controls configured
    • Dual DMIC support with volume control
  • Headset (plughw:0,2): SoundWire microphone (SWR_MIC)
    • Audio path: SWR_MIC → ADC2 → TX SMIC MUX0 (SWR_MIC0) → TX DEC0 → TX_AIF1_CAP
    • 10 mixer controls configured

Key Features

  • Dual device support: Test handset, headset, or both devices
  • Mixer validation: Verifies all mixer settings before audio operations
  • Clip/config-based testing: Auto-discovery of audio clips and configurations
  • Skip mode: Test mixer configuration without actual audio playback/recording
  • CI/LAVA integration:
    • Unique result file suffixes prevent file collisions in parallel runs
    • Unique testcase IDs prevent LAVA testcase ID collisions
    • Enables running multiple configurations simultaneously
  • Comprehensive logging: Mixer dumps, playback/recording logs per test case
  • Recording validation: File size and format verification

Documentation

Comprehensive README files included for both test suites:

  • Complete usage examples (basic, mixer-only, verbose, CI/LAVA)
  • Command line options and environment variables tables
  • Audio clip/config configuration tables
  • Test execution flow diagrams
  • Sample output examples
  • Known limitations and workarounds
  • CI/LAVA integration guidelines

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@tmoida
Teja Swaroop (tmoida) force-pushed the feature/audio-hamoa branch 2 times, most recently from 1343228 to e4fd164 Compare June 17, 2026 12:10
@tmoida

Copy link
Copy Markdown
Contributor Author

Srikanth Muppandam (@smuppand) Thank you for the feedback. I've implemented the recommended approach:

Implementation Summary

Integrated Hamoa into existing AudioPlayback/AudioRecord tests - no separate test suite created.

Architecture Changes

  1. ALSA Profile Layer (Runner/utils/audio/alsa_common.sh):

    • Reusable Hamoa mixer configuration functions
    • 4 profiles: handset/headset × playback/capture
    • Mixer controls: 44 (handset playback), 22 (headset playback), 10 (capture)
  2. Extended Existing Tests:

    ./run.sh --backend alsa --alsa-profile hamoa --device handset|headset
    
  3. File Organization:

    • YAML files moved to main test directories (not separate suite)
    • AudioPlayback/AudioPlayback_Hamoa_{Handset,Headset}.yaml
    • AudioRecord/AudioRecord_Hamoa_{Handset,Headset}.yaml

Please review it and let me know your feedback.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This remains unresolved at e486595. The readiness block at AudioRecord/run.sh:648-717 still calls audio_record_probe_alsa_capture_profile before reaching setup_alsa_profile_route at line 819. Generic preparation configures Mic/VA-DMIC, not the explicitly requested headset TX route. If that route needs the Hamoa configuration before it can open, the generic probe fails and the runner exits before applying the configuration that would make capture work. An exact-code host fixture confirms this early exit. Please validate the selected profile/device and apply its route before probing that exact capture PCM, leaving generic discovery for --alsa-profile generic.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread Runner/utils/audio/audio_common.sh Outdated

# 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread Runner/utils/audio/alsa_common.sh Outdated
return 1
fi

if aplay -l 2>/dev/null | grep -q "card 0"; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread Runner/utils/audio/alsa_common.sh Outdated

validate_audio_file "$file" || return 1

size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null || echo 0)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread Runner/utils/audio/alsa_common.sh Outdated

# Hamoa profile wrapper for handset playback
# Args: $1 - optional log directory path
setup_alsa_profile_hamoa_playback_handset() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread Runner/utils/audio/alsa_common.sh Outdated

# Get ALSA device for Hamoa handset playback
get_alsa_device_hamoa_playback_handset() {
echo "plughw:0,1"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@tmoida
Teja Swaroop (tmoida) force-pushed the feature/audio-hamoa branch 2 times, most recently from a704af8 to f3074f4 Compare July 14, 2026 09:53
@tmoida

Copy link
Copy Markdown
Contributor Author

Srikanth Muppandam (@smuppand) Thank you for the detailed review. All comments have been addressed in the latest push.

Changes Made

Commit 1: audio: move common helpers under utils/audio

  • Replaced the BASH_SOURCE/dirname block with . "$TOOLS/audio/alsa_common.sh" directly — POSIX-safe and consistent with how other helpers are sourced in the repo

Commit 2: audio: add Hamoa ALSA profile helpers

  • check_alsa_device(): Now parses the exact card/device numbers from the identifier and uses arecord -l for capture, aplay -l for playback — no longer just checks "card 0 exists"
  • validate_recording(): Replaced direct stat logic with file_size_bytes helper for consistent size handling
  • Profile wrappers: Now call check_alsa_device and validate_mixer_state after mixer setup before returning success
  • Device getters: Delegate to get_alsa_device() instead of hard-coding device strings — single source of truth

Commit 3: audio: add Hamoa playback and capture LAVA tests

  • AudioPlayback/run.sh: Removed duplicate alsa_common.sh sourcing (audio_common.sh already sources it)
  • AudioRecord/run.sh: Added backend coercion before detection — if ALSA_PROFILE is non-generic and AUDIO_BACKEND is unset, sets AUDIO_BACKEND=alsa (mirrors AudioPlayback logic)
  • AudioRecord/run.sh: Made backend_ok check profile-aware — skips generic audio_probe_alsa_capture_profile when a hardware profile is active
  • AudioRecord/run.sh: Restored pw_set_default_source helper (removed direct wpctl set-default call)
  • AudioRecord/run.sh: Moved bytes= assignment to immediately after rc=$?, before the if [ "$rc" -ne 0 ] block — prevents false failures when arecord succeeds with rc=0

Please review and let me know your feedback.

Comment thread Runner/utils/audio/audio_common.sh Outdated

# Source ALSA-specific helpers (includes Hamoa profile functions)
# shellcheck disable=SC1091
. "$TOOLS/audio/alsa_common.sh"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread Runner/utils/audio/alsa_common.sh Outdated
# 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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. Detect the target from an explicit override, "PLATFORM_TARGET", DT compatible, or DT model.
  2. Select a target-specific audio profile.
  3. Resolve the ALSA card using a stable card ID or card name.
  4. Read the route-specific PCM number from the selected profile.
  5. Construct "plughw:${card_index},${pcm_device}" at runtime.
  6. Reject ambiguous card matches instead of selecting the first card.

Reuse the existing audio card discovery helpers rather than introducing fixed card indices.

Comment thread Runner/utils/audio/alsa_common.sh Outdated
# 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread Runner/utils/audio/alsa_common.sh Outdated
# 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() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"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:

  1. checked for existence before setup;
  2. applied to the resolved card;
  3. read back after setup;
  4. compared against the exact expected value.

Do not maintain a large setup list and a separate two-control validation list.

Comment thread Runner/utils/audio/alsa_common.sh Outdated
# 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() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@github-actions

Copy link
Copy Markdown

@ualcomm/qualcomm-linux-testing.triage This pull request has been marked as stale due to 30 days of inactivity and will automatically close after an additional 5 days.

@smuppand

Copy link
Copy Markdown
Contributor

Teja Swaroop (@tmoida) do you want to resume on this PR by reworking and resolving the merge conflicts?

@tmoida

Copy link
Copy Markdown
Contributor Author

Srikanth Muppandam (@smuppand) Yes, I will resume work on this PR and resolve the merge conflicts with the main branch. I will rebase the Hamoa changes on top of the recent audio runtime updates and push the changes.

@smuppand

Copy link
Copy Markdown
Contributor

Srikanth Muppandam (Srikanth Muppandam (@smuppand)) Yes, I will resume work on this PR and resolve the merge conflicts with the main branch. I will rebase the Hamoa changes on top of the recent audio runtime updates and push the changes.

Please review the existing code, as changes related to audio for distros have been made and merged over the last couple of weeks.

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown

@ualcomm/qualcomm-linux-testing.triage This pull request has been marked as stale due to 30 days of inactivity and will automatically close after an additional 5 days.

@github-actions github-actions Bot added the Stale label Oct 3, 2026
@tmoida

Copy link
Copy Markdown
Contributor Author

I have resumed work on this PR. I am reviewing the recent audio runtime and distro-related changes merged into main, rebasing the Hamoa changes on top of them, and resolving the merge conflicts.
Updated changes will be pushed shortly.

@github-actions github-actions Bot removed the Stale label Oct 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partially addresses #454 until the Ubuntu UCM procedure is implemented and validated.

Fix alsa_pick_capture() and audio_probe_alsa_capture_profile()'s extra_devices fallback: both picked hw: candidates, which record at the hardware's native rate only and do not go through ALSA's plug resampling layer. A requested rate different from the native rate (e.g. an 8000Hz capture config on hardware whose native rate is 48000Hz) then silently records at the native rate instead. Switch both to prefer plughw:, which supports the native rate as well as correct resampling for any other requested rate.

Source Runner/utils/alsa_common.sh when present, idempotently (guarded on resolve_alsa_card_index not already being defined), so the Hamoa ALSA profile helpers added in the next commit are available to every caller of audio_common.sh without each suite needing a separate source line.

Signed-off-by: Teja Swaroop Moida <tmoida@qti.qualcomm.com>
Comment thread Runner/utils/alsa_common.sh Fixed
Comment thread Runner/utils/alsa_common.sh Fixed
Comment thread Runner/utils/alsa_common.sh Fixed
Comment thread Runner/utils/alsa_common.sh Fixed
Comment thread Runner/utils/alsa_common.sh Fixed
Comment thread Runner/utils/alsa_common.sh Fixed
Add Runner/utils/alsa_common.sh, providing 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 11 mixer controls. Audio path: SWR_MIC -> ADC2 -> TX SMIC MUX0 -> TX DEC0 -> TX_AIF1_CAP

setup_alsa_profile_route() validates PCM device availability and mixer state after configuration before returning success.

- Resolve card index dynamically via resolve_alsa_card_index(), by matching a profile's distinctive mixer control across every registered card, instead of assuming a fixed card index (registration order is not guaranteed); reject ambiguous matches rather than guessing.

- Move mixer controls into declarative profile files under Runner/utils/audio_profiles/ (hamoa_{playback,capture}_{handset,headset}.profile), applied via a single setup_audio_route() executor rather than hard-coded per-device amixer sequences.

- check_mixer_control() now parses only the active ENUM Item0 or the exact values= field, instead of substring-matching the full amixer cget output (which could false-match, e.g. '1' inside '10').

- validate_mixer_state() checks every control declared in the profile after setup, using the same profile as the single source of truth for both setup and validation.

- setup_audio_route() is transactional: a per-card flock serializes concurrent writers, each control's prior value is snapshotted before being changed, and a partial failure rolls back every control already applied in that call.

- setup_alsa_profile_route() tries an alsaucm-based route (issue qualcomm-linux#454) first when a UCM configuration tree is installed and usable for the resolved card (resolve_alsa_ucm_card_name(), _alsa_ucm_available()), falling back to the amixer-profile mechanism above otherwise.

- Read control-list lines via a heredoc-fed 'while IFS= read -r' loop in rollback_audio_route(), setup_audio_route(), and validate_mixer_state(), rather than splitting on a temporarily-global IFS newline via 'set --'; this scopes the IFS override to a single read invocation instead of the whole shell.

Signed-off-by: Teja Swaroop Moida <tmoida@qti.qualcomm.com>
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

- Wire DMESG_SCAN=0 to --no-dmesg and VERBOSE=1 to --verbose in all four Hamoa YAML files, so the declared params actually reach the runner

- SKIP immediately (instead of warn-and-continue) when a hardware ALSA profile is set with a non-ALSA backend, in both AudioPlayback and AudioRecord

- Validate ALSA_PROFILE/DEVICE against an explicit allowlist and confirm card resolution before marking the backend ready, so an unsupported combination or missing card SKIPs early instead of failing deep inside profile setup (mirrored for AudioRecord as well)

- Replace dynamic function-name construction for profile/device dispatch with an explicit case/esac allowlist, so an unexpected value can never resolve to an arbitrary function name; gate on amixer/grep/sed/flock availability before dispatch

- Restore concrete PipeWire source requirement in AudioRecord: no longer silently records from PipeWire's ambient default source when no real hardware mic is found

- Fix elapsed-time validation for a --timeout shorter than the clip duration, so a clean, intentional early timeout is correctly accepted instead of judged against the full clip length

- aplay now passes its own -d duration limit (sourced from the same effective_timeout the watchdog uses) so it can finish and close the PCM device on its own schedule, instead of always being killed externally once the watchdog elapses

- Refresh both Read_me.md files with real, current sample output, corrected device mappings, and the UCM-first-then-amixer-fallback route selection documentation

Signed-off-by: Teja Swaroop Moida <tmoida@qti.qualcomm.com>
@tmoida

Copy link
Copy Markdown
Contributor Author

Hi Srikanth Muppandam (@smuppand), thanks again for the detailed feedback on this one. I reworked the implementation to address all the points you raised:

  • Replaced the dynamic function-name dispatch with an explicit case allowlist for profile/device combos, so there's no eval-style construction anymore.
  • Card index is no longer hardcoded to 0 — resolve_alsa_card_index() resolves it at runtime by matching a distinctive mixer control, and bails out if the match is ambiguous.
  • validate_mixer_state() now checks every control from the profile file (not just a couple of them), using the same profile as setup for consistency.
  • Mixer setup is transactional now — it locks per card, snapshots values before writing, and rolls back if anything fails partway through.
  • Fixed the bytes assignment bug in AudioRecord where a successful recording could get reported as 0 bytes, and restored the concrete PipeWire source requirement instead of falling back to an ambient default.
  • The Hamoa YAML files now actually wire DMESG_SCAN/VERBOSE to --no-dmesg/--verbose.

Please review and let me know your feedback.

aua_card_name="$(resolve_alsa_ucm_card_name "$aua_profile" 2>/dev/null)" || return 1
[ -n "$aua_card_name" ] || return 1

[ -d "/usr/share/alsa/ucm2/$aua_card_name" ] || return 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please detect UCM availability through a bounded alsaucm query for the resolved ALSA card rather than requiring this directory. The upstream configuration referenced by #454 lives at ucm2/conf.d/x1e80100/X1E80100-EVK.conf and includes /Qualcomm/x1e80100/HiFi.conf, so a working installation need not contain /usr/share/alsa/ucm2/X1E80100-EVK/. This check rejects that installation before attempting UCM and silently selects the raw mixer fallback. Also, field 3 from audio_card_get_registered_cards is a description, not a guaranteed UCM identifier. Resolve the card through ALSA/UCM and retain the capability-query failure separately from an absent configuration.

Public configuration: https://github.com/alsa-project/alsa-ucm-conf/blob/master/ucm2/conf.d/x1e80100/X1E80100-EVK.conf

# verification: requesting 84/12 is silently capped by the codec to 81/6.

PROFILE_NAME="hamoa_playback_handset"
PROFILE_MIXER_CONTROLS="

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback profile configures the codec/amplifier controls but does not connect the playback PCM to its codec backend. On a clean-boot X1E80100 EVK with the route switches off, speaker PCM 1 also needs WSA_CODEC_DMA_RX_0 Audio Mixer MultiMedia2 enabled. The public HiFi verb similarly enables RX_CODEC_DMA_RX_0 Audio Mixer MultiMedia1, MultiMedia3 Mixer TX_CODEC_DMA_TX_3, and MultiMedia4 Mixer VA_CODEC_DMA_TX_0 for the other three routes, but none is included in these profiles. Because the hardware-profile playback branch bypasses generic ALSA preparation, the declared mixer controls and PCM enumeration can validate while the actual path remains disconnected. Please include and validate the applicable PCM-to-codec route switches using runtime topology, or require successful equivalent UCM verb setup. Verify this from a clean boot without prior manual UCM preparation.

Reference: https://github.com/alsa-project/alsa-ucm-conf/blob/master/ucm2/Qualcomm/x1e80100/HiFi.conf

if [ "$ALSA_CAPTURE_PROBED" -eq 1 ] && [ -n "$AUDIO_ALSA_CAPTURE_DEVICE" ]; then
SRC_ID="$AUDIO_ALSA_CAPTURE_DEVICE"
# Hardware-specific ALSA profiles (e.g., Hamoa) configure mixer controls
# and provide an explicit device path for the requested device, instead

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please validate the profile/device combination before this branch, as playback already does. With --alsa-profile hamoa but no --device, this condition is false and the runner silently uses the generic probed microphone. A host fixture with AUDIO_ALSA_CAPTURE_DEVICE=plughw:7,0 confirms that this unrelated source is selected while ALSA_PROFILE=hamoa. A successful generic recording can therefore produce PASS without exercising the requested Hamoa profile. Reject the missing required device with an actionable selection error before probing or changing mixer state.

@tmoida

Copy link
Copy Markdown
Contributor Author

Closing this PR — main already covers Hamoa audio via its generic UCM route resolver when a UCM tree is installed.
Will follow up with a smaller PR for the remaining UCM gap. Thanks for the review!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Audio test procedures changed for Hamoa ubuntu

3 participants