xref: /openbmc/linux/sound/soc/sh/rcar/src.c (revision 7e7fe06de376e9874f4399dac81d65ea9b0a9507)
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"
17ba9c949fSKuninori Morimoto 
188aefda50SKuninori Morimoto #define SRC_NAME "src"
198aefda50SKuninori Morimoto 
20cfcefe01SKuninori Morimoto /* SCU_SYSTEM_STATUS0/1 */
21cfcefe01SKuninori Morimoto #define OUF_SRC(id)	((1 << (id + 16)) | (1 << id))
22cfcefe01SKuninori Morimoto 
23ba9c949fSKuninori Morimoto struct rsnd_src {
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 */
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))
9243cb6954SKuninori Morimoto 		return src->convert_rate;
9343cb6954SKuninori Morimoto 
9443cb6954SKuninori Morimoto 	convert_rate = src->sync.val;
9543cb6954SKuninori Morimoto 
9643cb6954SKuninori Morimoto 	if (!convert_rate)
9743cb6954SKuninori Morimoto 		convert_rate = src->convert_rate;
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 
1383b7843ffSKuninori Morimoto static int rsnd_src_hw_params(struct rsnd_mod *mod,
1392c0fac19SKuninori Morimoto 			      struct rsnd_dai_stream *io,
1403b7843ffSKuninori Morimoto 			      struct snd_pcm_substream *substream,
1413b7843ffSKuninori Morimoto 			      struct snd_pcm_hw_params *fe_params)
1423b7843ffSKuninori Morimoto {
1433b7843ffSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
1443b7843ffSKuninori Morimoto 	struct snd_soc_pcm_runtime *fe = substream->private_data;
1453b7843ffSKuninori Morimoto 
1463b7843ffSKuninori Morimoto 	/*
1473b7843ffSKuninori Morimoto 	 * SRC assumes that it is used under DPCM if user want to use
1483b7843ffSKuninori Morimoto 	 * sampling rate convert. Then, SRC should be FE.
1493b7843ffSKuninori Morimoto 	 * And then, this function will be called *after* BE settings.
1503b7843ffSKuninori Morimoto 	 * this means, each BE already has fixuped hw_params.
1513b7843ffSKuninori Morimoto 	 * see
1523b7843ffSKuninori Morimoto 	 *	dpcm_fe_dai_hw_params()
1533b7843ffSKuninori Morimoto 	 *	dpcm_be_dai_hw_params()
1543b7843ffSKuninori Morimoto 	 */
155fc99d23fSKuninori Morimoto 	src->convert_rate = 0;
1563b7843ffSKuninori Morimoto 	if (fe->dai_link->dynamic) {
1573b7843ffSKuninori Morimoto 		int stream = substream->stream;
1583b7843ffSKuninori Morimoto 		struct snd_soc_dpcm *dpcm;
1593b7843ffSKuninori Morimoto 		struct snd_pcm_hw_params *be_params;
1603b7843ffSKuninori Morimoto 
1618d6258a4SKuninori Morimoto 		for_each_dpcm_be(fe, stream, dpcm) {
1623b7843ffSKuninori Morimoto 			be_params = &dpcm->hw_params;
1633b7843ffSKuninori Morimoto 
1643b7843ffSKuninori Morimoto 			if (params_rate(fe_params) != params_rate(be_params))
1653b7843ffSKuninori Morimoto 				src->convert_rate = params_rate(be_params);
1663b7843ffSKuninori Morimoto 		}
1673b7843ffSKuninori Morimoto 	}
1683b7843ffSKuninori Morimoto 
1693b7843ffSKuninori Morimoto 	return 0;
1703b7843ffSKuninori Morimoto }
1713b7843ffSKuninori Morimoto 
17275916f65SKuninori Morimoto static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
17375916f65SKuninori Morimoto 				      struct rsnd_mod *mod)
174ba9c949fSKuninori Morimoto {
17575916f65SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
176cfcefe01SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
17775916f65SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
17890431eb4SKuninori Morimoto 	int is_play = rsnd_io_is_play(io);
17967923f77SKuninori Morimoto 	int use_src = 0;
1800102eed5SKuninori Morimoto 	u32 fin, fout;
18175916f65SKuninori Morimoto 	u32 ifscr, fsrate, adinr;
18275916f65SKuninori Morimoto 	u32 cr, route;
18375916f65SKuninori Morimoto 	u32 bsdsr, bsisr;
18490431eb4SKuninori Morimoto 	u32 i_busif, o_busif, tmp;
18575916f65SKuninori Morimoto 	uint ratio;
186ba9c949fSKuninori Morimoto 
18775916f65SKuninori Morimoto 	if (!runtime)
18875916f65SKuninori Morimoto 		return;
189ba9c949fSKuninori Morimoto 
1900102eed5SKuninori Morimoto 	fin  = rsnd_src_get_in_rate(priv, io);
1910102eed5SKuninori Morimoto 	fout = rsnd_src_get_out_rate(priv, io);
1920102eed5SKuninori Morimoto 
19375916f65SKuninori Morimoto 	/* 6 - 1/6 are very enough ratio for SRC_BSDSR */
1940102eed5SKuninori Morimoto 	if (fin == fout)
19575916f65SKuninori Morimoto 		ratio = 0;
1960102eed5SKuninori Morimoto 	else if (fin > fout)
1970102eed5SKuninori Morimoto 		ratio = 100 * fin / fout;
19875916f65SKuninori Morimoto 	else
1990102eed5SKuninori Morimoto 		ratio = 100 * fout / fin;
200cfcefe01SKuninori Morimoto 
20175916f65SKuninori Morimoto 	if (ratio > 600) {
20275916f65SKuninori Morimoto 		dev_err(dev, "FSO/FSI ratio error\n");
20375916f65SKuninori Morimoto 		return;
204ba9c949fSKuninori Morimoto 	}
205ba9c949fSKuninori Morimoto 
20667923f77SKuninori Morimoto 	use_src = (fin != fout) | rsnd_src_sync_is_enabled(mod);
20767923f77SKuninori Morimoto 
208ba9c949fSKuninori Morimoto 	/*
20975916f65SKuninori Morimoto 	 * SRC_ADINR
210ba9c949fSKuninori Morimoto 	 */
211c45f7263SKuninori Morimoto 	adinr = rsnd_get_adinr_bit(mod, io) |
212eed76bb8SKuninori Morimoto 		rsnd_runtime_channel_original(io);
21375916f65SKuninori Morimoto 
21475916f65SKuninori Morimoto 	/*
21575916f65SKuninori Morimoto 	 * SRC_IFSCR / SRC_IFSVR
21675916f65SKuninori Morimoto 	 */
21775916f65SKuninori Morimoto 	ifscr = 0;
21875916f65SKuninori Morimoto 	fsrate = 0;
21967923f77SKuninori Morimoto 	if (use_src) {
22093ca33c9SHiroyuki Yokoyama 		u64 n;
22193ca33c9SHiroyuki Yokoyama 
22275916f65SKuninori Morimoto 		ifscr = 1;
22393ca33c9SHiroyuki Yokoyama 		n = (u64)0x0400000 * fin;
22493ca33c9SHiroyuki Yokoyama 		do_div(n, fout);
22593ca33c9SHiroyuki Yokoyama 		fsrate = n;
22675916f65SKuninori Morimoto 	}
22775916f65SKuninori Morimoto 
22875916f65SKuninori Morimoto 	/*
22975916f65SKuninori Morimoto 	 * SRC_SRCCR / SRC_ROUTE_MODE0
23075916f65SKuninori Morimoto 	 */
23175916f65SKuninori Morimoto 	cr	= 0x00011110;
23275916f65SKuninori Morimoto 	route	= 0x0;
23367923f77SKuninori Morimoto 	if (use_src) {
23475916f65SKuninori Morimoto 		route	= 0x1;
23575916f65SKuninori Morimoto 
236ab2049f9SKuninori Morimoto 		if (rsnd_src_sync_is_enabled(mod)) {
23775916f65SKuninori Morimoto 			cr |= 0x1;
23875916f65SKuninori Morimoto 			route |= rsnd_io_is_play(io) ?
23975916f65SKuninori Morimoto 				(0x1 << 24) : (0x1 << 25);
24075916f65SKuninori Morimoto 		}
24175916f65SKuninori Morimoto 	}
24275916f65SKuninori Morimoto 
24375916f65SKuninori Morimoto 	/*
24475916f65SKuninori Morimoto 	 * SRC_BSDSR / SRC_BSISR
24575916f65SKuninori Morimoto 	 */
24675916f65SKuninori Morimoto 	switch (rsnd_mod_id(mod)) {
24775916f65SKuninori Morimoto 	case 5:
24875916f65SKuninori Morimoto 	case 6:
24975916f65SKuninori Morimoto 	case 7:
25075916f65SKuninori Morimoto 	case 8:
25175916f65SKuninori Morimoto 		bsdsr = 0x02400000; /* 6 - 1/6 */
25275916f65SKuninori Morimoto 		bsisr = 0x00100060; /* 6 - 1/6 */
25375916f65SKuninori Morimoto 		break;
25475916f65SKuninori Morimoto 	default:
25575916f65SKuninori Morimoto 		bsdsr = 0x01800000; /* 6 - 1/6 */
25675916f65SKuninori Morimoto 		bsisr = 0x00100060 ;/* 6 - 1/6 */
25775916f65SKuninori Morimoto 		break;
25875916f65SKuninori Morimoto 	}
25975916f65SKuninori Morimoto 
26090431eb4SKuninori Morimoto 	/* BUSIF_MODE */
26190431eb4SKuninori Morimoto 	tmp = rsnd_get_busif_shift(io, mod);
26290431eb4SKuninori Morimoto 	i_busif = ( is_play ? tmp : 0) | 1;
26390431eb4SKuninori Morimoto 	o_busif = (!is_play ? tmp : 0) | 1;
26490431eb4SKuninori Morimoto 
2650fbab951SKuninori Morimoto 	rsnd_mod_write(mod, SRC_ROUTE_MODE0, route);
2660fbab951SKuninori Morimoto 
26775916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCIR, 1);	/* initialize */
26875916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_ADINR, adinr);
26975916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_IFSCR, ifscr);
27075916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_IFSVR, fsrate);
27175916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCCR, cr);
27275916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BSDSR, bsdsr);
27375916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BSISR, bsisr);
27475916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCIR, 0);	/* cancel initialize */
27575916f65SKuninori Morimoto 
27690431eb4SKuninori Morimoto 	rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif);
27790431eb4SKuninori Morimoto 	rsnd_mod_write(mod, SRC_O_BUSIF_MODE, o_busif);
27890431eb4SKuninori Morimoto 
27975916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
28075916f65SKuninori Morimoto 
2810102eed5SKuninori Morimoto 	rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout);
28275916f65SKuninori Morimoto }
28375916f65SKuninori Morimoto 
284b5b442abSKuninori Morimoto static int rsnd_src_irq(struct rsnd_mod *mod,
285b5b442abSKuninori Morimoto 			struct rsnd_dai_stream *io,
286b5b442abSKuninori Morimoto 			struct rsnd_priv *priv,
287b5b442abSKuninori Morimoto 			int enable)
288cfcefe01SKuninori Morimoto {
289cfcefe01SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
290cfcefe01SKuninori Morimoto 	u32 sys_int_val, int_val, sys_int_mask;
291adf6a681SKuninori Morimoto 	int irq = src->irq;
292cfcefe01SKuninori Morimoto 	int id = rsnd_mod_id(mod);
293cfcefe01SKuninori Morimoto 
294cfcefe01SKuninori Morimoto 	sys_int_val =
295cfcefe01SKuninori Morimoto 	sys_int_mask = OUF_SRC(id);
296cfcefe01SKuninori Morimoto 	int_val = 0x3300;
297cfcefe01SKuninori Morimoto 
298cfcefe01SKuninori Morimoto 	/*
299cfcefe01SKuninori Morimoto 	 * IRQ is not supported on non-DT
300cfcefe01SKuninori Morimoto 	 * see
30175916f65SKuninori Morimoto 	 *	rsnd_src_probe_()
302cfcefe01SKuninori Morimoto 	 */
303cfcefe01SKuninori Morimoto 	if ((irq <= 0) || !enable) {
304cfcefe01SKuninori Morimoto 		sys_int_val = 0;
305cfcefe01SKuninori Morimoto 		int_val = 0;
306cfcefe01SKuninori Morimoto 	}
307cfcefe01SKuninori Morimoto 
3081a1bf58aSKuninori Morimoto 	/*
3091a1bf58aSKuninori Morimoto 	 * WORKAROUND
3101a1bf58aSKuninori Morimoto 	 *
311ab2049f9SKuninori Morimoto 	 * ignore over flow error when rsnd_src_sync_is_enabled()
3121a1bf58aSKuninori Morimoto 	 */
313ab2049f9SKuninori Morimoto 	if (rsnd_src_sync_is_enabled(mod))
3141a1bf58aSKuninori Morimoto 		sys_int_val = sys_int_val & 0xffff;
3151a1bf58aSKuninori Morimoto 
316cfcefe01SKuninori Morimoto 	rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val);
317cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val);
318cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val);
319b5b442abSKuninori Morimoto 
320b5b442abSKuninori Morimoto 	return 0;
321cfcefe01SKuninori Morimoto }
322cfcefe01SKuninori Morimoto 
3238cc225f7SKuninori Morimoto static void rsnd_src_status_clear(struct rsnd_mod *mod)
324cfcefe01SKuninori Morimoto {
325cfcefe01SKuninori Morimoto 	u32 val = OUF_SRC(rsnd_mod_id(mod));
326cfcefe01SKuninori Morimoto 
32742b197e7SKuninori Morimoto 	rsnd_mod_write(mod, SCU_SYS_STATUS0, val);
32842b197e7SKuninori Morimoto 	rsnd_mod_write(mod, SCU_SYS_STATUS1, val);
329cfcefe01SKuninori Morimoto }
330cfcefe01SKuninori Morimoto 
3316a25c8daSKuninori Morimoto static bool rsnd_src_error_occurred(struct rsnd_mod *mod)
332cfcefe01SKuninori Morimoto {
3332b627869SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
3342b627869SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
3351a1bf58aSKuninori Morimoto 	u32 val0, val1;
3362b627869SKuninori Morimoto 	u32 status0, status1;
337cfcefe01SKuninori Morimoto 	bool ret = false;
338cfcefe01SKuninori Morimoto 
3391a1bf58aSKuninori Morimoto 	val0 = val1 = OUF_SRC(rsnd_mod_id(mod));
3401a1bf58aSKuninori Morimoto 
3411a1bf58aSKuninori Morimoto 	/*
3421a1bf58aSKuninori Morimoto 	 * WORKAROUND
3431a1bf58aSKuninori Morimoto 	 *
344ab2049f9SKuninori Morimoto 	 * ignore over flow error when rsnd_src_sync_is_enabled()
3451a1bf58aSKuninori Morimoto 	 */
346ab2049f9SKuninori Morimoto 	if (rsnd_src_sync_is_enabled(mod))
3471a1bf58aSKuninori Morimoto 		val0 = val0 & 0xffff;
3481a1bf58aSKuninori Morimoto 
3492b627869SKuninori Morimoto 	status0 = rsnd_mod_read(mod, SCU_SYS_STATUS0);
3502b627869SKuninori Morimoto 	status1 = rsnd_mod_read(mod, SCU_SYS_STATUS1);
3512b627869SKuninori Morimoto 	if ((status0 & val0) || (status1 & val1)) {
3522b627869SKuninori Morimoto 		rsnd_dbg_irq_status(dev, "%s[%d] err status : 0x%08x, 0x%08x\n",
3532b627869SKuninori Morimoto 			rsnd_mod_name(mod), rsnd_mod_id(mod),
3542b627869SKuninori Morimoto 			status0, status1);
3552b627869SKuninori Morimoto 
356cfcefe01SKuninori Morimoto 		ret = true;
3572b627869SKuninori Morimoto 	}
358cfcefe01SKuninori Morimoto 
359cfcefe01SKuninori Morimoto 	return ret;
360cfcefe01SKuninori Morimoto }
361cfcefe01SKuninori Morimoto 
36275916f65SKuninori Morimoto static int rsnd_src_start(struct rsnd_mod *mod,
363497debaaSKuninori Morimoto 			  struct rsnd_dai_stream *io,
364497debaaSKuninori Morimoto 			  struct rsnd_priv *priv)
365cfcefe01SKuninori Morimoto {
3661a1bf58aSKuninori Morimoto 	u32 val;
3671a1bf58aSKuninori Morimoto 
3681a1bf58aSKuninori Morimoto 	/*
3691a1bf58aSKuninori Morimoto 	 * WORKAROUND
3701a1bf58aSKuninori Morimoto 	 *
3711a1bf58aSKuninori Morimoto 	 * Enable SRC output if you want to use sync convert together with DVC
3721a1bf58aSKuninori Morimoto 	 */
373ab2049f9SKuninori Morimoto 	val = (rsnd_io_to_mod_dvc(io) && !rsnd_src_sync_is_enabled(mod)) ?
3741a1bf58aSKuninori Morimoto 		0x01 : 0x11;
375cfcefe01SKuninori Morimoto 
376cfcefe01SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, val);
377cfcefe01SKuninori Morimoto 
37875916f65SKuninori Morimoto 	return 0;
37975916f65SKuninori Morimoto }
380cfcefe01SKuninori Morimoto 
38175916f65SKuninori Morimoto static int rsnd_src_stop(struct rsnd_mod *mod,
38275916f65SKuninori Morimoto 			 struct rsnd_dai_stream *io,
38375916f65SKuninori Morimoto 			 struct rsnd_priv *priv)
38475916f65SKuninori Morimoto {
38531739a68SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, 0);
386cfcefe01SKuninori Morimoto 
387cfcefe01SKuninori Morimoto 	return 0;
388cfcefe01SKuninori Morimoto }
389cfcefe01SKuninori Morimoto 
39075916f65SKuninori Morimoto static int rsnd_src_init(struct rsnd_mod *mod,
391497debaaSKuninori Morimoto 			 struct rsnd_dai_stream *io,
392497debaaSKuninori Morimoto 			 struct rsnd_priv *priv)
393cfcefe01SKuninori Morimoto {
39475916f65SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
395cfcefe01SKuninori Morimoto 
396ef30da1cSKuninori Morimoto 	/* reset sync convert_rate */
397ef30da1cSKuninori Morimoto 	src->sync.val = 0;
398ef30da1cSKuninori Morimoto 
39975916f65SKuninori Morimoto 	rsnd_mod_power_on(mod);
400cfcefe01SKuninori Morimoto 
40198efeeaeSKuninori Morimoto 	rsnd_src_activation(mod);
402cfcefe01SKuninori Morimoto 
40375916f65SKuninori Morimoto 	rsnd_src_set_convert_rate(io, mod);
40475916f65SKuninori Morimoto 
4058cc225f7SKuninori Morimoto 	rsnd_src_status_clear(mod);
40675916f65SKuninori Morimoto 
40775916f65SKuninori Morimoto 	return 0;
408cfcefe01SKuninori Morimoto }
409cfcefe01SKuninori Morimoto 
41075916f65SKuninori Morimoto static int rsnd_src_quit(struct rsnd_mod *mod,
411b761bf27SKuninori Morimoto 			 struct rsnd_dai_stream *io,
412b761bf27SKuninori Morimoto 			 struct rsnd_priv *priv)
413b761bf27SKuninori Morimoto {
41475916f65SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
41575916f65SKuninori Morimoto 
416475a361aSKuninori Morimoto 	rsnd_src_halt(mod);
417475a361aSKuninori Morimoto 
41875916f65SKuninori Morimoto 	rsnd_mod_power_off(mod);
41975916f65SKuninori Morimoto 
42075916f65SKuninori Morimoto 	/* reset sync convert_rate */
42175916f65SKuninori Morimoto 	src->sync.val = 0;
42275916f65SKuninori Morimoto 
42375916f65SKuninori Morimoto 	return 0;
424b761bf27SKuninori Morimoto }
425b761bf27SKuninori Morimoto 
42675916f65SKuninori Morimoto static void __rsnd_src_interrupt(struct rsnd_mod *mod,
42788c61cffSKuninori Morimoto 				 struct rsnd_dai_stream *io)
428cfcefe01SKuninori Morimoto {
42902299d98SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
4306a25c8daSKuninori Morimoto 	bool stop = false;
431cfcefe01SKuninori Morimoto 
43202299d98SKuninori Morimoto 	spin_lock(&priv->lock);
43302299d98SKuninori Morimoto 
43402299d98SKuninori Morimoto 	/* ignore all cases if not working */
435d5bbe7deSKuninori Morimoto 	if (!rsnd_io_is_working(io))
43675916f65SKuninori Morimoto 		goto rsnd_src_interrupt_out;
437cfcefe01SKuninori Morimoto 
4386a25c8daSKuninori Morimoto 	if (rsnd_src_error_occurred(mod))
4396a25c8daSKuninori Morimoto 		stop = true;
44088c61cffSKuninori Morimoto 
4418cc225f7SKuninori Morimoto 	rsnd_src_status_clear(mod);
44275916f65SKuninori Morimoto rsnd_src_interrupt_out:
4438cc225f7SKuninori Morimoto 
44402299d98SKuninori Morimoto 	spin_unlock(&priv->lock);
4456a25c8daSKuninori Morimoto 
4466a25c8daSKuninori Morimoto 	if (stop)
4476a25c8daSKuninori Morimoto 		snd_pcm_stop_xrun(io->substream);
44888c61cffSKuninori Morimoto }
44988c61cffSKuninori Morimoto 
45075916f65SKuninori Morimoto static irqreturn_t rsnd_src_interrupt(int irq, void *data)
45188c61cffSKuninori Morimoto {
45288c61cffSKuninori Morimoto 	struct rsnd_mod *mod = data;
45388c61cffSKuninori Morimoto 
45475916f65SKuninori Morimoto 	rsnd_mod_interrupt(mod, __rsnd_src_interrupt);
455cfcefe01SKuninori Morimoto 
456cfcefe01SKuninori Morimoto 	return IRQ_HANDLED;
457cfcefe01SKuninori Morimoto }
458cfcefe01SKuninori Morimoto 
45975916f65SKuninori Morimoto static int rsnd_src_probe_(struct rsnd_mod *mod,
4602c0fac19SKuninori Morimoto 			   struct rsnd_dai_stream *io,
461690602fcSKuninori Morimoto 			   struct rsnd_priv *priv)
462ba9c949fSKuninori Morimoto {
463ba9c949fSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
464ba9c949fSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
465adf6a681SKuninori Morimoto 	int irq = src->irq;
466ba9c949fSKuninori Morimoto 	int ret;
467ba9c949fSKuninori Morimoto 
468cfcefe01SKuninori Morimoto 	if (irq > 0) {
469cfcefe01SKuninori Morimoto 		/*
470cfcefe01SKuninori Morimoto 		 * IRQ is not supported on non-DT
471cfcefe01SKuninori Morimoto 		 * see
472b5b442abSKuninori Morimoto 		 *	rsnd_src_irq()
473cfcefe01SKuninori Morimoto 		 */
474cfcefe01SKuninori Morimoto 		ret = devm_request_irq(dev, irq,
47575916f65SKuninori Morimoto 				       rsnd_src_interrupt,
476cfcefe01SKuninori Morimoto 				       IRQF_SHARED,
477cfcefe01SKuninori Morimoto 				       dev_name(dev), mod);
478cfcefe01SKuninori Morimoto 		if (ret)
479b543b52aSKuninori Morimoto 			return ret;
480cfcefe01SKuninori Morimoto 	}
481cfcefe01SKuninori Morimoto 
482b99305d2SKuninori Morimoto 	ret = rsnd_dma_attach(io, mod, &src->dma);
483cfcefe01SKuninori Morimoto 
484cfcefe01SKuninori Morimoto 	return ret;
485ba9c949fSKuninori Morimoto }
486ba9c949fSKuninori Morimoto 
48775916f65SKuninori Morimoto static int rsnd_src_pcm_new(struct rsnd_mod *mod,
4882c0fac19SKuninori Morimoto 			    struct rsnd_dai_stream *io,
48943cb6954SKuninori Morimoto 			    struct snd_soc_pcm_runtime *rtd)
49043cb6954SKuninori Morimoto {
49143cb6954SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
49243cb6954SKuninori Morimoto 	int ret;
49343cb6954SKuninori Morimoto 
49443cb6954SKuninori Morimoto 	/*
49543cb6954SKuninori Morimoto 	 * enable SRC sync convert if possible
49643cb6954SKuninori Morimoto 	 */
49743cb6954SKuninori Morimoto 
49843cb6954SKuninori Morimoto 	/*
49961a219feSKuninori Morimoto 	 * It can't use SRC Synchronous convert
50061a219feSKuninori Morimoto 	 * when Capture if it uses CMD
5017115cb91SKuninori Morimoto 	 */
50261a219feSKuninori Morimoto 	if (rsnd_io_to_mod_cmd(io) && !rsnd_io_is_play(io))
5037115cb91SKuninori Morimoto 		return 0;
5047115cb91SKuninori Morimoto 
5057115cb91SKuninori Morimoto 	/*
50643cb6954SKuninori Morimoto 	 * enable sync convert
50743cb6954SKuninori Morimoto 	 */
508b65a7cccSKuninori Morimoto 	ret = rsnd_kctrl_new_s(mod, io, rtd,
50943cb6954SKuninori Morimoto 			       rsnd_io_is_play(io) ?
51043cb6954SKuninori Morimoto 			       "SRC Out Rate Switch" :
51143cb6954SKuninori Morimoto 			       "SRC In Rate Switch",
512f0b04d8bSKuninori Morimoto 			       rsnd_kctrl_accept_anytime,
51375916f65SKuninori Morimoto 			       rsnd_src_set_convert_rate,
51443cb6954SKuninori Morimoto 			       &src->sen, 1);
51543cb6954SKuninori Morimoto 	if (ret < 0)
51643cb6954SKuninori Morimoto 		return ret;
51743cb6954SKuninori Morimoto 
518b65a7cccSKuninori Morimoto 	ret = rsnd_kctrl_new_s(mod, io, rtd,
51943cb6954SKuninori Morimoto 			       rsnd_io_is_play(io) ?
52043cb6954SKuninori Morimoto 			       "SRC Out Rate" :
52143cb6954SKuninori Morimoto 			       "SRC In Rate",
522f0b04d8bSKuninori Morimoto 			       rsnd_kctrl_accept_runtime,
52375916f65SKuninori Morimoto 			       rsnd_src_set_convert_rate,
52443cb6954SKuninori Morimoto 			       &src->sync, 192000);
52543cb6954SKuninori Morimoto 
52643cb6954SKuninori Morimoto 	return ret;
52743cb6954SKuninori Morimoto }
52843cb6954SKuninori Morimoto 
52975916f65SKuninori Morimoto static struct rsnd_mod_ops rsnd_src_ops = {
5308aefda50SKuninori Morimoto 	.name		= SRC_NAME,
53172adc61fSKuninori Morimoto 	.dma_req	= rsnd_src_dma_req,
53275916f65SKuninori Morimoto 	.probe		= rsnd_src_probe_,
53375916f65SKuninori Morimoto 	.init		= rsnd_src_init,
53475916f65SKuninori Morimoto 	.quit		= rsnd_src_quit,
53575916f65SKuninori Morimoto 	.start		= rsnd_src_start,
53675916f65SKuninori Morimoto 	.stop		= rsnd_src_stop,
537b5b442abSKuninori Morimoto 	.irq		= rsnd_src_irq,
5383b7843ffSKuninori Morimoto 	.hw_params	= rsnd_src_hw_params,
53975916f65SKuninori Morimoto 	.pcm_new	= rsnd_src_pcm_new,
540*7e7fe06dSKuninori Morimoto 	.get_status	= rsnd_mod_get_status,
541ba9c949fSKuninori Morimoto };
542ba9c949fSKuninori Morimoto 
543ba9c949fSKuninori Morimoto struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
544ba9c949fSKuninori Morimoto {
545ba9c949fSKuninori Morimoto 	if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv)))
546ba9c949fSKuninori Morimoto 		id = 0;
547ba9c949fSKuninori Morimoto 
548adf6a681SKuninori Morimoto 	return rsnd_mod_get(rsnd_src_get(priv, id));
54990e8e50fSKuninori Morimoto }
55090e8e50fSKuninori Morimoto 
5512ea6b074SKuninori Morimoto int rsnd_src_probe(struct rsnd_priv *priv)
552ba9c949fSKuninori Morimoto {
553adf6a681SKuninori Morimoto 	struct device_node *node;
554adf6a681SKuninori Morimoto 	struct device_node *np;
555ba9c949fSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
556ba9c949fSKuninori Morimoto 	struct rsnd_src *src;
557ba9c949fSKuninori Morimoto 	struct clk *clk;
558ba9c949fSKuninori Morimoto 	char name[RSND_SRC_NAME_SIZE];
5592f78dd7fSKuninori Morimoto 	int i, nr, ret;
560ba9c949fSKuninori Morimoto 
561e8e7b7bdSKuninori Morimoto 	/* This driver doesn't support Gen1 at this point */
562e8e7b7bdSKuninori Morimoto 	if (rsnd_is_gen1(priv))
563e8e7b7bdSKuninori Morimoto 		return 0;
564033e7ed8SKuninori Morimoto 
565adf6a681SKuninori Morimoto 	node = rsnd_src_of_node(priv);
566adf6a681SKuninori Morimoto 	if (!node)
567adf6a681SKuninori Morimoto 		return 0; /* not used is not error */
56890e8e50fSKuninori Morimoto 
569adf6a681SKuninori Morimoto 	nr = of_get_child_count(node);
570adf6a681SKuninori Morimoto 	if (!nr) {
571adf6a681SKuninori Morimoto 		ret = -EINVAL;
572adf6a681SKuninori Morimoto 		goto rsnd_src_probe_done;
573adf6a681SKuninori Morimoto 	}
574ba9c949fSKuninori Morimoto 
575a86854d0SKees Cook 	src	= devm_kcalloc(dev, nr, sizeof(*src), GFP_KERNEL);
576adf6a681SKuninori Morimoto 	if (!src) {
577adf6a681SKuninori Morimoto 		ret = -ENOMEM;
578adf6a681SKuninori Morimoto 		goto rsnd_src_probe_done;
579adf6a681SKuninori Morimoto 	}
580ba9c949fSKuninori Morimoto 
581ba9c949fSKuninori Morimoto 	priv->src_nr	= nr;
582ba9c949fSKuninori Morimoto 	priv->src	= src;
583ba9c949fSKuninori Morimoto 
584adf6a681SKuninori Morimoto 	i = 0;
585adf6a681SKuninori Morimoto 	for_each_child_of_node(node, np) {
586de196515SSergei Shtylyov 		if (!of_device_is_available(np))
587de196515SSergei Shtylyov 			goto skip;
588de196515SSergei Shtylyov 
589adf6a681SKuninori Morimoto 		src = rsnd_src_get(priv, i);
590adf6a681SKuninori Morimoto 
5918aefda50SKuninori Morimoto 		snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d",
5928aefda50SKuninori Morimoto 			 SRC_NAME, i);
593ba9c949fSKuninori Morimoto 
594adf6a681SKuninori Morimoto 		src->irq = irq_of_parse_and_map(np, 0);
595adf6a681SKuninori Morimoto 		if (!src->irq) {
596adf6a681SKuninori Morimoto 			ret = -EINVAL;
59753ba2aa3SJulia Lawall 			of_node_put(np);
598adf6a681SKuninori Morimoto 			goto rsnd_src_probe_done;
599adf6a681SKuninori Morimoto 		}
600ba9c949fSKuninori Morimoto 
601adf6a681SKuninori Morimoto 		clk = devm_clk_get(dev, name);
602adf6a681SKuninori Morimoto 		if (IS_ERR(clk)) {
603adf6a681SKuninori Morimoto 			ret = PTR_ERR(clk);
60453ba2aa3SJulia Lawall 			of_node_put(np);
605adf6a681SKuninori Morimoto 			goto rsnd_src_probe_done;
606adf6a681SKuninori Morimoto 		}
607ba9c949fSKuninori Morimoto 
608e8e7b7bdSKuninori Morimoto 		ret = rsnd_mod_init(priv, rsnd_mod_get(src),
609*7e7fe06dSKuninori Morimoto 				    &rsnd_src_ops, clk, RSND_MOD_SRC, i);
61053ba2aa3SJulia Lawall 		if (ret) {
61153ba2aa3SJulia Lawall 			of_node_put(np);
612adf6a681SKuninori Morimoto 			goto rsnd_src_probe_done;
61353ba2aa3SJulia Lawall 		}
614adf6a681SKuninori Morimoto 
615de196515SSergei Shtylyov skip:
616adf6a681SKuninori Morimoto 		i++;
617ba9c949fSKuninori Morimoto 	}
618ba9c949fSKuninori Morimoto 
619adf6a681SKuninori Morimoto 	ret = 0;
620adf6a681SKuninori Morimoto 
621adf6a681SKuninori Morimoto rsnd_src_probe_done:
622adf6a681SKuninori Morimoto 	of_node_put(node);
623adf6a681SKuninori Morimoto 
624adf6a681SKuninori Morimoto 	return ret;
625ba9c949fSKuninori Morimoto }
6262f78dd7fSKuninori Morimoto 
6272ea6b074SKuninori Morimoto void rsnd_src_remove(struct rsnd_priv *priv)
6282f78dd7fSKuninori Morimoto {
6292f78dd7fSKuninori Morimoto 	struct rsnd_src *src;
6302f78dd7fSKuninori Morimoto 	int i;
6312f78dd7fSKuninori Morimoto 
6322f78dd7fSKuninori Morimoto 	for_each_rsnd_src(src, priv, i) {
633b76e218aSKuninori Morimoto 		rsnd_mod_quit(rsnd_mod_get(src));
6342f78dd7fSKuninori Morimoto 	}
6352f78dd7fSKuninori Morimoto }
636