summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorMisael Lopez Cruz <misael.lopez@ti.com>2011-05-31 09:23:01 +0100
committerAndy Green <andy.green@linaro.org>2011-05-31 11:04:32 +0100
commit29cc0bf1d80d4b8cbdfbfbe83eb7418fa16ee20c (patch)
tree87d96d5398fdc80e66e97b0dcbc06e289c3fc244 /sound
parent3ec15d87d48a6f976aa4fd22e827e59347f61e3c (diff)
ASoC: McPDM: Use mutex instead of spinlocks
Use mutex instead of spinlocks to allow protecting sleeping functions like pm_runtime calls. Change-Id: I373b340c6895bb3d8c7827a37a1a20406c461c6c Signed-off-by: Misael Lopez Cruz <misael.lopez@ti.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/omap/omap-mcpdm.c66
1 files changed, 40 insertions, 26 deletions
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 323606a4cab..a9763827454 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);