xref: /linux/sound/soc/renesas/rcar/mix.c (revision 60675d4ca1ef0857e44eba5849b74a3a998d0c0f)
1*c087a94bSLad Prabhakar // SPDX-License-Identifier: GPL-2.0
2*c087a94bSLad Prabhakar //
3*c087a94bSLad Prabhakar // mix.c
4*c087a94bSLad Prabhakar //
5*c087a94bSLad Prabhakar // Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6*c087a94bSLad Prabhakar 
7*c087a94bSLad Prabhakar /*
8*c087a94bSLad Prabhakar  *		    CTUn	MIXn
9*c087a94bSLad Prabhakar  *		    +------+	+------+
10*c087a94bSLad Prabhakar  * [SRC3 / SRC6] -> |CTU n0| ->	[MIX n0| ->
11*c087a94bSLad Prabhakar  * [SRC4 / SRC9] -> |CTU n1| ->	[MIX n1| ->
12*c087a94bSLad Prabhakar  * [SRC0 / SRC1] -> |CTU n2| ->	[MIX n2| ->
13*c087a94bSLad Prabhakar  * [SRC2 / SRC5] -> |CTU n3| ->	[MIX n3| ->
14*c087a94bSLad Prabhakar  *		    +------+	+------+
15*c087a94bSLad Prabhakar  *
16*c087a94bSLad Prabhakar  * ex)
17*c087a94bSLad Prabhakar  *	DAI0 : playback = <&src0 &ctu02 &mix0 &dvc0 &ssi0>;
18*c087a94bSLad Prabhakar  *	DAI1 : playback = <&src2 &ctu03 &mix0 &dvc0 &ssi0>;
19*c087a94bSLad Prabhakar  *
20*c087a94bSLad Prabhakar  * MIX Volume
21*c087a94bSLad Prabhakar  *	amixer set "MIX",0  100%  // DAI0 Volume
22*c087a94bSLad Prabhakar  *	amixer set "MIX",1  100%  // DAI1 Volume
23*c087a94bSLad Prabhakar  *
24*c087a94bSLad Prabhakar  * Volume Ramp
25*c087a94bSLad Prabhakar  *	amixer set "MIX Ramp Up Rate"   "0.125 dB/1 step"
26*c087a94bSLad Prabhakar  *	amixer set "MIX Ramp Down Rate" "4 dB/1 step"
27*c087a94bSLad Prabhakar  *	amixer set "MIX Ramp" on
28*c087a94bSLad Prabhakar  *	aplay xxx.wav &
29*c087a94bSLad Prabhakar  *	amixer set "MIX",0  80%  // DAI0 Volume Down
30*c087a94bSLad Prabhakar  *	amixer set "MIX",1 100%  // DAI1 Volume Up
31*c087a94bSLad Prabhakar  */
32*c087a94bSLad Prabhakar 
33*c087a94bSLad Prabhakar #include "rsnd.h"
34*c087a94bSLad Prabhakar 
35*c087a94bSLad Prabhakar #define MIX_NAME_SIZE	16
36*c087a94bSLad Prabhakar #define MIX_NAME "mix"
37*c087a94bSLad Prabhakar 
38*c087a94bSLad Prabhakar struct rsnd_mix {
39*c087a94bSLad Prabhakar 	struct rsnd_mod mod;
40*c087a94bSLad Prabhakar 	struct rsnd_kctrl_cfg_s volumeA; /* MDBAR */
41*c087a94bSLad Prabhakar 	struct rsnd_kctrl_cfg_s volumeB; /* MDBBR */
42*c087a94bSLad Prabhakar 	struct rsnd_kctrl_cfg_s volumeC; /* MDBCR */
43*c087a94bSLad Prabhakar 	struct rsnd_kctrl_cfg_s volumeD; /* MDBDR */
44*c087a94bSLad Prabhakar 	struct rsnd_kctrl_cfg_s ren;	/* Ramp Enable */
45*c087a94bSLad Prabhakar 	struct rsnd_kctrl_cfg_s rup;	/* Ramp Rate Up */
46*c087a94bSLad Prabhakar 	struct rsnd_kctrl_cfg_s rdw;	/* Ramp Rate Down */
47*c087a94bSLad Prabhakar 	u32 flags;
48*c087a94bSLad Prabhakar };
49*c087a94bSLad Prabhakar 
50*c087a94bSLad Prabhakar #define ONCE_KCTRL_INITIALIZED		(1 << 0)
51*c087a94bSLad Prabhakar #define HAS_VOLA			(1 << 1)
52*c087a94bSLad Prabhakar #define HAS_VOLB			(1 << 2)
53*c087a94bSLad Prabhakar #define HAS_VOLC			(1 << 3)
54*c087a94bSLad Prabhakar #define HAS_VOLD			(1 << 4)
55*c087a94bSLad Prabhakar 
56*c087a94bSLad Prabhakar #define VOL_MAX				0x3ff
57*c087a94bSLad Prabhakar 
58*c087a94bSLad Prabhakar #define rsnd_mod_to_mix(_mod)	\
59*c087a94bSLad Prabhakar 	container_of((_mod), struct rsnd_mix, mod)
60*c087a94bSLad Prabhakar 
61*c087a94bSLad Prabhakar #define rsnd_mix_get(priv, id) ((struct rsnd_mix *)(priv->mix) + id)
62*c087a94bSLad Prabhakar #define rsnd_mix_nr(priv) ((priv)->mix_nr)
63*c087a94bSLad Prabhakar #define for_each_rsnd_mix(pos, priv, i)					\
64*c087a94bSLad Prabhakar 	for ((i) = 0;							\
65*c087a94bSLad Prabhakar 	     ((i) < rsnd_mix_nr(priv)) &&				\
66*c087a94bSLad Prabhakar 		     ((pos) = (struct rsnd_mix *)(priv)->mix + i);	\
67*c087a94bSLad Prabhakar 	     i++)
68*c087a94bSLad Prabhakar 
69*c087a94bSLad Prabhakar static void rsnd_mix_activation(struct rsnd_mod *mod)
70*c087a94bSLad Prabhakar {
71*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_SWRSR, 0);
72*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_SWRSR, 1);
73*c087a94bSLad Prabhakar }
74*c087a94bSLad Prabhakar 
75*c087a94bSLad Prabhakar static void rsnd_mix_halt(struct rsnd_mod *mod)
76*c087a94bSLad Prabhakar {
77*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_MIXIR, 1);
78*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_SWRSR, 0);
79*c087a94bSLad Prabhakar }
80*c087a94bSLad Prabhakar 
81*c087a94bSLad Prabhakar #define rsnd_mix_get_vol(mix, X) \
82*c087a94bSLad Prabhakar 	rsnd_flags_has(mix, HAS_VOL##X) ? \
83*c087a94bSLad Prabhakar 		(VOL_MAX - rsnd_kctrl_vals(mix->volume##X)) : 0
84*c087a94bSLad Prabhakar static void rsnd_mix_volume_parameter(struct rsnd_dai_stream *io,
85*c087a94bSLad Prabhakar 				      struct rsnd_mod *mod)
86*c087a94bSLad Prabhakar {
87*c087a94bSLad Prabhakar 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
88*c087a94bSLad Prabhakar 	struct device *dev = rsnd_priv_to_dev(priv);
89*c087a94bSLad Prabhakar 	struct rsnd_mix *mix = rsnd_mod_to_mix(mod);
90*c087a94bSLad Prabhakar 	u32 volA = rsnd_mix_get_vol(mix, A);
91*c087a94bSLad Prabhakar 	u32 volB = rsnd_mix_get_vol(mix, B);
92*c087a94bSLad Prabhakar 	u32 volC = rsnd_mix_get_vol(mix, C);
93*c087a94bSLad Prabhakar 	u32 volD = rsnd_mix_get_vol(mix, D);
94*c087a94bSLad Prabhakar 
95*c087a94bSLad Prabhakar 	dev_dbg(dev, "MIX A/B/C/D = %02x/%02x/%02x/%02x\n",
96*c087a94bSLad Prabhakar 		volA, volB, volC, volD);
97*c087a94bSLad Prabhakar 
98*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_MDBAR, volA);
99*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_MDBBR, volB);
100*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_MDBCR, volC);
101*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_MDBDR, volD);
102*c087a94bSLad Prabhakar }
103*c087a94bSLad Prabhakar 
104*c087a94bSLad Prabhakar static void rsnd_mix_volume_init(struct rsnd_dai_stream *io,
105*c087a94bSLad Prabhakar 				 struct rsnd_mod *mod)
106*c087a94bSLad Prabhakar {
107*c087a94bSLad Prabhakar 	struct rsnd_mix *mix = rsnd_mod_to_mix(mod);
108*c087a94bSLad Prabhakar 
109*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_MIXIR, 1);
110*c087a94bSLad Prabhakar 
111*c087a94bSLad Prabhakar 	/* General Information */
112*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_ADINR, rsnd_runtime_channel_after_ctu(io));
113*c087a94bSLad Prabhakar 
114*c087a94bSLad Prabhakar 	/* volume step */
115*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_MIXMR, rsnd_kctrl_vals(mix->ren));
116*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_MVPDR, rsnd_kctrl_vals(mix->rup) << 8 |
117*c087a94bSLad Prabhakar 				       rsnd_kctrl_vals(mix->rdw));
118*c087a94bSLad Prabhakar 
119*c087a94bSLad Prabhakar 	/* common volume parameter */
120*c087a94bSLad Prabhakar 	rsnd_mix_volume_parameter(io, mod);
121*c087a94bSLad Prabhakar 
122*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_MIXIR, 0);
123*c087a94bSLad Prabhakar }
124*c087a94bSLad Prabhakar 
125*c087a94bSLad Prabhakar static void rsnd_mix_volume_update(struct rsnd_dai_stream *io,
126*c087a94bSLad Prabhakar 				  struct rsnd_mod *mod)
127*c087a94bSLad Prabhakar {
128*c087a94bSLad Prabhakar 	/* Disable MIX dB setting */
129*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_MDBER, 0);
130*c087a94bSLad Prabhakar 
131*c087a94bSLad Prabhakar 	/* common volume parameter */
132*c087a94bSLad Prabhakar 	rsnd_mix_volume_parameter(io, mod);
133*c087a94bSLad Prabhakar 
134*c087a94bSLad Prabhakar 	/* Enable MIX dB setting */
135*c087a94bSLad Prabhakar 	rsnd_mod_write(mod, MIX_MDBER, 1);
136*c087a94bSLad Prabhakar }
137*c087a94bSLad Prabhakar 
138*c087a94bSLad Prabhakar static int rsnd_mix_probe_(struct rsnd_mod *mod,
139*c087a94bSLad Prabhakar 			   struct rsnd_dai_stream *io,
140*c087a94bSLad Prabhakar 			   struct rsnd_priv *priv)
141*c087a94bSLad Prabhakar {
142*c087a94bSLad Prabhakar 	return rsnd_cmd_attach(io, rsnd_mod_id(mod));
143*c087a94bSLad Prabhakar }
144*c087a94bSLad Prabhakar 
145*c087a94bSLad Prabhakar static int rsnd_mix_init(struct rsnd_mod *mod,
146*c087a94bSLad Prabhakar 			 struct rsnd_dai_stream *io,
147*c087a94bSLad Prabhakar 			 struct rsnd_priv *priv)
148*c087a94bSLad Prabhakar {
149*c087a94bSLad Prabhakar 	int ret;
150*c087a94bSLad Prabhakar 
151*c087a94bSLad Prabhakar 	ret = rsnd_mod_power_on(mod);
152*c087a94bSLad Prabhakar 	if (ret < 0)
153*c087a94bSLad Prabhakar 		return ret;
154*c087a94bSLad Prabhakar 
155*c087a94bSLad Prabhakar 	rsnd_mix_activation(mod);
156*c087a94bSLad Prabhakar 
157*c087a94bSLad Prabhakar 	rsnd_mix_volume_init(io, mod);
158*c087a94bSLad Prabhakar 
159*c087a94bSLad Prabhakar 	rsnd_mix_volume_update(io, mod);
160*c087a94bSLad Prabhakar 
161*c087a94bSLad Prabhakar 	return 0;
162*c087a94bSLad Prabhakar }
163*c087a94bSLad Prabhakar 
164*c087a94bSLad Prabhakar static int rsnd_mix_quit(struct rsnd_mod *mod,
165*c087a94bSLad Prabhakar 			 struct rsnd_dai_stream *io,
166*c087a94bSLad Prabhakar 			 struct rsnd_priv *priv)
167*c087a94bSLad Prabhakar {
168*c087a94bSLad Prabhakar 	rsnd_mix_halt(mod);
169*c087a94bSLad Prabhakar 
170*c087a94bSLad Prabhakar 	rsnd_mod_power_off(mod);
171*c087a94bSLad Prabhakar 
172*c087a94bSLad Prabhakar 	return 0;
173*c087a94bSLad Prabhakar }
174*c087a94bSLad Prabhakar 
175*c087a94bSLad Prabhakar static int rsnd_mix_pcm_new(struct rsnd_mod *mod,
176*c087a94bSLad Prabhakar 			    struct rsnd_dai_stream *io,
177*c087a94bSLad Prabhakar 			    struct snd_soc_pcm_runtime *rtd)
178*c087a94bSLad Prabhakar {
179*c087a94bSLad Prabhakar 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
180*c087a94bSLad Prabhakar 	struct device *dev = rsnd_priv_to_dev(priv);
181*c087a94bSLad Prabhakar 	struct rsnd_mix *mix = rsnd_mod_to_mix(mod);
182*c087a94bSLad Prabhakar 	struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
183*c087a94bSLad Prabhakar 	struct rsnd_kctrl_cfg_s *volume;
184*c087a94bSLad Prabhakar 	int ret;
185*c087a94bSLad Prabhakar 
186*c087a94bSLad Prabhakar 	switch (rsnd_mod_id(src_mod)) {
187*c087a94bSLad Prabhakar 	case 3:
188*c087a94bSLad Prabhakar 	case 6:	/* MDBAR */
189*c087a94bSLad Prabhakar 		volume = &mix->volumeA;
190*c087a94bSLad Prabhakar 		rsnd_flags_set(mix, HAS_VOLA);
191*c087a94bSLad Prabhakar 		break;
192*c087a94bSLad Prabhakar 	case 4:
193*c087a94bSLad Prabhakar 	case 9:	/* MDBBR */
194*c087a94bSLad Prabhakar 		volume = &mix->volumeB;
195*c087a94bSLad Prabhakar 		rsnd_flags_set(mix, HAS_VOLB);
196*c087a94bSLad Prabhakar 		break;
197*c087a94bSLad Prabhakar 	case 0:
198*c087a94bSLad Prabhakar 	case 1:	/* MDBCR */
199*c087a94bSLad Prabhakar 		volume = &mix->volumeC;
200*c087a94bSLad Prabhakar 		rsnd_flags_set(mix, HAS_VOLC);
201*c087a94bSLad Prabhakar 		break;
202*c087a94bSLad Prabhakar 	case 2:
203*c087a94bSLad Prabhakar 	case 5:	/* MDBDR */
204*c087a94bSLad Prabhakar 		volume = &mix->volumeD;
205*c087a94bSLad Prabhakar 		rsnd_flags_set(mix, HAS_VOLD);
206*c087a94bSLad Prabhakar 		break;
207*c087a94bSLad Prabhakar 	default:
208*c087a94bSLad Prabhakar 		dev_err(dev, "unknown SRC is connected\n");
209*c087a94bSLad Prabhakar 		return -EINVAL;
210*c087a94bSLad Prabhakar 	}
211*c087a94bSLad Prabhakar 
212*c087a94bSLad Prabhakar 	/* Volume */
213*c087a94bSLad Prabhakar 	ret = rsnd_kctrl_new_s(mod, io, rtd,
214*c087a94bSLad Prabhakar 			       "MIX Playback Volume",
215*c087a94bSLad Prabhakar 			       rsnd_kctrl_accept_anytime,
216*c087a94bSLad Prabhakar 			       rsnd_mix_volume_update,
217*c087a94bSLad Prabhakar 			       volume, VOL_MAX);
218*c087a94bSLad Prabhakar 	if (ret < 0)
219*c087a94bSLad Prabhakar 		return ret;
220*c087a94bSLad Prabhakar 	rsnd_kctrl_vals(*volume) = VOL_MAX;
221*c087a94bSLad Prabhakar 
222*c087a94bSLad Prabhakar 	if (rsnd_flags_has(mix, ONCE_KCTRL_INITIALIZED))
223*c087a94bSLad Prabhakar 		return ret;
224*c087a94bSLad Prabhakar 
225*c087a94bSLad Prabhakar 	/* Ramp */
226*c087a94bSLad Prabhakar 	ret = rsnd_kctrl_new_s(mod, io, rtd,
227*c087a94bSLad Prabhakar 			       "MIX Ramp Switch",
228*c087a94bSLad Prabhakar 			       rsnd_kctrl_accept_anytime,
229*c087a94bSLad Prabhakar 			       rsnd_mix_volume_update,
230*c087a94bSLad Prabhakar 			       &mix->ren, 1);
231*c087a94bSLad Prabhakar 	if (ret < 0)
232*c087a94bSLad Prabhakar 		return ret;
233*c087a94bSLad Prabhakar 
234*c087a94bSLad Prabhakar 	ret = rsnd_kctrl_new_e(mod, io, rtd,
235*c087a94bSLad Prabhakar 			       "MIX Ramp Up Rate",
236*c087a94bSLad Prabhakar 			       rsnd_kctrl_accept_anytime,
237*c087a94bSLad Prabhakar 			       rsnd_mix_volume_update,
238*c087a94bSLad Prabhakar 			       &mix->rup,
239*c087a94bSLad Prabhakar 			       volume_ramp_rate,
240*c087a94bSLad Prabhakar 			       VOLUME_RAMP_MAX_MIX);
241*c087a94bSLad Prabhakar 	if (ret < 0)
242*c087a94bSLad Prabhakar 		return ret;
243*c087a94bSLad Prabhakar 
244*c087a94bSLad Prabhakar 	ret = rsnd_kctrl_new_e(mod, io, rtd,
245*c087a94bSLad Prabhakar 			       "MIX Ramp Down Rate",
246*c087a94bSLad Prabhakar 			       rsnd_kctrl_accept_anytime,
247*c087a94bSLad Prabhakar 			       rsnd_mix_volume_update,
248*c087a94bSLad Prabhakar 			       &mix->rdw,
249*c087a94bSLad Prabhakar 			       volume_ramp_rate,
250*c087a94bSLad Prabhakar 			       VOLUME_RAMP_MAX_MIX);
251*c087a94bSLad Prabhakar 
252*c087a94bSLad Prabhakar 	rsnd_flags_set(mix, ONCE_KCTRL_INITIALIZED);
253*c087a94bSLad Prabhakar 
254*c087a94bSLad Prabhakar 	return ret;
255*c087a94bSLad Prabhakar }
256*c087a94bSLad Prabhakar 
257*c087a94bSLad Prabhakar #ifdef CONFIG_DEBUG_FS
258*c087a94bSLad Prabhakar static void rsnd_mix_debug_info(struct seq_file *m,
259*c087a94bSLad Prabhakar 				struct rsnd_dai_stream *io,
260*c087a94bSLad Prabhakar 				struct rsnd_mod *mod)
261*c087a94bSLad Prabhakar {
262*c087a94bSLad Prabhakar 	rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU,
263*c087a94bSLad Prabhakar 				  0xd00 + rsnd_mod_id(mod) * 0x40, 0x30);
264*c087a94bSLad Prabhakar }
265*c087a94bSLad Prabhakar #define DEBUG_INFO .debug_info = rsnd_mix_debug_info
266*c087a94bSLad Prabhakar #else
267*c087a94bSLad Prabhakar #define DEBUG_INFO
268*c087a94bSLad Prabhakar #endif
269*c087a94bSLad Prabhakar 
270*c087a94bSLad Prabhakar static struct rsnd_mod_ops rsnd_mix_ops = {
271*c087a94bSLad Prabhakar 	.name		= MIX_NAME,
272*c087a94bSLad Prabhakar 	.probe		= rsnd_mix_probe_,
273*c087a94bSLad Prabhakar 	.init		= rsnd_mix_init,
274*c087a94bSLad Prabhakar 	.quit		= rsnd_mix_quit,
275*c087a94bSLad Prabhakar 	.pcm_new	= rsnd_mix_pcm_new,
276*c087a94bSLad Prabhakar 	.get_status	= rsnd_mod_get_status,
277*c087a94bSLad Prabhakar 	DEBUG_INFO
278*c087a94bSLad Prabhakar };
279*c087a94bSLad Prabhakar 
280*c087a94bSLad Prabhakar struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id)
281*c087a94bSLad Prabhakar {
282*c087a94bSLad Prabhakar 	if (WARN_ON(id < 0 || id >= rsnd_mix_nr(priv)))
283*c087a94bSLad Prabhakar 		id = 0;
284*c087a94bSLad Prabhakar 
285*c087a94bSLad Prabhakar 	return rsnd_mod_get(rsnd_mix_get(priv, id));
286*c087a94bSLad Prabhakar }
287*c087a94bSLad Prabhakar 
288*c087a94bSLad Prabhakar int rsnd_mix_probe(struct rsnd_priv *priv)
289*c087a94bSLad Prabhakar {
290*c087a94bSLad Prabhakar 	struct device_node *node;
291*c087a94bSLad Prabhakar 	struct device_node *np;
292*c087a94bSLad Prabhakar 	struct device *dev = rsnd_priv_to_dev(priv);
293*c087a94bSLad Prabhakar 	struct rsnd_mix *mix;
294*c087a94bSLad Prabhakar 	struct clk *clk;
295*c087a94bSLad Prabhakar 	char name[MIX_NAME_SIZE];
296*c087a94bSLad Prabhakar 	int i, nr, ret;
297*c087a94bSLad Prabhakar 
298*c087a94bSLad Prabhakar 	node = rsnd_mix_of_node(priv);
299*c087a94bSLad Prabhakar 	if (!node)
300*c087a94bSLad Prabhakar 		return 0; /* not used is not error */
301*c087a94bSLad Prabhakar 
302*c087a94bSLad Prabhakar 	nr = of_get_child_count(node);
303*c087a94bSLad Prabhakar 	if (!nr) {
304*c087a94bSLad Prabhakar 		ret = -EINVAL;
305*c087a94bSLad Prabhakar 		goto rsnd_mix_probe_done;
306*c087a94bSLad Prabhakar 	}
307*c087a94bSLad Prabhakar 
308*c087a94bSLad Prabhakar 	mix	= devm_kcalloc(dev, nr, sizeof(*mix), GFP_KERNEL);
309*c087a94bSLad Prabhakar 	if (!mix) {
310*c087a94bSLad Prabhakar 		ret = -ENOMEM;
311*c087a94bSLad Prabhakar 		goto rsnd_mix_probe_done;
312*c087a94bSLad Prabhakar 	}
313*c087a94bSLad Prabhakar 
314*c087a94bSLad Prabhakar 	priv->mix_nr	= nr;
315*c087a94bSLad Prabhakar 	priv->mix	= mix;
316*c087a94bSLad Prabhakar 
317*c087a94bSLad Prabhakar 	i = 0;
318*c087a94bSLad Prabhakar 	ret = 0;
319*c087a94bSLad Prabhakar 	for_each_child_of_node(node, np) {
320*c087a94bSLad Prabhakar 		mix = rsnd_mix_get(priv, i);
321*c087a94bSLad Prabhakar 
322*c087a94bSLad Prabhakar 		snprintf(name, MIX_NAME_SIZE, "%s.%d",
323*c087a94bSLad Prabhakar 			 MIX_NAME, i);
324*c087a94bSLad Prabhakar 
325*c087a94bSLad Prabhakar 		clk = devm_clk_get(dev, name);
326*c087a94bSLad Prabhakar 		if (IS_ERR(clk)) {
327*c087a94bSLad Prabhakar 			ret = PTR_ERR(clk);
328*c087a94bSLad Prabhakar 			of_node_put(np);
329*c087a94bSLad Prabhakar 			goto rsnd_mix_probe_done;
330*c087a94bSLad Prabhakar 		}
331*c087a94bSLad Prabhakar 
332*c087a94bSLad Prabhakar 		ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops,
333*c087a94bSLad Prabhakar 				    clk, RSND_MOD_MIX, i);
334*c087a94bSLad Prabhakar 		if (ret) {
335*c087a94bSLad Prabhakar 			of_node_put(np);
336*c087a94bSLad Prabhakar 			goto rsnd_mix_probe_done;
337*c087a94bSLad Prabhakar 		}
338*c087a94bSLad Prabhakar 
339*c087a94bSLad Prabhakar 		i++;
340*c087a94bSLad Prabhakar 	}
341*c087a94bSLad Prabhakar 
342*c087a94bSLad Prabhakar rsnd_mix_probe_done:
343*c087a94bSLad Prabhakar 	of_node_put(node);
344*c087a94bSLad Prabhakar 
345*c087a94bSLad Prabhakar 	return ret;
346*c087a94bSLad Prabhakar }
347*c087a94bSLad Prabhakar 
348*c087a94bSLad Prabhakar void rsnd_mix_remove(struct rsnd_priv *priv)
349*c087a94bSLad Prabhakar {
350*c087a94bSLad Prabhakar 	struct rsnd_mix *mix;
351*c087a94bSLad Prabhakar 	int i;
352*c087a94bSLad Prabhakar 
353*c087a94bSLad Prabhakar 	for_each_rsnd_mix(mix, priv, i) {
354*c087a94bSLad Prabhakar 		rsnd_mod_quit(rsnd_mod_get(mix));
355*c087a94bSLad Prabhakar 	}
356*c087a94bSLad Prabhakar }
357