forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/sound/soc/samsung/odroid.c
....@@ -1,12 +1,9 @@
1
-/*
2
- * Copyright (C) 2017 Samsung Electronics Co., Ltd.
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of the GNU General Public License version 2 as
6
- * published by the Free Software Foundation.
7
- */
1
+// SPDX-License-Identifier: GPL-2.0
2
+//
3
+// Copyright (C) 2017 Samsung Electronics Co., Ltd.
84
95 #include <linux/clk.h>
6
+#include <linux/clk-provider.h>
107 #include <linux/of.h>
118 #include <linux/of_device.h>
129 #include <linux/module.h>
....@@ -17,26 +14,52 @@
1714
1815 struct odroid_priv {
1916 struct snd_soc_card card;
20
- struct snd_soc_dai_link dai_link;
21
-
2217 struct clk *clk_i2s_bus;
2318 struct clk *sclk_i2s;
19
+
20
+ /* Spinlock protecting fields below */
21
+ spinlock_t lock;
22
+ unsigned int be_sample_rate;
23
+ bool be_active;
2424 };
2525
26
-static int odroid_card_startup(struct snd_pcm_substream *substream)
26
+static int odroid_card_fe_startup(struct snd_pcm_substream *substream)
2727 {
2828 struct snd_pcm_runtime *runtime = substream->runtime;
2929
3030 snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2);
31
+
3132 return 0;
3233 }
3334
34
-static int odroid_card_hw_params(struct snd_pcm_substream *substream,
35
+static int odroid_card_fe_hw_params(struct snd_pcm_substream *substream,
3536 struct snd_pcm_hw_params *params)
3637 {
37
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
38
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
39
+ struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card);
40
+ unsigned long flags;
41
+ int ret = 0;
42
+
43
+ spin_lock_irqsave(&priv->lock, flags);
44
+ if (priv->be_active && priv->be_sample_rate != params_rate(params))
45
+ ret = -EINVAL;
46
+ spin_unlock_irqrestore(&priv->lock, flags);
47
+
48
+ return ret;
49
+}
50
+
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,
54
+};
55
+
56
+static int odroid_card_be_hw_params(struct snd_pcm_substream *substream,
57
+ struct snd_pcm_hw_params *params)
58
+{
59
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
3860 struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card);
3961 unsigned int pll_freq, rclk_freq, rfs;
62
+ unsigned long flags;
4063 int ret;
4164
4265 switch (params_rate(params)) {
....@@ -75,7 +98,7 @@
7598 return ret;
7699
77100 if (rtd->num_codecs > 1) {
78
- struct snd_soc_dai *codec_dai = rtd->codec_dais[1];
101
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 1);
79102
80103 ret = snd_soc_dai_set_sysclk(codec_dai, 0, rclk_freq,
81104 SND_SOC_CLOCK_IN);
....@@ -83,22 +106,106 @@
83106 return ret;
84107 }
85108
109
+ spin_lock_irqsave(&priv->lock, flags);
110
+ priv->be_sample_rate = params_rate(params);
111
+ spin_unlock_irqrestore(&priv->lock, flags);
112
+
86113 return 0;
87114 }
88115
89
-static const struct snd_soc_ops odroid_card_ops = {
90
- .startup = odroid_card_startup,
91
- .hw_params = odroid_card_hw_params,
116
+static int odroid_card_be_trigger(struct snd_pcm_substream *substream, int cmd)
117
+{
118
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
119
+ struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card);
120
+ unsigned long flags;
121
+
122
+ spin_lock_irqsave(&priv->lock, flags);
123
+
124
+ switch (cmd) {
125
+ case SNDRV_PCM_TRIGGER_START:
126
+ case SNDRV_PCM_TRIGGER_RESUME:
127
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
128
+ priv->be_active = true;
129
+ break;
130
+
131
+ case SNDRV_PCM_TRIGGER_STOP:
132
+ case SNDRV_PCM_TRIGGER_SUSPEND:
133
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
134
+ priv->be_active = false;
135
+ break;
136
+ }
137
+
138
+ spin_unlock_irqrestore(&priv->lock, flags);
139
+
140
+ return 0;
141
+}
142
+
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,
146
+};
147
+
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" },
152
+};
153
+
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")));
158
+
159
+SND_SOC_DAILINK_DEFS(mixer,
160
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
161
+ DAILINK_COMP_ARRAY(COMP_EMPTY()),
162
+ DAILINK_COMP_ARRAY(COMP_DUMMY()));
163
+
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")));
168
+
169
+static struct snd_soc_dai_link odroid_card_dais[] = {
170
+ {
171
+ /* Primary FE <-> BE link */
172
+ .ops = &odroid_card_fe_ops,
173
+ .name = "Primary",
174
+ .stream_name = "Primary",
175
+ .dynamic = 1,
176
+ .dpcm_playback = 1,
177
+ SND_SOC_DAILINK_REG(primary),
178
+ }, {
179
+ /* BE <-> CODECs link */
180
+ .name = "I2S Mixer",
181
+ .ops = &odroid_card_be_ops,
182
+ .no_pcm = 1,
183
+ .dpcm_playback = 1,
184
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
185
+ SND_SOC_DAIFMT_CBS_CFS,
186
+ SND_SOC_DAILINK_REG(mixer),
187
+ }, {
188
+ /* Secondary FE <-> BE link */
189
+ .playback_only = 1,
190
+ .ops = &odroid_card_fe_ops,
191
+ .name = "Secondary",
192
+ .stream_name = "Secondary",
193
+ .dynamic = 1,
194
+ .dpcm_playback = 1,
195
+ SND_SOC_DAILINK_REG(secondary),
196
+ }
92197 };
93198
94199 static int odroid_audio_probe(struct platform_device *pdev)
95200 {
96201 struct device *dev = &pdev->dev;
202
+ struct device_node *cpu_dai = NULL;
97203 struct device_node *cpu, *codec;
98204 struct odroid_priv *priv;
99
- struct snd_soc_dai_link *link;
100205 struct snd_soc_card *card;
101
- int ret;
206
+ struct snd_soc_dai_link *link, *codec_link;
207
+ int num_pcms, ret, i;
208
+ struct of_phandle_args args = {};
102209
103210 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
104211 if (!priv)
....@@ -110,6 +217,7 @@
110217 card->owner = THIS_MODULE;
111218 card->fully_routed = true;
112219
220
+ spin_lock_init(&priv->lock);
113221 snd_soc_card_set_drvdata(card, priv);
114222
115223 ret = snd_soc_of_parse_card_name(card, "model");
....@@ -130,41 +238,72 @@
130238 return ret;
131239 }
132240
133
- link = &priv->dai_link;
134
-
135
- link->ops = &odroid_card_ops;
136
- link->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
137
- SND_SOC_DAIFMT_CBS_CFS;
138
-
139
- card->dai_link = &priv->dai_link;
140
- card->num_links = 1;
241
+ card->dai_link = odroid_card_dais;
242
+ card->num_links = ARRAY_SIZE(odroid_card_dais);
141243
142244 cpu = of_get_child_by_name(dev->of_node, "cpu");
143245 codec = of_get_child_by_name(dev->of_node, "codec");
246
+ link = card->dai_link;
247
+ codec_link = &card->dai_link[1];
144248
145
- link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0);
146
- if (!link->cpu_of_node) {
147
- dev_err(dev, "Failed parsing cpu/sound-dai property\n");
148
- return -EINVAL;
249
+ /*
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.
253
+ */
254
+ num_pcms = of_count_phandle_with_args(cpu, "sound-dai",
255
+ "#sound-dai-cells");
256
+ if (num_pcms == 1) {
257
+ card->dapm_routes = odroid_dapm_routes;
258
+ card->num_dapm_routes = ARRAY_SIZE(odroid_dapm_routes);
259
+ card->num_links--;
149260 }
150261
151
- ret = snd_soc_of_get_dai_link_codecs(dev, codec, link);
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);
265
+ if (ret < 0)
266
+ break;
267
+
268
+ if (!args.np) {
269
+ dev_err(dev, "sound-dai property parse error: %d\n", ret);
270
+ ret = -EINVAL;
271
+ break;
272
+ }
273
+
274
+ ret = snd_soc_get_dai_name(&args, &link->cpus->dai_name);
275
+ of_node_put(args.np);
276
+
277
+ if (ret < 0)
278
+ break;
279
+ }
280
+ if (ret == 0) {
281
+ cpu_dai = of_parse_phandle(cpu, "sound-dai", 0);
282
+ if (!cpu_dai)
283
+ ret = -EINVAL;
284
+ }
285
+
286
+ of_node_put(cpu);
152287 if (ret < 0)
153
- goto err_put_codec_n;
288
+ goto err_put_node;
154289
155
- link->platform_of_node = link->cpu_of_node;
290
+ ret = snd_soc_of_get_dai_link_codecs(dev, codec, codec_link);
291
+ if (ret < 0)
292
+ goto err_put_cpu_dai;
156293
157
- link->name = "Primary";
158
- link->stream_name = link->name;
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;
298
+ }
159299
160
-
161
- priv->sclk_i2s = of_clk_get_by_name(link->cpu_of_node, "i2s_opclk1");
300
+ priv->sclk_i2s = of_clk_get_by_name(cpu_dai, "i2s_opclk1");
162301 if (IS_ERR(priv->sclk_i2s)) {
163302 ret = PTR_ERR(priv->sclk_i2s);
164
- goto err_put_i2s_n;
303
+ goto err_put_cpu_dai;
165304 }
166305
167
- priv->clk_i2s_bus = of_clk_get_by_name(link->cpu_of_node, "iis");
306
+ priv->clk_i2s_bus = of_clk_get_by_name(cpu_dai, "iis");
168307 if (IS_ERR(priv->clk_i2s_bus)) {
169308 ret = PTR_ERR(priv->clk_i2s_bus);
170309 goto err_put_sclk;
....@@ -172,20 +311,23 @@
172311
173312 ret = devm_snd_soc_register_card(dev, card);
174313 if (ret < 0) {
175
- dev_err(dev, "snd_soc_register_card() failed: %d\n", ret);
314
+ dev_err_probe(dev, ret, "snd_soc_register_card() failed\n");
176315 goto err_put_clk_i2s;
177316 }
178317
318
+ of_node_put(cpu_dai);
319
+ of_node_put(codec);
179320 return 0;
180321
181322 err_put_clk_i2s:
182323 clk_put(priv->clk_i2s_bus);
183324 err_put_sclk:
184325 clk_put(priv->sclk_i2s);
185
-err_put_i2s_n:
186
- of_node_put(link->cpu_of_node);
187
-err_put_codec_n:
188
- snd_soc_of_put_dai_link_codecs(link);
326
+err_put_cpu_dai:
327
+ of_node_put(cpu_dai);
328
+ snd_soc_of_put_dai_link_codecs(codec_link);
329
+err_put_node:
330
+ of_node_put(codec);
189331 return ret;
190332 }
191333
....@@ -193,8 +335,7 @@
193335 {
194336 struct odroid_priv *priv = platform_get_drvdata(pdev);
195337
196
- of_node_put(priv->dai_link.cpu_of_node);
197
- snd_soc_of_put_dai_link_codecs(&priv->dai_link);
338
+ snd_soc_of_put_dai_link_codecs(&priv->card.dai_link[1]);
198339 clk_put(priv->sclk_i2s);
199340 clk_put(priv->clk_i2s_bus);
200341