cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

audio-graph-card2.c (28777B)


      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@1 { 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@0 { mcodec1_ep: endpoint { remote-endpoint = <&codec1_ep>; }; };
     98(y)				port@1 { 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>");