xref: /openbmc/linux/sound/soc/sh/rcar/core.c (revision 36db6e8484ed455bbb320d89a119378897ae991c)
11e0edd4dSKuninori Morimoto // SPDX-License-Identifier: GPL-2.0
21e0edd4dSKuninori Morimoto //
31e0edd4dSKuninori Morimoto // Renesas R-Car SRU/SCU/SSIU/SSI support
41e0edd4dSKuninori Morimoto //
51e0edd4dSKuninori Morimoto // Copyright (C) 2013 Renesas Solutions Corp.
61e0edd4dSKuninori Morimoto // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
71e0edd4dSKuninori Morimoto //
81e0edd4dSKuninori Morimoto // Based on fsi.c
91e0edd4dSKuninori Morimoto // Kuninori Morimoto <morimoto.kuninori@renesas.com>
101536a968SKuninori Morimoto 
111536a968SKuninori Morimoto /*
121536a968SKuninori Morimoto  * Renesas R-Car sound device structure
131536a968SKuninori Morimoto  *
141536a968SKuninori Morimoto  * Gen1
151536a968SKuninori Morimoto  *
161536a968SKuninori Morimoto  * SRU		: Sound Routing Unit
171536a968SKuninori Morimoto  *  - SRC	: Sampling Rate Converter
181536a968SKuninori Morimoto  *  - CMD
191536a968SKuninori Morimoto  *    - CTU	: Channel Count Conversion Unit
201536a968SKuninori Morimoto  *    - MIX	: Mixer
211536a968SKuninori Morimoto  *    - DVC	: Digital Volume and Mute Function
221536a968SKuninori Morimoto  *  - SSI	: Serial Sound Interface
231536a968SKuninori Morimoto  *
241536a968SKuninori Morimoto  * Gen2
251536a968SKuninori Morimoto  *
261536a968SKuninori Morimoto  * SCU		: Sampling Rate Converter Unit
271536a968SKuninori Morimoto  *  - SRC	: Sampling Rate Converter
281536a968SKuninori Morimoto  *  - CMD
291536a968SKuninori Morimoto  *   - CTU	: Channel Count Conversion Unit
301536a968SKuninori Morimoto  *   - MIX	: Mixer
311536a968SKuninori Morimoto  *   - DVC	: Digital Volume and Mute Function
321536a968SKuninori Morimoto  * SSIU		: Serial Sound Interface Unit
331536a968SKuninori Morimoto  *  - SSI	: Serial Sound Interface
341536a968SKuninori Morimoto  */
351536a968SKuninori Morimoto 
361536a968SKuninori Morimoto /*
371536a968SKuninori Morimoto  *	driver data Image
381536a968SKuninori Morimoto  *
391536a968SKuninori Morimoto  * rsnd_priv
401536a968SKuninori Morimoto  *   |
411536a968SKuninori Morimoto  *   | ** this depends on Gen1/Gen2
421536a968SKuninori Morimoto  *   |
431536a968SKuninori Morimoto  *   +- gen
441536a968SKuninori Morimoto  *   |
451536a968SKuninori Morimoto  *   | ** these depend on data path
461536a968SKuninori Morimoto  *   | ** gen and platform data control it
471536a968SKuninori Morimoto  *   |
481536a968SKuninori Morimoto  *   +- rdai[0]
491536a968SKuninori Morimoto  *   |   |		 sru     ssiu      ssi
501536a968SKuninori Morimoto  *   |   +- playback -> [mod] -> [mod] -> [mod] -> ...
511536a968SKuninori Morimoto  *   |   |
521536a968SKuninori Morimoto  *   |   |		 sru     ssiu      ssi
531536a968SKuninori Morimoto  *   |   +- capture  -> [mod] -> [mod] -> [mod] -> ...
541536a968SKuninori Morimoto  *   |
551536a968SKuninori Morimoto  *   +- rdai[1]
561536a968SKuninori Morimoto  *   |   |		 sru     ssiu      ssi
571536a968SKuninori Morimoto  *   |   +- playback -> [mod] -> [mod] -> [mod] -> ...
581536a968SKuninori Morimoto  *   |   |
591536a968SKuninori Morimoto  *   |   |		 sru     ssiu      ssi
601536a968SKuninori Morimoto  *   |   +- capture  -> [mod] -> [mod] -> [mod] -> ...
611536a968SKuninori Morimoto  *   ...
621536a968SKuninori Morimoto  *   |
631536a968SKuninori Morimoto  *   | ** these control ssi
641536a968SKuninori Morimoto  *   |
651536a968SKuninori Morimoto  *   +- ssi
661536a968SKuninori Morimoto  *   |  |
671536a968SKuninori Morimoto  *   |  +- ssi[0]
681536a968SKuninori Morimoto  *   |  +- ssi[1]
691536a968SKuninori Morimoto  *   |  +- ssi[2]
701536a968SKuninori Morimoto  *   |  ...
711536a968SKuninori Morimoto  *   |
72ba9c949fSKuninori Morimoto  *   | ** these control src
731536a968SKuninori Morimoto  *   |
74ba9c949fSKuninori Morimoto  *   +- src
751536a968SKuninori Morimoto  *      |
76ba9c949fSKuninori Morimoto  *      +- src[0]
77ba9c949fSKuninori Morimoto  *      +- src[1]
78ba9c949fSKuninori Morimoto  *      +- src[2]
791536a968SKuninori Morimoto  *      ...
801536a968SKuninori Morimoto  *
811536a968SKuninori Morimoto  *
821536a968SKuninori Morimoto  * for_each_rsnd_dai(xx, priv, xx)
831536a968SKuninori Morimoto  *  rdai[0] => rdai[1] => rdai[2] => ...
841536a968SKuninori Morimoto  *
851536a968SKuninori Morimoto  * for_each_rsnd_mod(xx, rdai, xx)
861536a968SKuninori Morimoto  *  [mod] => [mod] => [mod] => ...
871536a968SKuninori Morimoto  *
881536a968SKuninori Morimoto  * rsnd_dai_call(xxx, fn )
891536a968SKuninori Morimoto  *  [mod]->fn() -> [mod]->fn() -> [mod]->fn()...
901536a968SKuninori Morimoto  *
911536a968SKuninori Morimoto  */
921f6e920fSKuninori Morimoto 
931536a968SKuninori Morimoto #include <linux/pm_runtime.h>
941536a968SKuninori Morimoto #include "rsnd.h"
951536a968SKuninori Morimoto 
96dc272156SHiroyuki Yokoyama #define RSND_RATES SNDRV_PCM_RATE_8000_192000
97ba5d553bSDragos Tarcatu #define RSND_FMTS (SNDRV_PCM_FMTBIT_S8 |\
98ba5d553bSDragos Tarcatu 		   SNDRV_PCM_FMTBIT_S16_LE |\
99ba5d553bSDragos Tarcatu 		   SNDRV_PCM_FMTBIT_S24_LE)
1001536a968SKuninori Morimoto 
10133187fb4SFabian Frederick static const struct of_device_id rsnd_of_match[] = {
102e797f58eSKuninori Morimoto 	{ .compatible = "renesas,rcar_sound-gen1", .data = (void *)RSND_GEN1 },
103e797f58eSKuninori Morimoto 	{ .compatible = "renesas,rcar_sound-gen2", .data = (void *)RSND_GEN2 },
104d188e140SKuninori Morimoto 	{ .compatible = "renesas,rcar_sound-gen3", .data = (void *)RSND_GEN3 },
105c2bc6527SKuninori Morimoto 	{ .compatible = "renesas,rcar_sound-gen4", .data = (void *)RSND_GEN4 },
106ba164a49SJiada Wang 	/* Special Handling */
107ba164a49SJiada Wang 	{ .compatible = "renesas,rcar_sound-r8a77990", .data = (void *)(RSND_GEN3 | RSND_SOC_E) },
10890e8e50fSKuninori Morimoto 	{},
10990e8e50fSKuninori Morimoto };
11090e8e50fSKuninori Morimoto MODULE_DEVICE_TABLE(of, rsnd_of_match);
11190e8e50fSKuninori Morimoto 
1121536a968SKuninori Morimoto /*
11381ad174dSKuninori Morimoto  *	rsnd_mod functions
11481ad174dSKuninori Morimoto  */
rsnd_mod_make_sure(struct rsnd_mod * mod,enum rsnd_mod_type type)115f1df1229SKuninori Morimoto void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type)
116f1df1229SKuninori Morimoto {
117f1df1229SKuninori Morimoto 	if (mod->type != type) {
118f1df1229SKuninori Morimoto 		struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
119f1df1229SKuninori Morimoto 		struct device *dev = rsnd_priv_to_dev(priv);
120f1df1229SKuninori Morimoto 
121c0ea089dSKuninori Morimoto 		dev_warn(dev, "%s is not your expected module\n",
122c0ea089dSKuninori Morimoto 			 rsnd_mod_name(mod));
123f1df1229SKuninori Morimoto 	}
124f1df1229SKuninori Morimoto }
125f1df1229SKuninori Morimoto 
rsnd_mod_dma_req(struct rsnd_dai_stream * io,struct rsnd_mod * mod)1269b99e9a7SKuninori Morimoto struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io,
1279b99e9a7SKuninori Morimoto 				  struct rsnd_mod *mod)
128d9288d0bSKuninori Morimoto {
12972adc61fSKuninori Morimoto 	if (!mod || !mod->ops || !mod->ops->dma_req)
13072adc61fSKuninori Morimoto 		return NULL;
131d9288d0bSKuninori Morimoto 
1329b99e9a7SKuninori Morimoto 	return mod->ops->dma_req(io, mod);
133d9288d0bSKuninori Morimoto }
134d9288d0bSKuninori Morimoto 
1350246c661SKuninori Morimoto #define MOD_NAME_NUM   5
136c0ea089dSKuninori Morimoto #define MOD_NAME_SIZE 16
rsnd_mod_name(struct rsnd_mod * mod)137c0ea089dSKuninori Morimoto char *rsnd_mod_name(struct rsnd_mod *mod)
138c0ea089dSKuninori Morimoto {
1390246c661SKuninori Morimoto 	static char names[MOD_NAME_NUM][MOD_NAME_SIZE];
1400246c661SKuninori Morimoto 	static int num;
1410246c661SKuninori Morimoto 	char *name = names[num];
1420246c661SKuninori Morimoto 
1430246c661SKuninori Morimoto 	num++;
1440246c661SKuninori Morimoto 	if (num >= MOD_NAME_NUM)
1450246c661SKuninori Morimoto 		num = 0;
146c0ea089dSKuninori Morimoto 
147c0ea089dSKuninori Morimoto 	/*
148c0ea089dSKuninori Morimoto 	 * Let's use same char to avoid pointlessness memory
149c0ea089dSKuninori Morimoto 	 * Thus, rsnd_mod_name() should be used immediately
150c0ea089dSKuninori Morimoto 	 * Don't keep pointer
151c0ea089dSKuninori Morimoto 	 */
152c0ea089dSKuninori Morimoto 	if ((mod)->ops->id_sub) {
153c0ea089dSKuninori Morimoto 		snprintf(name, MOD_NAME_SIZE, "%s[%d%d]",
154c0ea089dSKuninori Morimoto 			 mod->ops->name,
155c0ea089dSKuninori Morimoto 			 rsnd_mod_id(mod),
156c0ea089dSKuninori Morimoto 			 rsnd_mod_id_sub(mod));
157c0ea089dSKuninori Morimoto 	} else {
158c0ea089dSKuninori Morimoto 		snprintf(name, MOD_NAME_SIZE, "%s[%d]",
159c0ea089dSKuninori Morimoto 			 mod->ops->name,
160c0ea089dSKuninori Morimoto 			 rsnd_mod_id(mod));
161c0ea089dSKuninori Morimoto 	}
162c0ea089dSKuninori Morimoto 
163c0ea089dSKuninori Morimoto 	return name;
164c0ea089dSKuninori Morimoto }
165c0ea089dSKuninori Morimoto 
rsnd_mod_get_status(struct rsnd_mod * mod,struct rsnd_dai_stream * io,enum rsnd_mod_type type)1667e7fe06dSKuninori Morimoto u32 *rsnd_mod_get_status(struct rsnd_mod *mod,
1677e7fe06dSKuninori Morimoto 			 struct rsnd_dai_stream *io,
1685ba17b42SKuninori Morimoto 			 enum rsnd_mod_type type)
1695ba17b42SKuninori Morimoto {
1705ba17b42SKuninori Morimoto 	return &mod->status;
1715ba17b42SKuninori Morimoto }
1725ba17b42SKuninori Morimoto 
rsnd_mod_id_raw(struct rsnd_mod * mod)173c16015f3SKuninori Morimoto int rsnd_mod_id_raw(struct rsnd_mod *mod)
174c16015f3SKuninori Morimoto {
175c16015f3SKuninori Morimoto 	return mod->id;
176c16015f3SKuninori Morimoto }
177c16015f3SKuninori Morimoto 
rsnd_mod_id(struct rsnd_mod * mod)178c16015f3SKuninori Morimoto int rsnd_mod_id(struct rsnd_mod *mod)
179c16015f3SKuninori Morimoto {
180c16015f3SKuninori Morimoto 	if ((mod)->ops->id)
181c16015f3SKuninori Morimoto 		return (mod)->ops->id(mod);
182c16015f3SKuninori Morimoto 
183c16015f3SKuninori Morimoto 	return rsnd_mod_id_raw(mod);
184c16015f3SKuninori Morimoto }
185c16015f3SKuninori Morimoto 
rsnd_mod_id_sub(struct rsnd_mod * mod)186c16015f3SKuninori Morimoto int rsnd_mod_id_sub(struct rsnd_mod *mod)
187c16015f3SKuninori Morimoto {
188c16015f3SKuninori Morimoto 	if ((mod)->ops->id_sub)
189c16015f3SKuninori Morimoto 		return (mod)->ops->id_sub(mod);
190c16015f3SKuninori Morimoto 
191c16015f3SKuninori Morimoto 	return 0;
192c16015f3SKuninori Morimoto }
193c16015f3SKuninori Morimoto 
rsnd_mod_init(struct rsnd_priv * priv,struct rsnd_mod * mod,struct rsnd_mod_ops * ops,struct clk * clk,enum rsnd_mod_type type,int id)1942099bc8eSKuninori Morimoto int rsnd_mod_init(struct rsnd_priv *priv,
1952099bc8eSKuninori Morimoto 		  struct rsnd_mod *mod,
196cdaa3cdfSKuninori Morimoto 		  struct rsnd_mod_ops *ops,
19785642952SKuninori Morimoto 		  struct clk *clk,
198a126021dSKuninori Morimoto 		  enum rsnd_mod_type type,
199cdaa3cdfSKuninori Morimoto 		  int id)
200cdaa3cdfSKuninori Morimoto {
2012f78dd7fSKuninori Morimoto 	int ret = clk_prepare(clk);
2022f78dd7fSKuninori Morimoto 
2032f78dd7fSKuninori Morimoto 	if (ret)
2042f78dd7fSKuninori Morimoto 		return ret;
2052f78dd7fSKuninori Morimoto 
206cdaa3cdfSKuninori Morimoto 	mod->id		= id;
207cdaa3cdfSKuninori Morimoto 	mod->ops	= ops;
208a126021dSKuninori Morimoto 	mod->type	= type;
20985642952SKuninori Morimoto 	mod->clk	= clk;
2102099bc8eSKuninori Morimoto 	mod->priv	= priv;
2112f78dd7fSKuninori Morimoto 
212652fc90fSPierre-Louis Bossart 	return 0;
2132f78dd7fSKuninori Morimoto }
2142f78dd7fSKuninori Morimoto 
rsnd_mod_quit(struct rsnd_mod * mod)2152f78dd7fSKuninori Morimoto void rsnd_mod_quit(struct rsnd_mod *mod)
2162f78dd7fSKuninori Morimoto {
2172f78dd7fSKuninori Morimoto 	clk_unprepare(mod->clk);
218ea96380bSKuninori Morimoto 	mod->clk = NULL;
219cdaa3cdfSKuninori Morimoto }
220cdaa3cdfSKuninori Morimoto 
rsnd_mod_interrupt(struct rsnd_mod * mod,void (* callback)(struct rsnd_mod * mod,struct rsnd_dai_stream * io))221f501b7a4SKuninori Morimoto void rsnd_mod_interrupt(struct rsnd_mod *mod,
222f501b7a4SKuninori Morimoto 			void (*callback)(struct rsnd_mod *mod,
223f501b7a4SKuninori Morimoto 					 struct rsnd_dai_stream *io))
224f501b7a4SKuninori Morimoto {
225f501b7a4SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
226f501b7a4SKuninori Morimoto 	struct rsnd_dai *rdai;
2272daf71adSKuninori Morimoto 	int i;
228f501b7a4SKuninori Morimoto 
2292daf71adSKuninori Morimoto 	for_each_rsnd_dai(rdai, priv, i) {
230e539943cSKuninori Morimoto 		struct rsnd_dai_stream *io = &rdai->playback;
231e539943cSKuninori Morimoto 
2322daf71adSKuninori Morimoto 		if (mod == io->mod[mod->type])
233f501b7a4SKuninori Morimoto 			callback(mod, io);
234f501b7a4SKuninori Morimoto 
235f501b7a4SKuninori Morimoto 		io = &rdai->capture;
2362daf71adSKuninori Morimoto 		if (mod == io->mod[mod->type])
237f501b7a4SKuninori Morimoto 			callback(mod, io);
238f501b7a4SKuninori Morimoto 	}
239f501b7a4SKuninori Morimoto }
240f501b7a4SKuninori Morimoto 
rsnd_io_is_working(struct rsnd_dai_stream * io)241d5bbe7deSKuninori Morimoto int rsnd_io_is_working(struct rsnd_dai_stream *io)
24202299d98SKuninori Morimoto {
24302299d98SKuninori Morimoto 	/* see rsnd_dai_stream_init/quit() */
2448fce974bSKuninori Morimoto 	if (io->substream)
2458fce974bSKuninori Morimoto 		return snd_pcm_running(io->substream);
2468fce974bSKuninori Morimoto 
2478fce974bSKuninori Morimoto 	return 0;
24802299d98SKuninori Morimoto }
24902299d98SKuninori Morimoto 
rsnd_runtime_channel_original_with_params(struct rsnd_dai_stream * io,struct snd_pcm_hw_params * params)250b2fb31bbSKuninori Morimoto int rsnd_runtime_channel_original_with_params(struct rsnd_dai_stream *io,
251b2fb31bbSKuninori Morimoto 					      struct snd_pcm_hw_params *params)
2528ec85e7fSKuninori Morimoto {
2535858a7d1SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
254b4c83b17SKuninori Morimoto 
255b2fb31bbSKuninori Morimoto 	/*
256b2fb31bbSKuninori Morimoto 	 * params will be added when refine
257b2fb31bbSKuninori Morimoto 	 * see
258b2fb31bbSKuninori Morimoto 	 *	__rsnd_soc_hw_rule_rate()
259b2fb31bbSKuninori Morimoto 	 *	__rsnd_soc_hw_rule_channels()
260b2fb31bbSKuninori Morimoto 	 */
261b2fb31bbSKuninori Morimoto 	if (params)
262b2fb31bbSKuninori Morimoto 		return params_channels(params);
2636da8f00eSKuninori Morimoto 	else if (runtime)
264eed76bb8SKuninori Morimoto 		return runtime->channels;
2656da8f00eSKuninori Morimoto 	return 0;
266eed76bb8SKuninori Morimoto }
267eed76bb8SKuninori Morimoto 
rsnd_runtime_channel_after_ctu_with_params(struct rsnd_dai_stream * io,struct snd_pcm_hw_params * params)268b2fb31bbSKuninori Morimoto int rsnd_runtime_channel_after_ctu_with_params(struct rsnd_dai_stream *io,
269b2fb31bbSKuninori Morimoto 					       struct snd_pcm_hw_params *params)
270eed76bb8SKuninori Morimoto {
271b2fb31bbSKuninori Morimoto 	int chan = rsnd_runtime_channel_original_with_params(io, params);
272eed76bb8SKuninori Morimoto 	struct rsnd_mod *ctu_mod = rsnd_io_to_mod_ctu(io);
273eed76bb8SKuninori Morimoto 
274eed76bb8SKuninori Morimoto 	if (ctu_mod) {
275c2aaaa57SKuninori Morimoto 		u32 converted_chan = rsnd_io_converted_chan(io);
276eed76bb8SKuninori Morimoto 
277f69f4522SKuninori Morimoto 		/*
278f69f4522SKuninori Morimoto 		 * !! Note !!
279f69f4522SKuninori Morimoto 		 *
280f69f4522SKuninori Morimoto 		 * converted_chan will be used for CTU,
281f69f4522SKuninori Morimoto 		 * or TDM Split mode.
282f69f4522SKuninori Morimoto 		 * User shouldn't use CTU with TDM Split mode.
283f69f4522SKuninori Morimoto 		 */
284f69f4522SKuninori Morimoto 		if (rsnd_runtime_is_tdm_split(io)) {
285f69f4522SKuninori Morimoto 			struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io));
286f69f4522SKuninori Morimoto 
287f69f4522SKuninori Morimoto 			dev_err(dev, "CTU and TDM Split should be used\n");
288f69f4522SKuninori Morimoto 		}
289f69f4522SKuninori Morimoto 
290eed76bb8SKuninori Morimoto 		if (converted_chan)
291eed76bb8SKuninori Morimoto 			return converted_chan;
292eed76bb8SKuninori Morimoto 	}
293eed76bb8SKuninori Morimoto 
294eed76bb8SKuninori Morimoto 	return chan;
295eed76bb8SKuninori Morimoto }
296eed76bb8SKuninori Morimoto 
rsnd_channel_normalization(int chan)29766287defSKuninori Morimoto int rsnd_channel_normalization(int chan)
29866287defSKuninori Morimoto {
2995db8617bSKuninori Morimoto 	if (WARN_ON((chan > 8) || (chan < 0)))
30066287defSKuninori Morimoto 		return 0;
30166287defSKuninori Morimoto 
30266287defSKuninori Morimoto 	/* TDM Extend Mode needs 8ch */
30366287defSKuninori Morimoto 	if (chan == 6)
30466287defSKuninori Morimoto 		chan = 8;
30566287defSKuninori Morimoto 
30666287defSKuninori Morimoto 	return chan;
30766287defSKuninori Morimoto }
30866287defSKuninori Morimoto 
rsnd_runtime_channel_for_ssi_with_params(struct rsnd_dai_stream * io,struct snd_pcm_hw_params * params)309b2fb31bbSKuninori Morimoto int rsnd_runtime_channel_for_ssi_with_params(struct rsnd_dai_stream *io,
310b2fb31bbSKuninori Morimoto 					     struct snd_pcm_hw_params *params)
311eed76bb8SKuninori Morimoto {
3121ff9593dSKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
313eed76bb8SKuninori Morimoto 	int chan = rsnd_io_is_play(io) ?
314b2fb31bbSKuninori Morimoto 		rsnd_runtime_channel_after_ctu_with_params(io, params) :
315b2fb31bbSKuninori Morimoto 		rsnd_runtime_channel_original_with_params(io, params);
316eed76bb8SKuninori Morimoto 
317eed76bb8SKuninori Morimoto 	/* Use Multi SSI */
318a6072802SKuninori Morimoto 	if (rsnd_runtime_is_multi_ssi(io))
3191ff9593dSKuninori Morimoto 		chan /= rsnd_rdai_ssi_lane_get(rdai);
3208ec85e7fSKuninori Morimoto 
32166287defSKuninori Morimoto 	return rsnd_channel_normalization(chan);
3228ec85e7fSKuninori Morimoto }
3238ec85e7fSKuninori Morimoto 
rsnd_runtime_is_multi_ssi(struct rsnd_dai_stream * io)324a6072802SKuninori Morimoto int rsnd_runtime_is_multi_ssi(struct rsnd_dai_stream *io)
325eed76bb8SKuninori Morimoto {
3261ff9593dSKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
3271ff9593dSKuninori Morimoto 	int lane = rsnd_rdai_ssi_lane_get(rdai);
328eed76bb8SKuninori Morimoto 	int chan = rsnd_io_is_play(io) ?
329eed76bb8SKuninori Morimoto 		rsnd_runtime_channel_after_ctu(io) :
330eed76bb8SKuninori Morimoto 		rsnd_runtime_channel_original(io);
331eed76bb8SKuninori Morimoto 
3321ff9593dSKuninori Morimoto 	return (chan > 2) && (lane > 1);
333eed76bb8SKuninori Morimoto }
334eed76bb8SKuninori Morimoto 
rsnd_runtime_is_tdm(struct rsnd_dai_stream * io)335a6072802SKuninori Morimoto int rsnd_runtime_is_tdm(struct rsnd_dai_stream *io)
336eed76bb8SKuninori Morimoto {
337eed76bb8SKuninori Morimoto 	return rsnd_runtime_channel_for_ssi(io) >= 6;
338eed76bb8SKuninori Morimoto }
339eed76bb8SKuninori Morimoto 
rsnd_runtime_is_tdm_split(struct rsnd_dai_stream * io)340f69f4522SKuninori Morimoto int rsnd_runtime_is_tdm_split(struct rsnd_dai_stream *io)
341f69f4522SKuninori Morimoto {
342f69f4522SKuninori Morimoto 	return !!rsnd_flags_has(io, RSND_STREAM_TDM_SPLIT);
343f69f4522SKuninori Morimoto }
344f69f4522SKuninori Morimoto 
345cdaa3cdfSKuninori Morimoto /*
3463023b384SKuninori Morimoto  *	ADINR function
347d7bdbc5dSKuninori Morimoto  */
rsnd_get_adinr_bit(struct rsnd_mod * mod,struct rsnd_dai_stream * io)3483023b384SKuninori Morimoto u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
349d7bdbc5dSKuninori Morimoto {
350d7bdbc5dSKuninori Morimoto 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
351d7bdbc5dSKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
352d7bdbc5dSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
353d7bdbc5dSKuninori Morimoto 
35441acc8ecSKuninori Morimoto 	switch (snd_pcm_format_width(runtime->format)) {
355ba5d553bSDragos Tarcatu 	case 8:
356ba5d553bSDragos Tarcatu 		return 16 << 16;
357d7bdbc5dSKuninori Morimoto 	case 16:
3585e7b9eddSKuninori Morimoto 		return 8 << 16;
35941acc8ecSKuninori Morimoto 	case 24:
3605e7b9eddSKuninori Morimoto 		return 0 << 16;
361d7bdbc5dSKuninori Morimoto 	}
362d7bdbc5dSKuninori Morimoto 
3635e7b9eddSKuninori Morimoto 	dev_warn(dev, "not supported sample bits\n");
3645e7b9eddSKuninori Morimoto 
3655e7b9eddSKuninori Morimoto 	return 0;
366d7bdbc5dSKuninori Morimoto }
367d7bdbc5dSKuninori Morimoto 
3684689032bSKuninori Morimoto /*
3694689032bSKuninori Morimoto  *	DALIGN function
3704689032bSKuninori Morimoto  */
rsnd_get_dalign(struct rsnd_mod * mod,struct rsnd_dai_stream * io)3714689032bSKuninori Morimoto u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
3724689032bSKuninori Morimoto {
37349df1e39SGeert Uytterhoeven 	static const u32 dalign_values[8] = {
37449df1e39SGeert Uytterhoeven 		0x76543210, 0x00000032, 0x00007654, 0x00000076,
37549df1e39SGeert Uytterhoeven 		0xfedcba98, 0x000000ba, 0x0000fedc, 0x000000fe,
376ef8e1479SNilkanth Ahirrao 	};
37749df1e39SGeert Uytterhoeven 	int id = 0;
3783ce2959dSKuninori Morimoto 	struct rsnd_mod *ssiu = rsnd_io_to_mod_ssiu(io);
379a504b1eeSKuninori Morimoto 	struct rsnd_mod *target;
3804689032bSKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
38149df1e39SGeert Uytterhoeven 	u32 dalign;
3824689032bSKuninori Morimoto 
3838cce431aSKuninori Morimoto 	/*
384a914e446SKuninori Morimoto 	 * *Hardware* L/R and *Software* L/R are inverted for 16bit data.
385a914e446SKuninori Morimoto 	 *	    31..16 15...0
386a914e446SKuninori Morimoto 	 *	HW: [L ch] [R ch]
387a914e446SKuninori Morimoto 	 *	SW: [R ch] [L ch]
3888cce431aSKuninori Morimoto 	 * We need to care about inversion timing to control
3898cce431aSKuninori Morimoto 	 * Playback/Capture correctly.
3908cce431aSKuninori Morimoto 	 * The point is [DVC] needs *Hardware* L/R, [MEM] needs *Software* L/R
3918cce431aSKuninori Morimoto 	 *
3928cce431aSKuninori Morimoto 	 * sL/R : software L/R
3938cce431aSKuninori Morimoto 	 * hL/R : hardware L/R
3948cce431aSKuninori Morimoto 	 * (*)  : conversion timing
3958cce431aSKuninori Morimoto 	 *
3968cce431aSKuninori Morimoto 	 * Playback
3978cce431aSKuninori Morimoto 	 *	     sL/R (*) hL/R     hL/R     hL/R      hL/R     hL/R
3988cce431aSKuninori Morimoto 	 *	[MEM] -> [SRC] -> [DVC] -> [CMD] -> [SSIU] -> [SSI] -> codec
3998cce431aSKuninori Morimoto 	 *
4008cce431aSKuninori Morimoto 	 * Capture
4018cce431aSKuninori Morimoto 	 *	     hL/R     hL/R      hL/R     hL/R     hL/R (*) sL/R
4028cce431aSKuninori Morimoto 	 *	codec -> [SSI] -> [SSIU] -> [SRC] -> [DVC] -> [CMD] -> [MEM]
4038cce431aSKuninori Morimoto 	 */
404a504b1eeSKuninori Morimoto 	if (rsnd_io_is_play(io)) {
405a504b1eeSKuninori Morimoto 		struct rsnd_mod *src = rsnd_io_to_mod_src(io);
406a504b1eeSKuninori Morimoto 
4073ce2959dSKuninori Morimoto 		target = src ? src : ssiu;
408a504b1eeSKuninori Morimoto 	} else {
409a504b1eeSKuninori Morimoto 		struct rsnd_mod *cmd = rsnd_io_to_mod_cmd(io);
410a504b1eeSKuninori Morimoto 
4113ce2959dSKuninori Morimoto 		target = cmd ? cmd : ssiu;
412a504b1eeSKuninori Morimoto 	}
413a504b1eeSKuninori Morimoto 
414ef8e1479SNilkanth Ahirrao 	if (mod == ssiu)
415ef8e1479SNilkanth Ahirrao 		id = rsnd_mod_id_sub(mod);
416ef8e1479SNilkanth Ahirrao 
41749df1e39SGeert Uytterhoeven 	dalign = dalign_values[id];
418ef8e1479SNilkanth Ahirrao 
41949df1e39SGeert Uytterhoeven 	if (mod == target && snd_pcm_format_width(runtime->format) == 16) {
42049df1e39SGeert Uytterhoeven 		/* Target mod needs inverted DALIGN when 16bit */
42149df1e39SGeert Uytterhoeven 		dalign = (dalign & 0xf0f0f0f0) >> 4 |
42249df1e39SGeert Uytterhoeven 			 (dalign & 0x0f0f0f0f) << 4;
42349df1e39SGeert Uytterhoeven 	}
42449df1e39SGeert Uytterhoeven 
42549df1e39SGeert Uytterhoeven 	return dalign;
4264689032bSKuninori Morimoto }
4274689032bSKuninori Morimoto 
rsnd_get_busif_shift(struct rsnd_dai_stream * io,struct rsnd_mod * mod)42890431eb4SKuninori Morimoto u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod)
42990431eb4SKuninori Morimoto {
43028889de6SKuninori Morimoto 	static const enum rsnd_mod_type playback_mods[] = {
43190431eb4SKuninori Morimoto 		RSND_MOD_SRC,
43290431eb4SKuninori Morimoto 		RSND_MOD_CMD,
43390431eb4SKuninori Morimoto 		RSND_MOD_SSIU,
43490431eb4SKuninori Morimoto 	};
43528889de6SKuninori Morimoto 	static const enum rsnd_mod_type capture_mods[] = {
43690431eb4SKuninori Morimoto 		RSND_MOD_CMD,
43790431eb4SKuninori Morimoto 		RSND_MOD_SRC,
43890431eb4SKuninori Morimoto 		RSND_MOD_SSIU,
43990431eb4SKuninori Morimoto 	};
44090431eb4SKuninori Morimoto 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
44190431eb4SKuninori Morimoto 	struct rsnd_mod *tmod = NULL;
44228889de6SKuninori Morimoto 	const enum rsnd_mod_type *mods =
44390431eb4SKuninori Morimoto 		rsnd_io_is_play(io) ?
44490431eb4SKuninori Morimoto 		playback_mods : capture_mods;
44590431eb4SKuninori Morimoto 	int i;
44690431eb4SKuninori Morimoto 
44790431eb4SKuninori Morimoto 	/*
44890431eb4SKuninori Morimoto 	 * This is needed for 24bit data
44990431eb4SKuninori Morimoto 	 * We need to shift 8bit
45090431eb4SKuninori Morimoto 	 *
45190431eb4SKuninori Morimoto 	 * Linux 24bit data is located as 0x00******
45290431eb4SKuninori Morimoto 	 * HW    24bit data is located as 0x******00
45390431eb4SKuninori Morimoto 	 *
45490431eb4SKuninori Morimoto 	 */
455ba5d553bSDragos Tarcatu 	if (snd_pcm_format_width(runtime->format) != 24)
45690431eb4SKuninori Morimoto 		return 0;
45790431eb4SKuninori Morimoto 
45890431eb4SKuninori Morimoto 	for (i = 0; i < ARRAY_SIZE(playback_mods); i++) {
45990431eb4SKuninori Morimoto 		tmod = rsnd_io_to_mod(io, mods[i]);
46090431eb4SKuninori Morimoto 		if (tmod)
46190431eb4SKuninori Morimoto 			break;
46290431eb4SKuninori Morimoto 	}
46390431eb4SKuninori Morimoto 
46490431eb4SKuninori Morimoto 	if (tmod != mod)
46590431eb4SKuninori Morimoto 		return 0;
46690431eb4SKuninori Morimoto 
46790431eb4SKuninori Morimoto 	if (rsnd_io_is_play(io))
46890431eb4SKuninori Morimoto 		return  (0 << 20) | /* shift to Left */
46990431eb4SKuninori Morimoto 			(8 << 16);  /* 8bit */
47090431eb4SKuninori Morimoto 	else
47190431eb4SKuninori Morimoto 		return  (1 << 20) | /* shift to Right */
47290431eb4SKuninori Morimoto 			(8 << 16);  /* 8bit */
47390431eb4SKuninori Morimoto }
47490431eb4SKuninori Morimoto 
475d7bdbc5dSKuninori Morimoto /*
4761536a968SKuninori Morimoto  *	rsnd_dai functions
4771536a968SKuninori Morimoto  */
rsnd_mod_next(int * iterator,struct rsnd_dai_stream * io,enum rsnd_mod_type * array,int array_size)478b3ca3fbeSKuninori Morimoto struct rsnd_mod *rsnd_mod_next(int *iterator,
479b3ca3fbeSKuninori Morimoto 			       struct rsnd_dai_stream *io,
480b3ca3fbeSKuninori Morimoto 			       enum rsnd_mod_type *array,
481b3ca3fbeSKuninori Morimoto 			       int array_size)
482b3ca3fbeSKuninori Morimoto {
483b3ca3fbeSKuninori Morimoto 	int max = array ? array_size : RSND_MOD_MAX;
484b3ca3fbeSKuninori Morimoto 
485b3ca3fbeSKuninori Morimoto 	for (; *iterator < max; (*iterator)++) {
486e539943cSKuninori Morimoto 		enum rsnd_mod_type type = (array) ? array[*iterator] : *iterator;
487e539943cSKuninori Morimoto 		struct rsnd_mod *mod = rsnd_io_to_mod(io, type);
488e539943cSKuninori Morimoto 
489b12f1e3aSKuninori Morimoto 		if (mod)
490b3ca3fbeSKuninori Morimoto 			return mod;
491b3ca3fbeSKuninori Morimoto 	}
492b3ca3fbeSKuninori Morimoto 
493b3ca3fbeSKuninori Morimoto 	return NULL;
494b3ca3fbeSKuninori Morimoto }
495b3ca3fbeSKuninori Morimoto 
49638587f4cSKuninori Morimoto static enum rsnd_mod_type rsnd_mod_sequence[][RSND_MOD_MAX] = {
49738587f4cSKuninori Morimoto 	{
49838587f4cSKuninori Morimoto 		/* CAPTURE */
49938587f4cSKuninori Morimoto 		RSND_MOD_AUDMAPP,
50038587f4cSKuninori Morimoto 		RSND_MOD_AUDMA,
50138587f4cSKuninori Morimoto 		RSND_MOD_DVC,
50238587f4cSKuninori Morimoto 		RSND_MOD_MIX,
50338587f4cSKuninori Morimoto 		RSND_MOD_CTU,
50438587f4cSKuninori Morimoto 		RSND_MOD_CMD,
50538587f4cSKuninori Morimoto 		RSND_MOD_SRC,
50638587f4cSKuninori Morimoto 		RSND_MOD_SSIU,
50738587f4cSKuninori Morimoto 		RSND_MOD_SSIM3,
50838587f4cSKuninori Morimoto 		RSND_MOD_SSIM2,
50938587f4cSKuninori Morimoto 		RSND_MOD_SSIM1,
51038587f4cSKuninori Morimoto 		RSND_MOD_SSIP,
51138587f4cSKuninori Morimoto 		RSND_MOD_SSI,
51238587f4cSKuninori Morimoto 	}, {
51338587f4cSKuninori Morimoto 		/* PLAYBACK */
51438587f4cSKuninori Morimoto 		RSND_MOD_AUDMAPP,
51538587f4cSKuninori Morimoto 		RSND_MOD_AUDMA,
51638587f4cSKuninori Morimoto 		RSND_MOD_SSIM3,
51738587f4cSKuninori Morimoto 		RSND_MOD_SSIM2,
51838587f4cSKuninori Morimoto 		RSND_MOD_SSIM1,
51938587f4cSKuninori Morimoto 		RSND_MOD_SSIP,
52038587f4cSKuninori Morimoto 		RSND_MOD_SSI,
52138587f4cSKuninori Morimoto 		RSND_MOD_SSIU,
52238587f4cSKuninori Morimoto 		RSND_MOD_DVC,
52338587f4cSKuninori Morimoto 		RSND_MOD_MIX,
52438587f4cSKuninori Morimoto 		RSND_MOD_CTU,
52538587f4cSKuninori Morimoto 		RSND_MOD_CMD,
52638587f4cSKuninori Morimoto 		RSND_MOD_SRC,
52738587f4cSKuninori Morimoto 	},
52838587f4cSKuninori Morimoto };
52938587f4cSKuninori Morimoto 
rsnd_status_update(struct rsnd_dai_stream * io,struct rsnd_mod * mod,enum rsnd_mod_type type,int shift,int add,int timing)530b43b8ae8SKuninori Morimoto static int rsnd_status_update(struct rsnd_dai_stream *io,
531b43b8ae8SKuninori Morimoto 			      struct rsnd_mod *mod, enum rsnd_mod_type type,
5325f222a29SKuninori Morimoto 			      int shift, int add, int timing)
5335f222a29SKuninori Morimoto {
534b43b8ae8SKuninori Morimoto 	u32 *status	= mod->ops->get_status(mod, io, type);
5355f222a29SKuninori Morimoto 	u32 mask	= 0xF << shift;
5365f222a29SKuninori Morimoto 	u8 val		= (*status >> shift) & 0xF;
5375f222a29SKuninori Morimoto 	u8 next_val	= (val + add) & 0xF;
5385f222a29SKuninori Morimoto 	int func_call	= (val == timing);
5395f222a29SKuninori Morimoto 
540b43b8ae8SKuninori Morimoto 	/* no status update */
541b43b8ae8SKuninori Morimoto 	if (add == 0 || shift == 28)
542b43b8ae8SKuninori Morimoto 		return 1;
543b43b8ae8SKuninori Morimoto 
5445f222a29SKuninori Morimoto 	if (next_val == 0xF) /* underflow case */
5459ff07d19SKuninori Morimoto 		func_call = -1;
5465f222a29SKuninori Morimoto 	else
5475f222a29SKuninori Morimoto 		*status = (*status & ~mask) + (next_val << shift);
5485f222a29SKuninori Morimoto 
5495f222a29SKuninori Morimoto 	return func_call;
5505f222a29SKuninori Morimoto }
5515f222a29SKuninori Morimoto 
552690602fcSKuninori Morimoto #define rsnd_dai_call(fn, io, param...)					\
553cdaa3cdfSKuninori Morimoto ({									\
554f30b4ca4SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io));	\
555a126021dSKuninori Morimoto 	struct rsnd_mod *mod;						\
5565f222a29SKuninori Morimoto 	int is_play = rsnd_io_is_play(io);				\
557a126021dSKuninori Morimoto 	int ret = 0, i;							\
5585f222a29SKuninori Morimoto 	enum rsnd_mod_type *types = rsnd_mod_sequence[is_play];		\
5595f222a29SKuninori Morimoto 	for_each_rsnd_mod_arrays(i, mod, io, types, RSND_MOD_MAX) {	\
5605f222a29SKuninori Morimoto 		int tmp = 0;						\
561b43b8ae8SKuninori Morimoto 		int func_call = rsnd_status_update(io, mod, types[i],	\
5625f222a29SKuninori Morimoto 						__rsnd_mod_shift_##fn,	\
5635f222a29SKuninori Morimoto 						__rsnd_mod_add_##fn,	\
5645f222a29SKuninori Morimoto 						__rsnd_mod_call_##fn);	\
5659ff07d19SKuninori Morimoto 		if (func_call > 0 && (mod)->ops->fn)			\
5665f222a29SKuninori Morimoto 			tmp = (mod)->ops->fn(mod, io, param);		\
5679ff07d19SKuninori Morimoto 		if (unlikely(func_call < 0) ||				\
5689ff07d19SKuninori Morimoto 		    unlikely(tmp && (tmp != -EPROBE_DEFER)))		\
5699ff07d19SKuninori Morimoto 			dev_err(dev, "%s : %s error (%d, %d)\n",	\
5709ff07d19SKuninori Morimoto 				rsnd_mod_name(mod), #fn, tmp, func_call);\
5715f222a29SKuninori Morimoto 		ret |= tmp;						\
572cdaa3cdfSKuninori Morimoto 	}								\
573cdaa3cdfSKuninori Morimoto 	ret;								\
574cdaa3cdfSKuninori Morimoto })
575cdaa3cdfSKuninori Morimoto 
rsnd_dai_connect(struct rsnd_mod * mod,struct rsnd_dai_stream * io,enum rsnd_mod_type type)57627924f32SKuninori Morimoto int rsnd_dai_connect(struct rsnd_mod *mod,
57727924f32SKuninori Morimoto 		     struct rsnd_dai_stream *io,
57827924f32SKuninori Morimoto 		     enum rsnd_mod_type type)
579cdaa3cdfSKuninori Morimoto {
58048725e9cSKuninori Morimoto 	struct rsnd_priv *priv;
58148725e9cSKuninori Morimoto 	struct device *dev;
58284e95355SKuninori Morimoto 
5836020779bSKuninori Morimoto 	if (!mod)
5846020779bSKuninori Morimoto 		return -EIO;
5856020779bSKuninori Morimoto 
586bfa3119cSKuninori Morimoto 	if (io->mod[type] == mod)
587bfa3119cSKuninori Morimoto 		return 0;
588bfa3119cSKuninori Morimoto 
58952dc6852SKuninori Morimoto 	if (io->mod[type])
59052dc6852SKuninori Morimoto 		return -EINVAL;
59152dc6852SKuninori Morimoto 
59248725e9cSKuninori Morimoto 	priv = rsnd_mod_to_priv(mod);
59348725e9cSKuninori Morimoto 	dev = rsnd_priv_to_dev(priv);
59448725e9cSKuninori Morimoto 
59527924f32SKuninori Morimoto 	io->mod[type] = mod;
596cdaa3cdfSKuninori Morimoto 
597c0ea089dSKuninori Morimoto 	dev_dbg(dev, "%s is connected to io (%s)\n",
598c0ea089dSKuninori Morimoto 		rsnd_mod_name(mod),
59984e95355SKuninori Morimoto 		rsnd_io_is_play(io) ? "Playback" : "Capture");
60084e95355SKuninori Morimoto 
601cdaa3cdfSKuninori Morimoto 	return 0;
602cdaa3cdfSKuninori Morimoto }
603cdaa3cdfSKuninori Morimoto 
rsnd_dai_disconnect(struct rsnd_mod * mod,struct rsnd_dai_stream * io,enum rsnd_mod_type type)604d3a76823SKuninori Morimoto static void rsnd_dai_disconnect(struct rsnd_mod *mod,
60527924f32SKuninori Morimoto 				struct rsnd_dai_stream *io,
60627924f32SKuninori Morimoto 				enum rsnd_mod_type type)
607d3a76823SKuninori Morimoto {
60827924f32SKuninori Morimoto 	io->mod[type] = NULL;
609d3a76823SKuninori Morimoto }
610d3a76823SKuninori Morimoto 
rsnd_rdai_channels_ctrl(struct rsnd_dai * rdai,int max_channels)6111ff9593dSKuninori Morimoto int rsnd_rdai_channels_ctrl(struct rsnd_dai *rdai,
6121ff9593dSKuninori Morimoto 			    int max_channels)
6131ff9593dSKuninori Morimoto {
6141ff9593dSKuninori Morimoto 	if (max_channels > 0)
6151ff9593dSKuninori Morimoto 		rdai->max_channels = max_channels;
6161ff9593dSKuninori Morimoto 
6171ff9593dSKuninori Morimoto 	return rdai->max_channels;
6181ff9593dSKuninori Morimoto }
6191ff9593dSKuninori Morimoto 
rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai * rdai,int ssi_lane)6201ff9593dSKuninori Morimoto int rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai *rdai,
6211ff9593dSKuninori Morimoto 			    int ssi_lane)
6221ff9593dSKuninori Morimoto {
6231ff9593dSKuninori Morimoto 	if (ssi_lane > 0)
6241ff9593dSKuninori Morimoto 		rdai->ssi_lane = ssi_lane;
6251ff9593dSKuninori Morimoto 
6261ff9593dSKuninori Morimoto 	return rdai->ssi_lane;
6271ff9593dSKuninori Morimoto }
6281ff9593dSKuninori Morimoto 
rsnd_rdai_width_ctrl(struct rsnd_dai * rdai,int width)629fb2815f4SDragos Tarcatu int rsnd_rdai_width_ctrl(struct rsnd_dai *rdai, int width)
630fb2815f4SDragos Tarcatu {
631fb2815f4SDragos Tarcatu 	if (width > 0)
632fb2815f4SDragos Tarcatu 		rdai->chan_width = width;
633fb2815f4SDragos Tarcatu 
634fb2815f4SDragos Tarcatu 	return rdai->chan_width;
635fb2815f4SDragos Tarcatu }
636fb2815f4SDragos Tarcatu 
rsnd_rdai_get(struct rsnd_priv * priv,int id)637710d0889SKuninori Morimoto struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id)
6381536a968SKuninori Morimoto {
639ecba9e72SKuninori Morimoto 	if ((id < 0) || (id >= rsnd_rdai_nr(priv)))
6402192f81cSKuninori Morimoto 		return NULL;
6412192f81cSKuninori Morimoto 
6421536a968SKuninori Morimoto 	return priv->rdai + id;
6431536a968SKuninori Morimoto }
6441536a968SKuninori Morimoto 
645a0d847c3SKuninori Morimoto static struct snd_soc_dai_driver
rsnd_daidrv_get(struct rsnd_priv * priv,int id)646a0d847c3SKuninori Morimoto *rsnd_daidrv_get(struct rsnd_priv *priv, int id)
647a0d847c3SKuninori Morimoto {
648a0d847c3SKuninori Morimoto 	if ((id < 0) || (id >= rsnd_rdai_nr(priv)))
649a0d847c3SKuninori Morimoto 		return NULL;
650a0d847c3SKuninori Morimoto 
651a0d847c3SKuninori Morimoto 	return priv->daidrv + id;
652a0d847c3SKuninori Morimoto }
653a0d847c3SKuninori Morimoto 
654eb2535f5SKuninori Morimoto #define rsnd_dai_to_priv(dai) snd_soc_dai_get_drvdata(dai)
rsnd_dai_to_rdai(struct snd_soc_dai * dai)6551536a968SKuninori Morimoto static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai)
6561536a968SKuninori Morimoto {
657eb2535f5SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
6581536a968SKuninori Morimoto 
659710d0889SKuninori Morimoto 	return rsnd_rdai_get(priv, dai->id);
6601536a968SKuninori Morimoto }
6611536a968SKuninori Morimoto 
6621536a968SKuninori Morimoto /*
6631536a968SKuninori Morimoto  *	rsnd_soc_dai functions
6641536a968SKuninori Morimoto  */
rsnd_dai_period_elapsed(struct rsnd_dai_stream * io)66575defee0SKuninori Morimoto void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io)
66675defee0SKuninori Morimoto {
66775defee0SKuninori Morimoto 	struct snd_pcm_substream *substream = io->substream;
66875defee0SKuninori Morimoto 
66975defee0SKuninori Morimoto 	/*
67075defee0SKuninori Morimoto 	 * this function should be called...
67175defee0SKuninori Morimoto 	 *
67275defee0SKuninori Morimoto 	 * - if rsnd_dai_pointer_update() returns true
67375defee0SKuninori Morimoto 	 * - without spin lock
67475defee0SKuninori Morimoto 	 */
67575defee0SKuninori Morimoto 
67675defee0SKuninori Morimoto 	snd_pcm_period_elapsed(substream);
6771536a968SKuninori Morimoto }
6781536a968SKuninori Morimoto 
rsnd_dai_stream_init(struct rsnd_dai_stream * io,struct snd_pcm_substream * substream)6795626ad08SKuninori Morimoto static void rsnd_dai_stream_init(struct rsnd_dai_stream *io,
6801536a968SKuninori Morimoto 				struct snd_pcm_substream *substream)
6811536a968SKuninori Morimoto {
6821536a968SKuninori Morimoto 	io->substream		= substream;
6835626ad08SKuninori Morimoto }
6841536a968SKuninori Morimoto 
rsnd_dai_stream_quit(struct rsnd_dai_stream * io)6855626ad08SKuninori Morimoto static void rsnd_dai_stream_quit(struct rsnd_dai_stream *io)
6865626ad08SKuninori Morimoto {
6875626ad08SKuninori Morimoto 	io->substream		= NULL;
6881536a968SKuninori Morimoto }
6891536a968SKuninori Morimoto 
6901536a968SKuninori Morimoto static
rsnd_substream_to_dai(struct snd_pcm_substream * substream)6911536a968SKuninori Morimoto struct snd_soc_dai *rsnd_substream_to_dai(struct snd_pcm_substream *substream)
6921536a968SKuninori Morimoto {
69328ec78b0SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
6941536a968SKuninori Morimoto 
69534a43780SKuninori Morimoto 	return  asoc_rtd_to_cpu(rtd, 0);
6961536a968SKuninori Morimoto }
6971536a968SKuninori Morimoto 
6981536a968SKuninori Morimoto static
rsnd_rdai_to_io(struct rsnd_dai * rdai,struct snd_pcm_substream * substream)6991536a968SKuninori Morimoto struct rsnd_dai_stream *rsnd_rdai_to_io(struct rsnd_dai *rdai,
7001536a968SKuninori Morimoto 					struct snd_pcm_substream *substream)
7011536a968SKuninori Morimoto {
7021536a968SKuninori Morimoto 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
7031536a968SKuninori Morimoto 		return &rdai->playback;
7041536a968SKuninori Morimoto 	else
7051536a968SKuninori Morimoto 		return &rdai->capture;
7061536a968SKuninori Morimoto }
7071536a968SKuninori Morimoto 
rsnd_soc_dai_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)7081536a968SKuninori Morimoto static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
7091536a968SKuninori Morimoto 			    struct snd_soc_dai *dai)
7101536a968SKuninori Morimoto {
711eb2535f5SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
7121536a968SKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
7131536a968SKuninori Morimoto 	struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
7141536a968SKuninori Morimoto 	int ret;
7151536a968SKuninori Morimoto 	unsigned long flags;
7161536a968SKuninori Morimoto 
71702299d98SKuninori Morimoto 	spin_lock_irqsave(&priv->lock, flags);
7181536a968SKuninori Morimoto 
7191536a968SKuninori Morimoto 	switch (cmd) {
7201536a968SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_START:
7214b9c75eaSKuninori Morimoto 	case SNDRV_PCM_TRIGGER_RESUME:
722690602fcSKuninori Morimoto 		ret = rsnd_dai_call(init, io, priv);
723cdaa3cdfSKuninori Morimoto 		if (ret < 0)
724cdaa3cdfSKuninori Morimoto 			goto dai_trigger_end;
725cdaa3cdfSKuninori Morimoto 
726690602fcSKuninori Morimoto 		ret = rsnd_dai_call(start, io, priv);
727cdaa3cdfSKuninori Morimoto 		if (ret < 0)
728cdaa3cdfSKuninori Morimoto 			goto dai_trigger_end;
729b5b442abSKuninori Morimoto 
730b5b442abSKuninori Morimoto 		ret = rsnd_dai_call(irq, io, priv, 1);
731b5b442abSKuninori Morimoto 		if (ret < 0)
732b5b442abSKuninori Morimoto 			goto dai_trigger_end;
733b5b442abSKuninori Morimoto 
7341536a968SKuninori Morimoto 		break;
7351536a968SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_STOP:
7364b9c75eaSKuninori Morimoto 	case SNDRV_PCM_TRIGGER_SUSPEND:
737b5b442abSKuninori Morimoto 		ret = rsnd_dai_call(irq, io, priv, 0);
738b5b442abSKuninori Morimoto 
739b5b442abSKuninori Morimoto 		ret |= rsnd_dai_call(stop, io, priv);
740cdaa3cdfSKuninori Morimoto 
74189e3e2c3SKuninori Morimoto 		ret |= rsnd_dai_call(quit, io, priv);
742cdaa3cdfSKuninori Morimoto 
7431536a968SKuninori Morimoto 		break;
7441536a968SKuninori Morimoto 	default:
7451536a968SKuninori Morimoto 		ret = -EINVAL;
7461536a968SKuninori Morimoto 	}
7471536a968SKuninori Morimoto 
7481536a968SKuninori Morimoto dai_trigger_end:
74902299d98SKuninori Morimoto 	spin_unlock_irqrestore(&priv->lock, flags);
7501536a968SKuninori Morimoto 
7511536a968SKuninori Morimoto 	return ret;
7521536a968SKuninori Morimoto }
7531536a968SKuninori Morimoto 
rsnd_soc_dai_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)7541536a968SKuninori Morimoto static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
7551536a968SKuninori Morimoto {
7561536a968SKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
7571536a968SKuninori Morimoto 
758f7c7a24bSKuninori Morimoto 	/* set clock master for audio interface */
7597704a82eSKuninori Morimoto 	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
7602d4dd776SCharles Keepax 	case SND_SOC_DAIFMT_BC_FC:
761e1508289SKuninori Morimoto 		rdai->clk_master = 0;
7621536a968SKuninori Morimoto 		break;
7632d4dd776SCharles Keepax 	case SND_SOC_DAIFMT_BP_FP:
764f7c7a24bSKuninori Morimoto 		rdai->clk_master = 1; /* cpu is master */
7651536a968SKuninori Morimoto 		break;
7661536a968SKuninori Morimoto 	default:
7671536a968SKuninori Morimoto 		return -EINVAL;
7681536a968SKuninori Morimoto 	}
7691536a968SKuninori Morimoto 
7701536a968SKuninori Morimoto 	/* set format */
77122e58665SJunya Monden 	rdai->bit_clk_inv = 0;
7721536a968SKuninori Morimoto 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
7731536a968SKuninori Morimoto 	case SND_SOC_DAIFMT_I2S:
7741536a968SKuninori Morimoto 		rdai->sys_delay = 0;
7751536a968SKuninori Morimoto 		rdai->data_alignment = 0;
7761a7889caSKuninori Morimoto 		rdai->frm_clk_inv = 0;
7771536a968SKuninori Morimoto 		break;
7781536a968SKuninori Morimoto 	case SND_SOC_DAIFMT_LEFT_J:
7793791b3eeSDragos Tarcatu 	case SND_SOC_DAIFMT_DSP_B:
7801536a968SKuninori Morimoto 		rdai->sys_delay = 1;
7811536a968SKuninori Morimoto 		rdai->data_alignment = 0;
7821a7889caSKuninori Morimoto 		rdai->frm_clk_inv = 1;
7831536a968SKuninori Morimoto 		break;
7841536a968SKuninori Morimoto 	case SND_SOC_DAIFMT_RIGHT_J:
7851536a968SKuninori Morimoto 		rdai->sys_delay = 1;
7861536a968SKuninori Morimoto 		rdai->data_alignment = 1;
7871a7889caSKuninori Morimoto 		rdai->frm_clk_inv = 1;
7881a7889caSKuninori Morimoto 		break;
7893791b3eeSDragos Tarcatu 	case SND_SOC_DAIFMT_DSP_A:
7903791b3eeSDragos Tarcatu 		rdai->sys_delay = 0;
7913791b3eeSDragos Tarcatu 		rdai->data_alignment = 0;
7923791b3eeSDragos Tarcatu 		rdai->frm_clk_inv = 1;
7933791b3eeSDragos Tarcatu 		break;
7941a7889caSKuninori Morimoto 	}
7951a7889caSKuninori Morimoto 
7961a7889caSKuninori Morimoto 	/* set clock inversion */
7971a7889caSKuninori Morimoto 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
7981a7889caSKuninori Morimoto 	case SND_SOC_DAIFMT_NB_IF:
7991a7889caSKuninori Morimoto 		rdai->frm_clk_inv = !rdai->frm_clk_inv;
8001a7889caSKuninori Morimoto 		break;
8011a7889caSKuninori Morimoto 	case SND_SOC_DAIFMT_IB_NF:
8021a7889caSKuninori Morimoto 		rdai->bit_clk_inv = !rdai->bit_clk_inv;
8031a7889caSKuninori Morimoto 		break;
8041a7889caSKuninori Morimoto 	case SND_SOC_DAIFMT_IB_IF:
8051a7889caSKuninori Morimoto 		rdai->bit_clk_inv = !rdai->bit_clk_inv;
8061a7889caSKuninori Morimoto 		rdai->frm_clk_inv = !rdai->frm_clk_inv;
8071a7889caSKuninori Morimoto 		break;
8081a7889caSKuninori Morimoto 	case SND_SOC_DAIFMT_NB_NF:
8091a7889caSKuninori Morimoto 	default:
8101536a968SKuninori Morimoto 		break;
8111536a968SKuninori Morimoto 	}
8121536a968SKuninori Morimoto 
8131536a968SKuninori Morimoto 	return 0;
8141536a968SKuninori Morimoto }
8151536a968SKuninori Morimoto 
rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai * dai,u32 tx_mask,u32 rx_mask,int slots,int slot_width)816186fadc1SKuninori Morimoto static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
817186fadc1SKuninori Morimoto 				     u32 tx_mask, u32 rx_mask,
818186fadc1SKuninori Morimoto 				     int slots, int slot_width)
819186fadc1SKuninori Morimoto {
820186fadc1SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
821186fadc1SKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
822186fadc1SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
823186fadc1SKuninori Morimoto 
824fb2815f4SDragos Tarcatu 	switch (slot_width) {
825fb2815f4SDragos Tarcatu 	case 16:
826fb2815f4SDragos Tarcatu 	case 24:
827fb2815f4SDragos Tarcatu 	case 32:
828fb2815f4SDragos Tarcatu 		break;
829fb2815f4SDragos Tarcatu 	default:
83082ab7e9aSKuninori Morimoto 		/* use default */
8311ad059a1SKuninori Morimoto 		/*
8321ad059a1SKuninori Morimoto 		 * Indicate warning if DT has "dai-tdm-slot-width"
8331ad059a1SKuninori Morimoto 		 * but the value was not expected.
8341ad059a1SKuninori Morimoto 		 */
8351ad059a1SKuninori Morimoto 		if (slot_width)
8361ad059a1SKuninori Morimoto 			dev_warn(dev, "unsupported TDM slot width (%d), force to use default 32\n",
8371ad059a1SKuninori Morimoto 				 slot_width);
83882ab7e9aSKuninori Morimoto 		slot_width = 32;
839fb2815f4SDragos Tarcatu 	}
840fb2815f4SDragos Tarcatu 
841186fadc1SKuninori Morimoto 	switch (slots) {
8428cc03722SKuninori Morimoto 	case 2:
843f69f4522SKuninori Morimoto 		/* TDM Split Mode */
844186fadc1SKuninori Morimoto 	case 6:
8458cc03722SKuninori Morimoto 	case 8:
846186fadc1SKuninori Morimoto 		/* TDM Extend Mode */
8471ff9593dSKuninori Morimoto 		rsnd_rdai_channels_set(rdai, slots);
8481ff9593dSKuninori Morimoto 		rsnd_rdai_ssi_lane_set(rdai, 1);
849fb2815f4SDragos Tarcatu 		rsnd_rdai_width_set(rdai, slot_width);
850186fadc1SKuninori Morimoto 		break;
851186fadc1SKuninori Morimoto 	default:
852186fadc1SKuninori Morimoto 		dev_err(dev, "unsupported TDM slots (%d)\n", slots);
853186fadc1SKuninori Morimoto 		return -EINVAL;
854186fadc1SKuninori Morimoto 	}
855186fadc1SKuninori Morimoto 
856186fadc1SKuninori Morimoto 	return 0;
857186fadc1SKuninori Morimoto }
858186fadc1SKuninori Morimoto 
8598cc03722SKuninori Morimoto static unsigned int rsnd_soc_hw_channels_list[] = {
86029d03ff5SKuninori Morimoto 	2, 6, 8,
8618cc03722SKuninori Morimoto };
8628cc03722SKuninori Morimoto 
8638cc03722SKuninori Morimoto static unsigned int rsnd_soc_hw_rate_list[] = {
8648cc03722SKuninori Morimoto 	  8000,
8658cc03722SKuninori Morimoto 	 11025,
8668cc03722SKuninori Morimoto 	 16000,
8678cc03722SKuninori Morimoto 	 22050,
8688cc03722SKuninori Morimoto 	 32000,
8698cc03722SKuninori Morimoto 	 44100,
8708cc03722SKuninori Morimoto 	 48000,
8718cc03722SKuninori Morimoto 	 64000,
8728cc03722SKuninori Morimoto 	 88200,
8738cc03722SKuninori Morimoto 	 96000,
8748cc03722SKuninori Morimoto 	176400,
8758cc03722SKuninori Morimoto 	192000,
8768cc03722SKuninori Morimoto };
8778cc03722SKuninori Morimoto 
rsnd_soc_hw_rule(struct rsnd_dai * rdai,unsigned int * list,int list_num,struct snd_interval * baseline,struct snd_interval * iv,struct rsnd_dai_stream * io,char * unit)878fb2815f4SDragos Tarcatu static int rsnd_soc_hw_rule(struct rsnd_dai *rdai,
8798cc03722SKuninori Morimoto 			    unsigned int *list, int list_num,
8806d612f67SKuninori Morimoto 			    struct snd_interval *baseline, struct snd_interval *iv,
8816d612f67SKuninori Morimoto 			    struct rsnd_dai_stream *io, char *unit)
8828cc03722SKuninori Morimoto {
8838cc03722SKuninori Morimoto 	struct snd_interval p;
884947f4eb5SKuninori Morimoto 	unsigned int rate;
8858cc03722SKuninori Morimoto 	int i;
8868cc03722SKuninori Morimoto 
8878cc03722SKuninori Morimoto 	snd_interval_any(&p);
8888cc03722SKuninori Morimoto 	p.min = UINT_MAX;
8898cc03722SKuninori Morimoto 	p.max = 0;
8908cc03722SKuninori Morimoto 
8918cc03722SKuninori Morimoto 	for (i = 0; i < list_num; i++) {
8928cc03722SKuninori Morimoto 
8938cc03722SKuninori Morimoto 		if (!snd_interval_test(iv, list[i]))
8948cc03722SKuninori Morimoto 			continue;
8958cc03722SKuninori Morimoto 
896fb2815f4SDragos Tarcatu 		rate = rsnd_ssi_clk_query(rdai,
8978cc03722SKuninori Morimoto 					  baseline->min, list[i], NULL);
8988cc03722SKuninori Morimoto 		if (rate > 0) {
8998cc03722SKuninori Morimoto 			p.min = min(p.min, list[i]);
9008cc03722SKuninori Morimoto 			p.max = max(p.max, list[i]);
9018cc03722SKuninori Morimoto 		}
9028cc03722SKuninori Morimoto 
903fb2815f4SDragos Tarcatu 		rate = rsnd_ssi_clk_query(rdai,
9048cc03722SKuninori Morimoto 					  baseline->max, list[i], NULL);
9058cc03722SKuninori Morimoto 		if (rate > 0) {
9068cc03722SKuninori Morimoto 			p.min = min(p.min, list[i]);
9078cc03722SKuninori Morimoto 			p.max = max(p.max, list[i]);
9088cc03722SKuninori Morimoto 		}
9098cc03722SKuninori Morimoto 	}
9108cc03722SKuninori Morimoto 
9116d612f67SKuninori Morimoto 	/* Indicate error once if it can't handle */
9126d612f67SKuninori Morimoto 	if (!rsnd_flags_has(io, RSND_HW_RULE_ERR) && (p.min > p.max)) {
9136d612f67SKuninori Morimoto 		struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
9146d612f67SKuninori Morimoto 		struct device *dev = rsnd_priv_to_dev(priv);
9156d612f67SKuninori Morimoto 
9166d612f67SKuninori Morimoto 		dev_warn(dev, "It can't handle %d %s <-> %d %s\n",
9176d612f67SKuninori Morimoto 			 baseline->min, unit, baseline->max, unit);
9186d612f67SKuninori Morimoto 		rsnd_flags_set(io, RSND_HW_RULE_ERR);
9196d612f67SKuninori Morimoto 	}
9206d612f67SKuninori Morimoto 
9218cc03722SKuninori Morimoto 	return snd_interval_refine(iv, &p);
9228cc03722SKuninori Morimoto }
9238cc03722SKuninori Morimoto 
rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)924b735662fSJiada Wang static int rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params,
925b735662fSJiada Wang 				 struct snd_pcm_hw_rule *rule)
9268cc03722SKuninori Morimoto {
9278cc03722SKuninori Morimoto 	struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
9288cc03722SKuninori Morimoto 	struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
9298cc03722SKuninori Morimoto 	struct snd_interval ic;
930b735662fSJiada Wang 	struct rsnd_dai_stream *io = rule->private;
931b735662fSJiada Wang 	struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
9328cc03722SKuninori Morimoto 
9338cc03722SKuninori Morimoto 	/*
9348cc03722SKuninori Morimoto 	 * possible sampling rate limitation is same as
9358cc03722SKuninori Morimoto 	 * 2ch if it supports multi ssi
936b2fb31bbSKuninori Morimoto 	 * and same as 8ch if TDM 6ch (see rsnd_ssi_config_init())
9378cc03722SKuninori Morimoto 	 */
9388cc03722SKuninori Morimoto 	ic = *ic_;
939b2fb31bbSKuninori Morimoto 	ic.min =
940b2fb31bbSKuninori Morimoto 	ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params);
9418cc03722SKuninori Morimoto 
942fb2815f4SDragos Tarcatu 	return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_rate_list,
9438cc03722SKuninori Morimoto 				ARRAY_SIZE(rsnd_soc_hw_rate_list),
9446d612f67SKuninori Morimoto 				&ic, ir, io, "ch");
9458cc03722SKuninori Morimoto }
9468cc03722SKuninori Morimoto 
rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)947b735662fSJiada Wang static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params,
9488cc03722SKuninori Morimoto 				     struct snd_pcm_hw_rule *rule)
9498cc03722SKuninori Morimoto {
9508cc03722SKuninori Morimoto 	struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
9518cc03722SKuninori Morimoto 	struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
9528cc03722SKuninori Morimoto 	struct snd_interval ic;
953b735662fSJiada Wang 	struct rsnd_dai_stream *io = rule->private;
954b735662fSJiada Wang 	struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
9558cc03722SKuninori Morimoto 
9568cc03722SKuninori Morimoto 	/*
9578cc03722SKuninori Morimoto 	 * possible sampling rate limitation is same as
9588cc03722SKuninori Morimoto 	 * 2ch if it supports multi ssi
959b2fb31bbSKuninori Morimoto 	 * and same as 8ch if TDM 6ch (see rsnd_ssi_config_init())
9608cc03722SKuninori Morimoto 	 */
9618cc03722SKuninori Morimoto 	ic = *ic_;
962b2fb31bbSKuninori Morimoto 	ic.min =
963b2fb31bbSKuninori Morimoto 	ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params);
9648cc03722SKuninori Morimoto 
965fb2815f4SDragos Tarcatu 	return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_channels_list,
9668cc03722SKuninori Morimoto 				ARRAY_SIZE(rsnd_soc_hw_channels_list),
9676d612f67SKuninori Morimoto 				ir, &ic, io, "Hz");
9688cc03722SKuninori Morimoto }
9698cc03722SKuninori Morimoto 
9705c2e035eSBhumika Goyal static const struct snd_pcm_hardware rsnd_pcm_hardware = {
9713c9736aaSKuninori Morimoto 	.info =		SNDRV_PCM_INFO_INTERLEAVED	|
9723c9736aaSKuninori Morimoto 			SNDRV_PCM_INFO_MMAP		|
9733c9736aaSKuninori Morimoto 			SNDRV_PCM_INFO_MMAP_VALID,
9743c9736aaSKuninori Morimoto 	.buffer_bytes_max	= 64 * 1024,
9753c9736aaSKuninori Morimoto 	.period_bytes_min	= 32,
9763c9736aaSKuninori Morimoto 	.period_bytes_max	= 8192,
9773c9736aaSKuninori Morimoto 	.periods_min		= 1,
9783c9736aaSKuninori Morimoto 	.periods_max		= 32,
9793c9736aaSKuninori Morimoto 	.fifo_size		= 256,
9803c9736aaSKuninori Morimoto };
9813c9736aaSKuninori Morimoto 
rsnd_soc_dai_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)9823c9736aaSKuninori Morimoto static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream,
9838cc03722SKuninori Morimoto 				struct snd_soc_dai *dai)
9848cc03722SKuninori Morimoto {
9858cc03722SKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
9863c9736aaSKuninori Morimoto 	struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
9878cc03722SKuninori Morimoto 	struct snd_pcm_hw_constraint_list *constraint = &rdai->constraint;
9883c9736aaSKuninori Morimoto 	struct snd_pcm_runtime *runtime = substream->runtime;
9898cc03722SKuninori Morimoto 	unsigned int max_channels = rsnd_rdai_channels_get(rdai);
9908cc03722SKuninori Morimoto 	int i;
9918cc03722SKuninori Morimoto 
9926d612f67SKuninori Morimoto 	rsnd_flags_del(io, RSND_HW_RULE_ERR);
9936d612f67SKuninori Morimoto 
994b2fb31bbSKuninori Morimoto 	rsnd_dai_stream_init(io, substream);
995b2fb31bbSKuninori Morimoto 
9968cc03722SKuninori Morimoto 	/*
9978cc03722SKuninori Morimoto 	 * Channel Limitation
9988cc03722SKuninori Morimoto 	 * It depends on Platform design
9998cc03722SKuninori Morimoto 	 */
10008cc03722SKuninori Morimoto 	constraint->list	= rsnd_soc_hw_channels_list;
10018cc03722SKuninori Morimoto 	constraint->count	= 0;
10028cc03722SKuninori Morimoto 	constraint->mask	= 0;
10038cc03722SKuninori Morimoto 
10048cc03722SKuninori Morimoto 	for (i = 0; i < ARRAY_SIZE(rsnd_soc_hw_channels_list); i++) {
10058cc03722SKuninori Morimoto 		if (rsnd_soc_hw_channels_list[i] > max_channels)
10068cc03722SKuninori Morimoto 			break;
10078cc03722SKuninori Morimoto 		constraint->count = i + 1;
10088cc03722SKuninori Morimoto 	}
10098cc03722SKuninori Morimoto 
10103c9736aaSKuninori Morimoto 	snd_soc_set_runtime_hwparams(substream, &rsnd_pcm_hardware);
10113c9736aaSKuninori Morimoto 
10128cc03722SKuninori Morimoto 	snd_pcm_hw_constraint_list(runtime, 0,
10138cc03722SKuninori Morimoto 				   SNDRV_PCM_HW_PARAM_CHANNELS, constraint);
10148cc03722SKuninori Morimoto 
10153c9736aaSKuninori Morimoto 	snd_pcm_hw_constraint_integer(runtime,
10163c9736aaSKuninori Morimoto 				      SNDRV_PCM_HW_PARAM_PERIODS);
10173c9736aaSKuninori Morimoto 
10188cc03722SKuninori Morimoto 	/*
10198cc03722SKuninori Morimoto 	 * Sampling Rate / Channel Limitation
10208cc03722SKuninori Morimoto 	 * It depends on Clock Master Mode
10218cc03722SKuninori Morimoto 	 */
10223c9736aaSKuninori Morimoto 	if (rsnd_rdai_is_clk_master(rdai)) {
1023b2fb31bbSKuninori Morimoto 		int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
1024b2fb31bbSKuninori Morimoto 
10258cc03722SKuninori Morimoto 		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
1026b735662fSJiada Wang 				    rsnd_soc_hw_rule_rate,
1027b735662fSJiada Wang 				    is_play ? &rdai->playback : &rdai->capture,
10288cc03722SKuninori Morimoto 				    SNDRV_PCM_HW_PARAM_CHANNELS, -1);
10298cc03722SKuninori Morimoto 		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
1030b735662fSJiada Wang 				    rsnd_soc_hw_rule_channels,
1031b735662fSJiada Wang 				    is_play ? &rdai->playback : &rdai->capture,
10328cc03722SKuninori Morimoto 				    SNDRV_PCM_HW_PARAM_RATE, -1);
10338cc03722SKuninori Morimoto 	}
10348cc03722SKuninori Morimoto 
10356ab6a247SKuninori Morimoto 	return 0;
103610a9cca1SKuninori Morimoto }
103710a9cca1SKuninori Morimoto 
rsnd_soc_dai_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)103810a9cca1SKuninori Morimoto static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream,
103910a9cca1SKuninori Morimoto 				  struct snd_soc_dai *dai)
104010a9cca1SKuninori Morimoto {
104110a9cca1SKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
1042f30b4ca4SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
104310a9cca1SKuninori Morimoto 	struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
104410a9cca1SKuninori Morimoto 
104510a9cca1SKuninori Morimoto 	/*
104610a9cca1SKuninori Morimoto 	 * call rsnd_dai_call without spinlock
104710a9cca1SKuninori Morimoto 	 */
10486ab6a247SKuninori Morimoto 	rsnd_dai_call(cleanup, io, priv);
1049b2fb31bbSKuninori Morimoto 
1050b2fb31bbSKuninori Morimoto 	rsnd_dai_stream_quit(io);
105110a9cca1SKuninori Morimoto }
105210a9cca1SKuninori Morimoto 
rsnd_soc_dai_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)10534d230d12SJiada Wang static int rsnd_soc_dai_prepare(struct snd_pcm_substream *substream,
10544d230d12SJiada Wang 				struct snd_soc_dai *dai)
10554d230d12SJiada Wang {
10564d230d12SJiada Wang 	struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
10574d230d12SJiada Wang 	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
10584d230d12SJiada Wang 	struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
10594d230d12SJiada Wang 
10604d230d12SJiada Wang 	return rsnd_dai_call(prepare, io, priv);
10614d230d12SJiada Wang }
10624d230d12SJiada Wang 
106302921765SKuninori Morimoto static u64 rsnd_soc_dai_formats[] = {
106402921765SKuninori Morimoto 	/*
106502921765SKuninori Morimoto 	 * 1st Priority
106602921765SKuninori Morimoto 	 *
106702921765SKuninori Morimoto 	 * Well tested formats.
106802921765SKuninori Morimoto 	 * Select below from Sound Card, not auto
106902921765SKuninori Morimoto 	 *	SND_SOC_DAIFMT_CBC_CFC
107002921765SKuninori Morimoto 	 *	SND_SOC_DAIFMT_CBP_CFP
107102921765SKuninori Morimoto 	 */
107202921765SKuninori Morimoto 	SND_SOC_POSSIBLE_DAIFMT_I2S	|
107302921765SKuninori Morimoto 	SND_SOC_POSSIBLE_DAIFMT_RIGHT_J	|
107402921765SKuninori Morimoto 	SND_SOC_POSSIBLE_DAIFMT_LEFT_J	|
107502921765SKuninori Morimoto 	SND_SOC_POSSIBLE_DAIFMT_NB_NF	|
107602921765SKuninori Morimoto 	SND_SOC_POSSIBLE_DAIFMT_NB_IF	|
107702921765SKuninori Morimoto 	SND_SOC_POSSIBLE_DAIFMT_IB_NF	|
107802921765SKuninori Morimoto 	SND_SOC_POSSIBLE_DAIFMT_IB_IF,
107902921765SKuninori Morimoto 	/*
108002921765SKuninori Morimoto 	 * 2nd Priority
108102921765SKuninori Morimoto 	 *
108202921765SKuninori Morimoto 	 * Supported, but not well tested
108302921765SKuninori Morimoto 	 */
108402921765SKuninori Morimoto 	SND_SOC_POSSIBLE_DAIFMT_DSP_A	|
108502921765SKuninori Morimoto 	SND_SOC_POSSIBLE_DAIFMT_DSP_B,
108602921765SKuninori Morimoto };
108702921765SKuninori Morimoto 
rsnd_parse_tdm_split_mode(struct rsnd_priv * priv,struct rsnd_dai_stream * io,struct device_node * dai_np)10882264cf2eSKuninori Morimoto static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv,
1089f497c88bSKuninori Morimoto 				      struct rsnd_dai_stream *io,
1090f497c88bSKuninori Morimoto 				      struct device_node *dai_np)
1091538a4ffeSKuninori Morimoto {
1092538a4ffeSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
1093538a4ffeSKuninori Morimoto 	struct device_node *ssiu_np = rsnd_ssiu_of_node(priv);
1094538a4ffeSKuninori Morimoto 	struct device_node *np;
1095f497c88bSKuninori Morimoto 	int is_play = rsnd_io_is_play(io);
1096e539943cSKuninori Morimoto 	int i;
1097538a4ffeSKuninori Morimoto 
1098538a4ffeSKuninori Morimoto 	if (!ssiu_np)
1099538a4ffeSKuninori Morimoto 		return;
1100538a4ffeSKuninori Morimoto 
1101538a4ffeSKuninori Morimoto 	/*
1102538a4ffeSKuninori Morimoto 	 * This driver assumes that it is TDM Split mode
1103538a4ffeSKuninori Morimoto 	 * if it includes ssiu node
1104538a4ffeSKuninori Morimoto 	 */
1105538a4ffeSKuninori Morimoto 	for (i = 0;; i++) {
1106538a4ffeSKuninori Morimoto 		struct device_node *node = is_play ?
1107538a4ffeSKuninori Morimoto 			of_parse_phandle(dai_np, "playback", i) :
1108538a4ffeSKuninori Morimoto 			of_parse_phandle(dai_np, "capture",  i);
1109538a4ffeSKuninori Morimoto 
1110538a4ffeSKuninori Morimoto 		if (!node)
1111538a4ffeSKuninori Morimoto 			break;
1112538a4ffeSKuninori Morimoto 
1113538a4ffeSKuninori Morimoto 		for_each_child_of_node(ssiu_np, np) {
1114538a4ffeSKuninori Morimoto 			if (np == node) {
1115538a4ffeSKuninori Morimoto 				rsnd_flags_set(io, RSND_STREAM_TDM_SPLIT);
1116538a4ffeSKuninori Morimoto 				dev_dbg(dev, "%s is part of TDM Split\n", io->name);
1117538a4ffeSKuninori Morimoto 			}
1118538a4ffeSKuninori Morimoto 		}
1119538a4ffeSKuninori Morimoto 
1120ef2c6951SKuninori Morimoto 		of_node_put(node);
1121538a4ffeSKuninori Morimoto 	}
1122ef2c6951SKuninori Morimoto 
1123ef2c6951SKuninori Morimoto 	of_node_put(ssiu_np);
1124538a4ffeSKuninori Morimoto }
1125538a4ffeSKuninori Morimoto 
rsnd_parse_connect_simple(struct rsnd_priv * priv,struct rsnd_dai_stream * io,struct device_node * dai_np)11262264cf2eSKuninori Morimoto static void rsnd_parse_connect_simple(struct rsnd_priv *priv,
11272264cf2eSKuninori Morimoto 				      struct rsnd_dai_stream *io,
11282264cf2eSKuninori Morimoto 				      struct device_node *dai_np)
11292264cf2eSKuninori Morimoto {
11302264cf2eSKuninori Morimoto 	if (!rsnd_io_to_mod_ssi(io))
11312264cf2eSKuninori Morimoto 		return;
11322264cf2eSKuninori Morimoto 
11332264cf2eSKuninori Morimoto 	rsnd_parse_tdm_split_mode(priv, io, dai_np);
11342264cf2eSKuninori Morimoto }
11352264cf2eSKuninori Morimoto 
rsnd_parse_connect_graph(struct rsnd_priv * priv,struct rsnd_dai_stream * io,struct device_node * endpoint)1136beed78aeSKuninori Morimoto static void rsnd_parse_connect_graph(struct rsnd_priv *priv,
1137beed78aeSKuninori Morimoto 				     struct rsnd_dai_stream *io,
1138beed78aeSKuninori Morimoto 				     struct device_node *endpoint)
1139beed78aeSKuninori Morimoto {
1140beed78aeSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
1141ef2c6951SKuninori Morimoto 	struct device_node *remote_node;
1142beed78aeSKuninori Morimoto 
1143beed78aeSKuninori Morimoto 	if (!rsnd_io_to_mod_ssi(io))
1144beed78aeSKuninori Morimoto 		return;
1145beed78aeSKuninori Morimoto 
1146ef2c6951SKuninori Morimoto 	remote_node = of_graph_get_remote_port_parent(endpoint);
1147ef2c6951SKuninori Morimoto 
1148beed78aeSKuninori Morimoto 	/* HDMI0 */
1149beed78aeSKuninori Morimoto 	if (strstr(remote_node->full_name, "hdmi@fead0000")) {
1150beed78aeSKuninori Morimoto 		rsnd_flags_set(io, RSND_STREAM_HDMI0);
1151beed78aeSKuninori Morimoto 		dev_dbg(dev, "%s connected to HDMI0\n", io->name);
1152beed78aeSKuninori Morimoto 	}
1153beed78aeSKuninori Morimoto 
1154beed78aeSKuninori Morimoto 	/* HDMI1 */
1155beed78aeSKuninori Morimoto 	if (strstr(remote_node->full_name, "hdmi@feae0000")) {
1156beed78aeSKuninori Morimoto 		rsnd_flags_set(io, RSND_STREAM_HDMI1);
1157beed78aeSKuninori Morimoto 		dev_dbg(dev, "%s connected to HDMI1\n", io->name);
1158beed78aeSKuninori Morimoto 	}
1159f69f4522SKuninori Morimoto 
11602264cf2eSKuninori Morimoto 	rsnd_parse_tdm_split_mode(priv, io, endpoint);
1161ef2c6951SKuninori Morimoto 
1162ef2c6951SKuninori Morimoto 	of_node_put(remote_node);
1163beed78aeSKuninori Morimoto }
1164beed78aeSKuninori Morimoto 
rsnd_parse_connect_common(struct rsnd_dai * rdai,char * name,struct rsnd_mod * (* mod_get)(struct rsnd_priv * priv,int id),struct device_node * node,struct device_node * playback,struct device_node * capture)1165ec02b5a1SKuninori Morimoto void rsnd_parse_connect_common(struct rsnd_dai *rdai, char *name,
116689b66174SKuninori Morimoto 		struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id),
116789b66174SKuninori Morimoto 		struct device_node *node,
116889b66174SKuninori Morimoto 		struct device_node *playback,
116989b66174SKuninori Morimoto 		struct device_node *capture)
117089b66174SKuninori Morimoto {
117189b66174SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
1172d09a7db4SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
117389b66174SKuninori Morimoto 	struct device_node *np;
117489b66174SKuninori Morimoto 	int i;
117589b66174SKuninori Morimoto 
117689b66174SKuninori Morimoto 	if (!node)
117789b66174SKuninori Morimoto 		return;
117889b66174SKuninori Morimoto 
117989b66174SKuninori Morimoto 	i = 0;
118089b66174SKuninori Morimoto 	for_each_child_of_node(node, np) {
118173919dbeSKuninori Morimoto 		struct rsnd_mod *mod;
118273919dbeSKuninori Morimoto 
1183d09a7db4SKuninori Morimoto 		i = rsnd_node_fixed_index(dev, np, name, i);
1184d09a7db4SKuninori Morimoto 		if (i < 0) {
1185d09a7db4SKuninori Morimoto 			of_node_put(np);
1186d09a7db4SKuninori Morimoto 			break;
1187d09a7db4SKuninori Morimoto 		}
1188c413983eSKuninori Morimoto 
118973919dbeSKuninori Morimoto 		mod = mod_get(priv, i);
1190e539943cSKuninori Morimoto 
119189b66174SKuninori Morimoto 		if (np == playback)
119289b66174SKuninori Morimoto 			rsnd_dai_connect(mod, &rdai->playback, mod->type);
119389b66174SKuninori Morimoto 		if (np == capture)
119489b66174SKuninori Morimoto 			rsnd_dai_connect(mod, &rdai->capture, mod->type);
119589b66174SKuninori Morimoto 		i++;
119689b66174SKuninori Morimoto 	}
119789b66174SKuninori Morimoto 
119889b66174SKuninori Morimoto 	of_node_put(node);
119989b66174SKuninori Morimoto }
120089b66174SKuninori Morimoto 
rsnd_node_fixed_index(struct device * dev,struct device_node * node,char * name,int idx)1201d09a7db4SKuninori Morimoto int rsnd_node_fixed_index(struct device *dev, struct device_node *node, char *name, int idx)
1202c413983eSKuninori Morimoto {
1203c413983eSKuninori Morimoto 	char node_name[16];
1204c413983eSKuninori Morimoto 
1205c413983eSKuninori Morimoto 	/*
1206c413983eSKuninori Morimoto 	 * rsnd is assuming each device nodes are sequential numbering,
1207c413983eSKuninori Morimoto 	 * but some of them are not.
1208c413983eSKuninori Morimoto 	 * This function adjusts index for it.
1209c413983eSKuninori Morimoto 	 *
1210c413983eSKuninori Morimoto 	 * ex)
1211c413983eSKuninori Morimoto 	 * Normal case,		special case
1212c413983eSKuninori Morimoto 	 *	ssi-0
1213c413983eSKuninori Morimoto 	 *	ssi-1
1214c413983eSKuninori Morimoto 	 *	ssi-2
1215c413983eSKuninori Morimoto 	 *	ssi-3		ssi-3
1216c413983eSKuninori Morimoto 	 *	ssi-4		ssi-4
1217c413983eSKuninori Morimoto 	 *	...
1218c413983eSKuninori Morimoto 	 *
1219c413983eSKuninori Morimoto 	 * assume Max 64 node
1220c413983eSKuninori Morimoto 	 */
1221c413983eSKuninori Morimoto 	for (; idx < 64; idx++) {
1222c413983eSKuninori Morimoto 		snprintf(node_name, sizeof(node_name), "%s-%d", name, idx);
1223c413983eSKuninori Morimoto 
1224c413983eSKuninori Morimoto 		if (strncmp(node_name, of_node_full_name(node), sizeof(node_name)) == 0)
1225c413983eSKuninori Morimoto 			return idx;
1226c413983eSKuninori Morimoto 	}
1227c413983eSKuninori Morimoto 
1228d09a7db4SKuninori Morimoto 	dev_err(dev, "strange node numbering (%s)",
1229d09a7db4SKuninori Morimoto 		of_node_full_name(node));
1230c413983eSKuninori Morimoto 	return -EINVAL;
1231c413983eSKuninori Morimoto }
1232c413983eSKuninori Morimoto 
rsnd_node_count(struct rsnd_priv * priv,struct device_node * node,char * name)1233c413983eSKuninori Morimoto int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name)
1234c413983eSKuninori Morimoto {
1235c413983eSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
1236c413983eSKuninori Morimoto 	struct device_node *np;
1237c413983eSKuninori Morimoto 	int i;
1238c413983eSKuninori Morimoto 
1239c413983eSKuninori Morimoto 	i = 0;
1240c413983eSKuninori Morimoto 	for_each_child_of_node(node, np) {
1241d09a7db4SKuninori Morimoto 		i = rsnd_node_fixed_index(dev, np, name, i);
1242c413983eSKuninori Morimoto 		if (i < 0) {
124317363235SChristophe JAILLET 			of_node_put(np);
1244c413983eSKuninori Morimoto 			return 0;
1245c413983eSKuninori Morimoto 		}
1246c413983eSKuninori Morimoto 		i++;
1247c413983eSKuninori Morimoto 	}
1248c413983eSKuninori Morimoto 
1249c413983eSKuninori Morimoto 	return i;
1250c413983eSKuninori Morimoto }
1251c413983eSKuninori Morimoto 
rsnd_dai_of_node(struct rsnd_priv * priv,int * is_graph)1252547b02f7SKuninori Morimoto static int rsnd_dai_of_node(struct rsnd_priv *priv, int *is_graph)
125311d0f8edSKuninori Morimoto {
125411d0f8edSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
125511d0f8edSKuninori Morimoto 	struct device_node *np = dev->of_node;
1256547b02f7SKuninori Morimoto 	struct device_node *ports, *node;
1257547b02f7SKuninori Morimoto 	int nr = 0;
1258547b02f7SKuninori Morimoto 	int i = 0;
125911d0f8edSKuninori Morimoto 
126011d0f8edSKuninori Morimoto 	*is_graph = 0;
126111d0f8edSKuninori Morimoto 
126211d0f8edSKuninori Morimoto 	/*
126311d0f8edSKuninori Morimoto 	 * parse both previous dai (= rcar_sound,dai), and
126411d0f8edSKuninori Morimoto 	 * graph dai (= ports/port)
126511d0f8edSKuninori Morimoto 	 */
12666328489cSKuninori Morimoto 
12676328489cSKuninori Morimoto 	/*
12686328489cSKuninori Morimoto 	 * Simple-Card
12696328489cSKuninori Morimoto 	 */
1270547b02f7SKuninori Morimoto 	node = of_get_child_by_name(np, RSND_NODE_DAI);
1271547b02f7SKuninori Morimoto 	if (!node)
1272547b02f7SKuninori Morimoto 		goto audio_graph;
1273547b02f7SKuninori Morimoto 
1274547b02f7SKuninori Morimoto 	of_node_put(node);
1275547b02f7SKuninori Morimoto 
1276547b02f7SKuninori Morimoto 	for_each_child_of_node(np, node) {
1277547b02f7SKuninori Morimoto 		if (!of_node_name_eq(node, RSND_NODE_DAI))
1278547b02f7SKuninori Morimoto 			continue;
1279547b02f7SKuninori Morimoto 
1280547b02f7SKuninori Morimoto 		priv->component_dais[i] = of_get_child_count(node);
1281547b02f7SKuninori Morimoto 		nr += priv->component_dais[i];
1282547b02f7SKuninori Morimoto 		i++;
1283547b02f7SKuninori Morimoto 		if (i >= RSND_MAX_COMPONENT) {
1284547b02f7SKuninori Morimoto 			dev_info(dev, "reach to max component\n");
12851a5ca2aaSKuninori Morimoto 			of_node_put(node);
1286547b02f7SKuninori Morimoto 			break;
1287547b02f7SKuninori Morimoto 		}
128811d0f8edSKuninori Morimoto 	}
128911d0f8edSKuninori Morimoto 
1290547b02f7SKuninori Morimoto 	return nr;
1291547b02f7SKuninori Morimoto 
1292547b02f7SKuninori Morimoto audio_graph:
12936328489cSKuninori Morimoto 	/*
12946328489cSKuninori Morimoto 	 * Audio-Graph-Card
12956328489cSKuninori Morimoto 	 */
1296547b02f7SKuninori Morimoto 	for_each_child_of_node(np, ports) {
1297547b02f7SKuninori Morimoto 		if (!of_node_name_eq(ports, "ports") &&
1298547b02f7SKuninori Morimoto 		    !of_node_name_eq(ports, "port"))
1299547b02f7SKuninori Morimoto 			continue;
1300*f9ba85f8SLad Prabhakar 		priv->component_dais[i] =
1301*f9ba85f8SLad Prabhakar 			of_graph_get_endpoint_count(of_node_name_eq(ports, "ports") ?
1302*f9ba85f8SLad Prabhakar 						    ports : np);
1303547b02f7SKuninori Morimoto 		nr += priv->component_dais[i];
1304547b02f7SKuninori Morimoto 		i++;
1305547b02f7SKuninori Morimoto 		if (i >= RSND_MAX_COMPONENT) {
1306547b02f7SKuninori Morimoto 			dev_info(dev, "reach to max component\n");
13071a5ca2aaSKuninori Morimoto 			of_node_put(node);
130828115b1cSJulia Lawall 			of_node_put(ports);
1309547b02f7SKuninori Morimoto 			break;
1310547b02f7SKuninori Morimoto 		}
13116328489cSKuninori Morimoto 	}
131211d0f8edSKuninori Morimoto 
1313547b02f7SKuninori Morimoto 	*is_graph = 1;
131411d0f8edSKuninori Morimoto 
1315547b02f7SKuninori Morimoto 	return nr;
131611d0f8edSKuninori Morimoto }
131711d0f8edSKuninori Morimoto 
1318e9b5daadSKuninori Morimoto 
1319e9b5daadSKuninori Morimoto #define PREALLOC_BUFFER		(32 * 1024)
1320e9b5daadSKuninori Morimoto #define PREALLOC_BUFFER_MAX	(32 * 1024)
1321e9b5daadSKuninori Morimoto 
rsnd_preallocate_pages(struct snd_soc_pcm_runtime * rtd,struct rsnd_dai_stream * io,int stream)1322e9b5daadSKuninori Morimoto static int rsnd_preallocate_pages(struct snd_soc_pcm_runtime *rtd,
1323e9b5daadSKuninori Morimoto 				  struct rsnd_dai_stream *io,
1324e9b5daadSKuninori Morimoto 				  int stream)
1325e9b5daadSKuninori Morimoto {
1326e9b5daadSKuninori Morimoto 	struct rsnd_priv *priv = rsnd_io_to_priv(io);
1327e9b5daadSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
1328e9b5daadSKuninori Morimoto 	struct snd_pcm_substream *substream;
1329e9b5daadSKuninori Morimoto 
1330e9b5daadSKuninori Morimoto 	/*
1331e9b5daadSKuninori Morimoto 	 * use Audio-DMAC dev if we can use IPMMU
1332e9b5daadSKuninori Morimoto 	 * see
1333e9b5daadSKuninori Morimoto 	 *	rsnd_dmaen_attach()
1334e9b5daadSKuninori Morimoto 	 */
1335e9b5daadSKuninori Morimoto 	if (io->dmac_dev)
1336e9b5daadSKuninori Morimoto 		dev = io->dmac_dev;
1337e9b5daadSKuninori Morimoto 
1338e9b5daadSKuninori Morimoto 	for (substream = rtd->pcm->streams[stream].substream;
1339e9b5daadSKuninori Morimoto 	     substream;
1340e9b5daadSKuninori Morimoto 	     substream = substream->next) {
1341e494dbcdSTakashi Iwai 		snd_pcm_set_managed_buffer(substream,
1342e9b5daadSKuninori Morimoto 					   SNDRV_DMA_TYPE_DEV,
1343e9b5daadSKuninori Morimoto 					   dev,
1344e9b5daadSKuninori Morimoto 					   PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
1345e9b5daadSKuninori Morimoto 	}
1346e9b5daadSKuninori Morimoto 
1347e9b5daadSKuninori Morimoto 	return 0;
1348e9b5daadSKuninori Morimoto }
1349e9b5daadSKuninori Morimoto 
rsnd_soc_dai_pcm_new(struct snd_soc_pcm_runtime * rtd,struct snd_soc_dai * dai)13504b0891a7SKuninori Morimoto static int rsnd_soc_dai_pcm_new(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
1351e9b5daadSKuninori Morimoto {
1352e9b5daadSKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
1353e9b5daadSKuninori Morimoto 	int ret;
1354e9b5daadSKuninori Morimoto 
1355e9b5daadSKuninori Morimoto 	ret = rsnd_dai_call(pcm_new, &rdai->playback, rtd);
1356e9b5daadSKuninori Morimoto 	if (ret)
1357e9b5daadSKuninori Morimoto 		return ret;
1358e9b5daadSKuninori Morimoto 
1359e9b5daadSKuninori Morimoto 	ret = rsnd_dai_call(pcm_new, &rdai->capture, rtd);
1360e9b5daadSKuninori Morimoto 	if (ret)
1361e9b5daadSKuninori Morimoto 		return ret;
1362e9b5daadSKuninori Morimoto 
1363e9b5daadSKuninori Morimoto 	ret = rsnd_preallocate_pages(rtd, &rdai->playback,
1364e9b5daadSKuninori Morimoto 				     SNDRV_PCM_STREAM_PLAYBACK);
1365e9b5daadSKuninori Morimoto 	if (ret)
1366e9b5daadSKuninori Morimoto 		return ret;
1367e9b5daadSKuninori Morimoto 
1368e9b5daadSKuninori Morimoto 	ret = rsnd_preallocate_pages(rtd, &rdai->capture,
1369e9b5daadSKuninori Morimoto 				     SNDRV_PCM_STREAM_CAPTURE);
1370e9b5daadSKuninori Morimoto 	if (ret)
1371e9b5daadSKuninori Morimoto 		return ret;
1372e9b5daadSKuninori Morimoto 
1373e9b5daadSKuninori Morimoto 	return 0;
1374e9b5daadSKuninori Morimoto }
1375e9b5daadSKuninori Morimoto 
13764b0891a7SKuninori Morimoto static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
13774b0891a7SKuninori Morimoto 	.pcm_new			= rsnd_soc_dai_pcm_new,
13784b0891a7SKuninori Morimoto 	.startup			= rsnd_soc_dai_startup,
13794b0891a7SKuninori Morimoto 	.shutdown			= rsnd_soc_dai_shutdown,
13804b0891a7SKuninori Morimoto 	.trigger			= rsnd_soc_dai_trigger,
13814b0891a7SKuninori Morimoto 	.set_fmt			= rsnd_soc_dai_set_fmt,
13824b0891a7SKuninori Morimoto 	.set_tdm_slot			= rsnd_soc_set_dai_tdm_slot,
13834b0891a7SKuninori Morimoto 	.prepare			= rsnd_soc_dai_prepare,
13844b0891a7SKuninori Morimoto 	.auto_selectable_formats	= rsnd_soc_dai_formats,
13854b0891a7SKuninori Morimoto 	.num_auto_selectable_formats	= ARRAY_SIZE(rsnd_soc_dai_formats),
13864b0891a7SKuninori Morimoto };
13874b0891a7SKuninori Morimoto 
__rsnd_dai_probe(struct rsnd_priv * priv,struct device_node * dai_np,struct device_node * node_np,uint32_t node_arg,int dai_i)13884d4b334bSKuninori Morimoto static void __rsnd_dai_probe(struct rsnd_priv *priv,
13894d4b334bSKuninori Morimoto 			     struct device_node *dai_np,
1390547b02f7SKuninori Morimoto 			     struct device_node *node_np,
1391547b02f7SKuninori Morimoto 			     uint32_t node_arg,
13929f761183SKuninori Morimoto 			     int dai_i)
139390e8e50fSKuninori Morimoto {
139494e2710cSKuninori Morimoto 	struct rsnd_dai_stream *io_playback;
139594e2710cSKuninori Morimoto 	struct rsnd_dai_stream *io_capture;
13964d4b334bSKuninori Morimoto 	struct snd_soc_dai_driver *drv;
139794e2710cSKuninori Morimoto 	struct rsnd_dai *rdai;
13982ea6b074SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
139968a410afSKuninori Morimoto 	int playback_exist = 0, capture_exist = 0;
14004d4b334bSKuninori Morimoto 	int io_i;
140190e8e50fSKuninori Morimoto 
140294e2710cSKuninori Morimoto 	rdai		= rsnd_rdai_get(priv, dai_i);
1403a0d847c3SKuninori Morimoto 	drv		= rsnd_daidrv_get(priv, dai_i);
140494e2710cSKuninori Morimoto 	io_playback	= &rdai->playback;
140594e2710cSKuninori Morimoto 	io_capture	= &rdai->capture;
140690e8e50fSKuninori Morimoto 
140794e2710cSKuninori Morimoto 	snprintf(rdai->name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", dai_i);
140890e8e50fSKuninori Morimoto 
1409547b02f7SKuninori Morimoto 	/* for multi Component */
1410547b02f7SKuninori Morimoto 	rdai->dai_args.np		= node_np;
1411547b02f7SKuninori Morimoto 	rdai->dai_args.args_count	= 1;
1412547b02f7SKuninori Morimoto 	rdai->dai_args.args[0]		= node_arg;
1413547b02f7SKuninori Morimoto 
141494e2710cSKuninori Morimoto 	rdai->priv	= priv;
141594e2710cSKuninori Morimoto 	drv->name	= rdai->name;
141694e2710cSKuninori Morimoto 	drv->ops	= &rsnd_soc_dai_ops;
14178897a147SKuninori Morimoto 	drv->id		= dai_i;
1418547b02f7SKuninori Morimoto 	drv->dai_args	= &rdai->dai_args;
141994e2710cSKuninori Morimoto 
14209328882eSKuninori Morimoto 	io_playback->rdai		= rdai;
14219328882eSKuninori Morimoto 	io_capture->rdai		= rdai;
14221ff9593dSKuninori Morimoto 	rsnd_rdai_channels_set(rdai, 2); /* default 2ch */
14231ff9593dSKuninori Morimoto 	rsnd_rdai_ssi_lane_set(rdai, 1); /* default 1lane */
1424fb2815f4SDragos Tarcatu 	rsnd_rdai_width_set(rdai, 32);   /* default 32bit width */
142594e2710cSKuninori Morimoto 
142694e2710cSKuninori Morimoto 	for (io_i = 0;; io_i++) {
1427e539943cSKuninori Morimoto 		struct device_node *playback = of_parse_phandle(dai_np, "playback", io_i);
1428e539943cSKuninori Morimoto 		struct device_node *capture  = of_parse_phandle(dai_np, "capture", io_i);
142990e8e50fSKuninori Morimoto 
143090e8e50fSKuninori Morimoto 		if (!playback && !capture)
143190e8e50fSKuninori Morimoto 			break;
143290e8e50fSKuninori Morimoto 
143368a410afSKuninori Morimoto 		if (io_i == 0) {
143468a410afSKuninori Morimoto 			/* check whether playback/capture property exists */
143568a410afSKuninori Morimoto 			if (playback)
143668a410afSKuninori Morimoto 				playback_exist = 1;
143768a410afSKuninori Morimoto 			if (capture)
143868a410afSKuninori Morimoto 				capture_exist = 1;
143968a410afSKuninori Morimoto 		}
144068a410afSKuninori Morimoto 
144189b66174SKuninori Morimoto 		rsnd_parse_connect_ssi(rdai, playback, capture);
14424e7788fbSKuninori Morimoto 		rsnd_parse_connect_ssiu(rdai, playback, capture);
144389b66174SKuninori Morimoto 		rsnd_parse_connect_src(rdai, playback, capture);
144489b66174SKuninori Morimoto 		rsnd_parse_connect_ctu(rdai, playback, capture);
144589b66174SKuninori Morimoto 		rsnd_parse_connect_mix(rdai, playback, capture);
144689b66174SKuninori Morimoto 		rsnd_parse_connect_dvc(rdai, playback, capture);
144790e8e50fSKuninori Morimoto 
144890e8e50fSKuninori Morimoto 		of_node_put(playback);
144990e8e50fSKuninori Morimoto 		of_node_put(capture);
145090e8e50fSKuninori Morimoto 	}
145190e8e50fSKuninori Morimoto 
145268a410afSKuninori Morimoto 	if (playback_exist) {
145368a410afSKuninori Morimoto 		snprintf(io_playback->name, RSND_DAI_NAME_SIZE, "DAI%d Playback", dai_i);
145468a410afSKuninori Morimoto 		drv->playback.rates		= RSND_RATES;
145568a410afSKuninori Morimoto 		drv->playback.formats		= RSND_FMTS;
145668a410afSKuninori Morimoto 		drv->playback.channels_min	= 2;
145768a410afSKuninori Morimoto 		drv->playback.channels_max	= 8;
145868a410afSKuninori Morimoto 		drv->playback.stream_name	= io_playback->name;
145968a410afSKuninori Morimoto 	}
146068a410afSKuninori Morimoto 	if (capture_exist) {
146168a410afSKuninori Morimoto 		snprintf(io_capture->name, RSND_DAI_NAME_SIZE, "DAI%d Capture", dai_i);
146268a410afSKuninori Morimoto 		drv->capture.rates		= RSND_RATES;
146368a410afSKuninori Morimoto 		drv->capture.formats		= RSND_FMTS;
146468a410afSKuninori Morimoto 		drv->capture.channels_min	= 2;
146568a410afSKuninori Morimoto 		drv->capture.channels_max	= 8;
146668a410afSKuninori Morimoto 		drv->capture.stream_name	= io_capture->name;
146768a410afSKuninori Morimoto 	}
146868a410afSKuninori Morimoto 
14697cc90a5cSKuninori Morimoto 	if (rsnd_ssi_is_pin_sharing(io_capture) ||
14707cc90a5cSKuninori Morimoto 	    rsnd_ssi_is_pin_sharing(io_playback)) {
1471f1cd5f3bSKuninori Morimoto 		/* should have symmetric_rate if pin sharing */
1472f1cd5f3bSKuninori Morimoto 		drv->symmetric_rate = 1;
14737cc90a5cSKuninori Morimoto 	}
14747cc90a5cSKuninori Morimoto 
147594e2710cSKuninori Morimoto 	dev_dbg(dev, "%s (%s/%s)\n", rdai->name,
147694e2710cSKuninori Morimoto 		rsnd_io_to_mod_ssi(io_playback) ? "play"    : " -- ",
147794e2710cSKuninori Morimoto 		rsnd_io_to_mod_ssi(io_capture) ? "capture" : "  --   ");
147890e8e50fSKuninori Morimoto }
147990e8e50fSKuninori Morimoto 
rsnd_dai_probe(struct rsnd_priv * priv)14804d4b334bSKuninori Morimoto static int rsnd_dai_probe(struct rsnd_priv *priv)
14814d4b334bSKuninori Morimoto {
14824d4b334bSKuninori Morimoto 	struct snd_soc_dai_driver *rdrv;
14834d4b334bSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
1484547b02f7SKuninori Morimoto 	struct device_node *np = dev->of_node;
14854d4b334bSKuninori Morimoto 	struct rsnd_dai *rdai;
14866328489cSKuninori Morimoto 	int nr = 0;
14874d4b334bSKuninori Morimoto 	int is_graph;
14884d4b334bSKuninori Morimoto 	int dai_i;
14894b4dab82SKuninori Morimoto 
1490547b02f7SKuninori Morimoto 	nr = rsnd_dai_of_node(priv, &is_graph);
14914d4b334bSKuninori Morimoto 	if (!nr)
14924d4b334bSKuninori Morimoto 		return -EINVAL;
14934d4b334bSKuninori Morimoto 
1494a86854d0SKees Cook 	rdrv = devm_kcalloc(dev, nr, sizeof(*rdrv), GFP_KERNEL);
1495a86854d0SKees Cook 	rdai = devm_kcalloc(dev, nr, sizeof(*rdai), GFP_KERNEL);
14964d4b334bSKuninori Morimoto 	if (!rdrv || !rdai)
14974d4b334bSKuninori Morimoto 		return -ENOMEM;
14984d4b334bSKuninori Morimoto 
14994d4b334bSKuninori Morimoto 	priv->rdai_nr	= nr;
15004d4b334bSKuninori Morimoto 	priv->daidrv	= rdrv;
15014d4b334bSKuninori Morimoto 	priv->rdai	= rdai;
15024d4b334bSKuninori Morimoto 
15034d4b334bSKuninori Morimoto 	/*
15044d4b334bSKuninori Morimoto 	 * parse all dai
15054d4b334bSKuninori Morimoto 	 */
15064d4b334bSKuninori Morimoto 	dai_i = 0;
15074d4b334bSKuninori Morimoto 	if (is_graph) {
1508547b02f7SKuninori Morimoto 		struct device_node *ports;
1509547b02f7SKuninori Morimoto 		struct device_node *dai_np;
1510547b02f7SKuninori Morimoto 
1511547b02f7SKuninori Morimoto 		for_each_child_of_node(np, ports) {
1512547b02f7SKuninori Morimoto 			if (!of_node_name_eq(ports, "ports") &&
1513547b02f7SKuninori Morimoto 			    !of_node_name_eq(ports, "port"))
1514547b02f7SKuninori Morimoto 				continue;
1515*f9ba85f8SLad Prabhakar 			for_each_endpoint_of_node(of_node_name_eq(ports, "ports") ?
1516*f9ba85f8SLad Prabhakar 						  ports : np, dai_np) {
1517547b02f7SKuninori Morimoto 				__rsnd_dai_probe(priv, dai_np, dai_np, 0, dai_i);
1518c2bc6527SKuninori Morimoto 				if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
1519e539943cSKuninori Morimoto 					rdai = rsnd_rdai_get(priv, dai_i);
1520beed78aeSKuninori Morimoto 
1521beed78aeSKuninori Morimoto 					rsnd_parse_connect_graph(priv, &rdai->playback, dai_np);
1522beed78aeSKuninori Morimoto 					rsnd_parse_connect_graph(priv, &rdai->capture,  dai_np);
1523beed78aeSKuninori Morimoto 				}
15247fa72ccaSKuninori Morimoto 				dai_i++;
15257fa72ccaSKuninori Morimoto 			}
1526547b02f7SKuninori Morimoto 		}
15274d4b334bSKuninori Morimoto 	} else {
1528547b02f7SKuninori Morimoto 		struct device_node *node;
1529547b02f7SKuninori Morimoto 		struct device_node *dai_np;
1530547b02f7SKuninori Morimoto 
1531547b02f7SKuninori Morimoto 		for_each_child_of_node(np, node) {
1532547b02f7SKuninori Morimoto 			if (!of_node_name_eq(node, RSND_NODE_DAI))
1533547b02f7SKuninori Morimoto 				continue;
1534547b02f7SKuninori Morimoto 
1535547b02f7SKuninori Morimoto 			for_each_child_of_node(node, dai_np) {
1536547b02f7SKuninori Morimoto 				__rsnd_dai_probe(priv, dai_np, np, dai_i, dai_i);
1537c2bc6527SKuninori Morimoto 				if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
1538e539943cSKuninori Morimoto 					rdai = rsnd_rdai_get(priv, dai_i);
1539f497c88bSKuninori Morimoto 
1540f497c88bSKuninori Morimoto 					rsnd_parse_connect_simple(priv, &rdai->playback, dai_np);
1541f497c88bSKuninori Morimoto 					rsnd_parse_connect_simple(priv, &rdai->capture,  dai_np);
1542538a4ffeSKuninori Morimoto 				}
1543538a4ffeSKuninori Morimoto 				dai_i++;
1544538a4ffeSKuninori Morimoto 			}
15454d4b334bSKuninori Morimoto 		}
1546547b02f7SKuninori Morimoto 	}
15474d4b334bSKuninori Morimoto 
15484d4b334bSKuninori Morimoto 	return 0;
15491536a968SKuninori Morimoto }
15501536a968SKuninori Morimoto 
15511536a968SKuninori Morimoto /*
15521536a968SKuninori Morimoto  *		pcm ops
15531536a968SKuninori Morimoto  */
rsnd_hw_update(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params)1554b43b8ae8SKuninori Morimoto static int rsnd_hw_update(struct snd_pcm_substream *substream,
1555b43b8ae8SKuninori Morimoto 			  struct snd_pcm_hw_params *hw_params)
1556b43b8ae8SKuninori Morimoto {
1557b43b8ae8SKuninori Morimoto 	struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
1558b43b8ae8SKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
1559b43b8ae8SKuninori Morimoto 	struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
1560b43b8ae8SKuninori Morimoto 	struct rsnd_priv *priv = rsnd_io_to_priv(io);
1561b43b8ae8SKuninori Morimoto 	unsigned long flags;
1562b43b8ae8SKuninori Morimoto 	int ret;
1563b43b8ae8SKuninori Morimoto 
1564b43b8ae8SKuninori Morimoto 	spin_lock_irqsave(&priv->lock, flags);
1565b43b8ae8SKuninori Morimoto 	if (hw_params)
1566b43b8ae8SKuninori Morimoto 		ret = rsnd_dai_call(hw_params, io, substream, hw_params);
1567b43b8ae8SKuninori Morimoto 	else
1568b43b8ae8SKuninori Morimoto 		ret = rsnd_dai_call(hw_free, io, substream);
1569b43b8ae8SKuninori Morimoto 	spin_unlock_irqrestore(&priv->lock, flags);
1570b43b8ae8SKuninori Morimoto 
1571b43b8ae8SKuninori Morimoto 	return ret;
1572b43b8ae8SKuninori Morimoto }
1573b43b8ae8SKuninori Morimoto 
rsnd_hw_params(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params)15749dcefa72SKuninori Morimoto static int rsnd_hw_params(struct snd_soc_component *component,
15759dcefa72SKuninori Morimoto 			  struct snd_pcm_substream *substream,
15761536a968SKuninori Morimoto 			  struct snd_pcm_hw_params *hw_params)
15771536a968SKuninori Morimoto {
15783b7843ffSKuninori Morimoto 	struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
15793b7843ffSKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
15803b7843ffSKuninori Morimoto 	struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
158128ec78b0SKuninori Morimoto 	struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
15823b7843ffSKuninori Morimoto 
1583c2aaaa57SKuninori Morimoto 	/*
1584c2aaaa57SKuninori Morimoto 	 * rsnd assumes that it might be used under DPCM if user want to use
1585c2aaaa57SKuninori Morimoto 	 * channel / rate convert. Then, rsnd should be FE.
1586c2aaaa57SKuninori Morimoto 	 * And then, this function will be called *after* BE settings.
1587c2aaaa57SKuninori Morimoto 	 * this means, each BE already has fixuped hw_params.
1588c2aaaa57SKuninori Morimoto 	 * see
1589c2aaaa57SKuninori Morimoto 	 *	dpcm_fe_dai_hw_params()
1590c2aaaa57SKuninori Morimoto 	 *	dpcm_be_dai_hw_params()
1591c2aaaa57SKuninori Morimoto 	 */
1592c2aaaa57SKuninori Morimoto 	io->converted_rate = 0;
1593c2aaaa57SKuninori Morimoto 	io->converted_chan = 0;
1594c2aaaa57SKuninori Morimoto 	if (fe->dai_link->dynamic) {
1595c2aaaa57SKuninori Morimoto 		struct rsnd_priv *priv = rsnd_io_to_priv(io);
1596c2aaaa57SKuninori Morimoto 		struct device *dev = rsnd_priv_to_dev(priv);
1597c2aaaa57SKuninori Morimoto 		struct snd_soc_dpcm *dpcm;
1598c2aaaa57SKuninori Morimoto 		int stream = substream->stream;
1599c2aaaa57SKuninori Morimoto 
1600c2aaaa57SKuninori Morimoto 		for_each_dpcm_be(fe, stream, dpcm) {
160125106550SKuninori Morimoto 			struct snd_soc_pcm_runtime *be = dpcm->be;
160225106550SKuninori Morimoto 			struct snd_pcm_hw_params *be_params = &be->dpcm[stream].hw_params;
1603e539943cSKuninori Morimoto 
1604c2aaaa57SKuninori Morimoto 			if (params_channels(hw_params) != params_channels(be_params))
1605c2aaaa57SKuninori Morimoto 				io->converted_chan = params_channels(be_params);
1606c2aaaa57SKuninori Morimoto 			if (params_rate(hw_params) != params_rate(be_params))
1607c2aaaa57SKuninori Morimoto 				io->converted_rate = params_rate(be_params);
1608c2aaaa57SKuninori Morimoto 		}
1609c2aaaa57SKuninori Morimoto 		if (io->converted_chan)
1610c2aaaa57SKuninori Morimoto 			dev_dbg(dev, "convert channels = %d\n", io->converted_chan);
161119c6a63cSMikhail Durnev 		if (io->converted_rate) {
161219c6a63cSMikhail Durnev 			/*
161319c6a63cSMikhail Durnev 			 * SRC supports convert rates from params_rate(hw_params)/k_down
161419c6a63cSMikhail Durnev 			 * to params_rate(hw_params)*k_up, where k_up is always 6, and
161519c6a63cSMikhail Durnev 			 * k_down depends on number of channels and SRC unit.
161619c6a63cSMikhail Durnev 			 * So all SRC units can upsample audio up to 6 times regardless
161719c6a63cSMikhail Durnev 			 * its number of channels. And all SRC units can downsample
161819c6a63cSMikhail Durnev 			 * 2 channel audio up to 6 times too.
161919c6a63cSMikhail Durnev 			 */
162019c6a63cSMikhail Durnev 			int k_up = 6;
162119c6a63cSMikhail Durnev 			int k_down = 6;
162219c6a63cSMikhail Durnev 			int channel;
162319c6a63cSMikhail Durnev 			struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
162419c6a63cSMikhail Durnev 
1625c2aaaa57SKuninori Morimoto 			dev_dbg(dev, "convert rate     = %d\n", io->converted_rate);
162619c6a63cSMikhail Durnev 
162719c6a63cSMikhail Durnev 			channel = io->converted_chan ? io->converted_chan :
162819c6a63cSMikhail Durnev 				  params_channels(hw_params);
162919c6a63cSMikhail Durnev 
163019c6a63cSMikhail Durnev 			switch (rsnd_mod_id(src_mod)) {
163119c6a63cSMikhail Durnev 			/*
163219c6a63cSMikhail Durnev 			 * SRC0 can downsample 4, 6 and 8 channel audio up to 4 times.
163319c6a63cSMikhail Durnev 			 * SRC1, SRC3 and SRC4 can downsample 4 channel audio
163419c6a63cSMikhail Durnev 			 * up to 4 times.
163519c6a63cSMikhail Durnev 			 * SRC1, SRC3 and SRC4 can downsample 6 and 8 channel audio
163619c6a63cSMikhail Durnev 			 * no more than twice.
163719c6a63cSMikhail Durnev 			 */
163819c6a63cSMikhail Durnev 			case 1:
163919c6a63cSMikhail Durnev 			case 3:
164019c6a63cSMikhail Durnev 			case 4:
164119c6a63cSMikhail Durnev 				if (channel > 4) {
164219c6a63cSMikhail Durnev 					k_down = 2;
164319c6a63cSMikhail Durnev 					break;
164419c6a63cSMikhail Durnev 				}
164519c6a63cSMikhail Durnev 				fallthrough;
164619c6a63cSMikhail Durnev 			case 0:
164719c6a63cSMikhail Durnev 				if (channel > 2)
164819c6a63cSMikhail Durnev 					k_down = 4;
164919c6a63cSMikhail Durnev 				break;
165019c6a63cSMikhail Durnev 
165119c6a63cSMikhail Durnev 			/* Other SRC units do not support more than 2 channels */
165219c6a63cSMikhail Durnev 			default:
165319c6a63cSMikhail Durnev 				if (channel > 2)
165419c6a63cSMikhail Durnev 					return -EINVAL;
165519c6a63cSMikhail Durnev 			}
165619c6a63cSMikhail Durnev 
165719c6a63cSMikhail Durnev 			if (params_rate(hw_params) > io->converted_rate * k_down) {
165819c6a63cSMikhail Durnev 				hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min =
165919c6a63cSMikhail Durnev 					io->converted_rate * k_down;
166019c6a63cSMikhail Durnev 				hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max =
166119c6a63cSMikhail Durnev 					io->converted_rate * k_down;
166219c6a63cSMikhail Durnev 				hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
166319c6a63cSMikhail Durnev 			} else if (params_rate(hw_params) * k_up < io->converted_rate) {
166419c6a63cSMikhail Durnev 				hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min =
16654aa2b05aSShang XiaoJing 					DIV_ROUND_UP(io->converted_rate, k_up);
166619c6a63cSMikhail Durnev 				hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max =
16674aa2b05aSShang XiaoJing 					DIV_ROUND_UP(io->converted_rate, k_up);
166819c6a63cSMikhail Durnev 				hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
166919c6a63cSMikhail Durnev 			}
167019c6a63cSMikhail Durnev 
167119c6a63cSMikhail Durnev 			/*
167219c6a63cSMikhail Durnev 			 * TBD: Max SRC input and output rates also depend on number
167319c6a63cSMikhail Durnev 			 * of channels and SRC unit:
167419c6a63cSMikhail Durnev 			 * SRC1, SRC3 and SRC4 do not support more than 128kHz
167519c6a63cSMikhail Durnev 			 * for 6 channel and 96kHz for 8 channel audio.
167619c6a63cSMikhail Durnev 			 * Perhaps this function should return EINVAL if the input or
167719c6a63cSMikhail Durnev 			 * the output rate exceeds the limitation.
167819c6a63cSMikhail Durnev 			 */
167919c6a63cSMikhail Durnev 		}
1680c2aaaa57SKuninori Morimoto 	}
1681c2aaaa57SKuninori Morimoto 
1682b43b8ae8SKuninori Morimoto 	return rsnd_hw_update(substream, hw_params);
16831536a968SKuninori Morimoto }
16841536a968SKuninori Morimoto 
rsnd_hw_free(struct snd_soc_component * component,struct snd_pcm_substream * substream)16859dcefa72SKuninori Morimoto static int rsnd_hw_free(struct snd_soc_component *component,
16869dcefa72SKuninori Morimoto 			struct snd_pcm_substream *substream)
1687859fd6cbSTimo Wischer {
1688b43b8ae8SKuninori Morimoto 	return rsnd_hw_update(substream, NULL);
1689859fd6cbSTimo Wischer }
1690859fd6cbSTimo Wischer 
rsnd_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)16919dcefa72SKuninori Morimoto static snd_pcm_uframes_t rsnd_pointer(struct snd_soc_component *component,
16929dcefa72SKuninori Morimoto 				      struct snd_pcm_substream *substream)
16931536a968SKuninori Morimoto {
16941536a968SKuninori Morimoto 	struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
16951536a968SKuninori Morimoto 	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
16961536a968SKuninori Morimoto 	struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
169707b7acb5SKuninori Morimoto 	snd_pcm_uframes_t pointer = 0;
16981536a968SKuninori Morimoto 
169907b7acb5SKuninori Morimoto 	rsnd_dai_call(pointer, io, &pointer);
170007b7acb5SKuninori Morimoto 
170107b7acb5SKuninori Morimoto 	return pointer;
17021536a968SKuninori Morimoto }
17031536a968SKuninori Morimoto 
17041536a968SKuninori Morimoto /*
1705170a2497SKuninori Morimoto  *		snd_kcontrol
1706170a2497SKuninori Morimoto  */
rsnd_kctrl_info(struct snd_kcontrol * kctrl,struct snd_ctl_elem_info * uinfo)1707170a2497SKuninori Morimoto static int rsnd_kctrl_info(struct snd_kcontrol *kctrl,
1708170a2497SKuninori Morimoto 			   struct snd_ctl_elem_info *uinfo)
1709170a2497SKuninori Morimoto {
171016d44989SKuninori Morimoto 	struct rsnd_kctrl_cfg *cfg = snd_kcontrol_chip(kctrl);
1711170a2497SKuninori Morimoto 
1712170a2497SKuninori Morimoto 	if (cfg->texts) {
1713170a2497SKuninori Morimoto 		uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1714170a2497SKuninori Morimoto 		uinfo->count = cfg->size;
1715170a2497SKuninori Morimoto 		uinfo->value.enumerated.items = cfg->max;
1716170a2497SKuninori Morimoto 		if (uinfo->value.enumerated.item >= cfg->max)
1717170a2497SKuninori Morimoto 			uinfo->value.enumerated.item = cfg->max - 1;
171875b1a8f9SJoe Perches 		strscpy(uinfo->value.enumerated.name,
1719170a2497SKuninori Morimoto 			cfg->texts[uinfo->value.enumerated.item],
1720170a2497SKuninori Morimoto 			sizeof(uinfo->value.enumerated.name));
1721170a2497SKuninori Morimoto 	} else {
1722170a2497SKuninori Morimoto 		uinfo->count = cfg->size;
1723170a2497SKuninori Morimoto 		uinfo->value.integer.min = 0;
1724170a2497SKuninori Morimoto 		uinfo->value.integer.max = cfg->max;
1725170a2497SKuninori Morimoto 		uinfo->type = (cfg->max == 1) ?
1726170a2497SKuninori Morimoto 			SNDRV_CTL_ELEM_TYPE_BOOLEAN :
1727170a2497SKuninori Morimoto 			SNDRV_CTL_ELEM_TYPE_INTEGER;
1728170a2497SKuninori Morimoto 	}
1729170a2497SKuninori Morimoto 
1730170a2497SKuninori Morimoto 	return 0;
1731170a2497SKuninori Morimoto }
1732170a2497SKuninori Morimoto 
rsnd_kctrl_get(struct snd_kcontrol * kctrl,struct snd_ctl_elem_value * uc)1733170a2497SKuninori Morimoto static int rsnd_kctrl_get(struct snd_kcontrol *kctrl,
1734170a2497SKuninori Morimoto 			  struct snd_ctl_elem_value *uc)
1735170a2497SKuninori Morimoto {
173616d44989SKuninori Morimoto 	struct rsnd_kctrl_cfg *cfg = snd_kcontrol_chip(kctrl);
1737170a2497SKuninori Morimoto 	int i;
1738170a2497SKuninori Morimoto 
1739170a2497SKuninori Morimoto 	for (i = 0; i < cfg->size; i++)
1740170a2497SKuninori Morimoto 		if (cfg->texts)
1741170a2497SKuninori Morimoto 			uc->value.enumerated.item[i] = cfg->val[i];
1742170a2497SKuninori Morimoto 		else
1743170a2497SKuninori Morimoto 			uc->value.integer.value[i] = cfg->val[i];
1744170a2497SKuninori Morimoto 
1745170a2497SKuninori Morimoto 	return 0;
1746170a2497SKuninori Morimoto }
1747170a2497SKuninori Morimoto 
rsnd_kctrl_put(struct snd_kcontrol * kctrl,struct snd_ctl_elem_value * uc)1748170a2497SKuninori Morimoto static int rsnd_kctrl_put(struct snd_kcontrol *kctrl,
1749170a2497SKuninori Morimoto 			  struct snd_ctl_elem_value *uc)
1750170a2497SKuninori Morimoto {
175116d44989SKuninori Morimoto 	struct rsnd_kctrl_cfg *cfg = snd_kcontrol_chip(kctrl);
1752170a2497SKuninori Morimoto 	int i, change = 0;
1753170a2497SKuninori Morimoto 
1754f0b04d8bSKuninori Morimoto 	if (!cfg->accept(cfg->io))
1755f0b04d8bSKuninori Morimoto 		return 0;
1756f0b04d8bSKuninori Morimoto 
1757170a2497SKuninori Morimoto 	for (i = 0; i < cfg->size; i++) {
1758170a2497SKuninori Morimoto 		if (cfg->texts) {
1759170a2497SKuninori Morimoto 			change |= (uc->value.enumerated.item[i] != cfg->val[i]);
1760170a2497SKuninori Morimoto 			cfg->val[i] = uc->value.enumerated.item[i];
1761170a2497SKuninori Morimoto 		} else {
1762170a2497SKuninori Morimoto 			change |= (uc->value.integer.value[i] != cfg->val[i]);
1763170a2497SKuninori Morimoto 			cfg->val[i] = uc->value.integer.value[i];
1764170a2497SKuninori Morimoto 		}
1765170a2497SKuninori Morimoto 	}
1766170a2497SKuninori Morimoto 
1767d7289565SKuninori Morimoto 	if (change && cfg->update)
176816d44989SKuninori Morimoto 		cfg->update(cfg->io, cfg->mod);
1769170a2497SKuninori Morimoto 
1770170a2497SKuninori Morimoto 	return change;
1771170a2497SKuninori Morimoto }
1772170a2497SKuninori Morimoto 
rsnd_kctrl_accept_anytime(struct rsnd_dai_stream * io)1773f0b04d8bSKuninori Morimoto int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io)
1774f0b04d8bSKuninori Morimoto {
1775f0b04d8bSKuninori Morimoto 	return 1;
1776f0b04d8bSKuninori Morimoto }
1777f0b04d8bSKuninori Morimoto 
rsnd_kctrl_accept_runtime(struct rsnd_dai_stream * io)177832973dcfSKuninori Morimoto struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg)
177932973dcfSKuninori Morimoto {
178032973dcfSKuninori Morimoto 	cfg->cfg.val = cfg->val;
178132973dcfSKuninori Morimoto 
178232973dcfSKuninori Morimoto 	return &cfg->cfg;
178332973dcfSKuninori Morimoto }
178432973dcfSKuninori Morimoto 
178532973dcfSKuninori Morimoto struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg)
178632973dcfSKuninori Morimoto {
178732973dcfSKuninori Morimoto 	cfg->cfg.val = &cfg->val;
178832973dcfSKuninori Morimoto 
178932973dcfSKuninori Morimoto 	return &cfg->cfg;
179032973dcfSKuninori Morimoto }
179132973dcfSKuninori Morimoto 
rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m * cfg)1792f3c26ac6SKuninori Morimoto const char * const volume_ramp_rate[] = {
1793f3c26ac6SKuninori Morimoto 	"128 dB/1 step",	 /* 00000 */
1794f3c26ac6SKuninori Morimoto 	"64 dB/1 step",		 /* 00001 */
1795f3c26ac6SKuninori Morimoto 	"32 dB/1 step",		 /* 00010 */
1796f3c26ac6SKuninori Morimoto 	"16 dB/1 step",		 /* 00011 */
1797f3c26ac6SKuninori Morimoto 	"8 dB/1 step",		 /* 00100 */
1798f3c26ac6SKuninori Morimoto 	"4 dB/1 step",		 /* 00101 */
1799f3c26ac6SKuninori Morimoto 	"2 dB/1 step",		 /* 00110 */
1800f3c26ac6SKuninori Morimoto 	"1 dB/1 step",		 /* 00111 */
1801f3c26ac6SKuninori Morimoto 	"0.5 dB/1 step",	 /* 01000 */
1802f3c26ac6SKuninori Morimoto 	"0.25 dB/1 step",	 /* 01001 */
18033e3c9ee1SKuninori Morimoto 	"0.125 dB/1 step",	 /* 01010 = VOLUME_RAMP_MAX_MIX */
1804f3c26ac6SKuninori Morimoto 	"0.125 dB/2 steps",	 /* 01011 */
1805f3c26ac6SKuninori Morimoto 	"0.125 dB/4 steps",	 /* 01100 */
1806f3c26ac6SKuninori Morimoto 	"0.125 dB/8 steps",	 /* 01101 */
1807f3c26ac6SKuninori Morimoto 	"0.125 dB/16 steps",	 /* 01110 */
1808f3c26ac6SKuninori Morimoto 	"0.125 dB/32 steps",	 /* 01111 */
1809f3c26ac6SKuninori Morimoto 	"0.125 dB/64 steps",	 /* 10000 */
1810f3c26ac6SKuninori Morimoto 	"0.125 dB/128 steps",	 /* 10001 */
1811f3c26ac6SKuninori Morimoto 	"0.125 dB/256 steps",	 /* 10010 */
1812f3c26ac6SKuninori Morimoto 	"0.125 dB/512 steps",	 /* 10011 */
1813f3c26ac6SKuninori Morimoto 	"0.125 dB/1024 steps",	 /* 10100 */
1814f3c26ac6SKuninori Morimoto 	"0.125 dB/2048 steps",	 /* 10101 */
1815f3c26ac6SKuninori Morimoto 	"0.125 dB/4096 steps",	 /* 10110 */
1816f3c26ac6SKuninori Morimoto 	"0.125 dB/8192 steps",	 /* 10111 = VOLUME_RAMP_MAX_DVC */
1817f3c26ac6SKuninori Morimoto };
1818f3c26ac6SKuninori Morimoto 
181932973dcfSKuninori Morimoto int rsnd_kctrl_new(struct rsnd_mod *mod,
1820b65a7cccSKuninori Morimoto 		   struct rsnd_dai_stream *io,
1821170a2497SKuninori Morimoto 		   struct snd_soc_pcm_runtime *rtd,
1822170a2497SKuninori Morimoto 		   const unsigned char *name,
1823f0b04d8bSKuninori Morimoto 		   int (*accept)(struct rsnd_dai_stream *io),
1824b65a7cccSKuninori Morimoto 		   void (*update)(struct rsnd_dai_stream *io,
182532973dcfSKuninori Morimoto 				  struct rsnd_mod *mod),
182632973dcfSKuninori Morimoto 		   struct rsnd_kctrl_cfg *cfg,
182732973dcfSKuninori Morimoto 		   const char * const *texts,
182832973dcfSKuninori Morimoto 		   int size,
182932973dcfSKuninori Morimoto 		   u32 max)
1830170a2497SKuninori Morimoto {
1831170a2497SKuninori Morimoto 	struct snd_card *card = rtd->card->snd_card;
1832170a2497SKuninori Morimoto 	struct snd_kcontrol *kctrl;
rsnd_kctrl_new(struct rsnd_mod * mod,struct rsnd_dai_stream * io,struct snd_soc_pcm_runtime * rtd,const unsigned char * name,int (* accept)(struct rsnd_dai_stream * io),void (* update)(struct rsnd_dai_stream * io,struct rsnd_mod * mod),struct rsnd_kctrl_cfg * cfg,const char * const * texts,int size,u32 max)1833170a2497SKuninori Morimoto 	struct snd_kcontrol_new knew = {
1834170a2497SKuninori Morimoto 		.iface		= SNDRV_CTL_ELEM_IFACE_MIXER,
1835170a2497SKuninori Morimoto 		.name		= name,
1836170a2497SKuninori Morimoto 		.info		= rsnd_kctrl_info,
18371a497983SMengdong Lin 		.index		= rtd->num,
1838170a2497SKuninori Morimoto 		.get		= rsnd_kctrl_get,
1839170a2497SKuninori Morimoto 		.put		= rsnd_kctrl_put,
1840170a2497SKuninori Morimoto 	};
1841170a2497SKuninori Morimoto 	int ret;
1842170a2497SKuninori Morimoto 
18439c698e84SKuninori Morimoto 	/*
18447aea8a9dSKuninori Morimoto 	 * 1) Avoid duplicate register for DVC with MIX case
18457aea8a9dSKuninori Morimoto 	 * 2) Allow duplicate register for MIX
18467aea8a9dSKuninori Morimoto 	 * 3) re-register if card was rebinded
18479c698e84SKuninori Morimoto 	 */
18489c698e84SKuninori Morimoto 	list_for_each_entry(kctrl, &card->controls, list) {
18499c698e84SKuninori Morimoto 		struct rsnd_kctrl_cfg *c = kctrl->private_data;
18509c698e84SKuninori Morimoto 
18517aea8a9dSKuninori Morimoto 		if (c == cfg)
18529c698e84SKuninori Morimoto 			return 0;
18539c698e84SKuninori Morimoto 	}
18549c698e84SKuninori Morimoto 
185532973dcfSKuninori Morimoto 	if (size > RSND_MAX_CHANNELS)
185632973dcfSKuninori Morimoto 		return -EINVAL;
185732973dcfSKuninori Morimoto 
185816d44989SKuninori Morimoto 	kctrl = snd_ctl_new1(&knew, cfg);
1859170a2497SKuninori Morimoto 	if (!kctrl)
1860170a2497SKuninori Morimoto 		return -ENOMEM;
1861170a2497SKuninori Morimoto 
1862170a2497SKuninori Morimoto 	ret = snd_ctl_add(card, kctrl);
18630ea617a2SColin Ian King 	if (ret < 0)
1864170a2497SKuninori Morimoto 		return ret;
1865170a2497SKuninori Morimoto 
186632973dcfSKuninori Morimoto 	cfg->texts	= texts;
186732973dcfSKuninori Morimoto 	cfg->max	= max;
186832973dcfSKuninori Morimoto 	cfg->size	= size;
1869f0b04d8bSKuninori Morimoto 	cfg->accept	= accept;
1870170a2497SKuninori Morimoto 	cfg->update	= update;
1871d1f83d6eSKuninori Morimoto 	cfg->card	= card;
1872d1f83d6eSKuninori Morimoto 	cfg->kctrl	= kctrl;
1873b65a7cccSKuninori Morimoto 	cfg->io		= io;
187416d44989SKuninori Morimoto 	cfg->mod	= mod;
1875170a2497SKuninori Morimoto 
1876170a2497SKuninori Morimoto 	return 0;
1877170a2497SKuninori Morimoto }
1878170a2497SKuninori Morimoto 
1879170a2497SKuninori Morimoto /*
1880019ea01bSKuninori Morimoto  *		snd_soc_component
18811536a968SKuninori Morimoto  */
1882019ea01bSKuninori Morimoto static const struct snd_soc_component_driver rsnd_soc_component = {
18831536a968SKuninori Morimoto 	.name			= "rsnd",
18841f9c82b5SKuninori Morimoto 	.probe			= rsnd_debugfs_probe,
18859dcefa72SKuninori Morimoto 	.hw_params		= rsnd_hw_params,
18869dcefa72SKuninori Morimoto 	.hw_free		= rsnd_hw_free,
18879dcefa72SKuninori Morimoto 	.pointer		= rsnd_pointer,
1888f712ff57SCharles Keepax 	.legacy_dai_naming	= 1,
18891536a968SKuninori Morimoto };
18901536a968SKuninori Morimoto 
1891d3a76823SKuninori Morimoto static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
1892f708d944SKuninori Morimoto 				       struct rsnd_dai_stream *io)
1893d3a76823SKuninori Morimoto {
1894d3a76823SKuninori Morimoto 	int ret;
1895d3a76823SKuninori Morimoto 
1896690602fcSKuninori Morimoto 	ret = rsnd_dai_call(probe, io, priv);
1897d3a76823SKuninori Morimoto 	if (ret == -EAGAIN) {
189848d58281SKuninori Morimoto 		struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
18999b87bfb2SKuninori Morimoto 		struct rsnd_mod *mod;
190048d58281SKuninori Morimoto 		int i;
190148d58281SKuninori Morimoto 
1902d3a76823SKuninori Morimoto 		/*
1903d3a76823SKuninori Morimoto 		 * Fallback to PIO mode
1904d3a76823SKuninori Morimoto 		 */
rsnd_rdai_continuance_probe(struct rsnd_priv * priv,struct rsnd_dai_stream * io)1905d3a76823SKuninori Morimoto 
1906d3a76823SKuninori Morimoto 		/*
1907d3a76823SKuninori Morimoto 		 * call "remove" for SSI/SRC/DVC
1908d3a76823SKuninori Morimoto 		 * SSI will be switch to PIO mode if it was DMA mode
1909d3a76823SKuninori Morimoto 		 * see
1910d3a76823SKuninori Morimoto 		 *	rsnd_dma_init()
191197463e19SKuninori Morimoto 		 *	rsnd_ssi_fallback()
1912d3a76823SKuninori Morimoto 		 */
1913690602fcSKuninori Morimoto 		rsnd_dai_call(remove, io, priv);
1914d3a76823SKuninori Morimoto 
1915d3a76823SKuninori Morimoto 		/*
191648d58281SKuninori Morimoto 		 * remove all mod from io
191748d58281SKuninori Morimoto 		 * and, re connect ssi
1918d3a76823SKuninori Morimoto 		 */
19199b87bfb2SKuninori Morimoto 		for_each_rsnd_mod(i, mod, io)
19209b87bfb2SKuninori Morimoto 			rsnd_dai_disconnect(mod, io, i);
192148d58281SKuninori Morimoto 		rsnd_dai_connect(ssi_mod, io, RSND_MOD_SSI);
1922d3a76823SKuninori Morimoto 
1923d3a76823SKuninori Morimoto 		/*
192497463e19SKuninori Morimoto 		 * fallback
192597463e19SKuninori Morimoto 		 */
1926690602fcSKuninori Morimoto 		rsnd_dai_call(fallback, io, priv);
192797463e19SKuninori Morimoto 
192897463e19SKuninori Morimoto 		/*
1929d3a76823SKuninori Morimoto 		 * retry to "probe".
1930d3a76823SKuninori Morimoto 		 * DAI has SSI which is PIO mode only now.
1931d3a76823SKuninori Morimoto 		 */
1932690602fcSKuninori Morimoto 		ret = rsnd_dai_call(probe, io, priv);
1933d3a76823SKuninori Morimoto 	}
1934d3a76823SKuninori Morimoto 
1935d3a76823SKuninori Morimoto 	return ret;
1936d3a76823SKuninori Morimoto }
1937d3a76823SKuninori Morimoto 
19381536a968SKuninori Morimoto /*
19391536a968SKuninori Morimoto  *	rsnd probe
19401536a968SKuninori Morimoto  */
19411536a968SKuninori Morimoto static int rsnd_probe(struct platform_device *pdev)
19421536a968SKuninori Morimoto {
19431536a968SKuninori Morimoto 	struct rsnd_priv *priv;
19441536a968SKuninori Morimoto 	struct device *dev = &pdev->dev;
19457681f6acSKuninori Morimoto 	struct rsnd_dai *rdai;
19462ea6b074SKuninori Morimoto 	int (*probe_func[])(struct rsnd_priv *priv) = {
1947d1ac970fSKuninori Morimoto 		rsnd_gen_probe,
1948288f392eSKuninori Morimoto 		rsnd_dma_probe,
1949d1ac970fSKuninori Morimoto 		rsnd_ssi_probe,
1950c7f69ab5SKuninori Morimoto 		rsnd_ssiu_probe,
1951ba9c949fSKuninori Morimoto 		rsnd_src_probe,
19529269e3c3SKuninori Morimoto 		rsnd_ctu_probe,
195370fb1052SKuninori Morimoto 		rsnd_mix_probe,
1954bff58ea4SKuninori Morimoto 		rsnd_dvc_probe,
rsnd_probe(struct platform_device * pdev)19551b2ca0adSKuninori Morimoto 		rsnd_cmd_probe,
1956d1ac970fSKuninori Morimoto 		rsnd_adg_probe,
1957d1ac970fSKuninori Morimoto 		rsnd_dai_probe,
1958d1ac970fSKuninori Morimoto 	};
1959d1ac970fSKuninori Morimoto 	int ret, i;
1960547b02f7SKuninori Morimoto 	int ci;
19611536a968SKuninori Morimoto 
19621536a968SKuninori Morimoto 	/*
19631536a968SKuninori Morimoto 	 *	init priv data
19641536a968SKuninori Morimoto 	 */
19651536a968SKuninori Morimoto 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
19660d7820d0SMarkus Elfring 	if (!priv)
19671536a968SKuninori Morimoto 		return -ENODEV;
19681536a968SKuninori Morimoto 
19699f464f8eSKuninori Morimoto 	priv->pdev	= pdev;
19706d8044b4SWolfram Sang 	priv->flags	= (unsigned long)of_device_get_match_data(dev);
19711536a968SKuninori Morimoto 	spin_lock_init(&priv->lock);
19721536a968SKuninori Morimoto 
19731536a968SKuninori Morimoto 	/*
19741536a968SKuninori Morimoto 	 *	init each module
19751536a968SKuninori Morimoto 	 */
1976d1ac970fSKuninori Morimoto 	for (i = 0; i < ARRAY_SIZE(probe_func); i++) {
19772ea6b074SKuninori Morimoto 		ret = probe_func[i](priv);
1978106d2effSKuninori Morimoto 		if (ret)
19793337744aSKuninori Morimoto 			return ret;
1980d1ac970fSKuninori Morimoto 	}
19814b4dab82SKuninori Morimoto 
19827681f6acSKuninori Morimoto 	for_each_rsnd_dai(rdai, priv, i) {
1983f708d944SKuninori Morimoto 		ret = rsnd_rdai_continuance_probe(priv, &rdai->playback);
19847681f6acSKuninori Morimoto 		if (ret)
1985d62a3dcdSKuninori Morimoto 			goto exit_snd_probe;
19861536a968SKuninori Morimoto 
1987f708d944SKuninori Morimoto 		ret = rsnd_rdai_continuance_probe(priv, &rdai->capture);
19887681f6acSKuninori Morimoto 		if (ret)
1989d62a3dcdSKuninori Morimoto 			goto exit_snd_probe;
19907681f6acSKuninori Morimoto 	}
19911536a968SKuninori Morimoto 
19920b1f6ec7SKuninori Morimoto 	dev_set_drvdata(dev, priv);
19930b1f6ec7SKuninori Morimoto 
19941536a968SKuninori Morimoto 	/*
19951536a968SKuninori Morimoto 	 *	asoc register
19961536a968SKuninori Morimoto 	 */
1997547b02f7SKuninori Morimoto 	ci = 0;
1998547b02f7SKuninori Morimoto 	for (i = 0; priv->component_dais[i] > 0; i++) {
1999547b02f7SKuninori Morimoto 		int nr = priv->component_dais[i];
2000547b02f7SKuninori Morimoto 
2001019ea01bSKuninori Morimoto 		ret = devm_snd_soc_register_component(dev, &rsnd_soc_component,
2002547b02f7SKuninori Morimoto 						      priv->daidrv + ci, nr);
20031536a968SKuninori Morimoto 		if (ret < 0) {
2004547b02f7SKuninori Morimoto 			dev_err(dev, "cannot snd component register\n");
2005019ea01bSKuninori Morimoto 			goto exit_snd_probe;
20061536a968SKuninori Morimoto 		}
20071536a968SKuninori Morimoto 
2008547b02f7SKuninori Morimoto 		ci += nr;
2009547b02f7SKuninori Morimoto 	}
2010547b02f7SKuninori Morimoto 
20111536a968SKuninori Morimoto 	pm_runtime_enable(dev);
20121536a968SKuninori Morimoto 
20131536a968SKuninori Morimoto 	dev_info(dev, "probed\n");
20141536a968SKuninori Morimoto 	return ret;
20151536a968SKuninori Morimoto 
2016d62a3dcdSKuninori Morimoto exit_snd_probe:
2017d62a3dcdSKuninori Morimoto 	for_each_rsnd_dai(rdai, priv, i) {
2018690602fcSKuninori Morimoto 		rsnd_dai_call(remove, &rdai->playback, priv);
2019690602fcSKuninori Morimoto 		rsnd_dai_call(remove, &rdai->capture, priv);
2020d62a3dcdSKuninori Morimoto 	}
20211536a968SKuninori Morimoto 
20226c92d5a2SKuninori Morimoto 	/*
20236c92d5a2SKuninori Morimoto 	 * adg is very special mod which can't use rsnd_dai_call(remove),
20246c92d5a2SKuninori Morimoto 	 * and it registers ADG clock on probe.
20256c92d5a2SKuninori Morimoto 	 * It should be unregister if probe failed.
20266c92d5a2SKuninori Morimoto 	 * Mainly it is assuming -EPROBE_DEFER case
20276c92d5a2SKuninori Morimoto 	 */
20286c92d5a2SKuninori Morimoto 	rsnd_adg_remove(priv);
20296c92d5a2SKuninori Morimoto 
20301536a968SKuninori Morimoto 	return ret;
20311536a968SKuninori Morimoto }
20321536a968SKuninori Morimoto 
20335310f0a3SUwe Kleine-König static void rsnd_remove(struct platform_device *pdev)
20341536a968SKuninori Morimoto {
20351536a968SKuninori Morimoto 	struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev);
20367681f6acSKuninori Morimoto 	struct rsnd_dai *rdai;
20372ea6b074SKuninori Morimoto 	void (*remove_func[])(struct rsnd_priv *priv) = {
20382f78dd7fSKuninori Morimoto 		rsnd_ssi_remove,
2039c7f69ab5SKuninori Morimoto 		rsnd_ssiu_remove,
20402f78dd7fSKuninori Morimoto 		rsnd_src_remove,
20419269e3c3SKuninori Morimoto 		rsnd_ctu_remove,
204270fb1052SKuninori Morimoto 		rsnd_mix_remove,
20432f78dd7fSKuninori Morimoto 		rsnd_dvc_remove,
20441b2ca0adSKuninori Morimoto 		rsnd_cmd_remove,
204568a55024SKuninori Morimoto 		rsnd_adg_remove,
20462f78dd7fSKuninori Morimoto 	};
rsnd_remove(struct platform_device * pdev)2047e57297fcSUwe Kleine-König 	int i;
20481536a968SKuninori Morimoto 
20491536a968SKuninori Morimoto 	pm_runtime_disable(&pdev->dev);
20501536a968SKuninori Morimoto 
20517681f6acSKuninori Morimoto 	for_each_rsnd_dai(rdai, priv, i) {
2052e57297fcSUwe Kleine-König 		int ret;
2053e57297fcSUwe Kleine-König 
2054e57297fcSUwe Kleine-König 		ret = rsnd_dai_call(remove, &rdai->playback, priv);
2055e57297fcSUwe Kleine-König 		if (ret)
2056e57297fcSUwe Kleine-König 			dev_warn(&pdev->dev, "Failed to remove playback dai #%d\n", i);
2057e57297fcSUwe Kleine-König 
2058e57297fcSUwe Kleine-König 		ret = rsnd_dai_call(remove, &rdai->capture, priv);
2059e57297fcSUwe Kleine-König 		if (ret)
2060e57297fcSUwe Kleine-König 			dev_warn(&pdev->dev, "Failed to remove capture dai #%d\n", i);
20617681f6acSKuninori Morimoto 	}
20621536a968SKuninori Morimoto 
20632f78dd7fSKuninori Morimoto 	for (i = 0; i < ARRAY_SIZE(remove_func); i++)
20642ea6b074SKuninori Morimoto 		remove_func[i](priv);
20651536a968SKuninori Morimoto }
20661536a968SKuninori Morimoto 
20676f542703SArnd Bergmann static int __maybe_unused rsnd_suspend(struct device *dev)
2068c2d31718SKuninori Morimoto {
2069c2d31718SKuninori Morimoto 	struct rsnd_priv *priv = dev_get_drvdata(dev);
2070c2d31718SKuninori Morimoto 
2071c2d31718SKuninori Morimoto 	rsnd_adg_clk_disable(priv);
2072c2d31718SKuninori Morimoto 
2073c2d31718SKuninori Morimoto 	return 0;
2074c2d31718SKuninori Morimoto }
2075c2d31718SKuninori Morimoto 
20766f542703SArnd Bergmann static int __maybe_unused rsnd_resume(struct device *dev)
2077c2d31718SKuninori Morimoto {
2078c2d31718SKuninori Morimoto 	struct rsnd_priv *priv = dev_get_drvdata(dev);
2079c2d31718SKuninori Morimoto 
2080c2d31718SKuninori Morimoto 	rsnd_adg_clk_enable(priv);
rsnd_suspend(struct device * dev)2081c2d31718SKuninori Morimoto 
2082c2d31718SKuninori Morimoto 	return 0;
2083c2d31718SKuninori Morimoto }
2084c2d31718SKuninori Morimoto 
208549ebf13bSArvind Yadav static const struct dev_pm_ops rsnd_pm_ops = {
2086f8a9a29cSNikita Yushchenko 	SET_SYSTEM_SLEEP_PM_OPS(rsnd_suspend, rsnd_resume)
2087c2d31718SKuninori Morimoto };
2088c2d31718SKuninori Morimoto 
20891536a968SKuninori Morimoto static struct platform_driver rsnd_driver = {
rsnd_resume(struct device * dev)20901536a968SKuninori Morimoto 	.driver	= {
20911536a968SKuninori Morimoto 		.name	= "rcar_sound",
2092c2d31718SKuninori Morimoto 		.pm	= &rsnd_pm_ops,
209390e8e50fSKuninori Morimoto 		.of_match_table = rsnd_of_match,
20941536a968SKuninori Morimoto 	},
20951536a968SKuninori Morimoto 	.probe		= rsnd_probe,
20965310f0a3SUwe Kleine-König 	.remove_new	= rsnd_remove,
20971536a968SKuninori Morimoto };
20981536a968SKuninori Morimoto module_platform_driver(rsnd_driver);
20991536a968SKuninori Morimoto 
21001e0edd4dSKuninori Morimoto MODULE_LICENSE("GPL v2");
21011536a968SKuninori Morimoto MODULE_DESCRIPTION("Renesas R-Car audio driver");
21021536a968SKuninori Morimoto MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
21031536a968SKuninori Morimoto MODULE_ALIAS("platform:rcar-pcm-audio");
2104