162306a36Sopenharmony_ci=========== 262306a36Sopenharmony_ciDynamic PCM 362306a36Sopenharmony_ci=========== 462306a36Sopenharmony_ci 562306a36Sopenharmony_ciDescription 662306a36Sopenharmony_ci=========== 762306a36Sopenharmony_ci 862306a36Sopenharmony_ciDynamic PCM allows an ALSA PCM device to digitally route its PCM audio to 962306a36Sopenharmony_civarious digital endpoints during the PCM stream runtime. e.g. PCM0 can route 1062306a36Sopenharmony_cidigital audio to I2S DAI0, I2S DAI1 or PDM DAI2. This is useful for on SoC DSP 1162306a36Sopenharmony_cidrivers that expose several ALSA PCMs and can route to multiple DAIs. 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ciThe DPCM runtime routing is determined by the ALSA mixer settings in the same 1462306a36Sopenharmony_ciway as the analog signal is routed in an ASoC codec driver. DPCM uses a DAPM 1562306a36Sopenharmony_cigraph representing the DSP internal audio paths and uses the mixer settings to 1662306a36Sopenharmony_cidetermine the path used by each ALSA PCM. 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciDPCM re-uses all the existing component codec, platform and DAI drivers without 1962306a36Sopenharmony_ciany modifications. 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ciPhone Audio System with SoC based DSP 2362306a36Sopenharmony_ci------------------------------------- 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ciConsider the following phone audio subsystem. This will be used in this 2662306a36Sopenharmony_cidocument for all examples :- 2762306a36Sopenharmony_ci:: 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci | Front End PCMs | SoC DSP | Back End DAIs | Audio devices | 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci ************* 3262306a36Sopenharmony_ci PCM0 <------------> * * <----DAI0-----> Codec Headset 3362306a36Sopenharmony_ci * * 3462306a36Sopenharmony_ci PCM1 <------------> * * <----DAI1-----> Codec Speakers 3562306a36Sopenharmony_ci * DSP * 3662306a36Sopenharmony_ci PCM2 <------------> * * <----DAI2-----> MODEM 3762306a36Sopenharmony_ci * * 3862306a36Sopenharmony_ci PCM3 <------------> * * <----DAI3-----> BT 3962306a36Sopenharmony_ci * * 4062306a36Sopenharmony_ci * * <----DAI4-----> DMIC 4162306a36Sopenharmony_ci * * 4262306a36Sopenharmony_ci * * <----DAI5-----> FM 4362306a36Sopenharmony_ci ************* 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ciThis diagram shows a simple smart phone audio subsystem. It supports Bluetooth, 4662306a36Sopenharmony_ciFM digital radio, Speakers, Headset Jack, digital microphones and cellular 4762306a36Sopenharmony_cimodem. This sound card exposes 4 DSP front end (FE) ALSA PCM devices and 4862306a36Sopenharmony_cisupports 6 back end (BE) DAIs. Each FE PCM can digitally route audio data to any 4962306a36Sopenharmony_ciof the BE DAIs. The FE PCM devices can also route audio to more than 1 BE DAI. 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ciExample - DPCM Switching playback from DAI0 to DAI1 5462306a36Sopenharmony_ci--------------------------------------------------- 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ciAudio is being played to the Headset. After a while the user removes the headset 5762306a36Sopenharmony_ciand audio continues playing on the speakers. 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciPlayback on PCM0 to Headset would look like :- 6062306a36Sopenharmony_ci:: 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci ************* 6362306a36Sopenharmony_ci PCM0 <============> * * <====DAI0=====> Codec Headset 6462306a36Sopenharmony_ci * * 6562306a36Sopenharmony_ci PCM1 <------------> * * <----DAI1-----> Codec Speakers 6662306a36Sopenharmony_ci * DSP * 6762306a36Sopenharmony_ci PCM2 <------------> * * <----DAI2-----> MODEM 6862306a36Sopenharmony_ci * * 6962306a36Sopenharmony_ci PCM3 <------------> * * <----DAI3-----> BT 7062306a36Sopenharmony_ci * * 7162306a36Sopenharmony_ci * * <----DAI4-----> DMIC 7262306a36Sopenharmony_ci * * 7362306a36Sopenharmony_ci * * <----DAI5-----> FM 7462306a36Sopenharmony_ci ************* 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ciThe headset is removed from the jack by user so the speakers must now be used :- 7762306a36Sopenharmony_ci:: 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci ************* 8062306a36Sopenharmony_ci PCM0 <============> * * <----DAI0-----> Codec Headset 8162306a36Sopenharmony_ci * * 8262306a36Sopenharmony_ci PCM1 <------------> * * <====DAI1=====> Codec Speakers 8362306a36Sopenharmony_ci * DSP * 8462306a36Sopenharmony_ci PCM2 <------------> * * <----DAI2-----> MODEM 8562306a36Sopenharmony_ci * * 8662306a36Sopenharmony_ci PCM3 <------------> * * <----DAI3-----> BT 8762306a36Sopenharmony_ci * * 8862306a36Sopenharmony_ci * * <----DAI4-----> DMIC 8962306a36Sopenharmony_ci * * 9062306a36Sopenharmony_ci * * <----DAI5-----> FM 9162306a36Sopenharmony_ci ************* 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ciThe audio driver processes this as follows :- 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci1. Machine driver receives Jack removal event. 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci2. Machine driver OR audio HAL disables the Headset path. 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci3. DPCM runs the PCM trigger(stop), hw_free(), shutdown() operations on DAI0 10062306a36Sopenharmony_ci for headset since the path is now disabled. 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci4. Machine driver or audio HAL enables the speaker path. 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci5. DPCM runs the PCM ops for startup(), hw_params(), prepare() and 10562306a36Sopenharmony_ci trigger(start) for DAI1 Speakers since the path is enabled. 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ciIn this example, the machine driver or userspace audio HAL can alter the routing 10862306a36Sopenharmony_ciand then DPCM will take care of managing the DAI PCM operations to either bring 10962306a36Sopenharmony_cithe link up or down. Audio playback does not stop during this transition. 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ciDPCM machine driver 11462306a36Sopenharmony_ci=================== 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ciThe DPCM enabled ASoC machine driver is similar to normal machine drivers 11762306a36Sopenharmony_ciexcept that we also have to :- 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci1. Define the FE and BE DAI links. 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci2. Define any FE/BE PCM operations. 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci3. Define widget graph connections. 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ciFE and BE DAI links 12762306a36Sopenharmony_ci------------------- 12862306a36Sopenharmony_ci:: 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci | Front End PCMs | SoC DSP | Back End DAIs | Audio devices | 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci ************* 13362306a36Sopenharmony_ci PCM0 <------------> * * <----DAI0-----> Codec Headset 13462306a36Sopenharmony_ci * * 13562306a36Sopenharmony_ci PCM1 <------------> * * <----DAI1-----> Codec Speakers 13662306a36Sopenharmony_ci * DSP * 13762306a36Sopenharmony_ci PCM2 <------------> * * <----DAI2-----> MODEM 13862306a36Sopenharmony_ci * * 13962306a36Sopenharmony_ci PCM3 <------------> * * <----DAI3-----> BT 14062306a36Sopenharmony_ci * * 14162306a36Sopenharmony_ci * * <----DAI4-----> DMIC 14262306a36Sopenharmony_ci * * 14362306a36Sopenharmony_ci * * <----DAI5-----> FM 14462306a36Sopenharmony_ci ************* 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ciFor the example above we have to define 4 FE DAI links and 6 BE DAI links. The 14762306a36Sopenharmony_ciFE DAI links are defined as follows :- 14862306a36Sopenharmony_ci:: 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci static struct snd_soc_dai_link machine_dais[] = { 15162306a36Sopenharmony_ci { 15262306a36Sopenharmony_ci .name = "PCM0 System", 15362306a36Sopenharmony_ci .stream_name = "System Playback", 15462306a36Sopenharmony_ci .cpu_dai_name = "System Pin", 15562306a36Sopenharmony_ci .platform_name = "dsp-audio", 15662306a36Sopenharmony_ci .codec_name = "snd-soc-dummy", 15762306a36Sopenharmony_ci .codec_dai_name = "snd-soc-dummy-dai", 15862306a36Sopenharmony_ci .dynamic = 1, 15962306a36Sopenharmony_ci .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 16062306a36Sopenharmony_ci .dpcm_playback = 1, 16162306a36Sopenharmony_ci }, 16262306a36Sopenharmony_ci .....< other FE and BE DAI links here > 16362306a36Sopenharmony_ci }; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ciThis FE DAI link is pretty similar to a regular DAI link except that we also 16662306a36Sopenharmony_ciset the DAI link to a DPCM FE with the ``dynamic = 1``. The supported FE stream 16762306a36Sopenharmony_cidirections should also be set with the ``dpcm_playback`` and ``dpcm_capture`` 16862306a36Sopenharmony_ciflags. There is also an option to specify the ordering of the trigger call for 16962306a36Sopenharmony_cieach FE. This allows the ASoC core to trigger the DSP before or after the other 17062306a36Sopenharmony_cicomponents (as some DSPs have strong requirements for the ordering DAI/DSP 17162306a36Sopenharmony_cistart and stop sequences). 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ciThe FE DAI above sets the codec and code DAIs to dummy devices since the BE is 17462306a36Sopenharmony_cidynamic and will change depending on runtime config. 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ciThe BE DAIs are configured as follows :- 17762306a36Sopenharmony_ci:: 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci static struct snd_soc_dai_link machine_dais[] = { 18062306a36Sopenharmony_ci .....< FE DAI links here > 18162306a36Sopenharmony_ci { 18262306a36Sopenharmony_ci .name = "Codec Headset", 18362306a36Sopenharmony_ci .cpu_dai_name = "ssp-dai.0", 18462306a36Sopenharmony_ci .platform_name = "snd-soc-dummy", 18562306a36Sopenharmony_ci .no_pcm = 1, 18662306a36Sopenharmony_ci .codec_name = "rt5640.0-001c", 18762306a36Sopenharmony_ci .codec_dai_name = "rt5640-aif1", 18862306a36Sopenharmony_ci .ignore_suspend = 1, 18962306a36Sopenharmony_ci .ignore_pmdown_time = 1, 19062306a36Sopenharmony_ci .be_hw_params_fixup = hswult_ssp0_fixup, 19162306a36Sopenharmony_ci .ops = &haswell_ops, 19262306a36Sopenharmony_ci .dpcm_playback = 1, 19362306a36Sopenharmony_ci .dpcm_capture = 1, 19462306a36Sopenharmony_ci }, 19562306a36Sopenharmony_ci .....< other BE DAI links here > 19662306a36Sopenharmony_ci }; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ciThis BE DAI link connects DAI0 to the codec (in this case RT5460 AIF1). It sets 19962306a36Sopenharmony_cithe ``no_pcm`` flag to mark it has a BE and sets flags for supported stream 20062306a36Sopenharmony_cidirections using ``dpcm_playback`` and ``dpcm_capture`` above. 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ciThe BE has also flags set for ignoring suspend and PM down time. This allows 20362306a36Sopenharmony_cithe BE to work in a hostless mode where the host CPU is not transferring data 20462306a36Sopenharmony_cilike a BT phone call :- 20562306a36Sopenharmony_ci:: 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci ************* 20862306a36Sopenharmony_ci PCM0 <------------> * * <----DAI0-----> Codec Headset 20962306a36Sopenharmony_ci * * 21062306a36Sopenharmony_ci PCM1 <------------> * * <----DAI1-----> Codec Speakers 21162306a36Sopenharmony_ci * DSP * 21262306a36Sopenharmony_ci PCM2 <------------> * * <====DAI2=====> MODEM 21362306a36Sopenharmony_ci * * 21462306a36Sopenharmony_ci PCM3 <------------> * * <====DAI3=====> BT 21562306a36Sopenharmony_ci * * 21662306a36Sopenharmony_ci * * <----DAI4-----> DMIC 21762306a36Sopenharmony_ci * * 21862306a36Sopenharmony_ci * * <----DAI5-----> FM 21962306a36Sopenharmony_ci ************* 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ciThis allows the host CPU to sleep while the DSP, MODEM DAI and the BT DAI are 22262306a36Sopenharmony_cistill in operation. 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ciA BE DAI link can also set the codec to a dummy device if the codec is a device 22562306a36Sopenharmony_cithat is managed externally. 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ciLikewise a BE DAI can also set a dummy cpu DAI if the CPU DAI is managed by the 22862306a36Sopenharmony_ciDSP firmware. 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ciFE/BE PCM operations 23262306a36Sopenharmony_ci-------------------- 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ciThe BE above also exports some PCM operations and a ``fixup`` callback. The fixup 23562306a36Sopenharmony_cicallback is used by the machine driver to (re)configure the DAI based upon the 23662306a36Sopenharmony_ciFE hw params. i.e. the DSP may perform SRC or ASRC from the FE to BE. 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cie.g. DSP converts all FE hw params to run at fixed rate of 48k, 16bit, stereo for 23962306a36Sopenharmony_ciDAI0. This means all FE hw_params have to be fixed in the machine driver for 24062306a36Sopenharmony_ciDAI0 so that the DAI is running at desired configuration regardless of the FE 24162306a36Sopenharmony_ciconfiguration. 24262306a36Sopenharmony_ci:: 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci static int dai0_fixup(struct snd_soc_pcm_runtime *rtd, 24562306a36Sopenharmony_ci struct snd_pcm_hw_params *params) 24662306a36Sopenharmony_ci { 24762306a36Sopenharmony_ci struct snd_interval *rate = hw_param_interval(params, 24862306a36Sopenharmony_ci SNDRV_PCM_HW_PARAM_RATE); 24962306a36Sopenharmony_ci struct snd_interval *channels = hw_param_interval(params, 25062306a36Sopenharmony_ci SNDRV_PCM_HW_PARAM_CHANNELS); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci /* The DSP will convert the FE rate to 48k, stereo */ 25362306a36Sopenharmony_ci rate->min = rate->max = 48000; 25462306a36Sopenharmony_ci channels->min = channels->max = 2; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* set DAI0 to 16 bit */ 25762306a36Sopenharmony_ci params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); 25862306a36Sopenharmony_ci return 0; 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ciThe other PCM operation are the same as for regular DAI links. Use as necessary. 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ciWidget graph connections 26562306a36Sopenharmony_ci------------------------ 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ciThe BE DAI links will normally be connected to the graph at initialisation time 26862306a36Sopenharmony_ciby the ASoC DAPM core. However, if the BE codec or BE DAI is a dummy then this 26962306a36Sopenharmony_cihas to be set explicitly in the driver :- 27062306a36Sopenharmony_ci:: 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci /* BE for codec Headset - DAI0 is dummy and managed by DSP FW */ 27362306a36Sopenharmony_ci {"DAI0 CODEC IN", NULL, "AIF1 Capture"}, 27462306a36Sopenharmony_ci {"AIF1 Playback", NULL, "DAI0 CODEC OUT"}, 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ciWriting a DPCM DSP driver 27862306a36Sopenharmony_ci========================= 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ciThe DPCM DSP driver looks much like a standard platform class ASoC driver 28162306a36Sopenharmony_cicombined with elements from a codec class driver. A DSP platform driver must 28262306a36Sopenharmony_ciimplement :- 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci1. Front End PCM DAIs - i.e. struct snd_soc_dai_driver. 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci2. DAPM graph showing DSP audio routing from FE DAIs to BEs. 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci3. DAPM widgets from DSP graph. 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci4. Mixers for gains, routing, etc. 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci5. DMA configuration. 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci6. BE AIF widgets. 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ciItems 6 is important for routing the audio outside of the DSP. AIF need to be 29762306a36Sopenharmony_cidefined for each BE and each stream direction. e.g for BE DAI0 above we would 29862306a36Sopenharmony_cihave :- 29962306a36Sopenharmony_ci:: 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci SND_SOC_DAPM_AIF_IN("DAI0 RX", NULL, 0, SND_SOC_NOPM, 0, 0), 30262306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("DAI0 TX", NULL, 0, SND_SOC_NOPM, 0, 0), 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ciThe BE AIF are used to connect the DSP graph to the graphs for the other 30562306a36Sopenharmony_cicomponent drivers (e.g. codec graph). 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ciHostless PCM streams 30962306a36Sopenharmony_ci==================== 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ciA hostless PCM stream is a stream that is not routed through the host CPU. An 31262306a36Sopenharmony_ciexample of this would be a phone call from handset to modem. 31362306a36Sopenharmony_ci:: 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci ************* 31662306a36Sopenharmony_ci PCM0 <------------> * * <----DAI0-----> Codec Headset 31762306a36Sopenharmony_ci * * 31862306a36Sopenharmony_ci PCM1 <------------> * * <====DAI1=====> Codec Speakers/Mic 31962306a36Sopenharmony_ci * DSP * 32062306a36Sopenharmony_ci PCM2 <------------> * * <====DAI2=====> MODEM 32162306a36Sopenharmony_ci * * 32262306a36Sopenharmony_ci PCM3 <------------> * * <----DAI3-----> BT 32362306a36Sopenharmony_ci * * 32462306a36Sopenharmony_ci * * <----DAI4-----> DMIC 32562306a36Sopenharmony_ci * * 32662306a36Sopenharmony_ci * * <----DAI5-----> FM 32762306a36Sopenharmony_ci ************* 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ciIn this case the PCM data is routed via the DSP. The host CPU in this use case 33062306a36Sopenharmony_ciis only used for control and can sleep during the runtime of the stream. 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ciThe host can control the hostless link either by :- 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci 1. Configuring the link as a CODEC <-> CODEC style link. In this case the link 33562306a36Sopenharmony_ci is enabled or disabled by the state of the DAPM graph. This usually means 33662306a36Sopenharmony_ci there is a mixer control that can be used to connect or disconnect the path 33762306a36Sopenharmony_ci between both DAIs. 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci 2. Hostless FE. This FE has a virtual connection to the BE DAI links on the DAPM 34062306a36Sopenharmony_ci graph. Control is then carried out by the FE as regular PCM operations. 34162306a36Sopenharmony_ci This method gives more control over the DAI links, but requires much more 34262306a36Sopenharmony_ci userspace code to control the link. Its recommended to use CODEC<->CODEC 34362306a36Sopenharmony_ci unless your HW needs more fine grained sequencing of the PCM ops. 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ciCODEC <-> CODEC link 34762306a36Sopenharmony_ci-------------------- 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ciThis DAI link is enabled when DAPM detects a valid path within the DAPM graph. 35062306a36Sopenharmony_ciThe machine driver sets some additional parameters to the DAI link i.e. 35162306a36Sopenharmony_ci:: 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci static const struct snd_soc_pcm_stream dai_params = { 35462306a36Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S32_LE, 35562306a36Sopenharmony_ci .rate_min = 8000, 35662306a36Sopenharmony_ci .rate_max = 8000, 35762306a36Sopenharmony_ci .channels_min = 2, 35862306a36Sopenharmony_ci .channels_max = 2, 35962306a36Sopenharmony_ci }; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci static struct snd_soc_dai_link dais[] = { 36262306a36Sopenharmony_ci < ... more DAI links above ... > 36362306a36Sopenharmony_ci { 36462306a36Sopenharmony_ci .name = "MODEM", 36562306a36Sopenharmony_ci .stream_name = "MODEM", 36662306a36Sopenharmony_ci .cpu_dai_name = "dai2", 36762306a36Sopenharmony_ci .codec_dai_name = "modem-aif1", 36862306a36Sopenharmony_ci .codec_name = "modem", 36962306a36Sopenharmony_ci .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 37062306a36Sopenharmony_ci | SND_SOC_DAIFMT_CBM_CFM, 37162306a36Sopenharmony_ci .params = &dai_params, 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci < ... more DAI links here ... > 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ciThese parameters are used to configure the DAI hw_params() when DAPM detects a 37662306a36Sopenharmony_civalid path and then calls the PCM operations to start the link. DAPM will also 37762306a36Sopenharmony_cicall the appropriate PCM operations to disable the DAI when the path is no 37862306a36Sopenharmony_cilonger valid. 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ciHostless FE 38262306a36Sopenharmony_ci----------- 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ciThe DAI link(s) are enabled by a FE that does not read or write any PCM data. 38562306a36Sopenharmony_ciThis means creating a new FE that is connected with a virtual path to both 38662306a36Sopenharmony_ciDAI links. The DAI links will be started when the FE PCM is started and stopped 38762306a36Sopenharmony_ciwhen the FE PCM is stopped. Note that the FE PCM cannot read or write data in 38862306a36Sopenharmony_cithis configuration. 389