xref: /openbmc/linux/sound/soc/sh/rcar/src.c (revision 98efeeaeeb5f2a66603ba7c9cb9b4f7a02dd3c01)
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_mod mod;
24940e9479SKuninori Morimoto 	struct rsnd_mod *dma;
2543cb6954SKuninori Morimoto 	struct rsnd_kctrl_cfg_s sen;  /* sync convert enable */
2643cb6954SKuninori Morimoto 	struct rsnd_kctrl_cfg_s sync; /* sync convert */
273b7843ffSKuninori Morimoto 	u32 convert_rate; /* sampling rate convert */
28cfcefe01SKuninori Morimoto 	int err;
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)
35232c00b6SKuninori Morimoto #define rsnd_src_to_dma(src) ((src)->dma)
36da599fd3SKuninori Morimoto #define rsnd_src_nr(priv) ((priv)->src_nr)
3743cb6954SKuninori Morimoto #define rsnd_enable_sync_convert(src) ((src)->sen.val)
3882e76ed3SKuninori Morimoto 
39ba9c949fSKuninori Morimoto #define rsnd_mod_to_src(_mod)				\
40ba9c949fSKuninori Morimoto 	container_of((_mod), struct rsnd_src, mod)
41ba9c949fSKuninori Morimoto 
42ba9c949fSKuninori Morimoto #define for_each_rsnd_src(pos, priv, i)				\
43ba9c949fSKuninori Morimoto 	for ((i) = 0;						\
44ba9c949fSKuninori Morimoto 	     ((i) < rsnd_src_nr(priv)) &&			\
45ba9c949fSKuninori Morimoto 	     ((pos) = (struct rsnd_src *)(priv)->src + i);	\
46ba9c949fSKuninori Morimoto 	     i++)
47ba9c949fSKuninori Morimoto 
48ba9c949fSKuninori Morimoto 
49ba9c949fSKuninori Morimoto /*
50ba9c949fSKuninori Morimoto  *		image of SRC (Sampling Rate Converter)
51ba9c949fSKuninori Morimoto  *
52ba9c949fSKuninori Morimoto  * 96kHz   <-> +-----+	48kHz	+-----+	 48kHz	+-------+
53ba9c949fSKuninori Morimoto  * 48kHz   <-> | SRC | <------>	| SSI |	<----->	| codec |
54ba9c949fSKuninori Morimoto  * 44.1kHz <-> +-----+		+-----+		+-------+
55ba9c949fSKuninori Morimoto  * ...
56ba9c949fSKuninori Morimoto  *
57ba9c949fSKuninori Morimoto  */
58ba9c949fSKuninori Morimoto 
59ba9c949fSKuninori Morimoto /*
60ba9c949fSKuninori Morimoto  * src.c is caring...
61ba9c949fSKuninori Morimoto  *
62ba9c949fSKuninori Morimoto  * Gen1
63ba9c949fSKuninori Morimoto  *
64ba9c949fSKuninori Morimoto  * [mem] -> [SRU] -> [SSI]
65ba9c949fSKuninori Morimoto  *        |--------|
66ba9c949fSKuninori Morimoto  *
67ba9c949fSKuninori Morimoto  * Gen2
68ba9c949fSKuninori Morimoto  *
69ba9c949fSKuninori Morimoto  * [mem] -> [SRC] -> [SSIU] -> [SSI]
70ba9c949fSKuninori Morimoto  *        |-----------------|
71ba9c949fSKuninori Morimoto  */
72ba9c949fSKuninori Morimoto 
73*98efeeaeSKuninori Morimoto static void rsnd_src_activation(struct rsnd_mod *mod)
74379febfdSKuninori Morimoto {
75379febfdSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SWRSR, 0);
76379febfdSKuninori Morimoto 	rsnd_mod_write(mod, SRC_SWRSR, 1);
77379febfdSKuninori Morimoto }
78379febfdSKuninori Morimoto 
799b99e9a7SKuninori Morimoto static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io,
809b99e9a7SKuninori Morimoto 					 struct rsnd_mod *mod)
8172adc61fSKuninori Morimoto {
8272adc61fSKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
8372adc61fSKuninori Morimoto 	int is_play = rsnd_io_is_play(io);
8472adc61fSKuninori Morimoto 
8572adc61fSKuninori Morimoto 	return rsnd_dma_request_channel(rsnd_src_of_node(priv),
8672adc61fSKuninori Morimoto 					mod,
8772adc61fSKuninori Morimoto 					is_play ? "rx" : "tx");
8872adc61fSKuninori Morimoto }
8972adc61fSKuninori Morimoto 
9088c61cffSKuninori Morimoto static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io,
9188c61cffSKuninori Morimoto 				 struct rsnd_src *src)
9243cb6954SKuninori Morimoto {
9343cb6954SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
9443cb6954SKuninori Morimoto 	u32 convert_rate;
9543cb6954SKuninori Morimoto 
9643cb6954SKuninori Morimoto 	if (!runtime)
9743cb6954SKuninori Morimoto 		return 0;
9843cb6954SKuninori Morimoto 
9943cb6954SKuninori Morimoto 	if (!rsnd_enable_sync_convert(src))
10043cb6954SKuninori Morimoto 		return src->convert_rate;
10143cb6954SKuninori Morimoto 
10243cb6954SKuninori Morimoto 	convert_rate = src->sync.val;
10343cb6954SKuninori Morimoto 
10443cb6954SKuninori Morimoto 	if (!convert_rate)
10543cb6954SKuninori Morimoto 		convert_rate = src->convert_rate;
10643cb6954SKuninori Morimoto 
10743cb6954SKuninori Morimoto 	if (!convert_rate)
10843cb6954SKuninori Morimoto 		convert_rate = runtime->rate;
10943cb6954SKuninori Morimoto 
11043cb6954SKuninori Morimoto 	return convert_rate;
11143cb6954SKuninori Morimoto }
11243cb6954SKuninori Morimoto 
113ba9c949fSKuninori Morimoto unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
114ba9c949fSKuninori Morimoto 				   struct rsnd_dai_stream *io,
115ba9c949fSKuninori Morimoto 				   struct snd_pcm_runtime *runtime)
116ba9c949fSKuninori Morimoto {
117b1eac430SKuninori Morimoto 	struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
118ba9c949fSKuninori Morimoto 	struct rsnd_src *src;
119b1eac430SKuninori Morimoto 	unsigned int rate = 0;
120ba9c949fSKuninori Morimoto 
121b1eac430SKuninori Morimoto 	if (src_mod) {
122b1eac430SKuninori Morimoto 		src = rsnd_mod_to_src(src_mod);
123ba9c949fSKuninori Morimoto 
124ba9c949fSKuninori Morimoto 		/*
125ba9c949fSKuninori Morimoto 		 * return convert rate if SRC is used,
126ba9c949fSKuninori Morimoto 		 * otherwise, return runtime->rate as usual
127ba9c949fSKuninori Morimoto 		 */
12888c61cffSKuninori Morimoto 		rate = rsnd_src_convert_rate(io, src);
129b1eac430SKuninori Morimoto 	}
130b1eac430SKuninori Morimoto 
131ba9c949fSKuninori Morimoto 	if (!rate)
132ba9c949fSKuninori Morimoto 		rate = runtime->rate;
133ba9c949fSKuninori Morimoto 
134ba9c949fSKuninori Morimoto 	return rate;
135ba9c949fSKuninori Morimoto }
136ba9c949fSKuninori Morimoto 
1373b7843ffSKuninori Morimoto static int rsnd_src_hw_params(struct rsnd_mod *mod,
1382c0fac19SKuninori Morimoto 			      struct rsnd_dai_stream *io,
1393b7843ffSKuninori Morimoto 			      struct snd_pcm_substream *substream,
1403b7843ffSKuninori Morimoto 			      struct snd_pcm_hw_params *fe_params)
1413b7843ffSKuninori Morimoto {
1423b7843ffSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
1433b7843ffSKuninori Morimoto 	struct snd_soc_pcm_runtime *fe = substream->private_data;
1443b7843ffSKuninori Morimoto 
1453b7843ffSKuninori Morimoto 	/*
1463b7843ffSKuninori Morimoto 	 * SRC assumes that it is used under DPCM if user want to use
1473b7843ffSKuninori Morimoto 	 * sampling rate convert. Then, SRC should be FE.
1483b7843ffSKuninori Morimoto 	 * And then, this function will be called *after* BE settings.
1493b7843ffSKuninori Morimoto 	 * this means, each BE already has fixuped hw_params.
1503b7843ffSKuninori Morimoto 	 * see
1513b7843ffSKuninori Morimoto 	 *	dpcm_fe_dai_hw_params()
1523b7843ffSKuninori Morimoto 	 *	dpcm_be_dai_hw_params()
1533b7843ffSKuninori Morimoto 	 */
1543b7843ffSKuninori Morimoto 	if (fe->dai_link->dynamic) {
1553b7843ffSKuninori Morimoto 		int stream = substream->stream;
1563b7843ffSKuninori Morimoto 		struct snd_soc_dpcm *dpcm;
1573b7843ffSKuninori Morimoto 		struct snd_pcm_hw_params *be_params;
1583b7843ffSKuninori Morimoto 
1593b7843ffSKuninori Morimoto 		list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1603b7843ffSKuninori Morimoto 			be_params = &dpcm->hw_params;
1613b7843ffSKuninori Morimoto 
1623b7843ffSKuninori Morimoto 			if (params_rate(fe_params) != params_rate(be_params))
1633b7843ffSKuninori Morimoto 				src->convert_rate = params_rate(be_params);
1643b7843ffSKuninori Morimoto 		}
1653b7843ffSKuninori Morimoto 	}
1663b7843ffSKuninori Morimoto 
1673b7843ffSKuninori Morimoto 	return 0;
1683b7843ffSKuninori Morimoto }
1693b7843ffSKuninori Morimoto 
17075916f65SKuninori Morimoto static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
17175916f65SKuninori Morimoto 				      struct rsnd_mod *mod)
172ba9c949fSKuninori Morimoto {
17375916f65SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
174cfcefe01SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
17575916f65SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
17675916f65SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
17775916f65SKuninori Morimoto 	u32 convert_rate = rsnd_src_convert_rate(io, src);
17875916f65SKuninori Morimoto 	u32 ifscr, fsrate, adinr;
17975916f65SKuninori Morimoto 	u32 cr, route;
18075916f65SKuninori Morimoto 	u32 bsdsr, bsisr;
18175916f65SKuninori Morimoto 	uint ratio;
182ba9c949fSKuninori Morimoto 
18375916f65SKuninori Morimoto 	if (!runtime)
18475916f65SKuninori Morimoto 		return;
185ba9c949fSKuninori Morimoto 
18675916f65SKuninori Morimoto 	/* 6 - 1/6 are very enough ratio for SRC_BSDSR */
18775916f65SKuninori Morimoto 	if (!convert_rate)
18875916f65SKuninori Morimoto 		ratio = 0;
18975916f65SKuninori Morimoto 	else if (convert_rate > runtime->rate)
19075916f65SKuninori Morimoto 		ratio = 100 * convert_rate / runtime->rate;
19175916f65SKuninori Morimoto 	else
19275916f65SKuninori Morimoto 		ratio = 100 * runtime->rate / convert_rate;
193cfcefe01SKuninori Morimoto 
19475916f65SKuninori Morimoto 	if (ratio > 600) {
19575916f65SKuninori Morimoto 		dev_err(dev, "FSO/FSI ratio error\n");
19675916f65SKuninori Morimoto 		return;
197ba9c949fSKuninori Morimoto 	}
198ba9c949fSKuninori Morimoto 
199ba9c949fSKuninori Morimoto 	/*
20075916f65SKuninori Morimoto 	 *	SRC_ADINR
201ba9c949fSKuninori Morimoto 	 */
202c45f7263SKuninori Morimoto 	adinr = rsnd_get_adinr_bit(mod, io) |
203c45f7263SKuninori Morimoto 		rsnd_get_adinr_chan(mod, io);
20475916f65SKuninori Morimoto 
20575916f65SKuninori Morimoto 	/*
20675916f65SKuninori Morimoto 	 *	SRC_IFSCR / SRC_IFSVR
20775916f65SKuninori Morimoto 	 */
20875916f65SKuninori Morimoto 	ifscr = 0;
20975916f65SKuninori Morimoto 	fsrate = 0;
21075916f65SKuninori Morimoto 	if (convert_rate) {
21175916f65SKuninori Morimoto 		ifscr = 1;
21275916f65SKuninori Morimoto 		fsrate = 0x0400000 / convert_rate * runtime->rate;
21375916f65SKuninori Morimoto 	}
21475916f65SKuninori Morimoto 
21575916f65SKuninori Morimoto 	/*
21675916f65SKuninori Morimoto 	 *	SRC_SRCCR / SRC_ROUTE_MODE0
21775916f65SKuninori Morimoto 	 */
21875916f65SKuninori Morimoto 	cr	= 0x00011110;
21975916f65SKuninori Morimoto 	route	= 0x0;
22075916f65SKuninori Morimoto 	if (convert_rate) {
22175916f65SKuninori Morimoto 		route	= 0x1;
22275916f65SKuninori Morimoto 
22375916f65SKuninori Morimoto 		if (rsnd_enable_sync_convert(src)) {
22475916f65SKuninori Morimoto 			cr |= 0x1;
22575916f65SKuninori Morimoto 			route |= rsnd_io_is_play(io) ?
22675916f65SKuninori Morimoto 				(0x1 << 24) : (0x1 << 25);
22775916f65SKuninori Morimoto 		}
22875916f65SKuninori Morimoto 	}
22975916f65SKuninori Morimoto 
23075916f65SKuninori Morimoto 	/*
23175916f65SKuninori Morimoto 	 * SRC_BSDSR / SRC_BSISR
23275916f65SKuninori Morimoto 	 */
23375916f65SKuninori Morimoto 	switch (rsnd_mod_id(mod)) {
23475916f65SKuninori Morimoto 	case 5:
23575916f65SKuninori Morimoto 	case 6:
23675916f65SKuninori Morimoto 	case 7:
23775916f65SKuninori Morimoto 	case 8:
23875916f65SKuninori Morimoto 		bsdsr = 0x02400000; /* 6 - 1/6 */
23975916f65SKuninori Morimoto 		bsisr = 0x00100060; /* 6 - 1/6 */
24075916f65SKuninori Morimoto 		break;
24175916f65SKuninori Morimoto 	default:
24275916f65SKuninori Morimoto 		bsdsr = 0x01800000; /* 6 - 1/6 */
24375916f65SKuninori Morimoto 		bsisr = 0x00100060 ;/* 6 - 1/6 */
24475916f65SKuninori Morimoto 		break;
24575916f65SKuninori Morimoto 	}
24675916f65SKuninori Morimoto 
24775916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCIR, 1);	/* initialize */
24875916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_ADINR, adinr);
24975916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_IFSCR, ifscr);
25075916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_IFSVR, fsrate);
25175916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCCR, cr);
25275916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BSDSR, bsdsr);
25375916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BSISR, bsisr);
25475916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_SRCIR, 0);	/* cancel initialize */
25575916f65SKuninori Morimoto 
25675916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_ROUTE_MODE0, route);
257bf4e8d7cSKuninori Morimoto 	rsnd_mod_write(mod, SRC_I_BUSIF_MODE, 1);
258bf4e8d7cSKuninori Morimoto 	rsnd_mod_write(mod, SRC_O_BUSIF_MODE, 1);
25975916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
26075916f65SKuninori Morimoto 
26175916f65SKuninori Morimoto 	if (convert_rate)
26275916f65SKuninori Morimoto 		rsnd_adg_set_convert_clk_gen2(mod, io,
26375916f65SKuninori Morimoto 					      runtime->rate,
26475916f65SKuninori Morimoto 					      convert_rate);
26575916f65SKuninori Morimoto 	else
26675916f65SKuninori Morimoto 		rsnd_adg_set_convert_timing_gen2(mod, io);
26775916f65SKuninori Morimoto }
26875916f65SKuninori Morimoto 
26975916f65SKuninori Morimoto #define rsnd_src_irq_enable(mod)  rsnd_src_irq_ctrol(mod, 1)
27075916f65SKuninori Morimoto #define rsnd_src_irq_disable(mod) rsnd_src_irq_ctrol(mod, 0)
27175916f65SKuninori Morimoto static void rsnd_src_irq_ctrol(struct rsnd_mod *mod, int enable)
272cfcefe01SKuninori Morimoto {
273cfcefe01SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
274cfcefe01SKuninori Morimoto 	u32 sys_int_val, int_val, sys_int_mask;
275adf6a681SKuninori Morimoto 	int irq = src->irq;
276cfcefe01SKuninori Morimoto 	int id = rsnd_mod_id(mod);
277cfcefe01SKuninori Morimoto 
278cfcefe01SKuninori Morimoto 	sys_int_val =
279cfcefe01SKuninori Morimoto 	sys_int_mask = OUF_SRC(id);
280cfcefe01SKuninori Morimoto 	int_val = 0x3300;
281cfcefe01SKuninori Morimoto 
282cfcefe01SKuninori Morimoto 	/*
283cfcefe01SKuninori Morimoto 	 * IRQ is not supported on non-DT
284cfcefe01SKuninori Morimoto 	 * see
28575916f65SKuninori Morimoto 	 *	rsnd_src_probe_()
286cfcefe01SKuninori Morimoto 	 */
287cfcefe01SKuninori Morimoto 	if ((irq <= 0) || !enable) {
288cfcefe01SKuninori Morimoto 		sys_int_val = 0;
289cfcefe01SKuninori Morimoto 		int_val = 0;
290cfcefe01SKuninori Morimoto 	}
291cfcefe01SKuninori Morimoto 
2921a1bf58aSKuninori Morimoto 	/*
2931a1bf58aSKuninori Morimoto 	 * WORKAROUND
2941a1bf58aSKuninori Morimoto 	 *
2951a1bf58aSKuninori Morimoto 	 * ignore over flow error when rsnd_enable_sync_convert()
2961a1bf58aSKuninori Morimoto 	 */
2971a1bf58aSKuninori Morimoto 	if (rsnd_enable_sync_convert(src))
2981a1bf58aSKuninori Morimoto 		sys_int_val = sys_int_val & 0xffff;
2991a1bf58aSKuninori Morimoto 
300cfcefe01SKuninori Morimoto 	rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val);
301cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val);
302cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val);
303cfcefe01SKuninori Morimoto }
304cfcefe01SKuninori Morimoto 
3058cc225f7SKuninori Morimoto static void rsnd_src_status_clear(struct rsnd_mod *mod)
306cfcefe01SKuninori Morimoto {
307cfcefe01SKuninori Morimoto 	u32 val = OUF_SRC(rsnd_mod_id(mod));
308cfcefe01SKuninori Morimoto 
309cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_STATUS0, val, val);
310cfcefe01SKuninori Morimoto 	rsnd_mod_bset(mod, SCU_SYS_STATUS1, val, val);
311cfcefe01SKuninori Morimoto }
312cfcefe01SKuninori Morimoto 
3138cc225f7SKuninori Morimoto static bool rsnd_src_record_error(struct rsnd_mod *mod)
314cfcefe01SKuninori Morimoto {
3151a1bf58aSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
3161a1bf58aSKuninori Morimoto 	u32 val0, val1;
317cfcefe01SKuninori Morimoto 	bool ret = false;
318cfcefe01SKuninori Morimoto 
3191a1bf58aSKuninori Morimoto 	val0 = val1 = OUF_SRC(rsnd_mod_id(mod));
3201a1bf58aSKuninori Morimoto 
3211a1bf58aSKuninori Morimoto 	/*
3221a1bf58aSKuninori Morimoto 	 * WORKAROUND
3231a1bf58aSKuninori Morimoto 	 *
3241a1bf58aSKuninori Morimoto 	 * ignore over flow error when rsnd_enable_sync_convert()
3251a1bf58aSKuninori Morimoto 	 */
3261a1bf58aSKuninori Morimoto 	if (rsnd_enable_sync_convert(src))
3271a1bf58aSKuninori Morimoto 		val0 = val0 & 0xffff;
3281a1bf58aSKuninori Morimoto 
3291a1bf58aSKuninori Morimoto 	if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val0) ||
3301a1bf58aSKuninori Morimoto 	    (rsnd_mod_read(mod, SCU_SYS_STATUS1) & val1)) {
331cfcefe01SKuninori Morimoto 		struct rsnd_src *src = rsnd_mod_to_src(mod);
332cfcefe01SKuninori Morimoto 
333cfcefe01SKuninori Morimoto 		src->err++;
334cfcefe01SKuninori Morimoto 		ret = true;
335cfcefe01SKuninori Morimoto 	}
336cfcefe01SKuninori Morimoto 
337cfcefe01SKuninori Morimoto 	return ret;
338cfcefe01SKuninori Morimoto }
339cfcefe01SKuninori Morimoto 
34075916f65SKuninori Morimoto static int rsnd_src_start(struct rsnd_mod *mod,
341497debaaSKuninori Morimoto 			  struct rsnd_dai_stream *io,
342497debaaSKuninori Morimoto 			  struct rsnd_priv *priv)
343cfcefe01SKuninori Morimoto {
3441a1bf58aSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
3451a1bf58aSKuninori Morimoto 	u32 val;
3461a1bf58aSKuninori Morimoto 
3471a1bf58aSKuninori Morimoto 	/*
3481a1bf58aSKuninori Morimoto 	 * WORKAROUND
3491a1bf58aSKuninori Morimoto 	 *
3501a1bf58aSKuninori Morimoto 	 * Enable SRC output if you want to use sync convert together with DVC
3511a1bf58aSKuninori Morimoto 	 */
3521a1bf58aSKuninori Morimoto 	val = (rsnd_io_to_mod_dvc(io) && !rsnd_enable_sync_convert(src)) ?
3531a1bf58aSKuninori Morimoto 		0x01 : 0x11;
354cfcefe01SKuninori Morimoto 
355cfcefe01SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, val);
356cfcefe01SKuninori Morimoto 
35775916f65SKuninori Morimoto 	return 0;
35875916f65SKuninori Morimoto }
359cfcefe01SKuninori Morimoto 
36075916f65SKuninori Morimoto static int rsnd_src_stop(struct rsnd_mod *mod,
36175916f65SKuninori Morimoto 			 struct rsnd_dai_stream *io,
36275916f65SKuninori Morimoto 			 struct rsnd_priv *priv)
36375916f65SKuninori Morimoto {
36475916f65SKuninori Morimoto 	/*
36575916f65SKuninori Morimoto 	 * stop SRC output only
36675916f65SKuninori Morimoto 	 * see rsnd_src_quit
36775916f65SKuninori Morimoto 	 */
36875916f65SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, 0x01);
369cfcefe01SKuninori Morimoto 
370cfcefe01SKuninori Morimoto 	return 0;
371cfcefe01SKuninori Morimoto }
372cfcefe01SKuninori Morimoto 
37375916f65SKuninori Morimoto static int rsnd_src_init(struct rsnd_mod *mod,
374497debaaSKuninori Morimoto 			 struct rsnd_dai_stream *io,
375497debaaSKuninori Morimoto 			 struct rsnd_priv *priv)
376cfcefe01SKuninori Morimoto {
37775916f65SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
378cfcefe01SKuninori Morimoto 
37975916f65SKuninori Morimoto 	rsnd_mod_power_on(mod);
380cfcefe01SKuninori Morimoto 
381*98efeeaeSKuninori Morimoto 	rsnd_src_activation(mod);
382cfcefe01SKuninori Morimoto 
38375916f65SKuninori Morimoto 	rsnd_src_set_convert_rate(io, mod);
38475916f65SKuninori Morimoto 
3858cc225f7SKuninori Morimoto 	rsnd_src_status_clear(mod);
38675916f65SKuninori Morimoto 
38775916f65SKuninori Morimoto 	rsnd_src_irq_enable(mod);
38875916f65SKuninori Morimoto 
38975916f65SKuninori Morimoto 	src->err = 0;
39075916f65SKuninori Morimoto 
39175916f65SKuninori Morimoto 	/* reset sync convert_rate */
39275916f65SKuninori Morimoto 	src->sync.val = 0;
39375916f65SKuninori Morimoto 
39475916f65SKuninori Morimoto 	return 0;
395cfcefe01SKuninori Morimoto }
396cfcefe01SKuninori Morimoto 
39775916f65SKuninori Morimoto static int rsnd_src_quit(struct rsnd_mod *mod,
398b761bf27SKuninori Morimoto 			 struct rsnd_dai_stream *io,
399b761bf27SKuninori Morimoto 			 struct rsnd_priv *priv)
400b761bf27SKuninori Morimoto {
40175916f65SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
40275916f65SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
40375916f65SKuninori Morimoto 
40475916f65SKuninori Morimoto 	rsnd_src_irq_disable(mod);
40575916f65SKuninori Morimoto 
406b761bf27SKuninori Morimoto 	/* stop both out/in */
407b761bf27SKuninori Morimoto 	rsnd_mod_write(mod, SRC_CTRL, 0);
408b761bf27SKuninori Morimoto 
40975916f65SKuninori Morimoto 	rsnd_mod_power_off(mod);
41075916f65SKuninori Morimoto 
41175916f65SKuninori Morimoto 	if (src->err)
41275916f65SKuninori Morimoto 		dev_warn(dev, "%s[%d] under/over flow err = %d\n",
41375916f65SKuninori Morimoto 			 rsnd_mod_name(mod), rsnd_mod_id(mod), src->err);
41475916f65SKuninori Morimoto 
41575916f65SKuninori Morimoto 	src->convert_rate = 0;
41675916f65SKuninori Morimoto 
41775916f65SKuninori Morimoto 	/* reset sync convert_rate */
41875916f65SKuninori Morimoto 	src->sync.val = 0;
41975916f65SKuninori Morimoto 
42075916f65SKuninori Morimoto 	return 0;
421b761bf27SKuninori Morimoto }
422b761bf27SKuninori Morimoto 
42375916f65SKuninori Morimoto static void __rsnd_src_interrupt(struct rsnd_mod *mod,
42488c61cffSKuninori Morimoto 				 struct rsnd_dai_stream *io)
425cfcefe01SKuninori Morimoto {
42602299d98SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
42769e32a58SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
42869e32a58SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
429cfcefe01SKuninori Morimoto 
43002299d98SKuninori Morimoto 	spin_lock(&priv->lock);
43102299d98SKuninori Morimoto 
43202299d98SKuninori Morimoto 	/* ignore all cases if not working */
433d5bbe7deSKuninori Morimoto 	if (!rsnd_io_is_working(io))
43475916f65SKuninori Morimoto 		goto rsnd_src_interrupt_out;
435cfcefe01SKuninori Morimoto 
4368cc225f7SKuninori Morimoto 	if (rsnd_src_record_error(mod)) {
437cfcefe01SKuninori Morimoto 
438cfcefe01SKuninori Morimoto 		dev_dbg(dev, "%s[%d] restart\n",
439cfcefe01SKuninori Morimoto 			rsnd_mod_name(mod), rsnd_mod_id(mod));
440639b231fSKuninori Morimoto 
44175916f65SKuninori Morimoto 		rsnd_src_stop(mod, io, priv);
44275916f65SKuninori Morimoto 		rsnd_src_start(mod, io, priv);
44369e32a58SKuninori Morimoto 	}
44469e32a58SKuninori Morimoto 
44569e32a58SKuninori Morimoto 	if (src->err > 1024) {
44675916f65SKuninori Morimoto 		rsnd_src_irq_disable(mod);
44769e32a58SKuninori Morimoto 
44869e32a58SKuninori Morimoto 		dev_warn(dev, "no more %s[%d] restart\n",
44969e32a58SKuninori Morimoto 			 rsnd_mod_name(mod), rsnd_mod_id(mod));
450cfcefe01SKuninori Morimoto 	}
45188c61cffSKuninori Morimoto 
4528cc225f7SKuninori Morimoto 	rsnd_src_status_clear(mod);
45375916f65SKuninori Morimoto rsnd_src_interrupt_out:
4548cc225f7SKuninori Morimoto 
45502299d98SKuninori Morimoto 	spin_unlock(&priv->lock);
45688c61cffSKuninori Morimoto }
45788c61cffSKuninori Morimoto 
45875916f65SKuninori Morimoto static irqreturn_t rsnd_src_interrupt(int irq, void *data)
45988c61cffSKuninori Morimoto {
46088c61cffSKuninori Morimoto 	struct rsnd_mod *mod = data;
46188c61cffSKuninori Morimoto 
46275916f65SKuninori Morimoto 	rsnd_mod_interrupt(mod, __rsnd_src_interrupt);
463cfcefe01SKuninori Morimoto 
464cfcefe01SKuninori Morimoto 	return IRQ_HANDLED;
465cfcefe01SKuninori Morimoto }
466cfcefe01SKuninori Morimoto 
46775916f65SKuninori Morimoto static int rsnd_src_probe_(struct rsnd_mod *mod,
4682c0fac19SKuninori Morimoto 			   struct rsnd_dai_stream *io,
469690602fcSKuninori Morimoto 			   struct rsnd_priv *priv)
470ba9c949fSKuninori Morimoto {
471ba9c949fSKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
472ba9c949fSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
473adf6a681SKuninori Morimoto 	int irq = src->irq;
474ba9c949fSKuninori Morimoto 	int ret;
475ba9c949fSKuninori Morimoto 
476cfcefe01SKuninori Morimoto 	if (irq > 0) {
477cfcefe01SKuninori Morimoto 		/*
478cfcefe01SKuninori Morimoto 		 * IRQ is not supported on non-DT
479cfcefe01SKuninori Morimoto 		 * see
48075916f65SKuninori Morimoto 		 *	rsnd_src_irq_enable()
481cfcefe01SKuninori Morimoto 		 */
482cfcefe01SKuninori Morimoto 		ret = devm_request_irq(dev, irq,
48375916f65SKuninori Morimoto 				       rsnd_src_interrupt,
484cfcefe01SKuninori Morimoto 				       IRQF_SHARED,
485cfcefe01SKuninori Morimoto 				       dev_name(dev), mod);
486cfcefe01SKuninori Morimoto 		if (ret)
487b543b52aSKuninori Morimoto 			return ret;
488cfcefe01SKuninori Morimoto 	}
489cfcefe01SKuninori Morimoto 
490adf6a681SKuninori Morimoto 	src->dma = rsnd_dma_attach(io, mod, 0);
491232c00b6SKuninori Morimoto 	if (IS_ERR(src->dma))
492232c00b6SKuninori Morimoto 		return PTR_ERR(src->dma);
493cfcefe01SKuninori Morimoto 
494cfcefe01SKuninori Morimoto 	return ret;
495ba9c949fSKuninori Morimoto }
496ba9c949fSKuninori Morimoto 
49775916f65SKuninori Morimoto static int rsnd_src_pcm_new(struct rsnd_mod *mod,
4982c0fac19SKuninori Morimoto 			    struct rsnd_dai_stream *io,
49943cb6954SKuninori Morimoto 			    struct snd_soc_pcm_runtime *rtd)
50043cb6954SKuninori Morimoto {
50143cb6954SKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
50243cb6954SKuninori Morimoto 	struct rsnd_src *src = rsnd_mod_to_src(mod);
50343cb6954SKuninori Morimoto 	int ret;
50443cb6954SKuninori Morimoto 
50543cb6954SKuninori Morimoto 	/*
50643cb6954SKuninori Morimoto 	 * enable SRC sync convert if possible
50743cb6954SKuninori Morimoto 	 */
50843cb6954SKuninori Morimoto 
50943cb6954SKuninori Morimoto 	/*
51043cb6954SKuninori Morimoto 	 * SRC sync convert needs clock master
51143cb6954SKuninori Morimoto 	 */
51243cb6954SKuninori Morimoto 	if (!rsnd_rdai_is_clk_master(rdai))
51343cb6954SKuninori Morimoto 		return 0;
51443cb6954SKuninori Morimoto 
51543cb6954SKuninori Morimoto 	/*
51643cb6954SKuninori Morimoto 	 * enable sync convert
51743cb6954SKuninori Morimoto 	 */
518b65a7cccSKuninori Morimoto 	ret = rsnd_kctrl_new_s(mod, io, rtd,
51943cb6954SKuninori Morimoto 			       rsnd_io_is_play(io) ?
52043cb6954SKuninori Morimoto 			       "SRC Out Rate Switch" :
52143cb6954SKuninori Morimoto 			       "SRC In Rate Switch",
52275916f65SKuninori Morimoto 			       rsnd_src_set_convert_rate,
52343cb6954SKuninori Morimoto 			       &src->sen, 1);
52443cb6954SKuninori Morimoto 	if (ret < 0)
52543cb6954SKuninori Morimoto 		return ret;
52643cb6954SKuninori Morimoto 
527b65a7cccSKuninori Morimoto 	ret = rsnd_kctrl_new_s(mod, io, rtd,
52843cb6954SKuninori Morimoto 			       rsnd_io_is_play(io) ?
52943cb6954SKuninori Morimoto 			       "SRC Out Rate" :
53043cb6954SKuninori Morimoto 			       "SRC In Rate",
53175916f65SKuninori Morimoto 			       rsnd_src_set_convert_rate,
53243cb6954SKuninori Morimoto 			       &src->sync, 192000);
53343cb6954SKuninori Morimoto 
53443cb6954SKuninori Morimoto 	return ret;
53543cb6954SKuninori Morimoto }
53643cb6954SKuninori Morimoto 
53775916f65SKuninori Morimoto static struct rsnd_mod_ops rsnd_src_ops = {
5388aefda50SKuninori Morimoto 	.name	= SRC_NAME,
53972adc61fSKuninori Morimoto 	.dma_req = rsnd_src_dma_req,
54075916f65SKuninori Morimoto 	.probe	= rsnd_src_probe_,
54175916f65SKuninori Morimoto 	.init	= rsnd_src_init,
54275916f65SKuninori Morimoto 	.quit	= rsnd_src_quit,
54375916f65SKuninori Morimoto 	.start	= rsnd_src_start,
54475916f65SKuninori Morimoto 	.stop	= rsnd_src_stop,
5453b7843ffSKuninori Morimoto 	.hw_params = rsnd_src_hw_params,
54675916f65SKuninori Morimoto 	.pcm_new = rsnd_src_pcm_new,
547ba9c949fSKuninori Morimoto };
548ba9c949fSKuninori Morimoto 
549ba9c949fSKuninori Morimoto struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
550ba9c949fSKuninori Morimoto {
551ba9c949fSKuninori Morimoto 	if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv)))
552ba9c949fSKuninori Morimoto 		id = 0;
553ba9c949fSKuninori Morimoto 
554adf6a681SKuninori Morimoto 	return rsnd_mod_get(rsnd_src_get(priv, id));
55590e8e50fSKuninori Morimoto }
55690e8e50fSKuninori Morimoto 
5572ea6b074SKuninori Morimoto int rsnd_src_probe(struct rsnd_priv *priv)
558ba9c949fSKuninori Morimoto {
559adf6a681SKuninori Morimoto 	struct device_node *node;
560adf6a681SKuninori Morimoto 	struct device_node *np;
561ba9c949fSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
562ba9c949fSKuninori Morimoto 	struct rsnd_src *src;
563ba9c949fSKuninori Morimoto 	struct clk *clk;
564ba9c949fSKuninori Morimoto 	char name[RSND_SRC_NAME_SIZE];
5652f78dd7fSKuninori Morimoto 	int i, nr, ret;
566ba9c949fSKuninori Morimoto 
567e8e7b7bdSKuninori Morimoto 	/* This driver doesn't support Gen1 at this point */
568e8e7b7bdSKuninori Morimoto 	if (rsnd_is_gen1(priv))
569e8e7b7bdSKuninori Morimoto 		return 0;
570033e7ed8SKuninori Morimoto 
571adf6a681SKuninori Morimoto 	node = rsnd_src_of_node(priv);
572adf6a681SKuninori Morimoto 	if (!node)
573adf6a681SKuninori Morimoto 		return 0; /* not used is not error */
57490e8e50fSKuninori Morimoto 
575adf6a681SKuninori Morimoto 	nr = of_get_child_count(node);
576adf6a681SKuninori Morimoto 	if (!nr) {
577adf6a681SKuninori Morimoto 		ret = -EINVAL;
578adf6a681SKuninori Morimoto 		goto rsnd_src_probe_done;
579adf6a681SKuninori Morimoto 	}
580ba9c949fSKuninori Morimoto 
581ba9c949fSKuninori Morimoto 	src	= devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL);
582adf6a681SKuninori Morimoto 	if (!src) {
583adf6a681SKuninori Morimoto 		ret = -ENOMEM;
584adf6a681SKuninori Morimoto 		goto rsnd_src_probe_done;
585adf6a681SKuninori Morimoto 	}
586ba9c949fSKuninori Morimoto 
587ba9c949fSKuninori Morimoto 	priv->src_nr	= nr;
588ba9c949fSKuninori Morimoto 	priv->src	= src;
589ba9c949fSKuninori Morimoto 
590adf6a681SKuninori Morimoto 	i = 0;
591adf6a681SKuninori Morimoto 	for_each_child_of_node(node, np) {
592adf6a681SKuninori Morimoto 		src = rsnd_src_get(priv, i);
593adf6a681SKuninori Morimoto 
5948aefda50SKuninori Morimoto 		snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d",
5958aefda50SKuninori Morimoto 			 SRC_NAME, i);
596ba9c949fSKuninori Morimoto 
597adf6a681SKuninori Morimoto 		src->irq = irq_of_parse_and_map(np, 0);
598adf6a681SKuninori Morimoto 		if (!src->irq) {
599adf6a681SKuninori Morimoto 			ret = -EINVAL;
600adf6a681SKuninori Morimoto 			goto rsnd_src_probe_done;
601adf6a681SKuninori Morimoto 		}
602ba9c949fSKuninori Morimoto 
603adf6a681SKuninori Morimoto 		clk = devm_clk_get(dev, name);
604adf6a681SKuninori Morimoto 		if (IS_ERR(clk)) {
605adf6a681SKuninori Morimoto 			ret = PTR_ERR(clk);
606adf6a681SKuninori Morimoto 			goto rsnd_src_probe_done;
607adf6a681SKuninori Morimoto 		}
608ba9c949fSKuninori Morimoto 
609e8e7b7bdSKuninori Morimoto 		ret = rsnd_mod_init(priv, rsnd_mod_get(src),
61075916f65SKuninori Morimoto 				    &rsnd_src_ops, clk, RSND_MOD_SRC, i);
6112f78dd7fSKuninori Morimoto 		if (ret)
612adf6a681SKuninori Morimoto 			goto rsnd_src_probe_done;
613adf6a681SKuninori Morimoto 
614adf6a681SKuninori Morimoto 		i++;
615ba9c949fSKuninori Morimoto 	}
616ba9c949fSKuninori Morimoto 
617adf6a681SKuninori Morimoto 	ret = 0;
618adf6a681SKuninori Morimoto 
619adf6a681SKuninori Morimoto rsnd_src_probe_done:
620adf6a681SKuninori Morimoto 	of_node_put(node);
621adf6a681SKuninori Morimoto 
622adf6a681SKuninori Morimoto 	return ret;
623ba9c949fSKuninori Morimoto }
6242f78dd7fSKuninori Morimoto 
6252ea6b074SKuninori Morimoto void rsnd_src_remove(struct rsnd_priv *priv)
6262f78dd7fSKuninori Morimoto {
6272f78dd7fSKuninori Morimoto 	struct rsnd_src *src;
6282f78dd7fSKuninori Morimoto 	int i;
6292f78dd7fSKuninori Morimoto 
6302f78dd7fSKuninori Morimoto 	for_each_rsnd_src(src, priv, i) {
631b76e218aSKuninori Morimoto 		rsnd_mod_quit(rsnd_mod_get(src));
6322f78dd7fSKuninori Morimoto 	}
6332f78dd7fSKuninori Morimoto }
634