xref: /openbmc/linux/sound/soc/sh/rcar/src.c (revision c2aaaa57d44a195b71fe1e9ff0c6a80ac017495d)
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 */
28adf6a681SKuninori Morimoto 	int irq;
29ba9c949fSKuninori Morimoto };
30ba9c949fSKuninori Morimoto 
31ba9c949fSKuninori Morimoto #define RSND_SRC_NAME_SIZE 16
32ba9c949fSKuninori Morimoto 
33adf6a681SKuninori Morimoto #define rsnd_src_get(priv, id) ((struct rsnd_src *)(priv->src) + id)
34da599fd3SKuninori Morimoto #define rsnd_src_nr(priv) ((priv)->src_nr)
35ab2049f9SKuninori Morimoto #define rsnd_src_sync_is_enabled(mod) (rsnd_mod_to_src(mod)->sen.val)
3682e76ed3SKuninori Morimoto 
37ba9c949fSKuninori Morimoto #define rsnd_mod_to_src(_mod)				\
38ba9c949fSKuninori Morimoto 	container_of((_mod), struct rsnd_src, mod)
39ba9c949fSKuninori Morimoto 
40ba9c949fSKuninori Morimoto #define for_each_rsnd_src(pos, priv, i)				\
41ba9c949fSKuninori Morimoto 	for ((i) = 0;						\
42ba9c949fSKuninori Morimoto 	     ((i) < rsnd_src_nr(priv)) &&			\
43ba9c949fSKuninori Morimoto 	     ((pos) = (struct rsnd_src *)(priv)->src + i);	\
44ba9c949fSKuninori Morimoto 	     i++)
45ba9c949fSKuninori Morimoto 
46ba9c949fSKuninori Morimoto 
47ba9c949fSKuninori Morimoto /*
48ba9c949fSKuninori Morimoto  *		image of SRC (Sampling Rate Converter)
49ba9c949fSKuninori Morimoto  *
50ba9c949fSKuninori Morimoto  * 96kHz   <-> +-----+	48kHz	+-----+	 48kHz	+-------+
51ba9c949fSKuninori Morimoto  * 48kHz   <-> | SRC | <------>	| SSI |	<----->	| codec |
52ba9c949fSKuninori Morimoto  * 44.1kHz <-> +-----+		+-----+		+-------+
53ba9c949fSKuninori Morimoto  * ...
54ba9c949fSKuninori Morimoto  *
55ba9c949fSKuninori Morimoto  */
56ba9c949fSKuninori Morimoto 
5798efeeaeSKuninori Morimoto static void rsnd_src_activation(struct rsnd_mod *mod)
58379febfdSKuninori Morimoto {
59379febfdSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SWRSR, 0);
60379febfdSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SWRSR, 1);
61379febfdSKuninori Morimoto }
62379febfdSKuninori Morimoto 
63475a361aSKuninori Morimoto static void rsnd_src_halt(struct rsnd_mod *mod)
64475a361aSKuninori Morimoto {
65475a361aSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCIR, 1);
66475a361aSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SWRSR, 0);
67475a361aSKuninori Morimoto }
68475a361aSKuninori Morimoto 
699b99e9a7SKuninori Morimoto static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io,
709b99e9a7SKuninori Morimoto 					 struct rsnd_mod *mod)
7172adc61fSKuninori Morimoto {
7272adc61fSKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
7372adc61fSKuninori Morimoto 	int is_play = rsnd_io_is_play(io);
7472adc61fSKuninori Morimoto 
7572adc61fSKuninori Morimoto 	return rsnd_dma_request_channel(rsnd_src_of_node(priv),
7672adc61fSKuninori Morimoto 					mod,
7772adc61fSKuninori Morimoto 					is_play ? "rx" : "tx");
7872adc61fSKuninori Morimoto }
7972adc61fSKuninori Morimoto 
8088c61cffSKuninori Morimoto static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io,
811a9be9eeSKuninori Morimoto 				 struct rsnd_mod *mod)
8243cb6954SKuninori Morimoto {
8343cb6954SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
841a9be9eeSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
8543cb6954SKuninori Morimoto 	u32 convert_rate;
8643cb6954SKuninori Morimoto 
8743cb6954SKuninori Morimoto 	if (!runtime)
8843cb6954SKuninori Morimoto 		return 0;
8943cb6954SKuninori Morimoto 
90ab2049f9SKuninori Morimoto 	if (!rsnd_src_sync_is_enabled(mod))
91*c2aaaa57SKuninori Morimoto 		return rsnd_io_converted_rate(io);
9243cb6954SKuninori Morimoto 
9343cb6954SKuninori Morimoto 	convert_rate = src->sync.val;
9443cb6954SKuninori Morimoto 
9543cb6954SKuninori Morimoto 	if (!convert_rate)
96*c2aaaa57SKuninori Morimoto 		convert_rate = rsnd_io_converted_rate(io);
9743cb6954SKuninori Morimoto 
9843cb6954SKuninori Morimoto 	if (!convert_rate)
9943cb6954SKuninori Morimoto 		convert_rate = runtime->rate;
10043cb6954SKuninori Morimoto 
10143cb6954SKuninori Morimoto 	return convert_rate;
10243cb6954SKuninori Morimoto }
10343cb6954SKuninori Morimoto 
104cbf1494fSKuninori Morimoto unsigned int rsnd_src_get_rate(struct rsnd_priv *priv,
105ba9c949fSKuninori Morimoto 			       struct rsnd_dai_stream *io,
106cbf1494fSKuninori Morimoto 			       int is_in)
107ba9c949fSKuninori Morimoto {
108b1eac430SKuninori Morimoto 	struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
109cbf1494fSKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
110b1eac430SKuninori Morimoto 	unsigned int rate = 0;
111cbf1494fSKuninori Morimoto 	int is_play = rsnd_io_is_play(io);
112cbf1494fSKuninori Morimoto 
113cbf1494fSKuninori Morimoto 	/*
114cbf1494fSKuninori Morimoto 	 * Playback
115cbf1494fSKuninori Morimoto 	 * runtime_rate -> [SRC] -> convert_rate
116cbf1494fSKuninori Morimoto 	 *
117cbf1494fSKuninori Morimoto 	 * Capture
118cbf1494fSKuninori Morimoto 	 * convert_rate -> [SRC] -> runtime_rate
119cbf1494fSKuninori Morimoto 	 */
120cbf1494fSKuninori Morimoto 
121cbf1494fSKuninori Morimoto 	if (is_play == is_in)
122cbf1494fSKuninori Morimoto 		return runtime->rate;
123ba9c949fSKuninori Morimoto 
124ba9c949fSKuninori Morimoto 	/*
125ba9c949fSKuninori Morimoto 	 * return convert rate if SRC is used,
126ba9c949fSKuninori Morimoto 	 * otherwise, return runtime->rate as usual
127ba9c949fSKuninori Morimoto 	 */
1281a9be9eeSKuninori Morimoto 	if (src_mod)
1291a9be9eeSKuninori Morimoto 		rate = rsnd_src_convert_rate(io, src_mod);
130b1eac430SKuninori Morimoto 
131ba9c949fSKuninori Morimoto 	if (!rate)
132ba9c949fSKuninori Morimoto 		rate = runtime->rate;
133ba9c949fSKuninori Morimoto 
134ba9c949fSKuninori Morimoto 	return rate;
135ba9c949fSKuninori Morimoto }
136ba9c949fSKuninori Morimoto 
13775916f65SKuninori Morimoto static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
13875916f65SKuninori Morimoto 				      struct rsnd_mod *mod)
139ba9c949fSKuninori Morimoto {
14075916f65SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
141cfcefe01SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
14275916f65SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
14390431eb4SKuninori Morimoto 	int is_play = rsnd_io_is_play(io);
14467923f77SKuninori Morimoto 	int use_src = 0;
1450102eed5SKuninori Morimoto 	u32 fin, fout;
14675916f65SKuninori Morimoto 	u32 ifscr, fsrate, adinr;
14775916f65SKuninori Morimoto 	u32 cr, route;
14875916f65SKuninori Morimoto 	u32 bsdsr, bsisr;
14990431eb4SKuninori Morimoto 	u32 i_busif, o_busif, tmp;
15075916f65SKuninori Morimoto 	uint ratio;
151ba9c949fSKuninori Morimoto 
15275916f65SKuninori Morimoto 	if (!runtime)
15375916f65SKuninori Morimoto 		return;
154ba9c949fSKuninori Morimoto 
1550102eed5SKuninori Morimoto 	fin  = rsnd_src_get_in_rate(priv, io);
1560102eed5SKuninori Morimoto 	fout = rsnd_src_get_out_rate(priv, io);
1570102eed5SKuninori Morimoto 
15875916f65SKuninori Morimoto 	/* 6 - 1/6 are very enough ratio for SRC_BSDSR */
1590102eed5SKuninori Morimoto 	if (fin == fout)
16075916f65SKuninori Morimoto 		ratio = 0;
1610102eed5SKuninori Morimoto 	else if (fin > fout)
1620102eed5SKuninori Morimoto 		ratio = 100 * fin / fout;
16375916f65SKuninori Morimoto 	else
1640102eed5SKuninori Morimoto 		ratio = 100 * fout / fin;
165cfcefe01SKuninori Morimoto 
16675916f65SKuninori Morimoto 	if (ratio > 600) {
16775916f65SKuninori Morimoto 		dev_err(dev, "FSO/FSI ratio error\n");
16875916f65SKuninori Morimoto 		return;
169ba9c949fSKuninori Morimoto 	}
170ba9c949fSKuninori Morimoto 
17167923f77SKuninori Morimoto 	use_src = (fin != fout) | rsnd_src_sync_is_enabled(mod);
17267923f77SKuninori Morimoto 
173ba9c949fSKuninori Morimoto 	/*
17475916f65SKuninori Morimoto 	 * SRC_ADINR
175ba9c949fSKuninori Morimoto 	 */
176c45f7263SKuninori Morimoto 	adinr = rsnd_get_adinr_bit(mod, io) |
177eed76bb8SKuninori Morimoto 		rsnd_runtime_channel_original(io);
17875916f65SKuninori Morimoto 
17975916f65SKuninori Morimoto 	/*
18075916f65SKuninori Morimoto 	 * SRC_IFSCR / SRC_IFSVR
18175916f65SKuninori Morimoto 	 */
18275916f65SKuninori Morimoto 	ifscr = 0;
18375916f65SKuninori Morimoto 	fsrate = 0;
18467923f77SKuninori Morimoto 	if (use_src) {
18593ca33c9SHiroyuki Yokoyama 		u64 n;
18693ca33c9SHiroyuki Yokoyama 
18775916f65SKuninori Morimoto 		ifscr = 1;
18893ca33c9SHiroyuki Yokoyama 		n = (u64)0x0400000 * fin;
18993ca33c9SHiroyuki Yokoyama 		do_div(n, fout);
19093ca33c9SHiroyuki Yokoyama 		fsrate = n;
19175916f65SKuninori Morimoto 	}
19275916f65SKuninori Morimoto 
19375916f65SKuninori Morimoto 	/*
19475916f65SKuninori Morimoto 	 * SRC_SRCCR / SRC_ROUTE_MODE0
19575916f65SKuninori Morimoto 	 */
19675916f65SKuninori Morimoto 	cr	= 0x00011110;
19775916f65SKuninori Morimoto 	route	= 0x0;
19867923f77SKuninori Morimoto 	if (use_src) {
19975916f65SKuninori Morimoto 		route	= 0x1;
20075916f65SKuninori Morimoto 
201ab2049f9SKuninori Morimoto 		if (rsnd_src_sync_is_enabled(mod)) {
20275916f65SKuninori Morimoto 			cr |= 0x1;
20375916f65SKuninori Morimoto 			route |= rsnd_io_is_play(io) ?
20475916f65SKuninori Morimoto 				(0x1 << 24) : (0x1 << 25);
20575916f65SKuninori Morimoto 		}
20675916f65SKuninori Morimoto 	}
20775916f65SKuninori Morimoto 
20875916f65SKuninori Morimoto 	/*
20975916f65SKuninori Morimoto 	 * SRC_BSDSR / SRC_BSISR
21075916f65SKuninori Morimoto 	 */
21175916f65SKuninori Morimoto 	switch (rsnd_mod_id(mod)) {
21275916f65SKuninori Morimoto 	case 5:
21375916f65SKuninori Morimoto 	case 6:
21475916f65SKuninori Morimoto 	case 7:
21575916f65SKuninori Morimoto 	case 8:
21675916f65SKuninori Morimoto 		bsdsr = 0x02400000; /* 6 - 1/6 */
21775916f65SKuninori Morimoto 		bsisr = 0x00100060; /* 6 - 1/6 */
21875916f65SKuninori Morimoto 		break;
21975916f65SKuninori Morimoto 	default:
22075916f65SKuninori Morimoto 		bsdsr = 0x01800000; /* 6 - 1/6 */
22175916f65SKuninori Morimoto 		bsisr = 0x00100060 ;/* 6 - 1/6 */
22275916f65SKuninori Morimoto 		break;
22375916f65SKuninori Morimoto 	}
22475916f65SKuninori Morimoto 
22590431eb4SKuninori Morimoto 	/* BUSIF_MODE */
22690431eb4SKuninori Morimoto 	tmp = rsnd_get_busif_shift(io, mod);
22790431eb4SKuninori Morimoto 	i_busif = ( is_play ? tmp : 0) | 1;
22890431eb4SKuninori Morimoto 	o_busif = (!is_play ? tmp : 0) | 1;
22990431eb4SKuninori Morimoto 
2300fbab951SKuninori Morimoto 	rsnd_mod_write(mod, SRC_ROUTE_MODE0, route);
2310fbab951SKuninori Morimoto 
23275916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCIR, 1);	/* initialize */
23375916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_ADINR, adinr);
23475916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_IFSCR, ifscr);
23575916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_IFSVR, fsrate);
23675916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCCR, cr);
23775916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BSDSR, bsdsr);
23875916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BSISR, bsisr);
23975916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCIR, 0);	/* cancel initialize */
24075916f65SKuninori Morimoto 
24190431eb4SKuninori Morimoto 	rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif);
24290431eb4SKuninori Morimoto 	rsnd_mod_write(mod, SRC_O_BUSIF_MODE, o_busif);
24390431eb4SKuninori Morimoto 
24475916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
24575916f65SKuninori Morimoto 
2460102eed5SKuninori Morimoto 	rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout);
24775916f65SKuninori Morimoto }
24875916f65SKuninori Morimoto 
249b5b442abSKuninori Morimoto static int rsnd_src_irq(struct rsnd_mod *mod,
250b5b442abSKuninori Morimoto 			struct rsnd_dai_stream *io,
251b5b442abSKuninori Morimoto 			struct rsnd_priv *priv,
252b5b442abSKuninori Morimoto 			int enable)
253cfcefe01SKuninori Morimoto {
254cfcefe01SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
255cfcefe01SKuninori Morimoto 	u32 sys_int_val, int_val, sys_int_mask;
256adf6a681SKuninori Morimoto 	int irq = src->irq;
257cfcefe01SKuninori Morimoto 	int id = rsnd_mod_id(mod);
258cfcefe01SKuninori Morimoto 
259cfcefe01SKuninori Morimoto 	sys_int_val =
260cfcefe01SKuninori Morimoto 	sys_int_mask = OUF_SRC(id);
261cfcefe01SKuninori Morimoto 	int_val = 0x3300;
262cfcefe01SKuninori Morimoto 
263cfcefe01SKuninori Morimoto 	/*
264cfcefe01SKuninori Morimoto 	 * IRQ is not supported on non-DT
265cfcefe01SKuninori Morimoto 	 * see
26675916f65SKuninori Morimoto 	 *	rsnd_src_probe_()
267cfcefe01SKuninori Morimoto 	 */
268cfcefe01SKuninori Morimoto 	if ((irq <= 0) || !enable) {
269cfcefe01SKuninori Morimoto 		sys_int_val = 0;
270cfcefe01SKuninori Morimoto 		int_val = 0;
271cfcefe01SKuninori Morimoto 	}
272cfcefe01SKuninori Morimoto 
2731a1bf58aSKuninori Morimoto 	/*
2741a1bf58aSKuninori Morimoto 	 * WORKAROUND
2751a1bf58aSKuninori Morimoto 	 *
276ab2049f9SKuninori Morimoto 	 * ignore over flow error when rsnd_src_sync_is_enabled()
2771a1bf58aSKuninori Morimoto 	 */
278ab2049f9SKuninori Morimoto 	if (rsnd_src_sync_is_enabled(mod))
2791a1bf58aSKuninori Morimoto 		sys_int_val = sys_int_val & 0xffff;
2801a1bf58aSKuninori Morimoto 
281cfcefe01SKuninori Morimoto 	rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val);
282cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val);
283cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val);
284b5b442abSKuninori Morimoto 
285b5b442abSKuninori Morimoto 	return 0;
286cfcefe01SKuninori Morimoto }
287cfcefe01SKuninori Morimoto 
2888cc225f7SKuninori Morimoto static void rsnd_src_status_clear(struct rsnd_mod *mod)
289cfcefe01SKuninori Morimoto {
290cfcefe01SKuninori Morimoto 	u32 val = OUF_SRC(rsnd_mod_id(mod));
291cfcefe01SKuninori Morimoto 
29242b197e7SKuninori Morimoto 	rsnd_mod_write(mod, SCU_SYS_STATUS0, val);
29342b197e7SKuninori Morimoto 	rsnd_mod_write(mod, SCU_SYS_STATUS1, val);
294cfcefe01SKuninori Morimoto }
295cfcefe01SKuninori Morimoto 
2966a25c8daSKuninori Morimoto static bool rsnd_src_error_occurred(struct rsnd_mod *mod)
297cfcefe01SKuninori Morimoto {
2982b627869SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
2992b627869SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
3001a1bf58aSKuninori Morimoto 	u32 val0, val1;
3012b627869SKuninori Morimoto 	u32 status0, status1;
302cfcefe01SKuninori Morimoto 	bool ret = false;
303cfcefe01SKuninori Morimoto 
3041a1bf58aSKuninori Morimoto 	val0 = val1 = OUF_SRC(rsnd_mod_id(mod));
3051a1bf58aSKuninori Morimoto 
3061a1bf58aSKuninori Morimoto 	/*
3071a1bf58aSKuninori Morimoto 	 * WORKAROUND
3081a1bf58aSKuninori Morimoto 	 *
309ab2049f9SKuninori Morimoto 	 * ignore over flow error when rsnd_src_sync_is_enabled()
3101a1bf58aSKuninori Morimoto 	 */
311ab2049f9SKuninori Morimoto 	if (rsnd_src_sync_is_enabled(mod))
3121a1bf58aSKuninori Morimoto 		val0 = val0 & 0xffff;
3131a1bf58aSKuninori Morimoto 
3142b627869SKuninori Morimoto 	status0 = rsnd_mod_read(mod, SCU_SYS_STATUS0);
3152b627869SKuninori Morimoto 	status1 = rsnd_mod_read(mod, SCU_SYS_STATUS1);
3162b627869SKuninori Morimoto 	if ((status0 & val0) || (status1 & val1)) {
317c0ea089dSKuninori Morimoto 		rsnd_dbg_irq_status(dev, "%s err status : 0x%08x, 0x%08x\n",
318c0ea089dSKuninori Morimoto 			rsnd_mod_name(mod), status0, status1);
3192b627869SKuninori Morimoto 
320cfcefe01SKuninori Morimoto 		ret = true;
3212b627869SKuninori Morimoto 	}
322cfcefe01SKuninori Morimoto 
323cfcefe01SKuninori Morimoto 	return ret;
324cfcefe01SKuninori Morimoto }
325cfcefe01SKuninori Morimoto 
32675916f65SKuninori Morimoto static int rsnd_src_start(struct rsnd_mod *mod,
327497debaaSKuninori Morimoto 			  struct rsnd_dai_stream *io,
328497debaaSKuninori Morimoto 			  struct rsnd_priv *priv)
329cfcefe01SKuninori Morimoto {
3301a1bf58aSKuninori Morimoto 	u32 val;
3311a1bf58aSKuninori Morimoto 
3321a1bf58aSKuninori Morimoto 	/*
3331a1bf58aSKuninori Morimoto 	 * WORKAROUND
3341a1bf58aSKuninori Morimoto 	 *
3351a1bf58aSKuninori Morimoto 	 * Enable SRC output if you want to use sync convert together with DVC
3361a1bf58aSKuninori Morimoto 	 */
337ab2049f9SKuninori Morimoto 	val = (rsnd_io_to_mod_dvc(io) && !rsnd_src_sync_is_enabled(mod)) ?
3381a1bf58aSKuninori Morimoto 		0x01 : 0x11;
339cfcefe01SKuninori Morimoto 
340cfcefe01SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, val);
341cfcefe01SKuninori Morimoto 
34275916f65SKuninori Morimoto 	return 0;
34375916f65SKuninori Morimoto }
344cfcefe01SKuninori Morimoto 
34575916f65SKuninori Morimoto static int rsnd_src_stop(struct rsnd_mod *mod,
34675916f65SKuninori Morimoto 			 struct rsnd_dai_stream *io,
34775916f65SKuninori Morimoto 			 struct rsnd_priv *priv)
34875916f65SKuninori Morimoto {
34931739a68SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, 0);
350cfcefe01SKuninori Morimoto 
351cfcefe01SKuninori Morimoto 	return 0;
352cfcefe01SKuninori Morimoto }
353cfcefe01SKuninori Morimoto 
35475916f65SKuninori Morimoto static int rsnd_src_init(struct rsnd_mod *mod,
355497debaaSKuninori Morimoto 			 struct rsnd_dai_stream *io,
356497debaaSKuninori Morimoto 			 struct rsnd_priv *priv)
357cfcefe01SKuninori Morimoto {
35875916f65SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
359cfcefe01SKuninori Morimoto 
360ef30da1cSKuninori Morimoto 	/* reset sync convert_rate */
361ef30da1cSKuninori Morimoto 	src->sync.val = 0;
362ef30da1cSKuninori Morimoto 
36375916f65SKuninori Morimoto 	rsnd_mod_power_on(mod);
364cfcefe01SKuninori Morimoto 
36598efeeaeSKuninori Morimoto 	rsnd_src_activation(mod);
366cfcefe01SKuninori Morimoto 
36775916f65SKuninori Morimoto 	rsnd_src_set_convert_rate(io, mod);
36875916f65SKuninori Morimoto 
3698cc225f7SKuninori Morimoto 	rsnd_src_status_clear(mod);
37075916f65SKuninori Morimoto 
37175916f65SKuninori Morimoto 	return 0;
372cfcefe01SKuninori Morimoto }
373cfcefe01SKuninori Morimoto 
37475916f65SKuninori Morimoto static int rsnd_src_quit(struct rsnd_mod *mod,
375b761bf27SKuninori Morimoto 			 struct rsnd_dai_stream *io,
376b761bf27SKuninori Morimoto 			 struct rsnd_priv *priv)
377b761bf27SKuninori Morimoto {
37875916f65SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
37975916f65SKuninori Morimoto 
380475a361aSKuninori Morimoto 	rsnd_src_halt(mod);
381475a361aSKuninori Morimoto 
38275916f65SKuninori Morimoto 	rsnd_mod_power_off(mod);
38375916f65SKuninori Morimoto 
38475916f65SKuninori Morimoto 	/* reset sync convert_rate */
38575916f65SKuninori Morimoto 	src->sync.val = 0;
38675916f65SKuninori Morimoto 
38775916f65SKuninori Morimoto 	return 0;
388b761bf27SKuninori Morimoto }
389b761bf27SKuninori Morimoto 
39075916f65SKuninori Morimoto static void __rsnd_src_interrupt(struct rsnd_mod *mod,
39188c61cffSKuninori Morimoto 				 struct rsnd_dai_stream *io)
392cfcefe01SKuninori Morimoto {
39302299d98SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
3946a25c8daSKuninori Morimoto 	bool stop = false;
395cfcefe01SKuninori Morimoto 
39602299d98SKuninori Morimoto 	spin_lock(&priv->lock);
39702299d98SKuninori Morimoto 
39802299d98SKuninori Morimoto 	/* ignore all cases if not working */
399d5bbe7deSKuninori Morimoto 	if (!rsnd_io_is_working(io))
40075916f65SKuninori Morimoto 		goto rsnd_src_interrupt_out;
401cfcefe01SKuninori Morimoto 
4026a25c8daSKuninori Morimoto 	if (rsnd_src_error_occurred(mod))
4036a25c8daSKuninori Morimoto 		stop = true;
40488c61cffSKuninori Morimoto 
4058cc225f7SKuninori Morimoto 	rsnd_src_status_clear(mod);
40675916f65SKuninori Morimoto rsnd_src_interrupt_out:
4078cc225f7SKuninori Morimoto 
40802299d98SKuninori Morimoto 	spin_unlock(&priv->lock);
4096a25c8daSKuninori Morimoto 
4106a25c8daSKuninori Morimoto 	if (stop)
4116a25c8daSKuninori Morimoto 		snd_pcm_stop_xrun(io->substream);
41288c61cffSKuninori Morimoto }
41388c61cffSKuninori Morimoto 
41475916f65SKuninori Morimoto static irqreturn_t rsnd_src_interrupt(int irq, void *data)
41588c61cffSKuninori Morimoto {
41688c61cffSKuninori Morimoto 	struct rsnd_mod *mod = data;
41788c61cffSKuninori Morimoto 
41875916f65SKuninori Morimoto 	rsnd_mod_interrupt(mod, __rsnd_src_interrupt);
419cfcefe01SKuninori Morimoto 
420cfcefe01SKuninori Morimoto 	return IRQ_HANDLED;
421cfcefe01SKuninori Morimoto }
422cfcefe01SKuninori Morimoto 
42375916f65SKuninori Morimoto static int rsnd_src_probe_(struct rsnd_mod *mod,
4242c0fac19SKuninori Morimoto 			   struct rsnd_dai_stream *io,
425690602fcSKuninori Morimoto 			   struct rsnd_priv *priv)
426ba9c949fSKuninori Morimoto {
427ba9c949fSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
428ba9c949fSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
429adf6a681SKuninori Morimoto 	int irq = src->irq;
430ba9c949fSKuninori Morimoto 	int ret;
431ba9c949fSKuninori Morimoto 
432cfcefe01SKuninori Morimoto 	if (irq > 0) {
433cfcefe01SKuninori Morimoto 		/*
434cfcefe01SKuninori Morimoto 		 * IRQ is not supported on non-DT
435cfcefe01SKuninori Morimoto 		 * see
436b5b442abSKuninori Morimoto 		 *	rsnd_src_irq()
437cfcefe01SKuninori Morimoto 		 */
438cfcefe01SKuninori Morimoto 		ret = devm_request_irq(dev, irq,
43975916f65SKuninori Morimoto 				       rsnd_src_interrupt,
440cfcefe01SKuninori Morimoto 				       IRQF_SHARED,
441cfcefe01SKuninori Morimoto 				       dev_name(dev), mod);
442cfcefe01SKuninori Morimoto 		if (ret)
443b543b52aSKuninori Morimoto 			return ret;
444cfcefe01SKuninori Morimoto 	}
445cfcefe01SKuninori Morimoto 
446b99305d2SKuninori Morimoto 	ret = rsnd_dma_attach(io, mod, &src->dma);
447cfcefe01SKuninori Morimoto 
448cfcefe01SKuninori Morimoto 	return ret;
449ba9c949fSKuninori Morimoto }
450ba9c949fSKuninori Morimoto 
45175916f65SKuninori Morimoto static int rsnd_src_pcm_new(struct rsnd_mod *mod,
4522c0fac19SKuninori Morimoto 			    struct rsnd_dai_stream *io,
45343cb6954SKuninori Morimoto 			    struct snd_soc_pcm_runtime *rtd)
45443cb6954SKuninori Morimoto {
45543cb6954SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
45643cb6954SKuninori Morimoto 	int ret;
45743cb6954SKuninori Morimoto 
45843cb6954SKuninori Morimoto 	/*
45943cb6954SKuninori Morimoto 	 * enable SRC sync convert if possible
46043cb6954SKuninori Morimoto 	 */
46143cb6954SKuninori Morimoto 
46243cb6954SKuninori Morimoto 	/*
46361a219feSKuninori Morimoto 	 * It can't use SRC Synchronous convert
46461a219feSKuninori Morimoto 	 * when Capture if it uses CMD
4657115cb91SKuninori Morimoto 	 */
46661a219feSKuninori Morimoto 	if (rsnd_io_to_mod_cmd(io) && !rsnd_io_is_play(io))
4677115cb91SKuninori Morimoto 		return 0;
4687115cb91SKuninori Morimoto 
4697115cb91SKuninori Morimoto 	/*
47043cb6954SKuninori Morimoto 	 * enable sync convert
47143cb6954SKuninori Morimoto 	 */
472b65a7cccSKuninori Morimoto 	ret = rsnd_kctrl_new_s(mod, io, rtd,
47343cb6954SKuninori Morimoto 			       rsnd_io_is_play(io) ?
47443cb6954SKuninori Morimoto 			       "SRC Out Rate Switch" :
47543cb6954SKuninori Morimoto 			       "SRC In Rate Switch",
476f0b04d8bSKuninori Morimoto 			       rsnd_kctrl_accept_anytime,
47775916f65SKuninori Morimoto 			       rsnd_src_set_convert_rate,
47843cb6954SKuninori Morimoto 			       &src->sen, 1);
47943cb6954SKuninori Morimoto 	if (ret < 0)
48043cb6954SKuninori Morimoto 		return ret;
48143cb6954SKuninori Morimoto 
482b65a7cccSKuninori Morimoto 	ret = rsnd_kctrl_new_s(mod, io, rtd,
48343cb6954SKuninori Morimoto 			       rsnd_io_is_play(io) ?
48443cb6954SKuninori Morimoto 			       "SRC Out Rate" :
48543cb6954SKuninori Morimoto 			       "SRC In Rate",
486f0b04d8bSKuninori Morimoto 			       rsnd_kctrl_accept_runtime,
48775916f65SKuninori Morimoto 			       rsnd_src_set_convert_rate,
48843cb6954SKuninori Morimoto 			       &src->sync, 192000);
48943cb6954SKuninori Morimoto 
49043cb6954SKuninori Morimoto 	return ret;
49143cb6954SKuninori Morimoto }
49243cb6954SKuninori Morimoto 
49375916f65SKuninori Morimoto static struct rsnd_mod_ops rsnd_src_ops = {
4948aefda50SKuninori Morimoto 	.name		= SRC_NAME,
49572adc61fSKuninori Morimoto 	.dma_req	= rsnd_src_dma_req,
49675916f65SKuninori Morimoto 	.probe		= rsnd_src_probe_,
49775916f65SKuninori Morimoto 	.init		= rsnd_src_init,
49875916f65SKuninori Morimoto 	.quit		= rsnd_src_quit,
49975916f65SKuninori Morimoto 	.start		= rsnd_src_start,
50075916f65SKuninori Morimoto 	.stop		= rsnd_src_stop,
501b5b442abSKuninori Morimoto 	.irq		= rsnd_src_irq,
50275916f65SKuninori Morimoto 	.pcm_new	= rsnd_src_pcm_new,
5037e7fe06dSKuninori Morimoto 	.get_status	= rsnd_mod_get_status,
504ba9c949fSKuninori Morimoto };
505ba9c949fSKuninori Morimoto 
506ba9c949fSKuninori Morimoto struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
507ba9c949fSKuninori Morimoto {
508ba9c949fSKuninori Morimoto 	if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv)))
509ba9c949fSKuninori Morimoto 		id = 0;
510ba9c949fSKuninori Morimoto 
511adf6a681SKuninori Morimoto 	return rsnd_mod_get(rsnd_src_get(priv, id));
51290e8e50fSKuninori Morimoto }
51390e8e50fSKuninori Morimoto 
5142ea6b074SKuninori Morimoto int rsnd_src_probe(struct rsnd_priv *priv)
515ba9c949fSKuninori Morimoto {
516adf6a681SKuninori Morimoto 	struct device_node *node;
517adf6a681SKuninori Morimoto 	struct device_node *np;
518ba9c949fSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
519ba9c949fSKuninori Morimoto 	struct rsnd_src *src;
520ba9c949fSKuninori Morimoto 	struct clk *clk;
521ba9c949fSKuninori Morimoto 	char name[RSND_SRC_NAME_SIZE];
5222f78dd7fSKuninori Morimoto 	int i, nr, ret;
523ba9c949fSKuninori Morimoto 
524e8e7b7bdSKuninori Morimoto 	/* This driver doesn't support Gen1 at this point */
525e8e7b7bdSKuninori Morimoto 	if (rsnd_is_gen1(priv))
526e8e7b7bdSKuninori Morimoto 		return 0;
527033e7ed8SKuninori Morimoto 
528adf6a681SKuninori Morimoto 	node = rsnd_src_of_node(priv);
529adf6a681SKuninori Morimoto 	if (!node)
530adf6a681SKuninori Morimoto 		return 0; /* not used is not error */
53190e8e50fSKuninori Morimoto 
532adf6a681SKuninori Morimoto 	nr = of_get_child_count(node);
533adf6a681SKuninori Morimoto 	if (!nr) {
534adf6a681SKuninori Morimoto 		ret = -EINVAL;
535adf6a681SKuninori Morimoto 		goto rsnd_src_probe_done;
536adf6a681SKuninori Morimoto 	}
537ba9c949fSKuninori Morimoto 
538a86854d0SKees Cook 	src	= devm_kcalloc(dev, nr, sizeof(*src), GFP_KERNEL);
539adf6a681SKuninori Morimoto 	if (!src) {
540adf6a681SKuninori Morimoto 		ret = -ENOMEM;
541adf6a681SKuninori Morimoto 		goto rsnd_src_probe_done;
542adf6a681SKuninori Morimoto 	}
543ba9c949fSKuninori Morimoto 
544ba9c949fSKuninori Morimoto 	priv->src_nr	= nr;
545ba9c949fSKuninori Morimoto 	priv->src	= src;
546ba9c949fSKuninori Morimoto 
547adf6a681SKuninori Morimoto 	i = 0;
548adf6a681SKuninori Morimoto 	for_each_child_of_node(node, np) {
549de196515SSergei Shtylyov 		if (!of_device_is_available(np))
550de196515SSergei Shtylyov 			goto skip;
551de196515SSergei Shtylyov 
552adf6a681SKuninori Morimoto 		src = rsnd_src_get(priv, i);
553adf6a681SKuninori Morimoto 
5548aefda50SKuninori Morimoto 		snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d",
5558aefda50SKuninori Morimoto 			 SRC_NAME, i);
556ba9c949fSKuninori Morimoto 
557adf6a681SKuninori Morimoto 		src->irq = irq_of_parse_and_map(np, 0);
558adf6a681SKuninori Morimoto 		if (!src->irq) {
559adf6a681SKuninori Morimoto 			ret = -EINVAL;
56053ba2aa3SJulia Lawall 			of_node_put(np);
561adf6a681SKuninori Morimoto 			goto rsnd_src_probe_done;
562adf6a681SKuninori Morimoto 		}
563ba9c949fSKuninori Morimoto 
564adf6a681SKuninori Morimoto 		clk = devm_clk_get(dev, name);
565adf6a681SKuninori Morimoto 		if (IS_ERR(clk)) {
566adf6a681SKuninori Morimoto 			ret = PTR_ERR(clk);
56753ba2aa3SJulia Lawall 			of_node_put(np);
568adf6a681SKuninori Morimoto 			goto rsnd_src_probe_done;
569adf6a681SKuninori Morimoto 		}
570ba9c949fSKuninori Morimoto 
571e8e7b7bdSKuninori Morimoto 		ret = rsnd_mod_init(priv, rsnd_mod_get(src),
5727e7fe06dSKuninori Morimoto 				    &rsnd_src_ops, clk, RSND_MOD_SRC, i);
57353ba2aa3SJulia Lawall 		if (ret) {
57453ba2aa3SJulia Lawall 			of_node_put(np);
575adf6a681SKuninori Morimoto 			goto rsnd_src_probe_done;
57653ba2aa3SJulia Lawall 		}
577adf6a681SKuninori Morimoto 
578de196515SSergei Shtylyov skip:
579adf6a681SKuninori Morimoto 		i++;
580ba9c949fSKuninori Morimoto 	}
581ba9c949fSKuninori Morimoto 
582adf6a681SKuninori Morimoto 	ret = 0;
583adf6a681SKuninori Morimoto 
584adf6a681SKuninori Morimoto rsnd_src_probe_done:
585adf6a681SKuninori Morimoto 	of_node_put(node);
586adf6a681SKuninori Morimoto 
587adf6a681SKuninori Morimoto 	return ret;
588ba9c949fSKuninori Morimoto }
5892f78dd7fSKuninori Morimoto 
5902ea6b074SKuninori Morimoto void rsnd_src_remove(struct rsnd_priv *priv)
5912f78dd7fSKuninori Morimoto {
5922f78dd7fSKuninori Morimoto 	struct rsnd_src *src;
5932f78dd7fSKuninori Morimoto 	int i;
5942f78dd7fSKuninori Morimoto 
5952f78dd7fSKuninori Morimoto 	for_each_rsnd_src(src, priv, i) {
596b76e218aSKuninori Morimoto 		rsnd_mod_quit(rsnd_mod_get(src));
5972f78dd7fSKuninori Morimoto 	}
5982f78dd7fSKuninori Morimoto }
599