forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4
kernel/sound/soc/generic/simple-card.c
....@@ -9,392 +9,614 @@
99 #include <linux/device.h>
1010 #include <linux/module.h>
1111 #include <linux/of.h>
12
+#include <linux/of_device.h>
1213 #include <linux/platform_device.h>
1314 #include <linux/string.h>
1415 #include <sound/simple_card.h>
1516 #include <sound/soc-dai.h>
1617 #include <sound/soc.h>
1718
18
-struct simple_card_data {
19
- struct snd_soc_card snd_card;
20
- struct simple_dai_props {
21
- struct asoc_simple_dai cpu_dai;
22
- struct asoc_simple_dai codec_dai;
23
- unsigned int mclk_fs;
24
- } *dai_props;
25
- unsigned int mclk_fs;
26
- struct asoc_simple_jack hp_jack;
27
- struct asoc_simple_jack mic_jack;
28
- struct snd_soc_dai_link *dai_link;
29
-};
30
-
31
-#define simple_priv_to_card(priv) (&(priv)->snd_card)
32
-#define simple_priv_to_props(priv, i) ((priv)->dai_props + (i))
33
-#define simple_priv_to_dev(priv) (simple_priv_to_card(priv)->dev)
34
-#define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i))
19
+#define DPCM_SELECTABLE 1
3520
3621 #define DAI "sound-dai"
3722 #define CELL "#sound-dai-cells"
3823 #define PREFIX "simple-audio-card,"
3924
40
-static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
41
-{
42
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
43
- struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
44
- struct simple_dai_props *dai_props =
45
- simple_priv_to_props(priv, rtd->num);
46
- int ret;
47
-
48
- ret = asoc_simple_card_clk_enable(&dai_props->cpu_dai);
49
- if (ret)
50
- return ret;
51
-
52
- ret = asoc_simple_card_clk_enable(&dai_props->codec_dai);
53
- if (ret)
54
- asoc_simple_card_clk_disable(&dai_props->cpu_dai);
55
-
56
- return ret;
57
-}
58
-
59
-static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream)
60
-{
61
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
62
- struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
63
- struct simple_dai_props *dai_props =
64
- simple_priv_to_props(priv, rtd->num);
65
-
66
- asoc_simple_card_clk_disable(&dai_props->cpu_dai);
67
-
68
- asoc_simple_card_clk_disable(&dai_props->codec_dai);
69
-}
70
-
71
-static int asoc_simple_set_clk_rate(struct asoc_simple_dai *simple_dai,
72
- unsigned long rate)
73
-{
74
- if (!simple_dai->clk)
75
- return 0;
76
-
77
- if (clk_get_rate(simple_dai->clk) == rate)
78
- return 0;
79
-
80
- return clk_set_rate(simple_dai->clk, rate);
81
-}
82
-
83
-static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream,
84
- struct snd_pcm_hw_params *params)
85
-{
86
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
87
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
88
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
89
- struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
90
- struct simple_dai_props *dai_props =
91
- simple_priv_to_props(priv, rtd->num);
92
- unsigned int mclk, mclk_fs = 0;
93
- int ret = 0;
94
-
95
- if (priv->mclk_fs)
96
- mclk_fs = priv->mclk_fs;
97
- else if (dai_props->mclk_fs)
98
- mclk_fs = dai_props->mclk_fs;
99
-
100
- if (mclk_fs) {
101
- mclk = params_rate(params) * mclk_fs;
102
-
103
- ret = asoc_simple_set_clk_rate(&dai_props->codec_dai, mclk);
104
- if (ret < 0)
105
- return ret;
106
-
107
- ret = asoc_simple_set_clk_rate(&dai_props->cpu_dai, mclk);
108
- if (ret < 0)
109
- return ret;
110
-
111
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
112
- SND_SOC_CLOCK_IN);
113
- if (ret && ret != -ENOTSUPP)
114
- goto err;
115
-
116
- ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
117
- SND_SOC_CLOCK_OUT);
118
- if (ret && ret != -ENOTSUPP)
119
- goto err;
120
- }
121
- return 0;
122
-err:
123
- return ret;
124
-}
125
-
126
-static const struct snd_soc_ops asoc_simple_card_ops = {
127
- .startup = asoc_simple_card_startup,
128
- .shutdown = asoc_simple_card_shutdown,
129
- .hw_params = asoc_simple_card_hw_params,
25
+static const struct snd_soc_ops simple_ops = {
26
+ .startup = asoc_simple_startup,
27
+ .shutdown = asoc_simple_shutdown,
28
+ .hw_params = asoc_simple_hw_params,
13029 };
13130
132
-static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
31
+static int asoc_simple_parse_dai(struct device_node *node,
32
+ struct snd_soc_dai_link_component *dlc,
33
+ int *is_single_link)
13334 {
134
- struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
135
- struct snd_soc_dai *codec = rtd->codec_dai;
136
- struct snd_soc_dai *cpu = rtd->cpu_dai;
137
- struct simple_dai_props *dai_props =
138
- simple_priv_to_props(priv, rtd->num);
35
+ struct of_phandle_args args;
13936 int ret;
14037
141
- ret = asoc_simple_card_init_dai(codec, &dai_props->codec_dai);
38
+ if (!node)
39
+ return 0;
40
+
41
+ /*
42
+ * Get node via "sound-dai = <&phandle port>"
43
+ * it will be used as xxx_of_node on soc_bind_dai_link()
44
+ */
45
+ ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args);
46
+ if (ret)
47
+ return ret;
48
+
49
+ /*
50
+ * FIXME
51
+ *
52
+ * Here, dlc->dai_name is pointer to CPU/Codec DAI name.
53
+ * If user unbinded CPU or Codec driver, but not for Sound Card,
54
+ * dlc->dai_name is keeping unbinded CPU or Codec
55
+ * driver's pointer.
56
+ *
57
+ * If user re-bind CPU or Codec driver again, ALSA SoC will try
58
+ * to rebind Card via snd_soc_try_rebind_card(), but because of
59
+ * above reason, it might can't bind Sound Card.
60
+ * Because Sound Card is pointing to released dai_name pointer.
61
+ *
62
+ * To avoid this rebind Card issue,
63
+ * 1) It needs to alloc memory to keep dai_name eventhough
64
+ * CPU or Codec driver was unbinded, or
65
+ * 2) user need to rebind Sound Card everytime
66
+ * if he unbinded CPU or Codec.
67
+ */
68
+ ret = snd_soc_of_get_dai_name(node, &dlc->dai_name);
14269 if (ret < 0)
14370 return ret;
14471
145
- ret = asoc_simple_card_init_dai(cpu, &dai_props->cpu_dai);
146
- if (ret < 0)
147
- return ret;
72
+ dlc->of_node = args.np;
73
+
74
+ if (is_single_link)
75
+ *is_single_link = !args.args_count;
14876
14977 return 0;
15078 }
15179
152
-static int asoc_simple_card_dai_link_of(struct device_node *node,
153
- struct simple_card_data *priv,
154
- int idx,
155
- bool is_top_level_node)
80
+static void simple_parse_convert(struct device *dev,
81
+ struct device_node *np,
82
+ struct asoc_simple_data *adata)
83
+{
84
+ struct device_node *top = dev->of_node;
85
+ struct device_node *node = of_get_parent(np);
86
+
87
+ asoc_simple_parse_convert(dev, top, PREFIX, adata);
88
+ asoc_simple_parse_convert(dev, node, PREFIX, adata);
89
+ asoc_simple_parse_convert(dev, node, NULL, adata);
90
+ asoc_simple_parse_convert(dev, np, NULL, adata);
91
+
92
+ of_node_put(node);
93
+}
94
+
95
+static void simple_parse_mclk_fs(struct device_node *top,
96
+ struct device_node *cpu,
97
+ struct device_node *codec,
98
+ struct simple_dai_props *props,
99
+ char *prefix)
100
+{
101
+ struct device_node *node = of_get_parent(cpu);
102
+ char prop[128];
103
+
104
+ snprintf(prop, sizeof(prop), "%smclk-fs", PREFIX);
105
+ of_property_read_u32(top, prop, &props->mclk_fs);
106
+
107
+ snprintf(prop, sizeof(prop), "%smclk-fs", prefix);
108
+ of_property_read_u32(node, prop, &props->mclk_fs);
109
+ of_property_read_u32(cpu, prop, &props->mclk_fs);
110
+ of_property_read_u32(codec, prop, &props->mclk_fs);
111
+
112
+ of_node_put(node);
113
+}
114
+
115
+static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
116
+ struct device_node *np,
117
+ struct device_node *codec,
118
+ struct link_info *li,
119
+ bool is_top)
156120 {
157121 struct device *dev = simple_priv_to_dev(priv);
158
- struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
159
- struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx);
160
- struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai;
161
- struct asoc_simple_dai *codec_dai = &dai_props->codec_dai;
162
- struct device_node *cpu = NULL;
163
- struct device_node *plat = NULL;
164
- struct device_node *codec = NULL;
165
- char prop[128];
122
+ struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
123
+ struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
124
+ struct asoc_simple_dai *dai;
125
+ struct snd_soc_dai_link_component *cpus = dai_link->cpus;
126
+ struct snd_soc_dai_link_component *codecs = dai_link->codecs;
127
+ struct device_node *top = dev->of_node;
128
+ struct device_node *node = of_get_parent(np);
166129 char *prefix = "";
167
- int ret, single_cpu;
130
+ int ret;
131
+
132
+ /*
133
+ * |CPU |Codec : turn
134
+ * CPU |Pass |return
135
+ * Codec |return|Pass
136
+ * np
137
+ */
138
+ if (li->cpu == (np == codec))
139
+ return 0;
140
+
141
+ dev_dbg(dev, "link_of DPCM (%pOF)\n", np);
142
+
143
+ li->link++;
168144
169145 /* For single DAI link & old style of DT node */
170
- if (is_top_level_node)
146
+ if (is_top)
171147 prefix = PREFIX;
172148
173
- snprintf(prop, sizeof(prop), "%scpu", prefix);
174
- cpu = of_get_child_by_name(node, prop);
149
+ if (li->cpu) {
150
+ int is_single_links = 0;
175151
176
- if (!cpu) {
177
- ret = -EINVAL;
178
- dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
179
- goto dai_link_of_err;
152
+ /* Codec is dummy */
153
+ codecs->of_node = NULL;
154
+ codecs->dai_name = "snd-soc-dummy-dai";
155
+ codecs->name = "snd-soc-dummy";
156
+
157
+ /* FE settings */
158
+ dai_link->dynamic = 1;
159
+ dai_link->dpcm_merged_format = 1;
160
+
161
+ dai =
162
+ dai_props->cpu_dai = &priv->dais[li->dais++];
163
+
164
+ ret = asoc_simple_parse_cpu(np, dai_link, &is_single_links);
165
+ if (ret)
166
+ goto out_put_node;
167
+
168
+ ret = asoc_simple_parse_clk_cpu(dev, np, dai_link, dai);
169
+ if (ret < 0)
170
+ goto out_put_node;
171
+
172
+ ret = asoc_simple_set_dailink_name(dev, dai_link,
173
+ "fe.%s",
174
+ cpus->dai_name);
175
+ if (ret < 0)
176
+ goto out_put_node;
177
+
178
+ asoc_simple_canonicalize_cpu(dai_link, is_single_links);
179
+ } else {
180
+ struct snd_soc_codec_conf *cconf;
181
+
182
+ /* CPU is dummy */
183
+ cpus->of_node = NULL;
184
+ cpus->dai_name = "snd-soc-dummy-dai";
185
+ cpus->name = "snd-soc-dummy";
186
+
187
+ /* BE settings */
188
+ dai_link->no_pcm = 1;
189
+ dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup;
190
+
191
+ dai =
192
+ dai_props->codec_dai = &priv->dais[li->dais++];
193
+
194
+ cconf =
195
+ dai_props->codec_conf = &priv->codec_conf[li->conf++];
196
+
197
+ ret = asoc_simple_parse_codec(np, dai_link);
198
+ if (ret < 0)
199
+ goto out_put_node;
200
+
201
+ ret = asoc_simple_parse_clk_codec(dev, np, dai_link, dai);
202
+ if (ret < 0)
203
+ goto out_put_node;
204
+
205
+ ret = asoc_simple_set_dailink_name(dev, dai_link,
206
+ "be.%s",
207
+ codecs->dai_name);
208
+ if (ret < 0)
209
+ goto out_put_node;
210
+
211
+ /* check "prefix" from top node */
212
+ snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
213
+ PREFIX "prefix");
214
+ snd_soc_of_parse_node_prefix(node, cconf, codecs->of_node,
215
+ "prefix");
216
+ snd_soc_of_parse_node_prefix(np, cconf, codecs->of_node,
217
+ "prefix");
180218 }
219
+
220
+ simple_parse_convert(dev, np, &dai_props->adata);
221
+ simple_parse_mclk_fs(top, np, codec, dai_props, prefix);
222
+
223
+ asoc_simple_canonicalize_platform(dai_link);
224
+
225
+ ret = asoc_simple_parse_tdm(np, dai);
226
+ if (ret)
227
+ goto out_put_node;
228
+
229
+ ret = asoc_simple_parse_daifmt(dev, node, codec,
230
+ prefix, &dai_link->dai_fmt);
231
+ if (ret < 0)
232
+ goto out_put_node;
233
+
234
+ snd_soc_dai_link_set_capabilities(dai_link);
235
+
236
+ dai_link->ops = &simple_ops;
237
+ dai_link->init = asoc_simple_dai_init;
238
+
239
+out_put_node:
240
+ of_node_put(node);
241
+ return ret;
242
+}
243
+
244
+static int simple_dai_link_of(struct asoc_simple_priv *priv,
245
+ struct device_node *np,
246
+ struct device_node *codec,
247
+ struct link_info *li,
248
+ bool is_top)
249
+{
250
+ struct device *dev = simple_priv_to_dev(priv);
251
+ struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
252
+ struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
253
+ struct asoc_simple_dai *cpu_dai;
254
+ struct asoc_simple_dai *codec_dai;
255
+ struct device_node *top = dev->of_node;
256
+ struct device_node *cpu = NULL;
257
+ struct device_node *node = NULL;
258
+ struct device_node *plat = NULL;
259
+ char prop[128];
260
+ char *prefix = "";
261
+ int ret, single_cpu = 0;
262
+
263
+ /*
264
+ * |CPU |Codec : turn
265
+ * CPU |Pass |return
266
+ * Codec |return|return
267
+ * np
268
+ */
269
+ if (!li->cpu || np == codec)
270
+ return 0;
271
+
272
+ cpu = np;
273
+ node = of_get_parent(np);
274
+ li->link++;
275
+
276
+ dev_dbg(dev, "link_of (%pOF)\n", node);
277
+
278
+ /* For single DAI link & old style of DT node */
279
+ if (is_top)
280
+ prefix = PREFIX;
181281
182282 snprintf(prop, sizeof(prop), "%splat", prefix);
183283 plat = of_get_child_by_name(node, prop);
184284
185
- snprintf(prop, sizeof(prop), "%scodec", prefix);
186
- codec = of_get_child_by_name(node, prop);
285
+ cpu_dai =
286
+ dai_props->cpu_dai = &priv->dais[li->dais++];
287
+ codec_dai =
288
+ dai_props->codec_dai = &priv->dais[li->dais++];
187289
188
- if (!codec) {
189
- ret = -EINVAL;
190
- dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
191
- goto dai_link_of_err;
192
- }
193
-
194
- ret = asoc_simple_card_parse_daifmt(dev, node, codec,
195
- prefix, &dai_link->dai_fmt);
290
+ ret = asoc_simple_parse_daifmt(dev, node, codec,
291
+ prefix, &dai_link->dai_fmt);
196292 if (ret < 0)
197293 goto dai_link_of_err;
198294
199
- of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs);
295
+ simple_parse_mclk_fs(top, cpu, codec, dai_props, prefix);
200296
201
- ret = asoc_simple_card_parse_cpu(cpu, dai_link,
202
- DAI, CELL, &single_cpu);
297
+ ret = asoc_simple_parse_cpu(cpu, dai_link, &single_cpu);
203298 if (ret < 0)
204299 goto dai_link_of_err;
205300
206
- ret = asoc_simple_card_parse_codec(codec, dai_link, DAI, CELL);
301
+ ret = asoc_simple_parse_codec(codec, dai_link);
207302 if (ret < 0)
208303 goto dai_link_of_err;
209304
210
- ret = asoc_simple_card_parse_platform(plat, dai_link, DAI, CELL);
305
+ ret = asoc_simple_parse_platform(plat, dai_link);
211306 if (ret < 0)
212307 goto dai_link_of_err;
213308
214
- ret = asoc_simple_card_of_parse_tdm(cpu, cpu_dai);
309
+ ret = asoc_simple_parse_tdm(cpu, cpu_dai);
215310 if (ret < 0)
216311 goto dai_link_of_err;
217312
218
- ret = asoc_simple_card_of_parse_tdm(codec, codec_dai);
313
+ ret = asoc_simple_parse_tdm(codec, codec_dai);
219314 if (ret < 0)
220315 goto dai_link_of_err;
221316
222
- ret = asoc_simple_card_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
317
+ ret = asoc_simple_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
223318 if (ret < 0)
224319 goto dai_link_of_err;
225320
226
- ret = asoc_simple_card_parse_clk_codec(dev, codec, dai_link, codec_dai);
321
+ ret = asoc_simple_parse_clk_codec(dev, codec, dai_link, codec_dai);
227322 if (ret < 0)
228323 goto dai_link_of_err;
229324
230
- ret = asoc_simple_card_canonicalize_dailink(dai_link);
325
+ ret = asoc_simple_set_dailink_name(dev, dai_link,
326
+ "%s-%s",
327
+ dai_link->cpus->dai_name,
328
+ dai_link->codecs->dai_name);
231329 if (ret < 0)
232330 goto dai_link_of_err;
233331
234
- ret = asoc_simple_card_set_dailink_name(dev, dai_link,
235
- "%s-%s",
236
- dai_link->cpu_dai_name,
237
- dai_link->codec_dai_name);
238
- if (ret < 0)
239
- goto dai_link_of_err;
332
+ dai_link->ops = &simple_ops;
333
+ dai_link->init = asoc_simple_dai_init;
240334
241
- dai_link->ops = &asoc_simple_card_ops;
242
- dai_link->init = asoc_simple_card_dai_init;
243
-
244
- asoc_simple_card_canonicalize_cpu(dai_link, single_cpu);
335
+ asoc_simple_canonicalize_cpu(dai_link, single_cpu);
336
+ asoc_simple_canonicalize_platform(dai_link);
245337
246338 dai_link_of_err:
247
- of_node_put(cpu);
248
- of_node_put(codec);
339
+ of_node_put(plat);
340
+ of_node_put(node);
249341
250342 return ret;
251343 }
252344
253
-static int asoc_simple_card_parse_aux_devs(struct device_node *node,
254
- struct simple_card_data *priv)
345
+static int simple_for_each_link(struct asoc_simple_priv *priv,
346
+ struct link_info *li,
347
+ int (*func_noml)(struct asoc_simple_priv *priv,
348
+ struct device_node *np,
349
+ struct device_node *codec,
350
+ struct link_info *li, bool is_top),
351
+ int (*func_dpcm)(struct asoc_simple_priv *priv,
352
+ struct device_node *np,
353
+ struct device_node *codec,
354
+ struct link_info *li, bool is_top))
255355 {
256356 struct device *dev = simple_priv_to_dev(priv);
257
- struct device_node *aux_node;
258
- struct snd_soc_card *card = simple_priv_to_card(priv);
259
- int i, n, len;
357
+ struct device_node *top = dev->of_node;
358
+ struct device_node *node;
359
+ uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev);
360
+ bool is_top = 0;
361
+ int ret = 0;
260362
261
- if (!of_find_property(node, PREFIX "aux-devs", &len))
262
- return 0; /* Ok to have no aux-devs */
263
-
264
- n = len / sizeof(__be32);
265
- if (n <= 0)
266
- return -EINVAL;
267
-
268
- card->aux_dev = devm_kcalloc(dev,
269
- n, sizeof(*card->aux_dev), GFP_KERNEL);
270
- if (!card->aux_dev)
271
- return -ENOMEM;
272
-
273
- for (i = 0; i < n; i++) {
274
- aux_node = of_parse_phandle(node, PREFIX "aux-devs", i);
275
- if (!aux_node)
276
- return -EINVAL;
277
- card->aux_dev[i].codec_of_node = aux_node;
363
+ /* Check if it has dai-link */
364
+ node = of_get_child_by_name(top, PREFIX "dai-link");
365
+ if (!node) {
366
+ node = of_node_get(top);
367
+ is_top = 1;
278368 }
279369
280
- card->num_aux_devs = n;
281
- return 0;
370
+ /* loop for all dai-link */
371
+ do {
372
+ struct asoc_simple_data adata;
373
+ struct device_node *codec;
374
+ struct device_node *plat;
375
+ struct device_node *np;
376
+ int num = of_get_child_count(node);
377
+
378
+ /* get codec */
379
+ codec = of_get_child_by_name(node, is_top ?
380
+ PREFIX "codec" : "codec");
381
+ if (!codec) {
382
+ ret = -ENODEV;
383
+ goto error;
384
+ }
385
+ /* get platform */
386
+ plat = of_get_child_by_name(node, is_top ?
387
+ PREFIX "plat" : "plat");
388
+
389
+ /* get convert-xxx property */
390
+ memset(&adata, 0, sizeof(adata));
391
+ for_each_child_of_node(node, np)
392
+ simple_parse_convert(dev, np, &adata);
393
+
394
+ /* loop for all CPU/Codec node */
395
+ for_each_child_of_node(node, np) {
396
+ if (plat == np)
397
+ continue;
398
+ /*
399
+ * It is DPCM
400
+ * if it has many CPUs,
401
+ * or has convert-xxx property
402
+ */
403
+ if (dpcm_selectable &&
404
+ (num > 2 ||
405
+ adata.convert_rate || adata.convert_channels))
406
+ ret = func_dpcm(priv, np, codec, li, is_top);
407
+ /* else normal sound */
408
+ else
409
+ ret = func_noml(priv, np, codec, li, is_top);
410
+
411
+ if (ret < 0) {
412
+ of_node_put(codec);
413
+ of_node_put(np);
414
+ goto error;
415
+ }
416
+ }
417
+
418
+ of_node_put(codec);
419
+ node = of_get_next_child(top, node);
420
+ } while (!is_top && node);
421
+
422
+ error:
423
+ of_node_put(node);
424
+ return ret;
282425 }
283426
284
-static int asoc_simple_card_parse_of(struct simple_card_data *priv)
427
+static int simple_parse_of(struct asoc_simple_priv *priv)
285428 {
286429 struct device *dev = simple_priv_to_dev(priv);
430
+ struct device_node *top = dev->of_node;
287431 struct snd_soc_card *card = simple_priv_to_card(priv);
288
- struct device_node *dai_link;
289
- struct device_node *node = dev->of_node;
432
+ struct link_info li;
290433 int ret;
291434
292
- if (!node)
435
+ if (!top)
293436 return -EINVAL;
294437
295
- dai_link = of_get_child_by_name(node, PREFIX "dai-link");
296
-
297
- ret = asoc_simple_card_of_parse_widgets(card, PREFIX);
438
+ ret = asoc_simple_parse_widgets(card, PREFIX);
298439 if (ret < 0)
299
- goto card_parse_end;
440
+ return ret;
300441
301
- ret = asoc_simple_card_of_parse_routing(card, PREFIX, 1);
442
+ ret = asoc_simple_parse_routing(card, PREFIX);
302443 if (ret < 0)
303
- goto card_parse_end;
444
+ return ret;
304445
305
- /* Factor to mclk, used in hw_params() */
306
- of_property_read_u32(node, PREFIX "mclk-fs", &priv->mclk_fs);
446
+ ret = asoc_simple_parse_pin_switches(card, PREFIX);
447
+ if (ret < 0)
448
+ return ret;
307449
308450 /* Single/Muti DAI link(s) & New style of DT node */
309
- if (dai_link) {
310
- struct device_node *np = NULL;
311
- int i = 0;
312
-
313
- for_each_child_of_node(node, np) {
314
- dev_dbg(dev, "\tlink %d:\n", i);
315
- ret = asoc_simple_card_dai_link_of(np, priv,
316
- i, false);
317
- if (ret < 0) {
318
- of_node_put(np);
319
- goto card_parse_end;
320
- }
321
- i++;
322
- }
323
- } else {
324
- /* For single DAI link & old style of DT node */
325
- ret = asoc_simple_card_dai_link_of(node, priv, 0, true);
451
+ memset(&li, 0, sizeof(li));
452
+ for (li.cpu = 1; li.cpu >= 0; li.cpu--) {
453
+ /*
454
+ * Detect all CPU first, and Detect all Codec 2nd.
455
+ *
456
+ * In Normal sound case, all DAIs are detected
457
+ * as "CPU-Codec".
458
+ *
459
+ * In DPCM sound case,
460
+ * all CPUs are detected as "CPU-dummy", and
461
+ * all Codecs are detected as "dummy-Codec".
462
+ * To avoid random sub-device numbering,
463
+ * detect "dummy-Codec" in last;
464
+ */
465
+ ret = simple_for_each_link(priv, &li,
466
+ simple_dai_link_of,
467
+ simple_dai_link_of_dpcm);
326468 if (ret < 0)
327
- goto card_parse_end;
469
+ return ret;
328470 }
329471
330
- ret = asoc_simple_card_parse_card_name(card, PREFIX);
472
+ ret = asoc_simple_parse_card_name(card, PREFIX);
331473 if (ret < 0)
332
- goto card_parse_end;
474
+ return ret;
333475
334
- ret = asoc_simple_card_parse_aux_devs(node, priv);
335
-
336
-card_parse_end:
337
- of_node_put(dai_link);
476
+ ret = snd_soc_of_parse_aux_devs(card, PREFIX "aux-devs");
338477
339478 return ret;
340479 }
341480
342
-static int asoc_simple_soc_card_probe(struct snd_soc_card *card)
481
+static int simple_count_noml(struct asoc_simple_priv *priv,
482
+ struct device_node *np,
483
+ struct device_node *codec,
484
+ struct link_info *li, bool is_top)
343485 {
344
- struct simple_card_data *priv = snd_soc_card_get_drvdata(card);
486
+ li->dais++; /* CPU or Codec */
487
+ if (np != codec)
488
+ li->link++; /* CPU-Codec */
489
+
490
+ return 0;
491
+}
492
+
493
+static int simple_count_dpcm(struct asoc_simple_priv *priv,
494
+ struct device_node *np,
495
+ struct device_node *codec,
496
+ struct link_info *li, bool is_top)
497
+{
498
+ li->dais++; /* CPU or Codec */
499
+ li->link++; /* CPU-dummy or dummy-Codec */
500
+ if (np == codec)
501
+ li->conf++;
502
+
503
+ return 0;
504
+}
505
+
506
+static void simple_get_dais_count(struct asoc_simple_priv *priv,
507
+ struct link_info *li)
508
+{
509
+ struct device *dev = simple_priv_to_dev(priv);
510
+ struct device_node *top = dev->of_node;
511
+
512
+ /*
513
+ * link_num : number of links.
514
+ * CPU-Codec / CPU-dummy / dummy-Codec
515
+ * dais_num : number of DAIs
516
+ * ccnf_num : number of codec_conf
517
+ * same number for "dummy-Codec"
518
+ *
519
+ * ex1)
520
+ * CPU0 --- Codec0 link : 5
521
+ * CPU1 --- Codec1 dais : 7
522
+ * CPU2 -/ ccnf : 1
523
+ * CPU3 --- Codec2
524
+ *
525
+ * => 5 links = 2xCPU-Codec + 2xCPU-dummy + 1xdummy-Codec
526
+ * => 7 DAIs = 4xCPU + 3xCodec
527
+ * => 1 ccnf = 1xdummy-Codec
528
+ *
529
+ * ex2)
530
+ * CPU0 --- Codec0 link : 5
531
+ * CPU1 --- Codec1 dais : 6
532
+ * CPU2 -/ ccnf : 1
533
+ * CPU3 -/
534
+ *
535
+ * => 5 links = 1xCPU-Codec + 3xCPU-dummy + 1xdummy-Codec
536
+ * => 6 DAIs = 4xCPU + 2xCodec
537
+ * => 1 ccnf = 1xdummy-Codec
538
+ *
539
+ * ex3)
540
+ * CPU0 --- Codec0 link : 6
541
+ * CPU1 -/ dais : 6
542
+ * CPU2 --- Codec1 ccnf : 2
543
+ * CPU3 -/
544
+ *
545
+ * => 6 links = 0xCPU-Codec + 4xCPU-dummy + 2xdummy-Codec
546
+ * => 6 DAIs = 4xCPU + 2xCodec
547
+ * => 2 ccnf = 2xdummy-Codec
548
+ *
549
+ * ex4)
550
+ * CPU0 --- Codec0 (convert-rate) link : 3
551
+ * CPU1 --- Codec1 dais : 4
552
+ * ccnf : 1
553
+ *
554
+ * => 3 links = 1xCPU-Codec + 1xCPU-dummy + 1xdummy-Codec
555
+ * => 4 DAIs = 2xCPU + 2xCodec
556
+ * => 1 ccnf = 1xdummy-Codec
557
+ */
558
+ if (!top) {
559
+ li->link = 1;
560
+ li->dais = 2;
561
+ li->conf = 0;
562
+ return;
563
+ }
564
+
565
+ simple_for_each_link(priv, li,
566
+ simple_count_noml,
567
+ simple_count_dpcm);
568
+
569
+ dev_dbg(dev, "link %d, dais %d, ccnf %d\n",
570
+ li->link, li->dais, li->conf);
571
+}
572
+
573
+static int simple_soc_probe(struct snd_soc_card *card)
574
+{
575
+ struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card);
345576 int ret;
346577
347
- ret = asoc_simple_card_init_hp(card, &priv->hp_jack, PREFIX);
578
+ ret = asoc_simple_init_hp(card, &priv->hp_jack, PREFIX);
348579 if (ret < 0)
349580 return ret;
350581
351
- ret = asoc_simple_card_init_mic(card, &priv->mic_jack, PREFIX);
582
+ ret = asoc_simple_init_mic(card, &priv->mic_jack, PREFIX);
352583 if (ret < 0)
353584 return ret;
354585
355586 return 0;
356587 }
357588
358
-static int asoc_simple_card_probe(struct platform_device *pdev)
589
+static int asoc_simple_probe(struct platform_device *pdev)
359590 {
360
- struct simple_card_data *priv;
361
- struct snd_soc_dai_link *dai_link;
362
- struct simple_dai_props *dai_props;
591
+ struct asoc_simple_priv *priv;
363592 struct device *dev = &pdev->dev;
364593 struct device_node *np = dev->of_node;
365594 struct snd_soc_card *card;
366
- int num, ret;
367
-
368
- /* Get the number of DAI links */
369
- if (np && of_get_child_by_name(np, PREFIX "dai-link"))
370
- num = of_get_child_count(np);
371
- else
372
- num = 1;
595
+ struct link_info li;
596
+ int ret;
373597
374598 /* Allocate the private data and the DAI link array */
375599 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
376600 if (!priv)
377601 return -ENOMEM;
378602
379
- dai_props = devm_kcalloc(dev, num, sizeof(*dai_props), GFP_KERNEL);
380
- dai_link = devm_kcalloc(dev, num, sizeof(*dai_link), GFP_KERNEL);
381
- if (!dai_props || !dai_link)
382
- return -ENOMEM;
383
-
384
- priv->dai_props = dai_props;
385
- priv->dai_link = dai_link;
386
-
387
- /* Init snd_soc_card */
388603 card = simple_priv_to_card(priv);
389604 card->owner = THIS_MODULE;
390605 card->dev = dev;
391
- card->dai_link = priv->dai_link;
392
- card->num_links = num;
393
- card->probe = asoc_simple_soc_card_probe;
606
+ card->probe = simple_soc_probe;
607
+
608
+ memset(&li, 0, sizeof(li));
609
+ simple_get_dais_count(priv, &li);
610
+ if (!li.link || !li.dais)
611
+ return -EINVAL;
612
+
613
+ ret = asoc_simple_init_priv(priv, &li);
614
+ if (ret < 0)
615
+ return ret;
394616
395617 if (np && of_device_is_available(np)) {
396618
397
- ret = asoc_simple_card_parse_of(priv);
619
+ ret = simple_parse_of(priv);
398620 if (ret < 0) {
399621 if (ret != -EPROBE_DEFER)
400622 dev_err(dev, "parse error %d\n", ret);
....@@ -403,6 +625,13 @@
403625
404626 } else {
405627 struct asoc_simple_card_info *cinfo;
628
+ struct snd_soc_dai_link_component *cpus;
629
+ struct snd_soc_dai_link_component *codecs;
630
+ struct snd_soc_dai_link_component *platform;
631
+ struct snd_soc_dai_link *dai_link = priv->dai_link;
632
+ struct simple_dai_props *dai_props = priv->dai_props;
633
+
634
+ int dai_idx = 0;
406635
407636 cinfo = dev->platform_data;
408637 if (!cinfo) {
....@@ -419,22 +648,33 @@
419648 return -EINVAL;
420649 }
421650
651
+ dai_props->cpu_dai = &priv->dais[dai_idx++];
652
+ dai_props->codec_dai = &priv->dais[dai_idx++];
653
+
654
+ cpus = dai_link->cpus;
655
+ cpus->dai_name = cinfo->cpu_dai.name;
656
+
657
+ codecs = dai_link->codecs;
658
+ codecs->name = cinfo->codec;
659
+ codecs->dai_name = cinfo->codec_dai.name;
660
+
661
+ platform = dai_link->platforms;
662
+ platform->name = cinfo->platform;
663
+
422664 card->name = (cinfo->card) ? cinfo->card : cinfo->name;
423665 dai_link->name = cinfo->name;
424666 dai_link->stream_name = cinfo->name;
425
- dai_link->platform_name = cinfo->platform;
426
- dai_link->codec_name = cinfo->codec;
427
- dai_link->cpu_dai_name = cinfo->cpu_dai.name;
428
- dai_link->codec_dai_name = cinfo->codec_dai.name;
429667 dai_link->dai_fmt = cinfo->daifmt;
430
- dai_link->init = asoc_simple_card_dai_init;
431
- memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai,
432
- sizeof(priv->dai_props->cpu_dai));
433
- memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai,
434
- sizeof(priv->dai_props->codec_dai));
668
+ dai_link->init = asoc_simple_dai_init;
669
+ memcpy(dai_props->cpu_dai, &cinfo->cpu_dai,
670
+ sizeof(*dai_props->cpu_dai));
671
+ memcpy(dai_props->codec_dai, &cinfo->codec_dai,
672
+ sizeof(*dai_props->codec_dai));
435673 }
436674
437675 snd_soc_card_set_drvdata(card, priv);
676
+
677
+ asoc_simple_debug_info(priv);
438678
439679 ret = devm_snd_soc_register_card(dev, card);
440680 if (ret < 0)
....@@ -442,32 +682,34 @@
442682
443683 return 0;
444684 err:
445
- asoc_simple_card_clean_reference(card);
685
+ asoc_simple_clean_reference(card);
446686
447687 return ret;
448688 }
449689
450
-static int asoc_simple_card_remove(struct platform_device *pdev)
690
+static int asoc_simple_remove(struct platform_device *pdev)
451691 {
452692 struct snd_soc_card *card = platform_get_drvdata(pdev);
453693
454
- return asoc_simple_card_clean_reference(card);
694
+ return asoc_simple_clean_reference(card);
455695 }
456696
457
-static const struct of_device_id asoc_simple_of_match[] = {
697
+static const struct of_device_id simple_of_match[] = {
458698 { .compatible = "simple-audio-card", },
699
+ { .compatible = "simple-scu-audio-card",
700
+ .data = (void *)DPCM_SELECTABLE },
459701 {},
460702 };
461
-MODULE_DEVICE_TABLE(of, asoc_simple_of_match);
703
+MODULE_DEVICE_TABLE(of, simple_of_match);
462704
463705 static struct platform_driver asoc_simple_card = {
464706 .driver = {
465707 .name = "asoc-simple-card",
466708 .pm = &snd_soc_pm_ops,
467
- .of_match_table = asoc_simple_of_match,
709
+ .of_match_table = simple_of_match,
468710 },
469
- .probe = asoc_simple_card_probe,
470
- .remove = asoc_simple_card_remove,
711
+ .probe = asoc_simple_probe,
712
+ .remove = asoc_simple_remove,
471713 };
472714
473715 module_platform_driver(asoc_simple_card);