This source file includes following definitions.
- asoc_simple_parse_dai
- simple_parse_convert
- simple_parse_mclk_fs
- simple_dai_link_of_dpcm
- simple_dai_link_of
- simple_for_each_link
- simple_parse_aux_devs
- simple_parse_of
- simple_count_noml
- simple_count_dpcm
- simple_get_dais_count
- simple_soc_probe
- asoc_simple_probe
- asoc_simple_remove
1
2
3
4
5
6
7
8 #include <linux/clk.h>
9 #include <linux/device.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/of_device.h>
13 #include <linux/platform_device.h>
14 #include <linux/string.h>
15 #include <sound/simple_card.h>
16 #include <sound/soc-dai.h>
17 #include <sound/soc.h>
18
19 #define DPCM_SELECTABLE 1
20
21 #define DAI "sound-dai"
22 #define CELL "#sound-dai-cells"
23 #define PREFIX "simple-audio-card,"
24
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,
29 };
30
31 static int asoc_simple_parse_dai(struct device_node *node,
32 struct snd_soc_dai_link_component *dlc,
33 int *is_single_link)
34 {
35 struct of_phandle_args args;
36 int ret;
37
38 if (!node)
39 return 0;
40
41
42
43
44
45 ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args);
46 if (ret)
47 return ret;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 ret = snd_soc_of_get_dai_name(node, &dlc->dai_name);
69 if (ret < 0)
70 return ret;
71
72 dlc->of_node = args.np;
73
74 if (is_single_link)
75 *is_single_link = !args.args_count;
76
77 return 0;
78 }
79
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)
120 {
121 struct device *dev = simple_priv_to_dev(priv);
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);
129 char *prefix = "";
130 int ret;
131
132
133
134
135
136
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++;
144
145
146 if (is_top)
147 prefix = PREFIX;
148
149 if (li->cpu) {
150 int is_single_links = 0;
151
152
153 codecs->of_node = NULL;
154 codecs->dai_name = "snd-soc-dummy-dai";
155 codecs->name = "snd-soc-dummy";
156
157
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
183 cpus->of_node = NULL;
184 cpus->dai_name = "snd-soc-dummy-dai";
185 cpus->name = "snd-soc-dummy";
186
187
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
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");
218 }
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 dai_link->dpcm_playback = 1;
235 dai_link->dpcm_capture = 1;
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;
262
263
264
265
266
267
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
279 if (is_top)
280 prefix = PREFIX;
281
282 snprintf(prop, sizeof(prop), "%splat", prefix);
283 plat = of_get_child_by_name(node, prop);
284
285 cpu_dai =
286 dai_props->cpu_dai = &priv->dais[li->dais++];
287 codec_dai =
288 dai_props->codec_dai = &priv->dais[li->dais++];
289
290 ret = asoc_simple_parse_daifmt(dev, node, codec,
291 prefix, &dai_link->dai_fmt);
292 if (ret < 0)
293 goto dai_link_of_err;
294
295 simple_parse_mclk_fs(top, cpu, codec, dai_props, prefix);
296
297 ret = asoc_simple_parse_cpu(cpu, dai_link, &single_cpu);
298 if (ret < 0)
299 goto dai_link_of_err;
300
301 ret = asoc_simple_parse_codec(codec, dai_link);
302 if (ret < 0)
303 goto dai_link_of_err;
304
305 ret = asoc_simple_parse_platform(plat, dai_link);
306 if (ret < 0)
307 goto dai_link_of_err;
308
309 ret = asoc_simple_parse_tdm(cpu, cpu_dai);
310 if (ret < 0)
311 goto dai_link_of_err;
312
313 ret = asoc_simple_parse_tdm(codec, codec_dai);
314 if (ret < 0)
315 goto dai_link_of_err;
316
317 ret = asoc_simple_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
318 if (ret < 0)
319 goto dai_link_of_err;
320
321 ret = asoc_simple_parse_clk_codec(dev, codec, dai_link, codec_dai);
322 if (ret < 0)
323 goto dai_link_of_err;
324
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);
329 if (ret < 0)
330 goto dai_link_of_err;
331
332 dai_link->ops = &simple_ops;
333 dai_link->init = asoc_simple_dai_init;
334
335 asoc_simple_canonicalize_cpu(dai_link, single_cpu);
336 asoc_simple_canonicalize_platform(dai_link);
337
338 dai_link_of_err:
339 of_node_put(plat);
340 of_node_put(node);
341
342 return ret;
343 }
344
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))
355 {
356 struct device *dev = simple_priv_to_dev(priv);
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;
362
363
364 node = of_get_child_by_name(top, PREFIX "dai-link");
365 if (!node) {
366 node = of_node_get(top);
367 is_top = 1;
368 }
369
370
371 do {
372 struct asoc_simple_data adata;
373 struct device_node *codec;
374 struct device_node *np;
375 int num = of_get_child_count(node);
376
377
378 codec = of_get_child_by_name(node, is_top ?
379 PREFIX "codec" : "codec");
380 if (!codec) {
381 ret = -ENODEV;
382 goto error;
383 }
384
385
386 memset(&adata, 0, sizeof(adata));
387 for_each_child_of_node(node, np)
388 simple_parse_convert(dev, np, &adata);
389
390
391 for_each_child_of_node(node, np) {
392
393
394
395
396
397 if (dpcm_selectable &&
398 (num > 2 ||
399 adata.convert_rate || adata.convert_channels))
400 ret = func_dpcm(priv, np, codec, li, is_top);
401
402 else
403 ret = func_noml(priv, np, codec, li, is_top);
404
405 if (ret < 0) {
406 of_node_put(codec);
407 of_node_put(np);
408 goto error;
409 }
410 }
411
412 of_node_put(codec);
413 node = of_get_next_child(top, node);
414 } while (!is_top && node);
415
416 error:
417 of_node_put(node);
418 return ret;
419 }
420
421 static int simple_parse_aux_devs(struct device_node *node,
422 struct asoc_simple_priv *priv)
423 {
424 struct device *dev = simple_priv_to_dev(priv);
425 struct device_node *aux_node;
426 struct snd_soc_card *card = simple_priv_to_card(priv);
427 int i, n, len;
428
429 if (!of_find_property(node, PREFIX "aux-devs", &len))
430 return 0;
431
432 n = len / sizeof(__be32);
433 if (n <= 0)
434 return -EINVAL;
435
436 card->aux_dev = devm_kcalloc(dev,
437 n, sizeof(*card->aux_dev), GFP_KERNEL);
438 if (!card->aux_dev)
439 return -ENOMEM;
440
441 for (i = 0; i < n; i++) {
442 aux_node = of_parse_phandle(node, PREFIX "aux-devs", i);
443 if (!aux_node)
444 return -EINVAL;
445 card->aux_dev[i].dlc.of_node = aux_node;
446 }
447
448 card->num_aux_devs = n;
449 return 0;
450 }
451
452 static int simple_parse_of(struct asoc_simple_priv *priv)
453 {
454 struct device *dev = simple_priv_to_dev(priv);
455 struct device_node *top = dev->of_node;
456 struct snd_soc_card *card = simple_priv_to_card(priv);
457 struct link_info li;
458 int ret;
459
460 if (!top)
461 return -EINVAL;
462
463 ret = asoc_simple_parse_widgets(card, PREFIX);
464 if (ret < 0)
465 return ret;
466
467 ret = asoc_simple_parse_routing(card, PREFIX);
468 if (ret < 0)
469 return ret;
470
471 ret = asoc_simple_parse_pin_switches(card, PREFIX);
472 if (ret < 0)
473 return ret;
474
475
476 memset(&li, 0, sizeof(li));
477 for (li.cpu = 1; li.cpu >= 0; li.cpu--) {
478
479
480
481
482
483
484
485
486
487
488
489
490 ret = simple_for_each_link(priv, &li,
491 simple_dai_link_of,
492 simple_dai_link_of_dpcm);
493 if (ret < 0)
494 return ret;
495 }
496
497 ret = asoc_simple_parse_card_name(card, PREFIX);
498 if (ret < 0)
499 return ret;
500
501 ret = simple_parse_aux_devs(top, priv);
502
503 return ret;
504 }
505
506 static int simple_count_noml(struct asoc_simple_priv *priv,
507 struct device_node *np,
508 struct device_node *codec,
509 struct link_info *li, bool is_top)
510 {
511 li->dais++;
512 if (np != codec)
513 li->link++;
514
515 return 0;
516 }
517
518 static int simple_count_dpcm(struct asoc_simple_priv *priv,
519 struct device_node *np,
520 struct device_node *codec,
521 struct link_info *li, bool is_top)
522 {
523 li->dais++;
524 li->link++;
525 if (np == codec)
526 li->conf++;
527
528 return 0;
529 }
530
531 static void simple_get_dais_count(struct asoc_simple_priv *priv,
532 struct link_info *li)
533 {
534 struct device *dev = simple_priv_to_dev(priv);
535 struct device_node *top = dev->of_node;
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583 if (!top) {
584 li->link = 1;
585 li->dais = 2;
586 li->conf = 0;
587 return;
588 }
589
590 simple_for_each_link(priv, li,
591 simple_count_noml,
592 simple_count_dpcm);
593
594 dev_dbg(dev, "link %d, dais %d, ccnf %d\n",
595 li->link, li->dais, li->conf);
596 }
597
598 static int simple_soc_probe(struct snd_soc_card *card)
599 {
600 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card);
601 int ret;
602
603 ret = asoc_simple_init_hp(card, &priv->hp_jack, PREFIX);
604 if (ret < 0)
605 return ret;
606
607 ret = asoc_simple_init_mic(card, &priv->mic_jack, PREFIX);
608 if (ret < 0)
609 return ret;
610
611 return 0;
612 }
613
614 static int asoc_simple_probe(struct platform_device *pdev)
615 {
616 struct asoc_simple_priv *priv;
617 struct device *dev = &pdev->dev;
618 struct device_node *np = dev->of_node;
619 struct snd_soc_card *card;
620 struct link_info li;
621 int ret;
622
623
624 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
625 if (!priv)
626 return -ENOMEM;
627
628 card = simple_priv_to_card(priv);
629 card->owner = THIS_MODULE;
630 card->dev = dev;
631 card->probe = simple_soc_probe;
632
633 memset(&li, 0, sizeof(li));
634 simple_get_dais_count(priv, &li);
635 if (!li.link || !li.dais)
636 return -EINVAL;
637
638 ret = asoc_simple_init_priv(priv, &li);
639 if (ret < 0)
640 return ret;
641
642 if (np && of_device_is_available(np)) {
643
644 ret = simple_parse_of(priv);
645 if (ret < 0) {
646 if (ret != -EPROBE_DEFER)
647 dev_err(dev, "parse error %d\n", ret);
648 goto err;
649 }
650
651 } else {
652 struct asoc_simple_card_info *cinfo;
653 struct snd_soc_dai_link_component *cpus;
654 struct snd_soc_dai_link_component *codecs;
655 struct snd_soc_dai_link_component *platform;
656 struct snd_soc_dai_link *dai_link = priv->dai_link;
657 struct simple_dai_props *dai_props = priv->dai_props;
658
659 int dai_idx = 0;
660
661 cinfo = dev->platform_data;
662 if (!cinfo) {
663 dev_err(dev, "no info for asoc-simple-card\n");
664 return -EINVAL;
665 }
666
667 if (!cinfo->name ||
668 !cinfo->codec_dai.name ||
669 !cinfo->codec ||
670 !cinfo->platform ||
671 !cinfo->cpu_dai.name) {
672 dev_err(dev, "insufficient asoc_simple_card_info settings\n");
673 return -EINVAL;
674 }
675
676 dai_props->cpu_dai = &priv->dais[dai_idx++];
677 dai_props->codec_dai = &priv->dais[dai_idx++];
678
679 cpus = dai_link->cpus;
680 cpus->dai_name = cinfo->cpu_dai.name;
681
682 codecs = dai_link->codecs;
683 codecs->name = cinfo->codec;
684 codecs->dai_name = cinfo->codec_dai.name;
685
686 platform = dai_link->platforms;
687 platform->name = cinfo->platform;
688
689 card->name = (cinfo->card) ? cinfo->card : cinfo->name;
690 dai_link->name = cinfo->name;
691 dai_link->stream_name = cinfo->name;
692 dai_link->dai_fmt = cinfo->daifmt;
693 dai_link->init = asoc_simple_dai_init;
694 memcpy(dai_props->cpu_dai, &cinfo->cpu_dai,
695 sizeof(*dai_props->cpu_dai));
696 memcpy(dai_props->codec_dai, &cinfo->codec_dai,
697 sizeof(*dai_props->codec_dai));
698 }
699
700 snd_soc_card_set_drvdata(card, priv);
701
702 asoc_simple_debug_info(priv);
703
704 ret = devm_snd_soc_register_card(dev, card);
705 if (ret < 0)
706 goto err;
707
708 return 0;
709 err:
710 asoc_simple_clean_reference(card);
711
712 return ret;
713 }
714
715 static int asoc_simple_remove(struct platform_device *pdev)
716 {
717 struct snd_soc_card *card = platform_get_drvdata(pdev);
718
719 return asoc_simple_clean_reference(card);
720 }
721
722 static const struct of_device_id simple_of_match[] = {
723 { .compatible = "simple-audio-card", },
724 { .compatible = "simple-scu-audio-card",
725 .data = (void *)DPCM_SELECTABLE },
726 {},
727 };
728 MODULE_DEVICE_TABLE(of, simple_of_match);
729
730 static struct platform_driver asoc_simple_card = {
731 .driver = {
732 .name = "asoc-simple-card",
733 .pm = &snd_soc_pm_ops,
734 .of_match_table = simple_of_match,
735 },
736 .probe = asoc_simple_probe,
737 .remove = asoc_simple_remove,
738 };
739
740 module_platform_driver(asoc_simple_card);
741
742 MODULE_ALIAS("platform:asoc-simple-card");
743 MODULE_LICENSE("GPL v2");
744 MODULE_DESCRIPTION("ASoC Simple Sound Card");
745 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");