Merge tag 'for-5.1-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[linux-2.6-microblaze.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 <kuninori.morimoto.gx@renesas.com>
7
8 #include <linux/clk.h>
9 #include <linux/device.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/platform_device.h>
13 #include <linux/string.h>
14 #include <sound/simple_card.h>
15 #include <sound/soc-dai.h>
16 #include <sound/soc.h>
17
18 struct simple_priv {
19         struct snd_soc_card snd_card;
20         struct simple_dai_props {
21                 struct asoc_simple_dai *cpu_dai;
22                 struct asoc_simple_dai *codec_dai;
23                 struct snd_soc_dai_link_component codecs; /* single codec */
24                 struct snd_soc_dai_link_component platforms;
25                 struct asoc_simple_card_data adata;
26                 struct snd_soc_codec_conf *codec_conf;
27                 unsigned int mclk_fs;
28         } *dai_props;
29         struct asoc_simple_jack hp_jack;
30         struct asoc_simple_jack mic_jack;
31         struct snd_soc_dai_link *dai_link;
32         struct asoc_simple_dai *dais;
33         struct snd_soc_codec_conf *codec_conf;
34 };
35
36 struct link_info {
37         int dais; /* number of dai  */
38         int link; /* number of link */
39         int conf; /* number of codec_conf */
40         int cpu;  /* turn for CPU / Codec */
41 };
42
43 #define simple_priv_to_card(priv) (&(priv)->snd_card)
44 #define simple_priv_to_props(priv, i) ((priv)->dai_props + (i))
45 #define simple_priv_to_dev(priv) (simple_priv_to_card(priv)->dev)
46 #define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i))
47
48 #define DAI     "sound-dai"
49 #define CELL    "#sound-dai-cells"
50 #define PREFIX  "simple-audio-card,"
51
52 static int simple_startup(struct snd_pcm_substream *substream)
53 {
54         struct snd_soc_pcm_runtime *rtd = substream->private_data;
55         struct simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
56         struct simple_dai_props *dai_props =
57                 simple_priv_to_props(priv, rtd->num);
58         int ret;
59
60         ret = asoc_simple_card_clk_enable(dai_props->cpu_dai);
61         if (ret)
62                 return ret;
63
64         ret = asoc_simple_card_clk_enable(dai_props->codec_dai);
65         if (ret)
66                 asoc_simple_card_clk_disable(dai_props->cpu_dai);
67
68         return ret;
69 }
70
71 static void simple_shutdown(struct snd_pcm_substream *substream)
72 {
73         struct snd_soc_pcm_runtime *rtd = substream->private_data;
74         struct simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
75         struct simple_dai_props *dai_props =
76                 simple_priv_to_props(priv, rtd->num);
77
78         asoc_simple_card_clk_disable(dai_props->cpu_dai);
79
80         asoc_simple_card_clk_disable(dai_props->codec_dai);
81 }
82
83 static int simple_set_clk_rate(struct asoc_simple_dai *simple_dai,
84                                unsigned long rate)
85 {
86         if (!simple_dai)
87                 return 0;
88
89         if (!simple_dai->clk)
90                 return 0;
91
92         if (clk_get_rate(simple_dai->clk) == rate)
93                 return 0;
94
95         return clk_set_rate(simple_dai->clk, rate);
96 }
97
98 static int simple_hw_params(struct snd_pcm_substream *substream,
99                             struct snd_pcm_hw_params *params)
100 {
101         struct snd_soc_pcm_runtime *rtd = substream->private_data;
102         struct snd_soc_dai *codec_dai = rtd->codec_dai;
103         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
104         struct simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
105         struct simple_dai_props *dai_props =
106                 simple_priv_to_props(priv, rtd->num);
107         unsigned int mclk, mclk_fs = 0;
108         int ret = 0;
109
110         if (dai_props->mclk_fs)
111                 mclk_fs = dai_props->mclk_fs;
112
113         if (mclk_fs) {
114                 mclk = params_rate(params) * mclk_fs;
115
116                 ret = simple_set_clk_rate(dai_props->codec_dai, mclk);
117                 if (ret < 0)
118                         return ret;
119
120                 ret = simple_set_clk_rate(dai_props->cpu_dai, mclk);
121                 if (ret < 0)
122                         return ret;
123
124                 ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
125                                              SND_SOC_CLOCK_IN);
126                 if (ret && ret != -ENOTSUPP)
127                         goto err;
128
129                 ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
130                                              SND_SOC_CLOCK_OUT);
131                 if (ret && ret != -ENOTSUPP)
132                         goto err;
133         }
134         return 0;
135 err:
136         return ret;
137 }
138
139 static const struct snd_soc_ops simple_ops = {
140         .startup        = simple_startup,
141         .shutdown       = simple_shutdown,
142         .hw_params      = simple_hw_params,
143 };
144
145 static int simple_dai_init(struct snd_soc_pcm_runtime *rtd)
146 {
147         struct simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
148         struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num);
149         int ret;
150
151         ret = asoc_simple_card_init_dai(rtd->codec_dai,
152                                         dai_props->codec_dai);
153         if (ret < 0)
154                 return ret;
155
156         ret = asoc_simple_card_init_dai(rtd->cpu_dai,
157                                         dai_props->cpu_dai);
158         if (ret < 0)
159                 return ret;
160
161         return 0;
162 }
163
164 static int simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
165                                      struct snd_pcm_hw_params *params)
166 {
167         struct simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
168         struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num);
169
170         asoc_simple_card_convert_fixup(&dai_props->adata, params);
171
172         return 0;
173 }
174
175 static void simple_get_conversion(struct device *dev,
176                                   struct device_node *np,
177                                   struct asoc_simple_card_data *adata)
178 {
179         struct device_node *top = dev->of_node;
180         struct device_node *node = of_get_parent(np);
181
182         asoc_simple_card_parse_convert(dev, top,  PREFIX, adata);
183         asoc_simple_card_parse_convert(dev, node, PREFIX, adata);
184         asoc_simple_card_parse_convert(dev, node, NULL,   adata);
185         asoc_simple_card_parse_convert(dev, np,   NULL,   adata);
186
187         of_node_put(node);
188 }
189
190 static int simple_dai_link_of_dpcm(struct simple_priv *priv,
191                                    struct device_node *np,
192                                    struct device_node *codec,
193                                    struct link_info *li,
194                                    bool is_top)
195 {
196         struct device *dev = simple_priv_to_dev(priv);
197         struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
198         struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
199         struct asoc_simple_dai *dai;
200         struct snd_soc_dai_link_component *codecs = dai_link->codecs;
201         struct device_node *top = dev->of_node;
202         struct device_node *node = of_get_parent(np);
203         char prop[128];
204         char *prefix = "";
205         int ret;
206
207         /*
208          *       |CPU   |Codec   : turn
209          * CPU   |Pass  |return
210          * Codec |return|Pass
211          * np
212          */
213         if (li->cpu == (np == codec))
214                 return 0;
215
216         dev_dbg(dev, "link_of DPCM (%pOF)\n", np);
217
218         li->link++;
219
220         of_node_put(node);
221
222         /* For single DAI link & old style of DT node */
223         if (is_top)
224                 prefix = PREFIX;
225
226         if (li->cpu) {
227                 int is_single_links = 0;
228
229                 /* BE is dummy */
230                 codecs->of_node         = NULL;
231                 codecs->dai_name        = "snd-soc-dummy-dai";
232                 codecs->name            = "snd-soc-dummy";
233
234                 /* FE settings */
235                 dai_link->dynamic               = 1;
236                 dai_link->dpcm_merged_format    = 1;
237
238                 dai =
239                 dai_props->cpu_dai      = &priv->dais[li->dais++];
240
241                 ret = asoc_simple_card_parse_cpu(np, dai_link, DAI, CELL,
242                                                  &is_single_links);
243                 if (ret)
244                         return ret;
245
246                 ret = asoc_simple_card_parse_clk_cpu(dev, np, dai_link, dai);
247                 if (ret < 0)
248                         return ret;
249
250                 ret = asoc_simple_card_set_dailink_name(dev, dai_link,
251                                                         "fe.%s",
252                                                         dai_link->cpu_dai_name);
253                 if (ret < 0)
254                         return ret;
255
256                 asoc_simple_card_canonicalize_cpu(dai_link, is_single_links);
257         } else {
258                 struct snd_soc_codec_conf *cconf;
259
260                 /* FE is dummy */
261                 dai_link->cpu_of_node           = NULL;
262                 dai_link->cpu_dai_name          = "snd-soc-dummy-dai";
263                 dai_link->cpu_name              = "snd-soc-dummy";
264
265                 /* BE settings */
266                 dai_link->no_pcm                = 1;
267                 dai_link->be_hw_params_fixup    = simple_be_hw_params_fixup;
268
269                 dai =
270                 dai_props->codec_dai    = &priv->dais[li->dais++];
271
272                 cconf =
273                 dai_props->codec_conf   = &priv->codec_conf[li->conf++];
274
275                 ret = asoc_simple_card_parse_codec(np, dai_link, DAI, CELL);
276                 if (ret < 0)
277                         return ret;
278
279                 ret = asoc_simple_card_parse_clk_codec(dev, np, dai_link, dai);
280                 if (ret < 0)
281                         return ret;
282
283                 ret = asoc_simple_card_set_dailink_name(dev, dai_link,
284                                                         "be.%s",
285                                                         codecs->dai_name);
286                 if (ret < 0)
287                         return ret;
288
289                 /* check "prefix" from top node */
290                 snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
291                                               PREFIX "prefix");
292                 snd_soc_of_parse_node_prefix(node, cconf, codecs->of_node,
293                                              "prefix");
294                 snd_soc_of_parse_node_prefix(np, cconf, codecs->of_node,
295                                              "prefix");
296         }
297
298         simple_get_conversion(dev, np, &dai_props->adata);
299
300         asoc_simple_card_canonicalize_platform(dai_link);
301
302         ret = asoc_simple_card_of_parse_tdm(np, dai);
303         if (ret)
304                 return ret;
305
306         snprintf(prop, sizeof(prop), "%smclk-fs", prefix);
307         of_property_read_u32(top,  PREFIX "mclk-fs", &dai_props->mclk_fs);
308         of_property_read_u32(node, prop, &dai_props->mclk_fs);
309         of_property_read_u32(np,   prop, &dai_props->mclk_fs);
310
311         ret = asoc_simple_card_parse_daifmt(dev, node, codec,
312                                             prefix, &dai_link->dai_fmt);
313         if (ret < 0)
314                 return ret;
315
316         dai_link->dpcm_playback         = 1;
317         dai_link->dpcm_capture          = 1;
318         dai_link->ops                   = &simple_ops;
319         dai_link->init                  = simple_dai_init;
320
321         return 0;
322 }
323
324 static int simple_dai_link_of(struct simple_priv *priv,
325                               struct device_node *np,
326                               struct device_node *codec,
327                               struct link_info *li,
328                               bool is_top)
329 {
330         struct device *dev = simple_priv_to_dev(priv);
331         struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
332         struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
333         struct asoc_simple_dai *cpu_dai;
334         struct asoc_simple_dai *codec_dai;
335         struct device_node *top = dev->of_node;
336         struct device_node *cpu = NULL;
337         struct device_node *node = NULL;
338         struct device_node *plat = NULL;
339         char prop[128];
340         char *prefix = "";
341         int ret, single_cpu;
342
343         /*
344          *       |CPU   |Codec   : turn
345          * CPU   |Pass  |return
346          * Codec |return|return
347          * np
348          */
349         if (!li->cpu || np == codec)
350                 return 0;
351
352         cpu  = np;
353         node = of_get_parent(np);
354         li->link++;
355
356         dev_dbg(dev, "link_of (%pOF)\n", node);
357
358         /* For single DAI link & old style of DT node */
359         if (is_top)
360                 prefix = PREFIX;
361
362         snprintf(prop, sizeof(prop), "%splat", prefix);
363         plat = of_get_child_by_name(node, prop);
364
365         cpu_dai                 =
366         dai_props->cpu_dai      = &priv->dais[li->dais++];
367         codec_dai               =
368         dai_props->codec_dai    = &priv->dais[li->dais++];
369
370         ret = asoc_simple_card_parse_daifmt(dev, node, codec,
371                                             prefix, &dai_link->dai_fmt);
372         if (ret < 0)
373                 goto dai_link_of_err;
374
375         snprintf(prop, sizeof(prop), "%smclk-fs", prefix);
376         of_property_read_u32(top,  PREFIX "mclk-fs", &dai_props->mclk_fs);
377         of_property_read_u32(node,  prop, &dai_props->mclk_fs);
378         of_property_read_u32(cpu,   prop, &dai_props->mclk_fs);
379         of_property_read_u32(codec, prop, &dai_props->mclk_fs);
380
381         ret = asoc_simple_card_parse_cpu(cpu, dai_link,
382                                          DAI, CELL, &single_cpu);
383         if (ret < 0)
384                 goto dai_link_of_err;
385
386         ret = asoc_simple_card_parse_codec(codec, dai_link, DAI, CELL);
387         if (ret < 0)
388                 goto dai_link_of_err;
389
390         ret = asoc_simple_card_parse_platform(plat, dai_link, DAI, CELL);
391         if (ret < 0)
392                 goto dai_link_of_err;
393
394         ret = asoc_simple_card_of_parse_tdm(cpu, cpu_dai);
395         if (ret < 0)
396                 goto dai_link_of_err;
397
398         ret = asoc_simple_card_of_parse_tdm(codec, codec_dai);
399         if (ret < 0)
400                 goto dai_link_of_err;
401
402         ret = asoc_simple_card_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
403         if (ret < 0)
404                 goto dai_link_of_err;
405
406         ret = asoc_simple_card_parse_clk_codec(dev, codec, dai_link, codec_dai);
407         if (ret < 0)
408                 goto dai_link_of_err;
409
410         ret = asoc_simple_card_set_dailink_name(dev, dai_link,
411                                                 "%s-%s",
412                                                 dai_link->cpu_dai_name,
413                                                 dai_link->codecs->dai_name);
414         if (ret < 0)
415                 goto dai_link_of_err;
416
417         dai_link->ops = &simple_ops;
418         dai_link->init = simple_dai_init;
419
420         asoc_simple_card_canonicalize_cpu(dai_link, single_cpu);
421         asoc_simple_card_canonicalize_platform(dai_link);
422
423 dai_link_of_err:
424         of_node_put(plat);
425         of_node_put(node);
426
427         return ret;
428 }
429
430 static int simple_for_each_link(struct simple_priv *priv,
431                         struct link_info *li,
432                         int (*func_noml)(struct simple_priv *priv,
433                                          struct device_node *np,
434                                          struct device_node *codec,
435                                          struct link_info *li, bool is_top),
436                         int (*func_dpcm)(struct simple_priv *priv,
437                                          struct device_node *np,
438                                          struct device_node *codec,
439                                          struct link_info *li, bool is_top))
440 {
441         struct device *dev = simple_priv_to_dev(priv);
442         struct device_node *top = dev->of_node;
443         struct device_node *node;
444         bool is_top = 0;
445         int ret = 0;
446
447         /* Check if it has dai-link */
448         node = of_get_child_by_name(top, PREFIX "dai-link");
449         if (!node) {
450                 node = of_node_get(top);
451                 is_top = 1;
452         }
453
454         /* loop for all dai-link */
455         do {
456                 struct asoc_simple_card_data adata;
457                 struct device_node *codec;
458                 struct device_node *np;
459                 int num = of_get_child_count(node);
460
461                 /* get codec */
462                 codec = of_get_child_by_name(node, is_top ?
463                                              PREFIX "codec" : "codec");
464                 if (!codec) {
465                         ret = -ENODEV;
466                         goto error;
467                 }
468
469                 of_node_put(codec);
470
471                 /* get convert-xxx property */
472                 memset(&adata, 0, sizeof(adata));
473                 for_each_child_of_node(node, np)
474                         simple_get_conversion(dev, np, &adata);
475
476                 /* loop for all CPU/Codec node */
477                 for_each_child_of_node(node, np) {
478                         /*
479                          * It is DPCM
480                          * if it has many CPUs,
481                          * or has convert-xxx property
482                          */
483                         if (num > 2 ||
484                             adata.convert_rate || adata.convert_channels)
485                                 ret = func_dpcm(priv, np, codec, li, is_top);
486                         /* else normal sound */
487                         else
488                                 ret = func_noml(priv, np, codec, li, is_top);
489
490                         if (ret < 0) {
491                                 of_node_put(np);
492                                 goto error;
493                         }
494                 }
495
496                 node = of_get_next_child(top, node);
497         } while (!is_top && node);
498
499  error:
500         of_node_put(node);
501         return ret;
502 }
503
504 static int simple_parse_aux_devs(struct device_node *node,
505                                  struct simple_priv *priv)
506 {
507         struct device *dev = simple_priv_to_dev(priv);
508         struct device_node *aux_node;
509         struct snd_soc_card *card = simple_priv_to_card(priv);
510         int i, n, len;
511
512         if (!of_find_property(node, PREFIX "aux-devs", &len))
513                 return 0;               /* Ok to have no aux-devs */
514
515         n = len / sizeof(__be32);
516         if (n <= 0)
517                 return -EINVAL;
518
519         card->aux_dev = devm_kcalloc(dev,
520                         n, sizeof(*card->aux_dev), GFP_KERNEL);
521         if (!card->aux_dev)
522                 return -ENOMEM;
523
524         for (i = 0; i < n; i++) {
525                 aux_node = of_parse_phandle(node, PREFIX "aux-devs", i);
526                 if (!aux_node)
527                         return -EINVAL;
528                 card->aux_dev[i].codec_of_node = aux_node;
529         }
530
531         card->num_aux_devs = n;
532         return 0;
533 }
534
535 static int simple_parse_of(struct simple_priv *priv)
536 {
537         struct device *dev = simple_priv_to_dev(priv);
538         struct device_node *top = dev->of_node;
539         struct snd_soc_card *card = simple_priv_to_card(priv);
540         struct link_info li;
541         int ret;
542
543         if (!top)
544                 return -EINVAL;
545
546         ret = asoc_simple_card_of_parse_widgets(card, PREFIX);
547         if (ret < 0)
548                 return ret;
549
550         ret = asoc_simple_card_of_parse_routing(card, PREFIX);
551         if (ret < 0)
552                 return ret;
553
554         /* Single/Muti DAI link(s) & New style of DT node */
555         memset(&li, 0, sizeof(li));
556         for (li.cpu = 1; li.cpu >= 0; li.cpu--) {
557                 /*
558                  * Detect all CPU first, and Detect all Codec 2nd.
559                  *
560                  * In Normal sound case, all DAIs are detected
561                  * as "CPU-Codec".
562                  *
563                  * In DPCM sound case,
564                  * all CPUs   are detected as "CPU-dummy", and
565                  * all Codecs are detected as "dummy-Codec".
566                  * To avoid random sub-device numbering,
567                  * detect "dummy-Codec" in last;
568                  */
569                 ret = simple_for_each_link(priv, &li,
570                                            simple_dai_link_of,
571                                            simple_dai_link_of_dpcm);
572                 if (ret < 0)
573                         return ret;
574         }
575
576         ret = asoc_simple_card_parse_card_name(card, PREFIX);
577         if (ret < 0)
578                 return ret;
579
580         ret = simple_parse_aux_devs(top, priv);
581
582         return ret;
583 }
584
585 static int simple_count_noml(struct simple_priv *priv,
586                              struct device_node *np,
587                              struct device_node *codec,
588                              struct link_info *li, bool is_top)
589 {
590         li->dais++; /* CPU or Codec */
591         if (np != codec)
592                 li->link++; /* CPU-Codec */
593
594         return 0;
595 }
596
597 static int simple_count_dpcm(struct simple_priv *priv,
598                              struct device_node *np,
599                              struct device_node *codec,
600                              struct link_info *li, bool is_top)
601 {
602         li->dais++; /* CPU or Codec */
603         li->link++; /* CPU-dummy or dummy-Codec */
604         if (np == codec)
605                 li->conf++;
606
607         return 0;
608 }
609
610 static void simple_get_dais_count(struct simple_priv *priv,
611                                   struct link_info *li)
612 {
613         struct device *dev = simple_priv_to_dev(priv);
614         struct device_node *top = dev->of_node;
615
616         /*
617          * link_num :   number of links.
618          *              CPU-Codec / CPU-dummy / dummy-Codec
619          * dais_num :   number of DAIs
620          * ccnf_num :   number of codec_conf
621          *              same number for "dummy-Codec"
622          *
623          * ex1)
624          * CPU0 --- Codec0      link : 5
625          * CPU1 --- Codec1      dais : 7
626          * CPU2 -/              ccnf : 1
627          * CPU3 --- Codec2
628          *
629          *      => 5 links = 2xCPU-Codec + 2xCPU-dummy + 1xdummy-Codec
630          *      => 7 DAIs  = 4xCPU + 3xCodec
631          *      => 1 ccnf  = 1xdummy-Codec
632          *
633          * ex2)
634          * CPU0 --- Codec0      link : 5
635          * CPU1 --- Codec1      dais : 6
636          * CPU2 -/              ccnf : 1
637          * CPU3 -/
638          *
639          *      => 5 links = 1xCPU-Codec + 3xCPU-dummy + 1xdummy-Codec
640          *      => 6 DAIs  = 4xCPU + 2xCodec
641          *      => 1 ccnf  = 1xdummy-Codec
642          *
643          * ex3)
644          * CPU0 --- Codec0      link : 6
645          * CPU1 -/              dais : 6
646          * CPU2 --- Codec1      ccnf : 2
647          * CPU3 -/
648          *
649          *      => 6 links = 0xCPU-Codec + 4xCPU-dummy + 2xdummy-Codec
650          *      => 6 DAIs  = 4xCPU + 2xCodec
651          *      => 2 ccnf  = 2xdummy-Codec
652          *
653          * ex4)
654          * CPU0 --- Codec0 (convert-rate)       link : 3
655          * CPU1 --- Codec1                      dais : 4
656          *                                      ccnf : 1
657          *
658          *      => 3 links = 1xCPU-Codec + 1xCPU-dummy + 1xdummy-Codec
659          *      => 4 DAIs  = 2xCPU + 2xCodec
660          *      => 1 ccnf  = 1xdummy-Codec
661          */
662         if (!top) {
663                 li->link = 1;
664                 li->dais = 2;
665                 li->conf = 0;
666                 return;
667         }
668
669         simple_for_each_link(priv, li,
670                              simple_count_noml,
671                              simple_count_dpcm);
672
673         dev_dbg(dev, "link %d, dais %d, ccnf %d\n",
674                 li->link, li->dais, li->conf);
675 }
676
677 static int simple_soc_probe(struct snd_soc_card *card)
678 {
679         struct simple_priv *priv = snd_soc_card_get_drvdata(card);
680         int ret;
681
682         ret = asoc_simple_card_init_hp(card, &priv->hp_jack, PREFIX);
683         if (ret < 0)
684                 return ret;
685
686         ret = asoc_simple_card_init_mic(card, &priv->mic_jack, PREFIX);
687         if (ret < 0)
688                 return ret;
689
690         return 0;
691 }
692
693 static int simple_probe(struct platform_device *pdev)
694 {
695         struct simple_priv *priv;
696         struct snd_soc_dai_link *dai_link;
697         struct simple_dai_props *dai_props;
698         struct asoc_simple_dai *dais;
699         struct device *dev = &pdev->dev;
700         struct device_node *np = dev->of_node;
701         struct snd_soc_card *card;
702         struct snd_soc_codec_conf *cconf;
703         struct link_info li;
704         int ret, i;
705
706         /* Allocate the private data and the DAI link array */
707         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
708         if (!priv)
709                 return -ENOMEM;
710
711         card = simple_priv_to_card(priv);
712         card->owner             = THIS_MODULE;
713         card->dev               = dev;
714         card->probe             = simple_soc_probe;
715
716         memset(&li, 0, sizeof(li));
717         simple_get_dais_count(priv, &li);
718         if (!li.link || !li.dais)
719                 return -EINVAL;
720
721         dai_props = devm_kcalloc(dev, li.link, sizeof(*dai_props), GFP_KERNEL);
722         dai_link  = devm_kcalloc(dev, li.link, sizeof(*dai_link),  GFP_KERNEL);
723         dais      = devm_kcalloc(dev, li.dais, sizeof(*dais),      GFP_KERNEL);
724         cconf     = devm_kcalloc(dev, li.conf, sizeof(*cconf),     GFP_KERNEL);
725         if (!dai_props || !dai_link || !dais)
726                 return -ENOMEM;
727
728         /*
729          * Use snd_soc_dai_link_component instead of legacy style
730          * It is codec only. but cpu/platform will be supported in the future.
731          * see
732          *      soc-core.c :: snd_soc_init_multicodec()
733          */
734         for (i = 0; i < li.link; i++) {
735                 dai_link[i].codecs      = &dai_props[i].codecs;
736                 dai_link[i].num_codecs  = 1;
737                 dai_link[i].platforms   = &dai_props[i].platforms;
738                 dai_link[i].num_platforms = 1;
739         }
740
741         priv->dai_props         = dai_props;
742         priv->dai_link          = dai_link;
743         priv->dais              = dais;
744         priv->codec_conf        = cconf;
745
746         card->dai_link          = priv->dai_link;
747         card->num_links         = li.link;
748         card->codec_conf        = cconf;
749         card->num_configs       = li.conf;
750
751         if (np && of_device_is_available(np)) {
752
753                 ret = simple_parse_of(priv);
754                 if (ret < 0) {
755                         if (ret != -EPROBE_DEFER)
756                                 dev_err(dev, "parse error %d\n", ret);
757                         goto err;
758                 }
759
760         } else {
761                 struct asoc_simple_card_info *cinfo;
762                 struct snd_soc_dai_link_component *codecs;
763                 struct snd_soc_dai_link_component *platform;
764                 int dai_idx = 0;
765
766                 cinfo = dev->platform_data;
767                 if (!cinfo) {
768                         dev_err(dev, "no info for asoc-simple-card\n");
769                         return -EINVAL;
770                 }
771
772                 if (!cinfo->name ||
773                     !cinfo->codec_dai.name ||
774                     !cinfo->codec ||
775                     !cinfo->platform ||
776                     !cinfo->cpu_dai.name) {
777                         dev_err(dev, "insufficient asoc_simple_card_info settings\n");
778                         return -EINVAL;
779                 }
780
781                 dai_props->cpu_dai      = &priv->dais[dai_idx++];
782                 dai_props->codec_dai    = &priv->dais[dai_idx++];
783
784                 codecs                  = dai_link->codecs;
785                 codecs->name            = cinfo->codec;
786                 codecs->dai_name        = cinfo->codec_dai.name;
787
788                 platform                = dai_link->platforms;
789                 platform->name          = cinfo->platform;
790
791                 card->name              = (cinfo->card) ? cinfo->card : cinfo->name;
792                 dai_link->name          = cinfo->name;
793                 dai_link->stream_name   = cinfo->name;
794                 dai_link->cpu_dai_name  = cinfo->cpu_dai.name;
795                 dai_link->dai_fmt       = cinfo->daifmt;
796                 dai_link->init          = simple_dai_init;
797                 memcpy(priv->dai_props->cpu_dai, &cinfo->cpu_dai,
798                                         sizeof(*priv->dai_props->cpu_dai));
799                 memcpy(priv->dai_props->codec_dai, &cinfo->codec_dai,
800                                         sizeof(*priv->dai_props->codec_dai));
801         }
802
803         snd_soc_card_set_drvdata(card, priv);
804
805         ret = devm_snd_soc_register_card(dev, card);
806         if (ret < 0)
807                 goto err;
808
809         return 0;
810 err:
811         asoc_simple_card_clean_reference(card);
812
813         return ret;
814 }
815
816 static int simple_remove(struct platform_device *pdev)
817 {
818         struct snd_soc_card *card = platform_get_drvdata(pdev);
819
820         return asoc_simple_card_clean_reference(card);
821 }
822
823 static const struct of_device_id simple_of_match[] = {
824         { .compatible = "simple-audio-card", },
825         { .compatible = "simple-scu-audio-card", },
826         {},
827 };
828 MODULE_DEVICE_TABLE(of, simple_of_match);
829
830 static struct platform_driver asoc_simple_card = {
831         .driver = {
832                 .name = "asoc-simple-card",
833                 .pm = &snd_soc_pm_ops,
834                 .of_match_table = simple_of_match,
835         },
836         .probe = simple_probe,
837         .remove = simple_remove,
838 };
839
840 module_platform_driver(asoc_simple_card);
841
842 MODULE_ALIAS("platform:asoc-simple-card");
843 MODULE_LICENSE("GPL v2");
844 MODULE_DESCRIPTION("ASoC Simple Sound Card");
845 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");