hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/sound/soc/generic/simple-card.c
....@@ -9,392 +9,615 @@
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, substream->stream, mclk,
112
- SND_SOC_CLOCK_IN);
113
- if (ret && ret != -ENOTSUPP)
114
- goto err;
115
-
116
- ret = snd_soc_dai_set_sysclk(cpu_dai, substream->stream, 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(plat);
414
+ of_node_put(np);
415
+ goto error;
416
+ }
417
+ }
418
+
419
+ of_node_put(codec);
420
+ node = of_get_next_child(top, node);
421
+ } while (!is_top && node);
422
+
423
+ error:
424
+ of_node_put(node);
425
+ return ret;
282426 }
283427
284
-static int asoc_simple_card_parse_of(struct simple_card_data *priv)
428
+static int simple_parse_of(struct asoc_simple_priv *priv)
285429 {
286430 struct device *dev = simple_priv_to_dev(priv);
431
+ struct device_node *top = dev->of_node;
287432 struct snd_soc_card *card = simple_priv_to_card(priv);
288
- struct device_node *dai_link;
289
- struct device_node *node = dev->of_node;
433
+ struct link_info li;
290434 int ret;
291435
292
- if (!node)
436
+ if (!top)
293437 return -EINVAL;
294438
295
- dai_link = of_get_child_by_name(node, PREFIX "dai-link");
296
-
297
- ret = asoc_simple_card_of_parse_widgets(card, PREFIX);
439
+ ret = asoc_simple_parse_widgets(card, PREFIX);
298440 if (ret < 0)
299
- goto card_parse_end;
441
+ return ret;
300442
301
- ret = asoc_simple_card_of_parse_routing(card, PREFIX, 1);
443
+ ret = asoc_simple_parse_routing(card, PREFIX);
302444 if (ret < 0)
303
- goto card_parse_end;
445
+ return ret;
304446
305
- /* Factor to mclk, used in hw_params() */
306
- of_property_read_u32(node, PREFIX "mclk-fs", &priv->mclk_fs);
447
+ ret = asoc_simple_parse_pin_switches(card, PREFIX);
448
+ if (ret < 0)
449
+ return ret;
307450
308451 /* 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);
452
+ memset(&li, 0, sizeof(li));
453
+ for (li.cpu = 1; li.cpu >= 0; li.cpu--) {
454
+ /*
455
+ * Detect all CPU first, and Detect all Codec 2nd.
456
+ *
457
+ * In Normal sound case, all DAIs are detected
458
+ * as "CPU-Codec".
459
+ *
460
+ * In DPCM sound case,
461
+ * all CPUs are detected as "CPU-dummy", and
462
+ * all Codecs are detected as "dummy-Codec".
463
+ * To avoid random sub-device numbering,
464
+ * detect "dummy-Codec" in last;
465
+ */
466
+ ret = simple_for_each_link(priv, &li,
467
+ simple_dai_link_of,
468
+ simple_dai_link_of_dpcm);
326469 if (ret < 0)
327
- goto card_parse_end;
470
+ return ret;
328471 }
329472
330
- ret = asoc_simple_card_parse_card_name(card, PREFIX);
473
+ ret = asoc_simple_parse_card_name(card, PREFIX);
331474 if (ret < 0)
332
- goto card_parse_end;
475
+ return ret;
333476
334
- ret = asoc_simple_card_parse_aux_devs(node, priv);
335
-
336
-card_parse_end:
337
- of_node_put(dai_link);
477
+ ret = snd_soc_of_parse_aux_devs(card, PREFIX "aux-devs");
338478
339479 return ret;
340480 }
341481
342
-static int asoc_simple_soc_card_probe(struct snd_soc_card *card)
482
+static int simple_count_noml(struct asoc_simple_priv *priv,
483
+ struct device_node *np,
484
+ struct device_node *codec,
485
+ struct link_info *li, bool is_top)
343486 {
344
- struct simple_card_data *priv = snd_soc_card_get_drvdata(card);
487
+ li->dais++; /* CPU or Codec */
488
+ if (np != codec)
489
+ li->link++; /* CPU-Codec */
490
+
491
+ return 0;
492
+}
493
+
494
+static int simple_count_dpcm(struct asoc_simple_priv *priv,
495
+ struct device_node *np,
496
+ struct device_node *codec,
497
+ struct link_info *li, bool is_top)
498
+{
499
+ li->dais++; /* CPU or Codec */
500
+ li->link++; /* CPU-dummy or dummy-Codec */
501
+ if (np == codec)
502
+ li->conf++;
503
+
504
+ return 0;
505
+}
506
+
507
+static void simple_get_dais_count(struct asoc_simple_priv *priv,
508
+ struct link_info *li)
509
+{
510
+ struct device *dev = simple_priv_to_dev(priv);
511
+ struct device_node *top = dev->of_node;
512
+
513
+ /*
514
+ * link_num : number of links.
515
+ * CPU-Codec / CPU-dummy / dummy-Codec
516
+ * dais_num : number of DAIs
517
+ * ccnf_num : number of codec_conf
518
+ * same number for "dummy-Codec"
519
+ *
520
+ * ex1)
521
+ * CPU0 --- Codec0 link : 5
522
+ * CPU1 --- Codec1 dais : 7
523
+ * CPU2 -/ ccnf : 1
524
+ * CPU3 --- Codec2
525
+ *
526
+ * => 5 links = 2xCPU-Codec + 2xCPU-dummy + 1xdummy-Codec
527
+ * => 7 DAIs = 4xCPU + 3xCodec
528
+ * => 1 ccnf = 1xdummy-Codec
529
+ *
530
+ * ex2)
531
+ * CPU0 --- Codec0 link : 5
532
+ * CPU1 --- Codec1 dais : 6
533
+ * CPU2 -/ ccnf : 1
534
+ * CPU3 -/
535
+ *
536
+ * => 5 links = 1xCPU-Codec + 3xCPU-dummy + 1xdummy-Codec
537
+ * => 6 DAIs = 4xCPU + 2xCodec
538
+ * => 1 ccnf = 1xdummy-Codec
539
+ *
540
+ * ex3)
541
+ * CPU0 --- Codec0 link : 6
542
+ * CPU1 -/ dais : 6
543
+ * CPU2 --- Codec1 ccnf : 2
544
+ * CPU3 -/
545
+ *
546
+ * => 6 links = 0xCPU-Codec + 4xCPU-dummy + 2xdummy-Codec
547
+ * => 6 DAIs = 4xCPU + 2xCodec
548
+ * => 2 ccnf = 2xdummy-Codec
549
+ *
550
+ * ex4)
551
+ * CPU0 --- Codec0 (convert-rate) link : 3
552
+ * CPU1 --- Codec1 dais : 4
553
+ * ccnf : 1
554
+ *
555
+ * => 3 links = 1xCPU-Codec + 1xCPU-dummy + 1xdummy-Codec
556
+ * => 4 DAIs = 2xCPU + 2xCodec
557
+ * => 1 ccnf = 1xdummy-Codec
558
+ */
559
+ if (!top) {
560
+ li->link = 1;
561
+ li->dais = 2;
562
+ li->conf = 0;
563
+ return;
564
+ }
565
+
566
+ simple_for_each_link(priv, li,
567
+ simple_count_noml,
568
+ simple_count_dpcm);
569
+
570
+ dev_dbg(dev, "link %d, dais %d, ccnf %d\n",
571
+ li->link, li->dais, li->conf);
572
+}
573
+
574
+static int simple_soc_probe(struct snd_soc_card *card)
575
+{
576
+ struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card);
345577 int ret;
346578
347
- ret = asoc_simple_card_init_hp(card, &priv->hp_jack, PREFIX);
579
+ ret = asoc_simple_init_hp(card, &priv->hp_jack, PREFIX);
348580 if (ret < 0)
349581 return ret;
350582
351
- ret = asoc_simple_card_init_mic(card, &priv->mic_jack, PREFIX);
583
+ ret = asoc_simple_init_mic(card, &priv->mic_jack, PREFIX);
352584 if (ret < 0)
353585 return ret;
354586
355587 return 0;
356588 }
357589
358
-static int asoc_simple_card_probe(struct platform_device *pdev)
590
+static int asoc_simple_probe(struct platform_device *pdev)
359591 {
360
- struct simple_card_data *priv;
361
- struct snd_soc_dai_link *dai_link;
362
- struct simple_dai_props *dai_props;
592
+ struct asoc_simple_priv *priv;
363593 struct device *dev = &pdev->dev;
364594 struct device_node *np = dev->of_node;
365595 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;
596
+ struct link_info li;
597
+ int ret;
373598
374599 /* Allocate the private data and the DAI link array */
375600 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
376601 if (!priv)
377602 return -ENOMEM;
378603
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 */
388604 card = simple_priv_to_card(priv);
389605 card->owner = THIS_MODULE;
390606 card->dev = dev;
391
- card->dai_link = priv->dai_link;
392
- card->num_links = num;
393
- card->probe = asoc_simple_soc_card_probe;
607
+ card->probe = simple_soc_probe;
608
+
609
+ memset(&li, 0, sizeof(li));
610
+ simple_get_dais_count(priv, &li);
611
+ if (!li.link || !li.dais)
612
+ return -EINVAL;
613
+
614
+ ret = asoc_simple_init_priv(priv, &li);
615
+ if (ret < 0)
616
+ return ret;
394617
395618 if (np && of_device_is_available(np)) {
396619
397
- ret = asoc_simple_card_parse_of(priv);
620
+ ret = simple_parse_of(priv);
398621 if (ret < 0) {
399622 if (ret != -EPROBE_DEFER)
400623 dev_err(dev, "parse error %d\n", ret);
....@@ -403,6 +626,13 @@
403626
404627 } else {
405628 struct asoc_simple_card_info *cinfo;
629
+ struct snd_soc_dai_link_component *cpus;
630
+ struct snd_soc_dai_link_component *codecs;
631
+ struct snd_soc_dai_link_component *platform;
632
+ struct snd_soc_dai_link *dai_link = priv->dai_link;
633
+ struct simple_dai_props *dai_props = priv->dai_props;
634
+
635
+ int dai_idx = 0;
406636
407637 cinfo = dev->platform_data;
408638 if (!cinfo) {
....@@ -419,22 +649,33 @@
419649 return -EINVAL;
420650 }
421651
652
+ dai_props->cpu_dai = &priv->dais[dai_idx++];
653
+ dai_props->codec_dai = &priv->dais[dai_idx++];
654
+
655
+ cpus = dai_link->cpus;
656
+ cpus->dai_name = cinfo->cpu_dai.name;
657
+
658
+ codecs = dai_link->codecs;
659
+ codecs->name = cinfo->codec;
660
+ codecs->dai_name = cinfo->codec_dai.name;
661
+
662
+ platform = dai_link->platforms;
663
+ platform->name = cinfo->platform;
664
+
422665 card->name = (cinfo->card) ? cinfo->card : cinfo->name;
423666 dai_link->name = cinfo->name;
424667 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;
429668 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));
669
+ dai_link->init = asoc_simple_dai_init;
670
+ memcpy(dai_props->cpu_dai, &cinfo->cpu_dai,
671
+ sizeof(*dai_props->cpu_dai));
672
+ memcpy(dai_props->codec_dai, &cinfo->codec_dai,
673
+ sizeof(*dai_props->codec_dai));
435674 }
436675
437676 snd_soc_card_set_drvdata(card, priv);
677
+
678
+ asoc_simple_debug_info(priv);
438679
439680 ret = devm_snd_soc_register_card(dev, card);
440681 if (ret < 0)
....@@ -442,32 +683,34 @@
442683
443684 return 0;
444685 err:
445
- asoc_simple_card_clean_reference(card);
686
+ asoc_simple_clean_reference(card);
446687
447688 return ret;
448689 }
449690
450
-static int asoc_simple_card_remove(struct platform_device *pdev)
691
+static int asoc_simple_remove(struct platform_device *pdev)
451692 {
452693 struct snd_soc_card *card = platform_get_drvdata(pdev);
453694
454
- return asoc_simple_card_clean_reference(card);
695
+ return asoc_simple_clean_reference(card);
455696 }
456697
457
-static const struct of_device_id asoc_simple_of_match[] = {
698
+static const struct of_device_id simple_of_match[] = {
458699 { .compatible = "simple-audio-card", },
700
+ { .compatible = "simple-scu-audio-card",
701
+ .data = (void *)DPCM_SELECTABLE },
459702 {},
460703 };
461
-MODULE_DEVICE_TABLE(of, asoc_simple_of_match);
704
+MODULE_DEVICE_TABLE(of, simple_of_match);
462705
463706 static struct platform_driver asoc_simple_card = {
464707 .driver = {
465708 .name = "asoc-simple-card",
466709 .pm = &snd_soc_pm_ops,
467
- .of_match_table = asoc_simple_of_match,
710
+ .of_match_table = simple_of_match,
468711 },
469
- .probe = asoc_simple_card_probe,
470
- .remove = asoc_simple_card_remove,
712
+ .probe = asoc_simple_probe,
713
+ .remove = asoc_simple_remove,
471714 };
472715
473716 module_platform_driver(asoc_simple_card);