diff --git a/tools/test/topology/test-playback.m4 b/tools/test/topology/test-playback.m4 index 3f762e83e41d..1a73e9e3b186 100644 --- a/tools/test/topology/test-playback.m4 +++ b/tools/test/topology/test-playback.m4 @@ -19,6 +19,9 @@ include(`platform/intel/bxt.m4') DEBUG_START +dnl Produce uppercase for input string +define(`upcase', `translit(`$*', `a-z', `A-Z')') + # # Machine Specific Config - !! MUST BE SET TO MATCH TEST MACHINE DRIVER !! # @@ -32,6 +35,7 @@ DEBUG_START # TEST_SSP_PHY_BITS - SSP physical slot size # TEST_SSP_DATA_BITS - SSP data slot size # TEST_SSP_MODE - SSP mode e.g. I2S, LEFT_J, DSP_A and DSP_B +# TEST_PIPE_AMOUNT - Total amount of pipelines e.g. 1, 2, 3, 4 # # Apply a non-trivial filter blob IIR and FIR tests. TODO: Note that the @@ -39,10 +43,42 @@ DEBUG_START define(PIPELINE_FILTER1, ifelse(TEST_PIPE_NAME, `eq-iir', `eq_iir_coef_loudness.m4')) define(PIPELINE_FILTER2, ifelse(TEST_PIPE_NAME, `eq-fir', `eq_fir_coef_loudness.m4')) +# Define TEST_HAS_PIPEn flags according to TEST_PIPE_AMOUNT. Those flags will be +# used to determine whether PIPELINE_n should be added. +ifelse(TEST_PIPE_AMOUNT, `2', +` +define(TEST_HAS_PIPE2) +') + +ifelse(TEST_PIPE_AMOUNT, `3', +` +define(TEST_HAS_PIPE2) +define(TEST_HAS_PIPE3) +') + +ifelse(TEST_PIPE_AMOUNT, `4', +` +define(TEST_HAS_PIPE2) +define(TEST_HAS_PIPE3) +define(TEST_HAS_PIPE4) +') + # -# Define the pipeline +# Define the pipeline(s) # -# PCM0P --> TEST_PIPE_NAME --> SSP(TEST_DAI_PORT) +# PCM0P --> BUF1.0 --> TEST_PIPE_NAME --> BUF1.1 --> SSP(TEST_DAI_PORT) +ifdef(`TEST_HAS_PIPE2', +` +# +---> BUF2.0 --> SSP(0 or 1) +') +ifdef(`TEST_HAS_PIPE3', +` +# +---> BUF3.0 --> SSP(2 or 3) +') +ifdef(`TEST_HAS_PIPE4', +` +# +---> BUF4.0 --> SSP(4 or 5) +') # # Playback pipeline 1 on PCM 0 using max 2 channels of s32le. @@ -52,10 +88,71 @@ PIPELINE_PCM_ADD(sof/pipe-TEST_PIPE_NAME-playback.m4, 1000, 0, 0, 8000, 192000, 48000) +# Generalize the pipeline junction name as PIPELINE_JUNCTION. +# e.g. TEST_PIPE_NAME=`crossover' --> PIPELINE_JUNCTION=`PIPELINE_CROSSOVER_1' +define(PIPELINE_JUNCTION, concat(concat(`PIPELINE_', upcase(TEST_PIPE_NAME)), `_1')) + +ifdef(`TEST_HAS_PIPE2', +` +# Playback pipeline 2 on PCM 1 using max 2 channels of s32le. +# Set 1000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-dai-endpoint.m4, + 2, 1, 2, s32le, + 1000, 0, 0, + 8000, 192000, 48000) + +# connect pipelines together +SectionGraph."pipe-sof-second-pipe" { + index "2" + + lines [ + # connect the second sink buffer + dapm(PIPELINE_SOURCE_2, PIPELINE_JUNCTION) + ] +} +') + +ifdef(`TEST_HAS_PIPE3', +` +# Playback pipeline 3 on PCM 2 using max 2 channels of s32le. +# Set 1000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-dai-endpoint.m4, + 3, 2, 2, s32le, + 1000, 0, 0, + 8000, 192000, 48000) + +# connect pipelines together +SectionGraph."pipe-sof-third-pipe" { + index "3" + + lines [ + # connect the third sink buffer + dapm(PIPELINE_SOURCE_3, PIPELINE_JUNCTION) + ] +} +') + +ifdef(`TEST_HAS_PIPE4', +` +# Playback pipeline 4 on PCM 3 using max 2 channels of s32le. +# Set 1000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-dai-endpoint.m4, + 4, 3, 2, s32le, + 1000, 0, 0, + 8000, 192000, 48000) + +# connect pipelines together +SectionGraph."pipe-sof-fourth-pipe" { + index "4" + + lines [ + # connect the fourth sink buffer + dapm(PIPELINE_SOURCE_4, PIPELINE_JUNCTION) + ] +} +') + # DAI configuration -# -# SSP port TEST_DAI_PORT is our only pipeline DAI -# # playback DAI is SSP TEST_DAI_PORT using 2 periods # Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 @@ -64,6 +161,48 @@ DAI_ADD(sof/pipe-dai-playback.m4, PIPELINE_SOURCE_1, 2, TEST_DAI_FORMAT, 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) +ifdef(`TEST_HAS_PIPE2', +` +define(TEST_DAI2_PORT, ifelse(TEST_DAI_PORT, `0', `1', `0')) +define(TEST_DAI2_LINK_NAME, ifelse(TEST_DAI_PORT, `0', `SSP1-Codec', `SSP0-Codec')) + +# playback DAI is SSP TEST_DAI2_PORT using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD_SCHED(sof/pipe-dai-sched-playback.m4, + 2, TEST_DAI_TYPE, TEST_DAI2_PORT, TEST_DAI2_LINK_NAME, + PIPELINE_SOURCE_2, 2, TEST_DAI_FORMAT, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER, + PIPELINE_PLAYBACK_SCHED_COMP_1) +') + +ifdef(`TEST_HAS_PIPE3', +` +define(TEST_DAI3_PORT, ifelse(TEST_DAI_PORT, `2', `3', `2')) +define(TEST_DAI3_LINK_NAME, ifelse(TEST_DAI_PORT, `2', `SSP3-Codec', `SSP2-Codec')) + +# playback DAI is SSP TEST_DAI3_PORT using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD_SCHED(sof/pipe-dai-sched-playback.m4, + 3, TEST_DAI_TYPE, TEST_DAI3_PORT, TEST_DAI3_LINK_NAME, + PIPELINE_SOURCE_3, 2, TEST_DAI_FORMAT, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER, + PIPELINE_PLAYBACK_SCHED_COMP_1) +') + +ifdef(`TEST_HAS_PIPE4', +` +define(TEST_DAI4_PORT, ifelse(TEST_DAI_PORT, `4', `5', `4')) +define(TEST_DAI4_LINK_NAME, ifelse(TEST_DAI_PORT, `4', `SSP5-Codec', `SSP4-Codec')) + +# playback DAI is SSP TEST_DAI4_PORT using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD_SCHED(sof/pipe-dai-sched-playback.m4, + 4, TEST_DAI_TYPE, TEST_DAI4_PORT, TEST_DAI4_LINK_NAME, + PIPELINE_SOURCE_4, 2, TEST_DAI_FORMAT, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER, + PIPELINE_PLAYBACK_SCHED_COMP_1) +') + # PCM Passthrough PCM_PLAYBACK_ADD(Passthrough, 0, PIPELINE_PCM_1) @@ -73,7 +212,7 @@ PCM_PLAYBACK_ADD(Passthrough, 0, PIPELINE_PCM_1) # Clocks masters wrt codec # # TEST_SSP_DATA_BITS bit I2S -# using TEST_SSP_PHY_BITS bit sample container on SSP TEST_DAI_PORT +# using TEST_SSP_PHY_BITS bit sample container on SSP port(s) # DAI_CONFIG(TEST_DAI_TYPE, TEST_DAI_PORT, 0, TEST_DAI_LINK_NAME, SSP_CONFIG(TEST_SSP_MODE, @@ -84,5 +223,40 @@ DAI_CONFIG(TEST_DAI_TYPE, TEST_DAI_PORT, 0, TEST_DAI_LINK_NAME, SSP_CONFIG_DATA(TEST_DAI_TYPE, TEST_DAI_PORT, TEST_SSP_DATA_BITS, TEST_SSP_MCLK_ID))) +ifdef(`TEST_HAS_PIPE2', +` +DAI_CONFIG(TEST_DAI_TYPE, TEST_DAI2_PORT, 1, TEST_DAI2_LINK_NAME, + SSP_CONFIG(TEST_SSP_MODE, + SSP_CLOCK(mclk, TEST_SSP_MCLK, codec_mclk_in), + SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_slave), + SSP_CLOCK(fsync, 48000, codec_slave), + SSP_TDM(2, TEST_SSP_PHY_BITS, 3, 3), + SSP_CONFIG_DATA(TEST_DAI_TYPE, TEST_DAI2_PORT, + TEST_SSP_DATA_BITS, TEST_SSP_MCLK_ID))) +') + +ifdef(`TEST_HAS_PIPE3', +` +DAI_CONFIG(TEST_DAI_TYPE, TEST_DAI3_PORT, 2, TEST_DAI3_LINK_NAME, + SSP_CONFIG(TEST_SSP_MODE, + SSP_CLOCK(mclk, TEST_SSP_MCLK, codec_mclk_in), + SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_slave), + SSP_CLOCK(fsync, 48000, codec_slave), + SSP_TDM(2, TEST_SSP_PHY_BITS, 3, 3), + SSP_CONFIG_DATA(TEST_DAI_TYPE, TEST_DAI3_PORT, + TEST_SSP_DATA_BITS, TEST_SSP_MCLK_ID))) +') + +ifdef(`TEST_HAS_PIPE4', +` +DAI_CONFIG(TEST_DAI_TYPE, TEST_DAI4_PORT, 3, TEST_DAI4_LINK_NAME, + SSP_CONFIG(TEST_SSP_MODE, + SSP_CLOCK(mclk, TEST_SSP_MCLK, codec_mclk_in), + SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_slave), + SSP_CLOCK(fsync, 48000, codec_slave), + SSP_TDM(2, TEST_SSP_PHY_BITS, 3, 3), + SSP_CONFIG_DATA(TEST_DAI_TYPE, TEST_DAI4_PORT, + TEST_SSP_DATA_BITS, TEST_SSP_MCLK_ID))) +') DEBUG_END diff --git a/tools/test/topology/tplg-build.sh b/tools/test/topology/tplg-build.sh index cc8a29e28f14..392f1b37019c 100755 --- a/tools/test/topology/tplg-build.sh +++ b/tools/test/topology/tplg-build.sh @@ -34,21 +34,22 @@ M4_STRINGS="" # 3) be_name - BE DAI link name in machine driver, used for matching # 4) format - PCM sample format # 5) dai_type - dai type e.g. SSP/DMIC -# 5) dai_id - SSP port number -# 6) dai_format - SSP sample format -# 7) dai_phy_bits - SSP physical number of BLKCs per slot/channel -# 8) dai_data_bits - SSP number of valid data bits per slot/channel -# 9) dai_bclk - SSP BCLK in HZ -# 10) dai_mclk - SSP MCLK in HZ -# 11) SSP mode - SSP mode e.g. I2S, LEFT_J, DSP_A and DSP_B -# 12) SSP mclk_id -# 13) Test pipelines +# 6) dai_id - SSP port number +# 7) dai_format - SSP sample format +# 8) dai_phy_bits - SSP physical number of BLKCs per slot/channel +# 9) dai_data_bits - SSP number of valid data bits per slot/channel +# 10) dai_bclk - SSP BCLK in HZ +# 11) dai_mclk - SSP MCLK in HZ +# 12) SSP mode - SSP mode e.g. I2S, LEFT_J, DSP_A and DSP_B +# 13) SSP mclk_id +# 14) total number of pipelines - range from 1 to 4 +# 15) Test pipelines # function simple_test { if [ $5 == "SSP" ] then - TESTS=("${!14}") + TESTS=("${!15}") elif [ $5 == "DMIC" ] then TESTS=("${!15}") @@ -87,7 +88,12 @@ function simple_test { then TFILE="test-ssp$6-mclk-${13}-${12}-$2-$4-$7-48k-$((${11} / 1000))k-$1" else - TFILE="$i-ssp$6-mclk-${13}-${12}-$2-$4-$7-48k-$((${11} / 1000))k-$1" + if [ ${14} == "1" ] + then + TFILE="$i-ssp$6-mclk-${13}-${12}-$2-$4-$7-48k-$((${11} / 1000))k-$1" + else + TFILE="$i-ssp$6-mclk-${13}-${12}-${14}way-$2-$4-$7-48k-$((${11} / 1000))k-$1" + fi fi #create input string for batch m4 processing M4_STRINGS+="-DTEST_PIPE_NAME=$2,-DTEST_DAI_LINK_NAME=$3\ @@ -95,7 +101,8 @@ function simple_test { -DTEST_PIPE_FORMAT=$4,-DTEST_SSP_BCLK=${10}\ -DTEST_SSP_MCLK=${11},-DTEST_SSP_PHY_BITS=$8\ -DTEST_SSP_DATA_BITS=$9,-DTEST_SSP_MODE=${12}\ - -DTEST_SSP_MCLK_ID=${13},-DTEST_DAI_TYPE=$5\ + -DTEST_SSP_MCLK_ID=${13},-DTEST_PIPE_AMOUNT=${14}\ + -DTEST_DAI_TYPE=$5\ $i.m4,$BUILD_OUTPUT/${TFILE}," #create input string for batch processing of conf files TEST_STRINGS+="$BUILD_OUTPUT/${TFILE}," @@ -108,7 +115,12 @@ function simple_test { then TFILE="test-ssp$6-mclk-${13}-${12}-$2-$4-$7-48k-$((${11} / 1000))k-$1" else - TFILE="$i-ssp$6-mclk-${13}-${12}-$2-$4-$7-48k-$((${11} / 1000))k-$1" + if [ ${14} == "1" ] + then + TFILE="$i-ssp$6-mclk-${13}-${12}-$2-$4-$7-48k-$((${11} / 1000))k-$1" + else + TFILE="$i-ssp$6-mclk-${13}-${12}-${14}way-$2-$4-$7-48k-$((${11} / 1000))k-$1" + fi fi echo "M4 pre-processing test $i -> ${TFILE}" m4 ${M4_FLAGS} \ @@ -123,6 +135,7 @@ function simple_test { -DTEST_SSP_DATA_BITS=$9 \ -DTEST_SSP_MODE=${12} \ -DTEST_SSP_MCLK_ID=${13} \ + -DTEST_PIPE_AMOUNT=${14} \ -DTEST_DAI_TYPE=$5 \ $i.m4 > "$BUILD_OUTPUT/${TFILE}.conf" echo "Compiling test $i -> $BUILD_OUTPUT/${TFILE}.tplg" @@ -136,18 +149,18 @@ function simple_test { echo "Preparing topology build input..." # Pre-process the simple tests -simple_test nocodec passthrough "NoCodec-2" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec passthrough "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s16le SSP 2 s24le 25 24 2400000 19200000 I2S 0 SIMPLE_TESTS[@] +simple_test nocodec passthrough "NoCodec-2" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec passthrough "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s16le SSP 2 s24le 25 24 2400000 19200000 I2S 0 1 SIMPLE_TESTS[@] -simple_test codec passthrough "SSP2-Codec" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test codec passthrough "SSP2-Codec" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test codec volume "SSP2-Codec" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test codec volume "SSP2-Codec" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test codec volume "SSP2-Codec" s24le SSP 2 s16le 20 16 1920000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test codec volume "SSP2-Codec" s16le SSP 2 s24le 25 24 2400000 19200000 I2S 0 SIMPLE_TESTS[@] +simple_test codec passthrough "SSP2-Codec" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test codec passthrough "SSP2-Codec" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test codec volume "SSP2-Codec" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test codec volume "SSP2-Codec" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test codec volume "SSP2-Codec" s24le SSP 2 s16le 20 16 1920000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test codec volume "SSP2-Codec" s16le SSP 2 s24le 25 24 2400000 19200000 I2S 0 1 SIMPLE_TESTS[@] # for APL APL_PROTOCOL_TESTS=(I2S LEFT_J DSP_A DSP_B) @@ -166,25 +179,25 @@ do do for mclk_id in ${MCLK_IDS[@]} do - simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] + simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] done done done for mclk_id in ${MCLK_IDS[@]} do - simple_test nocodec passthrough "NoCodec-${ssp}" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test nocodec passthrough "NoCodec-${ssp}" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test nocodec passthrough "NoCodec-${ssp}" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] + simple_test nocodec passthrough "NoCodec-${ssp}" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test nocodec passthrough "NoCodec-${ssp}" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test nocodec passthrough "NoCodec-${ssp}" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] - simple_test codec passthrough "SSP${ssp}-Codec" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test codec passthrough "SSP${ssp}-Codec" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test codec passthrough "SSP${ssp}-Codec" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] + simple_test codec passthrough "SSP${ssp}-Codec" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test codec passthrough "SSP${ssp}-Codec" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test codec passthrough "SSP${ssp}-Codec" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] done done done @@ -197,25 +210,28 @@ do do for format in ${APL_FORMAT_TESTS[@]} do - simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 SIMPLE_TESTS[@] - simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 SIMPLE_TESTS[@] + simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 1 SIMPLE_TESTS[@] + simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 1 SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 1 SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 1 SIMPLE_TESTS[@] done done - simple_test nocodec passthrough "NoCodec-${ssp}" s16le SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 SIMPLE_TESTS[@] - simple_test nocodec passthrough "NoCodec-${ssp}" s24le SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 SIMPLE_TESTS[@] + simple_test nocodec passthrough "NoCodec-${ssp}" s16le SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 1 SIMPLE_TESTS[@] + simple_test nocodec passthrough "NoCodec-${ssp}" s24le SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 1 SIMPLE_TESTS[@] - simple_test codec passthrough "SSP${ssp}-Codec" s16le SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 SIMPLE_TESTS[@] - simple_test codec passthrough "SSP${ssp}-Codec" s24le SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 SIMPLE_TESTS[@] + simple_test codec passthrough "SSP${ssp}-Codec" s16le SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 1 SIMPLE_TESTS[@] + simple_test codec passthrough "SSP${ssp}-Codec" s24le SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 1 SIMPLE_TESTS[@] done done # for processing algorithms -ALG_MODE_TESTS=(asrc eq-fir eq-iir src dcblock) -ALG_SIMPLE_TESTS=(test-capture test-playback) +ALG_SINGLE_MODE_TESTS=(asrc eq-fir eq-iir src dcblock) +ALG_SINGLE_SIMPLE_TESTS=(test-capture test-playback) +ALG_MULTI_MODE_TESTS=() +ALG_MULTI_SIMPLE_TESTS=() +ALG_MULTI_PIPE_AMOUNT=(2 3 4) ALG_PROTOCOL_TESTS=(I2S) ALG_SSP_TESTS=(5) ALG_MCLK_IDS=(0) @@ -224,33 +240,43 @@ for protocol in ${ALG_PROTOCOL_TESTS[@]} do for ssp in ${ALG_SSP_TESTS[@]} do - for mode in ${ALG_MODE_TESTS[@]} + for mclk_id in ${ALG_MCLK_IDS[@]} do - for mclk_id in ${ALG_MCLK_IDS[@]} + for mode in ${ALG_SINGLE_MODE_TESTS[@]} + do + simple_test codec $mode "SSP${ssp}-Codec" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id 1 ALG_SINGLE_SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id 1 ALG_SINGLE_SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id 1 ALG_SINGLE_SIMPLE_TESTS[@] + done + + for mode in ${ALG_MULTI_MODE_TESTS[@]} do - simple_test codec $mode "SSP${ssp}-Codec" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id ALG_SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id ALG_SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id ALG_SIMPLE_TESTS[@] + for pipe_num in ${ALG_MULTI_PIPE_AMOUNT[@]} + do + simple_test codec $mode "SSP${ssp}-Codec" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id $pipe_num ALG_MULTI_SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id $pipe_num ALG_MULTI_SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id $pipe_num ALG_MULTI_SIMPLE_TESTS[@] + done done done done done # for CNL -simple_test nocodec passthrough "NoCodec-0" s16le SSP 0 s16le 25 16 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec passthrough "NoCodec-2" s24le SSP 0 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-0" s16le SSP 0 s16le 25 16 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-0" s16le SSP 0 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-0" s24le SSP 0 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-0" s24le SSP 0 s16le 25 16 2400000 24000000 I2S 0 SIMPLE_TESTS[@] +simple_test nocodec passthrough "NoCodec-0" s16le SSP 0 s16le 25 16 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec passthrough "NoCodec-2" s24le SSP 0 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-0" s16le SSP 0 s16le 25 16 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-0" s16le SSP 0 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-0" s24le SSP 0 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-0" s24le SSP 0 s16le 25 16 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] -simple_test nocodec passthrough "NoCodec-2" s16le SSP 2 s16le 25 16 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec passthrough "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s16le SSP 2 s16le 25 16 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s16le SSP 2 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s24le SSP 2 s16le 25 16 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec src "NoCodec-4" s24le SSP 4 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] +simple_test nocodec passthrough "NoCodec-2" s16le SSP 2 s16le 25 16 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec passthrough "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s16le SSP 2 s16le 25 16 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s16le SSP 2 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s24le SSP 2 s16le 25 16 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec src "NoCodec-4" s24le SSP 4 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] # algorithms tests @@ -262,13 +288,13 @@ then : ${NO_PROCESSORS:=$(nproc)} - # Each test is defined by 14 consecutive strings, the last one - # is the ${14}.conf output file. + # Each test is defined by 15 consecutive strings, the last one + # is the ${15}.conf output file. shell_name=m4 # $0, only used in error messages echo $M4_STRINGS | tr " " "," | tr '\n' '\0' | - xargs ${VERBOSE:+-t} -P${NO_PROCESSORS} -d ',' -n14 \ + xargs ${VERBOSE:+-t} -P${NO_PROCESSORS} -d ',' -n15 \ bash ${VERBOSE:+-x} -c \ - 'm4 --fatal-warnings "${@:1:${#}-1}" > ${14}.conf || exit 255' \ + 'm4 --fatal-warnings "${@:1:${#}-1}" > ${15}.conf || exit 255' \ $shell_name #execute alsatplg to create topology binary diff --git a/tools/testbench/include/testbench/common_test.h b/tools/testbench/include/testbench/common_test.h index 409e3a6a5606..65f696136070 100644 --- a/tools/testbench/include/testbench/common_test.h +++ b/tools/testbench/include/testbench/common_test.h @@ -17,13 +17,16 @@ #define DEBUG_MSG_LEN 256 #define MAX_LIB_NAME_LEN 256 +#define MAX_OUTPUT_FILE_NUM 4 + /* number of widgets types supported in testbench */ #define NUM_WIDGETS_SUPPORTED 7 struct testbench_prm { char *tplg_file; /* topology file to use */ char *input_file; /* input file name */ - char *output_file; /* output file name */ + char *output_file[MAX_OUTPUT_FILE_NUM]; /* output file names */ + int output_file_num; /* number of output files */ char *bits_in; /* input bit format */ /* * input and output sample rate parameters @@ -37,6 +40,7 @@ struct testbench_prm { int fr_id; int fw_id; int sched_id; + int max_pipeline_id; enum sof_ipc_frame frame_fmt; }; diff --git a/tools/testbench/testbench.c b/tools/testbench/testbench.c index f5cb8391482d..4bbfc2f7146a 100644 --- a/tools/testbench/testbench.c +++ b/tools/testbench/testbench.c @@ -38,6 +38,39 @@ struct sof *sof_get() return &sof; } +/* + * Parse output filenames from user input + * This function takes in the output filenames as an input in the format: + * "output_file1,output_file2,..." + * The max supported output filename number is 4, min is 1. + */ +static int parse_output_files(char *outputs, struct testbench_prm *tp) +{ + char *output_token = NULL; + char *token = strtok_r(outputs, ",", &output_token); + int index; + + for (index = 0; index < MAX_OUTPUT_FILE_NUM && token; index++) { + /* get output file name with current index */ + tp->output_file[index] = strdup(token); + + /* next output */ + token = strtok_r(NULL, ",", &output_token); + } + + if (index == MAX_OUTPUT_FILE_NUM && token) { + fprintf(stderr, "error: max output file number is %d\n", + MAX_OUTPUT_FILE_NUM); + for (index = 0; index < MAX_OUTPUT_FILE_NUM; index++) + free(tp->output_file[index]); + return -EINVAL; + } + + /* set total output file number */ + tp->output_file_num = index; + return 0; +} + /* * Parse shared library from user input * Currently only handles volume and src comp @@ -85,13 +118,14 @@ static int parse_libraries(char *libs) /* print usage for testbench */ static void print_usage(char *executable) { - printf("Usage: %s -i -o ", executable); - printf("-t -b "); + printf("Usage: %s -i ", executable); + printf("-o "); + printf("-t -b -c "); printf("-a \n"); printf("input_format should be S16_LE, S32_LE, S24_LE or FLOAT_LE\n"); printf("Example Usage:\n"); printf("%s -i in.txt -o out.txt -t test.tplg ", executable); - printf("-r 48000 -R 96000 "); + printf("-r 48000 -R 96000 -c 2"); printf("-b S16_LE -a vol=libsof_volume.so\n"); } @@ -130,16 +164,16 @@ static void parse_input_args(int argc, char **argv, struct testbench_prm *tp) int option = 0; int ret = 0; - while ((option = getopt(argc, argv, "hdi:o:t:b:a:r:R:")) != -1) { + while ((option = getopt(argc, argv, "hdi:o:t:b:a:r:R:c:")) != -1) { switch (option) { /* input sample file */ case 'i': tp->input_file = strdup(optarg); break; - /* output sample file */ + /* output sample files */ case 'o': - tp->output_file = strdup(optarg); + ret = parse_output_files(optarg, tp); break; /* topology file */ @@ -168,6 +202,11 @@ static void parse_input_args(int argc, char **argv, struct testbench_prm *tp) tp->fs_out = atoi(optarg); break; + /* input/output channels */ + case 'c': + tp->channels = atoi(optarg); + break; + /* enable debug prints */ case 'd': debug = 1; @@ -190,6 +229,7 @@ int main(int argc, char **argv) struct testbench_prm tp; struct ipc_comp_dev *pcm_dev; struct pipeline *p; + struct pipeline *curr_p; struct sof_ipc_pipe_new *ipc_pipe; struct comp_dev *cd; struct file_comp_data *frcd, *fwcd; @@ -204,14 +244,18 @@ int main(int argc, char **argv) tp.fs_out = 0; tp.bits_in = 0; tp.input_file = NULL; - tp.output_file = NULL; + for (i = 0; i < MAX_OUTPUT_FILE_NUM; i++) + tp.output_file[i] = NULL; + tp.output_file_num = 0; tp.channels = TESTBENCH_NCH; + tp.max_pipeline_id = 0; /* command line arguments*/ parse_input_args(argc, argv, &tp); /* check args */ - if (!tp.tplg_file || !tp.input_file || !tp.output_file || !tp.bits_in) { + if (!tp.tplg_file || !tp.input_file || !tp.output_file_num || + !tp.bits_in) { print_usage(argv[0]); exit(EXIT_FAILURE); } @@ -256,8 +300,25 @@ int main(int argc, char **argv) tb_enable_trace(false); /* reduce trace output */ tic = clock(); - while (frcd->fs.reached_eof == 0) - pipeline_schedule_copy(p, 0); + while (frcd->fs.reached_eof == 0) { + /* + * Schedule copy for all pipelines which have the same schedule + * component as the working one. + * + * In common convention pipelines are added with monotonic + * increasing IDs started from 1, we could take care of it in + * test topologies so this for-loop will walk all pipelines. + */ + for (i = 1; i <= tp.max_pipeline_id; i++) { + pcm_dev = ipc_get_comp_by_ppl_id(sof.ipc, + COMP_TYPE_PIPELINE, i); + if (pcm_dev) { + curr_p = pcm_dev->pipeline; + if (pipeline_is_same_sched_comp(p, curr_p)) + pipeline_schedule_copy(curr_p, 0); + } + } + } if (!frcd->fs.reached_eof) printf("warning: possible pipeline xrun\n"); @@ -275,7 +336,7 @@ int main(int argc, char **argv) n_in = frcd->fs.n; n_out = fwcd->fs.n; t_exec = (double)(toc - tic) / CLOCKS_PER_SEC; - c_realtime = (double)n_out / TESTBENCH_NCH / tp.fs_out / t_exec; + c_realtime = (double)n_out / tp.channels / tp.fs_out / t_exec; /* free all components/buffers in pipeline */ free_comps(); @@ -289,7 +350,10 @@ int main(int argc, char **argv) printf("Input bit format: %s\n", tp.bits_in); printf("Input sample rate: %d\n", tp.fs_in); printf("Output sample rate: %d\n", tp.fs_out); - printf("Output written to file: \"%s\"\n", tp.output_file); + for (i = 0; i < tp.output_file_num; i++) { + printf("Output[%d] written to file: \"%s\"\n", + i, tp.output_file[i]); + } printf("Input sample count: %d\n", n_in); printf("Output sample count: %d\n", n_out); printf("Total execution time: %.2f us, %.2f x realtime\n", @@ -299,7 +363,8 @@ int main(int argc, char **argv) free(tp.bits_in); free(tp.input_file); free(tp.tplg_file); - free(tp.output_file); + for (i = 0; i < tp.output_file_num; i++) + free(tp.output_file[i]); /* close shared library objects */ for (i = 0; i < NUM_WIDGETS_SUPPORTED; i++) { diff --git a/tools/testbench/topology.c b/tools/testbench/topology.c index b216e6ab98f6..929e1521e25b 100644 --- a/tools/testbench/topology.c +++ b/tools/testbench/topology.c @@ -22,6 +22,7 @@ FILE *file; char pipeline_string[DEBUG_MSG_LEN]; struct shared_lib_table *lib_table; +int output_file_index; const struct sof_dai_types sof_dais[] = { {"SSP", SOF_DAI_INTEL_SSP}, @@ -332,9 +333,16 @@ static int load_filewrite(struct sof *sof, int comp_id, int pipeline_id, return -EINVAL; } - /* configure filewrite */ - filewrite.fn = strdup(tp->output_file); - tp->fw_id = comp_id; + /* configure filewrite (multiple output files are supported.) */ + if (!tp->output_file[output_file_index]) { + fprintf(stderr, "error: output[%d] file name is null\n", + output_file_index); + return -EINVAL; + } + filewrite.fn = strdup(tp->output_file[output_file_index]); + if (output_file_index == 0) + tp->fw_id = comp_id; + output_file_index++; /* Set format from testbench command line*/ filewrite.rate = tp->fs_out; @@ -671,6 +679,9 @@ int parse_topology(struct sof *sof, struct shared_lib_table *library_table, { struct snd_soc_tplg_hdr *hdr; + /* initialize output file index */ + output_file_index = 0; + struct comp_info *temp_comp_list = NULL; char message[DEBUG_MSG_LEN]; int next_comp_id = 0; @@ -729,6 +740,10 @@ int parse_topology(struct sof *sof, struct shared_lib_table *library_table, debug_print(message); + /* update max pipeline_id */ + if (hdr->index > tp->max_pipeline_id) + tp->max_pipeline_id = hdr->index; + num_comps += hdr->count; size = sizeof(struct comp_info) * num_comps; temp_comp_list = (struct comp_info *) diff --git a/tools/tplg_parser/tplg_parser.c b/tools/tplg_parser/tplg_parser.c index b0a85199bd80..776c6ef08f21 100644 --- a/tools/tplg_parser/tplg_parser.c +++ b/tools/tplg_parser/tplg_parser.c @@ -1097,8 +1097,10 @@ int tplg_load_graph(int num_comps, int pipeline_id, strcat(pipeline_string, graph_elem->source); strcat(pipeline_string, "->"); - if (route_num == (count - 1)) + if (route_num == (count - 1)) { strcat(pipeline_string, graph_elem->sink); + strcat(pipeline_string, "\n"); + } free(graph_elem); return 0; @@ -1138,7 +1140,8 @@ int load_widget(void *dev, int dev_type, struct comp_info *temp_comp_list, temp_comp_list[comp_index].type = widget->id; temp_comp_list[comp_index].pipeline_id = pipeline_id; - printf("debug: loading widget %s id %d\n", widget->name, widget->id); + printf("debug: loading comp_id %d: widget %s id %d\n", + comp_id, widget->name, widget->id); /* load widget based on type */ switch (widget->id) {