0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk.h>
0009 #include <linux/device.h>
0010 #include <linux/module.h>
0011 #include <linux/of.h>
0012 #include <linux/of_device.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/string.h>
0015 #include <sound/simple_card.h>
0016 #include <sound/soc-dai.h>
0017 #include <sound/soc.h>
0018
0019 #define DPCM_SELECTABLE 1
0020
0021 #define DAI "sound-dai"
0022 #define CELL "#sound-dai-cells"
0023 #define PREFIX "simple-audio-card,"
0024
0025 static const struct snd_soc_ops simple_ops = {
0026 .startup = asoc_simple_startup,
0027 .shutdown = asoc_simple_shutdown,
0028 .hw_params = asoc_simple_hw_params,
0029 };
0030
0031 static int asoc_simple_parse_platform(struct device_node *node,
0032 struct snd_soc_dai_link_component *dlc)
0033 {
0034 struct of_phandle_args args;
0035 int ret;
0036
0037 if (!node)
0038 return 0;
0039
0040
0041
0042
0043
0044 ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args);
0045 if (ret)
0046 return ret;
0047
0048
0049
0050 dlc->of_node = args.np;
0051
0052 return 0;
0053 }
0054
0055 static int asoc_simple_parse_dai(struct device_node *node,
0056 struct snd_soc_dai_link_component *dlc,
0057 int *is_single_link)
0058 {
0059 struct of_phandle_args args;
0060 int ret;
0061
0062 if (!node)
0063 return 0;
0064
0065
0066
0067
0068
0069 ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args);
0070 if (ret)
0071 return ret;
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 ret = snd_soc_of_get_dai_name(node, &dlc->dai_name);
0093 if (ret < 0)
0094 return ret;
0095
0096 dlc->of_node = args.np;
0097
0098 if (is_single_link)
0099 *is_single_link = !args.args_count;
0100
0101 return 0;
0102 }
0103
0104 static void simple_parse_convert(struct device *dev,
0105 struct device_node *np,
0106 struct asoc_simple_data *adata)
0107 {
0108 struct device_node *top = dev->of_node;
0109 struct device_node *node = of_get_parent(np);
0110
0111 asoc_simple_parse_convert(top, PREFIX, adata);
0112 asoc_simple_parse_convert(node, PREFIX, adata);
0113 asoc_simple_parse_convert(node, NULL, adata);
0114 asoc_simple_parse_convert(np, NULL, adata);
0115
0116 of_node_put(node);
0117 }
0118
0119 static void simple_parse_mclk_fs(struct device_node *top,
0120 struct device_node *np,
0121 struct simple_dai_props *props,
0122 char *prefix)
0123 {
0124 struct device_node *node = of_get_parent(np);
0125 char prop[128];
0126
0127 snprintf(prop, sizeof(prop), "%smclk-fs", PREFIX);
0128 of_property_read_u32(top, prop, &props->mclk_fs);
0129
0130 snprintf(prop, sizeof(prop), "%smclk-fs", prefix);
0131 of_property_read_u32(node, prop, &props->mclk_fs);
0132 of_property_read_u32(np, prop, &props->mclk_fs);
0133
0134 of_node_put(node);
0135 }
0136
0137 static int simple_parse_node(struct asoc_simple_priv *priv,
0138 struct device_node *np,
0139 struct link_info *li,
0140 char *prefix,
0141 int *cpu)
0142 {
0143 struct device *dev = simple_priv_to_dev(priv);
0144 struct device_node *top = dev->of_node;
0145 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
0146 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
0147 struct snd_soc_dai_link_component *dlc;
0148 struct asoc_simple_dai *dai;
0149 int ret;
0150
0151 if (cpu) {
0152 dlc = asoc_link_to_cpu(dai_link, 0);
0153 dai = simple_props_to_dai_cpu(dai_props, 0);
0154 } else {
0155 dlc = asoc_link_to_codec(dai_link, 0);
0156 dai = simple_props_to_dai_codec(dai_props, 0);
0157 }
0158
0159 simple_parse_mclk_fs(top, np, dai_props, prefix);
0160
0161 ret = asoc_simple_parse_dai(np, dlc, cpu);
0162 if (ret)
0163 return ret;
0164
0165 ret = asoc_simple_parse_clk(dev, np, dai, dlc);
0166 if (ret)
0167 return ret;
0168
0169 ret = asoc_simple_parse_tdm(np, dai);
0170 if (ret)
0171 return ret;
0172
0173 return 0;
0174 }
0175
0176 static int simple_link_init(struct asoc_simple_priv *priv,
0177 struct device_node *node,
0178 struct device_node *codec,
0179 struct link_info *li,
0180 char *prefix, char *name)
0181 {
0182 struct device *dev = simple_priv_to_dev(priv);
0183 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
0184 int ret;
0185
0186 ret = asoc_simple_parse_daifmt(dev, node, codec,
0187 prefix, &dai_link->dai_fmt);
0188 if (ret < 0)
0189 return 0;
0190
0191 dai_link->init = asoc_simple_dai_init;
0192 dai_link->ops = &simple_ops;
0193
0194 return asoc_simple_set_dailink_name(dev, dai_link, name);
0195 }
0196
0197 static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
0198 struct device_node *np,
0199 struct device_node *codec,
0200 struct link_info *li,
0201 bool is_top)
0202 {
0203 struct device *dev = simple_priv_to_dev(priv);
0204 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
0205 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
0206 struct device_node *top = dev->of_node;
0207 struct device_node *node = of_get_parent(np);
0208 char *prefix = "";
0209 char dai_name[64];
0210 int ret;
0211
0212 dev_dbg(dev, "link_of DPCM (%pOF)\n", np);
0213
0214
0215 if (is_top)
0216 prefix = PREFIX;
0217
0218 if (li->cpu) {
0219 struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0);
0220 struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0);
0221 int is_single_links = 0;
0222
0223
0224
0225
0226 dai_link->dynamic = 1;
0227 dai_link->dpcm_merged_format = 1;
0228
0229 ret = simple_parse_node(priv, np, li, prefix, &is_single_links);
0230 if (ret < 0)
0231 goto out_put_node;
0232
0233 snprintf(dai_name, sizeof(dai_name), "fe.%s", cpus->dai_name);
0234
0235 asoc_simple_canonicalize_cpu(cpus, is_single_links);
0236 asoc_simple_canonicalize_platform(platforms, cpus);
0237 } else {
0238 struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0);
0239 struct snd_soc_codec_conf *cconf;
0240
0241
0242
0243
0244 dai_link->no_pcm = 1;
0245 dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup;
0246
0247 cconf = simple_props_to_codec_conf(dai_props, 0);
0248
0249 ret = simple_parse_node(priv, np, li, prefix, NULL);
0250 if (ret < 0)
0251 goto out_put_node;
0252
0253 snprintf(dai_name, sizeof(dai_name), "be.%s", codecs->dai_name);
0254
0255
0256 snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
0257 PREFIX "prefix");
0258 snd_soc_of_parse_node_prefix(node, cconf, codecs->of_node,
0259 "prefix");
0260 snd_soc_of_parse_node_prefix(np, cconf, codecs->of_node,
0261 "prefix");
0262 }
0263
0264 simple_parse_convert(dev, np, &dai_props->adata);
0265
0266 snd_soc_dai_link_set_capabilities(dai_link);
0267
0268 ret = simple_link_init(priv, node, codec, li, prefix, dai_name);
0269
0270 out_put_node:
0271 li->link++;
0272
0273 of_node_put(node);
0274 return ret;
0275 }
0276
0277 static int simple_dai_link_of(struct asoc_simple_priv *priv,
0278 struct device_node *np,
0279 struct device_node *codec,
0280 struct link_info *li,
0281 bool is_top)
0282 {
0283 struct device *dev = simple_priv_to_dev(priv);
0284 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
0285 struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0);
0286 struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0);
0287 struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0);
0288 struct device_node *cpu = NULL;
0289 struct device_node *node = NULL;
0290 struct device_node *plat = NULL;
0291 char dai_name[64];
0292 char prop[128];
0293 char *prefix = "";
0294 int ret, single_cpu = 0;
0295
0296 cpu = np;
0297 node = of_get_parent(np);
0298
0299 dev_dbg(dev, "link_of (%pOF)\n", node);
0300
0301
0302 if (is_top)
0303 prefix = PREFIX;
0304
0305 snprintf(prop, sizeof(prop), "%splat", prefix);
0306 plat = of_get_child_by_name(node, prop);
0307
0308 ret = simple_parse_node(priv, cpu, li, prefix, &single_cpu);
0309 if (ret < 0)
0310 goto dai_link_of_err;
0311
0312 ret = simple_parse_node(priv, codec, li, prefix, NULL);
0313 if (ret < 0)
0314 goto dai_link_of_err;
0315
0316 ret = asoc_simple_parse_platform(plat, platforms);
0317 if (ret < 0)
0318 goto dai_link_of_err;
0319
0320 snprintf(dai_name, sizeof(dai_name),
0321 "%s-%s", cpus->dai_name, codecs->dai_name);
0322
0323 asoc_simple_canonicalize_cpu(cpus, single_cpu);
0324 asoc_simple_canonicalize_platform(platforms, cpus);
0325
0326 ret = simple_link_init(priv, node, codec, li, prefix, dai_name);
0327
0328 dai_link_of_err:
0329 of_node_put(plat);
0330 of_node_put(node);
0331
0332 li->link++;
0333
0334 return ret;
0335 }
0336
0337 static int __simple_for_each_link(struct asoc_simple_priv *priv,
0338 struct link_info *li,
0339 int (*func_noml)(struct asoc_simple_priv *priv,
0340 struct device_node *np,
0341 struct device_node *codec,
0342 struct link_info *li, bool is_top),
0343 int (*func_dpcm)(struct asoc_simple_priv *priv,
0344 struct device_node *np,
0345 struct device_node *codec,
0346 struct link_info *li, bool is_top))
0347 {
0348 struct device *dev = simple_priv_to_dev(priv);
0349 struct device_node *top = dev->of_node;
0350 struct device_node *node;
0351 uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev);
0352 bool is_top = 0;
0353 int ret = 0;
0354
0355
0356 node = of_get_child_by_name(top, PREFIX "dai-link");
0357 if (!node) {
0358 node = of_node_get(top);
0359 is_top = 1;
0360 }
0361
0362
0363 do {
0364 struct asoc_simple_data adata;
0365 struct device_node *codec;
0366 struct device_node *plat;
0367 struct device_node *np;
0368 int num = of_get_child_count(node);
0369
0370
0371 codec = of_get_child_by_name(node, is_top ?
0372 PREFIX "codec" : "codec");
0373 if (!codec) {
0374 ret = -ENODEV;
0375 goto error;
0376 }
0377
0378 plat = of_get_child_by_name(node, is_top ?
0379 PREFIX "plat" : "plat");
0380
0381
0382 memset(&adata, 0, sizeof(adata));
0383 for_each_child_of_node(node, np)
0384 simple_parse_convert(dev, np, &adata);
0385
0386
0387 for_each_child_of_node(node, np) {
0388 if (plat == np)
0389 continue;
0390
0391
0392
0393
0394
0395 if (dpcm_selectable &&
0396 (num > 2 ||
0397 adata.convert_rate || adata.convert_channels)) {
0398
0399
0400
0401
0402
0403
0404 if (li->cpu != (np == codec))
0405 ret = func_dpcm(priv, np, codec, li, is_top);
0406
0407 } else {
0408
0409
0410
0411
0412
0413
0414 if (li->cpu && (np != codec))
0415 ret = func_noml(priv, np, codec, li, is_top);
0416 }
0417
0418 if (ret < 0) {
0419 of_node_put(codec);
0420 of_node_put(np);
0421 goto error;
0422 }
0423 }
0424
0425 of_node_put(codec);
0426 node = of_get_next_child(top, node);
0427 } while (!is_top && node);
0428
0429 error:
0430 of_node_put(node);
0431 return ret;
0432 }
0433
0434 static int simple_for_each_link(struct asoc_simple_priv *priv,
0435 struct link_info *li,
0436 int (*func_noml)(struct asoc_simple_priv *priv,
0437 struct device_node *np,
0438 struct device_node *codec,
0439 struct link_info *li, bool is_top),
0440 int (*func_dpcm)(struct asoc_simple_priv *priv,
0441 struct device_node *np,
0442 struct device_node *codec,
0443 struct link_info *li, bool is_top))
0444 {
0445 int ret;
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458 for (li->cpu = 1; li->cpu >= 0; li->cpu--) {
0459 ret = __simple_for_each_link(priv, li, func_noml, func_dpcm);
0460 if (ret < 0)
0461 break;
0462 }
0463
0464 return ret;
0465 }
0466
0467 static int simple_parse_of(struct asoc_simple_priv *priv, struct link_info *li)
0468 {
0469 struct snd_soc_card *card = simple_priv_to_card(priv);
0470 int ret;
0471
0472 ret = asoc_simple_parse_widgets(card, PREFIX);
0473 if (ret < 0)
0474 return ret;
0475
0476 ret = asoc_simple_parse_routing(card, PREFIX);
0477 if (ret < 0)
0478 return ret;
0479
0480 ret = asoc_simple_parse_pin_switches(card, PREFIX);
0481 if (ret < 0)
0482 return ret;
0483
0484
0485 memset(li, 0, sizeof(*li));
0486 ret = simple_for_each_link(priv, li,
0487 simple_dai_link_of,
0488 simple_dai_link_of_dpcm);
0489 if (ret < 0)
0490 return ret;
0491
0492 ret = asoc_simple_parse_card_name(card, PREFIX);
0493 if (ret < 0)
0494 return ret;
0495
0496 ret = snd_soc_of_parse_aux_devs(card, PREFIX "aux-devs");
0497
0498 return ret;
0499 }
0500
0501 static int simple_count_noml(struct asoc_simple_priv *priv,
0502 struct device_node *np,
0503 struct device_node *codec,
0504 struct link_info *li, bool is_top)
0505 {
0506 if (li->link >= SNDRV_MAX_LINKS) {
0507 struct device *dev = simple_priv_to_dev(priv);
0508
0509 dev_err(dev, "too many links\n");
0510 return -EINVAL;
0511 }
0512
0513 li->num[li->link].cpus = 1;
0514 li->num[li->link].codecs = 1;
0515 li->num[li->link].platforms = 1;
0516
0517 li->link += 1;
0518
0519 return 0;
0520 }
0521
0522 static int simple_count_dpcm(struct asoc_simple_priv *priv,
0523 struct device_node *np,
0524 struct device_node *codec,
0525 struct link_info *li, bool is_top)
0526 {
0527 if (li->link >= SNDRV_MAX_LINKS) {
0528 struct device *dev = simple_priv_to_dev(priv);
0529
0530 dev_err(dev, "too many links\n");
0531 return -EINVAL;
0532 }
0533
0534 if (li->cpu) {
0535 li->num[li->link].cpus = 1;
0536 li->num[li->link].platforms = 1;
0537
0538 li->link++;
0539 } else {
0540 li->num[li->link].codecs = 1;
0541
0542 li->link++;
0543 }
0544
0545 return 0;
0546 }
0547
0548 static int simple_get_dais_count(struct asoc_simple_priv *priv,
0549 struct link_info *li)
0550 {
0551 struct device *dev = simple_priv_to_dev(priv);
0552 struct device_node *top = dev->of_node;
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600 if (!top) {
0601 li->num[0].cpus = 1;
0602 li->num[0].codecs = 1;
0603 li->num[0].platforms = 1;
0604
0605 li->link = 1;
0606 return 0;
0607 }
0608
0609 return simple_for_each_link(priv, li,
0610 simple_count_noml,
0611 simple_count_dpcm);
0612 }
0613
0614 static int simple_soc_probe(struct snd_soc_card *card)
0615 {
0616 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card);
0617 int ret;
0618
0619 ret = asoc_simple_init_hp(card, &priv->hp_jack, PREFIX);
0620 if (ret < 0)
0621 return ret;
0622
0623 ret = asoc_simple_init_mic(card, &priv->mic_jack, PREFIX);
0624 if (ret < 0)
0625 return ret;
0626
0627 return 0;
0628 }
0629
0630 static int asoc_simple_probe(struct platform_device *pdev)
0631 {
0632 struct asoc_simple_priv *priv;
0633 struct device *dev = &pdev->dev;
0634 struct device_node *np = dev->of_node;
0635 struct snd_soc_card *card;
0636 struct link_info *li;
0637 int ret;
0638
0639
0640 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0641 if (!priv)
0642 return -ENOMEM;
0643
0644 card = simple_priv_to_card(priv);
0645 card->owner = THIS_MODULE;
0646 card->dev = dev;
0647 card->probe = simple_soc_probe;
0648 card->driver_name = "simple-card";
0649
0650 li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
0651 if (!li)
0652 return -ENOMEM;
0653
0654 ret = simple_get_dais_count(priv, li);
0655 if (ret < 0)
0656 return ret;
0657
0658 if (!li->link)
0659 return -EINVAL;
0660
0661 ret = asoc_simple_init_priv(priv, li);
0662 if (ret < 0)
0663 return ret;
0664
0665 if (np && of_device_is_available(np)) {
0666
0667 ret = simple_parse_of(priv, li);
0668 if (ret < 0) {
0669 dev_err_probe(dev, ret, "parse error\n");
0670 goto err;
0671 }
0672
0673 } else {
0674 struct asoc_simple_card_info *cinfo;
0675 struct snd_soc_dai_link_component *cpus;
0676 struct snd_soc_dai_link_component *codecs;
0677 struct snd_soc_dai_link_component *platform;
0678 struct snd_soc_dai_link *dai_link = priv->dai_link;
0679 struct simple_dai_props *dai_props = priv->dai_props;
0680
0681 cinfo = dev->platform_data;
0682 if (!cinfo) {
0683 dev_err(dev, "no info for asoc-simple-card\n");
0684 return -EINVAL;
0685 }
0686
0687 if (!cinfo->name ||
0688 !cinfo->codec_dai.name ||
0689 !cinfo->codec ||
0690 !cinfo->platform ||
0691 !cinfo->cpu_dai.name) {
0692 dev_err(dev, "insufficient asoc_simple_card_info settings\n");
0693 return -EINVAL;
0694 }
0695
0696 cpus = dai_link->cpus;
0697 cpus->dai_name = cinfo->cpu_dai.name;
0698
0699 codecs = dai_link->codecs;
0700 codecs->name = cinfo->codec;
0701 codecs->dai_name = cinfo->codec_dai.name;
0702
0703 platform = dai_link->platforms;
0704 platform->name = cinfo->platform;
0705
0706 card->name = (cinfo->card) ? cinfo->card : cinfo->name;
0707 dai_link->name = cinfo->name;
0708 dai_link->stream_name = cinfo->name;
0709 dai_link->dai_fmt = cinfo->daifmt;
0710 dai_link->init = asoc_simple_dai_init;
0711 memcpy(dai_props->cpu_dai, &cinfo->cpu_dai,
0712 sizeof(*dai_props->cpu_dai));
0713 memcpy(dai_props->codec_dai, &cinfo->codec_dai,
0714 sizeof(*dai_props->codec_dai));
0715 }
0716
0717 snd_soc_card_set_drvdata(card, priv);
0718
0719 asoc_simple_debug_info(priv);
0720
0721 ret = devm_snd_soc_register_card(dev, card);
0722 if (ret < 0)
0723 goto err;
0724
0725 devm_kfree(dev, li);
0726 return 0;
0727 err:
0728 asoc_simple_clean_reference(card);
0729
0730 return ret;
0731 }
0732
0733 static const struct of_device_id simple_of_match[] = {
0734 { .compatible = "simple-audio-card", },
0735 { .compatible = "simple-scu-audio-card",
0736 .data = (void *)DPCM_SELECTABLE },
0737 {},
0738 };
0739 MODULE_DEVICE_TABLE(of, simple_of_match);
0740
0741 static struct platform_driver asoc_simple_card = {
0742 .driver = {
0743 .name = "asoc-simple-card",
0744 .pm = &snd_soc_pm_ops,
0745 .of_match_table = simple_of_match,
0746 },
0747 .probe = asoc_simple_probe,
0748 .remove = asoc_simple_remove,
0749 };
0750
0751 module_platform_driver(asoc_simple_card);
0752
0753 MODULE_ALIAS("platform:asoc-simple-card");
0754 MODULE_LICENSE("GPL v2");
0755 MODULE_DESCRIPTION("ASoC Simple Sound Card");
0756 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");