1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2018-2023, Linaro Limited.
3 // Copyright (c) 2018, The Linux Foundation. All rights reserved.
5 #include <dt-bindings/sound/qcom,q6afe.h>
6 #include <linux/module.h>
11 * qcom_snd_sdw_startup() - Helper to start Soundwire stream for SoC audio card
12 * @substream: The PCM substream from audio, as passed to snd_soc_ops->startup()
14 * Helper for the SoC audio card (snd_soc_ops->startup()) to allocate and set
15 * Soundwire stream runtime to each codec DAI.
17 * The shutdown() callback should call sdw_release_stream() on the same
22 int qcom_snd_sdw_startup(struct snd_pcm_substream *substream)
24 struct snd_soc_pcm_runtime *rtd = substream->private_data;
25 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
26 struct sdw_stream_runtime *sruntime;
27 struct snd_soc_dai *codec_dai;
30 sruntime = sdw_alloc_stream(cpu_dai->name);
34 for_each_rtd_codec_dais(rtd, i, codec_dai) {
35 ret = snd_soc_dai_set_stream(codec_dai, sruntime,
37 if (ret < 0 && ret != -ENOTSUPP) {
38 dev_err(rtd->dev, "Failed to set sdw stream on %s\n",
47 sdw_release_stream(sruntime);
51 EXPORT_SYMBOL_GPL(qcom_snd_sdw_startup);
53 int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
54 struct sdw_stream_runtime *sruntime,
55 bool *stream_prepared)
57 struct snd_soc_pcm_runtime *rtd = substream->private_data;
58 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
64 switch (cpu_dai->id) {
65 case WSA_CODEC_DMA_RX_0:
66 case WSA_CODEC_DMA_RX_1:
67 case RX_CODEC_DMA_RX_0:
68 case RX_CODEC_DMA_RX_1:
69 case TX_CODEC_DMA_TX_0:
70 case TX_CODEC_DMA_TX_1:
71 case TX_CODEC_DMA_TX_2:
72 case TX_CODEC_DMA_TX_3:
81 ret = sdw_prepare_stream(sruntime);
86 * NOTE: there is a strict hw requirement about the ordering of port
87 * enables and actual WSA881x PA enable. PA enable should only happen
88 * after soundwire ports are enabled if not DC on the line is
89 * accumulated resulting in Click/Pop Noise
90 * PA enable/mute are handled as part of codec DAPM and digital mute.
93 ret = sdw_enable_stream(sruntime);
95 sdw_deprepare_stream(sruntime);
98 *stream_prepared = true;
102 EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare);
104 int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
105 struct snd_pcm_hw_params *params,
106 struct sdw_stream_runtime **psruntime)
108 struct snd_soc_pcm_runtime *rtd = substream->private_data;
109 struct snd_soc_dai *codec_dai;
110 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
111 struct sdw_stream_runtime *sruntime;
114 switch (cpu_dai->id) {
115 case WSA_CODEC_DMA_RX_0:
116 case RX_CODEC_DMA_RX_0:
117 case RX_CODEC_DMA_RX_1:
118 case TX_CODEC_DMA_TX_0:
119 case TX_CODEC_DMA_TX_1:
120 case TX_CODEC_DMA_TX_2:
121 case TX_CODEC_DMA_TX_3:
122 for_each_rtd_codec_dais(rtd, i, codec_dai) {
123 sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
124 if (sruntime != ERR_PTR(-ENOTSUPP))
125 *psruntime = sruntime;
133 EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params);
135 int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
136 struct sdw_stream_runtime *sruntime, bool *stream_prepared)
138 struct snd_soc_pcm_runtime *rtd = substream->private_data;
139 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
141 switch (cpu_dai->id) {
142 case WSA_CODEC_DMA_RX_0:
143 case WSA_CODEC_DMA_RX_1:
144 case RX_CODEC_DMA_RX_0:
145 case RX_CODEC_DMA_RX_1:
146 case TX_CODEC_DMA_TX_0:
147 case TX_CODEC_DMA_TX_1:
148 case TX_CODEC_DMA_TX_2:
149 case TX_CODEC_DMA_TX_3:
150 if (sruntime && *stream_prepared) {
151 sdw_disable_stream(sruntime);
152 sdw_deprepare_stream(sruntime);
153 *stream_prepared = false;
162 EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free);
163 MODULE_LICENSE("GPL");