@@ -112,6 +112,23 @@ static int avs_dai_hw_params(struct snd_pcm_substream *substream,
112
112
return 0 ;
113
113
}
114
114
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
+
115
132
static int avs_dai_prepare (struct avs_dev * adev , struct snd_pcm_substream * substream ,
116
133
struct snd_soc_dai * dai )
117
134
{
@@ -134,6 +151,100 @@ static int avs_dai_prepare(struct avs_dev *adev, struct snd_pcm_substream *subst
134
151
return ret ;
135
152
}
136
153
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
+
137
248
static const unsigned int rates [] = {
138
249
8000 , 11025 , 12000 , 16000 ,
139
250
22050 , 24000 , 32000 , 44100 ,
@@ -589,7 +700,6 @@ static const struct snd_soc_component_driver avs_component_driver = {
589
700
.non_legacy_dai_naming = true,
590
701
};
591
702
592
- __maybe_unused
593
703
static int avs_soc_component_register (struct device * dev , const char * name ,
594
704
const struct snd_soc_component_driver * drv ,
595
705
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,
611
721
612
722
return snd_soc_add_component (& acomp -> base , cpu_dais , num_cpu_dais );
613
723
}
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