Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) // ASoC audio graph sound card support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) // Copyright (C) 2016 Renesas Solutions Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) // based on ${LINUX}/sound/soc/generic/simple-card.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/of_gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/of_graph.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <sound/simple_card_utils.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define DPCM_SELECTABLE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define PREFIX	"audio-graph-card,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static int graph_outdrv_event(struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 			      struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 			      int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	struct snd_soc_dapm_context *dapm = w->dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(dapm->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	case SND_SOC_DAPM_POST_PMU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		gpiod_set_value_cansleep(priv->pa_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	case SND_SOC_DAPM_PRE_PMD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		gpiod_set_value_cansleep(priv->pa_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) static const struct snd_soc_dapm_widget graph_dapm_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	SND_SOC_DAPM_OUT_DRV_E("Amplifier", SND_SOC_NOPM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 			       0, 0, NULL, 0, graph_outdrv_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 			       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) static const struct snd_soc_ops graph_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	.startup	= asoc_simple_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	.shutdown	= asoc_simple_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	.hw_params	= asoc_simple_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) static int graph_get_dai_id(struct device_node *ep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	struct device_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	struct device_node *endpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	struct of_endpoint info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	int i, id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	const u32 *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	/* use driver specified DAI ID if exist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	ret = snd_soc_get_dai_id(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	if (ret != -ENOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	/* use endpoint/port reg if exist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	ret = of_graph_parse_endpoint(ep, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		 * Because it will count port/endpoint if it doesn't have "reg".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		 * But, we can't judge whether it has "no reg", or "reg = <0>"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		 * only of_graph_parse_endpoint().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		 * We need to check "reg" property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		if (of_get_property(ep,   "reg", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 			return info.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		node = of_get_parent(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		reg = of_get_property(node, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		if (reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			return info.port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	node = of_graph_get_port_parent(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	 * Non HDMI sound case, counting port/endpoint on its DT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	 * is enough. Let's count it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	id = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	for_each_endpoint_of_node(node, endpoint) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		if (endpoint == ep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 			id = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	if (id < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	return id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static int asoc_simple_parse_dai(struct device_node *ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 				 struct snd_soc_dai_link_component *dlc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 				 int *is_single_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	struct device_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	struct of_phandle_args args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	if (!ep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	node = of_graph_get_port_parent(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	/* Get dai->name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	args.np		= node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	args.args[0]	= graph_get_dai_id(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	args.args_count	= (of_graph_get_endpoint_count(node) > 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	 * FIXME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	 * Here, dlc->dai_name is pointer to CPU/Codec DAI name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	 * If user unbinded CPU or Codec driver, but not for Sound Card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	 * dlc->dai_name is keeping unbinded CPU or Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	 * driver's pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	 * If user re-bind CPU or Codec driver again, ALSA SoC will try
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	 * to rebind Card via snd_soc_try_rebind_card(), but because of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	 * above reason, it might can't bind Sound Card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	 * Because Sound Card is pointing to released dai_name pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	 * To avoid this rebind Card issue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	 * 1) It needs to alloc memory to keep dai_name eventhough
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	 *    CPU or Codec driver was unbinded, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	 * 2) user need to rebind Sound Card everytime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	 *    if he unbinded CPU or Codec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	ret = snd_soc_get_dai_name(&args, &dlc->dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	dlc->of_node = node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	if (is_single_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		*is_single_link = of_graph_get_endpoint_count(node) == 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static void graph_parse_convert(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 				struct device_node *ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 				struct asoc_simple_data *adata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	struct device_node *top = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	struct device_node *port = of_get_parent(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	struct device_node *ports = of_get_parent(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	struct device_node *node = of_graph_get_port_parent(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	asoc_simple_parse_convert(dev, top,   NULL,   adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	asoc_simple_parse_convert(dev, node,  PREFIX, adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	asoc_simple_parse_convert(dev, ports, NULL,   adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	asoc_simple_parse_convert(dev, port,  NULL,   adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	asoc_simple_parse_convert(dev, ep,    NULL,   adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	of_node_put(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	of_node_put(ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static void graph_parse_mclk_fs(struct device_node *top,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 				struct device_node *ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 				struct simple_dai_props *props)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	struct device_node *port	= of_get_parent(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	struct device_node *ports	= of_get_parent(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	struct device_node *node	= of_graph_get_port_parent(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	of_property_read_u32(top,	"mclk-fs", &props->mclk_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	of_property_read_u32(ports,	"mclk-fs", &props->mclk_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	of_property_read_u32(port,	"mclk-fs", &props->mclk_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	of_property_read_u32(ep,	"mclk-fs", &props->mclk_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	of_node_put(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	of_node_put(ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 				  struct device_node *cpu_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 				  struct device_node *codec_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 				  struct link_info *li,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 				  int dup_codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	struct device *dev = simple_priv_to_dev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	struct device_node *top = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	struct device_node *ep = li->cpu ? cpu_ep : codec_ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	struct device_node *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	struct device_node *ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	struct device_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	struct asoc_simple_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	struct snd_soc_dai_link_component *cpus = dai_link->cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	struct snd_soc_dai_link_component *codecs = dai_link->codecs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	/* Do it all CPU endpoint, and 1st Codec endpoint */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	if (!li->cpu && dup_codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	port	= of_get_parent(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	ports	= of_get_parent(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	node	= of_graph_get_port_parent(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	li->link++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	dev_dbg(dev, "link_of DPCM (%pOF)\n", ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	if (li->cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		int is_single_links = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		/* Codec is dummy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		codecs->of_node		= NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		codecs->dai_name	= "snd-soc-dummy-dai";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		codecs->name		= "snd-soc-dummy";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		/* FE settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		dai_link->dynamic		= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		dai_link->dpcm_merged_format	= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		dai =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		dai_props->cpu_dai	= &priv->dais[li->dais++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		ret = asoc_simple_parse_cpu(ep, dai_link, &is_single_links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 			goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		ret = asoc_simple_parse_clk_cpu(dev, ep, dai_link, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 			goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		ret = asoc_simple_set_dailink_name(dev, dai_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 						   "fe.%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 						   cpus->dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 			goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		/* card->num_links includes Codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		asoc_simple_canonicalize_cpu(dai_link, is_single_links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		struct snd_soc_codec_conf *cconf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		/* CPU is dummy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		cpus->of_node		= NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		cpus->dai_name		= "snd-soc-dummy-dai";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		cpus->name		= "snd-soc-dummy";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		/* BE settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		dai_link->no_pcm		= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		dai_link->be_hw_params_fixup	= asoc_simple_be_hw_params_fixup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		dai =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		dai_props->codec_dai	= &priv->dais[li->dais++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		cconf =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		dai_props->codec_conf	= &priv->codec_conf[li->conf++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		ret = asoc_simple_parse_codec(ep, dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 			goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		ret = asoc_simple_parse_clk_codec(dev, ep, dai_link, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 			goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		ret = asoc_simple_set_dailink_name(dev, dai_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 						   "be.%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 						   codecs->dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 			goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		/* check "prefix" from top node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 					      "prefix");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		snd_soc_of_parse_node_prefix(node, cconf, codecs->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 					     PREFIX "prefix");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 					     "prefix");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		snd_soc_of_parse_node_prefix(port, cconf, codecs->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 					     "prefix");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	graph_parse_convert(dev, ep, &dai_props->adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	graph_parse_mclk_fs(top, ep, dai_props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	asoc_simple_canonicalize_platform(dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	ret = asoc_simple_parse_tdm(ep, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 				       NULL, &dai_link->dai_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	snd_soc_dai_link_set_capabilities(dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	dai_link->ops			= &graph_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	dai_link->init			= asoc_simple_dai_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) out_put_node:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	of_node_put(ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	of_node_put(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static int graph_dai_link_of(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 			     struct device_node *cpu_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 			     struct device_node *codec_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 			     struct link_info *li)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	struct device *dev = simple_priv_to_dev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	struct device_node *top = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	struct asoc_simple_dai *cpu_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	struct asoc_simple_dai *codec_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	int ret, single_cpu = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	/* Do it only CPU turn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	if (!li->cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	dev_dbg(dev, "link_of (%pOF)\n", cpu_ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	li->link++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	cpu_dai			=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	dai_props->cpu_dai	= &priv->dais[li->dais++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	codec_dai		=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	dai_props->codec_dai	= &priv->dais[li->dais++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	/* Factor to mclk, used in hw_params() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	graph_parse_mclk_fs(top, cpu_ep,   dai_props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	graph_parse_mclk_fs(top, codec_ep, dai_props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 				       NULL, &dai_link->dai_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	ret = asoc_simple_parse_cpu(cpu_ep, dai_link, &single_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	ret = asoc_simple_parse_codec(codec_ep, dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	ret = asoc_simple_parse_tdm(cpu_ep, cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	ret = asoc_simple_parse_tdm(codec_ep, codec_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	ret = asoc_simple_parse_clk_cpu(dev, cpu_ep, dai_link, cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	ret = asoc_simple_parse_clk_codec(dev, codec_ep, dai_link, codec_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	ret = asoc_simple_set_dailink_name(dev, dai_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 					   "%s-%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 					   dai_link->cpus->dai_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 					   dai_link->codecs->dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	dai_link->ops = &graph_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	dai_link->init = asoc_simple_dai_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	asoc_simple_canonicalize_cpu(dai_link, single_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	asoc_simple_canonicalize_platform(dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static int graph_for_each_link(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 			struct link_info *li,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 			int (*func_noml)(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 					 struct device_node *cpu_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 					 struct device_node *codec_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 					 struct link_info *li),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 			int (*func_dpcm)(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 					 struct device_node *cpu_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 					 struct device_node *codec_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 					 struct link_info *li, int dup_codec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	struct of_phandle_iterator it;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	struct device *dev = simple_priv_to_dev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	struct device_node *node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	struct device_node *cpu_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	struct device_node *cpu_ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	struct device_node *codec_ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	struct device_node *codec_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	struct device_node *codec_port_old = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	struct asoc_simple_data adata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	int rc, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	/* loop for all listed CPU port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		cpu_port = it.node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		cpu_ep	 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		/* loop for all CPU endpoint */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 			cpu_ep = of_get_next_child(cpu_port, cpu_ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 			if (!cpu_ep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 			/* get codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 			codec_ep = of_graph_get_remote_endpoint(cpu_ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 			codec_port = of_get_parent(codec_ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 			/* get convert-xxx property */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 			memset(&adata, 0, sizeof(adata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 			graph_parse_convert(dev, codec_ep, &adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 			graph_parse_convert(dev, cpu_ep,   &adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 			 * It is DPCM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 			 * if Codec port has many endpoints,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 			 * or has convert-xxx property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 			if (dpcm_selectable &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 			    ((of_get_child_count(codec_port) > 1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 			     adata.convert_rate || adata.convert_channels))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 				ret = func_dpcm(priv, cpu_ep, codec_ep, li,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 						(codec_port_old == codec_port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 			/* else normal sound */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 				ret = func_noml(priv, cpu_ep, codec_ep, li);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 			of_node_put(codec_ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 			of_node_put(codec_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 			if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 			codec_port_old = codec_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static int graph_parse_of(struct asoc_simple_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	struct snd_soc_card *card = simple_priv_to_card(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	struct link_info li;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	ret = asoc_simple_parse_widgets(card, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	ret = asoc_simple_parse_routing(card, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	memset(&li, 0, sizeof(li));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	for (li.cpu = 1; li.cpu >= 0; li.cpu--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		 * Detect all CPU first, and Detect all Codec 2nd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		 * In Normal sound case, all DAIs are detected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		 * as "CPU-Codec".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		 * In DPCM sound case,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		 * all CPUs   are detected as "CPU-dummy", and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		 * all Codecs are detected as "dummy-Codec".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		 * To avoid random sub-device numbering,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		 * detect "dummy-Codec" in last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		ret = graph_for_each_link(priv, &li,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 					  graph_dai_link_of,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 					  graph_dai_link_of_dpcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	return asoc_simple_parse_card_name(card, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static int graph_count_noml(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 			    struct device_node *cpu_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 			    struct device_node *codec_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 			    struct link_info *li)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	struct device *dev = simple_priv_to_dev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	li->link += 1; /* 1xCPU-Codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	li->dais += 2; /* 1xCPU + 1xCodec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	dev_dbg(dev, "Count As Normal\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static int graph_count_dpcm(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 			    struct device_node *cpu_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 			    struct device_node *codec_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 			    struct link_info *li,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 			    int dup_codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	struct device *dev = simple_priv_to_dev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	li->link++; /* 1xCPU-dummy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	li->dais++; /* 1xCPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	if (!dup_codec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		li->link++; /* 1xdummy-Codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		li->conf++; /* 1xdummy-Codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		li->dais++; /* 1xCodec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	dev_dbg(dev, "Count As DPCM\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) static void graph_get_dais_count(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 				 struct link_info *li)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	struct device *dev = simple_priv_to_dev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	 * link_num :	number of links.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	 *		CPU-Codec / CPU-dummy / dummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	 * dais_num :	number of DAIs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	 * ccnf_num :	number of codec_conf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	 *		same number for "dummy-Codec"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	 * ex1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	 * CPU0 --- Codec0	link : 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	 * CPU1 --- Codec1	dais : 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	 * CPU2 -/		ccnf : 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	 * CPU3 --- Codec2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	 *	=> 5 links = 2xCPU-Codec + 2xCPU-dummy + 1xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	 *	=> 7 DAIs  = 4xCPU + 3xCodec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	 *	=> 1 ccnf  = 1xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	 * ex2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	 * CPU0 --- Codec0	link : 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	 * CPU1 --- Codec1	dais : 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	 * CPU2 -/		ccnf : 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	 * CPU3 -/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	 *	=> 5 links = 1xCPU-Codec + 3xCPU-dummy + 1xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	 *	=> 6 DAIs  = 4xCPU + 2xCodec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	 *	=> 1 ccnf  = 1xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	 * ex3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	 * CPU0 --- Codec0	link : 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	 * CPU1 -/		dais : 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	 * CPU2 --- Codec1	ccnf : 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	 * CPU3 -/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	 *	=> 6 links = 0xCPU-Codec + 4xCPU-dummy + 2xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	 *	=> 6 DAIs  = 4xCPU + 2xCodec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 	 *	=> 2 ccnf  = 2xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	 * ex4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	 * CPU0 --- Codec0 (convert-rate)	link : 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	 * CPU1 --- Codec1			dais : 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	 *					ccnf : 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	 *	=> 3 links = 1xCPU-Codec + 1xCPU-dummy + 1xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	 *	=> 4 DAIs  = 2xCPU + 2xCodec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 	 *	=> 1 ccnf  = 1xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	graph_for_each_link(priv, li,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 			    graph_count_noml,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 			    graph_count_dpcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	dev_dbg(dev, "link %d, dais %d, ccnf %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 		li->link, li->dais, li->conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) static int graph_card_probe(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 	ret = asoc_simple_init_hp(card, &priv->hp_jack, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	ret = asoc_simple_init_mic(card, &priv->mic_jack, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) static int graph_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	struct asoc_simple_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	struct snd_soc_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	struct link_info li;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	/* Allocate the private data and the DAI link array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	card = simple_priv_to_card(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	card->owner		= THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	card->dev		= dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	card->dapm_widgets	= graph_dapm_widgets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	card->num_dapm_widgets	= ARRAY_SIZE(graph_dapm_widgets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	card->probe		= graph_card_probe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	memset(&li, 0, sizeof(li));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	graph_get_dais_count(priv, &li);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	if (!li.link || !li.dais)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	ret = asoc_simple_init_priv(priv, &li);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	if (IS_ERR(priv->pa_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 		ret = PTR_ERR(priv->pa_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 		dev_err(dev, "failed to get amplifier gpio: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	ret = graph_parse_of(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 		if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 			dev_err(dev, "parse error %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	snd_soc_card_set_drvdata(card, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	asoc_simple_debug_info(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 	ret = devm_snd_soc_register_card(dev, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	asoc_simple_clean_reference(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) static int graph_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 	struct snd_soc_card *card = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	return asoc_simple_clean_reference(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) static const struct of_device_id graph_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 	{ .compatible = "audio-graph-card", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	{ .compatible = "audio-graph-scu-card",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	  .data = (void *)DPCM_SELECTABLE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	{},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) MODULE_DEVICE_TABLE(of, graph_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static struct platform_driver graph_card = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 		.name = "asoc-audio-graph-card",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 		.pm = &snd_soc_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 		.of_match_table = graph_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 	.probe = graph_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 	.remove = graph_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) module_platform_driver(graph_card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) MODULE_ALIAS("platform:asoc-audio-graph-card");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) MODULE_DESCRIPTION("ASoC Audio Graph Sound Card");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");