root/sound/soc/generic/simple-card.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. asoc_simple_parse_dai
  2. simple_parse_convert
  3. simple_parse_mclk_fs
  4. simple_dai_link_of_dpcm
  5. simple_dai_link_of
  6. simple_for_each_link
  7. simple_parse_aux_devs
  8. simple_parse_of
  9. simple_count_noml
  10. simple_count_dpcm
  11. simple_get_dais_count
  12. simple_soc_probe
  13. asoc_simple_probe
  14. asoc_simple_remove

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

/* [<][>][^][v][top][bottom][index][help] */