1
2
3
4
5
6
7
8#include <linux/cleanup.h>
9#include <linux/clk.h>
10#include <linux/device.h>
11#include <linux/module.h>
12#include <linux/of.h>
13#include <linux/of_platform.h>
14#include <linux/platform_device.h>
15#include <linux/string.h>
16#include <sound/simple_card.h>
17#include <sound/soc-dai.h>
18#include <sound/soc.h>
19
20#define DPCM_SELECTABLE 1
21
22#define DAI "sound-dai"
23#define CELL "#sound-dai-cells"
24#define PREFIX "simple-audio-card,"
25
26static const struct snd_soc_ops simple_ops = {
27 .startup = simple_util_startup,
28 .shutdown = simple_util_shutdown,
29 .hw_params = simple_util_hw_params,
30};
31
32#define simple_ret(priv, ret) _simple_ret(priv, __func__, ret)
33static inline int _simple_ret(struct simple_util_priv *priv,
34 const char *func, int ret)
35{
36 return snd_soc_ret(simple_priv_to_dev(priv), ret, "at %s()\n", func);
37}
38
39static int simple_parse_platform(struct simple_util_priv *priv,
40 struct device_node *node,
41 struct snd_soc_dai_link_component *dlc)
42{
43 struct of_phandle_args args;
44 int ret;
45
46 if (!node)
47 return 0;
48
49
50
51
52
53 ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args);
54 if (ret)
55 return simple_ret(priv, ret);
56
57
58
59 dlc->of_node = args.np;
60
61 return 0;
62}
63
64static int simple_parse_dai(struct simple_util_priv *priv,
65 struct device_node *node,
66 struct snd_soc_dai_link_component *dlc,
67 int *is_single_link)
68{
69 struct device *dev = simple_priv_to_dev(priv);
70 struct of_phandle_args args;
71 struct snd_soc_dai *dai;
72 int ret;
73
74 if (!node)
75 return 0;
76
77
78
79
80
81 ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args);
82 if (ret)
83 goto end;
84
85
86
87
88 dai = snd_soc_get_dai_via_args(&args);
89 if (dai) {
90 ret = -ENOMEM;
91 dlc->dai_name = snd_soc_dai_name_get(dai);
92 dlc->dai_args = snd_soc_copy_dai_args(dev, &args);
93 if (!dlc->dai_args)
94 goto end;
95
96 goto parse_dai_end;
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 ret = snd_soc_get_dlc(&args, dlc);
119 if (ret < 0)
120 goto end;
121
122parse_dai_end:
123 if (is_single_link)
124 *is_single_link = !args.args_count;
125 ret = 0;
126end:
127 return simple_ret(priv, ret);
128}
129
130static void simple_parse_convert(struct device *dev,
131 struct device_node *np,
132 struct simple_util_data *adata)
133{
134 struct device_node *top = dev->of_node;
135 struct device_node *node __free(device_node) = of_get_parent(np);
136
137 simple_util_parse_convert(top, PREFIX, adata);
138 simple_util_parse_convert(node, PREFIX, adata);
139 simple_util_parse_convert(node, NULL, adata);
140 simple_util_parse_convert(np, NULL, adata);
141}
142
143static int simple_parse_node(struct simple_util_priv *priv,
144 struct device_node *np,
145 struct link_info *li,
146 char *prefix,
147 int *cpu)
148{
149 struct device *dev = simple_priv_to_dev(priv);
150 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
151 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
152 struct snd_soc_dai_link_component *dlc;
153 struct simple_util_dai *dai;
154 int ret;
155
156 if (cpu) {
157 dlc = snd_soc_link_to_cpu(dai_link, 0);
158 dai = simple_props_to_dai_cpu(dai_props, 0);
159 } else {
160 dlc = snd_soc_link_to_codec(dai_link, 0);
161 dai = simple_props_to_dai_codec(dai_props, 0);
162 }
163
164 ret = simple_parse_dai(priv, np, dlc, cpu);
165 if (ret)
166 goto end;
167
168 ret = simple_util_parse_clk(dev, np, dai, dlc);
169 if (ret)
170 goto end;
171
172 ret = simple_util_parse_tdm(np, dai);
173end:
174 return simple_ret(priv, ret);
175}
176
177static int simple_link_init(struct simple_util_priv *priv,
178 struct device_node *cpu,
179 struct device_node *codec,
180 struct link_info *li,
181 char *prefix, char *name)
182{
183 struct device *dev = simple_priv_to_dev(priv);
184 struct device_node *top = dev->of_node;
185 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
186 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
187 struct device_node *node __free(device_node) = of_get_parent(cpu);
188 enum snd_soc_trigger_order trigger_start = SND_SOC_TRIGGER_ORDER_DEFAULT;
189 enum snd_soc_trigger_order trigger_stop = SND_SOC_TRIGGER_ORDER_DEFAULT;
190 bool playback_only = 0, capture_only = 0;
191 int ret;
192
193 ret = simple_util_parse_daifmt(dev, node, codec,
194 prefix, &dai_link->dai_fmt);
195 if (ret < 0)
196 goto end;
197
198 graph_util_parse_link_direction(top, &playback_only, &capture_only);
199 graph_util_parse_link_direction(node, &playback_only, &capture_only);
200 graph_util_parse_link_direction(cpu, &playback_only, &capture_only);
201 graph_util_parse_link_direction(codec, &playback_only, &capture_only);
202
203 of_property_read_u32(top, "mclk-fs", &dai_props->mclk_fs);
204 of_property_read_u32(top, PREFIX "mclk-fs", &dai_props->mclk_fs);
205 of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs);
206 of_property_read_u32(node, PREFIX "mclk-fs", &dai_props->mclk_fs);
207 of_property_read_u32(cpu, "mclk-fs", &dai_props->mclk_fs);
208 of_property_read_u32(cpu, PREFIX "mclk-fs", &dai_props->mclk_fs);
209 of_property_read_u32(codec, "mclk-fs", &dai_props->mclk_fs);
210 of_property_read_u32(codec, PREFIX "mclk-fs", &dai_props->mclk_fs);
211
212 graph_util_parse_trigger_order(priv, top, &trigger_start, &trigger_stop);
213 graph_util_parse_trigger_order(priv, node, &trigger_start, &trigger_stop);
214 graph_util_parse_trigger_order(priv, cpu, &trigger_start, &trigger_stop);
215 graph_util_parse_trigger_order(priv, codec, &trigger_start, &trigger_stop);
216
217 dai_link->playback_only = playback_only;
218 dai_link->capture_only = capture_only;
219
220 dai_link->trigger_start = trigger_start;
221 dai_link->trigger_stop = trigger_stop;
222
223 dai_link->init = simple_util_dai_init;
224 dai_link->ops = &simple_ops;
225
226 ret = simple_util_set_dailink_name(priv, dai_link, name);
227end:
228 return simple_ret(priv, ret);
229}
230
231static int simple_dai_link_of_dpcm(struct simple_util_priv *priv,
232 struct device_node *np,
233 struct device_node *codec,
234 struct link_info *li,
235 bool is_top)
236{
237 struct device *dev = simple_priv_to_dev(priv);
238 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
239 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
240 struct device_node *top = dev->of_node;
241 struct device_node *node __free(device_node) = of_get_parent(np);
242 char *prefix = "";
243 char dai_name[64];
244 int ret;
245
246 dev_dbg(dev, "link_of DPCM (%pOF)\n", np);
247
248
249 if (is_top)
250 prefix = PREFIX;
251
252 if (li->cpu) {
253 struct snd_soc_dai_link_component *cpus = snd_soc_link_to_cpu(dai_link, 0);
254 struct snd_soc_dai_link_component *platforms = snd_soc_link_to_platform(dai_link, 0);
255 int is_single_links = 0;
256
257
258
259
260 dai_link->dynamic = 1;
261 dai_link->dpcm_merged_format = 1;
262
263 ret = simple_parse_node(priv, np, li, prefix, &is_single_links);
264 if (ret < 0)
265 goto out_put_node;
266
267 snprintf(dai_name, sizeof(dai_name), "fe.%s", cpus->dai_name);
268
269 simple_util_canonicalize_cpu(cpus, is_single_links);
270 simple_util_canonicalize_platform(platforms, cpus);
271 } else {
272 struct snd_soc_dai_link_component *codecs = snd_soc_link_to_codec(dai_link, 0);
273 struct snd_soc_codec_conf *cconf;
274
275
276
277
278 dai_link->no_pcm = 1;
279 dai_link->be_hw_params_fixup = simple_util_be_hw_params_fixup;
280
281 cconf = simple_props_to_codec_conf(dai_props, 0);
282
283 ret = simple_parse_node(priv, np, li, prefix, NULL);
284 if (ret < 0)
285 goto out_put_node;
286
287 snprintf(dai_name, sizeof(dai_name), "be.%s", codecs->dai_name);
288
289
290 snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
291 PREFIX "prefix");
292 snd_soc_of_parse_node_prefix(node, cconf, codecs->of_node,
293 "prefix");
294 snd_soc_of_parse_node_prefix(np, cconf, codecs->of_node,
295 "prefix");
296 }
297
298 simple_parse_convert(dev, np, &dai_props->adata);
299
300 ret = simple_link_init(priv, np, codec, li, prefix, dai_name);
301
302out_put_node:
303 li->link++;
304
305 return simple_ret(priv, ret);
306}
307
308static int simple_dai_link_of(struct simple_util_priv *priv,
309 struct device_node *np,
310 struct device_node *codec,
311 struct link_info *li,
312 bool is_top)
313{
314 struct device *dev = simple_priv_to_dev(priv);
315 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
316 struct snd_soc_dai_link_component *cpus = snd_soc_link_to_cpu(dai_link, 0);
317 struct snd_soc_dai_link_component *codecs = snd_soc_link_to_codec(dai_link, 0);
318 struct snd_soc_dai_link_component *platforms = snd_soc_link_to_platform(dai_link, 0);
319 struct device_node *cpu = NULL;
320 char dai_name[64];
321 char prop[128];
322 char *prefix = "";
323 int ret, single_cpu = 0;
324
325 cpu = np;
326 struct device_node *node __free(device_node) = of_get_parent(np);
327
328 dev_dbg(dev, "link_of (%pOF)\n", node);
329
330
331 if (is_top)
332 prefix = PREFIX;
333
334 snprintf(prop, sizeof(prop), "%splat", prefix);
335 struct device_node *plat __free(device_node) = of_get_child_by_name(node, prop);
336
337 ret = simple_parse_node(priv, cpu, li, prefix, &single_cpu);
338 if (ret < 0)
339 goto dai_link_of_err;
340
341 ret = simple_parse_node(priv, codec, li, prefix, NULL);
342 if (ret < 0)
343 goto dai_link_of_err;
344
345 ret = simple_parse_platform(priv, plat, platforms);
346 if (ret < 0)
347 goto dai_link_of_err;
348
349 snprintf(dai_name, sizeof(dai_name),
350 "%s-%s", cpus->dai_name, codecs->dai_name);
351
352 simple_util_canonicalize_cpu(cpus, single_cpu);
353 simple_util_canonicalize_platform(platforms, cpus);
354
355 ret = simple_link_init(priv, cpu, codec, li, prefix, dai_name);
356
357dai_link_of_err:
358 li->link++;
359
360 return simple_ret(priv, ret);
361}
362
363static int __simple_for_each_link(struct simple_util_priv *priv,
364 struct link_info *li,
365 int (*func_noml)(struct simple_util_priv *priv,
366 struct device_node *np,
367 struct device_node *codec,
368 struct link_info *li, bool is_top),
369 int (*func_dpcm)(struct simple_util_priv *priv,
370 struct device_node *np,
371 struct device_node *codec,
372 struct link_info *li, bool is_top))
373{
374 struct device *dev = simple_priv_to_dev(priv);
375 struct device_node *top = dev->of_node;
376 struct device_node *node;
377 uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev);
378 bool is_top = 0;
379 int ret = 0;
380
381
382 node = of_get_child_by_name(top, PREFIX "dai-link");
383 if (!node) {
384 node = of_node_get(top);
385 is_top = 1;
386 }
387
388 struct device_node *add_devs __free(device_node) = of_get_child_by_name(top, PREFIX "additional-devs");
389
390
391 do {
392 struct simple_util_data adata;
393 int num = of_get_child_count(node);
394
395
396 if (node == add_devs) {
397 node = of_get_next_child(top, node);
398 continue;
399 }
400
401
402 struct device_node *codec __free(device_node) =
403 of_get_child_by_name(node, is_top ? PREFIX "codec" : "codec");
404 if (!codec) {
405 ret = -ENODEV;
406 goto error;
407 }
408
409 struct device_node *plat __free(device_node) =
410 of_get_child_by_name(node, is_top ? PREFIX "plat" : "plat");
411
412
413 memset(&adata, 0, sizeof(adata));
414 for_each_child_of_node_scoped(node, np) {
415 if (np == add_devs)
416 continue;
417 simple_parse_convert(dev, np, &adata);
418 }
419
420
421 for_each_child_of_node_scoped(node, np) {
422 if (plat == np || add_devs == np)
423 continue;
424
425
426
427
428
429 if (dpcm_selectable &&
430 (num > 2 || simple_util_is_convert_required(&adata))) {
431
432
433
434
435
436
437 if (li->cpu != (np == codec))
438 ret = func_dpcm(priv, np, codec, li, is_top);
439
440 } else {
441
442
443
444
445
446
447 if (li->cpu && (np != codec))
448 ret = func_noml(priv, np, codec, li, is_top);
449 }
450
451 if (ret < 0)
452 goto error;
453 }
454
455 node = of_get_next_child(top, node);
456 } while (!is_top && node);
457
458error:
459 of_node_put(node);
460
461 return simple_ret(priv, ret);
462}
463
464static int simple_for_each_link(struct simple_util_priv *priv,
465 struct link_info *li,
466 int (*func_noml)(struct simple_util_priv *priv,
467 struct device_node *np,
468 struct device_node *codec,
469 struct link_info *li, bool is_top),
470 int (*func_dpcm)(struct simple_util_priv *priv,
471 struct device_node *np,
472 struct device_node *codec,
473 struct link_info *li, bool is_top))
474{
475 int ret;
476
477
478
479
480
481
482
483
484
485
486
487
488 for (li->cpu = 1; li->cpu >= 0; li->cpu--) {
489 ret = __simple_for_each_link(priv, li, func_noml, func_dpcm);
490 if (ret < 0)
491 break;
492 }
493
494 return simple_ret(priv, ret);
495}
496
497static void simple_depopulate_aux(void *data)
498{
499 struct simple_util_priv *priv = data;
500
501 of_platform_depopulate(simple_priv_to_dev(priv));
502}
503
504static int simple_populate_aux(struct simple_util_priv *priv)
505{
506 struct device *dev = simple_priv_to_dev(priv);
507 struct device_node *node __free(device_node) = of_get_child_by_name(dev->of_node, PREFIX "additional-devs");
508 int ret;
509
510 if (!node)
511 return 0;
512
513 ret = of_platform_populate(node, NULL, NULL, dev);
514 if (ret)
515 goto end;
516
517 ret = devm_add_action_or_reset(dev, simple_depopulate_aux, priv);
518end:
519 return simple_ret(priv, ret);
520}
521
522static int simple_parse_of(struct simple_util_priv *priv, struct link_info *li)
523{
524 struct snd_soc_card *card = simple_priv_to_card(priv);
525 int ret;
526
527 ret = simple_util_parse_widgets(card, PREFIX);
528 if (ret < 0)
529 goto end;
530
531 ret = simple_util_parse_routing(card, PREFIX);
532 if (ret < 0)
533 goto end;
534
535 ret = simple_util_parse_pin_switches(card, PREFIX);
536 if (ret < 0)
537 goto end;
538
539
540 memset(li, 0, sizeof(*li));
541 ret = simple_for_each_link(priv, li,
542 simple_dai_link_of,
543 simple_dai_link_of_dpcm);
544 if (ret < 0)
545 goto end;
546
547 ret = simple_util_parse_card_name(priv, PREFIX);
548 if (ret < 0)
549 goto end;
550
551 ret = simple_populate_aux(priv);
552 if (ret < 0)
553 goto end;
554
555 ret = snd_soc_of_parse_aux_devs(card, PREFIX "aux-devs");
556end:
557 return simple_ret(priv, ret);
558}
559
560static int simple_count_noml(struct simple_util_priv *priv,
561 struct device_node *np,
562 struct device_node *codec,
563 struct link_info *li, bool is_top)
564{
565 int ret = -EINVAL;
566
567 if (li->link >= SNDRV_MAX_LINKS)
568 goto end;
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584 li->num[li->link].cpus = 1;
585 li->num[li->link].platforms = 1;
586
587 li->num[li->link].codecs = 1;
588
589 li->link += 1;
590 ret = 0;
591end:
592 return simple_ret(priv, ret);
593}
594
595static int simple_count_dpcm(struct simple_util_priv *priv,
596 struct device_node *np,
597 struct device_node *codec,
598 struct link_info *li, bool is_top)
599{
600 int ret = -EINVAL;
601
602 if (li->link >= SNDRV_MAX_LINKS)
603 goto end;
604
605 if (li->cpu) {
606
607
608
609
610
611 li->num[li->link].cpus = 1;
612 li->num[li->link].platforms = 1;
613
614 li->link++;
615 } else {
616 li->num[li->link].codecs = 1;
617
618 li->link++;
619 }
620 ret = 0;
621end:
622 return simple_ret(priv, ret);
623}
624
625static int simple_get_dais_count(struct simple_util_priv *priv,
626 struct link_info *li)
627{
628 struct device *dev = simple_priv_to_dev(priv);
629 struct device_node *top = dev->of_node;
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677 if (!top) {
678 li->num[0].cpus = 1;
679 li->num[0].codecs = 1;
680 li->num[0].platforms = 1;
681
682 li->link = 1;
683 return 0;
684 }
685
686 return simple_for_each_link(priv, li,
687 simple_count_noml,
688 simple_count_dpcm);
689}
690
691static int simple_soc_probe(struct snd_soc_card *card)
692{
693 struct simple_util_priv *priv = snd_soc_card_get_drvdata(card);
694 int ret;
695
696 ret = simple_util_init_hp(card, &priv->hp_jack, PREFIX);
697 if (ret < 0)
698 goto end;
699
700 ret = simple_util_init_mic(card, &priv->mic_jack, PREFIX);
701 if (ret < 0)
702 goto end;
703
704 ret = simple_util_init_aux_jacks(priv, PREFIX);
705end:
706 return simple_ret(priv, ret);
707}
708
709static int simple_probe(struct platform_device *pdev)
710{
711 struct simple_util_priv *priv;
712 struct device *dev = &pdev->dev;
713 struct device_node *np = dev->of_node;
714 struct snd_soc_card *card;
715 int ret;
716
717
718 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
719 if (!priv)
720 return -ENOMEM;
721
722 card = simple_priv_to_card(priv);
723 card->owner = THIS_MODULE;
724 card->dev = dev;
725 card->probe = simple_soc_probe;
726 card->driver_name = "simple-card";
727
728 ret = -ENOMEM;
729 struct link_info *li __free(kfree) = kzalloc(sizeof(*li), GFP_KERNEL);
730 if (!li)
731 goto end;
732
733 ret = simple_get_dais_count(priv, li);
734 if (ret < 0)
735 goto end;
736
737 ret = -EINVAL;
738 if (!li->link)
739 goto end;
740
741 ret = simple_util_init_priv(priv, li);
742 if (ret < 0)
743 goto end;
744
745 if (np && of_device_is_available(np)) {
746
747 ret = simple_parse_of(priv, li);
748 if (ret < 0) {
749 dev_err_probe(dev, ret, "parse error\n");
750 goto err;
751 }
752
753 } else {
754 struct simple_util_info *cinfo;
755 struct snd_soc_dai_link_component *cpus;
756 struct snd_soc_dai_link_component *codecs;
757 struct snd_soc_dai_link_component *platform;
758 struct snd_soc_dai_link *dai_link = priv->dai_link;
759 struct simple_dai_props *dai_props = priv->dai_props;
760
761 ret = -EINVAL;
762
763 cinfo = dev->platform_data;
764 if (!cinfo) {
765 dev_err(dev, "no info for asoc-simple-card\n");
766 goto err;
767 }
768
769 if (!cinfo->name ||
770 !cinfo->codec_dai.name ||
771 !cinfo->codec ||
772 !cinfo->platform ||
773 !cinfo->cpu_dai.name) {
774 dev_err(dev, "insufficient simple_util_info settings\n");
775 goto err;
776 }
777
778 cpus = dai_link->cpus;
779 cpus->dai_name = cinfo->cpu_dai.name;
780
781 codecs = dai_link->codecs;
782 codecs->name = cinfo->codec;
783 codecs->dai_name = cinfo->codec_dai.name;
784
785 platform = dai_link->platforms;
786 platform->name = cinfo->platform;
787
788 card->name = (cinfo->card) ? cinfo->card : cinfo->name;
789 dai_link->name = cinfo->name;
790 dai_link->stream_name = cinfo->name;
791 dai_link->dai_fmt = cinfo->daifmt;
792 dai_link->init = simple_util_dai_init;
793 memcpy(dai_props->cpu_dai, &cinfo->cpu_dai,
794 sizeof(*dai_props->cpu_dai));
795 memcpy(dai_props->codec_dai, &cinfo->codec_dai,
796 sizeof(*dai_props->codec_dai));
797 }
798
799 snd_soc_card_set_drvdata(card, priv);
800
801 simple_util_debug_info(priv);
802
803 ret = devm_snd_soc_register_card(dev, card);
804 if (ret < 0)
805 goto err;
806
807 return 0;
808err:
809 simple_util_clean_reference(card);
810end:
811 return dev_err_probe(dev, ret, "parse error\n");
812}
813
814static const struct of_device_id simple_of_match[] = {
815 { .compatible = "simple-audio-card", },
816 { .compatible = "simple-scu-audio-card",
817 .data = (void *)DPCM_SELECTABLE },
818 {},
819};
820MODULE_DEVICE_TABLE(of, simple_of_match);
821
822static struct platform_driver simple_card = {
823 .driver = {
824 .name = "asoc-simple-card",
825 .pm = &snd_soc_pm_ops,
826 .of_match_table = simple_of_match,
827 },
828 .probe = simple_probe,
829 .remove = simple_util_remove,
830};
831
832module_platform_driver(simple_card);
833
834MODULE_ALIAS("platform:asoc-simple-card");
835MODULE_LICENSE("GPL v2");
836MODULE_DESCRIPTION("ASoC Simple Sound Card");
837MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
838