1 // SPDX-License-Identifier: GPL-2.0
3 // Copyright (C) 2017 Samsung Electronics Co., Ltd.
6 #include <linux/clk-provider.h>
8 #include <linux/of_device.h>
9 #include <linux/module.h>
10 #include <sound/soc.h>
11 #include <sound/pcm_params.h>
16 struct snd_soc_card card
;
17 struct clk
*clk_i2s_bus
;
20 /* Spinlock protecting fields below */
22 unsigned int be_sample_rate
;
26 static int odroid_card_fe_startup(struct snd_pcm_substream
*substream
)
28 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
30 snd_pcm_hw_constraint_single(runtime
, SNDRV_PCM_HW_PARAM_CHANNELS
, 2);
35 static int odroid_card_fe_hw_params(struct snd_pcm_substream
*substream
,
36 struct snd_pcm_hw_params
*params
)
38 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
39 struct odroid_priv
*priv
= snd_soc_card_get_drvdata(rtd
->card
);
43 spin_lock_irqsave(&priv
->lock
, flags
);
44 if (priv
->be_active
&& priv
->be_sample_rate
!= params_rate(params
))
46 spin_unlock_irqrestore(&priv
->lock
, flags
);
51 static const struct snd_soc_ops odroid_card_fe_ops
= {
52 .startup
= odroid_card_fe_startup
,
53 .hw_params
= odroid_card_fe_hw_params
,
56 static int odroid_card_be_hw_params(struct snd_pcm_substream
*substream
,
57 struct snd_pcm_hw_params
*params
)
59 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
60 struct odroid_priv
*priv
= snd_soc_card_get_drvdata(rtd
->card
);
61 unsigned int pll_freq
, rclk_freq
, rfs
;
65 switch (params_rate(params
)) {
67 pll_freq
= 196608001U;
72 pll_freq
= 180633609U;
78 pll_freq
= 196608001U;
85 ret
= clk_set_rate(priv
->clk_i2s_bus
, pll_freq
/ 2 + 1);
90 * We add 2 to the rclk_freq value in order to avoid too low clock
91 * frequency values due to the EPLL output frequency not being exact
92 * multiple of the audio sampling rate.
94 rclk_freq
= params_rate(params
) * rfs
+ 2;
96 ret
= clk_set_rate(priv
->sclk_i2s
, rclk_freq
);
100 if (rtd
->num_codecs
> 1) {
101 struct snd_soc_dai
*codec_dai
= rtd
->codec_dais
[1];
103 ret
= snd_soc_dai_set_sysclk(codec_dai
, 0, rclk_freq
,
109 spin_lock_irqsave(&priv
->lock
, flags
);
110 priv
->be_sample_rate
= params_rate(params
);
111 spin_unlock_irqrestore(&priv
->lock
, flags
);
116 static int odroid_card_be_trigger(struct snd_pcm_substream
*substream
, int cmd
)
118 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
119 struct odroid_priv
*priv
= snd_soc_card_get_drvdata(rtd
->card
);
122 spin_lock_irqsave(&priv
->lock
, flags
);
125 case SNDRV_PCM_TRIGGER_START
:
126 case SNDRV_PCM_TRIGGER_RESUME
:
127 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
128 priv
->be_active
= true;
131 case SNDRV_PCM_TRIGGER_STOP
:
132 case SNDRV_PCM_TRIGGER_SUSPEND
:
133 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
134 priv
->be_active
= false;
138 spin_unlock_irqrestore(&priv
->lock
, flags
);
143 static const struct snd_soc_ops odroid_card_be_ops
= {
144 .hw_params
= odroid_card_be_hw_params
,
145 .trigger
= odroid_card_be_trigger
,
148 /* DAPM routes for backward compatibility with old DTS */
149 static const struct snd_soc_dapm_route odroid_dapm_routes
[] = {
150 { "I2S Playback", NULL
, "Mixer DAI TX" },
151 { "HiFi Playback", NULL
, "Mixer DAI TX" },
154 SND_SOC_DAILINK_DEFS(primary
,
155 DAILINK_COMP_ARRAY(COMP_EMPTY()),
156 DAILINK_COMP_ARRAY(COMP_DUMMY()),
157 DAILINK_COMP_ARRAY(COMP_PLATFORM("3830000.i2s")));
159 SND_SOC_DAILINK_DEFS(mixer
,
160 DAILINK_COMP_ARRAY(COMP_DUMMY()),
161 DAILINK_COMP_ARRAY(COMP_EMPTY()),
162 DAILINK_COMP_ARRAY(COMP_DUMMY()));
164 SND_SOC_DAILINK_DEFS(secondary
,
165 DAILINK_COMP_ARRAY(COMP_EMPTY()),
166 DAILINK_COMP_ARRAY(COMP_DUMMY()),
167 DAILINK_COMP_ARRAY(COMP_PLATFORM("3830000.i2s-sec")));
169 static struct snd_soc_dai_link odroid_card_dais
[] = {
171 /* Primary FE <-> BE link */
172 .ops
= &odroid_card_fe_ops
,
174 .stream_name
= "Primary",
177 SND_SOC_DAILINK_REG(primary
),
179 /* BE <-> CODECs link */
181 .ops
= &odroid_card_be_ops
,
184 .dai_fmt
= SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
|
185 SND_SOC_DAIFMT_CBS_CFS
,
186 SND_SOC_DAILINK_REG(mixer
),
188 /* Secondary FE <-> BE link */
190 .ops
= &odroid_card_fe_ops
,
192 .stream_name
= "Secondary",
195 SND_SOC_DAILINK_REG(secondary
),
199 static int odroid_audio_probe(struct platform_device
*pdev
)
201 struct device
*dev
= &pdev
->dev
;
202 struct device_node
*cpu_dai
= NULL
;
203 struct device_node
*cpu
, *codec
;
204 struct odroid_priv
*priv
;
205 struct snd_soc_card
*card
;
206 struct snd_soc_dai_link
*link
, *codec_link
;
207 int num_pcms
, ret
, i
;
208 struct of_phandle_args args
= {};
210 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
217 card
->owner
= THIS_MODULE
;
218 card
->fully_routed
= true;
220 spin_lock_init(&priv
->lock
);
221 snd_soc_card_set_drvdata(card
, priv
);
223 ret
= snd_soc_of_parse_card_name(card
, "model");
227 if (of_property_read_bool(dev
->of_node
, "samsung,audio-widgets")) {
228 ret
= snd_soc_of_parse_audio_simple_widgets(card
,
229 "samsung,audio-widgets");
234 if (of_property_read_bool(dev
->of_node
, "samsung,audio-routing")) {
235 ret
= snd_soc_of_parse_audio_routing(card
,
236 "samsung,audio-routing");
241 card
->dai_link
= odroid_card_dais
;
242 card
->num_links
= ARRAY_SIZE(odroid_card_dais
);
244 cpu
= of_get_child_by_name(dev
->of_node
, "cpu");
245 codec
= of_get_child_by_name(dev
->of_node
, "codec");
246 link
= card
->dai_link
;
247 codec_link
= &card
->dai_link
[1];
250 * For backwards compatibility create the secondary CPU DAI link only
251 * if there are 2 CPU DAI entries in the cpu sound-dai property in DT.
252 * Also add required DAPM routes not available in old DTS.
254 num_pcms
= of_count_phandle_with_args(cpu
, "sound-dai",
257 card
->dapm_routes
= odroid_dapm_routes
;
258 card
->num_dapm_routes
= ARRAY_SIZE(odroid_dapm_routes
);
262 for (i
= 0; i
< num_pcms
; i
++, link
+= 2) {
263 ret
= of_parse_phandle_with_args(cpu
, "sound-dai",
264 "#sound-dai-cells", i
, &args
);
269 dev_err(dev
, "sound-dai property parse error: %d\n", ret
);
274 ret
= snd_soc_get_dai_name(&args
, &link
->cpus
->dai_name
);
275 of_node_put(args
.np
);
281 cpu_dai
= of_parse_phandle(cpu
, "sound-dai", 0);
290 ret
= snd_soc_of_get_dai_link_codecs(dev
, codec
, codec_link
);
292 goto err_put_cpu_dai
;
294 /* Set capture capability only for boards with the MAX98090 CODEC */
295 if (codec_link
->num_codecs
> 1) {
296 card
->dai_link
[0].dpcm_capture
= 1;
297 card
->dai_link
[1].dpcm_capture
= 1;
300 priv
->sclk_i2s
= of_clk_get_by_name(cpu_dai
, "i2s_opclk1");
301 if (IS_ERR(priv
->sclk_i2s
)) {
302 ret
= PTR_ERR(priv
->sclk_i2s
);
303 goto err_put_cpu_dai
;
306 priv
->clk_i2s_bus
= of_clk_get_by_name(cpu_dai
, "iis");
307 if (IS_ERR(priv
->clk_i2s_bus
)) {
308 ret
= PTR_ERR(priv
->clk_i2s_bus
);
312 ret
= devm_snd_soc_register_card(dev
, card
);
314 dev_err(dev
, "snd_soc_register_card() failed: %d\n", ret
);
315 goto err_put_clk_i2s
;
318 of_node_put(cpu_dai
);
323 clk_put(priv
->clk_i2s_bus
);
325 clk_put(priv
->sclk_i2s
);
327 of_node_put(cpu_dai
);
328 snd_soc_of_put_dai_link_codecs(codec_link
);
334 static int odroid_audio_remove(struct platform_device
*pdev
)
336 struct odroid_priv
*priv
= platform_get_drvdata(pdev
);
338 snd_soc_of_put_dai_link_codecs(&priv
->card
.dai_link
[1]);
339 clk_put(priv
->sclk_i2s
);
340 clk_put(priv
->clk_i2s_bus
);
345 static const struct of_device_id odroid_audio_of_match
[] = {
346 { .compatible
= "hardkernel,odroid-xu3-audio" },
347 { .compatible
= "hardkernel,odroid-xu4-audio" },
348 { .compatible
= "samsung,odroid-xu3-audio" },
349 { .compatible
= "samsung,odroid-xu4-audio" },
352 MODULE_DEVICE_TABLE(of
, odroid_audio_of_match
);
354 static struct platform_driver odroid_audio_driver
= {
356 .name
= "odroid-audio",
357 .of_match_table
= odroid_audio_of_match
,
358 .pm
= &snd_soc_pm_ops
,
360 .probe
= odroid_audio_probe
,
361 .remove
= odroid_audio_remove
,
363 module_platform_driver(odroid_audio_driver
);
365 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
366 MODULE_DESCRIPTION("Odroid XU3/XU4 audio support");
367 MODULE_LICENSE("GPL v2");