1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2018, Linaro Limited. 3 // Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 5 #include <linux/module.h> 6 #include <sound/soc.h> 7 #include "qdsp6/q6afe.h" 8 #include "sdw.h" 9 10 int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, 11 struct sdw_stream_runtime *sruntime, 12 bool *stream_prepared) 13 { 14 struct snd_soc_pcm_runtime *rtd = substream->private_data; 15 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 16 int ret; 17 18 if (!sruntime) 19 return 0; 20 21 switch (cpu_dai->id) { 22 case WSA_CODEC_DMA_RX_0: 23 case WSA_CODEC_DMA_RX_1: 24 case RX_CODEC_DMA_RX_0: 25 case RX_CODEC_DMA_RX_1: 26 case TX_CODEC_DMA_TX_0: 27 case TX_CODEC_DMA_TX_1: 28 case TX_CODEC_DMA_TX_2: 29 case TX_CODEC_DMA_TX_3: 30 break; 31 default: 32 return 0; 33 } 34 35 if (*stream_prepared) { 36 sdw_disable_stream(sruntime); 37 sdw_deprepare_stream(sruntime); 38 *stream_prepared = false; 39 } 40 41 ret = sdw_prepare_stream(sruntime); 42 if (ret) 43 return ret; 44 45 /** 46 * NOTE: there is a strict hw requirement about the ordering of port 47 * enables and actual WSA881x PA enable. PA enable should only happen 48 * after soundwire ports are enabled if not DC on the line is 49 * accumulated resulting in Click/Pop Noise 50 * PA enable/mute are handled as part of codec DAPM and digital mute. 51 */ 52 53 ret = sdw_enable_stream(sruntime); 54 if (ret) { 55 sdw_deprepare_stream(sruntime); 56 return ret; 57 } 58 *stream_prepared = true; 59 60 return ret; 61 } 62 EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare); 63 64 int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, 65 struct snd_pcm_hw_params *params, 66 struct sdw_stream_runtime **psruntime) 67 { 68 struct snd_soc_pcm_runtime *rtd = substream->private_data; 69 struct snd_soc_dai *codec_dai; 70 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 71 struct sdw_stream_runtime *sruntime; 72 int i; 73 74 switch (cpu_dai->id) { 75 case WSA_CODEC_DMA_RX_0: 76 case RX_CODEC_DMA_RX_0: 77 case RX_CODEC_DMA_RX_1: 78 case TX_CODEC_DMA_TX_0: 79 case TX_CODEC_DMA_TX_1: 80 case TX_CODEC_DMA_TX_2: 81 case TX_CODEC_DMA_TX_3: 82 for_each_rtd_codec_dais(rtd, i, codec_dai) { 83 sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream); 84 if (sruntime != ERR_PTR(-ENOTSUPP)) 85 *psruntime = sruntime; 86 } 87 break; 88 } 89 90 return 0; 91 92 } 93 EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params); 94 95 int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, 96 struct sdw_stream_runtime *sruntime, bool *stream_prepared) 97 { 98 struct snd_soc_pcm_runtime *rtd = substream->private_data; 99 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 100 101 switch (cpu_dai->id) { 102 case WSA_CODEC_DMA_RX_0: 103 case WSA_CODEC_DMA_RX_1: 104 case RX_CODEC_DMA_RX_0: 105 case RX_CODEC_DMA_RX_1: 106 case TX_CODEC_DMA_TX_0: 107 case TX_CODEC_DMA_TX_1: 108 case TX_CODEC_DMA_TX_2: 109 case TX_CODEC_DMA_TX_3: 110 if (sruntime && *stream_prepared) { 111 sdw_disable_stream(sruntime); 112 sdw_deprepare_stream(sruntime); 113 *stream_prepared = false; 114 } 115 break; 116 default: 117 break; 118 } 119 120 return 0; 121 } 122 EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free); 123 MODULE_LICENSE("GPL v2"); 124