xref: /openbmc/linux/sound/soc/qcom/sdw.c (revision 816ffd28002651a469e86d1118a225862e392ecd)
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