162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// ctu.c
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include "rsnd.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#define CTU_NAME_SIZE	16
1062306a36Sopenharmony_ci#define CTU_NAME "ctu"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/*
1362306a36Sopenharmony_ci * User needs to setup CTU by amixer, and its settings are
1462306a36Sopenharmony_ci * based on below registers
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci * CTUn_CPMDR : amixser set "CTU Pass"
1762306a36Sopenharmony_ci * CTUn_SV0xR : amixser set "CTU SV0"
1862306a36Sopenharmony_ci * CTUn_SV1xR : amixser set "CTU SV1"
1962306a36Sopenharmony_ci * CTUn_SV2xR : amixser set "CTU SV2"
2062306a36Sopenharmony_ci * CTUn_SV3xR : amixser set "CTU SV3"
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * [CTU Pass]
2362306a36Sopenharmony_ci * 0000: default
2462306a36Sopenharmony_ci * 0001: Connect input data of channel 0
2562306a36Sopenharmony_ci * 0010: Connect input data of channel 1
2662306a36Sopenharmony_ci * 0011: Connect input data of channel 2
2762306a36Sopenharmony_ci * 0100: Connect input data of channel 3
2862306a36Sopenharmony_ci * 0101: Connect input data of channel 4
2962306a36Sopenharmony_ci * 0110: Connect input data of channel 5
3062306a36Sopenharmony_ci * 0111: Connect input data of channel 6
3162306a36Sopenharmony_ci * 1000: Connect input data of channel 7
3262306a36Sopenharmony_ci * 1001: Connect calculated data by scale values of matrix row 0
3362306a36Sopenharmony_ci * 1010: Connect calculated data by scale values of matrix row 1
3462306a36Sopenharmony_ci * 1011: Connect calculated data by scale values of matrix row 2
3562306a36Sopenharmony_ci * 1100: Connect calculated data by scale values of matrix row 3
3662306a36Sopenharmony_ci *
3762306a36Sopenharmony_ci * [CTU SVx]
3862306a36Sopenharmony_ci * [Output0] = [SV00, SV01, SV02, SV03, SV04, SV05, SV06, SV07]
3962306a36Sopenharmony_ci * [Output1] = [SV10, SV11, SV12, SV13, SV14, SV15, SV16, SV17]
4062306a36Sopenharmony_ci * [Output2] = [SV20, SV21, SV22, SV23, SV24, SV25, SV26, SV27]
4162306a36Sopenharmony_ci * [Output3] = [SV30, SV31, SV32, SV33, SV34, SV35, SV36, SV37]
4262306a36Sopenharmony_ci * [Output4] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
4362306a36Sopenharmony_ci * [Output5] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
4462306a36Sopenharmony_ci * [Output6] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
4562306a36Sopenharmony_ci * [Output7] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
4662306a36Sopenharmony_ci *
4762306a36Sopenharmony_ci * [SVxx]
4862306a36Sopenharmony_ci * Plus					Minus
4962306a36Sopenharmony_ci * value	time		dB	value		time		dB
5062306a36Sopenharmony_ci * -----------------------------------------------------------------------
5162306a36Sopenharmony_ci * H'7F_FFFF	2		6	H'80_0000	2		6
5262306a36Sopenharmony_ci * ...
5362306a36Sopenharmony_ci * H'40_0000	1		0	H'C0_0000	1		0
5462306a36Sopenharmony_ci * ...
5562306a36Sopenharmony_ci * H'00_0001	2.38 x 10^-7	-132
5662306a36Sopenharmony_ci * H'00_0000	0		Mute	H'FF_FFFF	2.38 x 10^-7	-132
5762306a36Sopenharmony_ci *
5862306a36Sopenharmony_ci *
5962306a36Sopenharmony_ci * Ex) Input ch -> Output ch
6062306a36Sopenharmony_ci *	1ch     ->  0ch
6162306a36Sopenharmony_ci *	0ch     ->  1ch
6262306a36Sopenharmony_ci *
6362306a36Sopenharmony_ci *	amixer set "CTU Reset" on
6462306a36Sopenharmony_ci *	amixer set "CTU Pass" 9,10
6562306a36Sopenharmony_ci *	amixer set "CTU SV0" 0,4194304
6662306a36Sopenharmony_ci *	amixer set "CTU SV1" 4194304,0
6762306a36Sopenharmony_ci * or
6862306a36Sopenharmony_ci *	amixer set "CTU Reset" on
6962306a36Sopenharmony_ci *	amixer set "CTU Pass" 2,1
7062306a36Sopenharmony_ci */
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistruct rsnd_ctu {
7362306a36Sopenharmony_ci	struct rsnd_mod mod;
7462306a36Sopenharmony_ci	struct rsnd_kctrl_cfg_m pass;
7562306a36Sopenharmony_ci	struct rsnd_kctrl_cfg_m sv[4];
7662306a36Sopenharmony_ci	struct rsnd_kctrl_cfg_s reset;
7762306a36Sopenharmony_ci	int channels;
7862306a36Sopenharmony_ci	u32 flags;
7962306a36Sopenharmony_ci};
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci#define KCTRL_INITIALIZED	(1 << 0)
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci#define rsnd_ctu_nr(priv) ((priv)->ctu_nr)
8462306a36Sopenharmony_ci#define for_each_rsnd_ctu(pos, priv, i)					\
8562306a36Sopenharmony_ci	for ((i) = 0;							\
8662306a36Sopenharmony_ci	     ((i) < rsnd_ctu_nr(priv)) &&				\
8762306a36Sopenharmony_ci		     ((pos) = (struct rsnd_ctu *)(priv)->ctu + i);	\
8862306a36Sopenharmony_ci	     i++)
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#define rsnd_mod_to_ctu(_mod)	\
9162306a36Sopenharmony_ci	container_of((_mod), struct rsnd_ctu, mod)
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci#define rsnd_ctu_get(priv, id) ((struct rsnd_ctu *)(priv->ctu) + id)
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic void rsnd_ctu_activation(struct rsnd_mod *mod)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	rsnd_mod_write(mod, CTU_SWRSR, 0);
9862306a36Sopenharmony_ci	rsnd_mod_write(mod, CTU_SWRSR, 1);
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic void rsnd_ctu_halt(struct rsnd_mod *mod)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	rsnd_mod_write(mod, CTU_CTUIR, 1);
10462306a36Sopenharmony_ci	rsnd_mod_write(mod, CTU_SWRSR, 0);
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistatic int rsnd_ctu_probe_(struct rsnd_mod *mod,
10862306a36Sopenharmony_ci			   struct rsnd_dai_stream *io,
10962306a36Sopenharmony_ci			   struct rsnd_priv *priv)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	return rsnd_cmd_attach(io, rsnd_mod_id(mod));
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cistatic void rsnd_ctu_value_init(struct rsnd_dai_stream *io,
11562306a36Sopenharmony_ci			       struct rsnd_mod *mod)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
11862306a36Sopenharmony_ci	u32 cpmdr = 0;
11962306a36Sopenharmony_ci	u32 scmdr = 0;
12062306a36Sopenharmony_ci	int i, j;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	for (i = 0; i < RSND_MAX_CHANNELS; i++) {
12362306a36Sopenharmony_ci		u32 val = rsnd_kctrl_valm(ctu->pass, i);
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci		cpmdr |= val << (28 - (i * 4));
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci		if ((val > 0x8) && (scmdr < (val - 0x8)))
12862306a36Sopenharmony_ci			scmdr = val - 0x8;
12962306a36Sopenharmony_ci	}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	rsnd_mod_write(mod, CTU_CTUIR, 1);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	rsnd_mod_write(mod, CTU_ADINR, rsnd_runtime_channel_original(io));
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	rsnd_mod_write(mod, CTU_CPMDR, cpmdr);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	rsnd_mod_write(mod, CTU_SCMDR, scmdr);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci		if (i >= scmdr)
14262306a36Sopenharmony_ci			break;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci		for (j = 0; j < RSND_MAX_CHANNELS; j++)
14562306a36Sopenharmony_ci			rsnd_mod_write(mod, CTU_SVxxR(i, j), rsnd_kctrl_valm(ctu->sv[i], j));
14662306a36Sopenharmony_ci	}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	rsnd_mod_write(mod, CTU_CTUIR, 0);
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic void rsnd_ctu_value_reset(struct rsnd_dai_stream *io,
15262306a36Sopenharmony_ci				 struct rsnd_mod *mod)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
15562306a36Sopenharmony_ci	int i;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	if (!rsnd_kctrl_vals(ctu->reset))
15862306a36Sopenharmony_ci		return;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	for (i = 0; i < RSND_MAX_CHANNELS; i++) {
16162306a36Sopenharmony_ci		rsnd_kctrl_valm(ctu->pass, i) = 0;
16262306a36Sopenharmony_ci		rsnd_kctrl_valm(ctu->sv[0],  i) = 0;
16362306a36Sopenharmony_ci		rsnd_kctrl_valm(ctu->sv[1],  i) = 0;
16462306a36Sopenharmony_ci		rsnd_kctrl_valm(ctu->sv[2],  i) = 0;
16562306a36Sopenharmony_ci		rsnd_kctrl_valm(ctu->sv[3],  i) = 0;
16662306a36Sopenharmony_ci	}
16762306a36Sopenharmony_ci	rsnd_kctrl_vals(ctu->reset) = 0;
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic int rsnd_ctu_init(struct rsnd_mod *mod,
17162306a36Sopenharmony_ci			 struct rsnd_dai_stream *io,
17262306a36Sopenharmony_ci			 struct rsnd_priv *priv)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	int ret;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	ret = rsnd_mod_power_on(mod);
17762306a36Sopenharmony_ci	if (ret < 0)
17862306a36Sopenharmony_ci		return ret;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	rsnd_ctu_activation(mod);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	rsnd_ctu_value_init(io, mod);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	return 0;
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_cistatic int rsnd_ctu_quit(struct rsnd_mod *mod,
18862306a36Sopenharmony_ci			 struct rsnd_dai_stream *io,
18962306a36Sopenharmony_ci			 struct rsnd_priv *priv)
19062306a36Sopenharmony_ci{
19162306a36Sopenharmony_ci	rsnd_ctu_halt(mod);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	rsnd_mod_power_off(mod);
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	return 0;
19662306a36Sopenharmony_ci}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cistatic int rsnd_ctu_pcm_new(struct rsnd_mod *mod,
19962306a36Sopenharmony_ci			    struct rsnd_dai_stream *io,
20062306a36Sopenharmony_ci			    struct snd_soc_pcm_runtime *rtd)
20162306a36Sopenharmony_ci{
20262306a36Sopenharmony_ci	struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
20362306a36Sopenharmony_ci	int ret;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	if (rsnd_flags_has(ctu, KCTRL_INITIALIZED))
20662306a36Sopenharmony_ci		return 0;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	/* CTU Pass */
20962306a36Sopenharmony_ci	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU Pass",
21062306a36Sopenharmony_ci			       rsnd_kctrl_accept_anytime,
21162306a36Sopenharmony_ci			       NULL,
21262306a36Sopenharmony_ci			       &ctu->pass, RSND_MAX_CHANNELS,
21362306a36Sopenharmony_ci			       0xC);
21462306a36Sopenharmony_ci	if (ret < 0)
21562306a36Sopenharmony_ci		return ret;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	/* ROW0 */
21862306a36Sopenharmony_ci	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0",
21962306a36Sopenharmony_ci			       rsnd_kctrl_accept_anytime,
22062306a36Sopenharmony_ci			       NULL,
22162306a36Sopenharmony_ci			       &ctu->sv[0], RSND_MAX_CHANNELS,
22262306a36Sopenharmony_ci			       0x00FFFFFF);
22362306a36Sopenharmony_ci	if (ret < 0)
22462306a36Sopenharmony_ci		return ret;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	/* ROW1 */
22762306a36Sopenharmony_ci	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV1",
22862306a36Sopenharmony_ci			       rsnd_kctrl_accept_anytime,
22962306a36Sopenharmony_ci			       NULL,
23062306a36Sopenharmony_ci			       &ctu->sv[1], RSND_MAX_CHANNELS,
23162306a36Sopenharmony_ci			       0x00FFFFFF);
23262306a36Sopenharmony_ci	if (ret < 0)
23362306a36Sopenharmony_ci		return ret;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	/* ROW2 */
23662306a36Sopenharmony_ci	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV2",
23762306a36Sopenharmony_ci			       rsnd_kctrl_accept_anytime,
23862306a36Sopenharmony_ci			       NULL,
23962306a36Sopenharmony_ci			       &ctu->sv[2], RSND_MAX_CHANNELS,
24062306a36Sopenharmony_ci			       0x00FFFFFF);
24162306a36Sopenharmony_ci	if (ret < 0)
24262306a36Sopenharmony_ci		return ret;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	/* ROW3 */
24562306a36Sopenharmony_ci	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV3",
24662306a36Sopenharmony_ci			       rsnd_kctrl_accept_anytime,
24762306a36Sopenharmony_ci			       NULL,
24862306a36Sopenharmony_ci			       &ctu->sv[3], RSND_MAX_CHANNELS,
24962306a36Sopenharmony_ci			       0x00FFFFFF);
25062306a36Sopenharmony_ci	if (ret < 0)
25162306a36Sopenharmony_ci		return ret;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	/* Reset */
25462306a36Sopenharmony_ci	ret = rsnd_kctrl_new_s(mod, io, rtd, "CTU Reset",
25562306a36Sopenharmony_ci			       rsnd_kctrl_accept_anytime,
25662306a36Sopenharmony_ci			       rsnd_ctu_value_reset,
25762306a36Sopenharmony_ci			       &ctu->reset, 1);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	rsnd_flags_set(ctu, KCTRL_INITIALIZED);
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	return ret;
26262306a36Sopenharmony_ci}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistatic int rsnd_ctu_id(struct rsnd_mod *mod)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	/*
26762306a36Sopenharmony_ci	 * ctu00: -> 0, ctu01: -> 0, ctu02: -> 0, ctu03: -> 0
26862306a36Sopenharmony_ci	 * ctu10: -> 1, ctu11: -> 1, ctu12: -> 1, ctu13: -> 1
26962306a36Sopenharmony_ci	 */
27062306a36Sopenharmony_ci	return mod->id / 4;
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistatic int rsnd_ctu_id_sub(struct rsnd_mod *mod)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	/*
27662306a36Sopenharmony_ci	 * ctu00: -> 0, ctu01: -> 1, ctu02: -> 2, ctu03: -> 3
27762306a36Sopenharmony_ci	 * ctu10: -> 0, ctu11: -> 1, ctu12: -> 2, ctu13: -> 3
27862306a36Sopenharmony_ci	 */
27962306a36Sopenharmony_ci	return mod->id % 4;
28062306a36Sopenharmony_ci}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
28362306a36Sopenharmony_cistatic void rsnd_ctu_debug_info(struct seq_file *m,
28462306a36Sopenharmony_ci				struct rsnd_dai_stream *io,
28562306a36Sopenharmony_ci				struct rsnd_mod *mod)
28662306a36Sopenharmony_ci{
28762306a36Sopenharmony_ci	rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
28862306a36Sopenharmony_ci				  0x500 + rsnd_mod_id_raw(mod) * 0x100, 0x100);
28962306a36Sopenharmony_ci}
29062306a36Sopenharmony_ci#define DEBUG_INFO .debug_info = rsnd_ctu_debug_info
29162306a36Sopenharmony_ci#else
29262306a36Sopenharmony_ci#define DEBUG_INFO
29362306a36Sopenharmony_ci#endif
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_cistatic struct rsnd_mod_ops rsnd_ctu_ops = {
29662306a36Sopenharmony_ci	.name		= CTU_NAME,
29762306a36Sopenharmony_ci	.probe		= rsnd_ctu_probe_,
29862306a36Sopenharmony_ci	.init		= rsnd_ctu_init,
29962306a36Sopenharmony_ci	.quit		= rsnd_ctu_quit,
30062306a36Sopenharmony_ci	.pcm_new	= rsnd_ctu_pcm_new,
30162306a36Sopenharmony_ci	.get_status	= rsnd_mod_get_status,
30262306a36Sopenharmony_ci	.id		= rsnd_ctu_id,
30362306a36Sopenharmony_ci	.id_sub		= rsnd_ctu_id_sub,
30462306a36Sopenharmony_ci	.id_cmd		= rsnd_mod_id_raw,
30562306a36Sopenharmony_ci	DEBUG_INFO
30662306a36Sopenharmony_ci};
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cistruct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
30962306a36Sopenharmony_ci{
31062306a36Sopenharmony_ci	if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv)))
31162306a36Sopenharmony_ci		id = 0;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	return rsnd_mod_get(rsnd_ctu_get(priv, id));
31462306a36Sopenharmony_ci}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ciint rsnd_ctu_probe(struct rsnd_priv *priv)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	struct device_node *node;
31962306a36Sopenharmony_ci	struct device_node *np;
32062306a36Sopenharmony_ci	struct device *dev = rsnd_priv_to_dev(priv);
32162306a36Sopenharmony_ci	struct rsnd_ctu *ctu;
32262306a36Sopenharmony_ci	struct clk *clk;
32362306a36Sopenharmony_ci	char name[CTU_NAME_SIZE];
32462306a36Sopenharmony_ci	int i, nr, ret;
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	/* This driver doesn't support Gen1 at this point */
32762306a36Sopenharmony_ci	if (rsnd_is_gen1(priv))
32862306a36Sopenharmony_ci		return 0;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	node = rsnd_ctu_of_node(priv);
33162306a36Sopenharmony_ci	if (!node)
33262306a36Sopenharmony_ci		return 0; /* not used is not error */
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	nr = of_get_child_count(node);
33562306a36Sopenharmony_ci	if (!nr) {
33662306a36Sopenharmony_ci		ret = -EINVAL;
33762306a36Sopenharmony_ci		goto rsnd_ctu_probe_done;
33862306a36Sopenharmony_ci	}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	ctu = devm_kcalloc(dev, nr, sizeof(*ctu), GFP_KERNEL);
34162306a36Sopenharmony_ci	if (!ctu) {
34262306a36Sopenharmony_ci		ret = -ENOMEM;
34362306a36Sopenharmony_ci		goto rsnd_ctu_probe_done;
34462306a36Sopenharmony_ci	}
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	priv->ctu_nr	= nr;
34762306a36Sopenharmony_ci	priv->ctu	= ctu;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	i = 0;
35062306a36Sopenharmony_ci	ret = 0;
35162306a36Sopenharmony_ci	for_each_child_of_node(node, np) {
35262306a36Sopenharmony_ci		ctu = rsnd_ctu_get(priv, i);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci		/*
35562306a36Sopenharmony_ci		 * CTU00, CTU01, CTU02, CTU03 => CTU0
35662306a36Sopenharmony_ci		 * CTU10, CTU11, CTU12, CTU13 => CTU1
35762306a36Sopenharmony_ci		 */
35862306a36Sopenharmony_ci		snprintf(name, CTU_NAME_SIZE, "%s.%d",
35962306a36Sopenharmony_ci			 CTU_NAME, i / 4);
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci		clk = devm_clk_get(dev, name);
36262306a36Sopenharmony_ci		if (IS_ERR(clk)) {
36362306a36Sopenharmony_ci			ret = PTR_ERR(clk);
36462306a36Sopenharmony_ci			of_node_put(np);
36562306a36Sopenharmony_ci			goto rsnd_ctu_probe_done;
36662306a36Sopenharmony_ci		}
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci		ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops,
36962306a36Sopenharmony_ci				    clk, RSND_MOD_CTU, i);
37062306a36Sopenharmony_ci		if (ret) {
37162306a36Sopenharmony_ci			of_node_put(np);
37262306a36Sopenharmony_ci			goto rsnd_ctu_probe_done;
37362306a36Sopenharmony_ci		}
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci		i++;
37662306a36Sopenharmony_ci	}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_cirsnd_ctu_probe_done:
38062306a36Sopenharmony_ci	of_node_put(node);
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	return ret;
38362306a36Sopenharmony_ci}
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_civoid rsnd_ctu_remove(struct rsnd_priv *priv)
38662306a36Sopenharmony_ci{
38762306a36Sopenharmony_ci	struct rsnd_ctu *ctu;
38862306a36Sopenharmony_ci	int i;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	for_each_rsnd_ctu(ctu, priv, i) {
39162306a36Sopenharmony_ci		rsnd_mod_quit(rsnd_mod_get(ctu));
39262306a36Sopenharmony_ci	}
39362306a36Sopenharmony_ci}
394