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 = snd_soc_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 return 0; 37 38 ret = sdw_prepare_stream(sruntime); 39 if (ret) 40 return ret; 41 42 /** 43 * NOTE: there is a strict hw requirement about the ordering of port 44 * enables and actual WSA881x PA enable. PA enable should only happen 45 * after soundwire ports are enabled if not DC on the line is 46 * accumulated resulting in Click/Pop Noise 47 * PA enable/mute are handled as part of codec DAPM and digital mute. 48 */ 49 50 ret = sdw_enable_stream(sruntime); 51 if (ret) { 52 sdw_deprepare_stream(sruntime); 53 return ret; 54 } 55 *stream_prepared = true; 56 57 return ret; 58 } 59 EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare); 60 61 int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, 62 struct snd_pcm_hw_params *params, 63 struct sdw_stream_runtime **psruntime) 64 { 65 struct snd_soc_pcm_runtime *rtd = substream->private_data; 66 struct snd_soc_dai *codec_dai; 67 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 68 struct sdw_stream_runtime *sruntime; 69 int i; 70 71 switch (cpu_dai->id) { 72 case WSA_CODEC_DMA_RX_0: 73 case RX_CODEC_DMA_RX_0: 74 case RX_CODEC_DMA_RX_1: 75 case TX_CODEC_DMA_TX_0: 76 case TX_CODEC_DMA_TX_1: 77 case TX_CODEC_DMA_TX_2: 78 case TX_CODEC_DMA_TX_3: 79 for_each_rtd_codec_dais(rtd, i, codec_dai) { 80 sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream); 81 if (sruntime != ERR_PTR(-ENOTSUPP)) 82 *psruntime = sruntime; 83 } 84 break; 85 } 86 87 return 0; 88 89 } 90 EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params); 91 92 int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, 93 struct sdw_stream_runtime *sruntime, bool *stream_prepared) 94 { 95 struct snd_soc_pcm_runtime *rtd = substream->private_data; 96 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 97 98 switch (cpu_dai->id) { 99 case WSA_CODEC_DMA_RX_0: 100 case WSA_CODEC_DMA_RX_1: 101 case RX_CODEC_DMA_RX_0: 102 case RX_CODEC_DMA_RX_1: 103 case TX_CODEC_DMA_TX_0: 104 case TX_CODEC_DMA_TX_1: 105 case TX_CODEC_DMA_TX_2: 106 case TX_CODEC_DMA_TX_3: 107 if (sruntime && *stream_prepared) { 108 sdw_disable_stream(sruntime); 109 sdw_deprepare_stream(sruntime); 110 *stream_prepared = false; 111 } 112 break; 113 default: 114 break; 115 } 116 117 return 0; 118 } 119 EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free); 120 MODULE_LICENSE("GPL v2"); 121