summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAviral Gupta <aviralg@codeaurora.org>2014-06-20 19:40:46 +0530
committerAviral Gupta <aviralg@codeaurora.org>2014-06-26 11:13:46 +0530
commit6013969c2fda99b02e6b71985b34926eeaf7a9d7 (patch)
treefe940f27cd8339998fb3b3612ae82145348c37a2
parent7ec3c7db46846e2f5e2fe6540d3e08c2b7cdf0a1 (diff)
ASoC: msm8x16: fix the target crash due to dpm timeout
DPM timeout was happening due to the suspend call to the codec driver being blocked. This was due to a deadlock by acquiring the same mutex by the suspend call and the work queue. Fix by modifying the codeflow so that the deadlock is avoided. CRs-Fixed: 681986 Change-Id: I96f11ee968a0e9bd267a80d2d11f1fa49985f5a9 Signed-off-by: Aviral Gupta <aviralg@codeaurora.org>
-rw-r--r--sound/soc/codecs/msm8x16-wcd.c78
-rw-r--r--sound/soc/codecs/msm8x16-wcd.h5
-rw-r--r--sound/soc/msm/msm8x16.c49
3 files changed, 47 insertions, 85 deletions
diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c
index dda668bf5fdb..c88cc472e7b8 100644
--- a/sound/soc/codecs/msm8x16-wcd.c
+++ b/sound/soc/codecs/msm8x16-wcd.c
@@ -347,7 +347,7 @@ static int __msm8x16_wcd_reg_read(struct snd_soc_codec *codec,
ret = msm8x16_wcd_spmi_read(reg, 1, &temp);
else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) {
mutex_lock(&pdata->cdc_mclk_mutex);
- if (atomic_read(&pdata->dis_work_mclk) == false) {
+ if (atomic_read(&pdata->mclk_enabled) == false) {
pdata->digital_cdc_clk.clk_val = pdata->mclk_freq;
ret = afe_set_digital_codec_core_clock(
AFE_PORT_ID_PRIMARY_MI2S_RX,
@@ -359,8 +359,8 @@ static int __msm8x16_wcd_reg_read(struct snd_soc_codec *codec,
pr_debug("%s: MCLK not enabled\n", __func__);
ret = msm8x16_wcd_ahb_read_device(
msm8x16_wcd, reg, 1, &temp);
- atomic_set(&pdata->dis_work_mclk, true);
- schedule_delayed_work(&pdata->enable_mclk_work, 50);
+ atomic_set(&pdata->mclk_enabled, true);
+ schedule_delayed_work(&pdata->disable_mclk_work, 50);
err:
mutex_unlock(&pdata->cdc_mclk_mutex);
mutex_unlock(&msm8x16_wcd->io_lock);
@@ -397,7 +397,7 @@ static int __msm8x16_wcd_reg_write(struct snd_soc_codec *codec,
ret = msm8x16_wcd_spmi_write(reg, 1, &val);
else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) {
mutex_lock(&pdata->cdc_mclk_mutex);
- if (atomic_read(&pdata->dis_work_mclk) == false) {
+ if (atomic_read(&pdata->mclk_enabled) == false) {
pr_debug("MCLK not enabled %s:\n", __func__);
pdata->digital_cdc_clk.clk_val = pdata->mclk_freq;
ret = afe_set_digital_codec_core_clock(
@@ -410,8 +410,8 @@ static int __msm8x16_wcd_reg_write(struct snd_soc_codec *codec,
}
ret = msm8x16_wcd_ahb_write_device(
msm8x16_wcd, reg, &val, 1);
- atomic_set(&pdata->dis_work_mclk, true);
- schedule_delayed_work(&pdata->enable_mclk_work, 50);
+ atomic_set(&pdata->mclk_enabled, true);
+ schedule_delayed_work(&pdata->disable_mclk_work, 50);
err:
mutex_unlock(&pdata->cdc_mclk_mutex);
mutex_unlock(&msm8x16_wcd->io_lock);
@@ -3323,37 +3323,23 @@ int msm8x16_wcd_suspend(struct snd_soc_codec *codec)
struct msm8x16_wcd_pdata *msm8x16_pdata = msm8x16->dev->platform_data;
pdata = snd_soc_card_get_drvdata(codec->card);
- pr_debug("%s: mclk cnt = %d, dis_work_mclk = %d"
- "mclk_act = %d\n",
+ pr_debug("%s: mclk cnt = %d, mclk_enabled = %d\n",
__func__, atomic_read(&pdata->mclk_rsc_ref),
- atomic_read(&pdata->dis_work_mclk),
- atomic_read(&pdata->mclk_act));
- mutex_lock(&pdata->cdc_mclk_mutex);
- if ((atomic_read(&pdata->dis_work_mclk) == true) ||
- (atomic_read(&pdata->mclk_rsc_ref) > 0)) {
- pdata->digital_cdc_clk.clk_val = 0;
- afe_set_digital_codec_core_clock(
+ atomic_read(&pdata->mclk_enabled));
+ if (atomic_read(&pdata->mclk_enabled) == true) {
+ cancel_delayed_work_sync(
+ &pdata->disable_mclk_work);
+ mutex_lock(&pdata->cdc_mclk_mutex);
+ if (atomic_read(&pdata->mclk_enabled) == true) {
+ pdata->digital_cdc_clk.clk_val = 0;
+ afe_set_digital_codec_core_clock(
AFE_PORT_ID_PRIMARY_MI2S_RX,
&pdata->digital_cdc_clk);
- /*
- * set mclk activity to resource as
- * it will get updated accordingly going further in this
- * function.
- */
- atomic_set(&pdata->mclk_act, MCLK_SUS_RSC);
- if (atomic_read(&pdata->dis_work_mclk) == true) {
- cancel_delayed_work_sync(
- &pdata->enable_mclk_work);
- atomic_set(&pdata->mclk_act, MCLK_SUS_DIS);
- atomic_set(&pdata->dis_work_mclk, false);
+ atomic_set(&pdata->mclk_enabled, false);
}
- } else
- /*
- * mark no activity on mclk in this suspend
- */
- atomic_set(&pdata->mclk_act, MCLK_SUS_NO_ACT);
+ mutex_unlock(&pdata->cdc_mclk_mutex);
+ }
msm8x16_wcd_disable_static_supplies_to_optimum(msm8x16, msm8x16_pdata);
- mutex_unlock(&pdata->cdc_mclk_mutex);
return 0;
}
@@ -3365,34 +3351,6 @@ int msm8x16_wcd_resume(struct snd_soc_codec *codec)
pdata = snd_soc_card_get_drvdata(codec->card);
msm8x16_wcd_enable_static_supplies_to_optimum(msm8x16, msm8x16_pdata);
- pr_debug("%s: mclk cnt = %d, dis_work_mclk = %d"
- "mclk_act = %d\n",
- __func__, atomic_read(&pdata->mclk_rsc_ref),
- atomic_read(&pdata->dis_work_mclk),
- atomic_read(&pdata->mclk_act));
- if (atomic_read(&pdata->mclk_act) == MCLK_SUS_NO_ACT)
- /*
- * no activity in suspend just return
- */
- return 0;
- mutex_lock(&pdata->cdc_mclk_mutex);
- if ((atomic_read(&pdata->dis_work_mclk) == false) ||
- (atomic_read(&pdata->mclk_rsc_ref) > 0)) {
- pdata->digital_cdc_clk.clk_val = pdata->mclk_freq;
- afe_set_digital_codec_core_clock(
- AFE_PORT_ID_PRIMARY_MI2S_RX,
- &pdata->digital_cdc_clk);
- if (atomic_read(&pdata->mclk_act) == MCLK_SUS_DIS) {
- /*
- * MCLK activity marked as the disabled during suspend
- * this indicated MCLK was enabled to read and write the
- * AHB bus.
- */
- atomic_set(&pdata->dis_work_mclk, true);
- schedule_delayed_work(&pdata->enable_mclk_work, 50);
- }
- }
- mutex_unlock(&pdata->cdc_mclk_mutex);
return 0;
}
diff --git a/sound/soc/codecs/msm8x16-wcd.h b/sound/soc/codecs/msm8x16-wcd.h
index 7d497299264e..3cceb0a37fca 100644
--- a/sound/soc/codecs/msm8x16-wcd.h
+++ b/sound/soc/codecs/msm8x16-wcd.h
@@ -130,10 +130,9 @@ struct msm8916_asoc_mach_data {
int us_euro_gpio;
int mclk_freq;
atomic_t mclk_rsc_ref;
- atomic_t dis_work_mclk;
- atomic_t mclk_act;
+ atomic_t mclk_enabled;
struct mutex cdc_mclk_mutex;
- struct delayed_work enable_mclk_work;
+ struct delayed_work disable_mclk_work;
struct afe_digital_clk_cfg digital_cdc_clk;
};
diff --git a/sound/soc/msm/msm8x16.c b/sound/soc/msm/msm8x16.c
index a17cdfe1a6ef..18381a28d46e 100644
--- a/sound/soc/msm/msm8x16.c
+++ b/sound/soc/msm/msm8x16.c
@@ -593,28 +593,29 @@ static int msm8x16_enable_codec_ext_clk(struct snd_soc_codec *codec,
atomic_read(&pdata->mclk_rsc_ref));
if (enable) {
if (atomic_inc_return(&pdata->mclk_rsc_ref) == 1) {
+ cancel_delayed_work_sync(
+ &pdata->disable_mclk_work);
mutex_lock(&pdata->cdc_mclk_mutex);
- if (atomic_read(&pdata->dis_work_mclk) == true) {
- cancel_delayed_work_sync(
- &pdata->enable_mclk_work);
- } else {
- pdata->digital_cdc_clk.clk_val = pdata->mclk_freq;
+ if (atomic_read(&pdata->mclk_enabled) == false) {
+ pdata->digital_cdc_clk.clk_val =
+ pdata->mclk_freq;
afe_set_digital_codec_core_clock(
AFE_PORT_ID_PRIMARY_MI2S_RX,
&pdata->digital_cdc_clk);
- atomic_set(&pdata->dis_work_mclk, true);
+ atomic_set(&pdata->mclk_enabled, true);
}
mutex_unlock(&pdata->cdc_mclk_mutex);
}
} else {
+ cancel_delayed_work_sync(&pdata->disable_mclk_work);
mutex_lock(&pdata->cdc_mclk_mutex);
- atomic_set(&pdata->mclk_rsc_ref, 0);
- cancel_delayed_work_sync(&pdata->enable_mclk_work);
- pdata->digital_cdc_clk.clk_val = 0;
- afe_set_digital_codec_core_clock(
- AFE_PORT_ID_PRIMARY_MI2S_RX,
- &pdata->digital_cdc_clk);
- atomic_set(&pdata->dis_work_mclk, false);
+ if (atomic_read(&pdata->mclk_enabled) == true) {
+ pdata->digital_cdc_clk.clk_val = 0;
+ afe_set_digital_codec_core_clock(
+ AFE_PORT_ID_PRIMARY_MI2S_RX,
+ &pdata->digital_cdc_clk);
+ atomic_set(&pdata->mclk_enabled, false);
+ }
mutex_unlock(&pdata->cdc_mclk_mutex);
}
return ret;
@@ -1820,26 +1821,30 @@ static struct snd_soc_card bear_cards[MAX_SND_CARDS] = {
},
};
-void enable_mclk(struct work_struct *work)
+void disable_mclk(struct work_struct *work)
{
struct msm8916_asoc_mach_data *pdata = NULL;
struct delayed_work *dwork;
int ret = 0;
- pr_debug("%s:\n", __func__);
dwork = to_delayed_work(work);
pdata = container_of(dwork, struct msm8916_asoc_mach_data,
- enable_mclk_work);
+ disable_mclk_work);
mutex_lock(&pdata->cdc_mclk_mutex);
- if (atomic_read(&pdata->dis_work_mclk) == true) {
- pr_debug("clock enabled now disable\n");
+ pr_debug("%s: mclk_enabled %d mclk_rsc_ref %d\n", __func__,
+ atomic_read(&pdata->mclk_enabled),
+ atomic_read(&pdata->mclk_rsc_ref));
+
+ if (atomic_read(&pdata->mclk_enabled) == true
+ && atomic_read(&pdata->mclk_rsc_ref) == 0) {
+ pr_debug("Disable the mclk\n");
pdata->digital_cdc_clk.clk_val = 0;
ret = afe_set_digital_codec_core_clock(
AFE_PORT_ID_PRIMARY_MI2S_RX,
&pdata->digital_cdc_clk);
if (ret < 0)
- pr_err("failed to disable the MCLK\n");
- atomic_set(&pdata->dis_work_mclk, false);
+ pr_err("%s failed to disable the MCLK\n", __func__);
+ atomic_set(&pdata->mclk_enabled, false);
}
mutex_unlock(&pdata->cdc_mclk_mutex);
}
@@ -2171,10 +2176,10 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev)
if (ret)
goto err;
/* initialize timer */
- INIT_DELAYED_WORK(&pdata->enable_mclk_work, enable_mclk);
+ INIT_DELAYED_WORK(&pdata->disable_mclk_work, disable_mclk);
mutex_init(&pdata->cdc_mclk_mutex);
atomic_set(&pdata->mclk_rsc_ref, 0);
- atomic_set(&pdata->dis_work_mclk, false);
+ atomic_set(&pdata->mclk_enabled, false);
ret = snd_soc_of_parse_audio_routing(card,
"qcom,audio-routing");