xref: /openbmc/linux/sound/soc/sh/rcar/src.c (revision 7674bec4fc09e85803a8f2bd26a013d0076a80a9)
11e0edd4dSKuninori Morimoto // SPDX-License-Identifier: GPL-2.0
21e0edd4dSKuninori Morimoto //
31e0edd4dSKuninori Morimoto // Renesas R-Car SRC support
41e0edd4dSKuninori Morimoto //
51e0edd4dSKuninori Morimoto // Copyright (C) 2013 Renesas Solutions Corp.
61e0edd4dSKuninori Morimoto // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
72b627869SKuninori Morimoto 
82b627869SKuninori Morimoto /*
92b627869SKuninori Morimoto  * you can enable below define if you don't need
102b627869SKuninori Morimoto  * SSI interrupt status debug message when debugging
112b627869SKuninori Morimoto  * see rsnd_dbg_irq_status()
122b627869SKuninori Morimoto  *
132b627869SKuninori Morimoto  * #define RSND_DEBUG_NO_IRQ_STATUS 1
142b627869SKuninori Morimoto  */
152b627869SKuninori Morimoto 
16ba9c949fSKuninori Morimoto #include "rsnd.h"
17*7674bec4SKuninori Morimoto #include <linux/sys_soc.h>
18ba9c949fSKuninori Morimoto 
198aefda50SKuninori Morimoto #define SRC_NAME "src"
208aefda50SKuninori Morimoto 
21cfcefe01SKuninori Morimoto /* SCU_SYSTEM_STATUS0/1 */
22cfcefe01SKuninori Morimoto #define OUF_SRC(id)	((1 << (id + 16)) | (1 << id))
23cfcefe01SKuninori Morimoto 
24ba9c949fSKuninori Morimoto struct rsnd_src {
25ba9c949fSKuninori Morimoto 	struct rsnd_mod mod;
26940e9479SKuninori Morimoto 	struct rsnd_mod *dma;
2743cb6954SKuninori Morimoto 	struct rsnd_kctrl_cfg_s sen;  /* sync convert enable */
2843cb6954SKuninori Morimoto 	struct rsnd_kctrl_cfg_s sync; /* sync convert */
29adf6a681SKuninori Morimoto 	int irq;
30ba9c949fSKuninori Morimoto };
31ba9c949fSKuninori Morimoto 
32ba9c949fSKuninori Morimoto #define RSND_SRC_NAME_SIZE 16
33ba9c949fSKuninori Morimoto 
34adf6a681SKuninori Morimoto #define rsnd_src_get(priv, id) ((struct rsnd_src *)(priv->src) + id)
35da599fd3SKuninori Morimoto #define rsnd_src_nr(priv) ((priv)->src_nr)
36ab2049f9SKuninori Morimoto #define rsnd_src_sync_is_enabled(mod) (rsnd_mod_to_src(mod)->sen.val)
3782e76ed3SKuninori Morimoto 
38ba9c949fSKuninori Morimoto #define rsnd_mod_to_src(_mod)				\
39ba9c949fSKuninori Morimoto 	container_of((_mod), struct rsnd_src, mod)
40ba9c949fSKuninori Morimoto 
41ba9c949fSKuninori Morimoto #define for_each_rsnd_src(pos, priv, i)				\
42ba9c949fSKuninori Morimoto 	for ((i) = 0;						\
43ba9c949fSKuninori Morimoto 	     ((i) < rsnd_src_nr(priv)) &&			\
44ba9c949fSKuninori Morimoto 	     ((pos) = (struct rsnd_src *)(priv)->src + i);	\
45ba9c949fSKuninori Morimoto 	     i++)
46ba9c949fSKuninori Morimoto 
47ba9c949fSKuninori Morimoto 
48ba9c949fSKuninori Morimoto /*
49ba9c949fSKuninori Morimoto  *		image of SRC (Sampling Rate Converter)
50ba9c949fSKuninori Morimoto  *
51ba9c949fSKuninori Morimoto  * 96kHz   <-> +-----+	48kHz	+-----+	 48kHz	+-------+
52ba9c949fSKuninori Morimoto  * 48kHz   <-> | SRC | <------>	| SSI |	<----->	| codec |
53ba9c949fSKuninori Morimoto  * 44.1kHz <-> +-----+		+-----+		+-------+
54ba9c949fSKuninori Morimoto  * ...
55ba9c949fSKuninori Morimoto  *
56ba9c949fSKuninori Morimoto  */
57ba9c949fSKuninori Morimoto 
5898efeeaeSKuninori Morimoto static void rsnd_src_activation(struct rsnd_mod *mod)
59379febfdSKuninori Morimoto {
60379febfdSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SWRSR, 0);
61379febfdSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SWRSR, 1);
62379febfdSKuninori Morimoto }
63379febfdSKuninori Morimoto 
64475a361aSKuninori Morimoto static void rsnd_src_halt(struct rsnd_mod *mod)
65475a361aSKuninori Morimoto {
66475a361aSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCIR, 1);
67475a361aSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SWRSR, 0);
68475a361aSKuninori Morimoto }
69475a361aSKuninori Morimoto 
709b99e9a7SKuninori Morimoto static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io,
719b99e9a7SKuninori Morimoto 					 struct rsnd_mod *mod)
7272adc61fSKuninori Morimoto {
7372adc61fSKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
7472adc61fSKuninori Morimoto 	int is_play = rsnd_io_is_play(io);
7572adc61fSKuninori Morimoto 
7672adc61fSKuninori Morimoto 	return rsnd_dma_request_channel(rsnd_src_of_node(priv),
7772adc61fSKuninori Morimoto 					mod,
7872adc61fSKuninori Morimoto 					is_play ? "rx" : "tx");
7972adc61fSKuninori Morimoto }
8072adc61fSKuninori Morimoto 
8188c61cffSKuninori Morimoto static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io,
821a9be9eeSKuninori Morimoto 				 struct rsnd_mod *mod)
8343cb6954SKuninori Morimoto {
8443cb6954SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
851a9be9eeSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
8643cb6954SKuninori Morimoto 	u32 convert_rate;
8743cb6954SKuninori Morimoto 
8843cb6954SKuninori Morimoto 	if (!runtime)
8943cb6954SKuninori Morimoto 		return 0;
9043cb6954SKuninori Morimoto 
91ab2049f9SKuninori Morimoto 	if (!rsnd_src_sync_is_enabled(mod))
92c2aaaa57SKuninori Morimoto 		return rsnd_io_converted_rate(io);
9343cb6954SKuninori Morimoto 
9443cb6954SKuninori Morimoto 	convert_rate = src->sync.val;
9543cb6954SKuninori Morimoto 
9643cb6954SKuninori Morimoto 	if (!convert_rate)
97c2aaaa57SKuninori Morimoto 		convert_rate = rsnd_io_converted_rate(io);
9843cb6954SKuninori Morimoto 
9943cb6954SKuninori Morimoto 	if (!convert_rate)
10043cb6954SKuninori Morimoto 		convert_rate = runtime->rate;
10143cb6954SKuninori Morimoto 
10243cb6954SKuninori Morimoto 	return convert_rate;
10343cb6954SKuninori Morimoto }
10443cb6954SKuninori Morimoto 
105cbf1494fSKuninori Morimoto unsigned int rsnd_src_get_rate(struct rsnd_priv *priv,
106ba9c949fSKuninori Morimoto 			       struct rsnd_dai_stream *io,
107cbf1494fSKuninori Morimoto 			       int is_in)
108ba9c949fSKuninori Morimoto {
109b1eac430SKuninori Morimoto 	struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
110cbf1494fSKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
111b1eac430SKuninori Morimoto 	unsigned int rate = 0;
112cbf1494fSKuninori Morimoto 	int is_play = rsnd_io_is_play(io);
113cbf1494fSKuninori Morimoto 
114cbf1494fSKuninori Morimoto 	/*
115cbf1494fSKuninori Morimoto 	 * Playback
116cbf1494fSKuninori Morimoto 	 * runtime_rate -> [SRC] -> convert_rate
117cbf1494fSKuninori Morimoto 	 *
118cbf1494fSKuninori Morimoto 	 * Capture
119cbf1494fSKuninori Morimoto 	 * convert_rate -> [SRC] -> runtime_rate
120cbf1494fSKuninori Morimoto 	 */
121cbf1494fSKuninori Morimoto 
122cbf1494fSKuninori Morimoto 	if (is_play == is_in)
123cbf1494fSKuninori Morimoto 		return runtime->rate;
124ba9c949fSKuninori Morimoto 
125ba9c949fSKuninori Morimoto 	/*
126ba9c949fSKuninori Morimoto 	 * return convert rate if SRC is used,
127ba9c949fSKuninori Morimoto 	 * otherwise, return runtime->rate as usual
128ba9c949fSKuninori Morimoto 	 */
1291a9be9eeSKuninori Morimoto 	if (src_mod)
1301a9be9eeSKuninori Morimoto 		rate = rsnd_src_convert_rate(io, src_mod);
131b1eac430SKuninori Morimoto 
132ba9c949fSKuninori Morimoto 	if (!rate)
133ba9c949fSKuninori Morimoto 		rate = runtime->rate;
134ba9c949fSKuninori Morimoto 
135ba9c949fSKuninori Morimoto 	return rate;
136ba9c949fSKuninori Morimoto }
137ba9c949fSKuninori Morimoto 
138*7674bec4SKuninori Morimoto const static u32 bsdsr_table_pattern1[] = {
139*7674bec4SKuninori Morimoto 	0x01800000, /* 6 - 1/6 */
140*7674bec4SKuninori Morimoto 	0x01000000, /* 6 - 1/4 */
141*7674bec4SKuninori Morimoto 	0x00c00000, /* 6 - 1/3 */
142*7674bec4SKuninori Morimoto 	0x00800000, /* 6 - 1/2 */
143*7674bec4SKuninori Morimoto 	0x00600000, /* 6 - 2/3 */
144*7674bec4SKuninori Morimoto 	0x00400000, /* 6 - 1   */
145*7674bec4SKuninori Morimoto };
146*7674bec4SKuninori Morimoto 
147*7674bec4SKuninori Morimoto const static u32 bsdsr_table_pattern2[] = {
148*7674bec4SKuninori Morimoto 	0x02400000, /* 6 - 1/6 */
149*7674bec4SKuninori Morimoto 	0x01800000, /* 6 - 1/4 */
150*7674bec4SKuninori Morimoto 	0x01200000, /* 6 - 1/3 */
151*7674bec4SKuninori Morimoto 	0x00c00000, /* 6 - 1/2 */
152*7674bec4SKuninori Morimoto 	0x00900000, /* 6 - 2/3 */
153*7674bec4SKuninori Morimoto 	0x00600000, /* 6 - 1   */
154*7674bec4SKuninori Morimoto };
155*7674bec4SKuninori Morimoto 
156*7674bec4SKuninori Morimoto const static u32 bsisr_table[] = {
157*7674bec4SKuninori Morimoto 	0x00100060, /* 6 - 1/6 */
158*7674bec4SKuninori Morimoto 	0x00100040, /* 6 - 1/4 */
159*7674bec4SKuninori Morimoto 	0x00100030, /* 6 - 1/3 */
160*7674bec4SKuninori Morimoto 	0x00100020, /* 6 - 1/2 */
161*7674bec4SKuninori Morimoto 	0x00100020, /* 6 - 2/3 */
162*7674bec4SKuninori Morimoto 	0x00100020, /* 6 - 1   */
163*7674bec4SKuninori Morimoto };
164*7674bec4SKuninori Morimoto 
165*7674bec4SKuninori Morimoto const static u32 chan288888[] = {
166*7674bec4SKuninori Morimoto 	0x00000006, /* 1 to 2 */
167*7674bec4SKuninori Morimoto 	0x000001fe, /* 1 to 8 */
168*7674bec4SKuninori Morimoto 	0x000001fe, /* 1 to 8 */
169*7674bec4SKuninori Morimoto 	0x000001fe, /* 1 to 8 */
170*7674bec4SKuninori Morimoto 	0x000001fe, /* 1 to 8 */
171*7674bec4SKuninori Morimoto 	0x000001fe, /* 1 to 8 */
172*7674bec4SKuninori Morimoto };
173*7674bec4SKuninori Morimoto 
174*7674bec4SKuninori Morimoto const static u32 chan244888[] = {
175*7674bec4SKuninori Morimoto 	0x00000006, /* 1 to 2 */
176*7674bec4SKuninori Morimoto 	0x0000001e, /* 1 to 4 */
177*7674bec4SKuninori Morimoto 	0x0000001e, /* 1 to 4 */
178*7674bec4SKuninori Morimoto 	0x000001fe, /* 1 to 8 */
179*7674bec4SKuninori Morimoto 	0x000001fe, /* 1 to 8 */
180*7674bec4SKuninori Morimoto 	0x000001fe, /* 1 to 8 */
181*7674bec4SKuninori Morimoto };
182*7674bec4SKuninori Morimoto 
183*7674bec4SKuninori Morimoto const static u32 chan222222[] = {
184*7674bec4SKuninori Morimoto 	0x00000006, /* 1 to 2 */
185*7674bec4SKuninori Morimoto 	0x00000006, /* 1 to 2 */
186*7674bec4SKuninori Morimoto 	0x00000006, /* 1 to 2 */
187*7674bec4SKuninori Morimoto 	0x00000006, /* 1 to 2 */
188*7674bec4SKuninori Morimoto 	0x00000006, /* 1 to 2 */
189*7674bec4SKuninori Morimoto 	0x00000006, /* 1 to 2 */
190*7674bec4SKuninori Morimoto };
191*7674bec4SKuninori Morimoto 
192*7674bec4SKuninori Morimoto static const struct soc_device_attribute ov_soc[] = {
193*7674bec4SKuninori Morimoto 	{ .soc_id = "r8a77990" }, /* E3 */
194*7674bec4SKuninori Morimoto 	{ /* sentinel */ }
195*7674bec4SKuninori Morimoto };
196*7674bec4SKuninori Morimoto 
19775916f65SKuninori Morimoto static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
19875916f65SKuninori Morimoto 				      struct rsnd_mod *mod)
199ba9c949fSKuninori Morimoto {
20075916f65SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
201cfcefe01SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
20275916f65SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
203*7674bec4SKuninori Morimoto 	const struct soc_device_attribute *soc = soc_device_match(ov_soc);
20490431eb4SKuninori Morimoto 	int is_play = rsnd_io_is_play(io);
20567923f77SKuninori Morimoto 	int use_src = 0;
2060102eed5SKuninori Morimoto 	u32 fin, fout;
20775916f65SKuninori Morimoto 	u32 ifscr, fsrate, adinr;
20875916f65SKuninori Morimoto 	u32 cr, route;
20990431eb4SKuninori Morimoto 	u32 i_busif, o_busif, tmp;
210*7674bec4SKuninori Morimoto 	const u32 *bsdsr_table;
211*7674bec4SKuninori Morimoto 	const u32 *chptn;
21275916f65SKuninori Morimoto 	uint ratio;
213*7674bec4SKuninori Morimoto 	int chan;
214*7674bec4SKuninori Morimoto 	int idx;
215ba9c949fSKuninori Morimoto 
21675916f65SKuninori Morimoto 	if (!runtime)
21775916f65SKuninori Morimoto 		return;
218ba9c949fSKuninori Morimoto 
2190102eed5SKuninori Morimoto 	fin  = rsnd_src_get_in_rate(priv, io);
2200102eed5SKuninori Morimoto 	fout = rsnd_src_get_out_rate(priv, io);
2210102eed5SKuninori Morimoto 
222*7674bec4SKuninori Morimoto 	chan = rsnd_runtime_channel_original(io);
223*7674bec4SKuninori Morimoto 
22475916f65SKuninori Morimoto 	/* 6 - 1/6 are very enough ratio for SRC_BSDSR */
2250102eed5SKuninori Morimoto 	if (fin == fout)
22675916f65SKuninori Morimoto 		ratio = 0;
2270102eed5SKuninori Morimoto 	else if (fin > fout)
2280102eed5SKuninori Morimoto 		ratio = 100 * fin / fout;
22975916f65SKuninori Morimoto 	else
2300102eed5SKuninori Morimoto 		ratio = 100 * fout / fin;
231cfcefe01SKuninori Morimoto 
23275916f65SKuninori Morimoto 	if (ratio > 600) {
23375916f65SKuninori Morimoto 		dev_err(dev, "FSO/FSI ratio error\n");
23475916f65SKuninori Morimoto 		return;
235ba9c949fSKuninori Morimoto 	}
236ba9c949fSKuninori Morimoto 
23767923f77SKuninori Morimoto 	use_src = (fin != fout) | rsnd_src_sync_is_enabled(mod);
23867923f77SKuninori Morimoto 
239ba9c949fSKuninori Morimoto 	/*
24075916f65SKuninori Morimoto 	 * SRC_ADINR
241ba9c949fSKuninori Morimoto 	 */
242*7674bec4SKuninori Morimoto 	adinr = rsnd_get_adinr_bit(mod, io) | chan;
24375916f65SKuninori Morimoto 
24475916f65SKuninori Morimoto 	/*
24575916f65SKuninori Morimoto 	 * SRC_IFSCR / SRC_IFSVR
24675916f65SKuninori Morimoto 	 */
24775916f65SKuninori Morimoto 	ifscr = 0;
24875916f65SKuninori Morimoto 	fsrate = 0;
24967923f77SKuninori Morimoto 	if (use_src) {
25093ca33c9SHiroyuki Yokoyama 		u64 n;
25193ca33c9SHiroyuki Yokoyama 
25275916f65SKuninori Morimoto 		ifscr = 1;
25393ca33c9SHiroyuki Yokoyama 		n = (u64)0x0400000 * fin;
25493ca33c9SHiroyuki Yokoyama 		do_div(n, fout);
25593ca33c9SHiroyuki Yokoyama 		fsrate = n;
25675916f65SKuninori Morimoto 	}
25775916f65SKuninori Morimoto 
25875916f65SKuninori Morimoto 	/*
25975916f65SKuninori Morimoto 	 * SRC_SRCCR / SRC_ROUTE_MODE0
26075916f65SKuninori Morimoto 	 */
26175916f65SKuninori Morimoto 	cr	= 0x00011110;
26275916f65SKuninori Morimoto 	route	= 0x0;
26367923f77SKuninori Morimoto 	if (use_src) {
26475916f65SKuninori Morimoto 		route	= 0x1;
26575916f65SKuninori Morimoto 
266ab2049f9SKuninori Morimoto 		if (rsnd_src_sync_is_enabled(mod)) {
26775916f65SKuninori Morimoto 			cr |= 0x1;
26875916f65SKuninori Morimoto 			route |= rsnd_io_is_play(io) ?
26975916f65SKuninori Morimoto 				(0x1 << 24) : (0x1 << 25);
27075916f65SKuninori Morimoto 		}
27175916f65SKuninori Morimoto 	}
27275916f65SKuninori Morimoto 
27375916f65SKuninori Morimoto 	/*
27475916f65SKuninori Morimoto 	 * SRC_BSDSR / SRC_BSISR
275*7674bec4SKuninori Morimoto 	 *
276*7674bec4SKuninori Morimoto 	 * see
277*7674bec4SKuninori Morimoto 	 *	Combination of Register Setting Related to
278*7674bec4SKuninori Morimoto 	 *	FSO/FSI Ratio and Channel, Latency
27975916f65SKuninori Morimoto 	 */
28075916f65SKuninori Morimoto 	switch (rsnd_mod_id(mod)) {
281*7674bec4SKuninori Morimoto 	case 0:
282*7674bec4SKuninori Morimoto 		chptn		= chan288888;
283*7674bec4SKuninori Morimoto 		bsdsr_table	= bsdsr_table_pattern1;
284*7674bec4SKuninori Morimoto 		break;
285*7674bec4SKuninori Morimoto 	case 1:
286*7674bec4SKuninori Morimoto 	case 3:
287*7674bec4SKuninori Morimoto 	case 4:
288*7674bec4SKuninori Morimoto 		chptn		= chan244888;
289*7674bec4SKuninori Morimoto 		bsdsr_table	= bsdsr_table_pattern1;
290*7674bec4SKuninori Morimoto 		break;
291*7674bec4SKuninori Morimoto 	case 2:
292*7674bec4SKuninori Morimoto 	case 9:
293*7674bec4SKuninori Morimoto 		chptn		= chan222222;
294*7674bec4SKuninori Morimoto 		bsdsr_table	= bsdsr_table_pattern1;
295*7674bec4SKuninori Morimoto 		break;
29675916f65SKuninori Morimoto 	case 5:
29775916f65SKuninori Morimoto 	case 6:
29875916f65SKuninori Morimoto 	case 7:
29975916f65SKuninori Morimoto 	case 8:
300*7674bec4SKuninori Morimoto 		chptn		= chan222222;
301*7674bec4SKuninori Morimoto 		bsdsr_table	= bsdsr_table_pattern2;
30275916f65SKuninori Morimoto 		break;
30375916f65SKuninori Morimoto 	default:
304*7674bec4SKuninori Morimoto 		goto convert_rate_err;
30575916f65SKuninori Morimoto 	}
30675916f65SKuninori Morimoto 
307*7674bec4SKuninori Morimoto 	/*
308*7674bec4SKuninori Morimoto 	 * E3 need to overwrite
309*7674bec4SKuninori Morimoto 	 */
310*7674bec4SKuninori Morimoto 	if (soc)
311*7674bec4SKuninori Morimoto 		switch (rsnd_mod_id(mod)) {
312*7674bec4SKuninori Morimoto 		case 0:
313*7674bec4SKuninori Morimoto 		case 4:
314*7674bec4SKuninori Morimoto 			chptn	= chan222222;
315*7674bec4SKuninori Morimoto 		}
316*7674bec4SKuninori Morimoto 
317*7674bec4SKuninori Morimoto 	for (idx = 0; idx < ARRAY_SIZE(chan222222); idx++)
318*7674bec4SKuninori Morimoto 		if (chptn[idx] & (1 << chan))
319*7674bec4SKuninori Morimoto 			break;
320*7674bec4SKuninori Morimoto 
321*7674bec4SKuninori Morimoto 	if (chan > 8 ||
322*7674bec4SKuninori Morimoto 	    idx >= ARRAY_SIZE(chan222222))
323*7674bec4SKuninori Morimoto 		goto convert_rate_err;
324*7674bec4SKuninori Morimoto 
32590431eb4SKuninori Morimoto 	/* BUSIF_MODE */
32690431eb4SKuninori Morimoto 	tmp = rsnd_get_busif_shift(io, mod);
32790431eb4SKuninori Morimoto 	i_busif = ( is_play ? tmp : 0) | 1;
32890431eb4SKuninori Morimoto 	o_busif = (!is_play ? tmp : 0) | 1;
32990431eb4SKuninori Morimoto 
3300fbab951SKuninori Morimoto 	rsnd_mod_write(mod, SRC_ROUTE_MODE0, route);
3310fbab951SKuninori Morimoto 
33275916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCIR, 1);	/* initialize */
33375916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_ADINR, adinr);
33475916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_IFSCR, ifscr);
33575916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_IFSVR, fsrate);
33675916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCCR, cr);
337*7674bec4SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BSDSR, bsdsr_table[idx]);
338*7674bec4SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BSISR, bsisr_table[idx]);
33975916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCIR, 0);	/* cancel initialize */
34075916f65SKuninori Morimoto 
34190431eb4SKuninori Morimoto 	rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif);
34290431eb4SKuninori Morimoto 	rsnd_mod_write(mod, SRC_O_BUSIF_MODE, o_busif);
34390431eb4SKuninori Morimoto 
34475916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
34575916f65SKuninori Morimoto 
3460102eed5SKuninori Morimoto 	rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout);
347*7674bec4SKuninori Morimoto 
348*7674bec4SKuninori Morimoto 	return;
349*7674bec4SKuninori Morimoto 
350*7674bec4SKuninori Morimoto convert_rate_err:
351*7674bec4SKuninori Morimoto 	dev_err(dev, "unknown BSDSR/BSDIR settings\n");
35275916f65SKuninori Morimoto }
35375916f65SKuninori Morimoto 
354b5b442abSKuninori Morimoto static int rsnd_src_irq(struct rsnd_mod *mod,
355b5b442abSKuninori Morimoto 			struct rsnd_dai_stream *io,
356b5b442abSKuninori Morimoto 			struct rsnd_priv *priv,
357b5b442abSKuninori Morimoto 			int enable)
358cfcefe01SKuninori Morimoto {
359cfcefe01SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
360cfcefe01SKuninori Morimoto 	u32 sys_int_val, int_val, sys_int_mask;
361adf6a681SKuninori Morimoto 	int irq = src->irq;
362cfcefe01SKuninori Morimoto 	int id = rsnd_mod_id(mod);
363cfcefe01SKuninori Morimoto 
364cfcefe01SKuninori Morimoto 	sys_int_val =
365cfcefe01SKuninori Morimoto 	sys_int_mask = OUF_SRC(id);
366cfcefe01SKuninori Morimoto 	int_val = 0x3300;
367cfcefe01SKuninori Morimoto 
368cfcefe01SKuninori Morimoto 	/*
369cfcefe01SKuninori Morimoto 	 * IRQ is not supported on non-DT
370cfcefe01SKuninori Morimoto 	 * see
37175916f65SKuninori Morimoto 	 *	rsnd_src_probe_()
372cfcefe01SKuninori Morimoto 	 */
373cfcefe01SKuninori Morimoto 	if ((irq <= 0) || !enable) {
374cfcefe01SKuninori Morimoto 		sys_int_val = 0;
375cfcefe01SKuninori Morimoto 		int_val = 0;
376cfcefe01SKuninori Morimoto 	}
377cfcefe01SKuninori Morimoto 
3781a1bf58aSKuninori Morimoto 	/*
3791a1bf58aSKuninori Morimoto 	 * WORKAROUND
3801a1bf58aSKuninori Morimoto 	 *
381ab2049f9SKuninori Morimoto 	 * ignore over flow error when rsnd_src_sync_is_enabled()
3821a1bf58aSKuninori Morimoto 	 */
383ab2049f9SKuninori Morimoto 	if (rsnd_src_sync_is_enabled(mod))
3841a1bf58aSKuninori Morimoto 		sys_int_val = sys_int_val & 0xffff;
3851a1bf58aSKuninori Morimoto 
386cfcefe01SKuninori Morimoto 	rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val);
387cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val);
388cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val);
389b5b442abSKuninori Morimoto 
390b5b442abSKuninori Morimoto 	return 0;
391cfcefe01SKuninori Morimoto }
392cfcefe01SKuninori Morimoto 
3938cc225f7SKuninori Morimoto static void rsnd_src_status_clear(struct rsnd_mod *mod)
394cfcefe01SKuninori Morimoto {
395cfcefe01SKuninori Morimoto 	u32 val = OUF_SRC(rsnd_mod_id(mod));
396cfcefe01SKuninori Morimoto 
39742b197e7SKuninori Morimoto 	rsnd_mod_write(mod, SCU_SYS_STATUS0, val);
39842b197e7SKuninori Morimoto 	rsnd_mod_write(mod, SCU_SYS_STATUS1, val);
399cfcefe01SKuninori Morimoto }
400cfcefe01SKuninori Morimoto 
4016a25c8daSKuninori Morimoto static bool rsnd_src_error_occurred(struct rsnd_mod *mod)
402cfcefe01SKuninori Morimoto {
4032b627869SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
4042b627869SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
4051a1bf58aSKuninori Morimoto 	u32 val0, val1;
4062b627869SKuninori Morimoto 	u32 status0, status1;
407cfcefe01SKuninori Morimoto 	bool ret = false;
408cfcefe01SKuninori Morimoto 
4091a1bf58aSKuninori Morimoto 	val0 = val1 = OUF_SRC(rsnd_mod_id(mod));
4101a1bf58aSKuninori Morimoto 
4111a1bf58aSKuninori Morimoto 	/*
4121a1bf58aSKuninori Morimoto 	 * WORKAROUND
4131a1bf58aSKuninori Morimoto 	 *
414ab2049f9SKuninori Morimoto 	 * ignore over flow error when rsnd_src_sync_is_enabled()
4151a1bf58aSKuninori Morimoto 	 */
416ab2049f9SKuninori Morimoto 	if (rsnd_src_sync_is_enabled(mod))
4171a1bf58aSKuninori Morimoto 		val0 = val0 & 0xffff;
4181a1bf58aSKuninori Morimoto 
4192b627869SKuninori Morimoto 	status0 = rsnd_mod_read(mod, SCU_SYS_STATUS0);
4202b627869SKuninori Morimoto 	status1 = rsnd_mod_read(mod, SCU_SYS_STATUS1);
4212b627869SKuninori Morimoto 	if ((status0 & val0) || (status1 & val1)) {
422c0ea089dSKuninori Morimoto 		rsnd_dbg_irq_status(dev, "%s err status : 0x%08x, 0x%08x\n",
423c0ea089dSKuninori Morimoto 			rsnd_mod_name(mod), status0, status1);
4242b627869SKuninori Morimoto 
425cfcefe01SKuninori Morimoto 		ret = true;
4262b627869SKuninori Morimoto 	}
427cfcefe01SKuninori Morimoto 
428cfcefe01SKuninori Morimoto 	return ret;
429cfcefe01SKuninori Morimoto }
430cfcefe01SKuninori Morimoto 
43175916f65SKuninori Morimoto static int rsnd_src_start(struct rsnd_mod *mod,
432497debaaSKuninori Morimoto 			  struct rsnd_dai_stream *io,
433497debaaSKuninori Morimoto 			  struct rsnd_priv *priv)
434cfcefe01SKuninori Morimoto {
4351a1bf58aSKuninori Morimoto 	u32 val;
4361a1bf58aSKuninori Morimoto 
4371a1bf58aSKuninori Morimoto 	/*
4381a1bf58aSKuninori Morimoto 	 * WORKAROUND
4391a1bf58aSKuninori Morimoto 	 *
4401a1bf58aSKuninori Morimoto 	 * Enable SRC output if you want to use sync convert together with DVC
4411a1bf58aSKuninori Morimoto 	 */
442ab2049f9SKuninori Morimoto 	val = (rsnd_io_to_mod_dvc(io) && !rsnd_src_sync_is_enabled(mod)) ?
4431a1bf58aSKuninori Morimoto 		0x01 : 0x11;
444cfcefe01SKuninori Morimoto 
445cfcefe01SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, val);
446cfcefe01SKuninori Morimoto 
44775916f65SKuninori Morimoto 	return 0;
44875916f65SKuninori Morimoto }
449cfcefe01SKuninori Morimoto 
45075916f65SKuninori Morimoto static int rsnd_src_stop(struct rsnd_mod *mod,
45175916f65SKuninori Morimoto 			 struct rsnd_dai_stream *io,
45275916f65SKuninori Morimoto 			 struct rsnd_priv *priv)
45375916f65SKuninori Morimoto {
45431739a68SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, 0);
455cfcefe01SKuninori Morimoto 
456cfcefe01SKuninori Morimoto 	return 0;
457cfcefe01SKuninori Morimoto }
458cfcefe01SKuninori Morimoto 
45975916f65SKuninori Morimoto static int rsnd_src_init(struct rsnd_mod *mod,
460497debaaSKuninori Morimoto 			 struct rsnd_dai_stream *io,
461497debaaSKuninori Morimoto 			 struct rsnd_priv *priv)
462cfcefe01SKuninori Morimoto {
46375916f65SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
464cfcefe01SKuninori Morimoto 
465ef30da1cSKuninori Morimoto 	/* reset sync convert_rate */
466ef30da1cSKuninori Morimoto 	src->sync.val = 0;
467ef30da1cSKuninori Morimoto 
46875916f65SKuninori Morimoto 	rsnd_mod_power_on(mod);
469cfcefe01SKuninori Morimoto 
47098efeeaeSKuninori Morimoto 	rsnd_src_activation(mod);
471cfcefe01SKuninori Morimoto 
47275916f65SKuninori Morimoto 	rsnd_src_set_convert_rate(io, mod);
47375916f65SKuninori Morimoto 
4748cc225f7SKuninori Morimoto 	rsnd_src_status_clear(mod);
47575916f65SKuninori Morimoto 
47675916f65SKuninori Morimoto 	return 0;
477cfcefe01SKuninori Morimoto }
478cfcefe01SKuninori Morimoto 
47975916f65SKuninori Morimoto static int rsnd_src_quit(struct rsnd_mod *mod,
480b761bf27SKuninori Morimoto 			 struct rsnd_dai_stream *io,
481b761bf27SKuninori Morimoto 			 struct rsnd_priv *priv)
482b761bf27SKuninori Morimoto {
48375916f65SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
48475916f65SKuninori Morimoto 
485475a361aSKuninori Morimoto 	rsnd_src_halt(mod);
486475a361aSKuninori Morimoto 
48775916f65SKuninori Morimoto 	rsnd_mod_power_off(mod);
48875916f65SKuninori Morimoto 
48975916f65SKuninori Morimoto 	/* reset sync convert_rate */
49075916f65SKuninori Morimoto 	src->sync.val = 0;
49175916f65SKuninori Morimoto 
49275916f65SKuninori Morimoto 	return 0;
493b761bf27SKuninori Morimoto }
494b761bf27SKuninori Morimoto 
49575916f65SKuninori Morimoto static void __rsnd_src_interrupt(struct rsnd_mod *mod,
49688c61cffSKuninori Morimoto 				 struct rsnd_dai_stream *io)
497cfcefe01SKuninori Morimoto {
49802299d98SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
4996a25c8daSKuninori Morimoto 	bool stop = false;
500cfcefe01SKuninori Morimoto 
50102299d98SKuninori Morimoto 	spin_lock(&priv->lock);
50202299d98SKuninori Morimoto 
50302299d98SKuninori Morimoto 	/* ignore all cases if not working */
504d5bbe7deSKuninori Morimoto 	if (!rsnd_io_is_working(io))
50575916f65SKuninori Morimoto 		goto rsnd_src_interrupt_out;
506cfcefe01SKuninori Morimoto 
5076a25c8daSKuninori Morimoto 	if (rsnd_src_error_occurred(mod))
5086a25c8daSKuninori Morimoto 		stop = true;
50988c61cffSKuninori Morimoto 
5108cc225f7SKuninori Morimoto 	rsnd_src_status_clear(mod);
51175916f65SKuninori Morimoto rsnd_src_interrupt_out:
5128cc225f7SKuninori Morimoto 
51302299d98SKuninori Morimoto 	spin_unlock(&priv->lock);
5146a25c8daSKuninori Morimoto 
5156a25c8daSKuninori Morimoto 	if (stop)
5166a25c8daSKuninori Morimoto 		snd_pcm_stop_xrun(io->substream);
51788c61cffSKuninori Morimoto }
51888c61cffSKuninori Morimoto 
51975916f65SKuninori Morimoto static irqreturn_t rsnd_src_interrupt(int irq, void *data)
52088c61cffSKuninori Morimoto {
52188c61cffSKuninori Morimoto 	struct rsnd_mod *mod = data;
52288c61cffSKuninori Morimoto 
52375916f65SKuninori Morimoto 	rsnd_mod_interrupt(mod, __rsnd_src_interrupt);
524cfcefe01SKuninori Morimoto 
525cfcefe01SKuninori Morimoto 	return IRQ_HANDLED;
526cfcefe01SKuninori Morimoto }
527cfcefe01SKuninori Morimoto 
52875916f65SKuninori Morimoto static int rsnd_src_probe_(struct rsnd_mod *mod,
5292c0fac19SKuninori Morimoto 			   struct rsnd_dai_stream *io,
530690602fcSKuninori Morimoto 			   struct rsnd_priv *priv)
531ba9c949fSKuninori Morimoto {
532ba9c949fSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
533ba9c949fSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
534adf6a681SKuninori Morimoto 	int irq = src->irq;
535ba9c949fSKuninori Morimoto 	int ret;
536ba9c949fSKuninori Morimoto 
537cfcefe01SKuninori Morimoto 	if (irq > 0) {
538cfcefe01SKuninori Morimoto 		/*
539cfcefe01SKuninori Morimoto 		 * IRQ is not supported on non-DT
540cfcefe01SKuninori Morimoto 		 * see
541b5b442abSKuninori Morimoto 		 *	rsnd_src_irq()
542cfcefe01SKuninori Morimoto 		 */
543cfcefe01SKuninori Morimoto 		ret = devm_request_irq(dev, irq,
54475916f65SKuninori Morimoto 				       rsnd_src_interrupt,
545cfcefe01SKuninori Morimoto 				       IRQF_SHARED,
546cfcefe01SKuninori Morimoto 				       dev_name(dev), mod);
547cfcefe01SKuninori Morimoto 		if (ret)
548b543b52aSKuninori Morimoto 			return ret;
549cfcefe01SKuninori Morimoto 	}
550cfcefe01SKuninori Morimoto 
551b99305d2SKuninori Morimoto 	ret = rsnd_dma_attach(io, mod, &src->dma);
552cfcefe01SKuninori Morimoto 
553cfcefe01SKuninori Morimoto 	return ret;
554ba9c949fSKuninori Morimoto }
555ba9c949fSKuninori Morimoto 
55675916f65SKuninori Morimoto static int rsnd_src_pcm_new(struct rsnd_mod *mod,
5572c0fac19SKuninori Morimoto 			    struct rsnd_dai_stream *io,
55843cb6954SKuninori Morimoto 			    struct snd_soc_pcm_runtime *rtd)
55943cb6954SKuninori Morimoto {
56043cb6954SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
56143cb6954SKuninori Morimoto 	int ret;
56243cb6954SKuninori Morimoto 
56343cb6954SKuninori Morimoto 	/*
56443cb6954SKuninori Morimoto 	 * enable SRC sync convert if possible
56543cb6954SKuninori Morimoto 	 */
56643cb6954SKuninori Morimoto 
56743cb6954SKuninori Morimoto 	/*
56861a219feSKuninori Morimoto 	 * It can't use SRC Synchronous convert
56961a219feSKuninori Morimoto 	 * when Capture if it uses CMD
5707115cb91SKuninori Morimoto 	 */
57161a219feSKuninori Morimoto 	if (rsnd_io_to_mod_cmd(io) && !rsnd_io_is_play(io))
5727115cb91SKuninori Morimoto 		return 0;
5737115cb91SKuninori Morimoto 
5747115cb91SKuninori Morimoto 	/*
57543cb6954SKuninori Morimoto 	 * enable sync convert
57643cb6954SKuninori Morimoto 	 */
577b65a7cccSKuninori Morimoto 	ret = rsnd_kctrl_new_s(mod, io, rtd,
57843cb6954SKuninori Morimoto 			       rsnd_io_is_play(io) ?
57943cb6954SKuninori Morimoto 			       "SRC Out Rate Switch" :
58043cb6954SKuninori Morimoto 			       "SRC In Rate Switch",
581f0b04d8bSKuninori Morimoto 			       rsnd_kctrl_accept_anytime,
58275916f65SKuninori Morimoto 			       rsnd_src_set_convert_rate,
58343cb6954SKuninori Morimoto 			       &src->sen, 1);
58443cb6954SKuninori Morimoto 	if (ret < 0)
58543cb6954SKuninori Morimoto 		return ret;
58643cb6954SKuninori Morimoto 
587b65a7cccSKuninori Morimoto 	ret = rsnd_kctrl_new_s(mod, io, rtd,
58843cb6954SKuninori Morimoto 			       rsnd_io_is_play(io) ?
58943cb6954SKuninori Morimoto 			       "SRC Out Rate" :
59043cb6954SKuninori Morimoto 			       "SRC In Rate",
591f0b04d8bSKuninori Morimoto 			       rsnd_kctrl_accept_runtime,
59275916f65SKuninori Morimoto 			       rsnd_src_set_convert_rate,
59343cb6954SKuninori Morimoto 			       &src->sync, 192000);
59443cb6954SKuninori Morimoto 
59543cb6954SKuninori Morimoto 	return ret;
59643cb6954SKuninori Morimoto }
59743cb6954SKuninori Morimoto 
59875916f65SKuninori Morimoto static struct rsnd_mod_ops rsnd_src_ops = {
5998aefda50SKuninori Morimoto 	.name		= SRC_NAME,
60072adc61fSKuninori Morimoto 	.dma_req	= rsnd_src_dma_req,
60175916f65SKuninori Morimoto 	.probe		= rsnd_src_probe_,
60275916f65SKuninori Morimoto 	.init		= rsnd_src_init,
60375916f65SKuninori Morimoto 	.quit		= rsnd_src_quit,
60475916f65SKuninori Morimoto 	.start		= rsnd_src_start,
60575916f65SKuninori Morimoto 	.stop		= rsnd_src_stop,
606b5b442abSKuninori Morimoto 	.irq		= rsnd_src_irq,
60775916f65SKuninori Morimoto 	.pcm_new	= rsnd_src_pcm_new,
6087e7fe06dSKuninori Morimoto 	.get_status	= rsnd_mod_get_status,
609ba9c949fSKuninori Morimoto };
610ba9c949fSKuninori Morimoto 
611ba9c949fSKuninori Morimoto struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
612ba9c949fSKuninori Morimoto {
613ba9c949fSKuninori Morimoto 	if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv)))
614ba9c949fSKuninori Morimoto 		id = 0;
615ba9c949fSKuninori Morimoto 
616adf6a681SKuninori Morimoto 	return rsnd_mod_get(rsnd_src_get(priv, id));
61790e8e50fSKuninori Morimoto }
61890e8e50fSKuninori Morimoto 
6192ea6b074SKuninori Morimoto int rsnd_src_probe(struct rsnd_priv *priv)
620ba9c949fSKuninori Morimoto {
621adf6a681SKuninori Morimoto 	struct device_node *node;
622adf6a681SKuninori Morimoto 	struct device_node *np;
623ba9c949fSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
624ba9c949fSKuninori Morimoto 	struct rsnd_src *src;
625ba9c949fSKuninori Morimoto 	struct clk *clk;
626ba9c949fSKuninori Morimoto 	char name[RSND_SRC_NAME_SIZE];
6272f78dd7fSKuninori Morimoto 	int i, nr, ret;
628ba9c949fSKuninori Morimoto 
629e8e7b7bdSKuninori Morimoto 	/* This driver doesn't support Gen1 at this point */
630e8e7b7bdSKuninori Morimoto 	if (rsnd_is_gen1(priv))
631e8e7b7bdSKuninori Morimoto 		return 0;
632033e7ed8SKuninori Morimoto 
633adf6a681SKuninori Morimoto 	node = rsnd_src_of_node(priv);
634adf6a681SKuninori Morimoto 	if (!node)
635adf6a681SKuninori Morimoto 		return 0; /* not used is not error */
63690e8e50fSKuninori Morimoto 
637adf6a681SKuninori Morimoto 	nr = of_get_child_count(node);
638adf6a681SKuninori Morimoto 	if (!nr) {
639adf6a681SKuninori Morimoto 		ret = -EINVAL;
640adf6a681SKuninori Morimoto 		goto rsnd_src_probe_done;
641adf6a681SKuninori Morimoto 	}
642ba9c949fSKuninori Morimoto 
643a86854d0SKees Cook 	src	= devm_kcalloc(dev, nr, sizeof(*src), GFP_KERNEL);
644adf6a681SKuninori Morimoto 	if (!src) {
645adf6a681SKuninori Morimoto 		ret = -ENOMEM;
646adf6a681SKuninori Morimoto 		goto rsnd_src_probe_done;
647adf6a681SKuninori Morimoto 	}
648ba9c949fSKuninori Morimoto 
649ba9c949fSKuninori Morimoto 	priv->src_nr	= nr;
650ba9c949fSKuninori Morimoto 	priv->src	= src;
651ba9c949fSKuninori Morimoto 
652adf6a681SKuninori Morimoto 	i = 0;
653adf6a681SKuninori Morimoto 	for_each_child_of_node(node, np) {
654de196515SSergei Shtylyov 		if (!of_device_is_available(np))
655de196515SSergei Shtylyov 			goto skip;
656de196515SSergei Shtylyov 
657adf6a681SKuninori Morimoto 		src = rsnd_src_get(priv, i);
658adf6a681SKuninori Morimoto 
6598aefda50SKuninori Morimoto 		snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d",
6608aefda50SKuninori Morimoto 			 SRC_NAME, i);
661ba9c949fSKuninori Morimoto 
662adf6a681SKuninori Morimoto 		src->irq = irq_of_parse_and_map(np, 0);
663adf6a681SKuninori Morimoto 		if (!src->irq) {
664adf6a681SKuninori Morimoto 			ret = -EINVAL;
66553ba2aa3SJulia Lawall 			of_node_put(np);
666adf6a681SKuninori Morimoto 			goto rsnd_src_probe_done;
667adf6a681SKuninori Morimoto 		}
668ba9c949fSKuninori Morimoto 
669adf6a681SKuninori Morimoto 		clk = devm_clk_get(dev, name);
670adf6a681SKuninori Morimoto 		if (IS_ERR(clk)) {
671adf6a681SKuninori Morimoto 			ret = PTR_ERR(clk);
67253ba2aa3SJulia Lawall 			of_node_put(np);
673adf6a681SKuninori Morimoto 			goto rsnd_src_probe_done;
674adf6a681SKuninori Morimoto 		}
675ba9c949fSKuninori Morimoto 
676e8e7b7bdSKuninori Morimoto 		ret = rsnd_mod_init(priv, rsnd_mod_get(src),
6777e7fe06dSKuninori Morimoto 				    &rsnd_src_ops, clk, RSND_MOD_SRC, i);
67853ba2aa3SJulia Lawall 		if (ret) {
67953ba2aa3SJulia Lawall 			of_node_put(np);
680adf6a681SKuninori Morimoto 			goto rsnd_src_probe_done;
68153ba2aa3SJulia Lawall 		}
682adf6a681SKuninori Morimoto 
683de196515SSergei Shtylyov skip:
684adf6a681SKuninori Morimoto 		i++;
685ba9c949fSKuninori Morimoto 	}
686ba9c949fSKuninori Morimoto 
687adf6a681SKuninori Morimoto 	ret = 0;
688adf6a681SKuninori Morimoto 
689adf6a681SKuninori Morimoto rsnd_src_probe_done:
690adf6a681SKuninori Morimoto 	of_node_put(node);
691adf6a681SKuninori Morimoto 
692adf6a681SKuninori Morimoto 	return ret;
693ba9c949fSKuninori Morimoto }
6942f78dd7fSKuninori Morimoto 
6952ea6b074SKuninori Morimoto void rsnd_src_remove(struct rsnd_priv *priv)
6962f78dd7fSKuninori Morimoto {
6972f78dd7fSKuninori Morimoto 	struct rsnd_src *src;
6982f78dd7fSKuninori Morimoto 	int i;
6992f78dd7fSKuninori Morimoto 
7002f78dd7fSKuninori Morimoto 	for_each_rsnd_src(src, priv, i) {
701b76e218aSKuninori Morimoto 		rsnd_mod_quit(rsnd_mod_get(src));
7022f78dd7fSKuninori Morimoto 	}
7032f78dd7fSKuninori Morimoto }
704