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