diff --git a/tools/topology/topology2/README.md b/tools/topology/topology2/README.md index bea7ffcfdcde..759867a47d1c 100644 --- a/tools/topology/topology2/README.md +++ b/tools/topology/topology2/README.md @@ -242,6 +242,8 @@ default ID ranges for the same endpoint types. | Jack Echo Ref | 11 | `SDW_JACK_ECHO_REF_PCM_ID` | | Speaker Echo Ref | 12 | `SDW_SPK_ECHO_REF_PCM_ID` | | Bluetooth | 2 or 20 | `BT_PCM_ID` | +| USB Audio Offload (UAOL) | 21 | `UAOL_PCM_ID` | +| Deepbuffer UAOL | 22 | `DEEP_BUFFER_PCM_ID` | | Deep Buffer (Jack) | 31 | `DEEP_BUFFER_PCM_ID` | | Deep Buffer (Speaker) | 35 | `DEEP_BUFFER_PCM_ID_2` | | DMIC Deep Buffer | 46 | `DMIC0_DEEP_BUFFER_PCM_ID` | @@ -301,6 +303,9 @@ is at N1 (50/51, 60/61, 70/71, 80/81). | HDMI 4 Host / DAI | 80 / 81 | `HDMI4_HOST_PIPELINE_ID` / `HDMI4_DAI_PIPELINE_ID` | | Compress Jack / Speaker | 90 / 92 | `COMPR_PIPELINE_ID` / `COMPR_2_PIPELINE_ID` | | PCH DMIC0 Host / DAI | 100 / 101 | `DMIC0_HOST_PIPELINE_ID` / `DMIC0_DAI_PIPELINE_ID` | +| UAOL Playback Host / DAI | 210 / 211 | `UAOL_PB_HOST_PIPELINE_ID` / `UAOL_PB_DAI_PIPELINE_ID` | +| UAOL Capture Host / DAI | 212 / 213 | `UAOL_CP_HOST_PIPELINE_ID` / `UAOL_CP_DAI_PIPELINE_ID` | +| UAOL Deepbuffer | 214 | `DEEP_BUFFER_PIPELINE_ID` | **Intel HDA Pipeline IDs:** diff --git a/tools/topology/topology2/cavs-uaol.conf b/tools/topology/topology2/cavs-uaol.conf new file mode 100644 index 000000000000..c62e217dab02 --- /dev/null +++ b/tools/topology/topology2/cavs-uaol.conf @@ -0,0 +1,82 @@ +# Basic USB Audio Offload Link (UAOL) topology. +# +# This is a function topology, loaded next to the other function topologies of +# the sof_sdw card, so its PCM and pipeline IDs must not collide with theirs. +# +# The UAOL function itself lives in platform/intel/uaol-generic.conf. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Define { + UAOL_PLAYBACK_PCM 'UAOL Playback' + UAOL_CAPTURE_PCM 'UAOL Capture' + # The two directions are separate DAI links so that the format fixup of + # a link is decided by the DAI copier of that direction alone. The names + # are abbreviated because alsatplg drops widget tuples above 36 characters + # and the dai-copier name is 'dai-copier.UAOL..' + UAOL_PB_DAI_NAME 'UAOL0-Play' + UAOL_CP_DAI_NAME 'UAOL0-Cap' + # The BE IDs are the dai link IDs that are matched with the machine + # driver, which creates the playback link first + UAOL_PB_BE_ID 9 + UAOL_CP_BE_ID 10 + # UAOL_DAI_INDEX is the UAOL link the DSP uses, only link 0 is addressable + UAOL_DAI_INDEX 0 + UAOL_PCM_NAME 'UAOL' + UAOL_PCM_ID 21 + UAOL_PB_HOST_PIPELINE_ID 210 + UAOL_PB_DAI_PIPELINE_ID 211 + UAOL_CP_HOST_PIPELINE_ID 212 + UAOL_CP_DAI_PIPELINE_ID 213 + # The mixer of the playback path only supports a stereo stream, while the + # capture path passes through whatever the USB device records + UAOL_PLAYBACK_CHANNELS 2 + UAOL_CAPTURE_CHANNELS_MIN 1 + UAOL_CAPTURE_CHANNELS_MAX 2 + UAOL_RATE 48000 + + # The deep buffer PCM feeds the same mixer as the normal playback PCM. It + # takes the source and the sink as plain widget names, so it repeats the + # pipeline IDs defined above. + DEEP_BUFFER_PCM_NAME 'Deepbuffer UAOL' + DEEP_BUFFER_PCM_ID 22 + DEEP_BUFFER_PIPELINE_ID 214 + DEEP_BUFFER_PIPELINE_SRC 'mixin.214.1' + DEEP_BUFFER_PIPELINE_SINK 'mixout.211.1' +} + + diff --git a/tools/topology/topology2/include/components/dai-copier.conf b/tools/topology/topology2/include/components/dai-copier.conf index e5508ada3df5..3b97ff0b4adf 100644 --- a/tools/topology/topology2/include/components/dai-copier.conf +++ b/tools/topology/topology2/include/components/dai-copier.conf @@ -44,6 +44,7 @@ Class.Widget."dai-copier" { "HDA" "SSP" "DMIC" + "UAOL" "SAI" ] } @@ -57,6 +58,7 @@ Class.Widget."dai-copier" { "SSP" "DMIC" "HDA" + "UAOL" "SAI" ] } @@ -103,6 +105,8 @@ Class.Widget."dai-copier" { $DMIC_LINK_INPUT_CLASS # DMIC link input (DSP <-) $I2S_LINK_OUTPUT_CLASS # I2S link output (DSP ->) $I2S_LINK_INPUT_CLASS # I2S link input (DSP <-) + $ALH_UAOL_STREAM_LINK_OUTPUT_CLASS # UAOL link output (DSP ->) + $ALH_UAOL_STREAM_LINK_INPUT_CLASS # UAOL link input (DSP <-) $IPC_OUTPUT_CLASS # IPC output (DSP ->) $IPC_INPUT_CLASS # IPC input (DSP <-) $I2S_MULTILINK_OUTPUT_CLASS # I2S Multi gtw output (DSP ->) diff --git a/tools/topology/topology2/include/components/dai.conf b/tools/topology/topology2/include/components/dai.conf index 4a34594b5eb0..41f884b4e9f9 100644 --- a/tools/topology/topology2/include/components/dai.conf +++ b/tools/topology/topology2/include/components/dai.conf @@ -28,6 +28,7 @@ Class.Widget."dai" { "DMIC" "HDA" "ALH" + "UAOL" "SAI" "ESAI" ] diff --git a/tools/topology/topology2/include/dais/uaol.conf b/tools/topology/topology2/include/dais/uaol.conf new file mode 100644 index 000000000000..56d8dd726481 --- /dev/null +++ b/tools/topology/topology2/include/dais/uaol.conf @@ -0,0 +1,95 @@ +# +# UAOL DAI +# +# All attributes defined herein are namespaced by alsatplg to +# "Object.Dai.UAOL.attribute_name" +# +# UAOL (USB Audio Offload Link) is an ACE2+ alt link. It belongs to the ALH +# class family in the firmware gateway enumeration, but it is described by its +# own DAI class because the ALH class carries SoundWire specific attributes. +# +# Usage: this component can be used by declaring as follows: +# +# For Playback +#Object.Dai.UAOL."N" { +# direction "playback" +# name "UAOL0" +# id 0 +# Object.Base.hw_config."0" {} +# } +# For Capture +#Object.Dai.UAOL."N" { +# direction "capture" +# name "UAOL0" +# id 0 +# Object.Base.hw_config."1" {} +# } +# +# Where N is the dai index of the UAOL DAI in the firmware + +Class.Dai."UAOL" { + # + # instance ID of UAOL DAI object + # + DefineAttribute."instance" {} + + # + # UAOL link index in the firmware + # + DefineAttribute."dai_index" { + token_ref "dai.word" + } + + DefineAttribute."direction" { + type "string" + constraints { + !valid_values [ + "playback" + "capture" + "duplex" + ] + } + } + + # type of DAI + DefineAttribute.dai_type { + type "string" + token_ref "dai.string" + } + + # Backend DAI Link ID matching with the machine driver + DefineAttribute.id {} + + DefineAttribute."default_hw_config_id" {} + + DefineAttribute.name { + type "string" + } + + DefineAttribute.rate {} + + DefineAttribute.ch {} + + attributes { + !constructor [ + "name" + ] + !mandatory [ + "id" + "dai_index" + ] + !immutable [ + "type" + ] + # + # UAOL DAI objects instantiated within the same alsaconf node must + # have unique instance attribute + # + unique "instance" + } + + dai_type "UAOL" + default_hw_config_id 0 + rate 48000 + ch 2 +} diff --git a/tools/topology/topology2/platform/intel/uaol-generic.conf b/tools/topology/topology2/platform/intel/uaol-generic.conf new file mode 100644 index 000000000000..559e07a549db --- /dev/null +++ b/tools/topology/topology2/platform/intel/uaol-generic.conf @@ -0,0 +1,327 @@ +# USB Audio Offload Link (UAOL) function. +# +# The offloaded USB endpoint is driven by the UAOL gateway in the firmware: +# +# PCM ---------------> gain ---> mixin ---+ +# | +# Deepbuffer PCM ----> gain ---> mixin ---+--> mixout --> gain --> UAOL0-Play +# +# PCM <------------ module-copier <--- eqiir <---------------- UAOL0-Cap +# +# The capture path carries no mixer, as the number of channels follows the USB +# device and a mixer only handles a fixed channel count. + +# Deep buffer playback, included when the DMA buffer is 1 - 1000 ms +IncludeByKey.DEEPBUFFER_FW_DMA_MS { + "([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|1000)" "platform/intel/deep-buffer.conf" +} + +Object.Dai.UAOL [ + { + name $UAOL_PB_DAI_NAME + dai_index $UAOL_DAI_INDEX + id $UAOL_PB_BE_ID + default_hw_conf_id 0 + Object.Base.hw_config.1 { + name "UAOL0-Play" + } + direction playback + } + { + name $UAOL_CP_DAI_NAME + dai_index $UAOL_DAI_INDEX + id $UAOL_CP_BE_ID + default_hw_conf_id 0 + Object.Base.hw_config.1 { + name "UAOL0-Cap" + } + direction capture + } +] + +Object.Pipeline { + host-copier-gain-mixin-playback [ + { + index $UAOL_PB_HOST_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name $UAOL_PLAYBACK_PCM + pcm_id $UAOL_PCM_ID + num_input_audio_formats 2 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $UAOL_PCM_NAME Playback Volume' + } + } + } + ] + + mixout-gain-dai-copier-playback [ + { + index $UAOL_PB_DAI_PIPELINE_ID + + Object.Widget.dai-copier.1 { + node_type $ALH_UAOL_STREAM_LINK_OUTPUT_CLASS + stream_name $UAOL_PB_DAI_NAME + dai_type "UAOL" + copier_type "UAOL" + num_output_audio_formats 2 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $UAOL_PCM_NAME Playback Volume' + } + } + } + ] + + host-gateway-capture [ + { + index $UAOL_CP_HOST_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name $UAOL_CAPTURE_PCM + pcm_id $UAOL_PCM_ID + num_input_audio_formats 2 + num_output_audio_formats 4 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 1 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 1 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + dai-copier-eqiir-module-copier-capture [ + { + index $UAOL_CP_DAI_PIPELINE_ID + + Object.Widget.dai-copier.1 { + node_type $ALH_UAOL_STREAM_LINK_INPUT_CLASS + stream_name $UAOL_CP_DAI_NAME + dai_type "UAOL" + type dai_out + copier_type "UAOL" + num_input_audio_formats 4 + num_output_audio_formats 2 + num_output_pins 1 + + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 1 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.eqiir.1 { + num_input_audio_formats 2 + num_output_audio_formats 2 + + Object.Control.bytes.1 { + name '$UAOL_PCM_NAME Capture IIR Eq' + + } + + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 1 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.module-copier.2 { + num_input_audio_formats 2 + num_output_audio_formats 2 + + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 1 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] +} + +Object.PCM.pcm [ + { + name $UAOL_PCM_NAME + id $UAOL_PCM_ID + direction "duplex" + Object.Base.fe_dai.1 { + name $UAOL_PCM_NAME + } + Object.PCM.pcm_caps.1 { + direction "playback" + name $UAOL_PLAYBACK_PCM + formats 'S16_LE,S32_LE' + channels_min $UAOL_PLAYBACK_CHANNELS + channels_max $UAOL_PLAYBACK_CHANNELS + rates '48000' + rate_min $UAOL_RATE + rate_max $UAOL_RATE + } + Object.PCM.pcm_caps.2 { + direction "capture" + name $UAOL_CAPTURE_PCM + formats 'S16_LE,S32_LE' + channels_min $UAOL_CAPTURE_CHANNELS_MIN + channels_max $UAOL_CAPTURE_CHANNELS_MAX + rates '48000' + rate_min $UAOL_RATE + rate_max $UAOL_RATE + } + } +] + +# top-level pipeline connections +Object.Base.route [ + { + source "host-copier.$UAOL_PCM_ID.playback" + sink "gain.$UAOL_PB_HOST_PIPELINE_ID.1" + } + { + source "mixin.$UAOL_PB_HOST_PIPELINE_ID.1" + sink "mixout.$UAOL_PB_DAI_PIPELINE_ID.1" + } + { + source "gain.$UAOL_PB_DAI_PIPELINE_ID.1" + sink "dai-copier.UAOL.$UAOL_PB_DAI_NAME.playback" + } + { + source "dai-copier.UAOL.$UAOL_CP_DAI_NAME.capture" + sink "eqiir.$UAOL_CP_DAI_PIPELINE_ID.1" + } + { + source "module-copier.$UAOL_CP_DAI_PIPELINE_ID.2" + sink "host-copier.$UAOL_PCM_ID.capture" + } +] diff --git a/tools/topology/topology2/production/tplg-targets-sdca-generic.cmake b/tools/topology/topology2/production/tplg-targets-sdca-generic.cmake index c7d5b5d8af1b..7979d2d07255 100644 --- a/tools/topology/topology2/production/tplg-targets-sdca-generic.cmake +++ b/tools/topology/topology2/production/tplg-targets-sdca-generic.cmake @@ -37,6 +37,19 @@ SDW_DMIC_STREAM=Capture-SmartMic" "cavs-sdw\;sof-hdmi-pcm5-id6\;SDW_JACK=false,HDMI1_ID=6,HDMI2_ID=7,HDMI3_ID=8" "cavs-sdw\;sof-hdmi-pcm5-id7\;SDW_JACK=false,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9" +# USB Audio Offload Link function topology. The UAOL backend is the last one +# sof_sdw creates, so its dai link ID depends on the composition of the board: +# it follows the SoundWire links, the PCH DMIC pair, the three HDMI links and +# the BT link. Each direction is a separate link, so two consecutive IDs are +# taken. The range below covers a jack and amplifier board without DMIC and BT +# (6) up to a jack, amplifier with feedback, PCH DMIC and BT board (10). +# Add a variant here for every further ID that is needed. +"cavs-uaol\;sof-uaol-id6\;UAOL_PB_BE_ID=6,UAOL_CP_BE_ID=7" +"cavs-uaol\;sof-uaol-id7\;UAOL_PB_BE_ID=7,UAOL_CP_BE_ID=8" +"cavs-uaol\;sof-uaol-id8\;UAOL_PB_BE_ID=8,UAOL_CP_BE_ID=9" +"cavs-uaol\;sof-uaol-id9\;UAOL_PB_BE_ID=9,UAOL_CP_BE_ID=10" +"cavs-uaol\;sof-uaol-id10\;UAOL_PB_BE_ID=10,UAOL_CP_BE_ID=11" + # Feature topologies which should work with the function topologies above "cavs-sdw\;sof-sdca-amp-ref\;SDW_JACK=false,NUM_HDMIS=0,JACK_RATE=48000,\ SDW_AMP_FEEDBACK=false,SDW_SPK_ECHO_REF=true,SDW_SPK_ECHO_REF_PCM_ID=12"