Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions alsa_settings/NVL_RVP_SDW.state
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ state.sofsoundwire {
control.1 {
iface MIXER
name 'rt722 FU05 Playback Volume'
value.0 87
value.1 87
value.0 72
value.1 72
}
control.2 {
iface MIXER
Expand All @@ -14,8 +14,8 @@ state.sofsoundwire {
control.3 {
iface MIXER
name 'rt722 FU0F Capture Volume'
value.0 46
value.1 46
value.0 58
value.1 58
}
control.4 {
iface MIXER
Expand All @@ -26,8 +26,8 @@ state.sofsoundwire {
control.5 {
iface MIXER
name 'rt722 FU06 Playback Volume'
value.0 60
value.1 60
value.0 72
value.1 72
}
control.6 {
iface MIXER
Expand All @@ -40,10 +40,10 @@ state.sofsoundwire {
control.7 {
iface MIXER
name 'rt722 FU1E Capture Volume'
value.0 63
value.1 63
value.2 63
value.3 63
value.0 50
value.1 50
value.2 50
value.3 50
}
control.8 {
iface MIXER
Expand Down
28 changes: 14 additions & 14 deletions alsa_settings/NVL_SDW_RT712.state
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ state.sofsoundwire {
control.1 {
iface MIXER
name 'rt1320-1 FU21 Playback Volume'
value.0 87
value.1 87
value.0 72
value.1 72
}
control.2 {
iface MIXER
Expand Down Expand Up @@ -99,14 +99,14 @@ state.sofsoundwire {
control.13 {
iface MIXER
name 'rt712 FU0F Capture Volume'
value.0 46
value.1 46
value.0 40
value.1 40
}
control.14 {
iface MIXER
name 'rt712 FU44 Boost Volume'
value.0 2
value.1 2
value.0 0
value.1 0
}
control.15 {
iface MIXER
Expand All @@ -133,10 +133,10 @@ state.sofsoundwire {
control.18 {
iface MIXER
name 'rt712 FU15 Boost Volume'
value.0 2
value.1 2
value.2 2
value.3 2
value.0 0
value.1 0
value.2 0
value.3 0
}
control.19 {
iface MIXER
Expand Down Expand Up @@ -191,14 +191,14 @@ state.sofsoundwire {
control.29 {
iface MIXER
name 'Pre Mixer Speaker Playback Volume'
value.0 45
value.1 45
value.0 33
value.1 33
}
control.30 {
iface MIXER
name 'Post Mixer Speaker Playback Volume'
value.0 45
value.1 45
value.0 33
value.1 33
}
control.34 {
iface MIXER
Expand Down
28 changes: 28 additions & 0 deletions case-lib/hijack.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,34 @@ function func_exit_handler()

dlogi "Starting func_exit_handler($exit_status)"

# Cleanup audio processes (aplay/arecord/tinyplay/tinycap) that may be left running
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Déjà vu...I feel like there are a couple instances of such cleanup functions around already? Sorry if not.

# This prevents "Device or resource busy" errors in subsequent tests
case "$SOF_ALSA_TOOL" in
'alsa')
if pgrep aplay >/dev/null 2>&1 || pgrep arecord >/dev/null 2>&1; then
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
if pgrep aplay >/dev/null 2>&1 || pgrep arecord >/dev/null 2>&1; then
if pgrep aplay >/dev/null || pgrep arecord >/dev/null ; then

dlogi "Cleaning up leftover aplay/arecord processes"
pkill -9 aplay 2>/dev/null || true
pkill -9 arecord 2>/dev/null || true
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
pkill -9 arecord 2>/dev/null || true
pkill -9 arecord || true

sleep 0.5
fi
;;
'tinyalsa')
if pgrep tinyplay >/dev/null 2>&1 || pgrep tinycap >/dev/null 2>&1; then
dlogi "Cleaning up leftover tinyplay/tinycap processes"
pkill -9 tinyplay 2>/dev/null || true
pkill -9 tinycap 2>/dev/null || true
sleep 0.5
fi
;;
*)
# Unknown or unset - cleanup both
pkill -9 aplay 2>/dev/null || true
pkill -9 arecord 2>/dev/null || true
pkill -9 tinyplay 2>/dev/null || true
pkill -9 tinycap 2>/dev/null || true
;;
esac

finish_kmsg_collection

func_lib_check_and_disable_pipewire
Expand Down
10 changes: 4 additions & 6 deletions case-lib/lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -990,10 +990,7 @@ kill_process()
local pid="$1"
local sleep_secs="${2:-1}"

[[ -n "$pid" ]] || {
die "kill_process: missing pid"
return 1
}
[[ -n "$pid" ]] || die "kill_process: missing pid"

ps -p "$pid" >/dev/null || return 0

Expand Down Expand Up @@ -1310,7 +1307,8 @@ is_ipc4()
logger_disabled()
{
# Disable logging when available...
if [ "${OPT_VAL['s']}" -eq 0 ]; then
local log_switch="${OPT_VAL['s']:-1}"
if [ "$log_switch" -eq 0 ]; then
return 0
fi

Expand Down Expand Up @@ -1404,7 +1402,7 @@ set_alsa_settings()
# common nocodec_ci alsa settings
"$SCRIPT_HOME"/alsa_settings/CAVS_NOCODEC_CI.sh
;;
TGLU_RVP_NOCODEC_IPC4ZPH | ADLP_RVP_NOCODEC_IPC4ZPH | ADLP_RVP_NOCODEC-ipc4 | TGLU_RVP_NOCODEC-ipc4 | MTLP_RVP_NOCODEC | MTLP_RVP_NOCODEC-multicore-2cores | MTLP_RVP_NOCODEC-multicore-3cores | LNLM_RVP_NOCODEC)
TGLU_RVP_NOCODEC_IPC4ZPH | ADLP_RVP_NOCODEC_IPC4ZPH | ADLP_RVP_NOCODEC-ipc4 | TGLU_RVP_NOCODEC-ipc4 | MTLP_RVP_NOCODEC | MTLP_RVP_NOCODEC-multicore-2cores | MTLP_RVP_NOCODEC-multicore-3cores | LNLM_RVP_NOCODEC | PTLH_RVP_NOCODEC | NVL_RVP_NOCODEC | NVLS_RVP_NOCODEC | WCL_RVP_NOCODEC)
dlogi "Use reset_sof_volume function to set amixer setting."
;;
*)
Expand Down
180 changes: 168 additions & 12 deletions case-lib/pipeline.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,54 @@
#!/bin/bash

# Parse and validate multiple topology files from colon/comma-separated input
# Args: $1: topology path(s) - can be single file or colon/comma-separated list
# Returns: Sets global TPLG_FILES (comma-separated) and TPLG_COUNT
# Example: func_tplg_parse_and_validate "$TPLG"
func_tplg_parse_and_validate()
{
local tplg_input="$1"
tplg_input="${tplg_input//,/:}" # Normalize to colon separator
IFS=':' read -ra tplg_array <<< "$tplg_input"

# Validate and collect accessible topologies
local -a valid_tplg_list=()
for single_tplg in "${tplg_array[@]}"; do
single_tplg="${single_tplg## }"; single_tplg="${single_tplg%% }" # Trim whitespace
[[ -z "$single_tplg" ]] && continue

# Filter out topology files based on system config (NO_HDMI_MODE, NO_BT_MODE, NO_DMIC_MODE)
local tplg_basename; tplg_basename=$(basename "$single_tplg")
local tplg_lower="${tplg_basename,,}" # Convert to lowercase

if [ -n "$NO_HDMI_MODE" ] && [[ "$tplg_lower" == *"hdmi"* ]]; then
dlogw "Skipping HDMI topology (NO_HDMI_MODE=true): $single_tplg"
continue
fi
if [ -n "$NO_BT_MODE" ] && [[ "$tplg_lower" == *"bt"* || "$tplg_lower" == *"bluetooth"* ]]; then
dlogw "Skipping Bluetooth topology (NO_BT_MODE=true): $single_tplg"
continue
fi
if [ -n "$NO_DMIC_MODE" ] && [[ "$tplg_lower" == *"dmic"* ]]; then
dlogw "Skipping DMIC topology (NO_DMIC_MODE=true): $single_tplg"
continue
fi

local tplg_path
if tplg_path=$(func_lib_get_tplg_path "$single_tplg"); then
valid_tplg_list+=("$tplg_path")
else
dlogw "Topology $single_tplg not found, skipping"
fi
done

[ ${#valid_tplg_list[@]} -eq 0 ] && die "No topology found from: $tplg_input"

# Export as global variables
TPLG_FILES=$(IFS=,; echo "${valid_tplg_list[*]}")
export TPLG_FILES
export TPLG_COUNT=${#valid_tplg_list[@]}
}

# This function will evaluate pipeline parameter related shell code generated by
# - sof-tplgreader.py (for SOF, pipeline parameters dumped from topology)
# - sof-dump-status.py (for legacy HDA, pipeline paramters dumped from proc)
Expand Down Expand Up @@ -32,11 +81,12 @@ func_pipeline_export()
return 0
}

# got tplg_file, verify file exist
tplg_path=$(func_lib_get_tplg_path "$1") || {
die "Topology $1 not found, check the TPLG environment variable or specify topology path with -t"
}
dlogi "$SCRIPT_NAME will use topology $tplg_path to run the test case"
# Support multiple topologies separated by colon (:) or comma (,)
# sof-tplgreader.py natively supports multiple files with comma separator
func_tplg_parse_and_validate "$1"
local tplg_files="$TPLG_FILES"

dlogi "$SCRIPT_NAME will use $TPLG_COUNT topology file(s) to run the test case"

# create block option string
local ignore=""
Expand All @@ -60,16 +110,119 @@ func_pipeline_export()
[[ "$ignore" ]] && opt="$opt -b '$ignore'"
[[ "$SOFCARD" ]] && opt="$opt -s $SOFCARD"

# sof-tplgreader.py handles multiple files natively with comma separator
local -a pipeline_lst
local cmd="sof-tplgreader.py $tplg_path $opt -e" line=""
dlogi "Run command to get pipeline parameters"
local cmd="sof-tplgreader.py $tplg_files $opt -e" line=""
dlogi "Run command to get pipeline parameters from all topologies"
dlogc "$cmd"
readarray -t pipeline_lst < <(eval "$cmd")
for line in "${pipeline_lst[@]}"
do

# Capture output and check for errors
local output exit_code
output=$(eval "$cmd" 2>&1)
exit_code=$?

if [ $exit_code -ne 0 ]; then
dloge "sof-tplgreader.py failed with exit code $exit_code"
dloge "Command: $cmd"
dloge "Output: $output"
echo "ERROR: sof-tplgreader.py failed (exit $exit_code)" >&2
echo "Command: $cmd" >&2
echo "Output: $output" >&2
die "Failed to parse topologies"
fi

# Read output into array
readarray -t pipeline_lst <<< "$output"

# Check if we got any output
if [ ${#pipeline_lst[@]} -eq 0 ] || [ -z "${pipeline_lst[0]}" ]; then
dloge "sof-tplgreader.py returned no output"
dloge "Topologies: ${valid_tplg_list[*]}"
echo "ERROR: No output from sof-tplgreader.py" >&2
echo "Command: $cmd" >&2
die "No pipeline data from topologies"
fi

# Evaluate all collected pipeline parameters first
for line in "${pipeline_lst[@]}"; do
eval "$line"
done
[[ ! "$PIPELINE_COUNT" ]] && die "Failed to parse $tplg_path, please check topology parsing command"

# Deduplicate pipelines by 'dev' field (hw:X,Y)
# Same PCM device can be defined in multiple topology files
# Always deduplicate to ensure no duplicate testing (harmless with single topology)
if [ "${PIPELINE_COUNT:-0}" -gt 0 ]; then
local orig_count=$PIPELINE_COUNT
local -A seen_devs
local new_idx=0

# Iterate through all pipelines and keep only first occurrence of each unique 'dev'
for idx in $(seq 0 $((PIPELINE_COUNT - 1))); do
local dev_val; dev_val=$(func_pipeline_parse_value "$idx" "dev")

# Skip if we've seen this dev before
if [[ -n "${seen_devs[$dev_val]}" ]]; then
continue
fi
seen_devs["$dev_val"]=1

# If this is a new unique dev, copy pipeline to new index if needed
if [ $new_idx -ne "$idx" ]; then
# Copy all fields from old index to new index
for key in pcm id dev type fmt fmts rate rates channel channels snd; do
local val; val=$(func_pipeline_parse_value "$idx" "$key")
if [[ -n "$val" ]]; then
eval "PIPELINE_${new_idx}[$key]=\"$val\""
fi
done
fi
new_idx=$((new_idx + 1))
done

# Update pipeline count
PIPELINE_COUNT=$new_idx
if [ "$orig_count" -ne "$PIPELINE_COUNT" ]; then
dlogi "Deduplicated $orig_count pipelines to $PIPELINE_COUNT unique devices"
fi

# Sort pipelines by id to ensure consistent ordering (matches sof-dump-status.py output)
if [ "$PIPELINE_COUNT" -gt 0 ]; then
# Collect all pipelines with their id
local -a sorted_indices=()
for idx in $(seq 0 $((PIPELINE_COUNT - 1))); do
local id_val; id_val=$(func_pipeline_parse_value "$idx" "id")
sorted_indices+=("$id_val:$idx")
done

# Sort by id (numeric)
mapfile -t sorted_indices < <(sort -t: -k1 -n <<<"${sorted_indices[*]}")

# Create temporary copy of all pipelines
local -A temp_pipelines
for idx in $(seq 0 $((PIPELINE_COUNT - 1))); do
for key in pcm id dev type fmt fmts rate rates channel channels snd; do
local val; val=$(func_pipeline_parse_value "$idx" "$key")
[[ -n "$val" ]] && temp_pipelines["${idx}_${key}"]="$val"
done
done

# Reorder pipelines based on sorted id
local new_idx=0
for entry in "${sorted_indices[@]}"; do
local old_idx="${entry#*:}"
for key in pcm id dev type fmt fmts rate rates channel channels snd; do
local val="${temp_pipelines[${old_idx}_${key}]}"
if [[ -n "$val" ]]; then
eval "PIPELINE_${new_idx}[$key]=\"$val\""
fi
done
new_idx=$((new_idx + 1))
done
dlogi "Sorted $PIPELINE_COUNT pipelines by id"
fi
fi

[[ ! "$PIPELINE_COUNT" ]] && die "Failed to parse topologies, please check topology parsing command"
[[ $PIPELINE_COUNT -eq 0 ]] && dlogw "No pipeline found with option: $opt, unable to run $SCRIPT_NAME" && exit 2
return 0
}
Expand All @@ -78,7 +231,10 @@ func_pipeline_parse_value()
{
local idx=$1
local key=$2
[[ $idx -ge $PIPELINE_COUNT ]] && echo "" && return
if [[ $idx -ge $PIPELINE_COUNT ]]; then
echo ""
return 0
fi
local array_key='PIPELINE_'"$idx"'['"$key"']'
eval echo "\${$array_key}" # dynmaic echo the target value of the PIPELINE
}
Loading
Loading