aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorShengjiu Wang <b02247@freescale.com>2014-04-09 22:11:00 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:58:20 -0400
commit28d18f23fe7577f613ad8cfb4699bba26178304b (patch)
treeb06bedfb3390f703e2c8dad339715903550e26c6 /sound/soc/fsl
parent440fbeee5bba4d4356a392ff35fe262774c48ea1 (diff)
ENGR00307835-4 ASoC: fsl: implement ASRC P2P xrun handler
When ASRC P2P is working, it will check the xrun status of cpu dai in the back end bistream. then will do Whole route stop and restart. Signed-off-by: Shengjiu Wang <b02247@freescale.com>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl_asrc.c103
-rw-r--r--sound/soc/fsl/fsl_asrc.h3
2 files changed, 105 insertions, 1 deletions
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index d06dc3803b42..6c67719c7958 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -318,6 +318,23 @@ static int fsl_asrc_p2p_trigger(struct snd_pcm_substream *substream, int cmd,
318 return 0; 318 return 0;
319} 319}
320 320
321static int fsl_asrc_p2p_startup(struct snd_pcm_substream *substream,
322 struct snd_soc_dai *cpu_dai)
323{
324 struct fsl_asrc_p2p *asrc_p2p = snd_soc_dai_get_drvdata(cpu_dai);
325
326 asrc_p2p->substream[substream->stream] = substream;
327 return 0;
328}
329
330static void fsl_asrc_p2p_shutdown(struct snd_pcm_substream *substream,
331 struct snd_soc_dai *cpu_dai)
332{
333 struct fsl_asrc_p2p *asrc_p2p = snd_soc_dai_get_drvdata(cpu_dai);
334
335 asrc_p2p->substream[substream->stream] = NULL;
336}
337
321#define IMX_ASRC_RATES SNDRV_PCM_RATE_8000_192000 338#define IMX_ASRC_RATES SNDRV_PCM_RATE_8000_192000
322 339
323#define IMX_ASRC_FORMATS \ 340#define IMX_ASRC_FORMATS \
@@ -325,6 +342,8 @@ static int fsl_asrc_p2p_trigger(struct snd_pcm_substream *substream, int cmd,
325 SNDRV_PCM_FORMAT_S20_3LE) 342 SNDRV_PCM_FORMAT_S20_3LE)
326 343
327static struct snd_soc_dai_ops fsl_asrc_p2p_dai_ops = { 344static struct snd_soc_dai_ops fsl_asrc_p2p_dai_ops = {
345 .startup = fsl_asrc_p2p_startup,
346 .shutdown = fsl_asrc_p2p_shutdown,
328 .trigger = fsl_asrc_p2p_trigger, 347 .trigger = fsl_asrc_p2p_trigger,
329 .hw_params = fsl_asrc_p2p_hw_params, 348 .hw_params = fsl_asrc_p2p_hw_params,
330 .hw_free = fsl_asrc_p2p_hw_free, 349 .hw_free = fsl_asrc_p2p_hw_free,
@@ -363,6 +382,86 @@ static const struct snd_soc_component_driver fsl_asrc_p2p_component = {
363 .name = "fsl-asrc-p2p", 382 .name = "fsl-asrc-p2p",
364}; 383};
365 384
385static bool fsl_asrc_p2p_check_xrun(struct snd_pcm_substream *substream)
386{
387 struct snd_soc_pcm_runtime *rtd = substream->private_data;
388 struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
389 struct snd_pcm_substream *be_substream;
390 struct snd_soc_dpcm *dpcm;
391 int ret = 0;
392
393 /* find the be for this fe stream */
394 list_for_each_entry(dpcm, &rtd->dpcm[substream->stream].be_clients, list_be) {
395 struct snd_soc_pcm_runtime *be = dpcm->be;
396 struct snd_soc_dai *dai = be->cpu_dai;
397
398 if (dpcm->fe != rtd)
399 continue;
400
401 be_substream = snd_soc_dpcm_get_substream(be, substream->stream);
402 dma_params_be = snd_soc_dai_get_dma_data(dai, be_substream);
403 if (dma_params_be->check_xrun && dma_params_be->check_xrun(be_substream))
404 ret = 1;
405 }
406
407 return ret;
408}
409
410static int stop_lock_stream(struct snd_pcm_substream *substream)
411{
412 if (substream) {
413 snd_pcm_stream_lock_irq(substream);
414 if (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING)
415 substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
416 }
417 return 0;
418}
419
420static int start_unlock_stream(struct snd_pcm_substream *substream)
421{
422 if (substream) {
423 if (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING)
424 substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
425 snd_pcm_stream_unlock_irq(substream);
426 }
427 return 0;
428}
429
430static void fsl_asrc_p2p_reset(struct snd_pcm_substream *substream, bool stop)
431{
432 struct snd_soc_pcm_runtime *rtd = substream->private_data;
433 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
434 struct fsl_asrc_p2p *asrc_p2p = snd_soc_dai_get_drvdata(cpu_dai);
435 struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
436 struct snd_soc_dpcm *dpcm;
437 struct snd_pcm_substream *be_substream;
438
439 if (stop) {
440 stop_lock_stream(asrc_p2p->substream[0]);
441 stop_lock_stream(asrc_p2p->substream[1]);
442 }
443
444 /* find the be for this fe stream */
445 list_for_each_entry(dpcm, &rtd->dpcm[substream->stream].be_clients, list_be) {
446 struct snd_soc_pcm_runtime *be = dpcm->be;
447 struct snd_soc_dai *dai = be->cpu_dai;
448
449 if (dpcm->fe != rtd)
450 continue;
451
452 be_substream = snd_soc_dpcm_get_substream(be, substream->stream);
453 dma_params_be = snd_soc_dai_get_dma_data(dai, be_substream);
454 dma_params_be->device_reset(be_substream, 0);
455 break;
456 }
457
458 if (stop) {
459 start_unlock_stream(asrc_p2p->substream[1]);
460 start_unlock_stream(asrc_p2p->substream[0]);
461 }
462}
463
464
366/* 465/*
367 * This function will register the snd_soc_pcm_link drivers. 466 * This function will register the snd_soc_pcm_link drivers.
368 */ 467 */
@@ -429,6 +528,10 @@ static int fsl_asrc_p2p_probe(struct platform_device *pdev)
429 528
430 asrc_p2p->dma_params_tx.filter_data = &asrc_p2p->filter_data_tx; 529 asrc_p2p->dma_params_tx.filter_data = &asrc_p2p->filter_data_tx;
431 asrc_p2p->dma_params_rx.filter_data = &asrc_p2p->filter_data_rx; 530 asrc_p2p->dma_params_rx.filter_data = &asrc_p2p->filter_data_rx;
531 asrc_p2p->dma_params_tx.check_xrun = fsl_asrc_p2p_check_xrun;
532 asrc_p2p->dma_params_rx.check_xrun = fsl_asrc_p2p_check_xrun;
533 asrc_p2p->dma_params_tx.device_reset = fsl_asrc_p2p_reset;
534 asrc_p2p->dma_params_rx.device_reset = fsl_asrc_p2p_reset;
432 535
433 platform_set_drvdata(pdev, asrc_p2p); 536 platform_set_drvdata(pdev, asrc_p2p);
434 537
diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h
index c85ab8719697..81af098af520 100644
--- a/sound/soc/fsl/fsl_asrc.h
+++ b/sound/soc/fsl/fsl_asrc.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fsl_asrc.h - ALSA ASRC interface 2 * fsl_asrc.h - ALSA ASRC interface
3 * 3 *
4 * Copyright (C) 2013 Freescale Semiconductor, Inc. This file is licensed 4 * Copyright (C) 2013-2014 Freescale Semiconductor, Inc. This file is licensed
5 * under the terms of the GNU General Public License version 2. This 5 * under the terms of the GNU General Public License version 2. This
6 * program is licensed "as is" without any warranty of any kind, whether 6 * program is licensed "as is" without any warranty of any kind, whether
7 * express or implied. 7 * express or implied.
@@ -33,6 +33,7 @@ struct fsl_asrc_p2p {
33 struct snd_dmaengine_dai_dma_data dma_params_tx; 33 struct snd_dmaengine_dai_dma_data dma_params_tx;
34 struct imx_dma_data filter_data_tx; 34 struct imx_dma_data filter_data_tx;
35 struct imx_dma_data filter_data_rx; 35 struct imx_dma_data filter_data_rx;
36 struct snd_pcm_substream *substream[2];
36 37
37 struct dma_async_tx_descriptor *asrc_p2p_desc; 38 struct dma_async_tx_descriptor *asrc_p2p_desc;
38 struct dma_chan *asrc_p2p_dma_chan; 39 struct dma_chan *asrc_p2p_dma_chan;