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