From 07a252e76deabfe72c15d2a494a5e79168dbf088 Mon Sep 17 00:00:00 2001 From: Misael Lopez Cruz Date: Wed, 12 Jan 2011 17:40:04 -0600 Subject: [PATCH 38/60] ASoC: McPDM: Use mutex instead of spinlocks commit b06af35e466b994afc9854b33c0d11cf2bd05152 upstream Use mutex instead of spinlocks to allow protecting sleeping functions like pm_runtime calls. Change-Id: I373b340c6895bb3d8c7827a37a1a20406c461c6c Signed-off-by: Misael Lopez Cruz Integrated-by: Jingdong Lu --- sound/soc/omap/omap-mcpdm.c | 66 ++++++++++++++++++++++++++----------------- 1 files changed, 40 insertions(+), 26 deletions(-) diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 323606a..a976382 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -68,7 +68,7 @@ struct omap_mcpdm { struct delayed_work delayed_abe_work; #endif - spinlock_t lock; + struct mutex mutex; struct omap_mcpdm_platform_data *pdata; struct omap_mcpdm_link *downlink; struct omap_mcpdm_link *uplink; @@ -407,18 +407,13 @@ static int omap_mcpdm_request(struct omap_mcpdm *mcpdm) pm_runtime_get_sync(&pdev->dev); - spin_lock(&mcpdm->lock); - if (!mcpdm->free) { dev_err(mcpdm->dev, "McPDM interface is in use\n"); - spin_unlock(&mcpdm->lock); ret = -EBUSY; goto err; } mcpdm->free = 0; - spin_unlock(&mcpdm->lock); - /* Disable lines while request is ongoing */ omap_mcpdm_write(mcpdm, MCPDM_CTRL, 0x00); @@ -451,14 +446,11 @@ static void omap_mcpdm_free(struct omap_mcpdm *mcpdm) pdev = to_platform_device(mcpdm->dev); pdata = pdev->dev.platform_data; - spin_lock(&mcpdm->lock); if (mcpdm->free) { dev_err(mcpdm->dev, "McPDM interface is already free\n"); - spin_unlock(&mcpdm->lock); return; } mcpdm->free = 1; - spin_unlock(&mcpdm->lock); pm_runtime_put_sync(&pdev->dev); @@ -504,15 +496,23 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, dev_dbg(dai->dev, "%s: active %d\n", __func__, dai->active); + mutex_lock(&mcpdm->mutex); + /* make sure we stop any pre-existing shutdown */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) cancel_delayed_work(&mcpdm->delayed_work); if (!dai->active && mcpdm->free) { err = omap_mcpdm_request(mcpdm); + if (err) { + mutex_unlock(&mcpdm->mutex); + return err; + } omap_mcpdm_set_offset(mcpdm); } + mutex_unlock(&mcpdm->mutex); + return err; } @@ -523,10 +523,7 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, dev_dbg(dai->dev, "%s: active %d\n", __func__, dai->active); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - mcpdm->dl_active--; - else - mcpdm->ul_active--; + mutex_lock(&mcpdm->mutex); if (!dai->active) { if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) @@ -536,6 +533,7 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, msecs_to_jiffies(1000)); /* TODO: pdata ? */ } + mutex_unlock(&mcpdm->mutex); } /* work to delay McPDM shutdown */ @@ -544,11 +542,15 @@ static void playback_work(struct work_struct *work) struct omap_mcpdm *mcpdm = container_of(work, struct omap_mcpdm, delayed_work.work); + mutex_lock(&mcpdm->mutex); + if (!mcpdm->dl_active) omap_mcpdm_playback_close(mcpdm, mcpdm->downlink); if (!mcpdm->free && !mcpdm->dl_active && !mcpdm->ul_active) omap_mcpdm_free(mcpdm); + + mutex_unlock(&mcpdm->mutex); } static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, @@ -633,22 +635,31 @@ static int omap_mcpdm_abe_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); - int ret; + int ret = 0; + + mutex_lock(&mcpdm->mutex); /* make sure we stop any pre-existing shutdown */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { cancel_delayed_work(&mcpdm->delayed_abe_work); } - ret = omap_mcpdm_dai_startup(substream, dai); - if (ret < 0) - return ret; + if (!dai->active && mcpdm->free) { + ret = omap_mcpdm_request(mcpdm); + if (ret) { + mutex_unlock(&mcpdm->mutex); + return ret; + } + omap_mcpdm_set_offset(mcpdm); + } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) mcpdm->dl_active++; else mcpdm->ul_active++; + mutex_unlock(&mcpdm->mutex); + return ret; } @@ -659,6 +670,8 @@ static void omap_mcpdm_abe_dai_shutdown(struct snd_pcm_substream *substream, dev_dbg(dai->dev, "%s: active %d\n", __func__, dai->active); + mutex_lock(&mcpdm->mutex); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) mcpdm->dl_active--; else @@ -676,6 +689,8 @@ static void omap_mcpdm_abe_dai_shutdown(struct snd_pcm_substream *substream, msecs_to_jiffies(1000)); /* TODO: pdata ? */ } + mutex_unlock(&mcpdm->mutex); + } /* work to delay McPDM shutdown */ @@ -684,7 +699,7 @@ static void playback_abe_work(struct work_struct *work) struct omap_mcpdm *mcpdm = container_of(work, struct omap_mcpdm, delayed_abe_work.work); - spin_lock(&mcpdm->lock); + mutex_lock(&mcpdm->mutex); if (!mcpdm->dl_active && mcpdm->dn_channels) { abe_disable_data_transfer(PDM_DL_PORT); udelay(250); @@ -692,8 +707,8 @@ static void playback_abe_work(struct work_struct *work) omap_mcpdm_playback_close(mcpdm, mcpdm->downlink); abe_dsp_mcpdm_shutdown(); } - spin_unlock(&mcpdm->lock); abe_dsp_pm_put(); + mutex_unlock(&mcpdm->mutex); if (!mcpdm->free && !mcpdm->ul_active) omap_mcpdm_free(mcpdm); @@ -711,32 +726,31 @@ static int omap_mcpdm_abe_dai_hw_params(struct snd_pcm_substream *substream, snd_soc_dai_set_dma_data(dai, substream, &omap_mcpdm_dai_dma_params[stream]); + mutex_lock(&mcpdm->mutex); if (stream == SNDRV_PCM_STREAM_PLAYBACK) { /* Check if McPDM is already started */ if (!mcpdm->dn_channels) { abe_dsp_pm_get(); - spin_lock(&mcpdm->lock); /* start ATC before McPDM IP */ abe_enable_data_transfer(PDM_DL_PORT); udelay(250); mcpdm->downlink->channels = (PDM_DN_MASK | PDM_CMD_MASK); - ret = omap_mcpdm_playback_open(mcpdm, &omap_mcpdm_links[0]); if (ret < 0) { - spin_unlock(&mcpdm->lock); - goto out; + mutex_unlock(&mcpdm->mutex); + return ret; } omap_mcpdm_start(mcpdm, stream); - spin_unlock(&mcpdm->lock); } } else { mcpdm->uplink->channels = PDM_UP1_EN | PDM_UP2_EN; ret = omap_mcpdm_capture_open(mcpdm, &omap_mcpdm_links[1]); } -out: + mutex_unlock(&mcpdm->mutex); + return ret; } @@ -846,7 +860,7 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) mcpdm->downlink = &omap_mcpdm_links[0]; mcpdm->uplink = &omap_mcpdm_links[1]; - spin_lock_init(&mcpdm->lock); + mutex_init(&mcpdm->mutex); mcpdm->free = 1; mcpdm->io_base = omap_hwmod_get_mpu_rt_va(oh); -- 1.7.4.1