From 07a252e76deabfe72c15d2a494a5e79168dbf088 Mon Sep 17 00:00:00 2001
From: Misael Lopez Cruz <misael.lopez@ti.com>
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 <misael.lopez@ti.com>
Integrated-by: Jingdong Lu <jingdong.lu@windriver.com>
---
 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

