From 7c1c49995acc7b7bef69545b9b4bbee44e562d99 Mon Sep 17 00:00:00 2001 From: Sebastien Guiriec Date: Wed, 19 Oct 2011 16:44:36 -0700 Subject: ASoC: McPDM: Add check in order to reset the McPDM in case on COMMAND mode If McPDM enters in command mode the McPDM channels are reset in order to exit from command mode. The check will be done via delayed_work which is scheduled to be executed in 250ms periods. Change-Id: I4446b9a09e1a330993ea4b148877d70851800d0f Signed-off-by: Sebastien Guiriec Signed-off-by: Peter Ujfalusi --- sound/soc/omap/omap-abe-dsp.c | 3 ++- sound/soc/omap/omap-mcpdm.c | 29 ++++++++++++++++++++++++++++- sound/soc/omap/omap-mcpdm.h | 1 + 3 files changed, 31 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/omap/omap-abe-dsp.c b/sound/soc/omap/omap-abe-dsp.c index c90c228..b66db25 100644 --- a/sound/soc/omap/omap-abe-dsp.c +++ b/sound/soc/omap/omap-abe-dsp.c @@ -2664,7 +2664,8 @@ static int abe_probe(struct snd_soc_platform *platform) fw_data + sizeof(struct fw_header) + abe->hdr.coeff_size, abe->hdr.firmware_size); - ret = request_irq(abe->irq, abe_irq_handler, 0, "ABE", (void *)abe); + ret = request_threaded_irq(abe->irq, NULL, abe_irq_handler, + IRQF_ONESHOT, "ABE", (void *)abe); if (ret) { dev_err(platform->dev, "request for ABE IRQ %d failed %d\n", abe->irq, ret); diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 81e6866..d06f315 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -69,6 +69,7 @@ struct omap_mcpdm { struct mutex mutex; struct omap_mcpdm_platform_data *pdata; struct completion irq_completion; + struct delayed_work esd_work; struct abe *abe; struct omap_abe_port *dl_port; struct omap_abe_port *ul_port; @@ -397,7 +398,7 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, omap_mcpdm_set_offset(mcpdm); omap_mcpdm_open(mcpdm); - + schedule_delayed_work(&mcpdm->esd_work, msecs_to_jiffies(250)); out: mutex_unlock(&mcpdm->mutex); return err; @@ -427,6 +428,7 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, omap_mcpdm_stop(mcpdm); } + cancel_delayed_work_sync(&mcpdm->esd_work); omap_mcpdm_close(mcpdm); pm_runtime_put_sync(mcpdm->dev); @@ -542,6 +544,29 @@ static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, return 0; } +static void mcpdm_esd_work(struct work_struct *work) +{ + struct omap_mcpdm *mcpdm = container_of(work, struct omap_mcpdm, + esd_work.work); + + if (omap_mcpdm_read(mcpdm, MCPDM_STATUS)) { + if (mcpdm->abe_mode) { + omap_abe_port_disable(mcpdm->abe, mcpdm->dl_port); + omap_abe_port_disable(mcpdm->abe, mcpdm->ul_port); + udelay(250); + } + omap_mcpdm_stop(mcpdm); + + if (mcpdm->abe_mode) { + omap_abe_port_enable(mcpdm->abe, mcpdm->dl_port); + omap_abe_port_enable(mcpdm->abe, mcpdm->ul_port); + udelay(250); + } + omap_mcpdm_start(mcpdm); + } + schedule_delayed_work(&mcpdm->esd_work, msecs_to_jiffies(250)); +} + static struct snd_soc_dai_ops omap_mcpdm_dai_ops = { .startup = omap_mcpdm_dai_startup, .shutdown = omap_mcpdm_dai_shutdown, @@ -811,6 +836,8 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) goto err_dl; #endif + INIT_DELAYED_WORK(&mcpdm->esd_work, mcpdm_esd_work); + ret = snd_soc_register_dais(&pdev->dev, omap_mcpdm_dai, ARRAY_SIZE(omap_mcpdm_dai)); if (ret < 0) diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h index 79fdf30..3aa5011 100644 --- a/sound/soc/omap/omap-mcpdm.h +++ b/sound/soc/omap/omap-mcpdm.h @@ -42,6 +42,7 @@ #define MCPDM_FIFO_CTRL_DN 0x50 #define MCPDM_FIFO_CTRL_UP 0x54 #define MCPDM_DN_OFFSET 0x58 +#define MCPDM_STATUS 0x68 /* * MCPDM_IRQ bit fields -- cgit v1.1