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