Linux Audio

Check our new training course

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