xref: /kernel/linux/linux-6.6/sound/soc/qcom/sdw.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci// Copyright (c) 2018, Linaro Limited.
362306a36Sopenharmony_ci// Copyright (c) 2018, The Linux Foundation. All rights reserved.
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/module.h>
662306a36Sopenharmony_ci#include <sound/soc.h>
762306a36Sopenharmony_ci#include "qdsp6/q6afe.h"
862306a36Sopenharmony_ci#include "sdw.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ciint qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
1162306a36Sopenharmony_ci			 struct sdw_stream_runtime *sruntime,
1262306a36Sopenharmony_ci			 bool *stream_prepared)
1362306a36Sopenharmony_ci{
1462306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = substream->private_data;
1562306a36Sopenharmony_ci	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
1662306a36Sopenharmony_ci	int ret;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	if (!sruntime)
1962306a36Sopenharmony_ci		return 0;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	switch (cpu_dai->id) {
2262306a36Sopenharmony_ci	case WSA_CODEC_DMA_RX_0:
2362306a36Sopenharmony_ci	case WSA_CODEC_DMA_RX_1:
2462306a36Sopenharmony_ci	case RX_CODEC_DMA_RX_0:
2562306a36Sopenharmony_ci	case RX_CODEC_DMA_RX_1:
2662306a36Sopenharmony_ci	case TX_CODEC_DMA_TX_0:
2762306a36Sopenharmony_ci	case TX_CODEC_DMA_TX_1:
2862306a36Sopenharmony_ci	case TX_CODEC_DMA_TX_2:
2962306a36Sopenharmony_ci	case TX_CODEC_DMA_TX_3:
3062306a36Sopenharmony_ci		break;
3162306a36Sopenharmony_ci	default:
3262306a36Sopenharmony_ci		return 0;
3362306a36Sopenharmony_ci	}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	if (*stream_prepared)
3662306a36Sopenharmony_ci		return 0;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	ret = sdw_prepare_stream(sruntime);
3962306a36Sopenharmony_ci	if (ret)
4062306a36Sopenharmony_ci		return ret;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	/**
4362306a36Sopenharmony_ci	 * NOTE: there is a strict hw requirement about the ordering of port
4462306a36Sopenharmony_ci	 * enables and actual WSA881x PA enable. PA enable should only happen
4562306a36Sopenharmony_ci	 * after soundwire ports are enabled if not DC on the line is
4662306a36Sopenharmony_ci	 * accumulated resulting in Click/Pop Noise
4762306a36Sopenharmony_ci	 * PA enable/mute are handled as part of codec DAPM and digital mute.
4862306a36Sopenharmony_ci	 */
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	ret = sdw_enable_stream(sruntime);
5162306a36Sopenharmony_ci	if (ret) {
5262306a36Sopenharmony_ci		sdw_deprepare_stream(sruntime);
5362306a36Sopenharmony_ci		return ret;
5462306a36Sopenharmony_ci	}
5562306a36Sopenharmony_ci	*stream_prepared  = true;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	return ret;
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ciint qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
6262306a36Sopenharmony_ci			   struct snd_pcm_hw_params *params,
6362306a36Sopenharmony_ci			   struct sdw_stream_runtime **psruntime)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = substream->private_data;
6662306a36Sopenharmony_ci	struct snd_soc_dai *codec_dai;
6762306a36Sopenharmony_ci	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
6862306a36Sopenharmony_ci	struct sdw_stream_runtime *sruntime;
6962306a36Sopenharmony_ci	int i;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	switch (cpu_dai->id) {
7262306a36Sopenharmony_ci	case WSA_CODEC_DMA_RX_0:
7362306a36Sopenharmony_ci	case RX_CODEC_DMA_RX_0:
7462306a36Sopenharmony_ci	case RX_CODEC_DMA_RX_1:
7562306a36Sopenharmony_ci	case TX_CODEC_DMA_TX_0:
7662306a36Sopenharmony_ci	case TX_CODEC_DMA_TX_1:
7762306a36Sopenharmony_ci	case TX_CODEC_DMA_TX_2:
7862306a36Sopenharmony_ci	case TX_CODEC_DMA_TX_3:
7962306a36Sopenharmony_ci		for_each_rtd_codec_dais(rtd, i, codec_dai) {
8062306a36Sopenharmony_ci			sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
8162306a36Sopenharmony_ci			if (sruntime != ERR_PTR(-ENOTSUPP))
8262306a36Sopenharmony_ci				*psruntime = sruntime;
8362306a36Sopenharmony_ci		}
8462306a36Sopenharmony_ci		break;
8562306a36Sopenharmony_ci	}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	return 0;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci}
9062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params);
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ciint qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
9362306a36Sopenharmony_ci			 struct sdw_stream_runtime *sruntime, bool *stream_prepared)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = substream->private_data;
9662306a36Sopenharmony_ci	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	switch (cpu_dai->id) {
9962306a36Sopenharmony_ci	case WSA_CODEC_DMA_RX_0:
10062306a36Sopenharmony_ci	case WSA_CODEC_DMA_RX_1:
10162306a36Sopenharmony_ci	case RX_CODEC_DMA_RX_0:
10262306a36Sopenharmony_ci	case RX_CODEC_DMA_RX_1:
10362306a36Sopenharmony_ci	case TX_CODEC_DMA_TX_0:
10462306a36Sopenharmony_ci	case TX_CODEC_DMA_TX_1:
10562306a36Sopenharmony_ci	case TX_CODEC_DMA_TX_2:
10662306a36Sopenharmony_ci	case TX_CODEC_DMA_TX_3:
10762306a36Sopenharmony_ci		if (sruntime && *stream_prepared) {
10862306a36Sopenharmony_ci			sdw_disable_stream(sruntime);
10962306a36Sopenharmony_ci			sdw_deprepare_stream(sruntime);
11062306a36Sopenharmony_ci			*stream_prepared = false;
11162306a36Sopenharmony_ci		}
11262306a36Sopenharmony_ci		break;
11362306a36Sopenharmony_ci	default:
11462306a36Sopenharmony_ci		break;
11562306a36Sopenharmony_ci	}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	return 0;
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free);
12062306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
121