linux/sound/soc/generic/audio-graph-card2.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// ASoC Audio Graph Card2 support
   4//
   5// Copyright (C) 2020 Renesas Electronics Corp.
   6// Copyright (C) 2020 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
   7//
   8// based on ${LINUX}/sound/soc/generic/audio-graph-card.c
   9#include <linux/clk.h>
  10#include <linux/device.h>
  11#include <linux/gpio.h>
  12#include <linux/gpio/consumer.h>
  13#include <linux/module.h>
  14#include <linux/of.h>
  15#include <linux/of_device.h>
  16#include <linux/of_gpio.h>
  17#include <linux/of_graph.h>
  18#include <linux/platform_device.h>
  19#include <linux/string.h>
  20#include <sound/graph_card.h>
  21
  22/************************************
  23        daifmt
  24 ************************************
  25        ports {
  26                format = "left_j";
  27                port@0 {
  28                        bitclock-master;
  29                        sample0: endpoint@0 {
  30                                frame-master;
  31                        };
  32                        sample1: endpoint@1 {
  33                                format = "i2s";
  34                        };
  35                };
  36                ...
  37        };
  38
  39 You can set daifmt at ports/port/endpoint.
  40 It uses *latest* format, and *share* master settings.
  41 In above case,
  42        sample0: left_j, bitclock-master, frame-master
  43        sample1: i2s,    bitclock-master
  44
  45 If there was no settings, *Codec* will be
  46 bitclock/frame provider as default.
  47 see
  48        graph_parse_daifmt().
  49
  50 ************************************
  51        Normal Audio-Graph
  52 ************************************
  53
  54 CPU <---> Codec
  55
  56 sound {
  57        compatible = "audio-graph-card2";
  58        links = <&cpu>;
  59 };
  60
  61 CPU {
  62        cpu: port {
  63                bitclock-master;
  64                frame-master;
  65                cpu_ep: endpoint { remote-endpoint = <&codec_ep>; }; };
  66 };
  67
  68 Codec {
  69        port {  codec_ep: endpoint { remote-endpoint = <&cpu_ep>; }; };
  70 };
  71
  72 ************************************
  73        Multi-CPU/Codec
  74 ************************************
  75
  76It has connection part (= X) and list part (= y).
  77links indicates connection part of CPU side (= A).
  78
  79            +-+   (A)        +-+
  80 CPU1 --(y) | | <-(X)--(X)-> | | (y)-- Codec1
  81 CPU2 --(y) | |              | | (y)-- Codec2
  82            +-+              +-+
  83
  84        sound {
  85                compatible = "audio-graph-card2";
  86
  87(A)             links = <&mcpu>;
  88
  89                multi {
  90                        ports@0 {
  91(X) (A)                 mcpu:   port@0 { mcpu0_ep: endpoint { remote-endpoint = <&mcodec0_ep>; }; };
  92(y)                             port@1 { mcpu1_ep: endpoint { remote-endpoint = <&cpu1_ep>; }; };
  93(y)                             port@2 { mcpu2_ep: endpoint { remote-endpoint = <&cpu2_ep>; }; };
  94                        };
  95                        ports@1 {
  96(X)                             port@0 { mcodec0_ep: endpoint { remote-endpoint = <&mcpu0_ep>; }; };
  97(y)                             port@1 { mcodec1_ep: endpoint { remote-endpoint = <&codec1_ep>; }; };
  98(y)                             port@2 { mcodec2_ep: endpoint { remote-endpoint = <&codec2_ep>; }; };
  99                        };
 100                };
 101        };
 102
 103 CPU {
 104        ports {
 105                bitclock-master;
 106                frame-master;
 107                port@0 { cpu1_ep: endpoint { remote-endpoint = <&mcpu1_ep>; }; };
 108                port@1 { cpu2_ep: endpoint { remote-endpoint = <&mcpu2_ep>; }; };
 109        };
 110 };
 111
 112 Codec {
 113        ports {
 114                port@0 { codec1_ep: endpoint { remote-endpoint = <&mcodec1_ep>; }; };
 115                port@1 { codec2_ep: endpoint { remote-endpoint = <&mcodec2_ep>; }; };
 116        };
 117 };
 118
 119 ************************************
 120        DPCM
 121 ************************************
 122
 123                DSP
 124           ************
 125 PCM0 <--> * fe0  be0 * <--> DAI0: Codec Headset
 126 PCM1 <--> * fe1  be1 * <--> DAI1: Codec Speakers
 127 PCM2 <--> * fe2  be2 * <--> DAI2: MODEM
 128 PCM3 <--> * fe3  be3 * <--> DAI3: BT
 129           *      be4 * <--> DAI4: DMIC
 130           *      be5 * <--> DAI5: FM
 131           ************
 132
 133 sound {
 134        compatible = "audio-graph-card2";
 135
 136        // indicate routing
 137        routing = "xxx Playback", "xxx Playback",
 138                  "xxx Playback", "xxx Playback",
 139                  "xxx Playback", "xxx Playback";
 140
 141        // indicate all Front-End, Back-End
 142        links = <&fe0, &fe1, ...,
 143                 &be0, &be1, ...>;
 144
 145        dpcm {
 146                // Front-End
 147                ports@0 {
 148                        fe0: port@0 { fe0_ep: endpoint { remote-endpoint = <&pcm0_ep>; }; };
 149                        fe1: port@1 { fe1_ep: endpoint { remote-endpoint = <&pcm1_ep>; }; };
 150                        ...
 151                };
 152                // Back-End
 153                ports@1 {
 154                        be0: port@0 { be0_ep: endpoint { remote-endpoint = <&dai0_ep>; }; };
 155                        be1: port@1 { be1_ep: endpoint { remote-endpoint = <&dai1_ep>; }; };
 156                        ...
 157                };
 158        };
 159 };
 160
 161 CPU {
 162        ports {
 163                bitclock-master;
 164                frame-master;
 165                port@0 { pcm0_ep: endpoint { remote-endpoint = <&fe0_ep>; }; };
 166                port@1 { pcm1_ep: endpoint { remote-endpoint = <&fe1_ep>; }; };
 167                ...
 168        };
 169 };
 170
 171 Codec {
 172        ports {
 173                port@0 { dai0_ep: endpoint { remote-endpoint = <&be0_ep>; }; };
 174                port@1 { dai1_ep: endpoint { remote-endpoint = <&be1_ep>; }; };
 175                ...
 176        };
 177 };
 178
 179 ************************************
 180        Codec to Codec
 181 ************************************
 182
 183 +--+
 184 |  |<-- Codec0 <- IN
 185 |  |--> Codec1 -> OUT
 186 +--+
 187
 188 sound {
 189        compatible = "audio-graph-card2";
 190
 191        routing = "OUT" ,"DAI1 Playback",
 192                  "DAI0 Capture", "IN";
 193
 194        links = <&c2c>;
 195
 196        codec2codec {
 197                ports {
 198                        rate = <48000>;
 199                c2c:    port@0 { c2cf_ep: endpoint { remote-endpoint = <&codec0_ep>; }; };
 200                        port@1 { c2cb_ep: endpoint { remote-endpoint = <&codec1_ep>; }; };
 201        };
 202 };
 203
 204 Codec {
 205        ports {
 206                port@0 {
 207                        bitclock-master;
 208                        frame-master;
 209                         codec0_ep: endpoint { remote-endpoint = <&c2cf_ep>; }; };
 210                port@1 { codec1_ep: endpoint { remote-endpoint = <&c2cb_ep>; }; };
 211        };
 212 };
 213
 214*/
 215
 216enum graph_type {
 217        GRAPH_NORMAL,
 218        GRAPH_DPCM,
 219        GRAPH_C2C,
 220
 221        GRAPH_MULTI,    /* don't use ! Use this only in __graph_get_type() */
 222};
 223
 224#define GRAPH_NODENAME_MULTI    "multi"
 225#define GRAPH_NODENAME_DPCM     "dpcm"
 226#define GRAPH_NODENAME_C2C      "codec2codec"
 227
 228#define port_to_endpoint(port) of_get_child_by_name(port, "endpoint")
 229
 230static enum graph_type __graph_get_type(struct device_node *lnk)
 231{
 232        struct device_node *np;
 233
 234        /*
 235         * target {
 236         *      ports {
 237         * =>           lnk:    port@0 { ... };
 238         *                      port@1 { ... };
 239         *      };
 240         * };
 241         */
 242        np = of_get_parent(lnk);
 243        if (of_node_name_eq(np, "ports"))
 244                np = of_get_parent(np);
 245
 246        if (of_node_name_eq(np, GRAPH_NODENAME_MULTI))
 247                return GRAPH_MULTI;
 248
 249        if (of_node_name_eq(np, GRAPH_NODENAME_DPCM))
 250                return GRAPH_DPCM;
 251
 252        if (of_node_name_eq(np, GRAPH_NODENAME_C2C))
 253                return GRAPH_C2C;
 254
 255        return GRAPH_NORMAL;
 256}
 257
 258static enum graph_type graph_get_type(struct asoc_simple_priv *priv,
 259                                      struct device_node *lnk)
 260{
 261        enum graph_type type = __graph_get_type(lnk);
 262
 263        /* GRAPH_MULTI here means GRAPH_NORMAL */
 264        if (type == GRAPH_MULTI)
 265                type = GRAPH_NORMAL;
 266
 267#ifdef DEBUG
 268        {
 269                struct device *dev = simple_priv_to_dev(priv);
 270                const char *str = "Normal";
 271
 272                switch (type) {
 273                case GRAPH_DPCM:
 274                        if (asoc_graph_is_ports0(lnk))
 275                                str = "DPCM Front-End";
 276                        else
 277                                str = "DPCM Back-End";
 278                        break;
 279                case GRAPH_C2C:
 280                        str = "Codec2Codec";
 281                        break;
 282                default:
 283                        break;
 284                }
 285
 286                dev_dbg(dev, "%pOF (%s)", lnk, str);
 287        }
 288#endif
 289        return type;
 290}
 291
 292static int graph_lnk_is_multi(struct device_node *lnk)
 293{
 294        return __graph_get_type(lnk) == GRAPH_MULTI;
 295}
 296
 297static struct device_node *graph_get_next_multi_ep(struct device_node **port)
 298{
 299        struct device_node *ports = of_get_parent(*port);
 300        struct device_node *ep = NULL;
 301        struct device_node *rep = NULL;
 302
 303        /*
 304         * multi {
 305         *      ports {
 306         * =>   lnk:    port@0 { ... };
 307         *              port@1 { ep { ... = rep0 } };
 308         *              port@2 { ep { ... = rep1 } };
 309         *              ...
 310         *      };
 311         * };
 312         *
 313         * xxx {
 314         *      port@0 { rep0 };
 315         *      port@1 { rep1 };
 316         * };
 317         */
 318        do {
 319                *port = of_get_next_child(ports, *port);
 320                if (!*port)
 321                        break;
 322        } while (!of_node_name_eq(*port, "port"));
 323
 324        if (*port) {
 325                ep  = port_to_endpoint(*port);
 326                rep = of_graph_get_remote_endpoint(ep);
 327        }
 328
 329        of_node_put(ep);
 330        of_node_put(ports);
 331
 332        return rep;
 333}
 334
 335static const struct snd_soc_ops graph_ops = {
 336        .startup        = asoc_simple_startup,
 337        .shutdown       = asoc_simple_shutdown,
 338        .hw_params      = asoc_simple_hw_params,
 339};
 340
 341static int graph_get_dai_id(struct device_node *ep)
 342{
 343        struct device_node *node;
 344        struct device_node *endpoint;
 345        struct of_endpoint info;
 346        int i, id;
 347        const u32 *reg;
 348        int ret;
 349
 350        /* use driver specified DAI ID if exist */
 351        ret = snd_soc_get_dai_id(ep);
 352        if (ret != -ENOTSUPP)
 353                return ret;
 354
 355        /* use endpoint/port reg if exist */
 356        ret = of_graph_parse_endpoint(ep, &info);
 357        if (ret == 0) {
 358                /*
 359                 * Because it will count port/endpoint if it doesn't have "reg".
 360                 * But, we can't judge whether it has "no reg", or "reg = <0>"
 361                 * only of_graph_parse_endpoint().
 362                 * We need to check "reg" property
 363                 */
 364                if (of_get_property(ep,   "reg", NULL))
 365                        return info.id;
 366
 367                node = of_get_parent(ep);
 368                reg = of_get_property(node, "reg", NULL);
 369                of_node_put(node);
 370                if (reg)
 371                        return info.port;
 372        }
 373        node = of_graph_get_port_parent(ep);
 374
 375        /*
 376         * Non HDMI sound case, counting port/endpoint on its DT
 377         * is enough. Let's count it.
 378         */
 379        i = 0;
 380        id = -1;
 381        for_each_endpoint_of_node(node, endpoint) {
 382                if (endpoint == ep)
 383                        id = i;
 384                i++;
 385        }
 386
 387        of_node_put(node);
 388
 389        if (id < 0)
 390                return -ENODEV;
 391
 392        return id;
 393}
 394
 395static int asoc_simple_parse_dai(struct device_node *ep,
 396                                 struct snd_soc_dai_link_component *dlc,
 397                                 int *is_single_link)
 398{
 399        struct device_node *node;
 400        struct of_phandle_args args;
 401        int ret;
 402
 403        if (!ep)
 404                return 0;
 405
 406        node = of_graph_get_port_parent(ep);
 407
 408        /* Get dai->name */
 409        args.np         = node;
 410        args.args[0]    = graph_get_dai_id(ep);
 411        args.args_count = (of_graph_get_endpoint_count(node) > 1);
 412
 413        /*
 414         * FIXME
 415         *
 416         * Here, dlc->dai_name is pointer to CPU/Codec DAI name.
 417         * If user unbinded CPU or Codec driver, but not for Sound Card,
 418         * dlc->dai_name is keeping unbinded CPU or Codec
 419         * driver's pointer.
 420         *
 421         * If user re-bind CPU or Codec driver again, ALSA SoC will try
 422         * to rebind Card via snd_soc_try_rebind_card(), but because of
 423         * above reason, it might can't bind Sound Card.
 424         * Because Sound Card is pointing to released dai_name pointer.
 425         *
 426         * To avoid this rebind Card issue,
 427         * 1) It needs to alloc memory to keep dai_name eventhough
 428         *    CPU or Codec driver was unbinded, or
 429         * 2) user need to rebind Sound Card everytime
 430         *    if he unbinded CPU or Codec.
 431         */
 432        ret = snd_soc_get_dai_name(&args, &dlc->dai_name);
 433        if (ret < 0)
 434                return ret;
 435
 436        dlc->of_node = node;
 437
 438        if (is_single_link)
 439                *is_single_link = of_graph_get_endpoint_count(node) == 1;
 440
 441        return 0;
 442}
 443
 444static void graph_parse_convert(struct device_node *ep,
 445                                struct simple_dai_props *props)
 446{
 447        struct device_node *port = of_get_parent(ep);
 448        struct device_node *ports = of_get_parent(port);
 449        struct asoc_simple_data *adata = &props->adata;
 450
 451        if (of_node_name_eq(ports, "ports"))
 452                asoc_simple_parse_convert(ports, NULL, adata);
 453        asoc_simple_parse_convert(port, NULL, adata);
 454        asoc_simple_parse_convert(ep,   NULL, adata);
 455
 456        of_node_put(port);
 457        of_node_put(ports);
 458}
 459
 460static void graph_parse_mclk_fs(struct device_node *ep,
 461                                struct simple_dai_props *props)
 462{
 463        struct device_node *port        = of_get_parent(ep);
 464        struct device_node *ports       = of_get_parent(port);
 465
 466        if (of_node_name_eq(ports, "ports"))
 467                of_property_read_u32(ports, "mclk-fs", &props->mclk_fs);
 468        of_property_read_u32(port,      "mclk-fs", &props->mclk_fs);
 469        of_property_read_u32(ep,        "mclk-fs", &props->mclk_fs);
 470
 471        of_node_put(port);
 472        of_node_put(ports);
 473}
 474
 475static int __graph_parse_node(struct asoc_simple_priv *priv,
 476                              enum graph_type gtype,
 477                              struct device_node *ep,
 478                              struct link_info *li,
 479                              int is_cpu, int idx)
 480{
 481        struct device *dev = simple_priv_to_dev(priv);
 482        struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
 483        struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
 484        struct snd_soc_dai_link_component *dlc;
 485        struct asoc_simple_dai *dai;
 486        int ret, is_single_links = 0;
 487
 488        if (is_cpu) {
 489                dlc = asoc_link_to_cpu(dai_link, idx);
 490                dai = simple_props_to_dai_cpu(dai_props, idx);
 491        } else {
 492                dlc = asoc_link_to_codec(dai_link, idx);
 493                dai = simple_props_to_dai_codec(dai_props, idx);
 494        }
 495
 496        graph_parse_mclk_fs(ep, dai_props);
 497
 498        ret = asoc_simple_parse_dai(ep, dlc, &is_single_links);
 499        if (ret < 0)
 500                return ret;
 501
 502        ret = asoc_simple_parse_tdm(ep, dai);
 503        if (ret < 0)
 504                return ret;
 505
 506        ret = asoc_simple_parse_tdm_width_map(dev, ep, dai);
 507        if (ret < 0)
 508                return ret;
 509
 510        ret = asoc_simple_parse_clk(dev, ep, dai, dlc);
 511        if (ret < 0)
 512                return ret;
 513
 514        /*
 515         * set DAI Name
 516         */
 517        if (!dai_link->name) {
 518                struct snd_soc_dai_link_component *cpus = dlc;
 519                struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, idx);
 520                char *cpu_multi   = "";
 521                char *codec_multi = "";
 522
 523                if (dai_link->num_cpus > 1)
 524                        cpu_multi = "_multi";
 525                if (dai_link->num_codecs > 1)
 526                        codec_multi = "_multi";
 527
 528                switch (gtype) {
 529                case GRAPH_NORMAL:
 530                        /* run is_cpu only. see audio_graph2_link_normal() */
 531                        if (is_cpu)
 532                                asoc_simple_set_dailink_name(dev, dai_link, "%s%s-%s%s",
 533                                                               cpus->dai_name,   cpu_multi,
 534                                                             codecs->dai_name, codec_multi);
 535                        break;
 536                case GRAPH_DPCM:
 537                        if (is_cpu)
 538                                asoc_simple_set_dailink_name(dev, dai_link, "fe.%pOFP.%s%s",
 539                                                cpus->of_node, cpus->dai_name, cpu_multi);
 540                        else
 541                                asoc_simple_set_dailink_name(dev, dai_link, "be.%pOFP.%s%s",
 542                                                codecs->of_node, codecs->dai_name, codec_multi);
 543                        break;
 544                case GRAPH_C2C:
 545                        /* run is_cpu only. see audio_graph2_link_c2c() */
 546                        if (is_cpu)
 547                                asoc_simple_set_dailink_name(dev, dai_link, "c2c.%s%s-%s%s",
 548                                                             cpus->dai_name,   cpu_multi,
 549                                                             codecs->dai_name, codec_multi);
 550                        break;
 551                default:
 552                        break;
 553                }
 554        }
 555
 556        /*
 557         * Check "prefix" from top node
 558         * if DPCM-BE case
 559         */
 560        if (!is_cpu && gtype == GRAPH_DPCM) {
 561                struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, idx);
 562                struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, idx);
 563                struct device_node *rport  = of_get_parent(ep);
 564                struct device_node *rports = of_get_parent(rport);
 565
 566                if (of_node_name_eq(rports, "ports"))
 567                        snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix");
 568                snd_soc_of_parse_node_prefix(rport,  cconf, codecs->of_node, "prefix");
 569
 570                of_node_put(rport);
 571                of_node_put(rports);
 572        }
 573
 574        if (is_cpu) {
 575                struct snd_soc_dai_link_component *cpus = dlc;
 576                struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, idx);
 577
 578                asoc_simple_canonicalize_cpu(cpus, is_single_links);
 579                asoc_simple_canonicalize_platform(platforms, cpus);
 580        }
 581
 582        return 0;
 583}
 584
 585static int graph_parse_node(struct asoc_simple_priv *priv,
 586                            enum graph_type gtype,
 587                            struct device_node *port,
 588                            struct link_info *li, int is_cpu)
 589{
 590        struct device_node *ep;
 591        int ret = 0;
 592
 593        if (graph_lnk_is_multi(port)) {
 594                int idx;
 595
 596                of_node_get(port);
 597
 598                for (idx = 0;; idx++) {
 599                        ep = graph_get_next_multi_ep(&port);
 600                        if (!ep)
 601                                break;
 602
 603                        ret = __graph_parse_node(priv, gtype, ep,
 604                                                 li, is_cpu, idx);
 605                        of_node_put(ep);
 606                        if (ret < 0)
 607                                break;
 608                }
 609        } else {
 610                /* Single CPU / Codec */
 611                ep = port_to_endpoint(port);
 612                ret = __graph_parse_node(priv, gtype, ep, li, is_cpu, 0);
 613                of_node_put(ep);
 614        }
 615
 616        return ret;
 617}
 618
 619static void graph_parse_daifmt(struct device_node *node,
 620                               unsigned int *daifmt, unsigned int *bit_frame)
 621{
 622        unsigned int fmt;
 623
 624        /*
 625         * see also above "daifmt" explanation
 626         * and samples.
 627         */
 628
 629        /*
 630         *      ports {
 631         * (A)
 632         *              port {
 633         * (B)
 634         *                      endpoint {
 635         * (C)
 636         *                      };
 637         *              };
 638         *      };
 639         * };
 640         */
 641
 642        /*
 643         * clock_provider:
 644         *
 645         * It can be judged it is provider
 646         * if (A) or (B) or (C) has bitclock-master / frame-master flag.
 647         *
 648         * use "or"
 649         */
 650        *bit_frame |= snd_soc_daifmt_parse_clock_provider_as_bitmap(node, NULL);
 651
 652#define update_daifmt(name)                                     \
 653        if (!(*daifmt & SND_SOC_DAIFMT_##name##_MASK) &&        \
 654                 (fmt & SND_SOC_DAIFMT_##name##_MASK))          \
 655                *daifmt |= fmt & SND_SOC_DAIFMT_##name##_MASK
 656
 657        /*
 658         * format
 659         *
 660         * This function is called by (C) -> (B) -> (A) order.
 661         * Set if applicable part was not yet set.
 662         */
 663        fmt = snd_soc_daifmt_parse_format(node, NULL);
 664        update_daifmt(FORMAT);
 665        update_daifmt(CLOCK);
 666        update_daifmt(INV);
 667}
 668
 669static void graph_link_init(struct asoc_simple_priv *priv,
 670                            struct device_node *port,
 671                            struct link_info *li,
 672                            int is_cpu_node)
 673{
 674        struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
 675        struct device_node *ep;
 676        struct device_node *ports;
 677        unsigned int daifmt = 0, daiclk = 0;
 678        unsigned int bit_frame = 0;
 679
 680        if (graph_lnk_is_multi(port)) {
 681                of_node_get(port);
 682                ep = graph_get_next_multi_ep(&port);
 683                port = of_get_parent(ep);
 684        } else {
 685                ep = port_to_endpoint(port);
 686        }
 687
 688        ports = of_get_parent(port);
 689
 690        /*
 691         *      ports {
 692         * (A)
 693         *              port {
 694         * (B)
 695         *                      endpoint {
 696         * (C)
 697         *                      };
 698         *              };
 699         *      };
 700         * };
 701         */
 702        graph_parse_daifmt(ep,    &daifmt, &bit_frame);         /* (C) */
 703        graph_parse_daifmt(port,  &daifmt, &bit_frame);         /* (B) */
 704        if (of_node_name_eq(ports, "ports"))
 705                graph_parse_daifmt(ports, &daifmt, &bit_frame); /* (A) */
 706
 707        /*
 708         * convert bit_frame
 709         * We need to flip clock_provider if it was CPU node,
 710         * because it is Codec base.
 711         */
 712        daiclk = snd_soc_daifmt_clock_provider_from_bitmap(bit_frame);
 713        if (is_cpu_node)
 714                daiclk = snd_soc_daifmt_clock_provider_flipped(daiclk);
 715
 716        dai_link->dai_fmt       = daifmt | daiclk;
 717        dai_link->init          = asoc_simple_dai_init;
 718        dai_link->ops           = &graph_ops;
 719        if (priv->ops)
 720                dai_link->ops   = priv->ops;
 721}
 722
 723int audio_graph2_link_normal(struct asoc_simple_priv *priv,
 724                             struct device_node *lnk,
 725                             struct link_info *li)
 726{
 727        struct device_node *cpu_port = lnk;
 728        struct device_node *cpu_ep = port_to_endpoint(cpu_port);
 729        struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
 730        int ret;
 731
 732        /*
 733         * call Codec first.
 734         * see
 735         *      __graph_parse_node() :: DAI Naming
 736         */
 737        ret = graph_parse_node(priv, GRAPH_NORMAL, codec_port, li, 0);
 738        if (ret < 0)
 739                goto err;
 740
 741        /*
 742         * call CPU, and set DAI Name
 743         */
 744        ret = graph_parse_node(priv, GRAPH_NORMAL, cpu_port, li, 1);
 745        if (ret < 0)
 746                goto err;
 747
 748        graph_link_init(priv, cpu_port, li, 1);
 749err:
 750        of_node_put(codec_port);
 751        of_node_put(cpu_ep);
 752
 753        return ret;
 754}
 755EXPORT_SYMBOL_GPL(audio_graph2_link_normal);
 756
 757int audio_graph2_link_dpcm(struct asoc_simple_priv *priv,
 758                           struct device_node *lnk,
 759                           struct link_info *li)
 760{
 761        struct device_node *ep = port_to_endpoint(lnk);
 762        struct device_node *rep = of_graph_get_remote_endpoint(ep);
 763        struct device_node *rport = of_graph_get_remote_port(ep);
 764        struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
 765        struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
 766        int is_cpu = asoc_graph_is_ports0(lnk);
 767        int ret;
 768
 769        if (is_cpu) {
 770                /*
 771                 * dpcm {
 772                 *      // Front-End
 773                 *      ports@0 {
 774                 * =>           lnk: port@0 { ep: { ... = rep }; };
 775                 *               ...
 776                 *      };
 777                 *      // Back-End
 778                 *      ports@0 {
 779                 *               ...
 780                 *      };
 781                 * };
 782                 *
 783                 * CPU {
 784                 *      rports: ports {
 785                 *              rport: port@0 { rep: { ... = ep } };
 786                 *      }
 787                 * }
 788                 */
 789                /*
 790                 * setup CPU here, Codec is already set as dummy.
 791                 * see
 792                 *      asoc_simple_init_priv()
 793                 */
 794                dai_link->dynamic               = 1;
 795                dai_link->dpcm_merged_format    = 1;
 796
 797                ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 1);
 798                if (ret)
 799                        goto err;
 800        } else {
 801                /*
 802                 * dpcm {
 803                 *      // Front-End
 804                 *      ports@0 {
 805                 *               ...
 806                 *      };
 807                 *      // Back-End
 808                 *      ports@0 {
 809                 * =>           lnk: port@0 { ep: { ... = rep; }; };
 810                 *               ...
 811                 *      };
 812                 * };
 813                 *
 814                 * Codec {
 815                 *      rports: ports {
 816                 *              rport: port@0 { rep: { ... = ep; }; };
 817                 *      }
 818                 * }
 819                 */
 820                /*
 821                 * setup Codec here, CPU is already set as dummy.
 822                 * see
 823                 *      asoc_simple_init_priv()
 824                 */
 825
 826                /* BE settings */
 827                dai_link->no_pcm                = 1;
 828                dai_link->be_hw_params_fixup    = asoc_simple_be_hw_params_fixup;
 829
 830                ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 0);
 831                if (ret < 0)
 832                        goto err;
 833        }
 834
 835        graph_parse_convert(rep, dai_props);
 836
 837        snd_soc_dai_link_set_capabilities(dai_link);
 838
 839        graph_link_init(priv, rport, li, is_cpu);
 840err:
 841        of_node_put(ep);
 842        of_node_put(rep);
 843        of_node_put(rport);
 844
 845        return ret;
 846}
 847EXPORT_SYMBOL_GPL(audio_graph2_link_dpcm);
 848
 849int audio_graph2_link_c2c(struct asoc_simple_priv *priv,
 850                          struct device_node *lnk,
 851                          struct link_info *li)
 852{
 853        struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
 854        struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
 855        struct snd_soc_pcm_stream *c2c_conf = dai_props->c2c_conf;
 856        struct device_node *port0, *port1, *ports;
 857        struct device_node *codec0_port, *codec1_port;
 858        struct device_node *ep0, *ep1;
 859        u32 val;
 860        int ret = -EINVAL;
 861
 862        /*
 863         * codec2codec {
 864         *      ports {
 865         *              rate = <48000>;
 866         * =>   lnk:    port@0 { c2c0_ep: { ... = codec0_ep; }; };
 867         *              port@1 { c2c1_ep: { ... = codec1_ep; }; };
 868         *      };
 869         * };
 870         *
 871         * Codec {
 872         *      ports {
 873         *              port@0 { codec0_ep: ... }; };
 874         *              port@1 { codec1_ep: ... }; };
 875         *      };
 876         * };
 877         */
 878        of_node_get(lnk);
 879        port0 = lnk;
 880        ports = of_get_parent(port0);
 881        port1 = of_get_next_child(ports, lnk);
 882
 883        if (!of_get_property(ports, "rate", &val)) {
 884                struct device *dev = simple_priv_to_dev(priv);
 885
 886                dev_err(dev, "Codec2Codec needs rate settings\n");
 887                goto err1;
 888        }
 889
 890        c2c_conf->formats       = SNDRV_PCM_FMTBIT_S32_LE; /* update ME */
 891        c2c_conf->rate_min      =
 892        c2c_conf->rate_max      = val;
 893        c2c_conf->channels_min  =
 894        c2c_conf->channels_max  = 2; /* update ME */
 895        dai_link->params        = c2c_conf;
 896
 897        ep0 = port_to_endpoint(port0);
 898        ep1 = port_to_endpoint(port1);
 899
 900        codec0_port = of_graph_get_remote_port(ep0);
 901        codec1_port = of_graph_get_remote_port(ep1);
 902
 903        /*
 904         * call Codec first.
 905         * see
 906         *      __graph_parse_node() :: DAI Naming
 907         */
 908        ret = graph_parse_node(priv, GRAPH_C2C, codec1_port, li, 0);
 909        if (ret < 0)
 910                goto err2;
 911
 912        /*
 913         * call CPU, and set DAI Name
 914         */
 915        ret = graph_parse_node(priv, GRAPH_C2C, codec0_port, li, 1);
 916        if (ret < 0)
 917                goto err2;
 918
 919        graph_link_init(priv, codec0_port, li, 1);
 920err2:
 921        of_node_put(ep0);
 922        of_node_put(ep1);
 923        of_node_put(codec0_port);
 924        of_node_put(codec1_port);
 925err1:
 926        of_node_put(ports);
 927        of_node_put(port0);
 928        of_node_put(port1);
 929
 930        return ret;
 931}
 932EXPORT_SYMBOL_GPL(audio_graph2_link_c2c);
 933
 934static int graph_link(struct asoc_simple_priv *priv,
 935                      struct graph2_custom_hooks *hooks,
 936                      enum graph_type gtype,
 937                      struct device_node *lnk,
 938                      struct link_info *li)
 939{
 940        struct device *dev = simple_priv_to_dev(priv);
 941        GRAPH2_CUSTOM func = NULL;
 942        int ret = -EINVAL;
 943
 944        switch (gtype) {
 945        case GRAPH_NORMAL:
 946                if (hooks && hooks->custom_normal)
 947                        func = hooks->custom_normal;
 948                else
 949                        func = audio_graph2_link_normal;
 950                break;
 951        case GRAPH_DPCM:
 952                if (hooks && hooks->custom_dpcm)
 953                        func = hooks->custom_dpcm;
 954                else
 955                        func = audio_graph2_link_dpcm;
 956                break;
 957        case GRAPH_C2C:
 958                if (hooks && hooks->custom_c2c)
 959                        func = hooks->custom_c2c;
 960                else
 961                        func = audio_graph2_link_c2c;
 962                break;
 963        default:
 964                break;
 965        }
 966
 967        if (!func) {
 968                dev_err(dev, "non supported gtype (%d)\n", gtype);
 969                goto err;
 970        }
 971
 972        ret = func(priv, lnk, li);
 973        if (ret < 0)
 974                goto err;
 975
 976        li->link++;
 977err:
 978        return ret;
 979}
 980
 981static int graph_counter(struct device_node *lnk)
 982{
 983        /*
 984         * Multi CPU / Codec
 985         *
 986         * multi {
 987         *      ports {
 988         * =>           lnk:    port@0 { ... };
 989         *                      port@1 { ... };
 990         *                      port@2 { ... };
 991         *                      ...
 992         *      };
 993         * };
 994         *
 995         * ignore first lnk part
 996         */
 997        if (graph_lnk_is_multi(lnk))
 998                return of_graph_get_endpoint_count(of_get_parent(lnk)) - 1;
 999        /*
1000         * Single CPU / Codec
1001         */
1002        else
1003                return 1;
1004}
1005
1006static int graph_count_normal(struct asoc_simple_priv *priv,
1007                              struct device_node *lnk,
1008                              struct link_info *li)
1009{
1010        struct device_node *cpu_port = lnk;
1011        struct device_node *cpu_ep = port_to_endpoint(cpu_port);
1012        struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
1013
1014        /*
1015         *      CPU {
1016         * =>           lnk: port { endpoint { .. }; };
1017         *      };
1018         */
1019        li->num[li->link].cpus          =
1020        li->num[li->link].platforms     = graph_counter(cpu_port);
1021        li->num[li->link].codecs        = graph_counter(codec_port);
1022
1023        of_node_put(cpu_ep);
1024        of_node_put(codec_port);
1025
1026        return 0;
1027}
1028
1029static int graph_count_dpcm(struct asoc_simple_priv *priv,
1030                            struct device_node *lnk,
1031                            struct link_info *li)
1032{
1033        struct device_node *ep = port_to_endpoint(lnk);
1034        struct device_node *rport = of_graph_get_remote_port(ep);
1035
1036        /*
1037         * dpcm {
1038         *      // Front-End
1039         *      ports@0 {
1040         * =>           lnk: port@0 { endpoint { ... }; };
1041         *               ...
1042         *      };
1043         *      // Back-End
1044         *      ports@1 {
1045         * =>           lnk: port@0 { endpoint { ... }; };
1046         *               ...
1047         *      };
1048         * };
1049         */
1050
1051        if (asoc_graph_is_ports0(lnk)) {
1052                li->num[li->link].cpus          = graph_counter(rport); /* FE */
1053                li->num[li->link].platforms     = graph_counter(rport);
1054        } else {
1055                li->num[li->link].codecs        = graph_counter(rport); /* BE */
1056        }
1057
1058        of_node_put(ep);
1059        of_node_put(rport);
1060
1061        return 0;
1062}
1063
1064static int graph_count_c2c(struct asoc_simple_priv *priv,
1065                           struct device_node *lnk,
1066                           struct link_info *li)
1067{
1068        struct device_node *ports = of_get_parent(lnk);
1069        struct device_node *port0 = lnk;
1070        struct device_node *port1 = of_get_next_child(ports, lnk);
1071        struct device_node *ep0 = port_to_endpoint(port0);
1072        struct device_node *ep1 = port_to_endpoint(port1);
1073        struct device_node *codec0 = of_graph_get_remote_port(ep0);
1074        struct device_node *codec1 = of_graph_get_remote_port(ep1);
1075
1076        of_node_get(lnk);
1077
1078        /*
1079         * codec2codec {
1080         *      ports {
1081         * =>   lnk:    port@0 { endpoint { ... }; };
1082         *              port@1 { endpoint { ... }; };
1083         *      };
1084         * };
1085         */
1086        li->num[li->link].cpus          =
1087        li->num[li->link].platforms     = graph_counter(codec0);
1088        li->num[li->link].codecs        = graph_counter(codec1);
1089        li->num[li->link].c2c           = 1;
1090
1091        of_node_put(ports);
1092        of_node_put(port1);
1093        of_node_put(ep0);
1094        of_node_put(ep1);
1095        of_node_put(codec0);
1096        of_node_put(codec1);
1097
1098        return 0;
1099}
1100
1101static int graph_count(struct asoc_simple_priv *priv,
1102                       struct graph2_custom_hooks *hooks,
1103                       enum graph_type gtype,
1104                       struct device_node *lnk,
1105                       struct link_info *li)
1106{
1107        struct device *dev = simple_priv_to_dev(priv);
1108        GRAPH2_CUSTOM func = NULL;
1109        int ret = -EINVAL;
1110
1111        if (li->link >= SNDRV_MAX_LINKS) {
1112                dev_err(dev, "too many links\n");
1113                return ret;
1114        }
1115
1116        switch (gtype) {
1117        case GRAPH_NORMAL:
1118                func = graph_count_normal;
1119                break;
1120        case GRAPH_DPCM:
1121                func = graph_count_dpcm;
1122                break;
1123        case GRAPH_C2C:
1124                func = graph_count_c2c;
1125                break;
1126        default:
1127                break;
1128        }
1129
1130        if (!func) {
1131                dev_err(dev, "non supported gtype (%d)\n", gtype);
1132                goto err;
1133        }
1134
1135        ret = func(priv, lnk, li);
1136        if (ret < 0)
1137                goto err;
1138
1139        li->link++;
1140err:
1141        return ret;
1142}
1143
1144static int graph_for_each_link(struct asoc_simple_priv *priv,
1145                               struct graph2_custom_hooks *hooks,
1146                               struct link_info *li,
1147                               int (*func)(struct asoc_simple_priv *priv,
1148                                           struct graph2_custom_hooks *hooks,
1149                                           enum graph_type gtype,
1150                                           struct device_node *lnk,
1151                                           struct link_info *li))
1152{
1153        struct of_phandle_iterator it;
1154        struct device *dev = simple_priv_to_dev(priv);
1155        struct device_node *node = dev->of_node;
1156        struct device_node *lnk;
1157        enum graph_type gtype;
1158        int rc, ret;
1159
1160        /* loop for all listed CPU port */
1161        of_for_each_phandle(&it, rc, node, "links", NULL, 0) {
1162                lnk = it.node;
1163
1164                gtype = graph_get_type(priv, lnk);
1165
1166                ret = func(priv, hooks, gtype, lnk, li);
1167                if (ret < 0)
1168                        return ret;
1169        }
1170
1171        return 0;
1172}
1173
1174int audio_graph2_parse_of(struct asoc_simple_priv *priv, struct device *dev,
1175                          struct graph2_custom_hooks *hooks)
1176{
1177        struct snd_soc_card *card = simple_priv_to_card(priv);
1178        struct link_info *li;
1179        int ret;
1180
1181        li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
1182        if (!li)
1183                return -ENOMEM;
1184
1185        card->probe     = asoc_graph_card_probe;
1186        card->owner     = THIS_MODULE;
1187        card->dev       = dev;
1188
1189        if ((hooks) && (hooks)->hook_pre) {
1190                ret = (hooks)->hook_pre(priv);
1191                if (ret < 0)
1192                        goto err;
1193        }
1194
1195        ret = graph_for_each_link(priv, hooks, li, graph_count);
1196        if (!li->link)
1197                ret = -EINVAL;
1198        if (ret < 0)
1199                goto err;
1200
1201        ret = asoc_simple_init_priv(priv, li);
1202        if (ret < 0)
1203                goto err;
1204
1205        priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW);
1206        if (IS_ERR(priv->pa_gpio)) {
1207                ret = PTR_ERR(priv->pa_gpio);
1208                dev_err(dev, "failed to get amplifier gpio: %d\n", ret);
1209                goto err;
1210        }
1211
1212        ret = asoc_simple_parse_widgets(card, NULL);
1213        if (ret < 0)
1214                goto err;
1215
1216        ret = asoc_simple_parse_routing(card, NULL);
1217        if (ret < 0)
1218                goto err;
1219
1220        memset(li, 0, sizeof(*li));
1221        ret = graph_for_each_link(priv, hooks, li, graph_link);
1222        if (ret < 0)
1223                goto err;
1224
1225        ret = asoc_simple_parse_card_name(card, NULL);
1226        if (ret < 0)
1227                goto err;
1228
1229        snd_soc_card_set_drvdata(card, priv);
1230
1231        if ((hooks) && (hooks)->hook_post) {
1232                ret = (hooks)->hook_post(priv);
1233                if (ret < 0)
1234                        goto err;
1235        }
1236
1237        asoc_simple_debug_info(priv);
1238
1239        ret = devm_snd_soc_register_card(dev, card);
1240err:
1241        devm_kfree(dev, li);
1242
1243        if (ret < 0)
1244                dev_err_probe(dev, ret, "parse error\n");
1245
1246        if (ret == 0)
1247                dev_warn(dev, "Audio Graph Card2 is still under Experimental stage\n");
1248
1249        return ret;
1250}
1251EXPORT_SYMBOL_GPL(audio_graph2_parse_of);
1252
1253static int graph_probe(struct platform_device *pdev)
1254{
1255        struct asoc_simple_priv *priv;
1256        struct device *dev = &pdev->dev;
1257
1258        /* Allocate the private data and the DAI link array */
1259        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1260        if (!priv)
1261                return -ENOMEM;
1262
1263        return audio_graph2_parse_of(priv, dev, NULL);
1264}
1265
1266static const struct of_device_id graph_of_match[] = {
1267        { .compatible = "audio-graph-card2", },
1268        {},
1269};
1270MODULE_DEVICE_TABLE(of, graph_of_match);
1271
1272static struct platform_driver graph_card = {
1273        .driver = {
1274                .name = "asoc-audio-graph-card2",
1275                .pm = &snd_soc_pm_ops,
1276                .of_match_table = graph_of_match,
1277        },
1278        .probe  = graph_probe,
1279        .remove = asoc_simple_remove,
1280};
1281module_platform_driver(graph_card);
1282
1283MODULE_ALIAS("platform:asoc-audio-graph-card2");
1284MODULE_LICENSE("GPL v2");
1285MODULE_DESCRIPTION("ASoC Audio Graph Card2");
1286MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
1287