0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/clk.h>
0010 #include <linux/device.h>
0011 #include <linux/gpio.h>
0012 #include <linux/gpio/consumer.h>
0013 #include <linux/module.h>
0014 #include <linux/of.h>
0015 #include <linux/of_device.h>
0016 #include <linux/of_gpio.h>
0017 #include <linux/of_graph.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/string.h>
0020 #include <sound/graph_card.h>
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216 enum graph_type {
0217 GRAPH_NORMAL,
0218 GRAPH_DPCM,
0219 GRAPH_C2C,
0220
0221 GRAPH_MULTI,
0222 };
0223
0224 #define GRAPH_NODENAME_MULTI "multi"
0225 #define GRAPH_NODENAME_DPCM "dpcm"
0226 #define GRAPH_NODENAME_C2C "codec2codec"
0227
0228 #define port_to_endpoint(port) of_get_child_by_name(port, "endpoint")
0229
0230 static enum graph_type __graph_get_type(struct device_node *lnk)
0231 {
0232 struct device_node *np, *parent_np;
0233 enum graph_type ret;
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243 np = of_get_parent(lnk);
0244 if (of_node_name_eq(np, "ports")) {
0245 parent_np = of_get_parent(np);
0246 of_node_put(np);
0247 np = parent_np;
0248 }
0249
0250 if (of_node_name_eq(np, GRAPH_NODENAME_MULTI)) {
0251 ret = GRAPH_MULTI;
0252 goto out_put;
0253 }
0254
0255 if (of_node_name_eq(np, GRAPH_NODENAME_DPCM)) {
0256 ret = GRAPH_DPCM;
0257 goto out_put;
0258 }
0259
0260 if (of_node_name_eq(np, GRAPH_NODENAME_C2C)) {
0261 ret = GRAPH_C2C;
0262 goto out_put;
0263 }
0264
0265 ret = GRAPH_NORMAL;
0266
0267 out_put:
0268 of_node_put(np);
0269 return ret;
0270
0271 }
0272
0273 static enum graph_type graph_get_type(struct asoc_simple_priv *priv,
0274 struct device_node *lnk)
0275 {
0276 enum graph_type type = __graph_get_type(lnk);
0277
0278
0279 if (type == GRAPH_MULTI)
0280 type = GRAPH_NORMAL;
0281
0282 #ifdef DEBUG
0283 {
0284 struct device *dev = simple_priv_to_dev(priv);
0285 const char *str = "Normal";
0286
0287 switch (type) {
0288 case GRAPH_DPCM:
0289 if (asoc_graph_is_ports0(lnk))
0290 str = "DPCM Front-End";
0291 else
0292 str = "DPCM Back-End";
0293 break;
0294 case GRAPH_C2C:
0295 str = "Codec2Codec";
0296 break;
0297 default:
0298 break;
0299 }
0300
0301 dev_dbg(dev, "%pOF (%s)", lnk, str);
0302 }
0303 #endif
0304 return type;
0305 }
0306
0307 static int graph_lnk_is_multi(struct device_node *lnk)
0308 {
0309 return __graph_get_type(lnk) == GRAPH_MULTI;
0310 }
0311
0312 static struct device_node *graph_get_next_multi_ep(struct device_node **port)
0313 {
0314 struct device_node *ports = of_get_parent(*port);
0315 struct device_node *ep = NULL;
0316 struct device_node *rep = NULL;
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333 do {
0334 *port = of_get_next_child(ports, *port);
0335 if (!*port)
0336 break;
0337 } while (!of_node_name_eq(*port, "port"));
0338
0339 if (*port) {
0340 ep = port_to_endpoint(*port);
0341 rep = of_graph_get_remote_endpoint(ep);
0342 }
0343
0344 of_node_put(ep);
0345 of_node_put(ports);
0346
0347 return rep;
0348 }
0349
0350 static const struct snd_soc_ops graph_ops = {
0351 .startup = asoc_simple_startup,
0352 .shutdown = asoc_simple_shutdown,
0353 .hw_params = asoc_simple_hw_params,
0354 };
0355
0356 static int graph_get_dai_id(struct device_node *ep)
0357 {
0358 struct device_node *node;
0359 struct device_node *endpoint;
0360 struct of_endpoint info;
0361 int i, id;
0362 const u32 *reg;
0363 int ret;
0364
0365
0366 ret = snd_soc_get_dai_id(ep);
0367 if (ret != -ENOTSUPP)
0368 return ret;
0369
0370
0371 ret = of_graph_parse_endpoint(ep, &info);
0372 if (ret == 0) {
0373
0374
0375
0376
0377
0378
0379 if (of_get_property(ep, "reg", NULL))
0380 return info.id;
0381
0382 node = of_get_parent(ep);
0383 reg = of_get_property(node, "reg", NULL);
0384 of_node_put(node);
0385 if (reg)
0386 return info.port;
0387 }
0388 node = of_graph_get_port_parent(ep);
0389
0390
0391
0392
0393
0394 i = 0;
0395 id = -1;
0396 for_each_endpoint_of_node(node, endpoint) {
0397 if (endpoint == ep)
0398 id = i;
0399 i++;
0400 }
0401
0402 of_node_put(node);
0403
0404 if (id < 0)
0405 return -ENODEV;
0406
0407 return id;
0408 }
0409
0410 static int asoc_simple_parse_dai(struct device_node *ep,
0411 struct snd_soc_dai_link_component *dlc,
0412 int *is_single_link)
0413 {
0414 struct device_node *node;
0415 struct of_phandle_args args;
0416 int ret;
0417
0418 if (!ep)
0419 return 0;
0420
0421 node = of_graph_get_port_parent(ep);
0422
0423
0424 args.np = node;
0425 args.args[0] = graph_get_dai_id(ep);
0426 args.args_count = (of_graph_get_endpoint_count(node) > 1);
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447 ret = snd_soc_get_dai_name(&args, &dlc->dai_name);
0448 if (ret < 0) {
0449 of_node_put(node);
0450 return ret;
0451 }
0452
0453 dlc->of_node = node;
0454
0455 if (is_single_link)
0456 *is_single_link = of_graph_get_endpoint_count(node) == 1;
0457
0458 return 0;
0459 }
0460
0461 static void graph_parse_convert(struct device_node *ep,
0462 struct simple_dai_props *props)
0463 {
0464 struct device_node *port = of_get_parent(ep);
0465 struct device_node *ports = of_get_parent(port);
0466 struct asoc_simple_data *adata = &props->adata;
0467
0468 if (of_node_name_eq(ports, "ports"))
0469 asoc_simple_parse_convert(ports, NULL, adata);
0470 asoc_simple_parse_convert(port, NULL, adata);
0471 asoc_simple_parse_convert(ep, NULL, adata);
0472
0473 of_node_put(port);
0474 of_node_put(ports);
0475 }
0476
0477 static void graph_parse_mclk_fs(struct device_node *ep,
0478 struct simple_dai_props *props)
0479 {
0480 struct device_node *port = of_get_parent(ep);
0481 struct device_node *ports = of_get_parent(port);
0482
0483 if (of_node_name_eq(ports, "ports"))
0484 of_property_read_u32(ports, "mclk-fs", &props->mclk_fs);
0485 of_property_read_u32(port, "mclk-fs", &props->mclk_fs);
0486 of_property_read_u32(ep, "mclk-fs", &props->mclk_fs);
0487
0488 of_node_put(port);
0489 of_node_put(ports);
0490 }
0491
0492 static int __graph_parse_node(struct asoc_simple_priv *priv,
0493 enum graph_type gtype,
0494 struct device_node *ep,
0495 struct link_info *li,
0496 int is_cpu, int idx)
0497 {
0498 struct device *dev = simple_priv_to_dev(priv);
0499 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
0500 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
0501 struct snd_soc_dai_link_component *dlc;
0502 struct asoc_simple_dai *dai;
0503 int ret, is_single_links = 0;
0504
0505 if (is_cpu) {
0506 dlc = asoc_link_to_cpu(dai_link, idx);
0507 dai = simple_props_to_dai_cpu(dai_props, idx);
0508 } else {
0509 dlc = asoc_link_to_codec(dai_link, idx);
0510 dai = simple_props_to_dai_codec(dai_props, idx);
0511 }
0512
0513 graph_parse_mclk_fs(ep, dai_props);
0514
0515 ret = asoc_simple_parse_dai(ep, dlc, &is_single_links);
0516 if (ret < 0)
0517 return ret;
0518
0519 ret = asoc_simple_parse_tdm(ep, dai);
0520 if (ret < 0)
0521 return ret;
0522
0523 ret = asoc_simple_parse_tdm_width_map(dev, ep, dai);
0524 if (ret < 0)
0525 return ret;
0526
0527 ret = asoc_simple_parse_clk(dev, ep, dai, dlc);
0528 if (ret < 0)
0529 return ret;
0530
0531
0532
0533
0534 if (!dai_link->name) {
0535 struct snd_soc_dai_link_component *cpus = dlc;
0536 struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, idx);
0537 char *cpu_multi = "";
0538 char *codec_multi = "";
0539
0540 if (dai_link->num_cpus > 1)
0541 cpu_multi = "_multi";
0542 if (dai_link->num_codecs > 1)
0543 codec_multi = "_multi";
0544
0545 switch (gtype) {
0546 case GRAPH_NORMAL:
0547
0548 if (is_cpu)
0549 asoc_simple_set_dailink_name(dev, dai_link, "%s%s-%s%s",
0550 cpus->dai_name, cpu_multi,
0551 codecs->dai_name, codec_multi);
0552 break;
0553 case GRAPH_DPCM:
0554 if (is_cpu)
0555 asoc_simple_set_dailink_name(dev, dai_link, "fe.%pOFP.%s%s",
0556 cpus->of_node, cpus->dai_name, cpu_multi);
0557 else
0558 asoc_simple_set_dailink_name(dev, dai_link, "be.%pOFP.%s%s",
0559 codecs->of_node, codecs->dai_name, codec_multi);
0560 break;
0561 case GRAPH_C2C:
0562
0563 if (is_cpu)
0564 asoc_simple_set_dailink_name(dev, dai_link, "c2c.%s%s-%s%s",
0565 cpus->dai_name, cpu_multi,
0566 codecs->dai_name, codec_multi);
0567 break;
0568 default:
0569 break;
0570 }
0571 }
0572
0573
0574
0575
0576
0577 if (!is_cpu && gtype == GRAPH_DPCM) {
0578 struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, idx);
0579 struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, idx);
0580 struct device_node *rport = of_get_parent(ep);
0581 struct device_node *rports = of_get_parent(rport);
0582
0583 if (of_node_name_eq(rports, "ports"))
0584 snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix");
0585 snd_soc_of_parse_node_prefix(rport, cconf, codecs->of_node, "prefix");
0586
0587 of_node_put(rport);
0588 of_node_put(rports);
0589 }
0590
0591 if (is_cpu) {
0592 struct snd_soc_dai_link_component *cpus = dlc;
0593 struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, idx);
0594
0595 asoc_simple_canonicalize_cpu(cpus, is_single_links);
0596 asoc_simple_canonicalize_platform(platforms, cpus);
0597 }
0598
0599 return 0;
0600 }
0601
0602 static int graph_parse_node(struct asoc_simple_priv *priv,
0603 enum graph_type gtype,
0604 struct device_node *port,
0605 struct link_info *li, int is_cpu)
0606 {
0607 struct device_node *ep;
0608 int ret = 0;
0609
0610 if (graph_lnk_is_multi(port)) {
0611 int idx;
0612
0613 of_node_get(port);
0614
0615 for (idx = 0;; idx++) {
0616 ep = graph_get_next_multi_ep(&port);
0617 if (!ep)
0618 break;
0619
0620 ret = __graph_parse_node(priv, gtype, ep,
0621 li, is_cpu, idx);
0622 of_node_put(ep);
0623 if (ret < 0)
0624 break;
0625 }
0626 } else {
0627
0628 ep = port_to_endpoint(port);
0629 ret = __graph_parse_node(priv, gtype, ep, li, is_cpu, 0);
0630 of_node_put(ep);
0631 }
0632
0633 return ret;
0634 }
0635
0636 static void graph_parse_daifmt(struct device_node *node,
0637 unsigned int *daifmt, unsigned int *bit_frame)
0638 {
0639 unsigned int fmt;
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667 *bit_frame |= snd_soc_daifmt_parse_clock_provider_as_bitmap(node, NULL);
0668
0669 #define update_daifmt(name) \
0670 if (!(*daifmt & SND_SOC_DAIFMT_##name##_MASK) && \
0671 (fmt & SND_SOC_DAIFMT_##name##_MASK)) \
0672 *daifmt |= fmt & SND_SOC_DAIFMT_##name##_MASK
0673
0674
0675
0676
0677
0678
0679
0680 fmt = snd_soc_daifmt_parse_format(node, NULL);
0681 update_daifmt(FORMAT);
0682 update_daifmt(CLOCK);
0683 update_daifmt(INV);
0684 }
0685
0686 static void graph_link_init(struct asoc_simple_priv *priv,
0687 struct device_node *port,
0688 struct link_info *li,
0689 int is_cpu_node)
0690 {
0691 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
0692 struct device_node *ep;
0693 struct device_node *ports;
0694 unsigned int daifmt = 0, daiclk = 0;
0695 unsigned int bit_frame = 0;
0696
0697 if (graph_lnk_is_multi(port)) {
0698 of_node_get(port);
0699 ep = graph_get_next_multi_ep(&port);
0700 port = of_get_parent(ep);
0701 } else {
0702 ep = port_to_endpoint(port);
0703 }
0704
0705 ports = of_get_parent(port);
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719 graph_parse_daifmt(ep, &daifmt, &bit_frame);
0720 graph_parse_daifmt(port, &daifmt, &bit_frame);
0721 if (of_node_name_eq(ports, "ports"))
0722 graph_parse_daifmt(ports, &daifmt, &bit_frame);
0723
0724
0725
0726
0727
0728
0729 daiclk = snd_soc_daifmt_clock_provider_from_bitmap(bit_frame);
0730 if (is_cpu_node)
0731 daiclk = snd_soc_daifmt_clock_provider_flipped(daiclk);
0732
0733 dai_link->dai_fmt = daifmt | daiclk;
0734 dai_link->init = asoc_simple_dai_init;
0735 dai_link->ops = &graph_ops;
0736 if (priv->ops)
0737 dai_link->ops = priv->ops;
0738 }
0739
0740 int audio_graph2_link_normal(struct asoc_simple_priv *priv,
0741 struct device_node *lnk,
0742 struct link_info *li)
0743 {
0744 struct device_node *cpu_port = lnk;
0745 struct device_node *cpu_ep = port_to_endpoint(cpu_port);
0746 struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
0747 int ret;
0748
0749
0750
0751
0752
0753
0754 ret = graph_parse_node(priv, GRAPH_NORMAL, codec_port, li, 0);
0755 if (ret < 0)
0756 goto err;
0757
0758
0759
0760
0761 ret = graph_parse_node(priv, GRAPH_NORMAL, cpu_port, li, 1);
0762 if (ret < 0)
0763 goto err;
0764
0765 graph_link_init(priv, cpu_port, li, 1);
0766 err:
0767 of_node_put(codec_port);
0768 of_node_put(cpu_ep);
0769
0770 return ret;
0771 }
0772 EXPORT_SYMBOL_GPL(audio_graph2_link_normal);
0773
0774 int audio_graph2_link_dpcm(struct asoc_simple_priv *priv,
0775 struct device_node *lnk,
0776 struct link_info *li)
0777 {
0778 struct device_node *ep = port_to_endpoint(lnk);
0779 struct device_node *rep = of_graph_get_remote_endpoint(ep);
0780 struct device_node *rport = of_graph_get_remote_port(ep);
0781 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
0782 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
0783 int is_cpu = asoc_graph_is_ports0(lnk);
0784 int ret;
0785
0786 if (is_cpu) {
0787
0788
0789
0790
0791
0792
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802
0803
0804
0805
0806
0807
0808
0809
0810
0811 dai_link->dynamic = 1;
0812 dai_link->dpcm_merged_format = 1;
0813
0814 ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 1);
0815 if (ret)
0816 goto err;
0817 } else {
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844 dai_link->no_pcm = 1;
0845 dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup;
0846
0847 ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 0);
0848 if (ret < 0)
0849 goto err;
0850 }
0851
0852 graph_parse_convert(rep, dai_props);
0853
0854 snd_soc_dai_link_set_capabilities(dai_link);
0855
0856 graph_link_init(priv, rport, li, is_cpu);
0857 err:
0858 of_node_put(ep);
0859 of_node_put(rep);
0860 of_node_put(rport);
0861
0862 return ret;
0863 }
0864 EXPORT_SYMBOL_GPL(audio_graph2_link_dpcm);
0865
0866 int audio_graph2_link_c2c(struct asoc_simple_priv *priv,
0867 struct device_node *lnk,
0868 struct link_info *li)
0869 {
0870 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
0871 struct device_node *port0, *port1, *ports;
0872 struct device_node *codec0_port, *codec1_port;
0873 struct device_node *ep0, *ep1;
0874 u32 val = 0;
0875 int ret = -EINVAL;
0876
0877
0878
0879
0880
0881
0882
0883
0884
0885
0886
0887
0888
0889
0890
0891
0892
0893 of_node_get(lnk);
0894 port0 = lnk;
0895 ports = of_get_parent(port0);
0896 port1 = of_get_next_child(ports, lnk);
0897
0898
0899
0900
0901
0902
0903
0904
0905
0906 of_property_read_u32(ports, "rate", &val);
0907 if (val) {
0908 struct device *dev = simple_priv_to_dev(priv);
0909 struct snd_soc_pcm_stream *c2c_conf;
0910
0911 c2c_conf = devm_kzalloc(dev, sizeof(*c2c_conf), GFP_KERNEL);
0912 if (!c2c_conf)
0913 goto err1;
0914
0915 c2c_conf->formats = SNDRV_PCM_FMTBIT_S32_LE;
0916 c2c_conf->rates = SNDRV_PCM_RATE_8000_384000;
0917 c2c_conf->rate_min =
0918 c2c_conf->rate_max = val;
0919 c2c_conf->channels_min =
0920 c2c_conf->channels_max = 2;
0921
0922 dai_link->params = c2c_conf;
0923 dai_link->num_params = 1;
0924 }
0925
0926 ep0 = port_to_endpoint(port0);
0927 ep1 = port_to_endpoint(port1);
0928
0929 codec0_port = of_graph_get_remote_port(ep0);
0930 codec1_port = of_graph_get_remote_port(ep1);
0931
0932
0933
0934
0935
0936
0937 ret = graph_parse_node(priv, GRAPH_C2C, codec1_port, li, 0);
0938 if (ret < 0)
0939 goto err2;
0940
0941
0942
0943
0944 ret = graph_parse_node(priv, GRAPH_C2C, codec0_port, li, 1);
0945 if (ret < 0)
0946 goto err2;
0947
0948 graph_link_init(priv, codec0_port, li, 1);
0949 err2:
0950 of_node_put(ep0);
0951 of_node_put(ep1);
0952 of_node_put(codec0_port);
0953 of_node_put(codec1_port);
0954 err1:
0955 of_node_put(ports);
0956 of_node_put(port0);
0957 of_node_put(port1);
0958
0959 return ret;
0960 }
0961 EXPORT_SYMBOL_GPL(audio_graph2_link_c2c);
0962
0963 static int graph_link(struct asoc_simple_priv *priv,
0964 struct graph2_custom_hooks *hooks,
0965 enum graph_type gtype,
0966 struct device_node *lnk,
0967 struct link_info *li)
0968 {
0969 struct device *dev = simple_priv_to_dev(priv);
0970 GRAPH2_CUSTOM func = NULL;
0971 int ret = -EINVAL;
0972
0973 switch (gtype) {
0974 case GRAPH_NORMAL:
0975 if (hooks && hooks->custom_normal)
0976 func = hooks->custom_normal;
0977 else
0978 func = audio_graph2_link_normal;
0979 break;
0980 case GRAPH_DPCM:
0981 if (hooks && hooks->custom_dpcm)
0982 func = hooks->custom_dpcm;
0983 else
0984 func = audio_graph2_link_dpcm;
0985 break;
0986 case GRAPH_C2C:
0987 if (hooks && hooks->custom_c2c)
0988 func = hooks->custom_c2c;
0989 else
0990 func = audio_graph2_link_c2c;
0991 break;
0992 default:
0993 break;
0994 }
0995
0996 if (!func) {
0997 dev_err(dev, "non supported gtype (%d)\n", gtype);
0998 goto err;
0999 }
1000
1001 ret = func(priv, lnk, li);
1002 if (ret < 0)
1003 goto err;
1004
1005 li->link++;
1006 err:
1007 return ret;
1008 }
1009
1010 static int graph_counter(struct device_node *lnk)
1011 {
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026 if (graph_lnk_is_multi(lnk))
1027 return of_graph_get_endpoint_count(of_get_parent(lnk)) - 1;
1028
1029
1030
1031 else
1032 return 1;
1033 }
1034
1035 static int graph_count_normal(struct asoc_simple_priv *priv,
1036 struct device_node *lnk,
1037 struct link_info *li)
1038 {
1039 struct device_node *cpu_port = lnk;
1040 struct device_node *cpu_ep = port_to_endpoint(cpu_port);
1041 struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
1042
1043
1044
1045
1046
1047
1048 li->num[li->link].cpus =
1049 li->num[li->link].platforms = graph_counter(cpu_port);
1050 li->num[li->link].codecs = graph_counter(codec_port);
1051
1052 of_node_put(cpu_ep);
1053 of_node_put(codec_port);
1054
1055 return 0;
1056 }
1057
1058 static int graph_count_dpcm(struct asoc_simple_priv *priv,
1059 struct device_node *lnk,
1060 struct link_info *li)
1061 {
1062 struct device_node *ep = port_to_endpoint(lnk);
1063 struct device_node *rport = of_graph_get_remote_port(ep);
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080 if (asoc_graph_is_ports0(lnk)) {
1081 li->num[li->link].cpus = graph_counter(rport);
1082 li->num[li->link].platforms = graph_counter(rport);
1083 } else {
1084 li->num[li->link].codecs = graph_counter(rport);
1085 }
1086
1087 of_node_put(ep);
1088 of_node_put(rport);
1089
1090 return 0;
1091 }
1092
1093 static int graph_count_c2c(struct asoc_simple_priv *priv,
1094 struct device_node *lnk,
1095 struct link_info *li)
1096 {
1097 struct device_node *ports = of_get_parent(lnk);
1098 struct device_node *port0 = lnk;
1099 struct device_node *port1 = of_get_next_child(ports, lnk);
1100 struct device_node *ep0 = port_to_endpoint(port0);
1101 struct device_node *ep1 = port_to_endpoint(port1);
1102 struct device_node *codec0 = of_graph_get_remote_port(ep0);
1103 struct device_node *codec1 = of_graph_get_remote_port(ep1);
1104
1105 of_node_get(lnk);
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115 li->num[li->link].cpus =
1116 li->num[li->link].platforms = graph_counter(codec0);
1117 li->num[li->link].codecs = graph_counter(codec1);
1118
1119 of_node_put(ports);
1120 of_node_put(port1);
1121 of_node_put(ep0);
1122 of_node_put(ep1);
1123 of_node_put(codec0);
1124 of_node_put(codec1);
1125
1126 return 0;
1127 }
1128
1129 static int graph_count(struct asoc_simple_priv *priv,
1130 struct graph2_custom_hooks *hooks,
1131 enum graph_type gtype,
1132 struct device_node *lnk,
1133 struct link_info *li)
1134 {
1135 struct device *dev = simple_priv_to_dev(priv);
1136 GRAPH2_CUSTOM func = NULL;
1137 int ret = -EINVAL;
1138
1139 if (li->link >= SNDRV_MAX_LINKS) {
1140 dev_err(dev, "too many links\n");
1141 return ret;
1142 }
1143
1144 switch (gtype) {
1145 case GRAPH_NORMAL:
1146 func = graph_count_normal;
1147 break;
1148 case GRAPH_DPCM:
1149 func = graph_count_dpcm;
1150 break;
1151 case GRAPH_C2C:
1152 func = graph_count_c2c;
1153 break;
1154 default:
1155 break;
1156 }
1157
1158 if (!func) {
1159 dev_err(dev, "non supported gtype (%d)\n", gtype);
1160 goto err;
1161 }
1162
1163 ret = func(priv, lnk, li);
1164 if (ret < 0)
1165 goto err;
1166
1167 li->link++;
1168 err:
1169 return ret;
1170 }
1171
1172 static int graph_for_each_link(struct asoc_simple_priv *priv,
1173 struct graph2_custom_hooks *hooks,
1174 struct link_info *li,
1175 int (*func)(struct asoc_simple_priv *priv,
1176 struct graph2_custom_hooks *hooks,
1177 enum graph_type gtype,
1178 struct device_node *lnk,
1179 struct link_info *li))
1180 {
1181 struct of_phandle_iterator it;
1182 struct device *dev = simple_priv_to_dev(priv);
1183 struct device_node *node = dev->of_node;
1184 struct device_node *lnk;
1185 enum graph_type gtype;
1186 int rc, ret;
1187
1188
1189 of_for_each_phandle(&it, rc, node, "links", NULL, 0) {
1190 lnk = it.node;
1191
1192 gtype = graph_get_type(priv, lnk);
1193
1194 ret = func(priv, hooks, gtype, lnk, li);
1195 if (ret < 0)
1196 return ret;
1197 }
1198
1199 return 0;
1200 }
1201
1202 int audio_graph2_parse_of(struct asoc_simple_priv *priv, struct device *dev,
1203 struct graph2_custom_hooks *hooks)
1204 {
1205 struct snd_soc_card *card = simple_priv_to_card(priv);
1206 struct link_info *li;
1207 int ret;
1208
1209 li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
1210 if (!li)
1211 return -ENOMEM;
1212
1213 card->probe = asoc_graph_card_probe;
1214 card->owner = THIS_MODULE;
1215 card->dev = dev;
1216
1217 if ((hooks) && (hooks)->hook_pre) {
1218 ret = (hooks)->hook_pre(priv);
1219 if (ret < 0)
1220 goto err;
1221 }
1222
1223 ret = graph_for_each_link(priv, hooks, li, graph_count);
1224 if (!li->link)
1225 ret = -EINVAL;
1226 if (ret < 0)
1227 goto err;
1228
1229 ret = asoc_simple_init_priv(priv, li);
1230 if (ret < 0)
1231 goto err;
1232
1233 priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW);
1234 if (IS_ERR(priv->pa_gpio)) {
1235 ret = PTR_ERR(priv->pa_gpio);
1236 dev_err(dev, "failed to get amplifier gpio: %d\n", ret);
1237 goto err;
1238 }
1239
1240 ret = asoc_simple_parse_widgets(card, NULL);
1241 if (ret < 0)
1242 goto err;
1243
1244 ret = asoc_simple_parse_routing(card, NULL);
1245 if (ret < 0)
1246 goto err;
1247
1248 memset(li, 0, sizeof(*li));
1249 ret = graph_for_each_link(priv, hooks, li, graph_link);
1250 if (ret < 0)
1251 goto err;
1252
1253 ret = asoc_simple_parse_card_name(card, NULL);
1254 if (ret < 0)
1255 goto err;
1256
1257 snd_soc_card_set_drvdata(card, priv);
1258
1259 if ((hooks) && (hooks)->hook_post) {
1260 ret = (hooks)->hook_post(priv);
1261 if (ret < 0)
1262 goto err;
1263 }
1264
1265 asoc_simple_debug_info(priv);
1266
1267 ret = devm_snd_soc_register_card(dev, card);
1268 err:
1269 devm_kfree(dev, li);
1270
1271 if (ret < 0)
1272 dev_err_probe(dev, ret, "parse error\n");
1273
1274 if (ret == 0)
1275 dev_warn(dev, "Audio Graph Card2 is still under Experimental stage\n");
1276
1277 return ret;
1278 }
1279 EXPORT_SYMBOL_GPL(audio_graph2_parse_of);
1280
1281 static int graph_probe(struct platform_device *pdev)
1282 {
1283 struct asoc_simple_priv *priv;
1284 struct device *dev = &pdev->dev;
1285
1286
1287 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1288 if (!priv)
1289 return -ENOMEM;
1290
1291 return audio_graph2_parse_of(priv, dev, NULL);
1292 }
1293
1294 static const struct of_device_id graph_of_match[] = {
1295 { .compatible = "audio-graph-card2", },
1296 {},
1297 };
1298 MODULE_DEVICE_TABLE(of, graph_of_match);
1299
1300 static struct platform_driver graph_card = {
1301 .driver = {
1302 .name = "asoc-audio-graph-card2",
1303 .pm = &snd_soc_pm_ops,
1304 .of_match_table = graph_of_match,
1305 },
1306 .probe = graph_probe,
1307 .remove = asoc_simple_remove,
1308 };
1309 module_platform_driver(graph_card);
1310
1311 MODULE_ALIAS("platform:asoc-audio-graph-card2");
1312 MODULE_LICENSE("GPL v2");
1313 MODULE_DESCRIPTION("ASoC Audio Graph Card2");
1314 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");