@@ -245,6 +245,155 @@ static const struct snd_soc_dai_ops avs_dai_nonhda_be_ops = {
245
245
.trigger = avs_dai_nonhda_be_trigger ,
246
246
};
247
247
248
+ static int avs_dai_hda_be_startup (struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
249
+ {
250
+ return avs_dai_startup (substream , dai , false);
251
+ }
252
+
253
+ static void avs_dai_hda_be_shutdown (struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
254
+ {
255
+ return avs_dai_nonhda_be_shutdown (substream , dai );
256
+ }
257
+
258
+ static int avs_dai_hda_be_hw_params (struct snd_pcm_substream * substream ,
259
+ struct snd_pcm_hw_params * hw_params , struct snd_soc_dai * dai )
260
+ {
261
+ struct avs_dma_data * data ;
262
+ struct hdac_ext_stream * link_stream ;
263
+
264
+ data = snd_soc_dai_get_dma_data (dai , substream );
265
+ if (data -> path )
266
+ return 0 ;
267
+
268
+ link_stream = substream -> runtime -> private_data ;
269
+
270
+ return avs_dai_be_hw_params (substream , hw_params , dai ,
271
+ hdac_stream (link_stream )-> stream_tag - 1 );
272
+ }
273
+
274
+ static int avs_dai_hda_be_hw_free (struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
275
+ {
276
+ struct avs_dma_data * data ;
277
+ struct snd_soc_pcm_runtime * rtd = snd_pcm_substream_chip (substream );
278
+ struct hdac_ext_stream * link_stream ;
279
+ struct hdac_ext_link * link ;
280
+ struct hda_codec * codec ;
281
+
282
+ dev_dbg (dai -> dev , "%s: %s\n" , __func__ , dai -> name );
283
+
284
+ data = snd_soc_dai_get_dma_data (dai , substream );
285
+ if (!data -> path )
286
+ return 0 ;
287
+
288
+ link_stream = substream -> runtime -> private_data ;
289
+ link_stream -> link_prepared = false;
290
+ avs_path_free (data -> path );
291
+ data -> path = NULL ;
292
+
293
+ /* clear link <-> stream mapping */
294
+ codec = dev_to_hda_codec (asoc_rtd_to_codec (rtd , 0 )-> dev );
295
+ link = snd_hdac_ext_bus_link_at (& codec -> bus -> core , codec -> core .addr );
296
+ if (!link )
297
+ return - EINVAL ;
298
+
299
+ if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK )
300
+ snd_hdac_ext_link_clear_stream_id (link , hdac_stream (link_stream )-> stream_tag );
301
+
302
+ return 0 ;
303
+ }
304
+
305
+ static int avs_dai_hda_be_prepare (struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
306
+ {
307
+ struct snd_soc_pcm_runtime * rtd = snd_pcm_substream_chip (substream );
308
+ struct snd_pcm_runtime * runtime = substream -> runtime ;
309
+ struct hdac_ext_stream * link_stream = runtime -> private_data ;
310
+ struct hdac_ext_link * link ;
311
+ struct hda_codec * codec ;
312
+ struct hdac_bus * bus ;
313
+ unsigned int format_val ;
314
+ int ret ;
315
+
316
+ if (link_stream -> link_prepared )
317
+ return 0 ;
318
+
319
+ codec = dev_to_hda_codec (asoc_rtd_to_codec (rtd , 0 )-> dev );
320
+ bus = & codec -> bus -> core ;
321
+ format_val = snd_hdac_calc_stream_format (runtime -> rate , runtime -> channels , runtime -> format ,
322
+ runtime -> sample_bits , 0 );
323
+
324
+ snd_hdac_ext_stream_decouple (bus , link_stream , true);
325
+ snd_hdac_ext_link_stream_reset (link_stream );
326
+ snd_hdac_ext_link_stream_setup (link_stream , format_val );
327
+
328
+ link = snd_hdac_ext_bus_link_at (bus , codec -> core .addr );
329
+ if (!link )
330
+ return - EINVAL ;
331
+
332
+ if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK )
333
+ snd_hdac_ext_link_set_stream_id (link , hdac_stream (link_stream )-> stream_tag );
334
+
335
+ ret = avs_dai_prepare (to_avs_dev (dai -> dev ), substream , dai );
336
+ if (ret )
337
+ return ret ;
338
+
339
+ link_stream -> link_prepared = true;
340
+ return 0 ;
341
+ }
342
+
343
+ static int avs_dai_hda_be_trigger (struct snd_pcm_substream * substream , int cmd ,
344
+ struct snd_soc_dai * dai )
345
+ {
346
+ struct hdac_ext_stream * link_stream ;
347
+ struct avs_dma_data * data ;
348
+ int ret = 0 ;
349
+
350
+ dev_dbg (dai -> dev , "entry %s cmd=%d\n" , __func__ , cmd );
351
+
352
+ data = snd_soc_dai_get_dma_data (dai , substream );
353
+ link_stream = substream -> runtime -> private_data ;
354
+
355
+ switch (cmd ) {
356
+ case SNDRV_PCM_TRIGGER_START :
357
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
358
+ snd_hdac_ext_link_stream_start (link_stream );
359
+
360
+ ret = avs_path_run (data -> path , AVS_TPLG_TRIGGER_AUTO );
361
+ if (ret < 0 )
362
+ dev_err (dai -> dev , "run BE path failed: %d\n" , ret );
363
+ break ;
364
+
365
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH :
366
+ case SNDRV_PCM_TRIGGER_STOP :
367
+ ret = avs_path_pause (data -> path );
368
+ if (ret < 0 )
369
+ dev_err (dai -> dev , "pause BE path failed: %d\n" , ret );
370
+
371
+ snd_hdac_ext_link_stream_clear (link_stream );
372
+
373
+ if (cmd == SNDRV_PCM_TRIGGER_STOP ) {
374
+ ret = avs_path_reset (data -> path );
375
+ if (ret < 0 )
376
+ dev_err (dai -> dev , "reset BE path failed: %d\n" , ret );
377
+ }
378
+ break ;
379
+
380
+ default :
381
+ ret = - EINVAL ;
382
+ break ;
383
+ }
384
+
385
+ return ret ;
386
+ }
387
+
388
+ static const struct snd_soc_dai_ops avs_dai_hda_be_ops = {
389
+ .startup = avs_dai_hda_be_startup ,
390
+ .shutdown = avs_dai_hda_be_shutdown ,
391
+ .hw_params = avs_dai_hda_be_hw_params ,
392
+ .hw_free = avs_dai_hda_be_hw_free ,
393
+ .prepare = avs_dai_hda_be_prepare ,
394
+ .trigger = avs_dai_hda_be_trigger ,
395
+ };
396
+
248
397
static const unsigned int rates [] = {
249
398
8000 , 11025 , 12000 , 16000 ,
250
399
22050 , 24000 , 32000 , 44100 ,
@@ -831,3 +980,203 @@ int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned l
831
980
plat_register :
832
981
return avs_soc_component_register (adev -> dev , name , & avs_component_driver , cpus , cpu_count );
833
982
}
983
+
984
+ /* HD-Audio CPU DAI template */
985
+ static const struct snd_soc_dai_driver hda_cpu_dai = {
986
+ .ops = & avs_dai_hda_be_ops ,
987
+ .playback = {
988
+ .channels_min = 1 ,
989
+ .channels_max = 8 ,
990
+ .rates = SNDRV_PCM_RATE_8000_192000 ,
991
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
992
+ SNDRV_PCM_FMTBIT_S24_LE |
993
+ SNDRV_PCM_FMTBIT_S32_LE ,
994
+ },
995
+ .capture = {
996
+ .channels_min = 1 ,
997
+ .channels_max = 8 ,
998
+ .rates = SNDRV_PCM_RATE_8000_192000 ,
999
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
1000
+ SNDRV_PCM_FMTBIT_S24_LE |
1001
+ SNDRV_PCM_FMTBIT_S32_LE ,
1002
+ },
1003
+ };
1004
+
1005
+ static void avs_component_hda_unregister_dais (struct snd_soc_component * component )
1006
+ {
1007
+ struct snd_soc_acpi_mach * mach ;
1008
+ struct snd_soc_dai * dai , * save ;
1009
+ struct hda_codec * codec ;
1010
+ char name [32 ];
1011
+
1012
+ mach = dev_get_platdata (component -> card -> dev );
1013
+ codec = mach -> pdata ;
1014
+ sprintf (name , "%s-cpu" , dev_name (& codec -> core .dev ));
1015
+
1016
+ for_each_component_dais_safe (component , dai , save ) {
1017
+ if (!strstr (dai -> driver -> name , name ))
1018
+ continue ;
1019
+
1020
+ if (dai -> playback_widget )
1021
+ snd_soc_dapm_free_widget (dai -> playback_widget );
1022
+ if (dai -> capture_widget )
1023
+ snd_soc_dapm_free_widget (dai -> capture_widget );
1024
+ snd_soc_unregister_dai (dai );
1025
+ }
1026
+ }
1027
+
1028
+ static int avs_component_hda_probe (struct snd_soc_component * component )
1029
+ {
1030
+ struct snd_soc_dapm_context * dapm ;
1031
+ struct snd_soc_dai_driver * dais ;
1032
+ struct snd_soc_acpi_mach * mach ;
1033
+ struct hda_codec * codec ;
1034
+ struct hda_pcm * pcm ;
1035
+ const char * cname ;
1036
+ int pcm_count = 0 , ret , i ;
1037
+
1038
+ mach = dev_get_platdata (component -> card -> dev );
1039
+ if (!mach )
1040
+ return - EINVAL ;
1041
+
1042
+ codec = mach -> pdata ;
1043
+ if (list_empty (& codec -> pcm_list_head ))
1044
+ return - EINVAL ;
1045
+ list_for_each_entry (pcm , & codec -> pcm_list_head , list )
1046
+ pcm_count ++ ;
1047
+
1048
+ dais = devm_kcalloc (component -> dev , pcm_count , sizeof (* dais ),
1049
+ GFP_KERNEL );
1050
+ if (!dais )
1051
+ return - ENOMEM ;
1052
+
1053
+ cname = dev_name (& codec -> core .dev );
1054
+ dapm = snd_soc_component_get_dapm (component );
1055
+ pcm = list_first_entry (& codec -> pcm_list_head , struct hda_pcm , list );
1056
+
1057
+ for (i = 0 ; i < pcm_count ; i ++ , pcm = list_next_entry (pcm , list )) {
1058
+ struct snd_soc_dai * dai ;
1059
+
1060
+ memcpy (& dais [i ], & hda_cpu_dai , sizeof (* dais ));
1061
+ dais [i ].id = i ;
1062
+ dais [i ].name = devm_kasprintf (component -> dev , GFP_KERNEL ,
1063
+ "%s-cpu%d" , cname , i );
1064
+ if (!dais [i ].name ) {
1065
+ ret = - ENOMEM ;
1066
+ goto exit ;
1067
+ }
1068
+
1069
+ if (pcm -> stream [0 ].substreams ) {
1070
+ dais [i ].playback .stream_name =
1071
+ devm_kasprintf (component -> dev , GFP_KERNEL ,
1072
+ "%s-cpu%d Tx" , cname , i );
1073
+ if (!dais [i ].playback .stream_name ) {
1074
+ ret = - ENOMEM ;
1075
+ goto exit ;
1076
+ }
1077
+ }
1078
+
1079
+ if (pcm -> stream [1 ].substreams ) {
1080
+ dais [i ].capture .stream_name =
1081
+ devm_kasprintf (component -> dev , GFP_KERNEL ,
1082
+ "%s-cpu%d Rx" , cname , i );
1083
+ if (!dais [i ].capture .stream_name ) {
1084
+ ret = - ENOMEM ;
1085
+ goto exit ;
1086
+ }
1087
+ }
1088
+
1089
+ dai = snd_soc_register_dai (component , & dais [i ], false);
1090
+ if (!dai ) {
1091
+ dev_err (component -> dev , "register dai for %s failed\n" ,
1092
+ pcm -> name );
1093
+ ret = - EINVAL ;
1094
+ goto exit ;
1095
+ }
1096
+
1097
+ ret = snd_soc_dapm_new_dai_widgets (dapm , dai );
1098
+ if (ret < 0 ) {
1099
+ dev_err (component -> dev , "create widgets failed: %d\n" ,
1100
+ ret );
1101
+ goto exit ;
1102
+ }
1103
+ }
1104
+
1105
+ ret = avs_component_probe (component );
1106
+ exit :
1107
+ if (ret )
1108
+ avs_component_hda_unregister_dais (component );
1109
+
1110
+ return ret ;
1111
+ }
1112
+
1113
+ static void avs_component_hda_remove (struct snd_soc_component * component )
1114
+ {
1115
+ avs_component_hda_unregister_dais (component );
1116
+ avs_component_remove (component );
1117
+ }
1118
+
1119
+ static int avs_component_hda_open (struct snd_soc_component * component ,
1120
+ struct snd_pcm_substream * substream )
1121
+ {
1122
+ struct snd_soc_pcm_runtime * rtd = snd_pcm_substream_chip (substream );
1123
+ struct hdac_ext_stream * link_stream ;
1124
+ struct hda_codec * codec ;
1125
+
1126
+ /* only BE DAI links are handled here */
1127
+ if (!rtd -> dai_link -> no_pcm )
1128
+ return avs_component_open (component , substream );
1129
+
1130
+ codec = dev_to_hda_codec (asoc_rtd_to_codec (rtd , 0 )-> dev );
1131
+ link_stream = snd_hdac_ext_stream_assign (& codec -> bus -> core , substream ,
1132
+ HDAC_EXT_STREAM_TYPE_LINK );
1133
+ if (!link_stream )
1134
+ return - EBUSY ;
1135
+
1136
+ substream -> runtime -> private_data = link_stream ;
1137
+ return 0 ;
1138
+ }
1139
+
1140
+ static int avs_component_hda_close (struct snd_soc_component * component ,
1141
+ struct snd_pcm_substream * substream )
1142
+ {
1143
+ struct snd_soc_pcm_runtime * rtd = snd_pcm_substream_chip (substream );
1144
+ struct hdac_ext_stream * link_stream ;
1145
+
1146
+ /* only BE DAI links are handled here */
1147
+ if (!rtd -> dai_link -> no_pcm )
1148
+ return 0 ;
1149
+
1150
+ link_stream = substream -> runtime -> private_data ;
1151
+ snd_hdac_ext_stream_release (link_stream , HDAC_EXT_STREAM_TYPE_LINK );
1152
+ substream -> runtime -> private_data = NULL ;
1153
+
1154
+ return 0 ;
1155
+ }
1156
+
1157
+ static const struct snd_soc_component_driver avs_hda_component_driver = {
1158
+ .name = "avs-hda-pcm" ,
1159
+ .probe = avs_component_hda_probe ,
1160
+ .remove = avs_component_hda_remove ,
1161
+ .open = avs_component_hda_open ,
1162
+ .close = avs_component_hda_close ,
1163
+ .pointer = avs_component_pointer ,
1164
+ .mmap = avs_component_mmap ,
1165
+ .pcm_construct = avs_component_construct ,
1166
+ /*
1167
+ * hda platform component's probe() is dependent on
1168
+ * codec->pcm_list_head, it needs to be initialized after codec
1169
+ * component. remove_order is here for completeness sake
1170
+ */
1171
+ .probe_order = SND_SOC_COMP_ORDER_LATE ,
1172
+ .remove_order = SND_SOC_COMP_ORDER_EARLY ,
1173
+ .module_get_upon_open = 1 ,
1174
+ .topology_name_prefix = "intel/avs" ,
1175
+ .non_legacy_dai_naming = true,
1176
+ };
1177
+
1178
+ int avs_hda_platform_register (struct avs_dev * adev , const char * name )
1179
+ {
1180
+ return avs_soc_component_register (adev -> dev , name ,
1181
+ & avs_hda_component_driver , NULL , 0 );
1182
+ }
0 commit comments