1
2
3
4
5
6
7
8
9#include <linux/clk.h>
10#include <linux/device.h>
11#include <linux/gpio.h>
12#include <linux/gpio/consumer.h>
13#include <linux/module.h>
14#include <linux/of.h>
15#include <linux/of_device.h>
16#include <linux/of_gpio.h>
17#include <linux/of_graph.h>
18#include <linux/platform_device.h>
19#include <linux/string.h>
20#include <sound/graph_card.h>
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216enum graph_type {
217 GRAPH_NORMAL,
218 GRAPH_DPCM,
219 GRAPH_C2C,
220
221 GRAPH_MULTI,
222};
223
224#define GRAPH_NODENAME_MULTI "multi"
225#define GRAPH_NODENAME_DPCM "dpcm"
226#define GRAPH_NODENAME_C2C "codec2codec"
227
228#define port_to_endpoint(port) of_get_child_by_name(port, "endpoint")
229
230static enum graph_type __graph_get_type(struct device_node *lnk)
231{
232 struct device_node *np;
233
234
235
236
237
238
239
240
241
242 np = of_get_parent(lnk);
243 if (of_node_name_eq(np, "ports"))
244 np = of_get_parent(np);
245
246 if (of_node_name_eq(np, GRAPH_NODENAME_MULTI))
247 return GRAPH_MULTI;
248
249 if (of_node_name_eq(np, GRAPH_NODENAME_DPCM))
250 return GRAPH_DPCM;
251
252 if (of_node_name_eq(np, GRAPH_NODENAME_C2C))
253 return GRAPH_C2C;
254
255 return GRAPH_NORMAL;
256}
257
258static enum graph_type graph_get_type(struct asoc_simple_priv *priv,
259 struct device_node *lnk)
260{
261 enum graph_type type = __graph_get_type(lnk);
262
263
264 if (type == GRAPH_MULTI)
265 type = GRAPH_NORMAL;
266
267#ifdef DEBUG
268 {
269 struct device *dev = simple_priv_to_dev(priv);
270 const char *str = "Normal";
271
272 switch (type) {
273 case GRAPH_DPCM:
274 if (asoc_graph_is_ports0(lnk))
275 str = "DPCM Front-End";
276 else
277 str = "DPCM Back-End";
278 break;
279 case GRAPH_C2C:
280 str = "Codec2Codec";
281 break;
282 default:
283 break;
284 }
285
286 dev_dbg(dev, "%pOF (%s)", lnk, str);
287 }
288#endif
289 return type;
290}
291
292static int graph_lnk_is_multi(struct device_node *lnk)
293{
294 return __graph_get_type(lnk) == GRAPH_MULTI;
295}
296
297static struct device_node *graph_get_next_multi_ep(struct device_node **port)
298{
299 struct device_node *ports = of_get_parent(*port);
300 struct device_node *ep = NULL;
301 struct device_node *rep = NULL;
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318 do {
319 *port = of_get_next_child(ports, *port);
320 if (!*port)
321 break;
322 } while (!of_node_name_eq(*port, "port"));
323
324 if (*port) {
325 ep = port_to_endpoint(*port);
326 rep = of_graph_get_remote_endpoint(ep);
327 }
328
329 of_node_put(ep);
330 of_node_put(ports);
331
332 return rep;
333}
334
335static const struct snd_soc_ops graph_ops = {
336 .startup = asoc_simple_startup,
337 .shutdown = asoc_simple_shutdown,
338 .hw_params = asoc_simple_hw_params,
339};
340
341static int graph_get_dai_id(struct device_node *ep)
342{
343 struct device_node *node;
344 struct device_node *endpoint;
345 struct of_endpoint info;
346 int i, id;
347 const u32 *reg;
348 int ret;
349
350
351 ret = snd_soc_get_dai_id(ep);
352 if (ret != -ENOTSUPP)
353 return ret;
354
355
356 ret = of_graph_parse_endpoint(ep, &info);
357 if (ret == 0) {
358
359
360
361
362
363
364 if (of_get_property(ep, "reg", NULL))
365 return info.id;
366
367 node = of_get_parent(ep);
368 reg = of_get_property(node, "reg", NULL);
369 of_node_put(node);
370 if (reg)
371 return info.port;
372 }
373 node = of_graph_get_port_parent(ep);
374
375
376
377
378
379 i = 0;
380 id = -1;
381 for_each_endpoint_of_node(node, endpoint) {
382 if (endpoint == ep)
383 id = i;
384 i++;
385 }
386
387 of_node_put(node);
388
389 if (id < 0)
390 return -ENODEV;
391
392 return id;
393}
394
395static int asoc_simple_parse_dai(struct device_node *ep,
396 struct snd_soc_dai_link_component *dlc,
397 int *is_single_link)
398{
399 struct device_node *node;
400 struct of_phandle_args args;
401 int ret;
402
403 if (!ep)
404 return 0;
405
406 node = of_graph_get_port_parent(ep);
407
408
409 args.np = node;
410 args.args[0] = graph_get_dai_id(ep);
411 args.args_count = (of_graph_get_endpoint_count(node) > 1);
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432 ret = snd_soc_get_dai_name(&args, &dlc->dai_name);
433 if (ret < 0)
434 return ret;
435
436 dlc->of_node = node;
437
438 if (is_single_link)
439 *is_single_link = of_graph_get_endpoint_count(node) == 1;
440
441 return 0;
442}
443
444static void graph_parse_convert(struct device_node *ep,
445 struct simple_dai_props *props)
446{
447 struct device_node *port = of_get_parent(ep);
448 struct device_node *ports = of_get_parent(port);
449 struct asoc_simple_data *adata = &props->adata;
450
451 if (of_node_name_eq(ports, "ports"))
452 asoc_simple_parse_convert(ports, NULL, adata);
453 asoc_simple_parse_convert(port, NULL, adata);
454 asoc_simple_parse_convert(ep, NULL, adata);
455
456 of_node_put(port);
457 of_node_put(ports);
458}
459
460static void graph_parse_mclk_fs(struct device_node *ep,
461 struct simple_dai_props *props)
462{
463 struct device_node *port = of_get_parent(ep);
464 struct device_node *ports = of_get_parent(port);
465
466 if (of_node_name_eq(ports, "ports"))
467 of_property_read_u32(ports, "mclk-fs", &props->mclk_fs);
468 of_property_read_u32(port, "mclk-fs", &props->mclk_fs);
469 of_property_read_u32(ep, "mclk-fs", &props->mclk_fs);
470
471 of_node_put(port);
472 of_node_put(ports);
473}
474
475static int __graph_parse_node(struct asoc_simple_priv *priv,
476 enum graph_type gtype,
477 struct device_node *ep,
478 struct link_info *li,
479 int is_cpu, int idx)
480{
481 struct device *dev = simple_priv_to_dev(priv);
482 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
483 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
484 struct snd_soc_dai_link_component *dlc;
485 struct asoc_simple_dai *dai;
486 int ret, is_single_links = 0;
487
488 if (is_cpu) {
489 dlc = asoc_link_to_cpu(dai_link, idx);
490 dai = simple_props_to_dai_cpu(dai_props, idx);
491 } else {
492 dlc = asoc_link_to_codec(dai_link, idx);
493 dai = simple_props_to_dai_codec(dai_props, idx);
494 }
495
496 graph_parse_mclk_fs(ep, dai_props);
497
498 ret = asoc_simple_parse_dai(ep, dlc, &is_single_links);
499 if (ret < 0)
500 return ret;
501
502 ret = asoc_simple_parse_tdm(ep, dai);
503 if (ret < 0)
504 return ret;
505
506 ret = asoc_simple_parse_tdm_width_map(dev, ep, dai);
507 if (ret < 0)
508 return ret;
509
510 ret = asoc_simple_parse_clk(dev, ep, dai, dlc);
511 if (ret < 0)
512 return ret;
513
514
515
516
517 if (!dai_link->name) {
518 struct snd_soc_dai_link_component *cpus = dlc;
519 struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, idx);
520 char *cpu_multi = "";
521 char *codec_multi = "";
522
523 if (dai_link->num_cpus > 1)
524 cpu_multi = "_multi";
525 if (dai_link->num_codecs > 1)
526 codec_multi = "_multi";
527
528 switch (gtype) {
529 case GRAPH_NORMAL:
530
531 if (is_cpu)
532 asoc_simple_set_dailink_name(dev, dai_link, "%s%s-%s%s",
533 cpus->dai_name, cpu_multi,
534 codecs->dai_name, codec_multi);
535 break;
536 case GRAPH_DPCM:
537 if (is_cpu)
538 asoc_simple_set_dailink_name(dev, dai_link, "fe.%pOFP.%s%s",
539 cpus->of_node, cpus->dai_name, cpu_multi);
540 else
541 asoc_simple_set_dailink_name(dev, dai_link, "be.%pOFP.%s%s",
542 codecs->of_node, codecs->dai_name, codec_multi);
543 break;
544 case GRAPH_C2C:
545
546 if (is_cpu)
547 asoc_simple_set_dailink_name(dev, dai_link, "c2c.%s%s-%s%s",
548 cpus->dai_name, cpu_multi,
549 codecs->dai_name, codec_multi);
550 break;
551 default:
552 break;
553 }
554 }
555
556
557
558
559
560 if (!is_cpu && gtype == GRAPH_DPCM) {
561 struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, idx);
562 struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, idx);
563 struct device_node *rport = of_get_parent(ep);
564 struct device_node *rports = of_get_parent(rport);
565
566 if (of_node_name_eq(rports, "ports"))
567 snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix");
568 snd_soc_of_parse_node_prefix(rport, cconf, codecs->of_node, "prefix");
569
570 of_node_put(rport);
571 of_node_put(rports);
572 }
573
574 if (is_cpu) {
575 struct snd_soc_dai_link_component *cpus = dlc;
576 struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, idx);
577
578 asoc_simple_canonicalize_cpu(cpus, is_single_links);
579 asoc_simple_canonicalize_platform(platforms, cpus);
580 }
581
582 return 0;
583}
584
585static int graph_parse_node(struct asoc_simple_priv *priv,
586 enum graph_type gtype,
587 struct device_node *port,
588 struct link_info *li, int is_cpu)
589{
590 struct device_node *ep;
591 int ret = 0;
592
593 if (graph_lnk_is_multi(port)) {
594 int idx;
595
596 of_node_get(port);
597
598 for (idx = 0;; idx++) {
599 ep = graph_get_next_multi_ep(&port);
600 if (!ep)
601 break;
602
603 ret = __graph_parse_node(priv, gtype, ep,
604 li, is_cpu, idx);
605 of_node_put(ep);
606 if (ret < 0)
607 break;
608 }
609 } else {
610
611 ep = port_to_endpoint(port);
612 ret = __graph_parse_node(priv, gtype, ep, li, is_cpu, 0);
613 of_node_put(ep);
614 }
615
616 return ret;
617}
618
619static void graph_parse_daifmt(struct device_node *node,
620 unsigned int *daifmt, unsigned int *bit_frame)
621{
622 unsigned int fmt;
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650 *bit_frame |= snd_soc_daifmt_parse_clock_provider_as_bitmap(node, NULL);
651
652#define update_daifmt(name) \
653 if (!(*daifmt & SND_SOC_DAIFMT_##name##_MASK) && \
654 (fmt & SND_SOC_DAIFMT_##name##_MASK)) \
655 *daifmt |= fmt & SND_SOC_DAIFMT_##name##_MASK
656
657
658
659
660
661
662
663 fmt = snd_soc_daifmt_parse_format(node, NULL);
664 update_daifmt(FORMAT);
665 update_daifmt(CLOCK);
666 update_daifmt(INV);
667}
668
669static void graph_link_init(struct asoc_simple_priv *priv,
670 struct device_node *port,
671 struct link_info *li,
672 int is_cpu_node)
673{
674 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
675 struct device_node *ep;
676 struct device_node *ports;
677 unsigned int daifmt = 0, daiclk = 0;
678 unsigned int bit_frame = 0;
679
680 if (graph_lnk_is_multi(port)) {
681 of_node_get(port);
682 ep = graph_get_next_multi_ep(&port);
683 port = of_get_parent(ep);
684 } else {
685 ep = port_to_endpoint(port);
686 }
687
688 ports = of_get_parent(port);
689
690
691
692
693
694
695
696
697
698
699
700
701
702 graph_parse_daifmt(ep, &daifmt, &bit_frame);
703 graph_parse_daifmt(port, &daifmt, &bit_frame);
704 if (of_node_name_eq(ports, "ports"))
705 graph_parse_daifmt(ports, &daifmt, &bit_frame);
706
707
708
709
710
711
712 daiclk = snd_soc_daifmt_clock_provider_from_bitmap(bit_frame);
713 if (is_cpu_node)
714 daiclk = snd_soc_daifmt_clock_provider_flipped(daiclk);
715
716 dai_link->dai_fmt = daifmt | daiclk;
717 dai_link->init = asoc_simple_dai_init;
718 dai_link->ops = &graph_ops;
719 if (priv->ops)
720 dai_link->ops = priv->ops;
721}
722
723int audio_graph2_link_normal(struct asoc_simple_priv *priv,
724 struct device_node *lnk,
725 struct link_info *li)
726{
727 struct device_node *cpu_port = lnk;
728 struct device_node *cpu_ep = port_to_endpoint(cpu_port);
729 struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
730 int ret;
731
732
733
734
735
736
737 ret = graph_parse_node(priv, GRAPH_NORMAL, codec_port, li, 0);
738 if (ret < 0)
739 goto err;
740
741
742
743
744 ret = graph_parse_node(priv, GRAPH_NORMAL, cpu_port, li, 1);
745 if (ret < 0)
746 goto err;
747
748 graph_link_init(priv, cpu_port, li, 1);
749err:
750 of_node_put(codec_port);
751 of_node_put(cpu_ep);
752
753 return ret;
754}
755EXPORT_SYMBOL_GPL(audio_graph2_link_normal);
756
757int audio_graph2_link_dpcm(struct asoc_simple_priv *priv,
758 struct device_node *lnk,
759 struct link_info *li)
760{
761 struct device_node *ep = port_to_endpoint(lnk);
762 struct device_node *rep = of_graph_get_remote_endpoint(ep);
763 struct device_node *rport = of_graph_get_remote_port(ep);
764 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
765 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
766 int is_cpu = asoc_graph_is_ports0(lnk);
767 int ret;
768
769 if (is_cpu) {
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794 dai_link->dynamic = 1;
795 dai_link->dpcm_merged_format = 1;
796
797 ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 1);
798 if (ret)
799 goto err;
800 } else {
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827 dai_link->no_pcm = 1;
828 dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup;
829
830 ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 0);
831 if (ret < 0)
832 goto err;
833 }
834
835 graph_parse_convert(rep, dai_props);
836
837 snd_soc_dai_link_set_capabilities(dai_link);
838
839 graph_link_init(priv, rport, li, is_cpu);
840err:
841 of_node_put(ep);
842 of_node_put(rep);
843 of_node_put(rport);
844
845 return ret;
846}
847EXPORT_SYMBOL_GPL(audio_graph2_link_dpcm);
848
849int audio_graph2_link_c2c(struct asoc_simple_priv *priv,
850 struct device_node *lnk,
851 struct link_info *li)
852{
853 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
854 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
855 struct snd_soc_pcm_stream *c2c_conf = dai_props->c2c_conf;
856 struct device_node *port0, *port1, *ports;
857 struct device_node *codec0_port, *codec1_port;
858 struct device_node *ep0, *ep1;
859 u32 val;
860 int ret = -EINVAL;
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878 of_node_get(lnk);
879 port0 = lnk;
880 ports = of_get_parent(port0);
881 port1 = of_get_next_child(ports, lnk);
882
883 if (!of_get_property(ports, "rate", &val)) {
884 struct device *dev = simple_priv_to_dev(priv);
885
886 dev_err(dev, "Codec2Codec needs rate settings\n");
887 goto err1;
888 }
889
890 c2c_conf->formats = SNDRV_PCM_FMTBIT_S32_LE;
891 c2c_conf->rate_min =
892 c2c_conf->rate_max = val;
893 c2c_conf->channels_min =
894 c2c_conf->channels_max = 2;
895 dai_link->params = c2c_conf;
896
897 ep0 = port_to_endpoint(port0);
898 ep1 = port_to_endpoint(port1);
899
900 codec0_port = of_graph_get_remote_port(ep0);
901 codec1_port = of_graph_get_remote_port(ep1);
902
903
904
905
906
907
908 ret = graph_parse_node(priv, GRAPH_C2C, codec1_port, li, 0);
909 if (ret < 0)
910 goto err2;
911
912
913
914
915 ret = graph_parse_node(priv, GRAPH_C2C, codec0_port, li, 1);
916 if (ret < 0)
917 goto err2;
918
919 graph_link_init(priv, codec0_port, li, 1);
920err2:
921 of_node_put(ep0);
922 of_node_put(ep1);
923 of_node_put(codec0_port);
924 of_node_put(codec1_port);
925err1:
926 of_node_put(ports);
927 of_node_put(port0);
928 of_node_put(port1);
929
930 return ret;
931}
932EXPORT_SYMBOL_GPL(audio_graph2_link_c2c);
933
934static int graph_link(struct asoc_simple_priv *priv,
935 struct graph2_custom_hooks *hooks,
936 enum graph_type gtype,
937 struct device_node *lnk,
938 struct link_info *li)
939{
940 struct device *dev = simple_priv_to_dev(priv);
941 GRAPH2_CUSTOM func = NULL;
942 int ret = -EINVAL;
943
944 switch (gtype) {
945 case GRAPH_NORMAL:
946 if (hooks && hooks->custom_normal)
947 func = hooks->custom_normal;
948 else
949 func = audio_graph2_link_normal;
950 break;
951 case GRAPH_DPCM:
952 if (hooks && hooks->custom_dpcm)
953 func = hooks->custom_dpcm;
954 else
955 func = audio_graph2_link_dpcm;
956 break;
957 case GRAPH_C2C:
958 if (hooks && hooks->custom_c2c)
959 func = hooks->custom_c2c;
960 else
961 func = audio_graph2_link_c2c;
962 break;
963 default:
964 break;
965 }
966
967 if (!func) {
968 dev_err(dev, "non supported gtype (%d)\n", gtype);
969 goto err;
970 }
971
972 ret = func(priv, lnk, li);
973 if (ret < 0)
974 goto err;
975
976 li->link++;
977err:
978 return ret;
979}
980
981static int graph_counter(struct device_node *lnk)
982{
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997 if (graph_lnk_is_multi(lnk))
998 return of_graph_get_endpoint_count(of_get_parent(lnk)) - 1;
999
1000
1001
1002 else
1003 return 1;
1004}
1005
1006static int graph_count_normal(struct asoc_simple_priv *priv,
1007 struct device_node *lnk,
1008 struct link_info *li)
1009{
1010 struct device_node *cpu_port = lnk;
1011 struct device_node *cpu_ep = port_to_endpoint(cpu_port);
1012 struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
1013
1014
1015
1016
1017
1018
1019 li->num[li->link].cpus =
1020 li->num[li->link].platforms = graph_counter(cpu_port);
1021 li->num[li->link].codecs = graph_counter(codec_port);
1022
1023 of_node_put(cpu_ep);
1024 of_node_put(codec_port);
1025
1026 return 0;
1027}
1028
1029static int graph_count_dpcm(struct asoc_simple_priv *priv,
1030 struct device_node *lnk,
1031 struct link_info *li)
1032{
1033 struct device_node *ep = port_to_endpoint(lnk);
1034 struct device_node *rport = of_graph_get_remote_port(ep);
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051 if (asoc_graph_is_ports0(lnk)) {
1052 li->num[li->link].cpus = graph_counter(rport);
1053 li->num[li->link].platforms = graph_counter(rport);
1054 } else {
1055 li->num[li->link].codecs = graph_counter(rport);
1056 }
1057
1058 of_node_put(ep);
1059 of_node_put(rport);
1060
1061 return 0;
1062}
1063
1064static int graph_count_c2c(struct asoc_simple_priv *priv,
1065 struct device_node *lnk,
1066 struct link_info *li)
1067{
1068 struct device_node *ports = of_get_parent(lnk);
1069 struct device_node *port0 = lnk;
1070 struct device_node *port1 = of_get_next_child(ports, lnk);
1071 struct device_node *ep0 = port_to_endpoint(port0);
1072 struct device_node *ep1 = port_to_endpoint(port1);
1073 struct device_node *codec0 = of_graph_get_remote_port(ep0);
1074 struct device_node *codec1 = of_graph_get_remote_port(ep1);
1075
1076 of_node_get(lnk);
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086 li->num[li->link].cpus =
1087 li->num[li->link].platforms = graph_counter(codec0);
1088 li->num[li->link].codecs = graph_counter(codec1);
1089 li->num[li->link].c2c = 1;
1090
1091 of_node_put(ports);
1092 of_node_put(port1);
1093 of_node_put(ep0);
1094 of_node_put(ep1);
1095 of_node_put(codec0);
1096 of_node_put(codec1);
1097
1098 return 0;
1099}
1100
1101static int graph_count(struct asoc_simple_priv *priv,
1102 struct graph2_custom_hooks *hooks,
1103 enum graph_type gtype,
1104 struct device_node *lnk,
1105 struct link_info *li)
1106{
1107 struct device *dev = simple_priv_to_dev(priv);
1108 GRAPH2_CUSTOM func = NULL;
1109 int ret = -EINVAL;
1110
1111 if (li->link >= SNDRV_MAX_LINKS) {
1112 dev_err(dev, "too many links\n");
1113 return ret;
1114 }
1115
1116 switch (gtype) {
1117 case GRAPH_NORMAL:
1118 func = graph_count_normal;
1119 break;
1120 case GRAPH_DPCM:
1121 func = graph_count_dpcm;
1122 break;
1123 case GRAPH_C2C:
1124 func = graph_count_c2c;
1125 break;
1126 default:
1127 break;
1128 }
1129
1130 if (!func) {
1131 dev_err(dev, "non supported gtype (%d)\n", gtype);
1132 goto err;
1133 }
1134
1135 ret = func(priv, lnk, li);
1136 if (ret < 0)
1137 goto err;
1138
1139 li->link++;
1140err:
1141 return ret;
1142}
1143
1144static int graph_for_each_link(struct asoc_simple_priv *priv,
1145 struct graph2_custom_hooks *hooks,
1146 struct link_info *li,
1147 int (*func)(struct asoc_simple_priv *priv,
1148 struct graph2_custom_hooks *hooks,
1149 enum graph_type gtype,
1150 struct device_node *lnk,
1151 struct link_info *li))
1152{
1153 struct of_phandle_iterator it;
1154 struct device *dev = simple_priv_to_dev(priv);
1155 struct device_node *node = dev->of_node;
1156 struct device_node *lnk;
1157 enum graph_type gtype;
1158 int rc, ret;
1159
1160
1161 of_for_each_phandle(&it, rc, node, "links", NULL, 0) {
1162 lnk = it.node;
1163
1164 gtype = graph_get_type(priv, lnk);
1165
1166 ret = func(priv, hooks, gtype, lnk, li);
1167 if (ret < 0)
1168 return ret;
1169 }
1170
1171 return 0;
1172}
1173
1174int audio_graph2_parse_of(struct asoc_simple_priv *priv, struct device *dev,
1175 struct graph2_custom_hooks *hooks)
1176{
1177 struct snd_soc_card *card = simple_priv_to_card(priv);
1178 struct link_info *li;
1179 int ret;
1180
1181 li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
1182 if (!li)
1183 return -ENOMEM;
1184
1185 card->probe = asoc_graph_card_probe;
1186 card->owner = THIS_MODULE;
1187 card->dev = dev;
1188
1189 if ((hooks) && (hooks)->hook_pre) {
1190 ret = (hooks)->hook_pre(priv);
1191 if (ret < 0)
1192 goto err;
1193 }
1194
1195 ret = graph_for_each_link(priv, hooks, li, graph_count);
1196 if (!li->link)
1197 ret = -EINVAL;
1198 if (ret < 0)
1199 goto err;
1200
1201 ret = asoc_simple_init_priv(priv, li);
1202 if (ret < 0)
1203 goto err;
1204
1205 priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW);
1206 if (IS_ERR(priv->pa_gpio)) {
1207 ret = PTR_ERR(priv->pa_gpio);
1208 dev_err(dev, "failed to get amplifier gpio: %d\n", ret);
1209 goto err;
1210 }
1211
1212 ret = asoc_simple_parse_widgets(card, NULL);
1213 if (ret < 0)
1214 goto err;
1215
1216 ret = asoc_simple_parse_routing(card, NULL);
1217 if (ret < 0)
1218 goto err;
1219
1220 memset(li, 0, sizeof(*li));
1221 ret = graph_for_each_link(priv, hooks, li, graph_link);
1222 if (ret < 0)
1223 goto err;
1224
1225 ret = asoc_simple_parse_card_name(card, NULL);
1226 if (ret < 0)
1227 goto err;
1228
1229 snd_soc_card_set_drvdata(card, priv);
1230
1231 if ((hooks) && (hooks)->hook_post) {
1232 ret = (hooks)->hook_post(priv);
1233 if (ret < 0)
1234 goto err;
1235 }
1236
1237 asoc_simple_debug_info(priv);
1238
1239 ret = devm_snd_soc_register_card(dev, card);
1240err:
1241 devm_kfree(dev, li);
1242
1243 if (ret < 0)
1244 dev_err_probe(dev, ret, "parse error\n");
1245
1246 if (ret == 0)
1247 dev_warn(dev, "Audio Graph Card2 is still under Experimental stage\n");
1248
1249 return ret;
1250}
1251EXPORT_SYMBOL_GPL(audio_graph2_parse_of);
1252
1253static int graph_probe(struct platform_device *pdev)
1254{
1255 struct asoc_simple_priv *priv;
1256 struct device *dev = &pdev->dev;
1257
1258
1259 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1260 if (!priv)
1261 return -ENOMEM;
1262
1263 return audio_graph2_parse_of(priv, dev, NULL);
1264}
1265
1266static const struct of_device_id graph_of_match[] = {
1267 { .compatible = "audio-graph-card2", },
1268 {},
1269};
1270MODULE_DEVICE_TABLE(of, graph_of_match);
1271
1272static struct platform_driver graph_card = {
1273 .driver = {
1274 .name = "asoc-audio-graph-card2",
1275 .pm = &snd_soc_pm_ops,
1276 .of_match_table = graph_of_match,
1277 },
1278 .probe = graph_probe,
1279 .remove = asoc_simple_remove,
1280};
1281module_platform_driver(graph_card);
1282
1283MODULE_ALIAS("platform:asoc-audio-graph-card2");
1284MODULE_LICENSE("GPL v2");
1285MODULE_DESCRIPTION("ASoC Audio Graph Card2");
1286MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
1287