@@ -112,6 +112,23 @@ static int avs_dai_hw_params(struct snd_pcm_substream *substream,
112112 return 0 ;
113113}
114114
115+ static int avs_dai_be_hw_params (struct snd_pcm_substream * substream ,
116+ struct snd_pcm_hw_params * be_hw_params , struct snd_soc_dai * dai ,
117+ int dma_id )
118+ {
119+ struct snd_pcm_hw_params * fe_hw_params = NULL ;
120+ struct snd_soc_pcm_runtime * fe , * be ;
121+ struct snd_soc_dpcm * dpcm ;
122+
123+ be = asoc_substream_to_rtd (substream );
124+ for_each_dpcm_fe (be , substream -> stream , dpcm ) {
125+ fe = dpcm -> fe ;
126+ fe_hw_params = & fe -> dpcm [substream -> stream ].hw_params ;
127+ }
128+
129+ return avs_dai_hw_params (substream , fe_hw_params , be_hw_params , dai , dma_id );
130+ }
131+
115132static int avs_dai_prepare (struct avs_dev * adev , struct snd_pcm_substream * substream ,
116133 struct snd_soc_dai * dai )
117134{
@@ -134,6 +151,100 @@ static int avs_dai_prepare(struct avs_dev *adev, struct snd_pcm_substream *subst
134151 return ret ;
135152}
136153
154+ static int avs_dai_nonhda_be_startup (struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
155+ {
156+ return avs_dai_startup (substream , dai , false);
157+ }
158+
159+ static void avs_dai_nonhda_be_shutdown (struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
160+ {
161+ struct avs_dma_data * data ;
162+
163+ data = snd_soc_dai_get_dma_data (dai , substream );
164+
165+ snd_soc_dai_set_dma_data (dai , substream , NULL );
166+ kfree (data );
167+ }
168+
169+ static int avs_dai_nonhda_be_hw_params (struct snd_pcm_substream * substream ,
170+ struct snd_pcm_hw_params * hw_params , struct snd_soc_dai * dai )
171+ {
172+ struct avs_dma_data * data ;
173+
174+ data = snd_soc_dai_get_dma_data (dai , substream );
175+ if (data -> path )
176+ return 0 ;
177+
178+ /* Actual port-id comes from topology. */
179+ return avs_dai_be_hw_params (substream , hw_params , dai , 0 );
180+ }
181+
182+ static int avs_dai_nonhda_be_hw_free (struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
183+ {
184+ struct avs_dma_data * data ;
185+
186+ dev_dbg (dai -> dev , "%s: %s\n" , __func__ , dai -> name );
187+
188+ data = snd_soc_dai_get_dma_data (dai , substream );
189+ if (data -> path ) {
190+ avs_path_free (data -> path );
191+ data -> path = NULL ;
192+ }
193+
194+ return 0 ;
195+ }
196+
197+ static int avs_dai_nonhda_be_prepare (struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
198+ {
199+ return avs_dai_prepare (to_avs_dev (dai -> dev ), substream , dai );
200+ }
201+
202+ static int avs_dai_nonhda_be_trigger (struct snd_pcm_substream * substream , int cmd ,
203+ struct snd_soc_dai * dai )
204+ {
205+ struct avs_dma_data * data ;
206+ int ret = 0 ;
207+
208+ data = snd_soc_dai_get_dma_data (dai , substream );
209+
210+ switch (cmd ) {
211+ case SNDRV_PCM_TRIGGER_START :
212+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
213+ ret = avs_path_run (data -> path , AVS_TPLG_TRIGGER_AUTO );
214+ if (ret < 0 )
215+ dev_err (dai -> dev , "run BE path failed: %d\n" , ret );
216+ break ;
217+
218+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH :
219+ case SNDRV_PCM_TRIGGER_STOP :
220+ ret = avs_path_pause (data -> path );
221+ if (ret < 0 )
222+ dev_err (dai -> dev , "pause BE path failed: %d\n" , ret );
223+
224+ if (cmd == SNDRV_PCM_TRIGGER_STOP ) {
225+ ret = avs_path_reset (data -> path );
226+ if (ret < 0 )
227+ dev_err (dai -> dev , "reset BE path failed: %d\n" , ret );
228+ }
229+ break ;
230+
231+ default :
232+ ret = - EINVAL ;
233+ break ;
234+ }
235+
236+ return ret ;
237+ }
238+
239+ static const struct snd_soc_dai_ops avs_dai_nonhda_be_ops = {
240+ .startup = avs_dai_nonhda_be_startup ,
241+ .shutdown = avs_dai_nonhda_be_shutdown ,
242+ .hw_params = avs_dai_nonhda_be_hw_params ,
243+ .hw_free = avs_dai_nonhda_be_hw_free ,
244+ .prepare = avs_dai_nonhda_be_prepare ,
245+ .trigger = avs_dai_nonhda_be_trigger ,
246+ };
247+
137248static const unsigned int rates [] = {
138249 8000 , 11025 , 12000 , 16000 ,
139250 22050 , 24000 , 32000 , 44100 ,
@@ -589,7 +700,6 @@ static const struct snd_soc_component_driver avs_component_driver = {
589700 .non_legacy_dai_naming = true,
590701};
591702
592- __maybe_unused
593703static int avs_soc_component_register (struct device * dev , const char * name ,
594704 const struct snd_soc_component_driver * drv ,
595705 struct snd_soc_dai_driver * cpu_dais , int num_cpu_dais )
@@ -611,3 +721,113 @@ static int avs_soc_component_register(struct device *dev, const char *name,
611721
612722 return snd_soc_add_component (& acomp -> base , cpu_dais , num_cpu_dais );
613723}
724+
725+ static struct snd_soc_dai_driver dmic_cpu_dais [] = {
726+ {
727+ .name = "DMIC Pin" ,
728+ .ops = & avs_dai_nonhda_be_ops ,
729+ .capture = {
730+ .stream_name = "DMIC Rx" ,
731+ .channels_min = 1 ,
732+ .channels_max = 4 ,
733+ .rates = SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_48000 ,
734+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE ,
735+ },
736+ },
737+ {
738+ .name = "DMIC WoV Pin" ,
739+ .ops = & avs_dai_nonhda_be_ops ,
740+ .capture = {
741+ .stream_name = "DMIC WoV Rx" ,
742+ .channels_min = 1 ,
743+ .channels_max = 4 ,
744+ .rates = SNDRV_PCM_RATE_16000 ,
745+ .formats = SNDRV_PCM_FMTBIT_S16_LE ,
746+ },
747+ },
748+ };
749+
750+ int avs_dmic_platform_register (struct avs_dev * adev , const char * name )
751+ {
752+ return avs_soc_component_register (adev -> dev , name , & avs_component_driver , dmic_cpu_dais ,
753+ ARRAY_SIZE (dmic_cpu_dais ));
754+ }
755+
756+ static const struct snd_soc_dai_driver i2s_dai_template = {
757+ .ops = & avs_dai_nonhda_be_ops ,
758+ .playback = {
759+ .channels_min = 1 ,
760+ .channels_max = 8 ,
761+ .rates = SNDRV_PCM_RATE_8000_192000 |
762+ SNDRV_PCM_RATE_KNOT ,
763+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
764+ SNDRV_PCM_FMTBIT_S24_LE |
765+ SNDRV_PCM_FMTBIT_S32_LE ,
766+ },
767+ .capture = {
768+ .channels_min = 1 ,
769+ .channels_max = 8 ,
770+ .rates = SNDRV_PCM_RATE_8000_192000 |
771+ SNDRV_PCM_RATE_KNOT ,
772+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
773+ SNDRV_PCM_FMTBIT_S24_LE |
774+ SNDRV_PCM_FMTBIT_S32_LE ,
775+ },
776+ };
777+
778+ int avs_i2s_platform_register (struct avs_dev * adev , const char * name , unsigned long port_mask ,
779+ unsigned long * tdms )
780+ {
781+ struct snd_soc_dai_driver * cpus , * dai ;
782+ size_t ssp_count , cpu_count ;
783+ int i , j ;
784+
785+ ssp_count = adev -> hw_cfg .i2s_caps .ctrl_count ;
786+ cpu_count = hweight_long (port_mask );
787+ if (tdms )
788+ for_each_set_bit (i , & port_mask , ssp_count )
789+ cpu_count += hweight_long (tdms [i ]);
790+
791+ cpus = devm_kzalloc (adev -> dev , sizeof (* cpus ) * cpu_count , GFP_KERNEL );
792+ if (!cpus )
793+ return - ENOMEM ;
794+
795+ dai = cpus ;
796+ for_each_set_bit (i , & port_mask , ssp_count ) {
797+ memcpy (dai , & i2s_dai_template , sizeof (* dai ));
798+
799+ dai -> name =
800+ devm_kasprintf (adev -> dev , GFP_KERNEL , "SSP%d Pin" , i );
801+ dai -> playback .stream_name =
802+ devm_kasprintf (adev -> dev , GFP_KERNEL , "ssp%d Tx" , i );
803+ dai -> capture .stream_name =
804+ devm_kasprintf (adev -> dev , GFP_KERNEL , "ssp%d Rx" , i );
805+
806+ if (!dai -> name || !dai -> playback .stream_name || !dai -> capture .stream_name )
807+ return - ENOMEM ;
808+ dai ++ ;
809+ }
810+
811+ if (!tdms )
812+ goto plat_register ;
813+
814+ for_each_set_bit (i , & port_mask , ssp_count ) {
815+ for_each_set_bit (j , & tdms [i ], ssp_count ) {
816+ memcpy (dai , & i2s_dai_template , sizeof (* dai ));
817+
818+ dai -> name =
819+ devm_kasprintf (adev -> dev , GFP_KERNEL , "SSP%d:%d Pin" , i , j );
820+ dai -> playback .stream_name =
821+ devm_kasprintf (adev -> dev , GFP_KERNEL , "ssp%d:%d Tx" , i , j );
822+ dai -> capture .stream_name =
823+ devm_kasprintf (adev -> dev , GFP_KERNEL , "ssp%d:%d Rx" , i , j );
824+
825+ if (!dai -> name || !dai -> playback .stream_name || !dai -> capture .stream_name )
826+ return - ENOMEM ;
827+ dai ++ ;
828+ }
829+ }
830+
831+ plat_register :
832+ return avs_soc_component_register (adev -> dev , name , & avs_component_driver , cpus , cpu_count );
833+ }
0 commit comments