arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / sound / soc / generic / audio-graph-card.c
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // ASoC audio graph sound card support
4 //
5 // Copyright (C) 2016 Renesas Solutions Corp.
6 // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7 //
8 // based on ${LINUX}/sound/soc/generic/simple-card.c
9
10 #include <linux/clk.h>
11 #include <linux/device.h>
12 #include <linux/gpio.h>
13 #include <linux/gpio/consumer.h>
14 #include <linux/module.h>
15 #include <linux/of.h>
16 #include <linux/of_graph.h>
17 #include <linux/platform_device.h>
18 #include <linux/string.h>
19 #include <sound/graph_card.h>
20
21 #define DPCM_SELECTABLE 1
22
23 static int graph_outdrv_event(struct snd_soc_dapm_widget *w,
24                               struct snd_kcontrol *kcontrol,
25                               int event)
26 {
27         struct snd_soc_dapm_context *dapm = w->dapm;
28         struct simple_util_priv *priv = snd_soc_card_get_drvdata(dapm->card);
29
30         switch (event) {
31         case SND_SOC_DAPM_POST_PMU:
32                 gpiod_set_value_cansleep(priv->pa_gpio, 1);
33                 break;
34         case SND_SOC_DAPM_PRE_PMD:
35                 gpiod_set_value_cansleep(priv->pa_gpio, 0);
36                 break;
37         default:
38                 return -EINVAL;
39         }
40
41         return 0;
42 }
43
44 static const struct snd_soc_dapm_widget graph_dapm_widgets[] = {
45         SND_SOC_DAPM_OUT_DRV_E("Amplifier", SND_SOC_NOPM,
46                                0, 0, NULL, 0, graph_outdrv_event,
47                                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
48 };
49
50 static const struct snd_soc_ops graph_ops = {
51         .startup        = simple_util_startup,
52         .shutdown       = simple_util_shutdown,
53         .hw_params      = simple_util_hw_params,
54 };
55
56 static bool soc_component_is_pcm(struct snd_soc_dai_link_component *dlc)
57 {
58         struct snd_soc_dai *dai = snd_soc_find_dai_with_mutex(dlc);
59
60         if (dai && (dai->component->driver->pcm_construct ||
61                     (dai->driver->ops && dai->driver->ops->pcm_new)))
62                 return true;
63
64         return false;
65 }
66
67 static void graph_parse_convert(struct device *dev,
68                                 struct device_node *ep,
69                                 struct simple_util_data *adata)
70 {
71         struct device_node *top = dev->of_node;
72         struct device_node *port = of_get_parent(ep);
73         struct device_node *ports = of_get_parent(port);
74         struct device_node *node = of_graph_get_port_parent(ep);
75
76         simple_util_parse_convert(top,   NULL,   adata);
77         if (of_node_name_eq(ports, "ports"))
78                 simple_util_parse_convert(ports, NULL, adata);
79         simple_util_parse_convert(port,  NULL,   adata);
80         simple_util_parse_convert(ep,    NULL,   adata);
81
82         of_node_put(port);
83         of_node_put(ports);
84         of_node_put(node);
85 }
86
87 static void graph_parse_mclk_fs(struct device_node *top,
88                                 struct device_node *ep,
89                                 struct simple_dai_props *props)
90 {
91         struct device_node *port        = of_get_parent(ep);
92         struct device_node *ports       = of_get_parent(port);
93
94         of_property_read_u32(top,       "mclk-fs", &props->mclk_fs);
95         if (of_node_name_eq(ports, "ports"))
96                 of_property_read_u32(ports, "mclk-fs", &props->mclk_fs);
97         of_property_read_u32(port,      "mclk-fs", &props->mclk_fs);
98         of_property_read_u32(ep,        "mclk-fs", &props->mclk_fs);
99
100         of_node_put(port);
101         of_node_put(ports);
102 }
103
104 static int graph_parse_node(struct simple_util_priv *priv,
105                             struct device_node *ep,
106                             struct link_info *li,
107                             int *cpu)
108 {
109         struct device *dev = simple_priv_to_dev(priv);
110         struct device_node *top = dev->of_node;
111         struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
112         struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
113         struct snd_soc_dai_link_component *dlc;
114         struct simple_util_dai *dai;
115         int ret;
116
117         if (cpu) {
118                 dlc = snd_soc_link_to_cpu(dai_link, 0);
119                 dai = simple_props_to_dai_cpu(dai_props, 0);
120         } else {
121                 dlc = snd_soc_link_to_codec(dai_link, 0);
122                 dai = simple_props_to_dai_codec(dai_props, 0);
123         }
124
125         graph_parse_mclk_fs(top, ep, dai_props);
126
127         ret = graph_util_parse_dai(dev, ep, dlc, cpu);
128         if (ret < 0)
129                 return ret;
130
131         ret = simple_util_parse_tdm(ep, dai);
132         if (ret < 0)
133                 return ret;
134
135         ret = simple_util_parse_clk(dev, ep, dai, dlc);
136         if (ret < 0)
137                 return ret;
138
139         return 0;
140 }
141
142 static int graph_link_init(struct simple_util_priv *priv,
143                            struct device_node *cpu_ep,
144                            struct device_node *codec_ep,
145                            struct link_info *li,
146                            char *name)
147 {
148         struct device *dev = simple_priv_to_dev(priv);
149         struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
150         int ret;
151
152         ret = simple_util_parse_daifmt(dev, cpu_ep, codec_ep,
153                                        NULL, &dai_link->dai_fmt);
154         if (ret < 0)
155                 return ret;
156
157         dai_link->init          = simple_util_dai_init;
158         dai_link->ops           = &graph_ops;
159         if (priv->ops)
160                 dai_link->ops   = priv->ops;
161
162         return simple_util_set_dailink_name(dev, dai_link, name);
163 }
164
165 static int graph_dai_link_of_dpcm(struct simple_util_priv *priv,
166                                   struct device_node *cpu_ep,
167                                   struct device_node *codec_ep,
168                                   struct link_info *li)
169 {
170         struct device *dev = simple_priv_to_dev(priv);
171         struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
172         struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
173         struct device_node *top = dev->of_node;
174         struct device_node *ep = li->cpu ? cpu_ep : codec_ep;
175         char dai_name[64];
176         int ret;
177
178         dev_dbg(dev, "link_of DPCM (%pOF)\n", ep);
179
180         if (li->cpu) {
181                 struct snd_soc_card *card = simple_priv_to_card(priv);
182                 struct snd_soc_dai_link_component *cpus = snd_soc_link_to_cpu(dai_link, 0);
183                 struct snd_soc_dai_link_component *platforms = snd_soc_link_to_platform(dai_link, 0);
184                 int is_single_links = 0;
185
186                 /* Codec is dummy */
187
188                 /* FE settings */
189                 dai_link->dynamic               = 1;
190                 dai_link->dpcm_merged_format    = 1;
191
192                 ret = graph_parse_node(priv, cpu_ep, li, &is_single_links);
193                 if (ret)
194                         return ret;
195
196                 snprintf(dai_name, sizeof(dai_name),
197                          "fe.%pOFP.%s", cpus->of_node, cpus->dai_name);
198                 /*
199                  * In BE<->BE connections it is not required to create
200                  * PCM devices at CPU end of the dai link and thus 'no_pcm'
201                  * flag needs to be set. It is useful when there are many
202                  * BE components and some of these have to be connected to
203                  * form a valid audio path.
204                  *
205                  * For example: FE <-> BE1 <-> BE2 <-> ... <-> BEn where
206                  * there are 'n' BE components in the path.
207                  */
208                 if (card->component_chaining && !soc_component_is_pcm(cpus)) {
209                         dai_link->no_pcm = 1;
210                         dai_link->be_hw_params_fixup = simple_util_be_hw_params_fixup;
211                 }
212
213                 simple_util_canonicalize_cpu(cpus, is_single_links);
214                 simple_util_canonicalize_platform(platforms, cpus);
215         } else {
216                 struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, 0);
217                 struct snd_soc_dai_link_component *codecs = snd_soc_link_to_codec(dai_link, 0);
218                 struct device_node *port;
219                 struct device_node *ports;
220
221                 /* CPU is dummy */
222
223                 /* BE settings */
224                 dai_link->no_pcm                = 1;
225                 dai_link->be_hw_params_fixup    = simple_util_be_hw_params_fixup;
226
227                 ret = graph_parse_node(priv, codec_ep, li, NULL);
228                 if (ret < 0)
229                         return ret;
230
231                 snprintf(dai_name, sizeof(dai_name),
232                          "be.%pOFP.%s", codecs->of_node, codecs->dai_name);
233
234                 /* check "prefix" from top node */
235                 port = of_get_parent(ep);
236                 ports = of_get_parent(port);
237                 snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
238                                               "prefix");
239                 if (of_node_name_eq(ports, "ports"))
240                         snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node, "prefix");
241                 snd_soc_of_parse_node_prefix(port, cconf, codecs->of_node,
242                                              "prefix");
243
244                 of_node_put(ports);
245                 of_node_put(port);
246         }
247
248         graph_parse_convert(dev, ep, &dai_props->adata);
249
250         snd_soc_dai_link_set_capabilities(dai_link);
251
252         ret = graph_link_init(priv, cpu_ep, codec_ep, li, dai_name);
253
254         li->link++;
255
256         return ret;
257 }
258
259 static int graph_dai_link_of(struct simple_util_priv *priv,
260                              struct device_node *cpu_ep,
261                              struct device_node *codec_ep,
262                              struct link_info *li)
263 {
264         struct device *dev = simple_priv_to_dev(priv);
265         struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
266         struct snd_soc_dai_link_component *cpus = snd_soc_link_to_cpu(dai_link, 0);
267         struct snd_soc_dai_link_component *codecs = snd_soc_link_to_codec(dai_link, 0);
268         struct snd_soc_dai_link_component *platforms = snd_soc_link_to_platform(dai_link, 0);
269         char dai_name[64];
270         int ret, is_single_links = 0;
271
272         dev_dbg(dev, "link_of (%pOF)\n", cpu_ep);
273
274         ret = graph_parse_node(priv, cpu_ep, li, &is_single_links);
275         if (ret < 0)
276                 return ret;
277
278         ret = graph_parse_node(priv, codec_ep, li, NULL);
279         if (ret < 0)
280                 return ret;
281
282         snprintf(dai_name, sizeof(dai_name),
283                  "%s-%s", cpus->dai_name, codecs->dai_name);
284
285         simple_util_canonicalize_cpu(cpus, is_single_links);
286         simple_util_canonicalize_platform(platforms, cpus);
287
288         ret = graph_link_init(priv, cpu_ep, codec_ep, li, dai_name);
289         if (ret < 0)
290                 return ret;
291
292         li->link++;
293
294         return 0;
295 }
296
297 static inline bool parse_as_dpcm_link(struct simple_util_priv *priv,
298                                       struct device_node *codec_port,
299                                       struct simple_util_data *adata)
300 {
301         if (priv->force_dpcm)
302                 return true;
303
304         if (!priv->dpcm_selectable)
305                 return false;
306
307         /*
308          * It is DPCM
309          * if Codec port has many endpoints,
310          * or has convert-xxx property
311          */
312         if ((of_get_child_count(codec_port) > 1) ||
313             simple_util_is_convert_required(adata))
314                 return true;
315
316         return false;
317 }
318
319 static int __graph_for_each_link(struct simple_util_priv *priv,
320                         struct link_info *li,
321                         int (*func_noml)(struct simple_util_priv *priv,
322                                          struct device_node *cpu_ep,
323                                          struct device_node *codec_ep,
324                                          struct link_info *li),
325                         int (*func_dpcm)(struct simple_util_priv *priv,
326                                          struct device_node *cpu_ep,
327                                          struct device_node *codec_ep,
328                                          struct link_info *li))
329 {
330         struct of_phandle_iterator it;
331         struct device *dev = simple_priv_to_dev(priv);
332         struct device_node *node = dev->of_node;
333         struct device_node *cpu_port;
334         struct device_node *cpu_ep;
335         struct device_node *codec_ep;
336         struct device_node *codec_port;
337         struct device_node *codec_port_old = NULL;
338         struct simple_util_data adata;
339         int rc, ret = 0;
340
341         /* loop for all listed CPU port */
342         of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
343                 cpu_port = it.node;
344                 cpu_ep   = NULL;
345
346                 /* loop for all CPU endpoint */
347                 while (1) {
348                         cpu_ep = of_get_next_child(cpu_port, cpu_ep);
349                         if (!cpu_ep)
350                                 break;
351
352                         /* get codec */
353                         codec_ep = of_graph_get_remote_endpoint(cpu_ep);
354                         codec_port = of_get_parent(codec_ep);
355
356                         /* get convert-xxx property */
357                         memset(&adata, 0, sizeof(adata));
358                         graph_parse_convert(dev, codec_ep, &adata);
359                         graph_parse_convert(dev, cpu_ep,   &adata);
360
361                         /* check if link requires DPCM parsing */
362                         if (parse_as_dpcm_link(priv, codec_port, &adata)) {
363                                 /*
364                                  * Codec endpoint can be NULL for pluggable audio HW.
365                                  * Platform DT can populate the Codec endpoint depending on the
366                                  * plugged HW.
367                                  */
368                                 /* Do it all CPU endpoint, and 1st Codec endpoint */
369                                 if (li->cpu ||
370                                     ((codec_port_old != codec_port) && codec_ep))
371                                         ret = func_dpcm(priv, cpu_ep, codec_ep, li);
372                         /* else normal sound */
373                         } else {
374                                 if (li->cpu)
375                                         ret = func_noml(priv, cpu_ep, codec_ep, li);
376                         }
377
378                         of_node_put(codec_ep);
379                         of_node_put(codec_port);
380
381                         if (ret < 0) {
382                                 of_node_put(cpu_ep);
383                                 return ret;
384                         }
385
386                         codec_port_old = codec_port;
387                 }
388         }
389
390         return 0;
391 }
392
393 static int graph_for_each_link(struct simple_util_priv *priv,
394                                struct link_info *li,
395                                int (*func_noml)(struct simple_util_priv *priv,
396                                                 struct device_node *cpu_ep,
397                                                 struct device_node *codec_ep,
398                                                 struct link_info *li),
399                                int (*func_dpcm)(struct simple_util_priv *priv,
400                                                 struct device_node *cpu_ep,
401                                                 struct device_node *codec_ep,
402                                                 struct link_info *li))
403 {
404         int ret;
405         /*
406          * Detect all CPU first, and Detect all Codec 2nd.
407          *
408          * In Normal sound case, all DAIs are detected
409          * as "CPU-Codec".
410          *
411          * In DPCM sound case,
412          * all CPUs   are detected as "CPU-dummy", and
413          * all Codecs are detected as "dummy-Codec".
414          * To avoid random sub-device numbering,
415          * detect "dummy-Codec" in last;
416          */
417         for (li->cpu = 1; li->cpu >= 0; li->cpu--) {
418                 ret = __graph_for_each_link(priv, li, func_noml, func_dpcm);
419                 if (ret < 0)
420                         break;
421         }
422
423         return ret;
424 }
425
426 static int graph_count_noml(struct simple_util_priv *priv,
427                             struct device_node *cpu_ep,
428                             struct device_node *codec_ep,
429                             struct link_info *li)
430 {
431         struct device *dev = simple_priv_to_dev(priv);
432
433         if (li->link >= SNDRV_MAX_LINKS) {
434                 dev_err(dev, "too many links\n");
435                 return -EINVAL;
436         }
437
438         /*
439          * DON'T REMOVE platforms
440          * see
441          *      simple-card.c :: simple_count_noml()
442          */
443         li->num[li->link].cpus          = 1;
444         li->num[li->link].platforms     = 1;
445
446         li->num[li->link].codecs        = 1;
447
448         li->link += 1; /* 1xCPU-Codec */
449
450         dev_dbg(dev, "Count As Normal\n");
451
452         return 0;
453 }
454
455 static int graph_count_dpcm(struct simple_util_priv *priv,
456                             struct device_node *cpu_ep,
457                             struct device_node *codec_ep,
458                             struct link_info *li)
459 {
460         struct device *dev = simple_priv_to_dev(priv);
461
462         if (li->link >= SNDRV_MAX_LINKS) {
463                 dev_err(dev, "too many links\n");
464                 return -EINVAL;
465         }
466
467         if (li->cpu) {
468                 /*
469                  * DON'T REMOVE platforms
470                  * see
471                  *      simple-card.c :: simple_count_noml()
472                  */
473                 li->num[li->link].cpus          = 1;
474                 li->num[li->link].platforms     = 1;
475
476                 li->link++; /* 1xCPU-dummy */
477         } else {
478                 li->num[li->link].codecs        = 1;
479
480                 li->link++; /* 1xdummy-Codec */
481         }
482
483         dev_dbg(dev, "Count As DPCM\n");
484
485         return 0;
486 }
487
488 static int graph_get_dais_count(struct simple_util_priv *priv,
489                                 struct link_info *li)
490 {
491         /*
492          * link_num :   number of links.
493          *              CPU-Codec / CPU-dummy / dummy-Codec
494          * dais_num :   number of DAIs
495          * ccnf_num :   number of codec_conf
496          *              same number for "dummy-Codec"
497          *
498          * ex1)
499          * CPU0 --- Codec0      link : 5
500          * CPU1 --- Codec1      dais : 7
501          * CPU2 -/              ccnf : 1
502          * CPU3 --- Codec2
503          *
504          *      => 5 links = 2xCPU-Codec + 2xCPU-dummy + 1xdummy-Codec
505          *      => 7 DAIs  = 4xCPU + 3xCodec
506          *      => 1 ccnf  = 1xdummy-Codec
507          *
508          * ex2)
509          * CPU0 --- Codec0      link : 5
510          * CPU1 --- Codec1      dais : 6
511          * CPU2 -/              ccnf : 1
512          * CPU3 -/
513          *
514          *      => 5 links = 1xCPU-Codec + 3xCPU-dummy + 1xdummy-Codec
515          *      => 6 DAIs  = 4xCPU + 2xCodec
516          *      => 1 ccnf  = 1xdummy-Codec
517          *
518          * ex3)
519          * CPU0 --- Codec0      link : 6
520          * CPU1 -/              dais : 6
521          * CPU2 --- Codec1      ccnf : 2
522          * CPU3 -/
523          *
524          *      => 6 links = 0xCPU-Codec + 4xCPU-dummy + 2xdummy-Codec
525          *      => 6 DAIs  = 4xCPU + 2xCodec
526          *      => 2 ccnf  = 2xdummy-Codec
527          *
528          * ex4)
529          * CPU0 --- Codec0 (convert-rate)       link : 3
530          * CPU1 --- Codec1                      dais : 4
531          *                                      ccnf : 1
532          *
533          *      => 3 links = 1xCPU-Codec + 1xCPU-dummy + 1xdummy-Codec
534          *      => 4 DAIs  = 2xCPU + 2xCodec
535          *      => 1 ccnf  = 1xdummy-Codec
536          */
537         return graph_for_each_link(priv, li,
538                                    graph_count_noml,
539                                    graph_count_dpcm);
540 }
541
542 int audio_graph_parse_of(struct simple_util_priv *priv, struct device *dev)
543 {
544         struct snd_soc_card *card = simple_priv_to_card(priv);
545         struct link_info *li;
546         int ret;
547
548         li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
549         if (!li)
550                 return -ENOMEM;
551
552         card->owner = THIS_MODULE;
553         card->dev = dev;
554
555         ret = graph_get_dais_count(priv, li);
556         if (ret < 0)
557                 return ret;
558
559         if (!li->link)
560                 return -EINVAL;
561
562         ret = simple_util_init_priv(priv, li);
563         if (ret < 0)
564                 return ret;
565
566         priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW);
567         if (IS_ERR(priv->pa_gpio)) {
568                 ret = PTR_ERR(priv->pa_gpio);
569                 dev_err(dev, "failed to get amplifier gpio: %d\n", ret);
570                 return ret;
571         }
572
573         ret = simple_util_parse_widgets(card, NULL);
574         if (ret < 0)
575                 return ret;
576
577         ret = simple_util_parse_routing(card, NULL);
578         if (ret < 0)
579                 return ret;
580
581         memset(li, 0, sizeof(*li));
582         ret = graph_for_each_link(priv, li,
583                                   graph_dai_link_of,
584                                   graph_dai_link_of_dpcm);
585         if (ret < 0)
586                 goto err;
587
588         ret = simple_util_parse_card_name(card, NULL);
589         if (ret < 0)
590                 goto err;
591
592         snd_soc_card_set_drvdata(card, priv);
593
594         simple_util_debug_info(priv);
595
596         ret = devm_snd_soc_register_card(dev, card);
597         if (ret < 0)
598                 goto err;
599
600         devm_kfree(dev, li);
601         return 0;
602
603 err:
604         simple_util_clean_reference(card);
605
606         return dev_err_probe(dev, ret, "parse error\n");
607 }
608 EXPORT_SYMBOL_GPL(audio_graph_parse_of);
609
610 static int graph_probe(struct platform_device *pdev)
611 {
612         struct simple_util_priv *priv;
613         struct device *dev = &pdev->dev;
614         struct snd_soc_card *card;
615
616         /* Allocate the private data and the DAI link array */
617         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
618         if (!priv)
619                 return -ENOMEM;
620
621         card = simple_priv_to_card(priv);
622         card->dapm_widgets      = graph_dapm_widgets;
623         card->num_dapm_widgets  = ARRAY_SIZE(graph_dapm_widgets);
624         card->probe             = graph_util_card_probe;
625
626         if (of_device_get_match_data(dev))
627                 priv->dpcm_selectable = 1;
628
629         return audio_graph_parse_of(priv, dev);
630 }
631
632 static const struct of_device_id graph_of_match[] = {
633         { .compatible = "audio-graph-card", },
634         { .compatible = "audio-graph-scu-card",
635           .data = (void *)DPCM_SELECTABLE },
636         {},
637 };
638 MODULE_DEVICE_TABLE(of, graph_of_match);
639
640 static struct platform_driver graph_card = {
641         .driver = {
642                 .name = "asoc-audio-graph-card",
643                 .pm = &snd_soc_pm_ops,
644                 .of_match_table = graph_of_match,
645         },
646         .probe = graph_probe,
647         .remove_new = simple_util_remove,
648 };
649 module_platform_driver(graph_card);
650
651 MODULE_ALIAS("platform:asoc-audio-graph-card");
652 MODULE_LICENSE("GPL v2");
653 MODULE_DESCRIPTION("ASoC Audio Graph Sound Card");
654 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");