]> Git Repo - linux.git/blob - sound/soc/generic/simple-card.c
Merge tag 'amd-drm-next-6.5-2023-06-09' of https://gitlab.freedesktop.org/agd5f/linux...
[linux.git] / sound / soc / generic / simple-card.c
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // ASoC simple sound card support
4 //
5 // Copyright (C) 2012 Renesas Solutions Corp.
6 // Kuninori Morimoto <[email protected]>
7
8 #include <linux/clk.h>
9 #include <linux/device.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/of_device.h>
13 #include <linux/platform_device.h>
14 #include <linux/string.h>
15 #include <sound/simple_card.h>
16 #include <sound/soc-dai.h>
17 #include <sound/soc.h>
18
19 #define DPCM_SELECTABLE 1
20
21 #define DAI     "sound-dai"
22 #define CELL    "#sound-dai-cells"
23 #define PREFIX  "simple-audio-card,"
24
25 static const struct snd_soc_ops simple_ops = {
26         .startup        = asoc_simple_startup,
27         .shutdown       = asoc_simple_shutdown,
28         .hw_params      = asoc_simple_hw_params,
29 };
30
31 static int asoc_simple_parse_platform(struct device_node *node,
32                                       struct snd_soc_dai_link_component *dlc)
33 {
34         struct of_phandle_args args;
35         int ret;
36
37         if (!node)
38                 return 0;
39
40         /*
41          * Get node via "sound-dai = <&phandle port>"
42          * it will be used as xxx_of_node on soc_bind_dai_link()
43          */
44         ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args);
45         if (ret)
46                 return ret;
47
48         /* dai_name is not required and may not exist for plat component */
49
50         dlc->of_node = args.np;
51
52         return 0;
53 }
54
55 static int asoc_simple_parse_dai(struct device_node *node,
56                                  struct snd_soc_dai_link_component *dlc,
57                                  int *is_single_link)
58 {
59         struct of_phandle_args args;
60         int ret;
61
62         if (!node)
63                 return 0;
64
65         /*
66          * Get node via "sound-dai = <&phandle port>"
67          * it will be used as xxx_of_node on soc_bind_dai_link()
68          */
69         ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args);
70         if (ret)
71                 return ret;
72
73         /*
74          * FIXME
75          *
76          * Here, dlc->dai_name is pointer to CPU/Codec DAI name.
77          * If user unbinded CPU or Codec driver, but not for Sound Card,
78          * dlc->dai_name is keeping unbinded CPU or Codec
79          * driver's pointer.
80          *
81          * If user re-bind CPU or Codec driver again, ALSA SoC will try
82          * to rebind Card via snd_soc_try_rebind_card(), but because of
83          * above reason, it might can't bind Sound Card.
84          * Because Sound Card is pointing to released dai_name pointer.
85          *
86          * To avoid this rebind Card issue,
87          * 1) It needs to alloc memory to keep dai_name eventhough
88          *    CPU or Codec driver was unbinded, or
89          * 2) user need to rebind Sound Card everytime
90          *    if he unbinded CPU or Codec.
91          */
92         ret = snd_soc_of_get_dai_name(node, &dlc->dai_name);
93         if (ret < 0)
94                 return ret;
95
96         dlc->of_node = args.np;
97
98         if (is_single_link)
99                 *is_single_link = !args.args_count;
100
101         return 0;
102 }
103
104 static void simple_parse_convert(struct device *dev,
105                                  struct device_node *np,
106                                  struct asoc_simple_data *adata)
107 {
108         struct device_node *top = dev->of_node;
109         struct device_node *node = of_get_parent(np);
110
111         asoc_simple_parse_convert(top,  PREFIX, adata);
112         asoc_simple_parse_convert(node, PREFIX, adata);
113         asoc_simple_parse_convert(node, NULL,   adata);
114         asoc_simple_parse_convert(np,   NULL,   adata);
115
116         of_node_put(node);
117 }
118
119 static void simple_parse_mclk_fs(struct device_node *top,
120                                  struct device_node *np,
121                                  struct simple_dai_props *props,
122                                  char *prefix)
123 {
124         struct device_node *node = of_get_parent(np);
125         char prop[128];
126
127         snprintf(prop, sizeof(prop), "%smclk-fs", PREFIX);
128         of_property_read_u32(top,       prop, &props->mclk_fs);
129
130         snprintf(prop, sizeof(prop), "%smclk-fs", prefix);
131         of_property_read_u32(node,      prop, &props->mclk_fs);
132         of_property_read_u32(np,        prop, &props->mclk_fs);
133
134         of_node_put(node);
135 }
136
137 static int simple_parse_node(struct asoc_simple_priv *priv,
138                              struct device_node *np,
139                              struct link_info *li,
140                              char *prefix,
141                              int *cpu)
142 {
143         struct device *dev = simple_priv_to_dev(priv);
144         struct device_node *top = dev->of_node;
145         struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
146         struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
147         struct snd_soc_dai_link_component *dlc;
148         struct asoc_simple_dai *dai;
149         int ret;
150
151         if (cpu) {
152                 dlc = asoc_link_to_cpu(dai_link, 0);
153                 dai = simple_props_to_dai_cpu(dai_props, 0);
154         } else {
155                 dlc = asoc_link_to_codec(dai_link, 0);
156                 dai = simple_props_to_dai_codec(dai_props, 0);
157         }
158
159         simple_parse_mclk_fs(top, np, dai_props, prefix);
160
161         ret = asoc_simple_parse_dai(np, dlc, cpu);
162         if (ret)
163                 return ret;
164
165         ret = asoc_simple_parse_clk(dev, np, dai, dlc);
166         if (ret)
167                 return ret;
168
169         ret = asoc_simple_parse_tdm(np, dai);
170         if (ret)
171                 return ret;
172
173         return 0;
174 }
175
176 static int simple_link_init(struct asoc_simple_priv *priv,
177                             struct device_node *node,
178                             struct device_node *codec,
179                             struct link_info *li,
180                             char *prefix, char *name)
181 {
182         struct device *dev = simple_priv_to_dev(priv);
183         struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
184         int ret;
185
186         ret = asoc_simple_parse_daifmt(dev, node, codec,
187                                        prefix, &dai_link->dai_fmt);
188         if (ret < 0)
189                 return 0;
190
191         dai_link->init                  = asoc_simple_dai_init;
192         dai_link->ops                   = &simple_ops;
193
194         return asoc_simple_set_dailink_name(dev, dai_link, name);
195 }
196
197 static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
198                                    struct device_node *np,
199                                    struct device_node *codec,
200                                    struct link_info *li,
201                                    bool is_top)
202 {
203         struct device *dev = simple_priv_to_dev(priv);
204         struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
205         struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
206         struct device_node *top = dev->of_node;
207         struct device_node *node = of_get_parent(np);
208         char *prefix = "";
209         char dai_name[64];
210         int ret;
211
212         dev_dbg(dev, "link_of DPCM (%pOF)\n", np);
213
214         /* For single DAI link & old style of DT node */
215         if (is_top)
216                 prefix = PREFIX;
217
218         if (li->cpu) {
219                 struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0);
220                 struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0);
221                 int is_single_links = 0;
222
223                 /* Codec is dummy */
224
225                 /* FE settings */
226                 dai_link->dynamic               = 1;
227                 dai_link->dpcm_merged_format    = 1;
228
229                 ret = simple_parse_node(priv, np, li, prefix, &is_single_links);
230                 if (ret < 0)
231                         goto out_put_node;
232
233                 snprintf(dai_name, sizeof(dai_name), "fe.%s", cpus->dai_name);
234
235                 asoc_simple_canonicalize_cpu(cpus, is_single_links);
236                 asoc_simple_canonicalize_platform(platforms, cpus);
237         } else {
238                 struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0);
239                 struct snd_soc_codec_conf *cconf;
240
241                 /* CPU is dummy */
242
243                 /* BE settings */
244                 dai_link->no_pcm                = 1;
245                 dai_link->be_hw_params_fixup    = asoc_simple_be_hw_params_fixup;
246
247                 cconf   = simple_props_to_codec_conf(dai_props, 0);
248
249                 ret = simple_parse_node(priv, np, li, prefix, NULL);
250                 if (ret < 0)
251                         goto out_put_node;
252
253                 snprintf(dai_name, sizeof(dai_name), "be.%s", codecs->dai_name);
254
255                 /* check "prefix" from top node */
256                 snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
257                                               PREFIX "prefix");
258                 snd_soc_of_parse_node_prefix(node, cconf, codecs->of_node,
259                                              "prefix");
260                 snd_soc_of_parse_node_prefix(np, cconf, codecs->of_node,
261                                              "prefix");
262         }
263
264         simple_parse_convert(dev, np, &dai_props->adata);
265
266         snd_soc_dai_link_set_capabilities(dai_link);
267
268         ret = simple_link_init(priv, node, codec, li, prefix, dai_name);
269
270 out_put_node:
271         li->link++;
272
273         of_node_put(node);
274         return ret;
275 }
276
277 static int simple_dai_link_of(struct asoc_simple_priv *priv,
278                               struct device_node *np,
279                               struct device_node *codec,
280                               struct link_info *li,
281                               bool is_top)
282 {
283         struct device *dev = simple_priv_to_dev(priv);
284         struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
285         struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0);
286         struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0);
287         struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0);
288         struct device_node *cpu = NULL;
289         struct device_node *node = NULL;
290         struct device_node *plat = NULL;
291         char dai_name[64];
292         char prop[128];
293         char *prefix = "";
294         int ret, single_cpu = 0;
295
296         cpu  = np;
297         node = of_get_parent(np);
298
299         dev_dbg(dev, "link_of (%pOF)\n", node);
300
301         /* For single DAI link & old style of DT node */
302         if (is_top)
303                 prefix = PREFIX;
304
305         snprintf(prop, sizeof(prop), "%splat", prefix);
306         plat = of_get_child_by_name(node, prop);
307
308         ret = simple_parse_node(priv, cpu, li, prefix, &single_cpu);
309         if (ret < 0)
310                 goto dai_link_of_err;
311
312         ret = simple_parse_node(priv, codec, li, prefix, NULL);
313         if (ret < 0)
314                 goto dai_link_of_err;
315
316         ret = asoc_simple_parse_platform(plat, platforms);
317         if (ret < 0)
318                 goto dai_link_of_err;
319
320         snprintf(dai_name, sizeof(dai_name),
321                  "%s-%s", cpus->dai_name, codecs->dai_name);
322
323         asoc_simple_canonicalize_cpu(cpus, single_cpu);
324         asoc_simple_canonicalize_platform(platforms, cpus);
325
326         ret = simple_link_init(priv, node, codec, li, prefix, dai_name);
327
328 dai_link_of_err:
329         of_node_put(plat);
330         of_node_put(node);
331
332         li->link++;
333
334         return ret;
335 }
336
337 static int __simple_for_each_link(struct asoc_simple_priv *priv,
338                         struct link_info *li,
339                         int (*func_noml)(struct asoc_simple_priv *priv,
340                                          struct device_node *np,
341                                          struct device_node *codec,
342                                          struct link_info *li, bool is_top),
343                         int (*func_dpcm)(struct asoc_simple_priv *priv,
344                                          struct device_node *np,
345                                          struct device_node *codec,
346                                          struct link_info *li, bool is_top))
347 {
348         struct device *dev = simple_priv_to_dev(priv);
349         struct device_node *top = dev->of_node;
350         struct device_node *node;
351         uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev);
352         bool is_top = 0;
353         int ret = 0;
354
355         /* Check if it has dai-link */
356         node = of_get_child_by_name(top, PREFIX "dai-link");
357         if (!node) {
358                 node = of_node_get(top);
359                 is_top = 1;
360         }
361
362         /* loop for all dai-link */
363         do {
364                 struct asoc_simple_data adata;
365                 struct device_node *codec;
366                 struct device_node *plat;
367                 struct device_node *np;
368                 int num = of_get_child_count(node);
369
370                 /* get codec */
371                 codec = of_get_child_by_name(node, is_top ?
372                                              PREFIX "codec" : "codec");
373                 if (!codec) {
374                         ret = -ENODEV;
375                         goto error;
376                 }
377                 /* get platform */
378                 plat = of_get_child_by_name(node, is_top ?
379                                             PREFIX "plat" : "plat");
380
381                 /* get convert-xxx property */
382                 memset(&adata, 0, sizeof(adata));
383                 for_each_child_of_node(node, np)
384                         simple_parse_convert(dev, np, &adata);
385
386                 /* loop for all CPU/Codec node */
387                 for_each_child_of_node(node, np) {
388                         if (plat == np)
389                                 continue;
390                         /*
391                          * It is DPCM
392                          * if it has many CPUs,
393                          * or has convert-xxx property
394                          */
395                         if (dpcm_selectable &&
396                             (num > 2 || asoc_simple_is_convert_required(&adata))) {
397                                 /*
398                                  * np
399                                  *       |1(CPU)|0(Codec)  li->cpu
400                                  * CPU   |Pass  |return
401                                  * Codec |return|Pass
402                                  */
403                                 if (li->cpu != (np == codec))
404                                         ret = func_dpcm(priv, np, codec, li, is_top);
405                         /* else normal sound */
406                         } else {
407                                 /*
408                                  * np
409                                  *       |1(CPU)|0(Codec)  li->cpu
410                                  * CPU   |Pass  |return
411                                  * Codec |return|return
412                                  */
413                                 if (li->cpu && (np != codec))
414                                         ret = func_noml(priv, np, codec, li, is_top);
415                         }
416
417                         if (ret < 0) {
418                                 of_node_put(codec);
419                                 of_node_put(np);
420                                 goto error;
421                         }
422                 }
423
424                 of_node_put(codec);
425                 of_node_put(plat);
426                 node = of_get_next_child(top, node);
427         } while (!is_top && node);
428
429  error:
430         of_node_put(node);
431         return ret;
432 }
433
434 static int simple_for_each_link(struct asoc_simple_priv *priv,
435                                 struct link_info *li,
436                                 int (*func_noml)(struct asoc_simple_priv *priv,
437                                                  struct device_node *np,
438                                                  struct device_node *codec,
439                                                  struct link_info *li, bool is_top),
440                                 int (*func_dpcm)(struct asoc_simple_priv *priv,
441                                                  struct device_node *np,
442                                                  struct device_node *codec,
443                                                  struct link_info *li, bool is_top))
444 {
445         int ret;
446         /*
447          * Detect all CPU first, and Detect all Codec 2nd.
448          *
449          * In Normal sound case, all DAIs are detected
450          * as "CPU-Codec".
451          *
452          * In DPCM sound case,
453          * all CPUs   are detected as "CPU-dummy", and
454          * all Codecs are detected as "dummy-Codec".
455          * To avoid random sub-device numbering,
456          * detect "dummy-Codec" in last;
457          */
458         for (li->cpu = 1; li->cpu >= 0; li->cpu--) {
459                 ret = __simple_for_each_link(priv, li, func_noml, func_dpcm);
460                 if (ret < 0)
461                         break;
462         }
463
464         return ret;
465 }
466
467 static int simple_parse_of(struct asoc_simple_priv *priv, struct link_info *li)
468 {
469         struct snd_soc_card *card = simple_priv_to_card(priv);
470         int ret;
471
472         ret = asoc_simple_parse_widgets(card, PREFIX);
473         if (ret < 0)
474                 return ret;
475
476         ret = asoc_simple_parse_routing(card, PREFIX);
477         if (ret < 0)
478                 return ret;
479
480         ret = asoc_simple_parse_pin_switches(card, PREFIX);
481         if (ret < 0)
482                 return ret;
483
484         /* Single/Muti DAI link(s) & New style of DT node */
485         memset(li, 0, sizeof(*li));
486         ret = simple_for_each_link(priv, li,
487                                    simple_dai_link_of,
488                                    simple_dai_link_of_dpcm);
489         if (ret < 0)
490                 return ret;
491
492         ret = asoc_simple_parse_card_name(card, PREFIX);
493         if (ret < 0)
494                 return ret;
495
496         ret = snd_soc_of_parse_aux_devs(card, PREFIX "aux-devs");
497
498         return ret;
499 }
500
501 static int simple_count_noml(struct asoc_simple_priv *priv,
502                              struct device_node *np,
503                              struct device_node *codec,
504                              struct link_info *li, bool is_top)
505 {
506         if (li->link >= SNDRV_MAX_LINKS) {
507                 struct device *dev = simple_priv_to_dev(priv);
508
509                 dev_err(dev, "too many links\n");
510                 return -EINVAL;
511         }
512
513         /*
514          * DON'T REMOVE platforms
515          *
516          * Some CPU might be using soc-generic-dmaengine-pcm. This means CPU and Platform
517          * are different Component, but are sharing same component->dev.
518          * Simple Card had been supported it without special Platform selection.
519          * We need platforms here.
520          *
521          * In case of no Platform, it will be Platform == CPU, but Platform will be
522          * ignored by snd_soc_rtd_add_component().
523          *
524          * see
525          *      simple-card-utils.c :: asoc_simple_canonicalize_platform()
526          */
527         li->num[li->link].cpus          = 1;
528         li->num[li->link].platforms     = 1;
529
530         li->num[li->link].codecs        = 1;
531
532         li->link += 1;
533
534         return 0;
535 }
536
537 static int simple_count_dpcm(struct asoc_simple_priv *priv,
538                              struct device_node *np,
539                              struct device_node *codec,
540                              struct link_info *li, bool is_top)
541 {
542         if (li->link >= SNDRV_MAX_LINKS) {
543                 struct device *dev = simple_priv_to_dev(priv);
544
545                 dev_err(dev, "too many links\n");
546                 return -EINVAL;
547         }
548
549         if (li->cpu) {
550                 /*
551                  * DON'T REMOVE platforms
552                  * see
553                  *      simple_count_noml()
554                  */
555                 li->num[li->link].cpus          = 1;
556                 li->num[li->link].platforms     = 1;
557
558                 li->link++; /* CPU-dummy */
559         } else {
560                 li->num[li->link].codecs        = 1;
561
562                 li->link++; /* dummy-Codec */
563         }
564
565         return 0;
566 }
567
568 static int simple_get_dais_count(struct asoc_simple_priv *priv,
569                                  struct link_info *li)
570 {
571         struct device *dev = simple_priv_to_dev(priv);
572         struct device_node *top = dev->of_node;
573
574         /*
575          * link_num :   number of links.
576          *              CPU-Codec / CPU-dummy / dummy-Codec
577          * dais_num :   number of DAIs
578          * ccnf_num :   number of codec_conf
579          *              same number for "dummy-Codec"
580          *
581          * ex1)
582          * CPU0 --- Codec0      link : 5
583          * CPU1 --- Codec1      dais : 7
584          * CPU2 -/              ccnf : 1
585          * CPU3 --- Codec2
586          *
587          *      => 5 links = 2xCPU-Codec + 2xCPU-dummy + 1xdummy-Codec
588          *      => 7 DAIs  = 4xCPU + 3xCodec
589          *      => 1 ccnf  = 1xdummy-Codec
590          *
591          * ex2)
592          * CPU0 --- Codec0      link : 5
593          * CPU1 --- Codec1      dais : 6
594          * CPU2 -/              ccnf : 1
595          * CPU3 -/
596          *
597          *      => 5 links = 1xCPU-Codec + 3xCPU-dummy + 1xdummy-Codec
598          *      => 6 DAIs  = 4xCPU + 2xCodec
599          *      => 1 ccnf  = 1xdummy-Codec
600          *
601          * ex3)
602          * CPU0 --- Codec0      link : 6
603          * CPU1 -/              dais : 6
604          * CPU2 --- Codec1      ccnf : 2
605          * CPU3 -/
606          *
607          *      => 6 links = 0xCPU-Codec + 4xCPU-dummy + 2xdummy-Codec
608          *      => 6 DAIs  = 4xCPU + 2xCodec
609          *      => 2 ccnf  = 2xdummy-Codec
610          *
611          * ex4)
612          * CPU0 --- Codec0 (convert-rate)       link : 3
613          * CPU1 --- Codec1                      dais : 4
614          *                                      ccnf : 1
615          *
616          *      => 3 links = 1xCPU-Codec + 1xCPU-dummy + 1xdummy-Codec
617          *      => 4 DAIs  = 2xCPU + 2xCodec
618          *      => 1 ccnf  = 1xdummy-Codec
619          */
620         if (!top) {
621                 li->num[0].cpus         = 1;
622                 li->num[0].codecs       = 1;
623                 li->num[0].platforms    = 1;
624
625                 li->link = 1;
626                 return 0;
627         }
628
629         return simple_for_each_link(priv, li,
630                                     simple_count_noml,
631                                     simple_count_dpcm);
632 }
633
634 static int simple_soc_probe(struct snd_soc_card *card)
635 {
636         struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card);
637         int ret;
638
639         ret = asoc_simple_init_hp(card, &priv->hp_jack, PREFIX);
640         if (ret < 0)
641                 return ret;
642
643         ret = asoc_simple_init_mic(card, &priv->mic_jack, PREFIX);
644         if (ret < 0)
645                 return ret;
646
647         ret = asoc_simple_init_aux_jacks(priv, PREFIX);
648         if (ret < 0)
649                 return ret;
650
651         return 0;
652 }
653
654 static int asoc_simple_probe(struct platform_device *pdev)
655 {
656         struct asoc_simple_priv *priv;
657         struct device *dev = &pdev->dev;
658         struct device_node *np = dev->of_node;
659         struct snd_soc_card *card;
660         struct link_info *li;
661         int ret;
662
663         /* Allocate the private data and the DAI link array */
664         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
665         if (!priv)
666                 return -ENOMEM;
667
668         card = simple_priv_to_card(priv);
669         card->owner             = THIS_MODULE;
670         card->dev               = dev;
671         card->probe             = simple_soc_probe;
672         card->driver_name       = "simple-card";
673
674         li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
675         if (!li)
676                 return -ENOMEM;
677
678         ret = simple_get_dais_count(priv, li);
679         if (ret < 0)
680                 return ret;
681
682         if (!li->link)
683                 return -EINVAL;
684
685         ret = asoc_simple_init_priv(priv, li);
686         if (ret < 0)
687                 return ret;
688
689         if (np && of_device_is_available(np)) {
690
691                 ret = simple_parse_of(priv, li);
692                 if (ret < 0) {
693                         dev_err_probe(dev, ret, "parse error\n");
694                         goto err;
695                 }
696
697         } else {
698                 struct asoc_simple_card_info *cinfo;
699                 struct snd_soc_dai_link_component *cpus;
700                 struct snd_soc_dai_link_component *codecs;
701                 struct snd_soc_dai_link_component *platform;
702                 struct snd_soc_dai_link *dai_link = priv->dai_link;
703                 struct simple_dai_props *dai_props = priv->dai_props;
704
705                 cinfo = dev->platform_data;
706                 if (!cinfo) {
707                         dev_err(dev, "no info for asoc-simple-card\n");
708                         return -EINVAL;
709                 }
710
711                 if (!cinfo->name ||
712                     !cinfo->codec_dai.name ||
713                     !cinfo->codec ||
714                     !cinfo->platform ||
715                     !cinfo->cpu_dai.name) {
716                         dev_err(dev, "insufficient asoc_simple_card_info settings\n");
717                         return -EINVAL;
718                 }
719
720                 cpus                    = dai_link->cpus;
721                 cpus->dai_name          = cinfo->cpu_dai.name;
722
723                 codecs                  = dai_link->codecs;
724                 codecs->name            = cinfo->codec;
725                 codecs->dai_name        = cinfo->codec_dai.name;
726
727                 platform                = dai_link->platforms;
728                 platform->name          = cinfo->platform;
729
730                 card->name              = (cinfo->card) ? cinfo->card : cinfo->name;
731                 dai_link->name          = cinfo->name;
732                 dai_link->stream_name   = cinfo->name;
733                 dai_link->dai_fmt       = cinfo->daifmt;
734                 dai_link->init          = asoc_simple_dai_init;
735                 memcpy(dai_props->cpu_dai, &cinfo->cpu_dai,
736                                         sizeof(*dai_props->cpu_dai));
737                 memcpy(dai_props->codec_dai, &cinfo->codec_dai,
738                                         sizeof(*dai_props->codec_dai));
739         }
740
741         snd_soc_card_set_drvdata(card, priv);
742
743         asoc_simple_debug_info(priv);
744
745         ret = devm_snd_soc_register_card(dev, card);
746         if (ret < 0)
747                 goto err;
748
749         devm_kfree(dev, li);
750         return 0;
751 err:
752         asoc_simple_clean_reference(card);
753
754         return ret;
755 }
756
757 static const struct of_device_id simple_of_match[] = {
758         { .compatible = "simple-audio-card", },
759         { .compatible = "simple-scu-audio-card",
760           .data = (void *)DPCM_SELECTABLE },
761         {},
762 };
763 MODULE_DEVICE_TABLE(of, simple_of_match);
764
765 static struct platform_driver asoc_simple_card = {
766         .driver = {
767                 .name = "asoc-simple-card",
768                 .pm = &snd_soc_pm_ops,
769                 .of_match_table = simple_of_match,
770         },
771         .probe = asoc_simple_probe,
772         .remove = asoc_simple_remove,
773 };
774
775 module_platform_driver(asoc_simple_card);
776
777 MODULE_ALIAS("platform:asoc-simple-card");
778 MODULE_LICENSE("GPL v2");
779 MODULE_DESCRIPTION("ASoC Simple Sound Card");
780 MODULE_AUTHOR("Kuninori Morimoto <[email protected]>");
This page took 0.080822 seconds and 4 git commands to generate.