xref: /openbmc/linux/sound/soc/qcom/sc7280.c (revision 816ffd28002651a469e86d1118a225862e392ecd)
157350bd4SSrinivasa Rao Mandadapu // SPDX-License-Identifier: GPL-2.0-only
257350bd4SSrinivasa Rao Mandadapu //
357350bd4SSrinivasa Rao Mandadapu // Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
457350bd4SSrinivasa Rao Mandadapu //
557350bd4SSrinivasa Rao Mandadapu // ALSA SoC Machine driver for sc7280
657350bd4SSrinivasa Rao Mandadapu 
757350bd4SSrinivasa Rao Mandadapu #include <linux/input.h>
857350bd4SSrinivasa Rao Mandadapu #include <linux/module.h>
957350bd4SSrinivasa Rao Mandadapu #include <linux/of_device.h>
1057350bd4SSrinivasa Rao Mandadapu #include <linux/platform_device.h>
1157350bd4SSrinivasa Rao Mandadapu #include <sound/core.h>
1257350bd4SSrinivasa Rao Mandadapu #include <sound/jack.h>
1357350bd4SSrinivasa Rao Mandadapu #include <sound/pcm.h>
1457350bd4SSrinivasa Rao Mandadapu #include <sound/soc.h>
15c5198db8SJudy Hsiao #include <sound/rt5682s.h>
1657350bd4SSrinivasa Rao Mandadapu #include <linux/soundwire/sdw.h>
175b7e984eSMohammad Rafi Shaik #include <sound/pcm_params.h>
1857350bd4SSrinivasa Rao Mandadapu 
19c5198db8SJudy Hsiao #include "../codecs/rt5682.h"
20c5198db8SJudy Hsiao #include "../codecs/rt5682s.h"
2157350bd4SSrinivasa Rao Mandadapu #include "common.h"
2257350bd4SSrinivasa Rao Mandadapu #include "lpass.h"
235f78e1fbSSrinivasa Rao Mandadapu #include "qdsp6/q6afe.h"
2457350bd4SSrinivasa Rao Mandadapu 
25c5198db8SJudy Hsiao #define DEFAULT_MCLK_RATE              19200000
264d9596d4SJudy Hsiao #define RT5682_PLL_FREQ (48000 * 512)
275f78e1fbSSrinivasa Rao Mandadapu #define MI2S_BCLK_RATE		1536000
28c5198db8SJudy Hsiao 
2957350bd4SSrinivasa Rao Mandadapu struct sc7280_snd_data {
3057350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_card card;
3157350bd4SSrinivasa Rao Mandadapu 	struct sdw_stream_runtime *sruntime[LPASS_MAX_PORTS];
32c5198db8SJudy Hsiao 	u32 pri_mi2s_clk_count;
3357350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_jack hs_jack;
3457350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_jack hdmi_jack;
3557350bd4SSrinivasa Rao Mandadapu 	bool jack_setup;
3657350bd4SSrinivasa Rao Mandadapu 	bool stream_prepared[LPASS_MAX_PORTS];
3757350bd4SSrinivasa Rao Mandadapu };
3857350bd4SSrinivasa Rao Mandadapu 
sc7280_jack_free(struct snd_jack * jack)3957350bd4SSrinivasa Rao Mandadapu static void sc7280_jack_free(struct snd_jack *jack)
4057350bd4SSrinivasa Rao Mandadapu {
4157350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_component *component = jack->private_data;
4257350bd4SSrinivasa Rao Mandadapu 
4357350bd4SSrinivasa Rao Mandadapu 	snd_soc_component_set_jack(component, NULL, NULL);
4457350bd4SSrinivasa Rao Mandadapu }
4557350bd4SSrinivasa Rao Mandadapu 
464ab959e5SAlper Nebi Yasak static struct snd_soc_jack_pin sc7280_jack_pins[] = {
474ab959e5SAlper Nebi Yasak 	{
484ab959e5SAlper Nebi Yasak 		.pin = "Headphone Jack",
494ab959e5SAlper Nebi Yasak 		.mask = SND_JACK_HEADPHONE,
504ab959e5SAlper Nebi Yasak 	},
514ab959e5SAlper Nebi Yasak 	{
524ab959e5SAlper Nebi Yasak 		.pin = "Headset Mic",
534ab959e5SAlper Nebi Yasak 		.mask = SND_JACK_MICROPHONE,
544ab959e5SAlper Nebi Yasak 	},
554ab959e5SAlper Nebi Yasak };
564ab959e5SAlper Nebi Yasak 
sc7280_headset_init(struct snd_soc_pcm_runtime * rtd)5757350bd4SSrinivasa Rao Mandadapu static int sc7280_headset_init(struct snd_soc_pcm_runtime *rtd)
5857350bd4SSrinivasa Rao Mandadapu {
5957350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_card *card = rtd->card;
6057350bd4SSrinivasa Rao Mandadapu 	struct sc7280_snd_data *pdata = snd_soc_card_get_drvdata(card);
61*841361d8SKuninori Morimoto 	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
62*841361d8SKuninori Morimoto 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
6357350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_component *component = codec_dai->component;
6457350bd4SSrinivasa Rao Mandadapu 	struct snd_jack *jack;
6557350bd4SSrinivasa Rao Mandadapu 	int rval, i;
6657350bd4SSrinivasa Rao Mandadapu 
6757350bd4SSrinivasa Rao Mandadapu 	if (!pdata->jack_setup) {
684ab959e5SAlper Nebi Yasak 		rval = snd_soc_card_jack_new_pins(card, "Headset Jack",
6957350bd4SSrinivasa Rao Mandadapu 						  SND_JACK_HEADSET | SND_JACK_LINEOUT |
7057350bd4SSrinivasa Rao Mandadapu 						  SND_JACK_MECHANICAL |
7157350bd4SSrinivasa Rao Mandadapu 						  SND_JACK_BTN_0 | SND_JACK_BTN_1 |
7257350bd4SSrinivasa Rao Mandadapu 						  SND_JACK_BTN_2 | SND_JACK_BTN_3 |
7357350bd4SSrinivasa Rao Mandadapu 						  SND_JACK_BTN_4 | SND_JACK_BTN_5,
744ab959e5SAlper Nebi Yasak 						  &pdata->hs_jack,
754ab959e5SAlper Nebi Yasak 						  sc7280_jack_pins,
764ab959e5SAlper Nebi Yasak 						  ARRAY_SIZE(sc7280_jack_pins));
7757350bd4SSrinivasa Rao Mandadapu 
7857350bd4SSrinivasa Rao Mandadapu 		if (rval < 0) {
7957350bd4SSrinivasa Rao Mandadapu 			dev_err(card->dev, "Unable to add Headset Jack\n");
8057350bd4SSrinivasa Rao Mandadapu 			return rval;
8157350bd4SSrinivasa Rao Mandadapu 		}
8257350bd4SSrinivasa Rao Mandadapu 
8357350bd4SSrinivasa Rao Mandadapu 		jack = pdata->hs_jack.jack;
8457350bd4SSrinivasa Rao Mandadapu 
8557350bd4SSrinivasa Rao Mandadapu 		snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
8657350bd4SSrinivasa Rao Mandadapu 		snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
8757350bd4SSrinivasa Rao Mandadapu 		snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
8857350bd4SSrinivasa Rao Mandadapu 		snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
8957350bd4SSrinivasa Rao Mandadapu 
9057350bd4SSrinivasa Rao Mandadapu 		jack->private_data = component;
9157350bd4SSrinivasa Rao Mandadapu 		jack->private_free = sc7280_jack_free;
9257350bd4SSrinivasa Rao Mandadapu 		pdata->jack_setup = true;
9357350bd4SSrinivasa Rao Mandadapu 	}
9457350bd4SSrinivasa Rao Mandadapu 	switch (cpu_dai->id) {
95c5198db8SJudy Hsiao 	case MI2S_PRIMARY:
9657350bd4SSrinivasa Rao Mandadapu 	case LPASS_CDC_DMA_RX0:
9757350bd4SSrinivasa Rao Mandadapu 	case LPASS_CDC_DMA_TX3:
985f78e1fbSSrinivasa Rao Mandadapu 	case TX_CODEC_DMA_TX_3:
9957350bd4SSrinivasa Rao Mandadapu 		for_each_rtd_codec_dais(rtd, i, codec_dai) {
10057350bd4SSrinivasa Rao Mandadapu 			rval = snd_soc_component_set_jack(component, &pdata->hs_jack, NULL);
10157350bd4SSrinivasa Rao Mandadapu 			if (rval != 0 && rval != -ENOTSUPP) {
10257350bd4SSrinivasa Rao Mandadapu 				dev_err(card->dev, "Failed to set jack: %d\n", rval);
10357350bd4SSrinivasa Rao Mandadapu 				return rval;
10457350bd4SSrinivasa Rao Mandadapu 			}
10557350bd4SSrinivasa Rao Mandadapu 		}
10657350bd4SSrinivasa Rao Mandadapu 		break;
10757350bd4SSrinivasa Rao Mandadapu 	default:
10857350bd4SSrinivasa Rao Mandadapu 		break;
10957350bd4SSrinivasa Rao Mandadapu 	}
11057350bd4SSrinivasa Rao Mandadapu 
11157350bd4SSrinivasa Rao Mandadapu 	return 0;
11257350bd4SSrinivasa Rao Mandadapu }
11357350bd4SSrinivasa Rao Mandadapu 
sc7280_hdmi_init(struct snd_soc_pcm_runtime * rtd)11457350bd4SSrinivasa Rao Mandadapu static int sc7280_hdmi_init(struct snd_soc_pcm_runtime *rtd)
11557350bd4SSrinivasa Rao Mandadapu {
11657350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_card *card = rtd->card;
11757350bd4SSrinivasa Rao Mandadapu 	struct sc7280_snd_data *pdata = snd_soc_card_get_drvdata(card);
118*841361d8SKuninori Morimoto 	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
11957350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_component *component = codec_dai->component;
12057350bd4SSrinivasa Rao Mandadapu 	struct snd_jack *jack;
12157350bd4SSrinivasa Rao Mandadapu 	int rval;
12257350bd4SSrinivasa Rao Mandadapu 
12357350bd4SSrinivasa Rao Mandadapu 	rval = snd_soc_card_jack_new(card, "HDMI Jack",	SND_JACK_LINEOUT,
12419aed2d6SAkihiko Odaki 				     &pdata->hdmi_jack);
12557350bd4SSrinivasa Rao Mandadapu 
12657350bd4SSrinivasa Rao Mandadapu 	if (rval < 0) {
12757350bd4SSrinivasa Rao Mandadapu 		dev_err(card->dev, "Unable to add HDMI Jack\n");
12857350bd4SSrinivasa Rao Mandadapu 		return rval;
12957350bd4SSrinivasa Rao Mandadapu 	}
13057350bd4SSrinivasa Rao Mandadapu 
13157350bd4SSrinivasa Rao Mandadapu 	jack = pdata->hdmi_jack.jack;
13257350bd4SSrinivasa Rao Mandadapu 	jack->private_data = component;
13357350bd4SSrinivasa Rao Mandadapu 	jack->private_free = sc7280_jack_free;
13457350bd4SSrinivasa Rao Mandadapu 
13557350bd4SSrinivasa Rao Mandadapu 	return snd_soc_component_set_jack(component, &pdata->hdmi_jack, NULL);
13657350bd4SSrinivasa Rao Mandadapu }
13757350bd4SSrinivasa Rao Mandadapu 
sc7280_rt5682_init(struct snd_soc_pcm_runtime * rtd)138c5198db8SJudy Hsiao static int sc7280_rt5682_init(struct snd_soc_pcm_runtime *rtd)
139c5198db8SJudy Hsiao {
140*841361d8SKuninori Morimoto 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
141*841361d8SKuninori Morimoto 	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
142c5198db8SJudy Hsiao 	struct snd_soc_card *card = rtd->card;
143c5198db8SJudy Hsiao 	struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card);
144c5198db8SJudy Hsiao 	int ret;
145c5198db8SJudy Hsiao 
146c5198db8SJudy Hsiao 	if (++data->pri_mi2s_clk_count == 1) {
147c5198db8SJudy Hsiao 		snd_soc_dai_set_sysclk(cpu_dai,
148c5198db8SJudy Hsiao 			LPASS_MCLK0,
149c5198db8SJudy Hsiao 			DEFAULT_MCLK_RATE,
150c5198db8SJudy Hsiao 			SNDRV_PCM_STREAM_PLAYBACK);
151c5198db8SJudy Hsiao 	}
152c5198db8SJudy Hsiao 	snd_soc_dai_set_fmt(codec_dai,
153c5198db8SJudy Hsiao 				SND_SOC_DAIFMT_CBC_CFC |
154c5198db8SJudy Hsiao 				SND_SOC_DAIFMT_NB_NF |
155c5198db8SJudy Hsiao 				SND_SOC_DAIFMT_I2S);
156c5198db8SJudy Hsiao 
1574d9596d4SJudy Hsiao 	ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL2, RT5682S_PLL_S_MCLK,
1584d9596d4SJudy Hsiao 					DEFAULT_MCLK_RATE, RT5682_PLL_FREQ);
159c5198db8SJudy Hsiao 	if (ret) {
160c5198db8SJudy Hsiao 		dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
161c5198db8SJudy Hsiao 		return ret;
162c5198db8SJudy Hsiao 	}
163c5198db8SJudy Hsiao 
1644d9596d4SJudy Hsiao 	ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL2,
1654d9596d4SJudy Hsiao 					RT5682_PLL_FREQ,
166c5198db8SJudy Hsiao 					SND_SOC_CLOCK_IN);
167c5198db8SJudy Hsiao 
168c5198db8SJudy Hsiao 	if (ret) {
169c5198db8SJudy Hsiao 		dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n",
170c5198db8SJudy Hsiao 			ret);
171c5198db8SJudy Hsiao 		return ret;
172c5198db8SJudy Hsiao 	}
173c5198db8SJudy Hsiao 
174c5198db8SJudy Hsiao 	return 0;
175c5198db8SJudy Hsiao }
176c5198db8SJudy Hsiao 
sc7280_init(struct snd_soc_pcm_runtime * rtd)17757350bd4SSrinivasa Rao Mandadapu static int sc7280_init(struct snd_soc_pcm_runtime *rtd)
17857350bd4SSrinivasa Rao Mandadapu {
179*841361d8SKuninori Morimoto 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
18057350bd4SSrinivasa Rao Mandadapu 
18157350bd4SSrinivasa Rao Mandadapu 	switch (cpu_dai->id) {
182c5198db8SJudy Hsiao 	case MI2S_PRIMARY:
18357350bd4SSrinivasa Rao Mandadapu 	case LPASS_CDC_DMA_TX3:
1845f78e1fbSSrinivasa Rao Mandadapu 	case TX_CODEC_DMA_TX_3:
18557350bd4SSrinivasa Rao Mandadapu 		return sc7280_headset_init(rtd);
18657350bd4SSrinivasa Rao Mandadapu 	case LPASS_CDC_DMA_RX0:
18757350bd4SSrinivasa Rao Mandadapu 	case LPASS_CDC_DMA_VA_TX0:
18857350bd4SSrinivasa Rao Mandadapu 	case MI2S_SECONDARY:
1895f78e1fbSSrinivasa Rao Mandadapu 	case RX_CODEC_DMA_RX_0:
1905f78e1fbSSrinivasa Rao Mandadapu 	case SECONDARY_MI2S_RX:
1915f78e1fbSSrinivasa Rao Mandadapu 	case VA_CODEC_DMA_TX_0:
19257350bd4SSrinivasa Rao Mandadapu 		return 0;
19357350bd4SSrinivasa Rao Mandadapu 	case LPASS_DP_RX:
19457350bd4SSrinivasa Rao Mandadapu 		return sc7280_hdmi_init(rtd);
19557350bd4SSrinivasa Rao Mandadapu 	default:
19657350bd4SSrinivasa Rao Mandadapu 		dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
19757350bd4SSrinivasa Rao Mandadapu 	}
19857350bd4SSrinivasa Rao Mandadapu 
19957350bd4SSrinivasa Rao Mandadapu 	return -EINVAL;
20057350bd4SSrinivasa Rao Mandadapu }
20157350bd4SSrinivasa Rao Mandadapu 
sc7280_snd_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)20257350bd4SSrinivasa Rao Mandadapu static int sc7280_snd_hw_params(struct snd_pcm_substream *substream,
20357350bd4SSrinivasa Rao Mandadapu 				struct snd_pcm_hw_params *params)
20457350bd4SSrinivasa Rao Mandadapu {
20557350bd4SSrinivasa Rao Mandadapu 	struct snd_pcm_runtime *runtime = substream->runtime;
20657350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
20757350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_dai *codec_dai;
208*841361d8SKuninori Morimoto 	const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
20957350bd4SSrinivasa Rao Mandadapu 	struct sc7280_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
21057350bd4SSrinivasa Rao Mandadapu 	struct sdw_stream_runtime *sruntime;
21157350bd4SSrinivasa Rao Mandadapu 	int i;
21257350bd4SSrinivasa Rao Mandadapu 
2135b7e984eSMohammad Rafi Shaik 	if (!rtd->dai_link->no_pcm) {
21457350bd4SSrinivasa Rao Mandadapu 		snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
21557350bd4SSrinivasa Rao Mandadapu 		snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, 48000, 48000);
2165b7e984eSMohammad Rafi Shaik 	}
21757350bd4SSrinivasa Rao Mandadapu 
21857350bd4SSrinivasa Rao Mandadapu 	switch (cpu_dai->id) {
21957350bd4SSrinivasa Rao Mandadapu 	case LPASS_CDC_DMA_TX3:
22057350bd4SSrinivasa Rao Mandadapu 	case LPASS_CDC_DMA_RX0:
2215f78e1fbSSrinivasa Rao Mandadapu 	case RX_CODEC_DMA_RX_0:
2225f78e1fbSSrinivasa Rao Mandadapu 	case SECONDARY_MI2S_RX:
2235f78e1fbSSrinivasa Rao Mandadapu 	case TX_CODEC_DMA_TX_3:
2245f78e1fbSSrinivasa Rao Mandadapu 	case VA_CODEC_DMA_TX_0:
22557350bd4SSrinivasa Rao Mandadapu 		for_each_rtd_codec_dais(rtd, i, codec_dai) {
22657350bd4SSrinivasa Rao Mandadapu 			sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
22757350bd4SSrinivasa Rao Mandadapu 			if (sruntime != ERR_PTR(-ENOTSUPP))
22857350bd4SSrinivasa Rao Mandadapu 				pdata->sruntime[cpu_dai->id] = sruntime;
22957350bd4SSrinivasa Rao Mandadapu 		}
23057350bd4SSrinivasa Rao Mandadapu 		break;
23157350bd4SSrinivasa Rao Mandadapu 	}
23257350bd4SSrinivasa Rao Mandadapu 
23357350bd4SSrinivasa Rao Mandadapu 	return 0;
23457350bd4SSrinivasa Rao Mandadapu }
23557350bd4SSrinivasa Rao Mandadapu 
sc7280_snd_swr_prepare(struct snd_pcm_substream * substream)23657350bd4SSrinivasa Rao Mandadapu static int sc7280_snd_swr_prepare(struct snd_pcm_substream *substream)
23757350bd4SSrinivasa Rao Mandadapu {
23857350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
239*841361d8SKuninori Morimoto 	const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
24057350bd4SSrinivasa Rao Mandadapu 	struct sc7280_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
24157350bd4SSrinivasa Rao Mandadapu 	struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
24257350bd4SSrinivasa Rao Mandadapu 	int ret;
24357350bd4SSrinivasa Rao Mandadapu 
24457350bd4SSrinivasa Rao Mandadapu 	if (!sruntime)
24557350bd4SSrinivasa Rao Mandadapu 		return 0;
24657350bd4SSrinivasa Rao Mandadapu 
24757350bd4SSrinivasa Rao Mandadapu 	if (data->stream_prepared[cpu_dai->id]) {
24857350bd4SSrinivasa Rao Mandadapu 		sdw_disable_stream(sruntime);
24957350bd4SSrinivasa Rao Mandadapu 		sdw_deprepare_stream(sruntime);
25057350bd4SSrinivasa Rao Mandadapu 		data->stream_prepared[cpu_dai->id] = false;
25157350bd4SSrinivasa Rao Mandadapu 	}
25257350bd4SSrinivasa Rao Mandadapu 
25357350bd4SSrinivasa Rao Mandadapu 	ret = sdw_prepare_stream(sruntime);
25457350bd4SSrinivasa Rao Mandadapu 	if (ret)
25557350bd4SSrinivasa Rao Mandadapu 		return ret;
25657350bd4SSrinivasa Rao Mandadapu 
25757350bd4SSrinivasa Rao Mandadapu 	ret = sdw_enable_stream(sruntime);
25857350bd4SSrinivasa Rao Mandadapu 	if (ret) {
25957350bd4SSrinivasa Rao Mandadapu 		sdw_deprepare_stream(sruntime);
26057350bd4SSrinivasa Rao Mandadapu 		return ret;
26157350bd4SSrinivasa Rao Mandadapu 	}
26257350bd4SSrinivasa Rao Mandadapu 	data->stream_prepared[cpu_dai->id] = true;
26357350bd4SSrinivasa Rao Mandadapu 
26457350bd4SSrinivasa Rao Mandadapu 	return ret;
26557350bd4SSrinivasa Rao Mandadapu }
26657350bd4SSrinivasa Rao Mandadapu 
sc7280_snd_prepare(struct snd_pcm_substream * substream)26757350bd4SSrinivasa Rao Mandadapu static int sc7280_snd_prepare(struct snd_pcm_substream *substream)
26857350bd4SSrinivasa Rao Mandadapu {
26957350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
270*841361d8SKuninori Morimoto 	const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
27157350bd4SSrinivasa Rao Mandadapu 
27257350bd4SSrinivasa Rao Mandadapu 	switch (cpu_dai->id) {
27357350bd4SSrinivasa Rao Mandadapu 	case LPASS_CDC_DMA_RX0:
27457350bd4SSrinivasa Rao Mandadapu 	case LPASS_CDC_DMA_TX3:
2755f78e1fbSSrinivasa Rao Mandadapu 	case RX_CODEC_DMA_RX_0:
2765f78e1fbSSrinivasa Rao Mandadapu 	case TX_CODEC_DMA_TX_3:
2775f78e1fbSSrinivasa Rao Mandadapu 	case VA_CODEC_DMA_TX_0:
27857350bd4SSrinivasa Rao Mandadapu 		return sc7280_snd_swr_prepare(substream);
27957350bd4SSrinivasa Rao Mandadapu 	default:
28057350bd4SSrinivasa Rao Mandadapu 		break;
28157350bd4SSrinivasa Rao Mandadapu 	}
28257350bd4SSrinivasa Rao Mandadapu 
28357350bd4SSrinivasa Rao Mandadapu 	return 0;
28457350bd4SSrinivasa Rao Mandadapu }
28557350bd4SSrinivasa Rao Mandadapu 
sc7280_snd_hw_free(struct snd_pcm_substream * substream)28657350bd4SSrinivasa Rao Mandadapu static int sc7280_snd_hw_free(struct snd_pcm_substream *substream)
28757350bd4SSrinivasa Rao Mandadapu {
28857350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
28957350bd4SSrinivasa Rao Mandadapu 	struct sc7280_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
290*841361d8SKuninori Morimoto 	const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
29157350bd4SSrinivasa Rao Mandadapu 	struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
29257350bd4SSrinivasa Rao Mandadapu 
29357350bd4SSrinivasa Rao Mandadapu 	switch (cpu_dai->id) {
29457350bd4SSrinivasa Rao Mandadapu 	case LPASS_CDC_DMA_RX0:
29557350bd4SSrinivasa Rao Mandadapu 	case LPASS_CDC_DMA_TX3:
2965f78e1fbSSrinivasa Rao Mandadapu 	case RX_CODEC_DMA_RX_0:
2975f78e1fbSSrinivasa Rao Mandadapu 	case TX_CODEC_DMA_TX_3:
2985f78e1fbSSrinivasa Rao Mandadapu 	case VA_CODEC_DMA_TX_0:
29957350bd4SSrinivasa Rao Mandadapu 		if (sruntime && data->stream_prepared[cpu_dai->id]) {
30057350bd4SSrinivasa Rao Mandadapu 			sdw_disable_stream(sruntime);
30157350bd4SSrinivasa Rao Mandadapu 			sdw_deprepare_stream(sruntime);
30257350bd4SSrinivasa Rao Mandadapu 			data->stream_prepared[cpu_dai->id] = false;
30357350bd4SSrinivasa Rao Mandadapu 		}
30457350bd4SSrinivasa Rao Mandadapu 		break;
30557350bd4SSrinivasa Rao Mandadapu 	default:
30657350bd4SSrinivasa Rao Mandadapu 		break;
30757350bd4SSrinivasa Rao Mandadapu 	}
30857350bd4SSrinivasa Rao Mandadapu 	return 0;
30957350bd4SSrinivasa Rao Mandadapu }
31057350bd4SSrinivasa Rao Mandadapu 
sc7280_snd_shutdown(struct snd_pcm_substream * substream)311c5198db8SJudy Hsiao static void sc7280_snd_shutdown(struct snd_pcm_substream *substream)
312c5198db8SJudy Hsiao {
313c5198db8SJudy Hsiao 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
314c5198db8SJudy Hsiao 	struct snd_soc_card *card = rtd->card;
315c5198db8SJudy Hsiao 	struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card);
316*841361d8SKuninori Morimoto 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
317c5198db8SJudy Hsiao 
318c5198db8SJudy Hsiao 	switch (cpu_dai->id) {
319c5198db8SJudy Hsiao 	case MI2S_PRIMARY:
320c5198db8SJudy Hsiao 		if (--data->pri_mi2s_clk_count == 0) {
321c5198db8SJudy Hsiao 			snd_soc_dai_set_sysclk(cpu_dai,
322c5198db8SJudy Hsiao 					       LPASS_MCLK0,
323c5198db8SJudy Hsiao 					       0,
324c5198db8SJudy Hsiao 					       SNDRV_PCM_STREAM_PLAYBACK);
325c5198db8SJudy Hsiao 		}
326c5198db8SJudy Hsiao 		break;
3275f78e1fbSSrinivasa Rao Mandadapu 	case SECONDARY_MI2S_RX:
3285f78e1fbSSrinivasa Rao Mandadapu 		snd_soc_dai_set_sysclk(cpu_dai, Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
3295f78e1fbSSrinivasa Rao Mandadapu 					       0, SNDRV_PCM_STREAM_PLAYBACK);
3305f78e1fbSSrinivasa Rao Mandadapu 		break;
331c5198db8SJudy Hsiao 	default:
332c5198db8SJudy Hsiao 		break;
333c5198db8SJudy Hsiao 	}
334c5198db8SJudy Hsiao }
335c5198db8SJudy Hsiao 
sc7280_snd_startup(struct snd_pcm_substream * substream)336c5198db8SJudy Hsiao static int sc7280_snd_startup(struct snd_pcm_substream *substream)
337c5198db8SJudy Hsiao {
3385f78e1fbSSrinivasa Rao Mandadapu 	unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS;
3395f78e1fbSSrinivasa Rao Mandadapu 	unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS;
340c5198db8SJudy Hsiao 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
341*841361d8SKuninori Morimoto 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
342*841361d8SKuninori Morimoto 	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
343c5198db8SJudy Hsiao 	int ret = 0;
344c5198db8SJudy Hsiao 
345c5198db8SJudy Hsiao 	switch (cpu_dai->id) {
346c5198db8SJudy Hsiao 	case MI2S_PRIMARY:
347c5198db8SJudy Hsiao 		ret = sc7280_rt5682_init(rtd);
348c5198db8SJudy Hsiao 		break;
3495f78e1fbSSrinivasa Rao Mandadapu 	case SECONDARY_MI2S_RX:
3505f78e1fbSSrinivasa Rao Mandadapu 		codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
3515f78e1fbSSrinivasa Rao Mandadapu 
3525f78e1fbSSrinivasa Rao Mandadapu 		snd_soc_dai_set_sysclk(cpu_dai, Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
3535f78e1fbSSrinivasa Rao Mandadapu 			MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
3545f78e1fbSSrinivasa Rao Mandadapu 
3555f78e1fbSSrinivasa Rao Mandadapu 		snd_soc_dai_set_fmt(cpu_dai, fmt);
3565f78e1fbSSrinivasa Rao Mandadapu 		snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
3575f78e1fbSSrinivasa Rao Mandadapu 		break;
358c5198db8SJudy Hsiao 	default:
359c85f533dSSrinivasa Rao Mandadapu 		break;
360c5198db8SJudy Hsiao 	}
361c5198db8SJudy Hsiao 	return ret;
362c5198db8SJudy Hsiao }
363c5198db8SJudy Hsiao 
36457350bd4SSrinivasa Rao Mandadapu static const struct snd_soc_ops sc7280_ops = {
365c5198db8SJudy Hsiao 	.startup = sc7280_snd_startup,
36657350bd4SSrinivasa Rao Mandadapu 	.hw_params = sc7280_snd_hw_params,
36757350bd4SSrinivasa Rao Mandadapu 	.hw_free = sc7280_snd_hw_free,
36857350bd4SSrinivasa Rao Mandadapu 	.prepare = sc7280_snd_prepare,
369c5198db8SJudy Hsiao 	.shutdown = sc7280_snd_shutdown,
370c5198db8SJudy Hsiao };
371c5198db8SJudy Hsiao 
372c5198db8SJudy Hsiao static const struct snd_soc_dapm_widget sc7280_snd_widgets[] = {
373c5198db8SJudy Hsiao 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
374c5198db8SJudy Hsiao 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
37557350bd4SSrinivasa Rao Mandadapu };
37657350bd4SSrinivasa Rao Mandadapu 
3774ab959e5SAlper Nebi Yasak static const struct snd_kcontrol_new sc7280_snd_controls[] = {
3784ab959e5SAlper Nebi Yasak 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
3794ab959e5SAlper Nebi Yasak 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
3804ab959e5SAlper Nebi Yasak };
3814ab959e5SAlper Nebi Yasak 
sc7280_snd_be_hw_params_fixup(struct snd_soc_pcm_runtime * rtd,struct snd_pcm_hw_params * params)3825b7e984eSMohammad Rafi Shaik static int sc7280_snd_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
3835b7e984eSMohammad Rafi Shaik 					 struct snd_pcm_hw_params *params)
3845b7e984eSMohammad Rafi Shaik {
3855b7e984eSMohammad Rafi Shaik 	struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
3865b7e984eSMohammad Rafi Shaik 	struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
3875b7e984eSMohammad Rafi Shaik 	struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
3885b7e984eSMohammad Rafi Shaik 
3895b7e984eSMohammad Rafi Shaik 	rate->min = rate->max = 48000;
3905b7e984eSMohammad Rafi Shaik 	channels->min = channels->max = 2;
3915b7e984eSMohammad Rafi Shaik 	snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
3925b7e984eSMohammad Rafi Shaik 
3935b7e984eSMohammad Rafi Shaik 	return 0;
3945b7e984eSMohammad Rafi Shaik }
3955b7e984eSMohammad Rafi Shaik 
sc7280_snd_platform_probe(struct platform_device * pdev)39657350bd4SSrinivasa Rao Mandadapu static int sc7280_snd_platform_probe(struct platform_device *pdev)
39757350bd4SSrinivasa Rao Mandadapu {
39857350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_card *card;
39957350bd4SSrinivasa Rao Mandadapu 	struct sc7280_snd_data *data;
40057350bd4SSrinivasa Rao Mandadapu 	struct device *dev = &pdev->dev;
40157350bd4SSrinivasa Rao Mandadapu 	struct snd_soc_dai_link *link;
40257350bd4SSrinivasa Rao Mandadapu 	int ret, i;
40357350bd4SSrinivasa Rao Mandadapu 
40457350bd4SSrinivasa Rao Mandadapu 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
40557350bd4SSrinivasa Rao Mandadapu 	if (!data)
40657350bd4SSrinivasa Rao Mandadapu 		return -ENOMEM;
40757350bd4SSrinivasa Rao Mandadapu 
40857350bd4SSrinivasa Rao Mandadapu 	card = &data->card;
40957350bd4SSrinivasa Rao Mandadapu 	snd_soc_card_set_drvdata(card, data);
41057350bd4SSrinivasa Rao Mandadapu 
41157350bd4SSrinivasa Rao Mandadapu 	card->owner = THIS_MODULE;
41257350bd4SSrinivasa Rao Mandadapu 	card->driver_name = "SC7280";
41357350bd4SSrinivasa Rao Mandadapu 	card->dev = dev;
41457350bd4SSrinivasa Rao Mandadapu 
415c5198db8SJudy Hsiao 	card->dapm_widgets = sc7280_snd_widgets;
416c5198db8SJudy Hsiao 	card->num_dapm_widgets = ARRAY_SIZE(sc7280_snd_widgets);
4174ab959e5SAlper Nebi Yasak 	card->controls = sc7280_snd_controls;
4184ab959e5SAlper Nebi Yasak 	card->num_controls = ARRAY_SIZE(sc7280_snd_controls);
419c5198db8SJudy Hsiao 
42057350bd4SSrinivasa Rao Mandadapu 	ret = qcom_snd_parse_of(card);
42157350bd4SSrinivasa Rao Mandadapu 	if (ret)
42257350bd4SSrinivasa Rao Mandadapu 		return ret;
42357350bd4SSrinivasa Rao Mandadapu 
42457350bd4SSrinivasa Rao Mandadapu 	for_each_card_prelinks(card, i, link) {
42557350bd4SSrinivasa Rao Mandadapu 		link->init = sc7280_init;
42657350bd4SSrinivasa Rao Mandadapu 		link->ops = &sc7280_ops;
4275b7e984eSMohammad Rafi Shaik 		if (link->no_pcm == 1)
4285b7e984eSMohammad Rafi Shaik 			link->be_hw_params_fixup = sc7280_snd_be_hw_params_fixup;
42957350bd4SSrinivasa Rao Mandadapu 	}
43057350bd4SSrinivasa Rao Mandadapu 
43157350bd4SSrinivasa Rao Mandadapu 	return devm_snd_soc_register_card(dev, card);
43257350bd4SSrinivasa Rao Mandadapu }
43357350bd4SSrinivasa Rao Mandadapu 
43457350bd4SSrinivasa Rao Mandadapu static const struct of_device_id sc7280_snd_device_id[]  = {
43557350bd4SSrinivasa Rao Mandadapu 	{ .compatible = "google,sc7280-herobrine" },
43657350bd4SSrinivasa Rao Mandadapu 	{}
43757350bd4SSrinivasa Rao Mandadapu };
43857350bd4SSrinivasa Rao Mandadapu MODULE_DEVICE_TABLE(of, sc7280_snd_device_id);
43957350bd4SSrinivasa Rao Mandadapu 
44057350bd4SSrinivasa Rao Mandadapu static struct platform_driver sc7280_snd_driver = {
44157350bd4SSrinivasa Rao Mandadapu 	.probe = sc7280_snd_platform_probe,
44257350bd4SSrinivasa Rao Mandadapu 	.driver = {
44357350bd4SSrinivasa Rao Mandadapu 		.name = "msm-snd-sc7280",
44457350bd4SSrinivasa Rao Mandadapu 		.of_match_table = sc7280_snd_device_id,
44557350bd4SSrinivasa Rao Mandadapu 		.pm = &snd_soc_pm_ops,
44657350bd4SSrinivasa Rao Mandadapu 	},
44757350bd4SSrinivasa Rao Mandadapu };
44857350bd4SSrinivasa Rao Mandadapu module_platform_driver(sc7280_snd_driver);
44957350bd4SSrinivasa Rao Mandadapu 
45057350bd4SSrinivasa Rao Mandadapu MODULE_DESCRIPTION("sc7280 ASoC Machine Driver");
45157350bd4SSrinivasa Rao Mandadapu MODULE_LICENSE("GPL");
452