10cbf1ecdSStephan Gerhold // SPDX-License-Identifier: GPL-2.0
20cbf1ecdSStephan Gerhold // Copyright (c) 2018, Linaro Limited.
30cbf1ecdSStephan Gerhold // Copyright (c) 2018, The Linux Foundation. All rights reserved.
40cbf1ecdSStephan Gerhold
50cbf1ecdSStephan Gerhold #include <linux/module.h>
60cbf1ecdSStephan Gerhold #include <sound/soc.h>
70cbf1ecdSStephan Gerhold #include "qdsp6/q6afe.h"
80cbf1ecdSStephan Gerhold #include "sdw.h"
90cbf1ecdSStephan Gerhold
qcom_snd_sdw_prepare(struct snd_pcm_substream * substream,struct sdw_stream_runtime * sruntime,bool * stream_prepared)100cbf1ecdSStephan Gerhold int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
110cbf1ecdSStephan Gerhold struct sdw_stream_runtime *sruntime,
120cbf1ecdSStephan Gerhold bool *stream_prepared)
130cbf1ecdSStephan Gerhold {
140cbf1ecdSStephan Gerhold struct snd_soc_pcm_runtime *rtd = substream->private_data;
15*841361d8SKuninori Morimoto struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
160cbf1ecdSStephan Gerhold int ret;
170cbf1ecdSStephan Gerhold
180cbf1ecdSStephan Gerhold if (!sruntime)
190cbf1ecdSStephan Gerhold return 0;
200cbf1ecdSStephan Gerhold
210cbf1ecdSStephan Gerhold switch (cpu_dai->id) {
220cbf1ecdSStephan Gerhold case WSA_CODEC_DMA_RX_0:
230cbf1ecdSStephan Gerhold case WSA_CODEC_DMA_RX_1:
240cbf1ecdSStephan Gerhold case RX_CODEC_DMA_RX_0:
250cbf1ecdSStephan Gerhold case RX_CODEC_DMA_RX_1:
260cbf1ecdSStephan Gerhold case TX_CODEC_DMA_TX_0:
270cbf1ecdSStephan Gerhold case TX_CODEC_DMA_TX_1:
280cbf1ecdSStephan Gerhold case TX_CODEC_DMA_TX_2:
290cbf1ecdSStephan Gerhold case TX_CODEC_DMA_TX_3:
300cbf1ecdSStephan Gerhold break;
310cbf1ecdSStephan Gerhold default:
320cbf1ecdSStephan Gerhold return 0;
330cbf1ecdSStephan Gerhold }
340cbf1ecdSStephan Gerhold
35e2e53088SSrinivas Kandagatla if (*stream_prepared)
36e2e53088SSrinivas Kandagatla return 0;
370cbf1ecdSStephan Gerhold
380cbf1ecdSStephan Gerhold ret = sdw_prepare_stream(sruntime);
390cbf1ecdSStephan Gerhold if (ret)
400cbf1ecdSStephan Gerhold return ret;
410cbf1ecdSStephan Gerhold
420cbf1ecdSStephan Gerhold /**
430cbf1ecdSStephan Gerhold * NOTE: there is a strict hw requirement about the ordering of port
440cbf1ecdSStephan Gerhold * enables and actual WSA881x PA enable. PA enable should only happen
450cbf1ecdSStephan Gerhold * after soundwire ports are enabled if not DC on the line is
460cbf1ecdSStephan Gerhold * accumulated resulting in Click/Pop Noise
470cbf1ecdSStephan Gerhold * PA enable/mute are handled as part of codec DAPM and digital mute.
480cbf1ecdSStephan Gerhold */
490cbf1ecdSStephan Gerhold
500cbf1ecdSStephan Gerhold ret = sdw_enable_stream(sruntime);
510cbf1ecdSStephan Gerhold if (ret) {
520cbf1ecdSStephan Gerhold sdw_deprepare_stream(sruntime);
530cbf1ecdSStephan Gerhold return ret;
540cbf1ecdSStephan Gerhold }
550cbf1ecdSStephan Gerhold *stream_prepared = true;
560cbf1ecdSStephan Gerhold
570cbf1ecdSStephan Gerhold return ret;
580cbf1ecdSStephan Gerhold }
590cbf1ecdSStephan Gerhold EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare);
600cbf1ecdSStephan Gerhold
qcom_snd_sdw_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct sdw_stream_runtime ** psruntime)610cbf1ecdSStephan Gerhold int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
620cbf1ecdSStephan Gerhold struct snd_pcm_hw_params *params,
630cbf1ecdSStephan Gerhold struct sdw_stream_runtime **psruntime)
640cbf1ecdSStephan Gerhold {
650cbf1ecdSStephan Gerhold struct snd_soc_pcm_runtime *rtd = substream->private_data;
660cbf1ecdSStephan Gerhold struct snd_soc_dai *codec_dai;
67*841361d8SKuninori Morimoto struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
680cbf1ecdSStephan Gerhold struct sdw_stream_runtime *sruntime;
690cbf1ecdSStephan Gerhold int i;
700cbf1ecdSStephan Gerhold
710cbf1ecdSStephan Gerhold switch (cpu_dai->id) {
720cbf1ecdSStephan Gerhold case WSA_CODEC_DMA_RX_0:
730cbf1ecdSStephan Gerhold case RX_CODEC_DMA_RX_0:
740cbf1ecdSStephan Gerhold case RX_CODEC_DMA_RX_1:
750cbf1ecdSStephan Gerhold case TX_CODEC_DMA_TX_0:
760cbf1ecdSStephan Gerhold case TX_CODEC_DMA_TX_1:
770cbf1ecdSStephan Gerhold case TX_CODEC_DMA_TX_2:
780cbf1ecdSStephan Gerhold case TX_CODEC_DMA_TX_3:
790cbf1ecdSStephan Gerhold for_each_rtd_codec_dais(rtd, i, codec_dai) {
800cbf1ecdSStephan Gerhold sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
810cbf1ecdSStephan Gerhold if (sruntime != ERR_PTR(-ENOTSUPP))
820cbf1ecdSStephan Gerhold *psruntime = sruntime;
830cbf1ecdSStephan Gerhold }
840cbf1ecdSStephan Gerhold break;
850cbf1ecdSStephan Gerhold }
860cbf1ecdSStephan Gerhold
870cbf1ecdSStephan Gerhold return 0;
880cbf1ecdSStephan Gerhold
890cbf1ecdSStephan Gerhold }
900cbf1ecdSStephan Gerhold EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params);
910cbf1ecdSStephan Gerhold
qcom_snd_sdw_hw_free(struct snd_pcm_substream * substream,struct sdw_stream_runtime * sruntime,bool * stream_prepared)920cbf1ecdSStephan Gerhold int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
930cbf1ecdSStephan Gerhold struct sdw_stream_runtime *sruntime, bool *stream_prepared)
940cbf1ecdSStephan Gerhold {
950cbf1ecdSStephan Gerhold struct snd_soc_pcm_runtime *rtd = substream->private_data;
96*841361d8SKuninori Morimoto struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
970cbf1ecdSStephan Gerhold
980cbf1ecdSStephan Gerhold switch (cpu_dai->id) {
990cbf1ecdSStephan Gerhold case WSA_CODEC_DMA_RX_0:
1000cbf1ecdSStephan Gerhold case WSA_CODEC_DMA_RX_1:
1010cbf1ecdSStephan Gerhold case RX_CODEC_DMA_RX_0:
1020cbf1ecdSStephan Gerhold case RX_CODEC_DMA_RX_1:
1030cbf1ecdSStephan Gerhold case TX_CODEC_DMA_TX_0:
1040cbf1ecdSStephan Gerhold case TX_CODEC_DMA_TX_1:
1050cbf1ecdSStephan Gerhold case TX_CODEC_DMA_TX_2:
1060cbf1ecdSStephan Gerhold case TX_CODEC_DMA_TX_3:
1070cbf1ecdSStephan Gerhold if (sruntime && *stream_prepared) {
1080cbf1ecdSStephan Gerhold sdw_disable_stream(sruntime);
1090cbf1ecdSStephan Gerhold sdw_deprepare_stream(sruntime);
1100cbf1ecdSStephan Gerhold *stream_prepared = false;
1110cbf1ecdSStephan Gerhold }
1120cbf1ecdSStephan Gerhold break;
1130cbf1ecdSStephan Gerhold default:
1140cbf1ecdSStephan Gerhold break;
1150cbf1ecdSStephan Gerhold }
1160cbf1ecdSStephan Gerhold
1170cbf1ecdSStephan Gerhold return 0;
1180cbf1ecdSStephan Gerhold }
1190cbf1ecdSStephan Gerhold EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free);
1200cbf1ecdSStephan Gerhold MODULE_LICENSE("GPL v2");
121