blob: c3947347dda3573c8363b4b4ee4ce24baafc1bfb [file] [log] [blame]
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +09001// SPDX-License-Identifier: GPL-2.0
2//
3// ASoC Audio Graph Card2 support
4//
5// Copyright (C) 2020 Renesas Electronics Corp.
6// Copyright (C) 2020 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7//
8// based on ${LINUX}/sound/soc/generic/audio-graph-card.c
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 daifmt
24 ************************************
25 ports {
26 format = "left_j";
27 port@0 {
28 bitclock-master;
29 sample0: endpoint@0 {
30 frame-master;
31 };
32 sample1: endpoint@1 {
33 format = "i2s";
34 };
35 };
36 ...
37 };
38
39 You can set daifmt at ports/port/endpoint.
40 It uses *latest* format, and *share* master settings.
41 In above case,
42 sample0: left_j, bitclock-master, frame-master
43 sample1: i2s, bitclock-master
44
45 If there was no settings, *Codec* will be
46 bitclock/frame provider as default.
47 see
48 graph_parse_daifmt().
49
50 ************************************
51 Normal Audio-Graph
52 ************************************
53
54 CPU <---> Codec
55
56 sound {
57 compatible = "audio-graph-card2";
58 links = <&cpu>;
59 };
60
61 CPU {
62 cpu: port {
63 bitclock-master;
64 frame-master;
65 cpu_ep: endpoint { remote-endpoint = <&codec_ep>; }; };
66 };
67
68 Codec {
69 port { codec_ep: endpoint { remote-endpoint = <&cpu_ep>; }; };
70 };
71
Kuninori Morimotoc8c74932021-10-12 13:55:03 +090072 ************************************
73 Multi-CPU/Codec
74 ************************************
75
76It has connection part (= X) and list part (= y).
77links indicates connection part of CPU side (= A).
78
79 +-+ (A) +-+
80 CPU1 --(y) | | <-(X)--(X)-> | | (y)-- Codec1
81 CPU2 --(y) | | | | (y)-- Codec2
82 +-+ +-+
83
84 sound {
85 compatible = "audio-graph-card2";
86
87(A) links = <&mcpu>;
88
89 multi {
90 ports@0 {
91(X) (A) mcpu: port@0 { mcpu0_ep: endpoint { remote-endpoint = <&mcodec0_ep>; }; };
92(y) port@1 { mcpu1_ep: endpoint { remote-endpoint = <&cpu1_ep>; }; };
93(y) port@1 { mcpu2_ep: endpoint { remote-endpoint = <&cpu2_ep>; }; };
94 };
95 ports@1 {
96(X) port@0 { mcodec0_ep: endpoint { remote-endpoint = <&mcpu0_ep>; }; };
97(y) port@0 { mcodec1_ep: endpoint { remote-endpoint = <&codec1_ep>; }; };
98(y) port@1 { mcodec2_ep: endpoint { remote-endpoint = <&codec2_ep>; }; };
99 };
100 };
101 };
102
103 CPU {
104 ports {
105 bitclock-master;
106 frame-master;
107 port@0 { cpu1_ep: endpoint { remote-endpoint = <&mcpu1_ep>; }; };
108 port@1 { cpu2_ep: endpoint { remote-endpoint = <&mcpu2_ep>; }; };
109 };
110 };
111
112 Codec {
113 ports {
114 port@0 { codec1_ep: endpoint { remote-endpoint = <&mcodec1_ep>; }; };
115 port@1 { codec2_ep: endpoint { remote-endpoint = <&mcodec2_ep>; }; };
116 };
117 };
118
Kuninori Morimotof03beb52021-10-12 13:55:12 +0900119 ************************************
120 DPCM
121 ************************************
122
123 DSP
124 ************
125 PCM0 <--> * fe0 be0 * <--> DAI0: Codec Headset
126 PCM1 <--> * fe1 be1 * <--> DAI1: Codec Speakers
127 PCM2 <--> * fe2 be2 * <--> DAI2: MODEM
128 PCM3 <--> * fe3 be3 * <--> DAI3: BT
129 * be4 * <--> DAI4: DMIC
130 * be5 * <--> DAI5: FM
131 ************
132
133 sound {
134 compatible = "audio-graph-card2";
135
136 // indicate routing
137 routing = "xxx Playback", "xxx Playback",
138 "xxx Playback", "xxx Playback",
139 "xxx Playback", "xxx Playback";
140
141 // indicate all Front-End, Back-End
142 links = <&fe0, &fe1, ...,
143 &be0, &be1, ...>;
144
145 dpcm {
146 // Front-End
147 ports@0 {
148 fe0: port@0 { fe0_ep: endpoint { remote-endpoint = <&pcm0_ep>; }; };
149 fe1: port@1 { fe1_ep: endpoint { remote-endpoint = <&pcm1_ep>; }; };
150 ...
151 };
152 // Back-End
153 ports@1 {
154 be0: port@0 { be0_ep: endpoint { remote-endpoint = <&dai0_ep>; }; };
155 be1: port@1 { be1_ep: endpoint { remote-endpoint = <&dai1_ep>; }; };
156 ...
157 };
158 };
159 };
160
161 CPU {
162 ports {
163 bitclock-master;
164 frame-master;
165 port@0 { pcm0_ep: endpoint { remote-endpoint = <&fe0_ep>; }; };
166 port@1 { pcm1_ep: endpoint { remote-endpoint = <&fe1_ep>; }; };
167 ...
168 };
169 };
170
171 Codec {
172 ports {
173 port@0 { dai0_ep: endpoint { remote-endpoint = <&be0_ep>; }; };
174 port@1 { dai1_ep: endpoint { remote-endpoint = <&be1_ep>; }; };
175 ...
176 };
177 };
178
Kuninori Morimotoc3a15c92021-10-12 13:55:33 +0900179 ************************************
180 Codec to Codec
181 ************************************
182
183 +--+
184 | |<-- Codec0 <- IN
185 | |--> Codec1 -> OUT
186 +--+
187
188 sound {
189 compatible = "audio-graph-card2";
190
191 routing = "OUT" ,"DAI1 Playback",
192 "DAI0 Capture", "IN";
193
194 links = <&c2c>;
195
196 codec2codec {
197 ports {
198 rate = <48000>;
199 c2c: port@0 { c2cf_ep: endpoint { remote-endpoint = <&codec0_ep>; }; };
200 port@1 { c2cb_ep: endpoint { remote-endpoint = <&codec1_ep>; }; };
201 };
202 };
203
204 Codec {
205 ports {
206 port@0 {
207 bitclock-master;
208 frame-master;
209 codec0_ep: endpoint { remote-endpoint = <&c2cf_ep>; }; };
210 port@1 { codec1_ep: endpoint { remote-endpoint = <&c2cb_ep>; }; };
211 };
212 };
213
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900214*/
215
216enum graph_type {
217 GRAPH_NORMAL,
Kuninori Morimotof03beb52021-10-12 13:55:12 +0900218 GRAPH_DPCM,
Kuninori Morimotoc3a15c92021-10-12 13:55:33 +0900219 GRAPH_C2C,
Kuninori Morimotoc8c74932021-10-12 13:55:03 +0900220
221 GRAPH_MULTI, /* don't use ! Use this only in __graph_get_type() */
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900222};
223
Kuninori Morimotoc8c74932021-10-12 13:55:03 +0900224#define GRAPH_NODENAME_MULTI "multi"
Kuninori Morimotof03beb52021-10-12 13:55:12 +0900225#define GRAPH_NODENAME_DPCM "dpcm"
Kuninori Morimotoc3a15c92021-10-12 13:55:33 +0900226#define GRAPH_NODENAME_C2C "codec2codec"
Kuninori Morimotoc8c74932021-10-12 13:55:03 +0900227
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900228#define port_to_endpoint(port) of_get_child_by_name(port, "endpoint")
229
Kuninori Morimotoc8c74932021-10-12 13:55:03 +0900230static enum graph_type __graph_get_type(struct device_node *lnk)
231{
232 struct device_node *np;
233
234 /*
235 * target {
236 * ports {
237 * => lnk: port@0 { ... };
238 * port@1 { ... };
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
Kuninori Morimotof03beb52021-10-12 13:55:12 +0900249 if (of_node_name_eq(np, GRAPH_NODENAME_DPCM))
250 return GRAPH_DPCM;
251
Kuninori Morimotoc3a15c92021-10-12 13:55:33 +0900252 if (of_node_name_eq(np, GRAPH_NODENAME_C2C))
253 return GRAPH_C2C;
254
Kuninori Morimotoc8c74932021-10-12 13:55:03 +0900255 return GRAPH_NORMAL;
256}
257
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900258static enum graph_type graph_get_type(struct asoc_simple_priv *priv,
259 struct device_node *lnk)
260{
Kuninori Morimotoc8c74932021-10-12 13:55:03 +0900261 enum graph_type type = __graph_get_type(lnk);
262
263 /* GRAPH_MULTI here means GRAPH_NORMAL */
264 if (type == GRAPH_MULTI)
265 type = GRAPH_NORMAL;
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900266
267#ifdef DEBUG
268 {
269 struct device *dev = simple_priv_to_dev(priv);
270 const char *str = "Normal";
271
Kuninori Morimotof03beb52021-10-12 13:55:12 +0900272 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;
Kuninori Morimotoc3a15c92021-10-12 13:55:33 +0900279 case GRAPH_C2C:
280 str = "Codec2Codec";
281 break;
Kuninori Morimotof03beb52021-10-12 13:55:12 +0900282 default:
283 break;
284 }
285
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900286 dev_dbg(dev, "%pOF (%s)", lnk, str);
287 }
288#endif
289 return type;
290}
291
Kuninori Morimotoc8c74932021-10-12 13:55:03 +0900292static 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 * multi {
305 * ports {
306 * => lnk: port@0 { ... };
307 * port@1 { ep { ... = rep0 } };
308 * port@2 { ep { ... = rep1 } };
309 * ...
310 * };
311 * };
312 *
313 * xxx {
314 * port@0 { rep0 };
315 * port@1 { rep1 };
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
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900335static 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 /* use driver specified DAI ID if exist */
351 ret = snd_soc_get_dai_id(ep);
352 if (ret != -ENOTSUPP)
353 return ret;
354
355 /* use endpoint/port reg if exist */
356 ret = of_graph_parse_endpoint(ep, &info);
357 if (ret == 0) {
358 /*
359 * Because it will count port/endpoint if it doesn't have "reg".
360 * But, we can't judge whether it has "no reg", or "reg = <0>"
361 * only of_graph_parse_endpoint().
362 * We need to check "reg" property
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 * Non HDMI sound case, counting port/endpoint on its DT
377 * is enough. Let's count it.
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 /* Get dai->name */
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 * FIXME
415 *
416 * Here, dlc->dai_name is pointer to CPU/Codec DAI name.
417 * If user unbinded CPU or Codec driver, but not for Sound Card,
418 * dlc->dai_name is keeping unbinded CPU or Codec
419 * driver's pointer.
420 *
421 * If user re-bind CPU or Codec driver again, ALSA SoC will try
422 * to rebind Card via snd_soc_try_rebind_card(), but because of
423 * above reason, it might can't bind Sound Card.
424 * Because Sound Card is pointing to released dai_name pointer.
425 *
426 * To avoid this rebind Card issue,
427 * 1) It needs to alloc memory to keep dai_name eventhough
428 * CPU or Codec driver was unbinded, or
429 * 2) user need to rebind Sound Card everytime
430 * if he unbinded CPU or Codec.
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
Kuninori Morimotof03beb52021-10-12 13:55:12 +0900444static 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
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900460static 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_clk(dev, ep, dai, dlc);
507 if (ret < 0)
508 return ret;
509
510 /*
511 * set DAI Name
512 */
513 if (!dai_link->name) {
514 struct snd_soc_dai_link_component *cpus = dlc;
515 struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, idx);
Kuninori Morimotoc8c74932021-10-12 13:55:03 +0900516 char *cpu_multi = "";
517 char *codec_multi = "";
518
519 if (dai_link->num_cpus > 1)
520 cpu_multi = "_multi";
521 if (dai_link->num_codecs > 1)
522 codec_multi = "_multi";
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900523
524 switch (gtype) {
525 case GRAPH_NORMAL:
526 /* run is_cpu only. see audio_graph2_link_normal() */
527 if (is_cpu)
Kuninori Morimotoc8c74932021-10-12 13:55:03 +0900528 asoc_simple_set_dailink_name(dev, dai_link, "%s%s-%s%s",
529 cpus->dai_name, cpu_multi,
530 codecs->dai_name, codec_multi);
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900531 break;
Kuninori Morimotof03beb52021-10-12 13:55:12 +0900532 case GRAPH_DPCM:
533 if (is_cpu)
534 asoc_simple_set_dailink_name(dev, dai_link, "fe.%pOFP.%s%s",
535 cpus->of_node, cpus->dai_name, cpu_multi);
536 else
537 asoc_simple_set_dailink_name(dev, dai_link, "be.%pOFP.%s%s",
538 codecs->of_node, codecs->dai_name, codec_multi);
539 break;
Kuninori Morimotoc3a15c92021-10-12 13:55:33 +0900540 case GRAPH_C2C:
541 /* run is_cpu only. see audio_graph2_link_c2c() */
542 if (is_cpu)
543 asoc_simple_set_dailink_name(dev, dai_link, "c2c.%s%s-%s%s",
544 cpus->dai_name, cpu_multi,
545 codecs->dai_name, codec_multi);
546 break;
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900547 default:
548 break;
549 }
550 }
551
Kuninori Morimotof03beb52021-10-12 13:55:12 +0900552 /*
553 * Check "prefix" from top node
554 * if DPCM-BE case
555 */
556 if (!is_cpu && gtype == GRAPH_DPCM) {
557 struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, idx);
558 struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, idx);
559 struct device_node *rport = of_get_parent(ep);
560 struct device_node *rports = of_get_parent(rport);
561
562 if (of_node_name_eq(rports, "ports"))
563 snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix");
564 snd_soc_of_parse_node_prefix(rport, cconf, codecs->of_node, "prefix");
565
566 of_node_put(rport);
567 of_node_put(rports);
568 }
569
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900570 if (is_cpu) {
571 struct snd_soc_dai_link_component *cpus = dlc;
572 struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, idx);
573
574 asoc_simple_canonicalize_cpu(cpus, is_single_links);
575 asoc_simple_canonicalize_platform(platforms, cpus);
576 }
577
578 return 0;
579}
580
581static int graph_parse_node(struct asoc_simple_priv *priv,
582 enum graph_type gtype,
583 struct device_node *port,
584 struct link_info *li, int is_cpu)
585{
Kuninori Morimotoc8c74932021-10-12 13:55:03 +0900586 struct device_node *ep;
587 int ret = 0;
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900588
Kuninori Morimotoc8c74932021-10-12 13:55:03 +0900589 if (graph_lnk_is_multi(port)) {
590 int idx;
591
592 of_node_get(port);
593
594 for (idx = 0;; idx++) {
595 ep = graph_get_next_multi_ep(&port);
596 if (!ep)
597 break;
598
599 ret = __graph_parse_node(priv, gtype, ep,
600 li, is_cpu, idx);
601 of_node_put(ep);
602 if (ret < 0)
603 break;
604 }
605 } else {
606 /* Single CPU / Codec */
607 ep = port_to_endpoint(port);
608 ret = __graph_parse_node(priv, gtype, ep, li, is_cpu, 0);
609 of_node_put(ep);
610 }
611
612 return ret;
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900613}
614
615static void graph_parse_daifmt(struct device_node *node,
616 unsigned int *daifmt, unsigned int *bit_frame)
617{
618 unsigned int fmt;
619
620 /*
621 * see also above "daifmt" explanation
622 * and samples.
623 */
624
625 /*
626 * ports {
627 * (A)
628 * port {
629 * (B)
630 * endpoint {
631 * (C)
632 * };
633 * };
634 * };
635 * };
636 */
637
638 /*
639 * clock_provider:
640 *
641 * It can be judged it is provider
642 * if (A) or (B) or (C) has bitclock-master / frame-master flag.
643 *
644 * use "or"
645 */
646 *bit_frame |= snd_soc_daifmt_parse_clock_provider_as_bitmap(node, NULL);
647
648#define update_daifmt(name) \
649 if (!(*daifmt & SND_SOC_DAIFMT_##name##_MASK) && \
650 (fmt & SND_SOC_DAIFMT_##name##_MASK)) \
651 *daifmt |= fmt & SND_SOC_DAIFMT_##name##_MASK
652
653 /*
654 * format
655 *
656 * This function is called by (C) -> (B) -> (A) order.
657 * Set if applicable part was not yet set.
658 */
659 fmt = snd_soc_daifmt_parse_format(node, NULL);
660 update_daifmt(FORMAT);
661 update_daifmt(CLOCK);
662 update_daifmt(INV);
663}
664
665static void graph_link_init(struct asoc_simple_priv *priv,
666 struct device_node *port,
667 struct link_info *li,
668 int is_cpu_node)
669{
670 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
671 struct device_node *ep;
672 struct device_node *ports;
673 unsigned int daifmt = 0, daiclk = 0;
674 unsigned int bit_frame = 0;
675
Kuninori Morimotoc8c74932021-10-12 13:55:03 +0900676 if (graph_lnk_is_multi(port)) {
677 of_node_get(port);
678 ep = graph_get_next_multi_ep(&port);
679 port = of_get_parent(ep);
680 } else {
681 ep = port_to_endpoint(port);
682 }
683
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900684 ports = of_get_parent(port);
685
686 /*
687 * ports {
688 * (A)
689 * port {
690 * (B)
691 * endpoint {
692 * (C)
693 * };
694 * };
695 * };
696 * };
697 */
698 graph_parse_daifmt(ep, &daifmt, &bit_frame); /* (C) */
699 graph_parse_daifmt(port, &daifmt, &bit_frame); /* (B) */
700 if (of_node_name_eq(ports, "ports"))
701 graph_parse_daifmt(ports, &daifmt, &bit_frame); /* (A) */
702
703 /*
704 * convert bit_frame
705 * We need to flip clock_provider if it was CPU node,
706 * because it is Codec base.
707 */
708 daiclk = snd_soc_daifmt_clock_provider_from_bitmap(bit_frame);
709 if (is_cpu_node)
710 daiclk = snd_soc_daifmt_clock_provider_fliped(daiclk);
711
712 dai_link->dai_fmt = daifmt | daiclk;
713 dai_link->init = asoc_simple_dai_init;
714 dai_link->ops = &graph_ops;
715 if (priv->ops)
716 dai_link->ops = priv->ops;
717}
718
719int audio_graph2_link_normal(struct asoc_simple_priv *priv,
720 struct device_node *lnk,
721 struct link_info *li)
722{
723 struct device_node *cpu_port = lnk;
724 struct device_node *cpu_ep = port_to_endpoint(cpu_port);
725 struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
726 int ret;
727
728 /*
729 * call Codec first.
730 * see
731 * __graph_parse_node() :: DAI Naming
732 */
733 ret = graph_parse_node(priv, GRAPH_NORMAL, codec_port, li, 0);
734 if (ret < 0)
735 goto err;
736
737 /*
738 * call CPU, and set DAI Name
739 */
740 ret = graph_parse_node(priv, GRAPH_NORMAL, cpu_port, li, 1);
741 if (ret < 0)
742 goto err;
743
744 graph_link_init(priv, cpu_port, li, 1);
745err:
746 of_node_put(codec_port);
747 of_node_put(cpu_ep);
748
749 return ret;
750}
751EXPORT_SYMBOL_GPL(audio_graph2_link_normal);
752
Kuninori Morimotof03beb52021-10-12 13:55:12 +0900753int audio_graph2_link_dpcm(struct asoc_simple_priv *priv,
754 struct device_node *lnk,
755 struct link_info *li)
756{
757 struct device_node *ep = port_to_endpoint(lnk);
758 struct device_node *rep = of_graph_get_remote_endpoint(ep);
759 struct device_node *rport = of_graph_get_remote_port(ep);
760 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
761 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
762 int is_cpu = asoc_graph_is_ports0(lnk);
763 int ret;
764
765 if (is_cpu) {
766 /*
767 * dpcm {
768 * // Front-End
769 * ports@0 {
770 * => lnk: port@0 { ep: { ... = rep }; };
771 * ...
772 * };
773 * // Back-End
774 * ports@0 {
775 * ...
776 * };
777 * };
778 *
779 * CPU {
780 * rports: ports {
781 * rport: port@0 { rep: { ... = ep } };
782 * }
783 * }
784 */
785 /*
786 * setup CPU here, Codec is already set as dummy.
787 * see
788 * asoc_simple_init_priv()
789 */
790 dai_link->dynamic = 1;
791 dai_link->dpcm_merged_format = 1;
792
793 ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 1);
794 if (ret)
795 goto err;
796 } else {
797 /*
798 * dpcm {
799 * // Front-End
800 * ports@0 {
801 * ...
802 * };
803 * // Back-End
804 * ports@0 {
805 * => lnk: port@0 { ep: { ... = rep; }; };
806 * ...
807 * };
808 * };
809 *
810 * Codec {
811 * rports: ports {
812 * rport: port@0 { rep: { ... = ep; }; };
813 * }
814 * }
815 */
816 /*
817 * setup Codec here, CPU is already set as dummy.
818 * see
819 * asoc_simple_init_priv()
820 */
821
822 /* BE settings */
823 dai_link->no_pcm = 1;
824 dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup;
825
826 ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 0);
827 if (ret < 0)
828 goto err;
829 }
830
831 graph_parse_convert(rep, dai_props);
832
833 snd_soc_dai_link_set_capabilities(dai_link);
834
835 graph_link_init(priv, rport, li, is_cpu);
836err:
837 of_node_put(ep);
838 of_node_put(rep);
839 of_node_put(rport);
840
841 return ret;
842}
843EXPORT_SYMBOL_GPL(audio_graph2_link_dpcm);
844
Kuninori Morimotoc3a15c92021-10-12 13:55:33 +0900845int audio_graph2_link_c2c(struct asoc_simple_priv *priv,
846 struct device_node *lnk,
847 struct link_info *li)
848{
849 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
850 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
851 struct snd_soc_pcm_stream *c2c_conf = dai_props->c2c_conf;
852 struct device_node *port0, *port1, *ports;
853 struct device_node *codec0_port, *codec1_port;
854 struct device_node *ep0, *ep1;
855 u32 val;
856 int ret = -EINVAL;
857
858 /*
859 * codec2codec {
860 * ports {
861 * rate = <48000>;
862 * => lnk: port@0 { c2c0_ep: { ... = codec0_ep; }; };
863 * port@1 { c2c1_ep: { ... = codec1_ep; }; };
864 * };
865 * };
866 *
867 * Codec {
868 * ports {
869 * port@0 { codec0_ep: ... }; };
870 * port@1 { codec1_ep: ... }; };
871 * };
872 * };
873 */
874 of_node_get(lnk);
875 port0 = lnk;
876 ports = of_get_parent(port0);
877 port1 = of_get_next_child(ports, lnk);
878
879 if (!of_get_property(ports, "rate", &val)) {
880 struct device *dev = simple_priv_to_dev(priv);
881
882 dev_err(dev, "Codec2Codec needs rate settings\n");
883 goto err1;
884 }
885
886 c2c_conf->formats = SNDRV_PCM_FMTBIT_S32_LE; /* update ME */
887 c2c_conf->rate_min =
888 c2c_conf->rate_max = val;
889 c2c_conf->channels_min =
890 c2c_conf->channels_max = 2; /* update ME */
891 dai_link->params = c2c_conf;
892
893 ep0 = port_to_endpoint(port0);
894 ep1 = port_to_endpoint(port1);
895
896 codec0_port = of_graph_get_remote_port(ep0);
897 codec1_port = of_graph_get_remote_port(ep1);
898
899 /*
900 * call Codec first.
901 * see
902 * __graph_parse_node() :: DAI Naming
903 */
904 ret = graph_parse_node(priv, GRAPH_C2C, codec1_port, li, 0);
905 if (ret < 0)
906 goto err2;
907
908 /*
909 * call CPU, and set DAI Name
910 */
911 ret = graph_parse_node(priv, GRAPH_C2C, codec0_port, li, 1);
912 if (ret < 0)
913 goto err2;
914
915 graph_link_init(priv, codec0_port, li, 1);
916err2:
917 of_node_put(ep0);
918 of_node_put(ep1);
919 of_node_put(codec0_port);
920 of_node_put(codec1_port);
921err1:
922 of_node_put(ports);
923 of_node_put(port0);
924 of_node_put(port1);
925
926 return ret;
927}
928EXPORT_SYMBOL_GPL(audio_graph2_link_c2c);
929
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900930static int graph_link(struct asoc_simple_priv *priv,
931 struct graph2_custom_hooks *hooks,
932 enum graph_type gtype,
933 struct device_node *lnk,
934 struct link_info *li)
935{
936 struct device *dev = simple_priv_to_dev(priv);
937 GRAPH2_CUSTOM func = NULL;
938 int ret = -EINVAL;
939
940 switch (gtype) {
941 case GRAPH_NORMAL:
942 if (hooks && hooks->custom_normal)
943 func = hooks->custom_normal;
944 else
945 func = audio_graph2_link_normal;
946 break;
Kuninori Morimotof03beb52021-10-12 13:55:12 +0900947 case GRAPH_DPCM:
948 if (hooks && hooks->custom_dpcm)
949 func = hooks->custom_dpcm;
950 else
951 func = audio_graph2_link_dpcm;
952 break;
Kuninori Morimotoc3a15c92021-10-12 13:55:33 +0900953 case GRAPH_C2C:
954 if (hooks && hooks->custom_c2c)
955 func = hooks->custom_c2c;
956 else
957 func = audio_graph2_link_c2c;
958 break;
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +0900959 default:
960 break;
961 }
962
963 if (!func) {
964 dev_err(dev, "non supported gtype (%d)\n", gtype);
965 goto err;
966 }
967
968 ret = func(priv, lnk, li);
969 if (ret < 0)
970 goto err;
971
972 li->link++;
973err:
974 return ret;
975}
976
977static int graph_counter(struct device_node *lnk)
978{
Kuninori Morimotoc8c74932021-10-12 13:55:03 +0900979 /*
980 * Multi CPU / Codec
981 *
982 * multi {
983 * ports {
984 * => lnk: port@0 { ... };
985 * port@1 { ... };
986 * port@2 { ... };
987 * ...
988 * };
989 * };
990 *
991 * ignore first lnk part
992 */
993 if (graph_lnk_is_multi(lnk))
994 return of_graph_get_endpoint_count(of_get_parent(lnk)) - 1;
995 /*
996 * Single CPU / Codec
997 */
998 else
999 return 1;
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +09001000}
1001
1002static int graph_count_normal(struct asoc_simple_priv *priv,
1003 struct device_node *lnk,
1004 struct link_info *li)
1005{
1006 struct device_node *cpu_port = lnk;
1007 struct device_node *cpu_ep = port_to_endpoint(cpu_port);
1008 struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
1009
1010 /*
1011 * CPU {
1012 * => lnk: port { endpoint { .. }; };
1013 * };
1014 */
1015 li->num[li->link].cpus =
1016 li->num[li->link].platforms = graph_counter(cpu_port);
1017 li->num[li->link].codecs = graph_counter(codec_port);
1018
1019 of_node_put(cpu_ep);
1020 of_node_put(codec_port);
1021
1022 return 0;
1023}
1024
Kuninori Morimotof03beb52021-10-12 13:55:12 +09001025static int graph_count_dpcm(struct asoc_simple_priv *priv,
1026 struct device_node *lnk,
1027 struct link_info *li)
1028{
1029 struct device_node *ep = port_to_endpoint(lnk);
1030 struct device_node *rport = of_graph_get_remote_port(ep);
1031
1032 /*
1033 * dpcm {
1034 * // Front-End
1035 * ports@0 {
1036 * => lnk: port@0 { endpoint { ... }; };
1037 * ...
1038 * };
1039 * // Back-End
1040 * ports@1 {
1041 * => lnk: port@0 { endpoint { ... }; };
1042 * ...
1043 * };
1044 * };
1045 */
1046
1047 if (asoc_graph_is_ports0(lnk)) {
1048 li->num[li->link].cpus = graph_counter(rport); /* FE */
1049 li->num[li->link].platforms = graph_counter(rport);
1050 } else {
1051 li->num[li->link].codecs = graph_counter(rport); /* BE */
1052 }
1053
1054 of_node_put(ep);
1055 of_node_put(rport);
1056
1057 return 0;
1058}
1059
Kuninori Morimotoc3a15c92021-10-12 13:55:33 +09001060static int graph_count_c2c(struct asoc_simple_priv *priv,
1061 struct device_node *lnk,
1062 struct link_info *li)
1063{
1064 struct device_node *ports = of_get_parent(lnk);
1065 struct device_node *port0 = lnk;
1066 struct device_node *port1 = of_get_next_child(ports, lnk);
1067 struct device_node *ep0 = port_to_endpoint(port0);
1068 struct device_node *ep1 = port_to_endpoint(port1);
1069 struct device_node *codec0 = of_graph_get_remote_port(ep0);
1070 struct device_node *codec1 = of_graph_get_remote_port(ep1);
1071
1072 of_node_get(lnk);
1073
1074 /*
1075 * codec2codec {
1076 * ports {
1077 * => lnk: port@0 { endpoint { ... }; };
1078 * port@1 { endpoint { ... }; };
1079 * };
1080 * };
1081 */
1082 li->num[li->link].cpus =
1083 li->num[li->link].platforms = graph_counter(codec0);
1084 li->num[li->link].codecs = graph_counter(codec1);
1085 li->num[li->link].c2c = 1;
1086
1087 of_node_put(ports);
1088 of_node_put(port1);
1089 of_node_put(ep0);
1090 of_node_put(ep1);
1091 of_node_put(codec0);
1092 of_node_put(codec1);
1093
1094 return 0;
1095}
1096
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +09001097static int graph_count(struct asoc_simple_priv *priv,
1098 struct graph2_custom_hooks *hooks,
1099 enum graph_type gtype,
1100 struct device_node *lnk,
1101 struct link_info *li)
1102{
1103 struct device *dev = simple_priv_to_dev(priv);
1104 GRAPH2_CUSTOM func = NULL;
1105 int ret = -EINVAL;
1106
1107 if (li->link >= SNDRV_MAX_LINKS) {
1108 dev_err(dev, "too many links\n");
1109 return ret;
1110 }
1111
1112 switch (gtype) {
1113 case GRAPH_NORMAL:
1114 func = graph_count_normal;
1115 break;
Kuninori Morimotof03beb52021-10-12 13:55:12 +09001116 case GRAPH_DPCM:
1117 func = graph_count_dpcm;
1118 break;
Kuninori Morimotoc3a15c92021-10-12 13:55:33 +09001119 case GRAPH_C2C:
1120 func = graph_count_c2c;
1121 break;
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +09001122 default:
1123 break;
1124 }
1125
1126 if (!func) {
1127 dev_err(dev, "non supported gtype (%d)\n", gtype);
1128 goto err;
1129 }
1130
1131 ret = func(priv, lnk, li);
1132 if (ret < 0)
1133 goto err;
1134
1135 li->link++;
1136err:
1137 return ret;
1138}
1139
1140static int graph_for_each_link(struct asoc_simple_priv *priv,
1141 struct graph2_custom_hooks *hooks,
1142 struct link_info *li,
1143 int (*func)(struct asoc_simple_priv *priv,
1144 struct graph2_custom_hooks *hooks,
1145 enum graph_type gtype,
1146 struct device_node *lnk,
1147 struct link_info *li))
1148{
1149 struct of_phandle_iterator it;
1150 struct device *dev = simple_priv_to_dev(priv);
1151 struct device_node *node = dev->of_node;
1152 struct device_node *lnk;
1153 enum graph_type gtype;
1154 int rc, ret;
1155
1156 /* loop for all listed CPU port */
1157 of_for_each_phandle(&it, rc, node, "links", NULL, 0) {
1158 lnk = it.node;
1159
1160 gtype = graph_get_type(priv, lnk);
1161
1162 ret = func(priv, hooks, gtype, lnk, li);
1163 if (ret < 0)
1164 return ret;
1165 }
1166
1167 return 0;
1168}
1169
1170int audio_graph2_parse_of(struct asoc_simple_priv *priv, struct device *dev,
1171 struct graph2_custom_hooks *hooks)
1172{
1173 struct snd_soc_card *card = simple_priv_to_card(priv);
1174 struct link_info *li;
1175 int ret;
1176
1177 dev_warn(dev, "Audio Graph Card2 is still under Experimental stage\n");
1178
1179 li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
1180 if (!li)
1181 return -ENOMEM;
1182
1183 card->probe = asoc_graph_card_probe;
1184 card->owner = THIS_MODULE;
1185 card->dev = dev;
1186
1187 if ((hooks) && (hooks)->hook_pre) {
1188 ret = (hooks)->hook_pre(priv);
1189 if (ret < 0)
1190 goto err;
1191 }
1192
1193 ret = graph_for_each_link(priv, hooks, li, graph_count);
1194 if (!li->link)
1195 ret = -EINVAL;
1196 if (ret < 0)
1197 goto err;
1198
1199 ret = asoc_simple_init_priv(priv, li);
1200 if (ret < 0)
1201 goto err;
1202
1203 priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW);
1204 if (IS_ERR(priv->pa_gpio)) {
1205 ret = PTR_ERR(priv->pa_gpio);
1206 dev_err(dev, "failed to get amplifier gpio: %d\n", ret);
1207 goto err;
1208 }
1209
1210 ret = asoc_simple_parse_widgets(card, NULL);
1211 if (ret < 0)
1212 goto err;
1213
1214 ret = asoc_simple_parse_routing(card, NULL);
1215 if (ret < 0)
1216 goto err;
1217
1218 memset(li, 0, sizeof(*li));
1219 ret = graph_for_each_link(priv, hooks, li, graph_link);
1220 if (ret < 0)
1221 goto err;
1222
1223 ret = asoc_simple_parse_card_name(card, NULL);
1224 if (ret < 0)
1225 goto err;
1226
1227 snd_soc_card_set_drvdata(card, priv);
1228
1229 if ((hooks) && (hooks)->hook_post) {
1230 ret = (hooks)->hook_post(priv);
1231 if (ret < 0)
1232 goto err;
1233 }
1234
1235 asoc_simple_debug_info(priv);
1236
1237 ret = devm_snd_soc_register_card(dev, card);
1238err:
1239 devm_kfree(dev, li);
1240
Kuninori Morimoto7a0299e2021-12-14 11:08:35 +09001241 if (ret < 0)
1242 dev_err_probe(dev, ret, "parse error\n");
Kuninori Morimoto6e5f68f2021-10-12 13:54:46 +09001243
1244 return ret;
1245}
1246EXPORT_SYMBOL_GPL(audio_graph2_parse_of);
1247
1248static int graph_probe(struct platform_device *pdev)
1249{
1250 struct asoc_simple_priv *priv;
1251 struct device *dev = &pdev->dev;
1252
1253 /* Allocate the private data and the DAI link array */
1254 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1255 if (!priv)
1256 return -ENOMEM;
1257
1258 return audio_graph2_parse_of(priv, dev, NULL);
1259}
1260
1261static const struct of_device_id graph_of_match[] = {
1262 { .compatible = "audio-graph-card2", },
1263 {},
1264};
1265MODULE_DEVICE_TABLE(of, graph_of_match);
1266
1267static struct platform_driver graph_card = {
1268 .driver = {
1269 .name = "asoc-audio-graph-card2",
1270 .pm = &snd_soc_pm_ops,
1271 .of_match_table = graph_of_match,
1272 },
1273 .probe = graph_probe,
1274 .remove = asoc_simple_remove,
1275};
1276module_platform_driver(graph_card);
1277
1278MODULE_ALIAS("platform:asoc-audio-graph-card2");
1279MODULE_LICENSE("GPL v2");
1280MODULE_DESCRIPTION("ASoC Audio Graph Card2");
1281MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");