xref: /openbmc/linux/sound/soc/sh/rcar/src.c (revision e8e7b7bdc65c19f8d84c25f7e0d21176d598c870)
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 
120ba9c949fSKuninori Morimoto /*
121ba9c949fSKuninori Morimoto  *		Gen1/Gen2 common functions
122ba9c949fSKuninori Morimoto  */
123379febfdSKuninori Morimoto static void rsnd_src_soft_reset(struct rsnd_mod *mod)
124379febfdSKuninori Morimoto {
125379febfdSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SWRSR, 0);
126379febfdSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SWRSR, 1);
127379febfdSKuninori Morimoto }
128379febfdSKuninori Morimoto 
129d1ade514SKuninori Morimoto 
130d1ade514SKuninori Morimoto #define rsnd_src_initialize_lock(mod)	__rsnd_src_initialize_lock(mod, 1)
131d1ade514SKuninori Morimoto #define rsnd_src_initialize_unlock(mod)	__rsnd_src_initialize_lock(mod, 0)
132d1ade514SKuninori Morimoto static void __rsnd_src_initialize_lock(struct rsnd_mod *mod, u32 enable)
133d1ade514SKuninori Morimoto {
134d1ade514SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCIR, enable);
135d1ade514SKuninori Morimoto }
136d1ade514SKuninori Morimoto 
1379b99e9a7SKuninori Morimoto static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io,
1389b99e9a7SKuninori Morimoto 					 struct rsnd_mod *mod)
13972adc61fSKuninori Morimoto {
14072adc61fSKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
14172adc61fSKuninori Morimoto 	int is_play = rsnd_io_is_play(io);
14272adc61fSKuninori Morimoto 
14372adc61fSKuninori Morimoto 	return rsnd_dma_request_channel(rsnd_src_of_node(priv),
14472adc61fSKuninori Morimoto 					mod,
14572adc61fSKuninori Morimoto 					is_play ? "rx" : "tx");
14672adc61fSKuninori Morimoto }
14772adc61fSKuninori Morimoto 
14888c61cffSKuninori Morimoto static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io,
14988c61cffSKuninori Morimoto 				 struct rsnd_src *src)
15043cb6954SKuninori Morimoto {
15143cb6954SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
15243cb6954SKuninori Morimoto 	u32 convert_rate;
15343cb6954SKuninori Morimoto 
15443cb6954SKuninori Morimoto 	if (!runtime)
15543cb6954SKuninori Morimoto 		return 0;
15643cb6954SKuninori Morimoto 
15743cb6954SKuninori Morimoto 	if (!rsnd_enable_sync_convert(src))
15843cb6954SKuninori Morimoto 		return src->convert_rate;
15943cb6954SKuninori Morimoto 
16043cb6954SKuninori Morimoto 	convert_rate = src->sync.val;
16143cb6954SKuninori Morimoto 
16243cb6954SKuninori Morimoto 	if (!convert_rate)
16343cb6954SKuninori Morimoto 		convert_rate = src->convert_rate;
16443cb6954SKuninori Morimoto 
16543cb6954SKuninori Morimoto 	if (!convert_rate)
16643cb6954SKuninori Morimoto 		convert_rate = runtime->rate;
16743cb6954SKuninori Morimoto 
16843cb6954SKuninori Morimoto 	return convert_rate;
16943cb6954SKuninori Morimoto }
17043cb6954SKuninori Morimoto 
171ba9c949fSKuninori Morimoto unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
172ba9c949fSKuninori Morimoto 				   struct rsnd_dai_stream *io,
173ba9c949fSKuninori Morimoto 				   struct snd_pcm_runtime *runtime)
174ba9c949fSKuninori Morimoto {
175b1eac430SKuninori Morimoto 	struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
176ba9c949fSKuninori Morimoto 	struct rsnd_src *src;
177b1eac430SKuninori Morimoto 	unsigned int rate = 0;
178ba9c949fSKuninori Morimoto 
179b1eac430SKuninori Morimoto 	if (src_mod) {
180b1eac430SKuninori Morimoto 		src = rsnd_mod_to_src(src_mod);
181ba9c949fSKuninori Morimoto 
182ba9c949fSKuninori Morimoto 		/*
183ba9c949fSKuninori Morimoto 		 * return convert rate if SRC is used,
184ba9c949fSKuninori Morimoto 		 * otherwise, return runtime->rate as usual
185ba9c949fSKuninori Morimoto 		 */
18688c61cffSKuninori Morimoto 		rate = rsnd_src_convert_rate(io, src);
187b1eac430SKuninori Morimoto 	}
188b1eac430SKuninori Morimoto 
189ba9c949fSKuninori Morimoto 	if (!rate)
190ba9c949fSKuninori Morimoto 		rate = runtime->rate;
191ba9c949fSKuninori Morimoto 
192ba9c949fSKuninori Morimoto 	return rate;
193ba9c949fSKuninori Morimoto }
194ba9c949fSKuninori Morimoto 
1954e2639ffSKuninori Morimoto static int rsnd_src_set_convert_rate(struct rsnd_mod *mod,
1964e2639ffSKuninori Morimoto 				     struct rsnd_dai_stream *io)
197ba9c949fSKuninori Morimoto {
198ba9c949fSKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
199ba9c949fSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
20088c61cffSKuninori Morimoto 	u32 convert_rate = rsnd_src_convert_rate(io, src);
201ba9c949fSKuninori Morimoto 	u32 fsrate = 0;
202ba9c949fSKuninori Morimoto 
203ba9c949fSKuninori Morimoto 	if (convert_rate)
204ba9c949fSKuninori Morimoto 		fsrate = 0x0400000 / convert_rate * runtime->rate;
205ba9c949fSKuninori Morimoto 
206ba9c949fSKuninori Morimoto 	/* Set channel number and output bit length */
2073023b384SKuninori Morimoto 	rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr_bit(mod, io));
208ba9c949fSKuninori Morimoto 
209ba9c949fSKuninori Morimoto 	/* Enable the initial value of IFS */
210ba9c949fSKuninori Morimoto 	if (fsrate) {
211ba9c949fSKuninori Morimoto 		rsnd_mod_write(mod, SRC_IFSCR, 1);
212ba9c949fSKuninori Morimoto 
213ba9c949fSKuninori Morimoto 		/* Set initial value of IFS */
214ba9c949fSKuninori Morimoto 		rsnd_mod_write(mod, SRC_IFSVR, fsrate);
215ba9c949fSKuninori Morimoto 	}
216ba9c949fSKuninori Morimoto 
217ba9c949fSKuninori Morimoto 	/* use DMA transfer */
218ba9c949fSKuninori Morimoto 	rsnd_mod_write(mod, SRC_BUSIF_MODE, 1);
219ba9c949fSKuninori Morimoto 
220ba9c949fSKuninori Morimoto 	return 0;
221ba9c949fSKuninori Morimoto }
222ba9c949fSKuninori Morimoto 
2233b7843ffSKuninori Morimoto static int rsnd_src_hw_params(struct rsnd_mod *mod,
2242c0fac19SKuninori Morimoto 			      struct rsnd_dai_stream *io,
2253b7843ffSKuninori Morimoto 			      struct snd_pcm_substream *substream,
2263b7843ffSKuninori Morimoto 			      struct snd_pcm_hw_params *fe_params)
2273b7843ffSKuninori Morimoto {
2283b7843ffSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
2293b7843ffSKuninori Morimoto 	struct snd_soc_pcm_runtime *fe = substream->private_data;
2303b7843ffSKuninori Morimoto 
2313b7843ffSKuninori Morimoto 	/* default value (mainly for non-DT) */
2323b7843ffSKuninori Morimoto 	src->convert_rate = src->info->convert_rate;
2333b7843ffSKuninori Morimoto 
2343b7843ffSKuninori Morimoto 	/*
2353b7843ffSKuninori Morimoto 	 * SRC assumes that it is used under DPCM if user want to use
2363b7843ffSKuninori Morimoto 	 * sampling rate convert. Then, SRC should be FE.
2373b7843ffSKuninori Morimoto 	 * And then, this function will be called *after* BE settings.
2383b7843ffSKuninori Morimoto 	 * this means, each BE already has fixuped hw_params.
2393b7843ffSKuninori Morimoto 	 * see
2403b7843ffSKuninori Morimoto 	 *	dpcm_fe_dai_hw_params()
2413b7843ffSKuninori Morimoto 	 *	dpcm_be_dai_hw_params()
2423b7843ffSKuninori Morimoto 	 */
2433b7843ffSKuninori Morimoto 	if (fe->dai_link->dynamic) {
2443b7843ffSKuninori Morimoto 		int stream = substream->stream;
2453b7843ffSKuninori Morimoto 		struct snd_soc_dpcm *dpcm;
2463b7843ffSKuninori Morimoto 		struct snd_pcm_hw_params *be_params;
2473b7843ffSKuninori Morimoto 
2483b7843ffSKuninori Morimoto 		list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
2493b7843ffSKuninori Morimoto 			be_params = &dpcm->hw_params;
2503b7843ffSKuninori Morimoto 
2513b7843ffSKuninori Morimoto 			if (params_rate(fe_params) != params_rate(be_params))
2523b7843ffSKuninori Morimoto 				src->convert_rate = params_rate(be_params);
2533b7843ffSKuninori Morimoto 		}
2543b7843ffSKuninori Morimoto 	}
2553b7843ffSKuninori Morimoto 
2563b7843ffSKuninori Morimoto 	return 0;
2573b7843ffSKuninori Morimoto }
2583b7843ffSKuninori Morimoto 
2593b7843ffSKuninori Morimoto static int rsnd_src_init(struct rsnd_mod *mod,
2603b7843ffSKuninori Morimoto 			 struct rsnd_priv *priv)
261ba9c949fSKuninori Morimoto {
262ba9c949fSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
263ba9c949fSKuninori Morimoto 
264c9929345SKuninori Morimoto 	rsnd_mod_power_on(mod);
265ba9c949fSKuninori Morimoto 
266379febfdSKuninori Morimoto 	rsnd_src_soft_reset(mod);
267379febfdSKuninori Morimoto 
268d1ade514SKuninori Morimoto 	rsnd_src_initialize_lock(mod);
269d1ade514SKuninori Morimoto 
270cfcefe01SKuninori Morimoto 	src->err = 0;
271cfcefe01SKuninori Morimoto 
27243cb6954SKuninori Morimoto 	/* reset sync convert_rate */
27343cb6954SKuninori Morimoto 	src->sync.val = 0;
27443cb6954SKuninori Morimoto 
275ba9c949fSKuninori Morimoto 	return 0;
276ba9c949fSKuninori Morimoto }
277ba9c949fSKuninori Morimoto 
278ba9c949fSKuninori Morimoto static int rsnd_src_quit(struct rsnd_mod *mod,
2792c0fac19SKuninori Morimoto 			 struct rsnd_dai_stream *io,
280690602fcSKuninori Morimoto 			 struct rsnd_priv *priv)
281ba9c949fSKuninori Morimoto {
282ba9c949fSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
283cfcefe01SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
284ba9c949fSKuninori Morimoto 
285c9929345SKuninori Morimoto 	rsnd_mod_power_off(mod);
286ba9c949fSKuninori Morimoto 
287cfcefe01SKuninori Morimoto 	if (src->err)
288337b0b4cSKuninori Morimoto 		dev_warn(dev, "%s[%d] under/over flow err = %d\n",
289337b0b4cSKuninori Morimoto 			 rsnd_mod_name(mod), rsnd_mod_id(mod), src->err);
290cfcefe01SKuninori Morimoto 
2913b7843ffSKuninori Morimoto 	src->convert_rate = 0;
2923b7843ffSKuninori Morimoto 
29343cb6954SKuninori Morimoto 	/* reset sync convert_rate */
29443cb6954SKuninori Morimoto 	src->sync.val = 0;
29543cb6954SKuninori Morimoto 
296ba9c949fSKuninori Morimoto 	return 0;
297ba9c949fSKuninori Morimoto }
298ba9c949fSKuninori Morimoto 
299f0ef0cb8SKuninori Morimoto static int rsnd_src_start(struct rsnd_mod *mod)
300ba9c949fSKuninori Morimoto {
301d1ade514SKuninori Morimoto 	rsnd_src_initialize_unlock(mod);
302ba9c949fSKuninori Morimoto 
303ba9c949fSKuninori Morimoto 	return 0;
304ba9c949fSKuninori Morimoto }
305ba9c949fSKuninori Morimoto 
306f0ef0cb8SKuninori Morimoto static int rsnd_src_stop(struct rsnd_mod *mod)
307ba9c949fSKuninori Morimoto {
308933cc8cbSKuninori Morimoto 	/* nothing to do */
309ba9c949fSKuninori Morimoto 	return 0;
310ba9c949fSKuninori Morimoto }
311ba9c949fSKuninori Morimoto 
312ba9c949fSKuninori Morimoto /*
313ba9c949fSKuninori Morimoto  *		Gen2 functions
314ba9c949fSKuninori Morimoto  */
315cfcefe01SKuninori Morimoto #define rsnd_src_irq_enable_gen2(mod)  rsnd_src_irq_ctrol_gen2(mod, 1)
316cfcefe01SKuninori Morimoto #define rsnd_src_irq_disable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 0)
317cfcefe01SKuninori Morimoto static void rsnd_src_irq_ctrol_gen2(struct rsnd_mod *mod, int enable)
318cfcefe01SKuninori Morimoto {
319cfcefe01SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
320cfcefe01SKuninori Morimoto 	u32 sys_int_val, int_val, sys_int_mask;
321cfcefe01SKuninori Morimoto 	int irq = src->info->irq;
322cfcefe01SKuninori Morimoto 	int id = rsnd_mod_id(mod);
323cfcefe01SKuninori Morimoto 
324cfcefe01SKuninori Morimoto 	sys_int_val =
325cfcefe01SKuninori Morimoto 	sys_int_mask = OUF_SRC(id);
326cfcefe01SKuninori Morimoto 	int_val = 0x3300;
327cfcefe01SKuninori Morimoto 
328cfcefe01SKuninori Morimoto 	/*
329cfcefe01SKuninori Morimoto 	 * IRQ is not supported on non-DT
330cfcefe01SKuninori Morimoto 	 * see
331cfcefe01SKuninori Morimoto 	 *	rsnd_src_probe_gen2()
332cfcefe01SKuninori Morimoto 	 */
333cfcefe01SKuninori Morimoto 	if ((irq <= 0) || !enable) {
334cfcefe01SKuninori Morimoto 		sys_int_val = 0;
335cfcefe01SKuninori Morimoto 		int_val = 0;
336cfcefe01SKuninori Morimoto 	}
337cfcefe01SKuninori Morimoto 
3381a1bf58aSKuninori Morimoto 	/*
3391a1bf58aSKuninori Morimoto 	 * WORKAROUND
3401a1bf58aSKuninori Morimoto 	 *
3411a1bf58aSKuninori Morimoto 	 * ignore over flow error when rsnd_enable_sync_convert()
3421a1bf58aSKuninori Morimoto 	 */
3431a1bf58aSKuninori Morimoto 	if (rsnd_enable_sync_convert(src))
3441a1bf58aSKuninori Morimoto 		sys_int_val = sys_int_val & 0xffff;
3451a1bf58aSKuninori Morimoto 
346cfcefe01SKuninori Morimoto 	rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val);
347cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val);
348cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val);
349cfcefe01SKuninori Morimoto }
350cfcefe01SKuninori Morimoto 
351cfcefe01SKuninori Morimoto static void rsnd_src_error_clear_gen2(struct rsnd_mod *mod)
352cfcefe01SKuninori Morimoto {
353cfcefe01SKuninori Morimoto 	u32 val = OUF_SRC(rsnd_mod_id(mod));
354cfcefe01SKuninori Morimoto 
355cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_STATUS0, val, val);
356cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_STATUS1, val, val);
357cfcefe01SKuninori Morimoto }
358cfcefe01SKuninori Morimoto 
359cfcefe01SKuninori Morimoto static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod)
360cfcefe01SKuninori Morimoto {
3611a1bf58aSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
3621a1bf58aSKuninori Morimoto 	u32 val0, val1;
363cfcefe01SKuninori Morimoto 	bool ret = false;
364cfcefe01SKuninori Morimoto 
3651a1bf58aSKuninori Morimoto 	val0 = val1 = OUF_SRC(rsnd_mod_id(mod));
3661a1bf58aSKuninori Morimoto 
3671a1bf58aSKuninori Morimoto 	/*
3681a1bf58aSKuninori Morimoto 	 * WORKAROUND
3691a1bf58aSKuninori Morimoto 	 *
3701a1bf58aSKuninori Morimoto 	 * ignore over flow error when rsnd_enable_sync_convert()
3711a1bf58aSKuninori Morimoto 	 */
3721a1bf58aSKuninori Morimoto 	if (rsnd_enable_sync_convert(src))
3731a1bf58aSKuninori Morimoto 		val0 = val0 & 0xffff;
3741a1bf58aSKuninori Morimoto 
3751a1bf58aSKuninori Morimoto 	if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val0) ||
3761a1bf58aSKuninori Morimoto 	    (rsnd_mod_read(mod, SCU_SYS_STATUS1) & val1)) {
377cfcefe01SKuninori Morimoto 		struct rsnd_src *src = rsnd_mod_to_src(mod);
378cfcefe01SKuninori Morimoto 
379cfcefe01SKuninori Morimoto 		src->err++;
380cfcefe01SKuninori Morimoto 		ret = true;
381cfcefe01SKuninori Morimoto 	}
382cfcefe01SKuninori Morimoto 
383cfcefe01SKuninori Morimoto 	/* clear error static */
384cfcefe01SKuninori Morimoto 	rsnd_src_error_clear_gen2(mod);
385cfcefe01SKuninori Morimoto 
386cfcefe01SKuninori Morimoto 	return ret;
387cfcefe01SKuninori Morimoto }
388cfcefe01SKuninori Morimoto 
389497debaaSKuninori Morimoto static int rsnd_src_start_gen2(struct rsnd_mod *mod,
390497debaaSKuninori Morimoto 			       struct rsnd_dai_stream *io,
391497debaaSKuninori Morimoto 			       struct rsnd_priv *priv)
392cfcefe01SKuninori Morimoto {
3931a1bf58aSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
3941a1bf58aSKuninori Morimoto 	u32 val;
3951a1bf58aSKuninori Morimoto 
3964689032bSKuninori Morimoto 	val = rsnd_get_dalign(mod, io);
3974689032bSKuninori Morimoto 
3984689032bSKuninori Morimoto 	rsnd_mod_write(mod, SRC_BUSIF_DALIGN, val);
3994689032bSKuninori Morimoto 
4001a1bf58aSKuninori Morimoto 	/*
4011a1bf58aSKuninori Morimoto 	 * WORKAROUND
4021a1bf58aSKuninori Morimoto 	 *
4031a1bf58aSKuninori Morimoto 	 * Enable SRC output if you want to use sync convert together with DVC
4041a1bf58aSKuninori Morimoto 	 */
4051a1bf58aSKuninori Morimoto 	val = (rsnd_io_to_mod_dvc(io) && !rsnd_enable_sync_convert(src)) ?
4061a1bf58aSKuninori Morimoto 		0x01 : 0x11;
407cfcefe01SKuninori Morimoto 
408cfcefe01SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, val);
409cfcefe01SKuninori Morimoto 
410cfcefe01SKuninori Morimoto 	rsnd_src_error_clear_gen2(mod);
411cfcefe01SKuninori Morimoto 
412cfcefe01SKuninori Morimoto 	rsnd_src_start(mod);
413cfcefe01SKuninori Morimoto 
414cfcefe01SKuninori Morimoto 	rsnd_src_irq_enable_gen2(mod);
415cfcefe01SKuninori Morimoto 
416cfcefe01SKuninori Morimoto 	return 0;
417cfcefe01SKuninori Morimoto }
418cfcefe01SKuninori Morimoto 
419497debaaSKuninori Morimoto static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
420497debaaSKuninori Morimoto 			      struct rsnd_dai_stream *io,
421497debaaSKuninori Morimoto 			      struct rsnd_priv *priv)
422cfcefe01SKuninori Morimoto {
423cfcefe01SKuninori Morimoto 	rsnd_src_irq_disable_gen2(mod);
424cfcefe01SKuninori Morimoto 
425b761bf27SKuninori Morimoto 	/*
426b761bf27SKuninori Morimoto 	 * stop SRC output only
427b761bf27SKuninori Morimoto 	 * see rsnd_src_quit_gen2
428b761bf27SKuninori Morimoto 	 */
429b761bf27SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, 0x01);
430cfcefe01SKuninori Morimoto 
431cfcefe01SKuninori Morimoto 	rsnd_src_error_record_gen2(mod);
432cfcefe01SKuninori Morimoto 
433cfcefe01SKuninori Morimoto 	return rsnd_src_stop(mod);
434cfcefe01SKuninori Morimoto }
435cfcefe01SKuninori Morimoto 
436b761bf27SKuninori Morimoto static int rsnd_src_quit_gen2(struct rsnd_mod *mod,
437b761bf27SKuninori Morimoto 			      struct rsnd_dai_stream *io,
438b761bf27SKuninori Morimoto 			      struct rsnd_priv *priv)
439b761bf27SKuninori Morimoto {
440b761bf27SKuninori Morimoto 	/* stop both out/in */
441b761bf27SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, 0);
442b761bf27SKuninori Morimoto 
443f36a8226SKuninori Morimoto 	return rsnd_src_quit(mod, io, priv);
444b761bf27SKuninori Morimoto }
445b761bf27SKuninori Morimoto 
44688c61cffSKuninori Morimoto static void __rsnd_src_interrupt_gen2(struct rsnd_mod *mod,
44788c61cffSKuninori Morimoto 				      struct rsnd_dai_stream *io)
448cfcefe01SKuninori Morimoto {
44902299d98SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
45069e32a58SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
45169e32a58SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
452cfcefe01SKuninori Morimoto 
45302299d98SKuninori Morimoto 	spin_lock(&priv->lock);
45402299d98SKuninori Morimoto 
45502299d98SKuninori Morimoto 	/* ignore all cases if not working */
456d5bbe7deSKuninori Morimoto 	if (!rsnd_io_is_working(io))
45702299d98SKuninori Morimoto 		goto rsnd_src_interrupt_gen2_out;
458cfcefe01SKuninori Morimoto 
459cfcefe01SKuninori Morimoto 	if (rsnd_src_error_record_gen2(mod)) {
460cfcefe01SKuninori Morimoto 
461cfcefe01SKuninori Morimoto 		dev_dbg(dev, "%s[%d] restart\n",
462cfcefe01SKuninori Morimoto 			rsnd_mod_name(mod), rsnd_mod_id(mod));
463639b231fSKuninori Morimoto 
464497debaaSKuninori Morimoto 		rsnd_src_stop_gen2(mod, io, priv);
465497debaaSKuninori Morimoto 		rsnd_src_start_gen2(mod, io, priv);
46669e32a58SKuninori Morimoto 	}
46769e32a58SKuninori Morimoto 
46869e32a58SKuninori Morimoto 	if (src->err > 1024) {
46969e32a58SKuninori Morimoto 		rsnd_src_irq_disable_gen2(mod);
47069e32a58SKuninori Morimoto 
47169e32a58SKuninori Morimoto 		dev_warn(dev, "no more %s[%d] restart\n",
47269e32a58SKuninori Morimoto 			 rsnd_mod_name(mod), rsnd_mod_id(mod));
473cfcefe01SKuninori Morimoto 	}
47488c61cffSKuninori Morimoto 
47502299d98SKuninori Morimoto rsnd_src_interrupt_gen2_out:
47602299d98SKuninori Morimoto 	spin_unlock(&priv->lock);
47788c61cffSKuninori Morimoto }
47888c61cffSKuninori Morimoto 
47988c61cffSKuninori Morimoto static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data)
48088c61cffSKuninori Morimoto {
48188c61cffSKuninori Morimoto 	struct rsnd_mod *mod = data;
48288c61cffSKuninori Morimoto 
48388c61cffSKuninori Morimoto 	rsnd_mod_interrupt(mod, __rsnd_src_interrupt_gen2);
484cfcefe01SKuninori Morimoto 
485cfcefe01SKuninori Morimoto 	return IRQ_HANDLED;
486cfcefe01SKuninori Morimoto }
487cfcefe01SKuninori Morimoto 
4884e2639ffSKuninori Morimoto static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod,
4894e2639ffSKuninori Morimoto 					  struct rsnd_dai_stream *io)
490ba9c949fSKuninori Morimoto {
491054cd7f4SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
492054cd7f4SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
493054cd7f4SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
494054cd7f4SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
49588c61cffSKuninori Morimoto 	u32 convert_rate = rsnd_src_convert_rate(io, src);
49643cb6954SKuninori Morimoto 	u32 cr, route;
497054cd7f4SKuninori Morimoto 	uint ratio;
498ba9c949fSKuninori Morimoto 	int ret;
499ba9c949fSKuninori Morimoto 
500054cd7f4SKuninori Morimoto 	/* 6 - 1/6 are very enough ratio for SRC_BSDSR */
501b167a578SKuninori Morimoto 	if (!convert_rate)
502054cd7f4SKuninori Morimoto 		ratio = 0;
503b167a578SKuninori Morimoto 	else if (convert_rate > runtime->rate)
504b167a578SKuninori Morimoto 		ratio = 100 * convert_rate / runtime->rate;
505054cd7f4SKuninori Morimoto 	else
506b167a578SKuninori Morimoto 		ratio = 100 * runtime->rate / convert_rate;
507054cd7f4SKuninori Morimoto 
508054cd7f4SKuninori Morimoto 	if (ratio > 600) {
509054cd7f4SKuninori Morimoto 		dev_err(dev, "FSO/FSI ratio error\n");
510054cd7f4SKuninori Morimoto 		return -EINVAL;
511054cd7f4SKuninori Morimoto 	}
512054cd7f4SKuninori Morimoto 
5134e2639ffSKuninori Morimoto 	ret = rsnd_src_set_convert_rate(mod, io);
514ba9c949fSKuninori Morimoto 	if (ret < 0)
515ba9c949fSKuninori Morimoto 		return ret;
516ba9c949fSKuninori Morimoto 
51743cb6954SKuninori Morimoto 	cr	= 0x00011110;
51843cb6954SKuninori Morimoto 	route	= 0x0;
519933cc8cbSKuninori Morimoto 	if (convert_rate) {
52043cb6954SKuninori Morimoto 		route	= 0x1;
52143cb6954SKuninori Morimoto 
52243cb6954SKuninori Morimoto 		if (rsnd_enable_sync_convert(src)) {
52343cb6954SKuninori Morimoto 			cr |= 0x1;
52443cb6954SKuninori Morimoto 			route |= rsnd_io_is_play(io) ?
52543cb6954SKuninori Morimoto 				(0x1 << 24) : (0x1 << 25);
526933cc8cbSKuninori Morimoto 		}
52743cb6954SKuninori Morimoto 	}
52843cb6954SKuninori Morimoto 
52943cb6954SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCCR, cr);
53043cb6954SKuninori Morimoto 	rsnd_mod_write(mod, SRC_ROUTE_MODE0, route);
531933cc8cbSKuninori Morimoto 
532054cd7f4SKuninori Morimoto 	switch (rsnd_mod_id(mod)) {
533054cd7f4SKuninori Morimoto 	case 5:
534054cd7f4SKuninori Morimoto 	case 6:
535054cd7f4SKuninori Morimoto 	case 7:
536054cd7f4SKuninori Morimoto 	case 8:
537054cd7f4SKuninori Morimoto 		rsnd_mod_write(mod, SRC_BSDSR, 0x02400000);
538054cd7f4SKuninori Morimoto 		break;
539054cd7f4SKuninori Morimoto 	default:
540ba9c949fSKuninori Morimoto 		rsnd_mod_write(mod, SRC_BSDSR, 0x01800000);
541054cd7f4SKuninori Morimoto 		break;
542054cd7f4SKuninori Morimoto 	}
543054cd7f4SKuninori Morimoto 
544ba9c949fSKuninori Morimoto 	rsnd_mod_write(mod, SRC_BSISR, 0x00100060);
545ba9c949fSKuninori Morimoto 
546ba9c949fSKuninori Morimoto 	return 0;
547ba9c949fSKuninori Morimoto }
548ba9c949fSKuninori Morimoto 
54988c61cffSKuninori Morimoto static int rsnd_src_set_convert_timing_gen2(struct rsnd_dai_stream *io,
55088c61cffSKuninori Morimoto 					    struct rsnd_mod *mod)
551ba9c949fSKuninori Morimoto {
552ba9c949fSKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
553ba9c949fSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
55488c61cffSKuninori Morimoto 	u32 convert_rate = rsnd_src_convert_rate(io, src);
555ba9c949fSKuninori Morimoto 	int ret;
556ba9c949fSKuninori Morimoto 
557ba9c949fSKuninori Morimoto 	if (convert_rate)
558f708d944SKuninori Morimoto 		ret = rsnd_adg_set_convert_clk_gen2(mod, io,
559ba9c949fSKuninori Morimoto 						    runtime->rate,
560ba9c949fSKuninori Morimoto 						    convert_rate);
561ba9c949fSKuninori Morimoto 	else
562f708d944SKuninori Morimoto 		ret = rsnd_adg_set_convert_timing_gen2(mod, io);
563ba9c949fSKuninori Morimoto 
564ba9c949fSKuninori Morimoto 	return ret;
565ba9c949fSKuninori Morimoto }
566ba9c949fSKuninori Morimoto 
567ba9c949fSKuninori Morimoto static int rsnd_src_probe_gen2(struct rsnd_mod *mod,
5682c0fac19SKuninori Morimoto 			       struct rsnd_dai_stream *io,
569690602fcSKuninori Morimoto 			       struct rsnd_priv *priv)
570ba9c949fSKuninori Morimoto {
571ba9c949fSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
572ba9c949fSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
573cfcefe01SKuninori Morimoto 	int irq = src->info->irq;
574ba9c949fSKuninori Morimoto 	int ret;
575ba9c949fSKuninori Morimoto 
576cfcefe01SKuninori Morimoto 	if (irq > 0) {
577cfcefe01SKuninori Morimoto 		/*
578cfcefe01SKuninori Morimoto 		 * IRQ is not supported on non-DT
579cfcefe01SKuninori Morimoto 		 * see
580cfcefe01SKuninori Morimoto 		 *	rsnd_src_irq_enable_gen2()
581cfcefe01SKuninori Morimoto 		 */
582cfcefe01SKuninori Morimoto 		ret = devm_request_irq(dev, irq,
583cfcefe01SKuninori Morimoto 				       rsnd_src_interrupt_gen2,
584cfcefe01SKuninori Morimoto 				       IRQF_SHARED,
585cfcefe01SKuninori Morimoto 				       dev_name(dev), mod);
586cfcefe01SKuninori Morimoto 		if (ret)
587b543b52aSKuninori Morimoto 			return ret;
588cfcefe01SKuninori Morimoto 	}
589cfcefe01SKuninori Morimoto 
59081ecbb65SKuninori Morimoto 	src->dma = rsnd_dma_attach(io, mod, src->info->dma_id);
591232c00b6SKuninori Morimoto 	if (IS_ERR(src->dma))
592232c00b6SKuninori Morimoto 		return PTR_ERR(src->dma);
593cfcefe01SKuninori Morimoto 
594cfcefe01SKuninori Morimoto 	return ret;
595ba9c949fSKuninori Morimoto }
596ba9c949fSKuninori Morimoto 
597ba9c949fSKuninori Morimoto static int rsnd_src_init_gen2(struct rsnd_mod *mod,
5982c0fac19SKuninori Morimoto 			      struct rsnd_dai_stream *io,
599690602fcSKuninori Morimoto 			      struct rsnd_priv *priv)
600ba9c949fSKuninori Morimoto {
601ba9c949fSKuninori Morimoto 	int ret;
602ba9c949fSKuninori Morimoto 
6033b7843ffSKuninori Morimoto 	ret = rsnd_src_init(mod, priv);
604ba9c949fSKuninori Morimoto 	if (ret < 0)
605ba9c949fSKuninori Morimoto 		return ret;
606ba9c949fSKuninori Morimoto 
6074e2639ffSKuninori Morimoto 	ret = rsnd_src_set_convert_rate_gen2(mod, io);
608ba9c949fSKuninori Morimoto 	if (ret < 0)
609ba9c949fSKuninori Morimoto 		return ret;
610ba9c949fSKuninori Morimoto 
61188c61cffSKuninori Morimoto 	ret = rsnd_src_set_convert_timing_gen2(io, mod);
612ba9c949fSKuninori Morimoto 	if (ret < 0)
613ba9c949fSKuninori Morimoto 		return ret;
614ba9c949fSKuninori Morimoto 
615ba9c949fSKuninori Morimoto 	return 0;
616ba9c949fSKuninori Morimoto }
617ba9c949fSKuninori Morimoto 
618b65a7cccSKuninori Morimoto static void rsnd_src_reconvert_update(struct rsnd_dai_stream *io,
619b65a7cccSKuninori Morimoto 				      struct rsnd_mod *mod)
62043cb6954SKuninori Morimoto {
62143cb6954SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
62243cb6954SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
62388c61cffSKuninori Morimoto 	u32 convert_rate = rsnd_src_convert_rate(io, src);
62443cb6954SKuninori Morimoto 	u32 fsrate;
62543cb6954SKuninori Morimoto 
62643cb6954SKuninori Morimoto 	if (!runtime)
62743cb6954SKuninori Morimoto 		return;
62843cb6954SKuninori Morimoto 
62943cb6954SKuninori Morimoto 	if (!convert_rate)
63043cb6954SKuninori Morimoto 		convert_rate = runtime->rate;
63143cb6954SKuninori Morimoto 
63243cb6954SKuninori Morimoto 	fsrate = 0x0400000 / convert_rate * runtime->rate;
63343cb6954SKuninori Morimoto 
63443cb6954SKuninori Morimoto 	/* update IFS */
63543cb6954SKuninori Morimoto 	rsnd_mod_write(mod, SRC_IFSVR, fsrate);
63643cb6954SKuninori Morimoto }
63743cb6954SKuninori Morimoto 
638b9bfe9d5SKuninori Morimoto static int rsnd_src_pcm_new_gen2(struct rsnd_mod *mod,
6392c0fac19SKuninori Morimoto 			    struct rsnd_dai_stream *io,
64043cb6954SKuninori Morimoto 			    struct snd_soc_pcm_runtime *rtd)
64143cb6954SKuninori Morimoto {
64243cb6954SKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
64343cb6954SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
64443cb6954SKuninori Morimoto 	int ret;
64543cb6954SKuninori Morimoto 
64643cb6954SKuninori Morimoto 	/*
64743cb6954SKuninori Morimoto 	 * enable SRC sync convert if possible
64843cb6954SKuninori Morimoto 	 */
64943cb6954SKuninori Morimoto 
65043cb6954SKuninori Morimoto 	/*
65143cb6954SKuninori Morimoto 	 * SRC sync convert needs clock master
65243cb6954SKuninori Morimoto 	 */
65343cb6954SKuninori Morimoto 	if (!rsnd_rdai_is_clk_master(rdai))
65443cb6954SKuninori Morimoto 		return 0;
65543cb6954SKuninori Morimoto 
65643cb6954SKuninori Morimoto 	/*
65743cb6954SKuninori Morimoto 	 * enable sync convert
65843cb6954SKuninori Morimoto 	 */
659b65a7cccSKuninori Morimoto 	ret = rsnd_kctrl_new_s(mod, io, rtd,
66043cb6954SKuninori Morimoto 			       rsnd_io_is_play(io) ?
66143cb6954SKuninori Morimoto 			       "SRC Out Rate Switch" :
66243cb6954SKuninori Morimoto 			       "SRC In Rate Switch",
66343cb6954SKuninori Morimoto 			       rsnd_src_reconvert_update,
66443cb6954SKuninori Morimoto 			       &src->sen, 1);
66543cb6954SKuninori Morimoto 	if (ret < 0)
66643cb6954SKuninori Morimoto 		return ret;
66743cb6954SKuninori Morimoto 
668b65a7cccSKuninori Morimoto 	ret = rsnd_kctrl_new_s(mod, io, rtd,
66943cb6954SKuninori Morimoto 			       rsnd_io_is_play(io) ?
67043cb6954SKuninori Morimoto 			       "SRC Out Rate" :
67143cb6954SKuninori Morimoto 			       "SRC In Rate",
67243cb6954SKuninori Morimoto 			       rsnd_src_reconvert_update,
67343cb6954SKuninori Morimoto 			       &src->sync, 192000);
67443cb6954SKuninori Morimoto 
67543cb6954SKuninori Morimoto 	return ret;
67643cb6954SKuninori Morimoto }
67743cb6954SKuninori Morimoto 
678ba9c949fSKuninori Morimoto static struct rsnd_mod_ops rsnd_src_gen2_ops = {
6798aefda50SKuninori Morimoto 	.name	= SRC_NAME,
68072adc61fSKuninori Morimoto 	.dma_req = rsnd_src_dma_req,
681ba9c949fSKuninori Morimoto 	.probe	= rsnd_src_probe_gen2,
682ba9c949fSKuninori Morimoto 	.init	= rsnd_src_init_gen2,
683b761bf27SKuninori Morimoto 	.quit	= rsnd_src_quit_gen2,
684ba9c949fSKuninori Morimoto 	.start	= rsnd_src_start_gen2,
685ba9c949fSKuninori Morimoto 	.stop	= rsnd_src_stop_gen2,
6863b7843ffSKuninori Morimoto 	.hw_params = rsnd_src_hw_params,
687b9bfe9d5SKuninori Morimoto 	.pcm_new = rsnd_src_pcm_new_gen2,
688ba9c949fSKuninori Morimoto };
689ba9c949fSKuninori Morimoto 
690ba9c949fSKuninori Morimoto struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
691ba9c949fSKuninori Morimoto {
692ba9c949fSKuninori Morimoto 	if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv)))
693ba9c949fSKuninori Morimoto 		id = 0;
694ba9c949fSKuninori Morimoto 
695b76e218aSKuninori Morimoto 	return rsnd_mod_get((struct rsnd_src *)(priv->src) + id);
696ba9c949fSKuninori Morimoto }
697ba9c949fSKuninori Morimoto 
69890e8e50fSKuninori Morimoto static void rsnd_of_parse_src(struct platform_device *pdev,
69990e8e50fSKuninori Morimoto 			      const struct rsnd_of_data *of_data,
70090e8e50fSKuninori Morimoto 			      struct rsnd_priv *priv)
70190e8e50fSKuninori Morimoto {
70290e8e50fSKuninori Morimoto 	struct device_node *src_node;
703cfcefe01SKuninori Morimoto 	struct device_node *np;
70490e8e50fSKuninori Morimoto 	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
70590e8e50fSKuninori Morimoto 	struct rsnd_src_platform_info *src_info;
70690e8e50fSKuninori Morimoto 	struct device *dev = &pdev->dev;
707cfcefe01SKuninori Morimoto 	int nr, i;
70890e8e50fSKuninori Morimoto 
70990e8e50fSKuninori Morimoto 	if (!of_data)
71090e8e50fSKuninori Morimoto 		return;
71190e8e50fSKuninori Morimoto 
71282e76ed3SKuninori Morimoto 	src_node = rsnd_src_of_node(priv);
71390e8e50fSKuninori Morimoto 	if (!src_node)
71490e8e50fSKuninori Morimoto 		return;
71590e8e50fSKuninori Morimoto 
71690e8e50fSKuninori Morimoto 	nr = of_get_child_count(src_node);
71790e8e50fSKuninori Morimoto 	if (!nr)
718f451e48dSKuninori Morimoto 		goto rsnd_of_parse_src_end;
71990e8e50fSKuninori Morimoto 
72090e8e50fSKuninori Morimoto 	src_info = devm_kzalloc(dev,
72190e8e50fSKuninori Morimoto 				sizeof(struct rsnd_src_platform_info) * nr,
72290e8e50fSKuninori Morimoto 				GFP_KERNEL);
72390e8e50fSKuninori Morimoto 	if (!src_info) {
72490e8e50fSKuninori Morimoto 		dev_err(dev, "src info allocation error\n");
725f451e48dSKuninori Morimoto 		goto rsnd_of_parse_src_end;
72690e8e50fSKuninori Morimoto 	}
72790e8e50fSKuninori Morimoto 
72890e8e50fSKuninori Morimoto 	info->src_info		= src_info;
72990e8e50fSKuninori Morimoto 	info->src_info_nr	= nr;
730f451e48dSKuninori Morimoto 
731cfcefe01SKuninori Morimoto 	i = 0;
732cfcefe01SKuninori Morimoto 	for_each_child_of_node(src_node, np) {
733cfcefe01SKuninori Morimoto 		src_info[i].irq = irq_of_parse_and_map(np, 0);
734cfcefe01SKuninori Morimoto 
735cfcefe01SKuninori Morimoto 		i++;
736cfcefe01SKuninori Morimoto 	}
737cfcefe01SKuninori Morimoto 
738f451e48dSKuninori Morimoto rsnd_of_parse_src_end:
739f451e48dSKuninori Morimoto 	of_node_put(src_node);
74090e8e50fSKuninori Morimoto }
74190e8e50fSKuninori Morimoto 
742ba9c949fSKuninori Morimoto int rsnd_src_probe(struct platform_device *pdev,
74390e8e50fSKuninori Morimoto 		   const struct rsnd_of_data *of_data,
744ba9c949fSKuninori Morimoto 		   struct rsnd_priv *priv)
745ba9c949fSKuninori Morimoto {
746ba9c949fSKuninori Morimoto 	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
747ba9c949fSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
748ba9c949fSKuninori Morimoto 	struct rsnd_src *src;
749ba9c949fSKuninori Morimoto 	struct clk *clk;
750ba9c949fSKuninori Morimoto 	char name[RSND_SRC_NAME_SIZE];
7512f78dd7fSKuninori Morimoto 	int i, nr, ret;
752ba9c949fSKuninori Morimoto 
753*e8e7b7bdSKuninori Morimoto 	/* This driver doesn't support Gen1 at this point */
754*e8e7b7bdSKuninori Morimoto 	if (rsnd_is_gen1(priv))
755*e8e7b7bdSKuninori Morimoto 		return 0;
756033e7ed8SKuninori Morimoto 
75790e8e50fSKuninori Morimoto 	rsnd_of_parse_src(pdev, of_data, priv);
75890e8e50fSKuninori Morimoto 
759ba9c949fSKuninori Morimoto 	/*
760ba9c949fSKuninori Morimoto 	 * init SRC
761ba9c949fSKuninori Morimoto 	 */
762ba9c949fSKuninori Morimoto 	nr	= info->src_info_nr;
763ba9c949fSKuninori Morimoto 	if (!nr)
764ba9c949fSKuninori Morimoto 		return 0;
765ba9c949fSKuninori Morimoto 
766ba9c949fSKuninori Morimoto 	src	= devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL);
76733363f7aSKuninori Morimoto 	if (!src)
768ba9c949fSKuninori Morimoto 		return -ENOMEM;
769ba9c949fSKuninori Morimoto 
770ba9c949fSKuninori Morimoto 	priv->src_nr	= nr;
771ba9c949fSKuninori Morimoto 	priv->src	= src;
772ba9c949fSKuninori Morimoto 
773ba9c949fSKuninori Morimoto 	for_each_rsnd_src(src, priv, i) {
7748aefda50SKuninori Morimoto 		snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d",
7758aefda50SKuninori Morimoto 			 SRC_NAME, i);
776ba9c949fSKuninori Morimoto 
777ba9c949fSKuninori Morimoto 		clk = devm_clk_get(dev, name);
778ba9c949fSKuninori Morimoto 		if (IS_ERR(clk))
779ba9c949fSKuninori Morimoto 			return PTR_ERR(clk);
780ba9c949fSKuninori Morimoto 
781ba9c949fSKuninori Morimoto 		src->info = &info->src_info[i];
782ba9c949fSKuninori Morimoto 
783*e8e7b7bdSKuninori Morimoto 		ret = rsnd_mod_init(priv, rsnd_mod_get(src),
784*e8e7b7bdSKuninori Morimoto 				    &rsnd_src_gen2_ops, clk, RSND_MOD_SRC, i);
7852f78dd7fSKuninori Morimoto 		if (ret)
7862f78dd7fSKuninori Morimoto 			return ret;
787ba9c949fSKuninori Morimoto 	}
788ba9c949fSKuninori Morimoto 
789ba9c949fSKuninori Morimoto 	return 0;
790ba9c949fSKuninori Morimoto }
7912f78dd7fSKuninori Morimoto 
7922f78dd7fSKuninori Morimoto void rsnd_src_remove(struct platform_device *pdev,
7932f78dd7fSKuninori Morimoto 		     struct rsnd_priv *priv)
7942f78dd7fSKuninori Morimoto {
7952f78dd7fSKuninori Morimoto 	struct rsnd_src *src;
7962f78dd7fSKuninori Morimoto 	int i;
7972f78dd7fSKuninori Morimoto 
7982f78dd7fSKuninori Morimoto 	for_each_rsnd_src(src, priv, i) {
799b76e218aSKuninori Morimoto 		rsnd_mod_quit(rsnd_mod_get(src));
8002f78dd7fSKuninori Morimoto 	}
8012f78dd7fSKuninori Morimoto }
802