xref: /openbmc/linux/sound/soc/sh/rcar/src.c (revision 75916f6524f055bca134f50901f926d5b0693db5)
1ba9c949fSKuninori Morimoto /*
2ba9c949fSKuninori Morimoto  * Renesas R-Car SRC support
3ba9c949fSKuninori Morimoto  *
4ba9c949fSKuninori Morimoto  * Copyright (C) 2013 Renesas Solutions Corp.
5ba9c949fSKuninori Morimoto  * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6ba9c949fSKuninori Morimoto  *
7ba9c949fSKuninori Morimoto  * This program is free software; you can redistribute it and/or modify
8ba9c949fSKuninori Morimoto  * it under the terms of the GNU General Public License version 2 as
9ba9c949fSKuninori Morimoto  * published by the Free Software Foundation.
10ba9c949fSKuninori Morimoto  */
11ba9c949fSKuninori Morimoto #include "rsnd.h"
12ba9c949fSKuninori Morimoto 
138aefda50SKuninori Morimoto #define SRC_NAME "src"
148aefda50SKuninori Morimoto 
15cfcefe01SKuninori Morimoto /* SRCx_STATUS */
16cfcefe01SKuninori Morimoto #define OUF_SRCO	((1 << 12) | (1 << 13))
17cfcefe01SKuninori Morimoto #define OUF_SRCI	((1 <<  9) | (1 <<  8))
18cfcefe01SKuninori Morimoto 
19cfcefe01SKuninori Morimoto /* SCU_SYSTEM_STATUS0/1 */
20cfcefe01SKuninori Morimoto #define OUF_SRC(id)	((1 << (id + 16)) | (1 << id))
21cfcefe01SKuninori Morimoto 
22ba9c949fSKuninori Morimoto struct rsnd_src {
23ba9c949fSKuninori Morimoto 	struct rsnd_src_platform_info *info; /* rcar_snd.h */
24ba9c949fSKuninori Morimoto 	struct rsnd_mod mod;
25940e9479SKuninori Morimoto 	struct rsnd_mod *dma;
2643cb6954SKuninori Morimoto 	struct rsnd_kctrl_cfg_s sen;  /* sync convert enable */
2743cb6954SKuninori Morimoto 	struct rsnd_kctrl_cfg_s sync; /* sync convert */
283b7843ffSKuninori Morimoto 	u32 convert_rate; /* sampling rate convert */
29cfcefe01SKuninori Morimoto 	int err;
30ba9c949fSKuninori Morimoto };
31ba9c949fSKuninori Morimoto 
32ba9c949fSKuninori Morimoto #define RSND_SRC_NAME_SIZE 16
33ba9c949fSKuninori Morimoto 
34232c00b6SKuninori Morimoto #define rsnd_src_to_dma(src) ((src)->dma)
35da599fd3SKuninori Morimoto #define rsnd_src_nr(priv) ((priv)->src_nr)
3643cb6954SKuninori Morimoto #define rsnd_enable_sync_convert(src) ((src)->sen.val)
3782e76ed3SKuninori Morimoto #define rsnd_src_of_node(priv) \
3882e76ed3SKuninori Morimoto 	of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,src")
3982e76ed3SKuninori Morimoto 
40ba9c949fSKuninori Morimoto #define rsnd_mod_to_src(_mod)				\
41ba9c949fSKuninori Morimoto 	container_of((_mod), struct rsnd_src, mod)
42ba9c949fSKuninori Morimoto 
43ba9c949fSKuninori Morimoto #define for_each_rsnd_src(pos, priv, i)				\
44ba9c949fSKuninori Morimoto 	for ((i) = 0;						\
45ba9c949fSKuninori Morimoto 	     ((i) < rsnd_src_nr(priv)) &&			\
46ba9c949fSKuninori Morimoto 	     ((pos) = (struct rsnd_src *)(priv)->src + i);	\
47ba9c949fSKuninori Morimoto 	     i++)
48ba9c949fSKuninori Morimoto 
49ba9c949fSKuninori Morimoto 
50ba9c949fSKuninori Morimoto /*
51ba9c949fSKuninori Morimoto  *		image of SRC (Sampling Rate Converter)
52ba9c949fSKuninori Morimoto  *
53ba9c949fSKuninori Morimoto  * 96kHz   <-> +-----+	48kHz	+-----+	 48kHz	+-------+
54ba9c949fSKuninori Morimoto  * 48kHz   <-> | SRC | <------>	| SSI |	<----->	| codec |
55ba9c949fSKuninori Morimoto  * 44.1kHz <-> +-----+		+-----+		+-------+
56ba9c949fSKuninori Morimoto  * ...
57ba9c949fSKuninori Morimoto  *
58ba9c949fSKuninori Morimoto  */
59ba9c949fSKuninori Morimoto 
60ba9c949fSKuninori Morimoto /*
61ba9c949fSKuninori Morimoto  * src.c is caring...
62ba9c949fSKuninori Morimoto  *
63ba9c949fSKuninori Morimoto  * Gen1
64ba9c949fSKuninori Morimoto  *
65ba9c949fSKuninori Morimoto  * [mem] -> [SRU] -> [SSI]
66ba9c949fSKuninori Morimoto  *        |--------|
67ba9c949fSKuninori Morimoto  *
68ba9c949fSKuninori Morimoto  * Gen2
69ba9c949fSKuninori Morimoto  *
70ba9c949fSKuninori Morimoto  * [mem] -> [SRC] -> [SSIU] -> [SSI]
71ba9c949fSKuninori Morimoto  *        |-----------------|
72ba9c949fSKuninori Morimoto  */
73ba9c949fSKuninori Morimoto 
74ba9c949fSKuninori Morimoto /*
75ba9c949fSKuninori Morimoto  *	How to use SRC bypass mode for debugging
76ba9c949fSKuninori Morimoto  *
77ba9c949fSKuninori Morimoto  * SRC has bypass mode, and it is useful for debugging.
78ba9c949fSKuninori Morimoto  * In Gen2 case,
79ba9c949fSKuninori Morimoto  * SRCm_MODE controls whether SRC is used or not
80ba9c949fSKuninori Morimoto  * SSI_MODE0 controls whether SSIU which receives SRC data
81ba9c949fSKuninori Morimoto  * is used or not.
82ba9c949fSKuninori Morimoto  * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC,
83ba9c949fSKuninori Morimoto  * but SRC bypass mode needs SSI_MODE0 only.
84ba9c949fSKuninori Morimoto  *
85ba9c949fSKuninori Morimoto  * This driver request
86ba9c949fSKuninori Morimoto  * struct rsnd_src_platform_info {
87ba9c949fSKuninori Morimoto  *	u32 convert_rate;
8829e69fd2SKuninori Morimoto  *	int dma_id;
89ba9c949fSKuninori Morimoto  * }
90ba9c949fSKuninori Morimoto  *
91ba9c949fSKuninori Morimoto  * rsnd_src_convert_rate() indicates
92ba9c949fSKuninori Morimoto  * above convert_rate, and it controls
93ba9c949fSKuninori Morimoto  * whether SRC is used or not.
94ba9c949fSKuninori Morimoto  *
95ba9c949fSKuninori Morimoto  * ex) doesn't use SRC
9629e69fd2SKuninori Morimoto  * static struct rsnd_dai_platform_info rsnd_dai = {
9729e69fd2SKuninori Morimoto  *	.playback = { .ssi = &rsnd_ssi[0], },
98ba9c949fSKuninori Morimoto  * };
99ba9c949fSKuninori Morimoto  *
100ba9c949fSKuninori Morimoto  * ex) uses SRC
10129e69fd2SKuninori Morimoto  * static struct rsnd_src_platform_info rsnd_src[] = {
10229e69fd2SKuninori Morimoto  *	RSND_SCU(48000, 0),
10329e69fd2SKuninori Morimoto  *	...
10429e69fd2SKuninori Morimoto  * };
10529e69fd2SKuninori Morimoto  * static struct rsnd_dai_platform_info rsnd_dai = {
10629e69fd2SKuninori Morimoto  *	.playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[0] },
107ba9c949fSKuninori Morimoto  * };
108ba9c949fSKuninori Morimoto  *
109ba9c949fSKuninori Morimoto  * ex) uses SRC bypass mode
11029e69fd2SKuninori Morimoto  * static struct rsnd_src_platform_info rsnd_src[] = {
11129e69fd2SKuninori Morimoto  *	RSND_SCU(0, 0),
11229e69fd2SKuninori Morimoto  *	...
11329e69fd2SKuninori Morimoto  * };
11429e69fd2SKuninori Morimoto  * static struct rsnd_dai_platform_info rsnd_dai = {
11529e69fd2SKuninori Morimoto  *	.playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[0] },
116ba9c949fSKuninori Morimoto  * };
117ba9c949fSKuninori Morimoto  *
118ba9c949fSKuninori Morimoto  */
119ba9c949fSKuninori Morimoto 
120379febfdSKuninori Morimoto static void rsnd_src_soft_reset(struct rsnd_mod *mod)
121379febfdSKuninori Morimoto {
122379febfdSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SWRSR, 0);
123379febfdSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SWRSR, 1);
124379febfdSKuninori Morimoto }
125379febfdSKuninori Morimoto 
1269b99e9a7SKuninori Morimoto static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io,
1279b99e9a7SKuninori Morimoto 					 struct rsnd_mod *mod)
12872adc61fSKuninori Morimoto {
12972adc61fSKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
13072adc61fSKuninori Morimoto 	int is_play = rsnd_io_is_play(io);
13172adc61fSKuninori Morimoto 
13272adc61fSKuninori Morimoto 	return rsnd_dma_request_channel(rsnd_src_of_node(priv),
13372adc61fSKuninori Morimoto 					mod,
13472adc61fSKuninori Morimoto 					is_play ? "rx" : "tx");
13572adc61fSKuninori Morimoto }
13672adc61fSKuninori Morimoto 
13788c61cffSKuninori Morimoto static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io,
13888c61cffSKuninori Morimoto 				 struct rsnd_src *src)
13943cb6954SKuninori Morimoto {
14043cb6954SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
14143cb6954SKuninori Morimoto 	u32 convert_rate;
14243cb6954SKuninori Morimoto 
14343cb6954SKuninori Morimoto 	if (!runtime)
14443cb6954SKuninori Morimoto 		return 0;
14543cb6954SKuninori Morimoto 
14643cb6954SKuninori Morimoto 	if (!rsnd_enable_sync_convert(src))
14743cb6954SKuninori Morimoto 		return src->convert_rate;
14843cb6954SKuninori Morimoto 
14943cb6954SKuninori Morimoto 	convert_rate = src->sync.val;
15043cb6954SKuninori Morimoto 
15143cb6954SKuninori Morimoto 	if (!convert_rate)
15243cb6954SKuninori Morimoto 		convert_rate = src->convert_rate;
15343cb6954SKuninori Morimoto 
15443cb6954SKuninori Morimoto 	if (!convert_rate)
15543cb6954SKuninori Morimoto 		convert_rate = runtime->rate;
15643cb6954SKuninori Morimoto 
15743cb6954SKuninori Morimoto 	return convert_rate;
15843cb6954SKuninori Morimoto }
15943cb6954SKuninori Morimoto 
160ba9c949fSKuninori Morimoto unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
161ba9c949fSKuninori Morimoto 				   struct rsnd_dai_stream *io,
162ba9c949fSKuninori Morimoto 				   struct snd_pcm_runtime *runtime)
163ba9c949fSKuninori Morimoto {
164b1eac430SKuninori Morimoto 	struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
165ba9c949fSKuninori Morimoto 	struct rsnd_src *src;
166b1eac430SKuninori Morimoto 	unsigned int rate = 0;
167ba9c949fSKuninori Morimoto 
168b1eac430SKuninori Morimoto 	if (src_mod) {
169b1eac430SKuninori Morimoto 		src = rsnd_mod_to_src(src_mod);
170ba9c949fSKuninori Morimoto 
171ba9c949fSKuninori Morimoto 		/*
172ba9c949fSKuninori Morimoto 		 * return convert rate if SRC is used,
173ba9c949fSKuninori Morimoto 		 * otherwise, return runtime->rate as usual
174ba9c949fSKuninori Morimoto 		 */
17588c61cffSKuninori Morimoto 		rate = rsnd_src_convert_rate(io, src);
176b1eac430SKuninori Morimoto 	}
177b1eac430SKuninori Morimoto 
178ba9c949fSKuninori Morimoto 	if (!rate)
179ba9c949fSKuninori Morimoto 		rate = runtime->rate;
180ba9c949fSKuninori Morimoto 
181ba9c949fSKuninori Morimoto 	return rate;
182ba9c949fSKuninori Morimoto }
183ba9c949fSKuninori Morimoto 
1843b7843ffSKuninori Morimoto static int rsnd_src_hw_params(struct rsnd_mod *mod,
1852c0fac19SKuninori Morimoto 			      struct rsnd_dai_stream *io,
1863b7843ffSKuninori Morimoto 			      struct snd_pcm_substream *substream,
1873b7843ffSKuninori Morimoto 			      struct snd_pcm_hw_params *fe_params)
1883b7843ffSKuninori Morimoto {
1893b7843ffSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
1903b7843ffSKuninori Morimoto 	struct snd_soc_pcm_runtime *fe = substream->private_data;
1913b7843ffSKuninori Morimoto 
1923b7843ffSKuninori Morimoto 	/* default value (mainly for non-DT) */
1933b7843ffSKuninori Morimoto 	src->convert_rate = src->info->convert_rate;
1943b7843ffSKuninori Morimoto 
1953b7843ffSKuninori Morimoto 	/*
1963b7843ffSKuninori Morimoto 	 * SRC assumes that it is used under DPCM if user want to use
1973b7843ffSKuninori Morimoto 	 * sampling rate convert. Then, SRC should be FE.
1983b7843ffSKuninori Morimoto 	 * And then, this function will be called *after* BE settings.
1993b7843ffSKuninori Morimoto 	 * this means, each BE already has fixuped hw_params.
2003b7843ffSKuninori Morimoto 	 * see
2013b7843ffSKuninori Morimoto 	 *	dpcm_fe_dai_hw_params()
2023b7843ffSKuninori Morimoto 	 *	dpcm_be_dai_hw_params()
2033b7843ffSKuninori Morimoto 	 */
2043b7843ffSKuninori Morimoto 	if (fe->dai_link->dynamic) {
2053b7843ffSKuninori Morimoto 		int stream = substream->stream;
2063b7843ffSKuninori Morimoto 		struct snd_soc_dpcm *dpcm;
2073b7843ffSKuninori Morimoto 		struct snd_pcm_hw_params *be_params;
2083b7843ffSKuninori Morimoto 
2093b7843ffSKuninori Morimoto 		list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
2103b7843ffSKuninori Morimoto 			be_params = &dpcm->hw_params;
2113b7843ffSKuninori Morimoto 
2123b7843ffSKuninori Morimoto 			if (params_rate(fe_params) != params_rate(be_params))
2133b7843ffSKuninori Morimoto 				src->convert_rate = params_rate(be_params);
2143b7843ffSKuninori Morimoto 		}
2153b7843ffSKuninori Morimoto 	}
2163b7843ffSKuninori Morimoto 
2173b7843ffSKuninori Morimoto 	return 0;
2183b7843ffSKuninori Morimoto }
2193b7843ffSKuninori Morimoto 
220*75916f65SKuninori Morimoto static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
221*75916f65SKuninori Morimoto 				      struct rsnd_mod *mod)
222ba9c949fSKuninori Morimoto {
223*75916f65SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
224cfcefe01SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
225*75916f65SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
226*75916f65SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
227*75916f65SKuninori Morimoto 	u32 convert_rate = rsnd_src_convert_rate(io, src);
228*75916f65SKuninori Morimoto 	u32 ifscr, fsrate, adinr;
229*75916f65SKuninori Morimoto 	u32 cr, route;
230*75916f65SKuninori Morimoto 	u32 bsdsr, bsisr;
231*75916f65SKuninori Morimoto 	uint ratio;
232ba9c949fSKuninori Morimoto 
233*75916f65SKuninori Morimoto 	if (!runtime)
234*75916f65SKuninori Morimoto 		return;
235ba9c949fSKuninori Morimoto 
236*75916f65SKuninori Morimoto 	/* 6 - 1/6 are very enough ratio for SRC_BSDSR */
237*75916f65SKuninori Morimoto 	if (!convert_rate)
238*75916f65SKuninori Morimoto 		ratio = 0;
239*75916f65SKuninori Morimoto 	else if (convert_rate > runtime->rate)
240*75916f65SKuninori Morimoto 		ratio = 100 * convert_rate / runtime->rate;
241*75916f65SKuninori Morimoto 	else
242*75916f65SKuninori Morimoto 		ratio = 100 * runtime->rate / convert_rate;
243cfcefe01SKuninori Morimoto 
244*75916f65SKuninori Morimoto 	if (ratio > 600) {
245*75916f65SKuninori Morimoto 		dev_err(dev, "FSO/FSI ratio error\n");
246*75916f65SKuninori Morimoto 		return;
247ba9c949fSKuninori Morimoto 	}
248ba9c949fSKuninori Morimoto 
249ba9c949fSKuninori Morimoto 	/*
250*75916f65SKuninori Morimoto 	 *	SRC_ADINR
251ba9c949fSKuninori Morimoto 	 */
252*75916f65SKuninori Morimoto 	adinr = rsnd_get_adinr_bit(mod, io);
253*75916f65SKuninori Morimoto 
254*75916f65SKuninori Morimoto 	/*
255*75916f65SKuninori Morimoto 	 *	SRC_IFSCR / SRC_IFSVR
256*75916f65SKuninori Morimoto 	 */
257*75916f65SKuninori Morimoto 	ifscr = 0;
258*75916f65SKuninori Morimoto 	fsrate = 0;
259*75916f65SKuninori Morimoto 	if (convert_rate) {
260*75916f65SKuninori Morimoto 		ifscr = 1;
261*75916f65SKuninori Morimoto 		fsrate = 0x0400000 / convert_rate * runtime->rate;
262*75916f65SKuninori Morimoto 	}
263*75916f65SKuninori Morimoto 
264*75916f65SKuninori Morimoto 	/*
265*75916f65SKuninori Morimoto 	 *	SRC_SRCCR / SRC_ROUTE_MODE0
266*75916f65SKuninori Morimoto 	 */
267*75916f65SKuninori Morimoto 	cr	= 0x00011110;
268*75916f65SKuninori Morimoto 	route	= 0x0;
269*75916f65SKuninori Morimoto 	if (convert_rate) {
270*75916f65SKuninori Morimoto 		route	= 0x1;
271*75916f65SKuninori Morimoto 
272*75916f65SKuninori Morimoto 		if (rsnd_enable_sync_convert(src)) {
273*75916f65SKuninori Morimoto 			cr |= 0x1;
274*75916f65SKuninori Morimoto 			route |= rsnd_io_is_play(io) ?
275*75916f65SKuninori Morimoto 				(0x1 << 24) : (0x1 << 25);
276*75916f65SKuninori Morimoto 		}
277*75916f65SKuninori Morimoto 	}
278*75916f65SKuninori Morimoto 
279*75916f65SKuninori Morimoto 	/*
280*75916f65SKuninori Morimoto 	 * SRC_BSDSR / SRC_BSISR
281*75916f65SKuninori Morimoto 	 */
282*75916f65SKuninori Morimoto 	switch (rsnd_mod_id(mod)) {
283*75916f65SKuninori Morimoto 	case 5:
284*75916f65SKuninori Morimoto 	case 6:
285*75916f65SKuninori Morimoto 	case 7:
286*75916f65SKuninori Morimoto 	case 8:
287*75916f65SKuninori Morimoto 		bsdsr = 0x02400000; /* 6 - 1/6 */
288*75916f65SKuninori Morimoto 		bsisr = 0x00100060; /* 6 - 1/6 */
289*75916f65SKuninori Morimoto 		break;
290*75916f65SKuninori Morimoto 	default:
291*75916f65SKuninori Morimoto 		bsdsr = 0x01800000; /* 6 - 1/6 */
292*75916f65SKuninori Morimoto 		bsisr = 0x00100060 ;/* 6 - 1/6 */
293*75916f65SKuninori Morimoto 		break;
294*75916f65SKuninori Morimoto 	}
295*75916f65SKuninori Morimoto 
296*75916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCIR, 1);	/* initialize */
297*75916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_ADINR, adinr);
298*75916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_IFSCR, ifscr);
299*75916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_IFSVR, fsrate);
300*75916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCCR, cr);
301*75916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BSDSR, bsdsr);
302*75916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BSISR, bsisr);
303*75916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCIR, 0);	/* cancel initialize */
304*75916f65SKuninori Morimoto 
305*75916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_ROUTE_MODE0, route);
306*75916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BUSIF_MODE, 1);
307*75916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
308*75916f65SKuninori Morimoto 
309*75916f65SKuninori Morimoto 	if (convert_rate)
310*75916f65SKuninori Morimoto 		rsnd_adg_set_convert_clk_gen2(mod, io,
311*75916f65SKuninori Morimoto 					      runtime->rate,
312*75916f65SKuninori Morimoto 					      convert_rate);
313*75916f65SKuninori Morimoto 	else
314*75916f65SKuninori Morimoto 		rsnd_adg_set_convert_timing_gen2(mod, io);
315*75916f65SKuninori Morimoto }
316*75916f65SKuninori Morimoto 
317*75916f65SKuninori Morimoto #define rsnd_src_irq_enable(mod)  rsnd_src_irq_ctrol(mod, 1)
318*75916f65SKuninori Morimoto #define rsnd_src_irq_disable(mod) rsnd_src_irq_ctrol(mod, 0)
319*75916f65SKuninori Morimoto static void rsnd_src_irq_ctrol(struct rsnd_mod *mod, int enable)
320cfcefe01SKuninori Morimoto {
321cfcefe01SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
322cfcefe01SKuninori Morimoto 	u32 sys_int_val, int_val, sys_int_mask;
323cfcefe01SKuninori Morimoto 	int irq = src->info->irq;
324cfcefe01SKuninori Morimoto 	int id = rsnd_mod_id(mod);
325cfcefe01SKuninori Morimoto 
326cfcefe01SKuninori Morimoto 	sys_int_val =
327cfcefe01SKuninori Morimoto 	sys_int_mask = OUF_SRC(id);
328cfcefe01SKuninori Morimoto 	int_val = 0x3300;
329cfcefe01SKuninori Morimoto 
330cfcefe01SKuninori Morimoto 	/*
331cfcefe01SKuninori Morimoto 	 * IRQ is not supported on non-DT
332cfcefe01SKuninori Morimoto 	 * see
333*75916f65SKuninori Morimoto 	 *	rsnd_src_probe_()
334cfcefe01SKuninori Morimoto 	 */
335cfcefe01SKuninori Morimoto 	if ((irq <= 0) || !enable) {
336cfcefe01SKuninori Morimoto 		sys_int_val = 0;
337cfcefe01SKuninori Morimoto 		int_val = 0;
338cfcefe01SKuninori Morimoto 	}
339cfcefe01SKuninori Morimoto 
3401a1bf58aSKuninori Morimoto 	/*
3411a1bf58aSKuninori Morimoto 	 * WORKAROUND
3421a1bf58aSKuninori Morimoto 	 *
3431a1bf58aSKuninori Morimoto 	 * ignore over flow error when rsnd_enable_sync_convert()
3441a1bf58aSKuninori Morimoto 	 */
3451a1bf58aSKuninori Morimoto 	if (rsnd_enable_sync_convert(src))
3461a1bf58aSKuninori Morimoto 		sys_int_val = sys_int_val & 0xffff;
3471a1bf58aSKuninori Morimoto 
348cfcefe01SKuninori Morimoto 	rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val);
349cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val);
350cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val);
351cfcefe01SKuninori Morimoto }
352cfcefe01SKuninori Morimoto 
353*75916f65SKuninori Morimoto static void rsnd_src_error_clear(struct rsnd_mod *mod)
354cfcefe01SKuninori Morimoto {
355cfcefe01SKuninori Morimoto 	u32 val = OUF_SRC(rsnd_mod_id(mod));
356cfcefe01SKuninori Morimoto 
357cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_STATUS0, val, val);
358cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_STATUS1, val, val);
359cfcefe01SKuninori Morimoto }
360cfcefe01SKuninori Morimoto 
361*75916f65SKuninori Morimoto static bool rsnd_src_error_record(struct rsnd_mod *mod)
362cfcefe01SKuninori Morimoto {
3631a1bf58aSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
3641a1bf58aSKuninori Morimoto 	u32 val0, val1;
365cfcefe01SKuninori Morimoto 	bool ret = false;
366cfcefe01SKuninori Morimoto 
3671a1bf58aSKuninori Morimoto 	val0 = val1 = OUF_SRC(rsnd_mod_id(mod));
3681a1bf58aSKuninori Morimoto 
3691a1bf58aSKuninori Morimoto 	/*
3701a1bf58aSKuninori Morimoto 	 * WORKAROUND
3711a1bf58aSKuninori Morimoto 	 *
3721a1bf58aSKuninori Morimoto 	 * ignore over flow error when rsnd_enable_sync_convert()
3731a1bf58aSKuninori Morimoto 	 */
3741a1bf58aSKuninori Morimoto 	if (rsnd_enable_sync_convert(src))
3751a1bf58aSKuninori Morimoto 		val0 = val0 & 0xffff;
3761a1bf58aSKuninori Morimoto 
3771a1bf58aSKuninori Morimoto 	if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val0) ||
3781a1bf58aSKuninori Morimoto 	    (rsnd_mod_read(mod, SCU_SYS_STATUS1) & val1)) {
379cfcefe01SKuninori Morimoto 		struct rsnd_src *src = rsnd_mod_to_src(mod);
380cfcefe01SKuninori Morimoto 
381cfcefe01SKuninori Morimoto 		src->err++;
382cfcefe01SKuninori Morimoto 		ret = true;
383cfcefe01SKuninori Morimoto 	}
384cfcefe01SKuninori Morimoto 
385cfcefe01SKuninori Morimoto 	/* clear error static */
386*75916f65SKuninori Morimoto 	rsnd_src_error_clear(mod);
387cfcefe01SKuninori Morimoto 
388cfcefe01SKuninori Morimoto 	return ret;
389cfcefe01SKuninori Morimoto }
390cfcefe01SKuninori Morimoto 
391*75916f65SKuninori Morimoto static int rsnd_src_start(struct rsnd_mod *mod,
392497debaaSKuninori Morimoto 			  struct rsnd_dai_stream *io,
393497debaaSKuninori Morimoto 			  struct rsnd_priv *priv)
394cfcefe01SKuninori Morimoto {
3951a1bf58aSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
3961a1bf58aSKuninori Morimoto 	u32 val;
3971a1bf58aSKuninori Morimoto 
3981a1bf58aSKuninori Morimoto 	/*
3991a1bf58aSKuninori Morimoto 	 * WORKAROUND
4001a1bf58aSKuninori Morimoto 	 *
4011a1bf58aSKuninori Morimoto 	 * Enable SRC output if you want to use sync convert together with DVC
4021a1bf58aSKuninori Morimoto 	 */
4031a1bf58aSKuninori Morimoto 	val = (rsnd_io_to_mod_dvc(io) && !rsnd_enable_sync_convert(src)) ?
4041a1bf58aSKuninori Morimoto 		0x01 : 0x11;
405cfcefe01SKuninori Morimoto 
406cfcefe01SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, val);
407cfcefe01SKuninori Morimoto 
408*75916f65SKuninori Morimoto 	return 0;
409*75916f65SKuninori Morimoto }
410cfcefe01SKuninori Morimoto 
411*75916f65SKuninori Morimoto static int rsnd_src_stop(struct rsnd_mod *mod,
412*75916f65SKuninori Morimoto 			 struct rsnd_dai_stream *io,
413*75916f65SKuninori Morimoto 			 struct rsnd_priv *priv)
414*75916f65SKuninori Morimoto {
415*75916f65SKuninori Morimoto 	/*
416*75916f65SKuninori Morimoto 	 * stop SRC output only
417*75916f65SKuninori Morimoto 	 * see rsnd_src_quit
418*75916f65SKuninori Morimoto 	 */
419*75916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, 0x01);
420cfcefe01SKuninori Morimoto 
421cfcefe01SKuninori Morimoto 	return 0;
422cfcefe01SKuninori Morimoto }
423cfcefe01SKuninori Morimoto 
424*75916f65SKuninori Morimoto static int rsnd_src_init(struct rsnd_mod *mod,
425497debaaSKuninori Morimoto 			 struct rsnd_dai_stream *io,
426497debaaSKuninori Morimoto 			 struct rsnd_priv *priv)
427cfcefe01SKuninori Morimoto {
428*75916f65SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
429cfcefe01SKuninori Morimoto 
430*75916f65SKuninori Morimoto 	rsnd_mod_power_on(mod);
431cfcefe01SKuninori Morimoto 
432*75916f65SKuninori Morimoto 	rsnd_src_soft_reset(mod);
433cfcefe01SKuninori Morimoto 
434*75916f65SKuninori Morimoto 	rsnd_src_set_convert_rate(io, mod);
435*75916f65SKuninori Morimoto 
436*75916f65SKuninori Morimoto 	rsnd_src_error_clear(mod);
437*75916f65SKuninori Morimoto 
438*75916f65SKuninori Morimoto 	rsnd_src_irq_enable(mod);
439*75916f65SKuninori Morimoto 
440*75916f65SKuninori Morimoto 	src->err = 0;
441*75916f65SKuninori Morimoto 
442*75916f65SKuninori Morimoto 	/* reset sync convert_rate */
443*75916f65SKuninori Morimoto 	src->sync.val = 0;
444*75916f65SKuninori Morimoto 
445*75916f65SKuninori Morimoto 	return 0;
446cfcefe01SKuninori Morimoto }
447cfcefe01SKuninori Morimoto 
448*75916f65SKuninori Morimoto static int rsnd_src_quit(struct rsnd_mod *mod,
449b761bf27SKuninori Morimoto 			 struct rsnd_dai_stream *io,
450b761bf27SKuninori Morimoto 			 struct rsnd_priv *priv)
451b761bf27SKuninori Morimoto {
452*75916f65SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
453*75916f65SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
454*75916f65SKuninori Morimoto 
455*75916f65SKuninori Morimoto 	rsnd_src_irq_disable(mod);
456*75916f65SKuninori Morimoto 
457b761bf27SKuninori Morimoto 	/* stop both out/in */
458b761bf27SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, 0);
459b761bf27SKuninori Morimoto 
460*75916f65SKuninori Morimoto 	rsnd_mod_power_off(mod);
461*75916f65SKuninori Morimoto 
462*75916f65SKuninori Morimoto 	if (src->err)
463*75916f65SKuninori Morimoto 		dev_warn(dev, "%s[%d] under/over flow err = %d\n",
464*75916f65SKuninori Morimoto 			 rsnd_mod_name(mod), rsnd_mod_id(mod), src->err);
465*75916f65SKuninori Morimoto 
466*75916f65SKuninori Morimoto 	src->convert_rate = 0;
467*75916f65SKuninori Morimoto 
468*75916f65SKuninori Morimoto 	/* reset sync convert_rate */
469*75916f65SKuninori Morimoto 	src->sync.val = 0;
470*75916f65SKuninori Morimoto 
471*75916f65SKuninori Morimoto 	return 0;
472b761bf27SKuninori Morimoto }
473b761bf27SKuninori Morimoto 
474*75916f65SKuninori Morimoto static void __rsnd_src_interrupt(struct rsnd_mod *mod,
47588c61cffSKuninori Morimoto 				 struct rsnd_dai_stream *io)
476cfcefe01SKuninori Morimoto {
47702299d98SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
47869e32a58SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
47969e32a58SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
480cfcefe01SKuninori Morimoto 
48102299d98SKuninori Morimoto 	spin_lock(&priv->lock);
48202299d98SKuninori Morimoto 
48302299d98SKuninori Morimoto 	/* ignore all cases if not working */
484d5bbe7deSKuninori Morimoto 	if (!rsnd_io_is_working(io))
485*75916f65SKuninori Morimoto 		goto rsnd_src_interrupt_out;
486cfcefe01SKuninori Morimoto 
487*75916f65SKuninori Morimoto 	if (rsnd_src_error_record(mod)) {
488cfcefe01SKuninori Morimoto 
489cfcefe01SKuninori Morimoto 		dev_dbg(dev, "%s[%d] restart\n",
490cfcefe01SKuninori Morimoto 			rsnd_mod_name(mod), rsnd_mod_id(mod));
491639b231fSKuninori Morimoto 
492*75916f65SKuninori Morimoto 		rsnd_src_stop(mod, io, priv);
493*75916f65SKuninori Morimoto 		rsnd_src_start(mod, io, priv);
49469e32a58SKuninori Morimoto 	}
49569e32a58SKuninori Morimoto 
49669e32a58SKuninori Morimoto 	if (src->err > 1024) {
497*75916f65SKuninori Morimoto 		rsnd_src_irq_disable(mod);
49869e32a58SKuninori Morimoto 
49969e32a58SKuninori Morimoto 		dev_warn(dev, "no more %s[%d] restart\n",
50069e32a58SKuninori Morimoto 			 rsnd_mod_name(mod), rsnd_mod_id(mod));
501cfcefe01SKuninori Morimoto 	}
50288c61cffSKuninori Morimoto 
503*75916f65SKuninori Morimoto rsnd_src_interrupt_out:
50402299d98SKuninori Morimoto 	spin_unlock(&priv->lock);
50588c61cffSKuninori Morimoto }
50688c61cffSKuninori Morimoto 
507*75916f65SKuninori Morimoto static irqreturn_t rsnd_src_interrupt(int irq, void *data)
50888c61cffSKuninori Morimoto {
50988c61cffSKuninori Morimoto 	struct rsnd_mod *mod = data;
51088c61cffSKuninori Morimoto 
511*75916f65SKuninori Morimoto 	rsnd_mod_interrupt(mod, __rsnd_src_interrupt);
512cfcefe01SKuninori Morimoto 
513cfcefe01SKuninori Morimoto 	return IRQ_HANDLED;
514cfcefe01SKuninori Morimoto }
515cfcefe01SKuninori Morimoto 
516*75916f65SKuninori Morimoto static int rsnd_src_probe_(struct rsnd_mod *mod,
5172c0fac19SKuninori Morimoto 			   struct rsnd_dai_stream *io,
518690602fcSKuninori Morimoto 			   struct rsnd_priv *priv)
519ba9c949fSKuninori Morimoto {
520ba9c949fSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
521ba9c949fSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
522cfcefe01SKuninori Morimoto 	int irq = src->info->irq;
523ba9c949fSKuninori Morimoto 	int ret;
524ba9c949fSKuninori Morimoto 
525cfcefe01SKuninori Morimoto 	if (irq > 0) {
526cfcefe01SKuninori Morimoto 		/*
527cfcefe01SKuninori Morimoto 		 * IRQ is not supported on non-DT
528cfcefe01SKuninori Morimoto 		 * see
529*75916f65SKuninori Morimoto 		 *	rsnd_src_irq_enable()
530cfcefe01SKuninori Morimoto 		 */
531cfcefe01SKuninori Morimoto 		ret = devm_request_irq(dev, irq,
532*75916f65SKuninori Morimoto 				       rsnd_src_interrupt,
533cfcefe01SKuninori Morimoto 				       IRQF_SHARED,
534cfcefe01SKuninori Morimoto 				       dev_name(dev), mod);
535cfcefe01SKuninori Morimoto 		if (ret)
536b543b52aSKuninori Morimoto 			return ret;
537cfcefe01SKuninori Morimoto 	}
538cfcefe01SKuninori Morimoto 
53981ecbb65SKuninori Morimoto 	src->dma = rsnd_dma_attach(io, mod, src->info->dma_id);
540232c00b6SKuninori Morimoto 	if (IS_ERR(src->dma))
541232c00b6SKuninori Morimoto 		return PTR_ERR(src->dma);
542cfcefe01SKuninori Morimoto 
543cfcefe01SKuninori Morimoto 	return ret;
544ba9c949fSKuninori Morimoto }
545ba9c949fSKuninori Morimoto 
546*75916f65SKuninori Morimoto static int rsnd_src_pcm_new(struct rsnd_mod *mod,
5472c0fac19SKuninori Morimoto 			    struct rsnd_dai_stream *io,
54843cb6954SKuninori Morimoto 			    struct snd_soc_pcm_runtime *rtd)
54943cb6954SKuninori Morimoto {
55043cb6954SKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
55143cb6954SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
55243cb6954SKuninori Morimoto 	int ret;
55343cb6954SKuninori Morimoto 
55443cb6954SKuninori Morimoto 	/*
55543cb6954SKuninori Morimoto 	 * enable SRC sync convert if possible
55643cb6954SKuninori Morimoto 	 */
55743cb6954SKuninori Morimoto 
55843cb6954SKuninori Morimoto 	/*
55943cb6954SKuninori Morimoto 	 * SRC sync convert needs clock master
56043cb6954SKuninori Morimoto 	 */
56143cb6954SKuninori Morimoto 	if (!rsnd_rdai_is_clk_master(rdai))
56243cb6954SKuninori Morimoto 		return 0;
56343cb6954SKuninori Morimoto 
56443cb6954SKuninori Morimoto 	/*
56543cb6954SKuninori Morimoto 	 * enable sync convert
56643cb6954SKuninori Morimoto 	 */
567b65a7cccSKuninori Morimoto 	ret = rsnd_kctrl_new_s(mod, io, rtd,
56843cb6954SKuninori Morimoto 			       rsnd_io_is_play(io) ?
56943cb6954SKuninori Morimoto 			       "SRC Out Rate Switch" :
57043cb6954SKuninori Morimoto 			       "SRC In Rate Switch",
571*75916f65SKuninori Morimoto 			       rsnd_src_set_convert_rate,
57243cb6954SKuninori Morimoto 			       &src->sen, 1);
57343cb6954SKuninori Morimoto 	if (ret < 0)
57443cb6954SKuninori Morimoto 		return ret;
57543cb6954SKuninori Morimoto 
576b65a7cccSKuninori Morimoto 	ret = rsnd_kctrl_new_s(mod, io, rtd,
57743cb6954SKuninori Morimoto 			       rsnd_io_is_play(io) ?
57843cb6954SKuninori Morimoto 			       "SRC Out Rate" :
57943cb6954SKuninori Morimoto 			       "SRC In Rate",
580*75916f65SKuninori Morimoto 			       rsnd_src_set_convert_rate,
58143cb6954SKuninori Morimoto 			       &src->sync, 192000);
58243cb6954SKuninori Morimoto 
58343cb6954SKuninori Morimoto 	return ret;
58443cb6954SKuninori Morimoto }
58543cb6954SKuninori Morimoto 
586*75916f65SKuninori Morimoto static struct rsnd_mod_ops rsnd_src_ops = {
5878aefda50SKuninori Morimoto 	.name	= SRC_NAME,
58872adc61fSKuninori Morimoto 	.dma_req = rsnd_src_dma_req,
589*75916f65SKuninori Morimoto 	.probe	= rsnd_src_probe_,
590*75916f65SKuninori Morimoto 	.init	= rsnd_src_init,
591*75916f65SKuninori Morimoto 	.quit	= rsnd_src_quit,
592*75916f65SKuninori Morimoto 	.start	= rsnd_src_start,
593*75916f65SKuninori Morimoto 	.stop	= rsnd_src_stop,
5943b7843ffSKuninori Morimoto 	.hw_params = rsnd_src_hw_params,
595*75916f65SKuninori Morimoto 	.pcm_new = rsnd_src_pcm_new,
596ba9c949fSKuninori Morimoto };
597ba9c949fSKuninori Morimoto 
598ba9c949fSKuninori Morimoto struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
599ba9c949fSKuninori Morimoto {
600ba9c949fSKuninori Morimoto 	if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv)))
601ba9c949fSKuninori Morimoto 		id = 0;
602ba9c949fSKuninori Morimoto 
603b76e218aSKuninori Morimoto 	return rsnd_mod_get((struct rsnd_src *)(priv->src) + id);
604ba9c949fSKuninori Morimoto }
605ba9c949fSKuninori Morimoto 
60690e8e50fSKuninori Morimoto static void rsnd_of_parse_src(struct platform_device *pdev,
60790e8e50fSKuninori Morimoto 			      const struct rsnd_of_data *of_data,
60890e8e50fSKuninori Morimoto 			      struct rsnd_priv *priv)
60990e8e50fSKuninori Morimoto {
61090e8e50fSKuninori Morimoto 	struct device_node *src_node;
611cfcefe01SKuninori Morimoto 	struct device_node *np;
61290e8e50fSKuninori Morimoto 	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
61390e8e50fSKuninori Morimoto 	struct rsnd_src_platform_info *src_info;
61490e8e50fSKuninori Morimoto 	struct device *dev = &pdev->dev;
615cfcefe01SKuninori Morimoto 	int nr, i;
61690e8e50fSKuninori Morimoto 
61790e8e50fSKuninori Morimoto 	if (!of_data)
61890e8e50fSKuninori Morimoto 		return;
61990e8e50fSKuninori Morimoto 
62082e76ed3SKuninori Morimoto 	src_node = rsnd_src_of_node(priv);
62190e8e50fSKuninori Morimoto 	if (!src_node)
62290e8e50fSKuninori Morimoto 		return;
62390e8e50fSKuninori Morimoto 
62490e8e50fSKuninori Morimoto 	nr = of_get_child_count(src_node);
62590e8e50fSKuninori Morimoto 	if (!nr)
626f451e48dSKuninori Morimoto 		goto rsnd_of_parse_src_end;
62790e8e50fSKuninori Morimoto 
62890e8e50fSKuninori Morimoto 	src_info = devm_kzalloc(dev,
62990e8e50fSKuninori Morimoto 				sizeof(struct rsnd_src_platform_info) * nr,
63090e8e50fSKuninori Morimoto 				GFP_KERNEL);
63190e8e50fSKuninori Morimoto 	if (!src_info) {
63290e8e50fSKuninori Morimoto 		dev_err(dev, "src info allocation error\n");
633f451e48dSKuninori Morimoto 		goto rsnd_of_parse_src_end;
63490e8e50fSKuninori Morimoto 	}
63590e8e50fSKuninori Morimoto 
63690e8e50fSKuninori Morimoto 	info->src_info		= src_info;
63790e8e50fSKuninori Morimoto 	info->src_info_nr	= nr;
638f451e48dSKuninori Morimoto 
639cfcefe01SKuninori Morimoto 	i = 0;
640cfcefe01SKuninori Morimoto 	for_each_child_of_node(src_node, np) {
641cfcefe01SKuninori Morimoto 		src_info[i].irq = irq_of_parse_and_map(np, 0);
642cfcefe01SKuninori Morimoto 
643cfcefe01SKuninori Morimoto 		i++;
644cfcefe01SKuninori Morimoto 	}
645cfcefe01SKuninori Morimoto 
646f451e48dSKuninori Morimoto rsnd_of_parse_src_end:
647f451e48dSKuninori Morimoto 	of_node_put(src_node);
64890e8e50fSKuninori Morimoto }
64990e8e50fSKuninori Morimoto 
650ba9c949fSKuninori Morimoto int rsnd_src_probe(struct platform_device *pdev,
65190e8e50fSKuninori Morimoto 		   const struct rsnd_of_data *of_data,
652ba9c949fSKuninori Morimoto 		   struct rsnd_priv *priv)
653ba9c949fSKuninori Morimoto {
654ba9c949fSKuninori Morimoto 	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
655ba9c949fSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
656ba9c949fSKuninori Morimoto 	struct rsnd_src *src;
657ba9c949fSKuninori Morimoto 	struct clk *clk;
658ba9c949fSKuninori Morimoto 	char name[RSND_SRC_NAME_SIZE];
6592f78dd7fSKuninori Morimoto 	int i, nr, ret;
660ba9c949fSKuninori Morimoto 
661e8e7b7bdSKuninori Morimoto 	/* This driver doesn't support Gen1 at this point */
662e8e7b7bdSKuninori Morimoto 	if (rsnd_is_gen1(priv))
663e8e7b7bdSKuninori Morimoto 		return 0;
664033e7ed8SKuninori Morimoto 
66590e8e50fSKuninori Morimoto 	rsnd_of_parse_src(pdev, of_data, priv);
66690e8e50fSKuninori Morimoto 
667ba9c949fSKuninori Morimoto 	/*
668ba9c949fSKuninori Morimoto 	 * init SRC
669ba9c949fSKuninori Morimoto 	 */
670ba9c949fSKuninori Morimoto 	nr	= info->src_info_nr;
671ba9c949fSKuninori Morimoto 	if (!nr)
672ba9c949fSKuninori Morimoto 		return 0;
673ba9c949fSKuninori Morimoto 
674ba9c949fSKuninori Morimoto 	src	= devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL);
67533363f7aSKuninori Morimoto 	if (!src)
676ba9c949fSKuninori Morimoto 		return -ENOMEM;
677ba9c949fSKuninori Morimoto 
678ba9c949fSKuninori Morimoto 	priv->src_nr	= nr;
679ba9c949fSKuninori Morimoto 	priv->src	= src;
680ba9c949fSKuninori Morimoto 
681ba9c949fSKuninori Morimoto 	for_each_rsnd_src(src, priv, i) {
6828aefda50SKuninori Morimoto 		snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d",
6838aefda50SKuninori Morimoto 			 SRC_NAME, i);
684ba9c949fSKuninori Morimoto 
685ba9c949fSKuninori Morimoto 		clk = devm_clk_get(dev, name);
686ba9c949fSKuninori Morimoto 		if (IS_ERR(clk))
687ba9c949fSKuninori Morimoto 			return PTR_ERR(clk);
688ba9c949fSKuninori Morimoto 
689ba9c949fSKuninori Morimoto 		src->info = &info->src_info[i];
690ba9c949fSKuninori Morimoto 
691e8e7b7bdSKuninori Morimoto 		ret = rsnd_mod_init(priv, rsnd_mod_get(src),
692*75916f65SKuninori Morimoto 				    &rsnd_src_ops, clk, RSND_MOD_SRC, i);
6932f78dd7fSKuninori Morimoto 		if (ret)
6942f78dd7fSKuninori Morimoto 			return ret;
695ba9c949fSKuninori Morimoto 	}
696ba9c949fSKuninori Morimoto 
697ba9c949fSKuninori Morimoto 	return 0;
698ba9c949fSKuninori Morimoto }
6992f78dd7fSKuninori Morimoto 
7002f78dd7fSKuninori Morimoto void rsnd_src_remove(struct platform_device *pdev,
7012f78dd7fSKuninori Morimoto 		     struct rsnd_priv *priv)
7022f78dd7fSKuninori Morimoto {
7032f78dd7fSKuninori Morimoto 	struct rsnd_src *src;
7042f78dd7fSKuninori Morimoto 	int i;
7052f78dd7fSKuninori Morimoto 
7062f78dd7fSKuninori Morimoto 	for_each_rsnd_src(src, priv, i) {
707b76e218aSKuninori Morimoto 		rsnd_mod_quit(rsnd_mod_get(src));
7082f78dd7fSKuninori Morimoto 	}
7092f78dd7fSKuninori Morimoto }
710