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