linux/sound/soc/generic/simple-card-utils.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// simple-card-utils.c
   4//
   5// Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
   6
   7#include <linux/clk.h>
   8#include <linux/gpio.h>
   9#include <linux/gpio/consumer.h>
  10#include <linux/module.h>
  11#include <linux/of.h>
  12#include <linux/of_gpio.h>
  13#include <linux/of_graph.h>
  14#include <sound/jack.h>
  15#include <sound/simple_card_utils.h>
  16
  17void asoc_simple_convert_fixup(struct asoc_simple_data *data,
  18                               struct snd_pcm_hw_params *params)
  19{
  20        struct snd_interval *rate = hw_param_interval(params,
  21                                                SNDRV_PCM_HW_PARAM_RATE);
  22        struct snd_interval *channels = hw_param_interval(params,
  23                                                SNDRV_PCM_HW_PARAM_CHANNELS);
  24
  25        if (data->convert_rate)
  26                rate->min =
  27                rate->max = data->convert_rate;
  28
  29        if (data->convert_channels)
  30                channels->min =
  31                channels->max = data->convert_channels;
  32}
  33EXPORT_SYMBOL_GPL(asoc_simple_convert_fixup);
  34
  35void asoc_simple_parse_convert(struct device *dev,
  36                               struct device_node *np,
  37                               char *prefix,
  38                               struct asoc_simple_data *data)
  39{
  40        char prop[128];
  41
  42        if (!prefix)
  43                prefix = "";
  44
  45        /* sampling rate convert */
  46        snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-rate");
  47        of_property_read_u32(np, prop, &data->convert_rate);
  48
  49        /* channels transfer */
  50        snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-channels");
  51        of_property_read_u32(np, prop, &data->convert_channels);
  52}
  53EXPORT_SYMBOL_GPL(asoc_simple_parse_convert);
  54
  55int asoc_simple_parse_daifmt(struct device *dev,
  56                             struct device_node *node,
  57                             struct device_node *codec,
  58                             char *prefix,
  59                             unsigned int *retfmt)
  60{
  61        struct device_node *bitclkmaster = NULL;
  62        struct device_node *framemaster = NULL;
  63        unsigned int daifmt;
  64
  65        daifmt = snd_soc_of_parse_daifmt(node, prefix,
  66                                         &bitclkmaster, &framemaster);
  67        daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
  68
  69        if (!bitclkmaster && !framemaster) {
  70                /*
  71                 * No dai-link level and master setting was not found from
  72                 * sound node level, revert back to legacy DT parsing and
  73                 * take the settings from codec node.
  74                 */
  75                dev_dbg(dev, "Revert to legacy daifmt parsing\n");
  76
  77                daifmt = snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
  78                        (daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
  79        } else {
  80                if (codec == bitclkmaster)
  81                        daifmt |= (codec == framemaster) ?
  82                                SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
  83                else
  84                        daifmt |= (codec == framemaster) ?
  85                                SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
  86        }
  87
  88        of_node_put(bitclkmaster);
  89        of_node_put(framemaster);
  90
  91        *retfmt = daifmt;
  92
  93        return 0;
  94}
  95EXPORT_SYMBOL_GPL(asoc_simple_parse_daifmt);
  96
  97int asoc_simple_set_dailink_name(struct device *dev,
  98                                 struct snd_soc_dai_link *dai_link,
  99                                 const char *fmt, ...)
 100{
 101        va_list ap;
 102        char *name = NULL;
 103        int ret = -ENOMEM;
 104
 105        va_start(ap, fmt);
 106        name = devm_kvasprintf(dev, GFP_KERNEL, fmt, ap);
 107        va_end(ap);
 108
 109        if (name) {
 110                ret = 0;
 111
 112                dai_link->name          = name;
 113                dai_link->stream_name   = name;
 114        }
 115
 116        return ret;
 117}
 118EXPORT_SYMBOL_GPL(asoc_simple_set_dailink_name);
 119
 120int asoc_simple_parse_card_name(struct snd_soc_card *card,
 121                                char *prefix)
 122{
 123        int ret;
 124
 125        if (!prefix)
 126                prefix = "";
 127
 128        /* Parse the card name from DT */
 129        ret = snd_soc_of_parse_card_name(card, "label");
 130        if (ret < 0 || !card->name) {
 131                char prop[128];
 132
 133                snprintf(prop, sizeof(prop), "%sname", prefix);
 134                ret = snd_soc_of_parse_card_name(card, prop);
 135                if (ret < 0)
 136                        return ret;
 137        }
 138
 139        if (!card->name && card->dai_link)
 140                card->name = card->dai_link->name;
 141
 142        return 0;
 143}
 144EXPORT_SYMBOL_GPL(asoc_simple_parse_card_name);
 145
 146static int asoc_simple_clk_enable(struct asoc_simple_dai *dai)
 147{
 148        if (dai)
 149                return clk_prepare_enable(dai->clk);
 150
 151        return 0;
 152}
 153
 154static void asoc_simple_clk_disable(struct asoc_simple_dai *dai)
 155{
 156        if (dai)
 157                clk_disable_unprepare(dai->clk);
 158}
 159
 160int asoc_simple_parse_clk(struct device *dev,
 161                          struct device_node *node,
 162                          struct asoc_simple_dai *simple_dai,
 163                          struct snd_soc_dai_link_component *dlc)
 164{
 165        struct clk *clk;
 166        u32 val;
 167
 168        /*
 169         * Parse dai->sysclk come from "clocks = <&xxx>"
 170         * (if system has common clock)
 171         *  or "system-clock-frequency = <xxx>"
 172         *  or device's module clock.
 173         */
 174        clk = devm_get_clk_from_child(dev, node, NULL);
 175        if (!IS_ERR(clk)) {
 176                simple_dai->sysclk = clk_get_rate(clk);
 177
 178                simple_dai->clk = clk;
 179        } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) {
 180                simple_dai->sysclk = val;
 181        } else {
 182                clk = devm_get_clk_from_child(dev, dlc->of_node, NULL);
 183                if (!IS_ERR(clk))
 184                        simple_dai->sysclk = clk_get_rate(clk);
 185        }
 186
 187        if (of_property_read_bool(node, "system-clock-direction-out"))
 188                simple_dai->clk_direction = SND_SOC_CLOCK_OUT;
 189
 190        return 0;
 191}
 192EXPORT_SYMBOL_GPL(asoc_simple_parse_clk);
 193
 194int asoc_simple_startup(struct snd_pcm_substream *substream)
 195{
 196        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 197        struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
 198        struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num);
 199        int ret;
 200
 201        ret = asoc_simple_clk_enable(dai_props->cpu_dai);
 202        if (ret)
 203                return ret;
 204
 205        ret = asoc_simple_clk_enable(dai_props->codec_dai);
 206        if (ret)
 207                asoc_simple_clk_disable(dai_props->cpu_dai);
 208
 209        return ret;
 210}
 211EXPORT_SYMBOL_GPL(asoc_simple_startup);
 212
 213void asoc_simple_shutdown(struct snd_pcm_substream *substream)
 214{
 215        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 216        struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
 217        struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
 218        struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
 219        struct simple_dai_props *dai_props =
 220                simple_priv_to_props(priv, rtd->num);
 221
 222        if (dai_props->mclk_fs) {
 223                snd_soc_dai_set_sysclk(codec_dai, 0, 0, SND_SOC_CLOCK_IN);
 224                snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_OUT);
 225        }
 226
 227        asoc_simple_clk_disable(dai_props->cpu_dai);
 228
 229        asoc_simple_clk_disable(dai_props->codec_dai);
 230}
 231EXPORT_SYMBOL_GPL(asoc_simple_shutdown);
 232
 233static int asoc_simple_set_clk_rate(struct asoc_simple_dai *simple_dai,
 234                                    unsigned long rate)
 235{
 236        if (!simple_dai)
 237                return 0;
 238
 239        if (!simple_dai->clk)
 240                return 0;
 241
 242        if (clk_get_rate(simple_dai->clk) == rate)
 243                return 0;
 244
 245        return clk_set_rate(simple_dai->clk, rate);
 246}
 247
 248int asoc_simple_hw_params(struct snd_pcm_substream *substream,
 249                          struct snd_pcm_hw_params *params)
 250{
 251        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 252        struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
 253        struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
 254        struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
 255        struct simple_dai_props *dai_props =
 256                simple_priv_to_props(priv, rtd->num);
 257        unsigned int mclk, mclk_fs = 0;
 258        int ret = 0;
 259
 260        if (dai_props->mclk_fs)
 261                mclk_fs = dai_props->mclk_fs;
 262
 263        if (mclk_fs) {
 264                mclk = params_rate(params) * mclk_fs;
 265
 266                ret = asoc_simple_set_clk_rate(dai_props->codec_dai, mclk);
 267                if (ret < 0)
 268                        return ret;
 269
 270                ret = asoc_simple_set_clk_rate(dai_props->cpu_dai, mclk);
 271                if (ret < 0)
 272                        return ret;
 273
 274                ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
 275                                             SND_SOC_CLOCK_IN);
 276                if (ret && ret != -ENOTSUPP)
 277                        goto err;
 278
 279                ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
 280                                             SND_SOC_CLOCK_OUT);
 281                if (ret && ret != -ENOTSUPP)
 282                        goto err;
 283        }
 284        return 0;
 285err:
 286        return ret;
 287}
 288EXPORT_SYMBOL_GPL(asoc_simple_hw_params);
 289
 290int asoc_simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 291                                   struct snd_pcm_hw_params *params)
 292{
 293        struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
 294        struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num);
 295
 296        asoc_simple_convert_fixup(&dai_props->adata, params);
 297
 298        return 0;
 299}
 300EXPORT_SYMBOL_GPL(asoc_simple_be_hw_params_fixup);
 301
 302static int asoc_simple_init_dai(struct snd_soc_dai *dai,
 303                                     struct asoc_simple_dai *simple_dai)
 304{
 305        int ret;
 306
 307        if (!simple_dai)
 308                return 0;
 309
 310        if (simple_dai->sysclk) {
 311                ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk,
 312                                             simple_dai->clk_direction);
 313                if (ret && ret != -ENOTSUPP) {
 314                        dev_err(dai->dev, "simple-card: set_sysclk error\n");
 315                        return ret;
 316                }
 317        }
 318
 319        if (simple_dai->slots) {
 320                ret = snd_soc_dai_set_tdm_slot(dai,
 321                                               simple_dai->tx_slot_mask,
 322                                               simple_dai->rx_slot_mask,
 323                                               simple_dai->slots,
 324                                               simple_dai->slot_width);
 325                if (ret && ret != -ENOTSUPP) {
 326                        dev_err(dai->dev, "simple-card: set_tdm_slot error\n");
 327                        return ret;
 328                }
 329        }
 330
 331        return 0;
 332}
 333
 334static int asoc_simple_init_dai_link_params(struct snd_soc_pcm_runtime *rtd,
 335                                            struct simple_dai_props *dai_props)
 336{
 337        struct snd_soc_dai_link *dai_link = rtd->dai_link;
 338        struct snd_soc_component *component;
 339        struct snd_soc_pcm_stream *params;
 340        struct snd_pcm_hardware hw;
 341        int i, ret, stream;
 342
 343        /* Only codecs should have non_legacy_dai_naming set. */
 344        for_each_rtd_components(rtd, i, component) {
 345                if (!component->driver->non_legacy_dai_naming)
 346                        return 0;
 347        }
 348
 349        /* Assumes the capabilities are the same for all supported streams */
 350        for_each_pcm_streams(stream) {
 351                ret = snd_soc_runtime_calc_hw(rtd, &hw, stream);
 352                if (ret == 0)
 353                        break;
 354        }
 355
 356        if (ret < 0) {
 357                dev_err(rtd->dev, "simple-card: no valid dai_link params\n");
 358                return ret;
 359        }
 360
 361        params = devm_kzalloc(rtd->dev, sizeof(*params), GFP_KERNEL);
 362        if (!params)
 363                return -ENOMEM;
 364
 365        params->formats = hw.formats;
 366        params->rates = hw.rates;
 367        params->rate_min = hw.rate_min;
 368        params->rate_max = hw.rate_max;
 369        params->channels_min = hw.channels_min;
 370        params->channels_max = hw.channels_max;
 371
 372        dai_link->params = params;
 373        dai_link->num_params = 1;
 374
 375        return 0;
 376}
 377
 378int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd)
 379{
 380        struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
 381        struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num);
 382        int ret;
 383
 384        ret = asoc_simple_init_dai(asoc_rtd_to_codec(rtd, 0),
 385                                   dai_props->codec_dai);
 386        if (ret < 0)
 387                return ret;
 388
 389        ret = asoc_simple_init_dai(asoc_rtd_to_cpu(rtd, 0),
 390                                   dai_props->cpu_dai);
 391        if (ret < 0)
 392                return ret;
 393
 394        ret = asoc_simple_init_dai_link_params(rtd, dai_props);
 395        if (ret < 0)
 396                return ret;
 397
 398        return 0;
 399}
 400EXPORT_SYMBOL_GPL(asoc_simple_dai_init);
 401
 402void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link)
 403{
 404        /* Assumes platform == cpu */
 405        if (!dai_link->platforms->of_node)
 406                dai_link->platforms->of_node = dai_link->cpus->of_node;
 407
 408        /*
 409         * DPCM BE can be no platform.
 410         * Alloced memory will be waste, but not leak.
 411         */
 412        if (!dai_link->platforms->of_node)
 413                dai_link->num_platforms = 0;
 414}
 415EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform);
 416
 417void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link *dai_link,
 418                                  int is_single_links)
 419{
 420        /*
 421         * In soc_bind_dai_link() will check cpu name after
 422         * of_node matching if dai_link has cpu_dai_name.
 423         * but, it will never match if name was created by
 424         * fmt_single_name() remove cpu_dai_name if cpu_args
 425         * was 0. See:
 426         *      fmt_single_name()
 427         *      fmt_multiple_name()
 428         */
 429        if (is_single_links)
 430                dai_link->cpus->dai_name = NULL;
 431}
 432EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_cpu);
 433
 434int asoc_simple_clean_reference(struct snd_soc_card *card)
 435{
 436        struct snd_soc_dai_link *dai_link;
 437        int i;
 438
 439        for_each_card_prelinks(card, i, dai_link) {
 440                of_node_put(dai_link->cpus->of_node);
 441                of_node_put(dai_link->codecs->of_node);
 442        }
 443        return 0;
 444}
 445EXPORT_SYMBOL_GPL(asoc_simple_clean_reference);
 446
 447int asoc_simple_parse_routing(struct snd_soc_card *card,
 448                              char *prefix)
 449{
 450        struct device_node *node = card->dev->of_node;
 451        char prop[128];
 452
 453        if (!prefix)
 454                prefix = "";
 455
 456        snprintf(prop, sizeof(prop), "%s%s", prefix, "routing");
 457
 458        if (!of_property_read_bool(node, prop))
 459                return 0;
 460
 461        return snd_soc_of_parse_audio_routing(card, prop);
 462}
 463EXPORT_SYMBOL_GPL(asoc_simple_parse_routing);
 464
 465int asoc_simple_parse_widgets(struct snd_soc_card *card,
 466                              char *prefix)
 467{
 468        struct device_node *node = card->dev->of_node;
 469        char prop[128];
 470
 471        if (!prefix)
 472                prefix = "";
 473
 474        snprintf(prop, sizeof(prop), "%s%s", prefix, "widgets");
 475
 476        if (of_property_read_bool(node, prop))
 477                return snd_soc_of_parse_audio_simple_widgets(card, prop);
 478
 479        /* no widgets is not error */
 480        return 0;
 481}
 482EXPORT_SYMBOL_GPL(asoc_simple_parse_widgets);
 483
 484int asoc_simple_parse_pin_switches(struct snd_soc_card *card,
 485                                   char *prefix)
 486{
 487        const unsigned int nb_controls_max = 16;
 488        const char **strings, *control_name;
 489        struct snd_kcontrol_new *controls;
 490        struct device *dev = card->dev;
 491        unsigned int i, nb_controls;
 492        char prop[128];
 493        int ret;
 494
 495        if (!prefix)
 496                prefix = "";
 497
 498        snprintf(prop, sizeof(prop), "%s%s", prefix, "pin-switches");
 499
 500        if (!of_property_read_bool(dev->of_node, prop))
 501                return 0;
 502
 503        strings = devm_kcalloc(dev, nb_controls_max,
 504                               sizeof(*strings), GFP_KERNEL);
 505        if (!strings)
 506                return -ENOMEM;
 507
 508        ret = of_property_read_string_array(dev->of_node, prop,
 509                                            strings, nb_controls_max);
 510        if (ret < 0)
 511                return ret;
 512
 513        nb_controls = (unsigned int)ret;
 514
 515        controls = devm_kcalloc(dev, nb_controls,
 516                                sizeof(*controls), GFP_KERNEL);
 517        if (!controls)
 518                return -ENOMEM;
 519
 520        for (i = 0; i < nb_controls; i++) {
 521                control_name = devm_kasprintf(dev, GFP_KERNEL,
 522                                              "%s Switch", strings[i]);
 523                if (!control_name)
 524                        return -ENOMEM;
 525
 526                controls[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 527                controls[i].name = control_name;
 528                controls[i].info = snd_soc_dapm_info_pin_switch;
 529                controls[i].get = snd_soc_dapm_get_pin_switch;
 530                controls[i].put = snd_soc_dapm_put_pin_switch;
 531                controls[i].private_value = (unsigned long)strings[i];
 532        }
 533
 534        card->controls = controls;
 535        card->num_controls = nb_controls;
 536
 537        return 0;
 538}
 539EXPORT_SYMBOL_GPL(asoc_simple_parse_pin_switches);
 540
 541int asoc_simple_init_jack(struct snd_soc_card *card,
 542                          struct asoc_simple_jack *sjack,
 543                          int is_hp, char *prefix,
 544                          char *pin)
 545{
 546        struct device *dev = card->dev;
 547        enum of_gpio_flags flags;
 548        char prop[128];
 549        char *pin_name;
 550        char *gpio_name;
 551        int mask;
 552        int det;
 553
 554        if (!prefix)
 555                prefix = "";
 556
 557        sjack->gpio.gpio = -ENOENT;
 558
 559        if (is_hp) {
 560                snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
 561                pin_name        = pin ? pin : "Headphones";
 562                gpio_name       = "Headphone detection";
 563                mask            = SND_JACK_HEADPHONE;
 564        } else {
 565                snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
 566                pin_name        = pin ? pin : "Mic Jack";
 567                gpio_name       = "Mic detection";
 568                mask            = SND_JACK_MICROPHONE;
 569        }
 570
 571        det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags);
 572        if (det == -EPROBE_DEFER)
 573                return -EPROBE_DEFER;
 574
 575        if (gpio_is_valid(det)) {
 576                sjack->pin.pin          = pin_name;
 577                sjack->pin.mask         = mask;
 578
 579                sjack->gpio.name        = gpio_name;
 580                sjack->gpio.report      = mask;
 581                sjack->gpio.gpio        = det;
 582                sjack->gpio.invert      = !!(flags & OF_GPIO_ACTIVE_LOW);
 583                sjack->gpio.debounce_time = 150;
 584
 585                snd_soc_card_jack_new(card, pin_name, mask,
 586                                      &sjack->jack,
 587                                      &sjack->pin, 1);
 588
 589                snd_soc_jack_add_gpios(&sjack->jack, 1,
 590                                       &sjack->gpio);
 591        }
 592
 593        return 0;
 594}
 595EXPORT_SYMBOL_GPL(asoc_simple_init_jack);
 596
 597int asoc_simple_init_priv(struct asoc_simple_priv *priv,
 598                          struct link_info *li)
 599{
 600        struct snd_soc_card *card = simple_priv_to_card(priv);
 601        struct device *dev = simple_priv_to_dev(priv);
 602        struct snd_soc_dai_link *dai_link;
 603        struct simple_dai_props *dai_props;
 604        struct asoc_simple_dai *dais;
 605        struct snd_soc_codec_conf *cconf = NULL;
 606        int i;
 607
 608        dai_props = devm_kcalloc(dev, li->link, sizeof(*dai_props), GFP_KERNEL);
 609        dai_link  = devm_kcalloc(dev, li->link, sizeof(*dai_link),  GFP_KERNEL);
 610        dais      = devm_kcalloc(dev, li->dais, sizeof(*dais),      GFP_KERNEL);
 611        if (!dai_props || !dai_link || !dais)
 612                return -ENOMEM;
 613
 614        if (li->conf) {
 615                cconf = devm_kcalloc(dev, li->conf, sizeof(*cconf), GFP_KERNEL);
 616                if (!cconf)
 617                        return -ENOMEM;
 618        }
 619
 620        /*
 621         * Use snd_soc_dai_link_component instead of legacy style
 622         * It is codec only. but cpu/platform will be supported in the future.
 623         * see
 624         *      soc-core.c :: snd_soc_init_multicodec()
 625         *
 626         * "platform" might be removed
 627         * see
 628         *      simple-card-utils.c :: asoc_simple_canonicalize_platform()
 629         */
 630        for (i = 0; i < li->link; i++) {
 631                dai_link[i].cpus                = &dai_props[i].cpus;
 632                dai_link[i].num_cpus            = 1;
 633                dai_link[i].codecs              = &dai_props[i].codecs;
 634                dai_link[i].num_codecs          = 1;
 635                dai_link[i].platforms           = &dai_props[i].platforms;
 636                dai_link[i].num_platforms       = 1;
 637        }
 638
 639        priv->dai_props         = dai_props;
 640        priv->dai_link          = dai_link;
 641        priv->dais              = dais;
 642        priv->codec_conf        = cconf;
 643
 644        card->dai_link          = priv->dai_link;
 645        card->num_links         = li->link;
 646        card->codec_conf        = cconf;
 647        card->num_configs       = li->conf;
 648
 649        return 0;
 650}
 651EXPORT_SYMBOL_GPL(asoc_simple_init_priv);
 652
 653/* Module information */
 654MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
 655MODULE_DESCRIPTION("ALSA SoC Simple Card Utils");
 656MODULE_LICENSE("GPL v2");
 657