1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2020, Linaro Limited
4 #include <linux/module.h>
5 #include <linux/platform_device.h>
6 #include <linux/of_device.h>
8 #include <sound/soc-dapm.h>
10 #include <linux/soundwire/sdw.h>
11 #include "qdsp6/q6afe.h"
14 #define DRIVER_NAME "sm8250"
15 #define MI2S_BCLK_RATE 1536000
17 struct sm8250_snd_data
{
18 bool stream_prepared
[AFE_PORT_MAX
];
19 struct snd_soc_card
*card
;
20 struct sdw_stream_runtime
*sruntime
[AFE_PORT_MAX
];
23 static int sm8250_be_hw_params_fixup(struct snd_soc_pcm_runtime
*rtd
,
24 struct snd_pcm_hw_params
*params
)
26 struct snd_interval
*rate
= hw_param_interval(params
,
27 SNDRV_PCM_HW_PARAM_RATE
);
28 struct snd_interval
*channels
= hw_param_interval(params
,
29 SNDRV_PCM_HW_PARAM_CHANNELS
);
31 rate
->min
= rate
->max
= 48000;
32 channels
->min
= channels
->max
= 2;
37 static int sm8250_snd_startup(struct snd_pcm_substream
*substream
)
39 unsigned int fmt
= SND_SOC_DAIFMT_CBS_CFS
;
40 unsigned int codec_dai_fmt
= SND_SOC_DAIFMT_CBS_CFS
;
41 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
42 struct snd_soc_dai
*cpu_dai
= asoc_rtd_to_cpu(rtd
, 0);
43 struct snd_soc_dai
*codec_dai
= asoc_rtd_to_codec(rtd
, 0);
45 switch (cpu_dai
->id
) {
46 case TERTIARY_MI2S_RX
:
47 codec_dai_fmt
|= SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_I2S
;
48 snd_soc_dai_set_sysclk(cpu_dai
,
49 Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT
,
50 MI2S_BCLK_RATE
, SNDRV_PCM_STREAM_PLAYBACK
);
51 snd_soc_dai_set_fmt(cpu_dai
, fmt
);
52 snd_soc_dai_set_fmt(codec_dai
, codec_dai_fmt
);
60 static int sm8250_snd_hw_params(struct snd_pcm_substream
*substream
,
61 struct snd_pcm_hw_params
*params
)
63 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
64 struct snd_soc_dai
*codec_dai
;
65 struct snd_soc_dai
*cpu_dai
= asoc_rtd_to_cpu(rtd
, 0);
66 struct sm8250_snd_data
*pdata
= snd_soc_card_get_drvdata(rtd
->card
);
67 struct sdw_stream_runtime
*sruntime
;
70 switch (cpu_dai
->id
) {
71 case WSA_CODEC_DMA_RX_0
:
72 for_each_rtd_codec_dais(rtd
, i
, codec_dai
) {
73 sruntime
= snd_soc_dai_get_sdw_stream(codec_dai
,
75 if (sruntime
!= ERR_PTR(-ENOTSUPP
))
76 pdata
->sruntime
[cpu_dai
->id
] = sruntime
;
85 static int sm8250_snd_wsa_dma_prepare(struct snd_pcm_substream
*substream
)
87 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
88 struct snd_soc_dai
*cpu_dai
= asoc_rtd_to_cpu(rtd
, 0);
89 struct sm8250_snd_data
*data
= snd_soc_card_get_drvdata(rtd
->card
);
90 struct sdw_stream_runtime
*sruntime
= data
->sruntime
[cpu_dai
->id
];
96 if (data
->stream_prepared
[cpu_dai
->id
]) {
97 sdw_disable_stream(sruntime
);
98 sdw_deprepare_stream(sruntime
);
99 data
->stream_prepared
[cpu_dai
->id
] = false;
102 ret
= sdw_prepare_stream(sruntime
);
107 * NOTE: there is a strict hw requirement about the ordering of port
108 * enables and actual WSA881x PA enable. PA enable should only happen
109 * after soundwire ports are enabled if not DC on the line is
110 * accumulated resulting in Click/Pop Noise
111 * PA enable/mute are handled as part of codec DAPM and digital mute.
114 ret
= sdw_enable_stream(sruntime
);
116 sdw_deprepare_stream(sruntime
);
119 data
->stream_prepared
[cpu_dai
->id
] = true;
124 static int sm8250_snd_prepare(struct snd_pcm_substream
*substream
)
126 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
127 struct snd_soc_dai
*cpu_dai
= asoc_rtd_to_cpu(rtd
, 0);
129 switch (cpu_dai
->id
) {
130 case WSA_CODEC_DMA_RX_0
:
131 case WSA_CODEC_DMA_RX_1
:
132 return sm8250_snd_wsa_dma_prepare(substream
);
140 static int sm8250_snd_hw_free(struct snd_pcm_substream
*substream
)
142 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
143 struct sm8250_snd_data
*data
= snd_soc_card_get_drvdata(rtd
->card
);
144 struct snd_soc_dai
*cpu_dai
= asoc_rtd_to_cpu(rtd
, 0);
145 struct sdw_stream_runtime
*sruntime
= data
->sruntime
[cpu_dai
->id
];
147 switch (cpu_dai
->id
) {
148 case WSA_CODEC_DMA_RX_0
:
149 case WSA_CODEC_DMA_RX_1
:
150 if (sruntime
&& data
->stream_prepared
[cpu_dai
->id
]) {
151 sdw_disable_stream(sruntime
);
152 sdw_deprepare_stream(sruntime
);
153 data
->stream_prepared
[cpu_dai
->id
] = false;
163 static const struct snd_soc_ops sm8250_be_ops
= {
164 .startup
= sm8250_snd_startup
,
165 .hw_params
= sm8250_snd_hw_params
,
166 .hw_free
= sm8250_snd_hw_free
,
167 .prepare
= sm8250_snd_prepare
,
170 static void sm8250_add_be_ops(struct snd_soc_card
*card
)
172 struct snd_soc_dai_link
*link
;
175 for_each_card_prelinks(card
, i
, link
) {
176 if (link
->no_pcm
== 1) {
177 link
->be_hw_params_fixup
= sm8250_be_hw_params_fixup
;
178 link
->ops
= &sm8250_be_ops
;
183 static int sm8250_platform_probe(struct platform_device
*pdev
)
185 struct snd_soc_card
*card
;
186 struct sm8250_snd_data
*data
;
187 struct device
*dev
= &pdev
->dev
;
190 card
= devm_kzalloc(dev
, sizeof(*card
), GFP_KERNEL
);
194 /* Allocate the private data */
195 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
200 dev_set_drvdata(dev
, card
);
201 snd_soc_card_set_drvdata(card
, data
);
202 ret
= qcom_snd_parse_of(card
);
206 card
->driver_name
= DRIVER_NAME
;
207 sm8250_add_be_ops(card
);
208 return devm_snd_soc_register_card(dev
, card
);
211 static const struct of_device_id snd_sm8250_dt_match
[] = {
212 {.compatible
= "qcom,sm8250-sndcard"},
213 {.compatible
= "qcom,qrb5165-rb5-sndcard"},
217 MODULE_DEVICE_TABLE(of
, snd_sm8250_dt_match
);
219 static struct platform_driver snd_sm8250_driver
= {
220 .probe
= sm8250_platform_probe
,
222 .name
= "snd-sm8250",
223 .of_match_table
= snd_sm8250_dt_match
,
226 module_platform_driver(snd_sm8250_driver
);
227 MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org");
228 MODULE_DESCRIPTION("SM8250 ASoC Machine Driver");
229 MODULE_LICENSE("GPL v2");