aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/sh/rcar/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sh/rcar/core.c')
-rw-r--r--sound/soc/sh/rcar/core.c160
1 files changed, 119 insertions, 41 deletions
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 02b4b085b8d7..3351a701c60e 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -138,12 +138,22 @@ struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io,
138 return mod->ops->dma_req(io, mod); 138 return mod->ops->dma_req(io, mod);
139} 139}
140 140
141u32 *rsnd_mod_get_status(struct rsnd_dai_stream *io,
142 struct rsnd_mod *mod,
143 enum rsnd_mod_type type)
144{
145 return &mod->status;
146}
147
141int rsnd_mod_init(struct rsnd_priv *priv, 148int rsnd_mod_init(struct rsnd_priv *priv,
142 struct rsnd_mod *mod, 149 struct rsnd_mod *mod,
143 struct rsnd_mod_ops *ops, 150 struct rsnd_mod_ops *ops,
144 struct clk *clk, 151 struct clk *clk,
145 enum rsnd_mod_type type, 152 u32* (*get_status)(struct rsnd_dai_stream *io,
146 int id) 153 struct rsnd_mod *mod,
154 enum rsnd_mod_type type),
155 enum rsnd_mod_type type,
156 int id)
147{ 157{
148 int ret = clk_prepare(clk); 158 int ret = clk_prepare(clk);
149 159
@@ -155,6 +165,7 @@ int rsnd_mod_init(struct rsnd_priv *priv,
155 mod->type = type; 165 mod->type = type;
156 mod->clk = clk; 166 mod->clk = clk;
157 mod->priv = priv; 167 mod->priv = priv;
168 mod->get_status = get_status;
158 169
159 return ret; 170 return ret;
160} 171}
@@ -163,6 +174,7 @@ void rsnd_mod_quit(struct rsnd_mod *mod)
163{ 174{
164 if (mod->clk) 175 if (mod->clk)
165 clk_unprepare(mod->clk); 176 clk_unprepare(mod->clk);
177 mod->clk = NULL;
166} 178}
167 179
168void rsnd_mod_interrupt(struct rsnd_mod *mod, 180void rsnd_mod_interrupt(struct rsnd_mod *mod,
@@ -212,13 +224,36 @@ int rsnd_get_slot_num(struct rsnd_dai_stream *io)
212 return rdai->slots_num; 224 return rdai->slots_num;
213} 225}
214 226
215int rsnd_get_slot_width(struct rsnd_dai_stream *io) 227int rsnd_runtime_channel_original(struct rsnd_dai_stream *io)
216{ 228{
217 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 229 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
218 int chan = runtime->channels;
219 230
220 /* Multi channel Mode */ 231 return runtime->channels;
221 if (rsnd_ssi_multi_slaves(io)) 232}
233
234int rsnd_runtime_channel_after_ctu(struct rsnd_dai_stream *io)
235{
236 int chan = rsnd_runtime_channel_original(io);
237 struct rsnd_mod *ctu_mod = rsnd_io_to_mod_ctu(io);
238
239 if (ctu_mod) {
240 u32 converted_chan = rsnd_ctu_converted_channel(ctu_mod);
241
242 if (converted_chan)
243 return converted_chan;
244 }
245
246 return chan;
247}
248
249int rsnd_runtime_channel_for_ssi(struct rsnd_dai_stream *io)
250{
251 int chan = rsnd_io_is_play(io) ?
252 rsnd_runtime_channel_after_ctu(io) :
253 rsnd_runtime_channel_original(io);
254
255 /* Use Multi SSI */
256 if (rsnd_runtime_is_ssi_multi(io))
222 chan /= rsnd_get_slot_num(io); 257 chan /= rsnd_get_slot_num(io);
223 258
224 /* TDM Extend Mode needs 8ch */ 259 /* TDM Extend Mode needs 8ch */
@@ -228,6 +263,21 @@ int rsnd_get_slot_width(struct rsnd_dai_stream *io)
228 return chan; 263 return chan;
229} 264}
230 265
266int rsnd_runtime_is_ssi_multi(struct rsnd_dai_stream *io)
267{
268 int slots = rsnd_get_slot_num(io);
269 int chan = rsnd_io_is_play(io) ?
270 rsnd_runtime_channel_after_ctu(io) :
271 rsnd_runtime_channel_original(io);
272
273 return (chan >= 6) && (slots > 1);
274}
275
276int rsnd_runtime_is_ssi_tdm(struct rsnd_dai_stream *io)
277{
278 return rsnd_runtime_channel_for_ssi(io) >= 6;
279}
280
231/* 281/*
232 * ADINR function 282 * ADINR function
233 */ 283 */
@@ -249,29 +299,6 @@ u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
249 return 0; 299 return 0;
250} 300}
251 301
252u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
253{
254 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
255 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
256 struct device *dev = rsnd_priv_to_dev(priv);
257 u32 chan = runtime->channels;
258
259 switch (chan) {
260 case 1:
261 case 2:
262 case 4:
263 case 6:
264 case 8:
265 break;
266 default:
267 dev_warn(dev, "not supported channel\n");
268 chan = 0;
269 break;
270 }
271
272 return chan;
273}
274
275/* 302/*
276 * DALIGN function 303 * DALIGN function
277 */ 304 */
@@ -324,31 +351,73 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
324 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ 351 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \
325 struct rsnd_mod *mod = (io)->mod[idx]; \ 352 struct rsnd_mod *mod = (io)->mod[idx]; \
326 struct device *dev = rsnd_priv_to_dev(priv); \ 353 struct device *dev = rsnd_priv_to_dev(priv); \
327 u32 *status = (io)->mod_status + idx; \ 354 u32 *status = mod->get_status(io, mod, idx); \
328 u32 mask = 0xF << __rsnd_mod_shift_##func; \ 355 u32 mask = 0xF << __rsnd_mod_shift_##func; \
329 u8 val = (*status >> __rsnd_mod_shift_##func) & 0xF; \ 356 u8 val = (*status >> __rsnd_mod_shift_##func) & 0xF; \
330 u8 add = ((val + __rsnd_mod_add_##func) & 0xF); \ 357 u8 add = ((val + __rsnd_mod_add_##func) & 0xF); \
331 int ret = 0; \ 358 int ret = 0; \
332 int call = (val == __rsnd_mod_call_##func) && (mod)->ops->func; \ 359 int call = (val == __rsnd_mod_call_##func) && (mod)->ops->func; \
333 *status = (*status & ~mask) + \ 360 if (add == 0xF) \
334 (add << __rsnd_mod_shift_##func); \ 361 call = 0; \
362 else \
363 *status = (*status & ~mask) + \
364 (add << __rsnd_mod_shift_##func); \
335 dev_dbg(dev, "%s[%d]\t0x%08x %s\n", \ 365 dev_dbg(dev, "%s[%d]\t0x%08x %s\n", \
336 rsnd_mod_name(mod), rsnd_mod_id(mod), \ 366 rsnd_mod_name(mod), rsnd_mod_id(mod), \
337 *status, call ? #func : ""); \ 367 *status, call ? #func : ""); \
338 if (call) \ 368 if (call) \
339 ret = (mod)->ops->func(mod, io, param); \ 369 ret = (mod)->ops->func(mod, io, param); \
370 if (ret) \
371 dev_dbg(dev, "%s[%d] : rsnd_mod_call error %d\n", \
372 rsnd_mod_name(mod), rsnd_mod_id(mod), ret); \
340 ret; \ 373 ret; \
341}) 374})
342 375
376static enum rsnd_mod_type rsnd_mod_sequence[][RSND_MOD_MAX] = {
377 {
378 /* CAPTURE */
379 RSND_MOD_AUDMAPP,
380 RSND_MOD_AUDMA,
381 RSND_MOD_DVC,
382 RSND_MOD_MIX,
383 RSND_MOD_CTU,
384 RSND_MOD_CMD,
385 RSND_MOD_SRC,
386 RSND_MOD_SSIU,
387 RSND_MOD_SSIM3,
388 RSND_MOD_SSIM2,
389 RSND_MOD_SSIM1,
390 RSND_MOD_SSIP,
391 RSND_MOD_SSI,
392 }, {
393 /* PLAYBACK */
394 RSND_MOD_AUDMAPP,
395 RSND_MOD_AUDMA,
396 RSND_MOD_SSIM3,
397 RSND_MOD_SSIM2,
398 RSND_MOD_SSIM1,
399 RSND_MOD_SSIP,
400 RSND_MOD_SSI,
401 RSND_MOD_SSIU,
402 RSND_MOD_DVC,
403 RSND_MOD_MIX,
404 RSND_MOD_CTU,
405 RSND_MOD_CMD,
406 RSND_MOD_SRC,
407 },
408};
409
343#define rsnd_dai_call(fn, io, param...) \ 410#define rsnd_dai_call(fn, io, param...) \
344({ \ 411({ \
345 struct rsnd_mod *mod; \ 412 struct rsnd_mod *mod; \
413 int type, is_play = rsnd_io_is_play(io); \
346 int ret = 0, i; \ 414 int ret = 0, i; \
347 for (i = 0; i < RSND_MOD_MAX; i++) { \ 415 for (i = 0; i < RSND_MOD_MAX; i++) { \
348 mod = (io)->mod[i]; \ 416 type = rsnd_mod_sequence[is_play][i]; \
417 mod = (io)->mod[type]; \
349 if (!mod) \ 418 if (!mod) \
350 continue; \ 419 continue; \
351 ret |= rsnd_mod_call(i, io, fn, param); \ 420 ret |= rsnd_mod_call(type, io, fn, param); \
352 } \ 421 } \
353 ret; \ 422 ret; \
354}) 423})
@@ -363,6 +432,9 @@ int rsnd_dai_connect(struct rsnd_mod *mod,
363 if (!mod) 432 if (!mod)
364 return -EIO; 433 return -EIO;
365 434
435 if (io->mod[type] == mod)
436 return 0;
437
366 if (io->mod[type]) 438 if (io->mod[type])
367 return -EINVAL; 439 return -EINVAL;
368 440
@@ -511,9 +583,16 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
511 ret = rsnd_dai_call(start, io, priv); 583 ret = rsnd_dai_call(start, io, priv);
512 if (ret < 0) 584 if (ret < 0)
513 goto dai_trigger_end; 585 goto dai_trigger_end;
586
587 ret = rsnd_dai_call(irq, io, priv, 1);
588 if (ret < 0)
589 goto dai_trigger_end;
590
514 break; 591 break;
515 case SNDRV_PCM_TRIGGER_STOP: 592 case SNDRV_PCM_TRIGGER_STOP:
516 ret = rsnd_dai_call(stop, io, priv); 593 ret = rsnd_dai_call(irq, io, priv, 0);
594
595 ret |= rsnd_dai_call(stop, io, priv);
517 596
518 ret |= rsnd_dai_call(quit, io, priv); 597 ret |= rsnd_dai_call(quit, io, priv);
519 598
@@ -863,7 +942,7 @@ static int rsnd_kctrl_put(struct snd_kcontrol *kctrl,
863 } 942 }
864 } 943 }
865 944
866 if (change) 945 if (change && cfg->update)
867 cfg->update(cfg->io, mod); 946 cfg->update(cfg->io, mod);
868 947
869 return change; 948 return change;
@@ -923,7 +1002,7 @@ int rsnd_kctrl_new_m(struct rsnd_mod *mod,
923 int ch_size, 1002 int ch_size,
924 u32 max) 1003 u32 max)
925{ 1004{
926 if (ch_size > RSND_DVC_CHANNELS) 1005 if (ch_size > RSND_MAX_CHANNELS)
927 return -EINVAL; 1006 return -EINVAL;
928 1007
929 _cfg->cfg.max = max; 1008 _cfg->cfg.max = max;
@@ -1055,7 +1134,6 @@ static int rsnd_probe(struct platform_device *pdev)
1055 struct rsnd_priv *priv; 1134 struct rsnd_priv *priv;
1056 struct device *dev = &pdev->dev; 1135 struct device *dev = &pdev->dev;
1057 struct rsnd_dai *rdai; 1136 struct rsnd_dai *rdai;
1058 const struct of_device_id *of_id = of_match_device(rsnd_of_match, dev);
1059 int (*probe_func[])(struct rsnd_priv *priv) = { 1137 int (*probe_func[])(struct rsnd_priv *priv) = {
1060 rsnd_gen_probe, 1138 rsnd_gen_probe,
1061 rsnd_dma_probe, 1139 rsnd_dma_probe,
@@ -1081,7 +1159,7 @@ static int rsnd_probe(struct platform_device *pdev)
1081 } 1159 }
1082 1160
1083 priv->pdev = pdev; 1161 priv->pdev = pdev;
1084 priv->flags = (unsigned long)of_id->data; 1162 priv->flags = (unsigned long)of_device_get_match_data(dev);
1085 spin_lock_init(&priv->lock); 1163 spin_lock_init(&priv->lock);
1086 1164
1087 /* 1165 /*