Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ecd9b09 authored by Santosh Mardi's avatar Santosh Mardi Committed by Aviral Gupta
Browse files

ASoC: msm8x16-wcd: add suspend and resume callback to codec driver



Add suspend and resume call backs to the codec driver to make
sure the clocks are disabled.

CRs-Fixed: 662773
Change-Id: I7e68721b7249e948d5660bac0da8c97131fefd3c
Signed-off-by: default avatarSantosh Mardi <gsantosh@codeaurora.org>
parent a345317a
Loading
Loading
Loading
Loading
+77 −0
Original line number Diff line number Diff line
@@ -3131,6 +3131,80 @@ static int msm8x16_wcd_codec_remove(struct snd_soc_codec *codec)
	return 0;
}

int msm8x16_wcd_suspend(struct snd_soc_codec *codec)
{
	struct msm8916_asoc_mach_data *pdata = NULL;

	pdata = snd_soc_card_get_drvdata(codec->card);
	pr_debug("%s: mclk cnt = %d, dis_work_mclk = %d\n",
			__func__, atomic_read(&pdata->mclk_rsc_ref),
			atomic_read(&pdata->dis_work_mclk));
	pr_debug("%s: mclk_act  = %d\n", __func__,
			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(
					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);
		}
	} else
		/*
		 * mark no activity on mclk in this suspend
		 */
		atomic_set(&pdata->mclk_act, MCLK_SUS_NO_ACT);
	mutex_unlock(&pdata->cdc_mclk_mutex);
	return 0;
}

int msm8x16_wcd_resume(struct snd_soc_codec *codec)
{
	struct msm8916_asoc_mach_data *pdata = NULL;

	pdata = snd_soc_card_get_drvdata(codec->card);
	pr_debug("%s: mclk cnt = %d, dis_work_mclk = %d\n",
			__func__, atomic_read(&pdata->mclk_rsc_ref),
			atomic_read(&pdata->dis_work_mclk));
	pr_debug("%s: mclk_act = %d\n", __func__,
			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;
}

static struct snd_soc_codec_driver soc_codec_dev_msm8x16_wcd = {
	.probe	= msm8x16_wcd_codec_probe,
	.remove	= msm8x16_wcd_codec_remove,
@@ -3138,6 +3212,9 @@ static struct snd_soc_codec_driver soc_codec_dev_msm8x16_wcd = {
	.read = msm8x16_wcd_read,
	.write = msm8x16_wcd_write,

	.suspend = msm8x16_wcd_suspend,
	.resume = msm8x16_wcd_resume,

	.readable_register = msm8x16_wcd_readable,
	.volatile_register = msm8x16_wcd_volatile,

+8 −0
Original line number Diff line number Diff line
@@ -39,6 +39,13 @@
	(((reg >= 0x200) && (reg <= 0x4FF)) ? 1 : 0)
#define MSM8X16_WCD_IS_TOMBAK_REG(reg) \
	(((reg >= 0x000) && (reg <= 0x1FF)) ? 1 : 0)
/*
 * MCLK activity indicators during suspend and resume call
 */
#define MCLK_SUS_DIS	1
#define MCLK_SUS_RSC	2
#define MCLK_SUS_NO_ACT	3

extern const u8 msm8x16_wcd_reg_readable[MSM8X16_WCD_CACHE_SIZE];
extern const u8 msm8x16_wcd_reg_readonly[MSM8X16_WCD_CACHE_SIZE];
extern const u8 msm8x16_wcd_reset_reg_defaults[MSM8X16_WCD_CACHE_SIZE];
@@ -124,6 +131,7 @@ struct msm8916_asoc_mach_data {
	int mclk_freq;
	atomic_t mclk_rsc_ref;
	atomic_t dis_work_mclk;
	atomic_t mclk_act;
	struct mutex cdc_mclk_mutex;
	struct delayed_work enable_mclk_work;
	struct afe_digital_clk_cfg digital_cdc_clk;
+1 −1
Original line number Diff line number Diff line
@@ -580,6 +580,7 @@ static int msm8x16_enable_codec_ext_clk(struct snd_soc_codec *codec,
			msm8x16_wcd_mclk_enable(codec, 1, dapm);
		}
	} else {
		msm8x16_wcd_mclk_enable(codec, 0, dapm);
		mutex_lock(&pdata->cdc_mclk_mutex);
		atomic_set(&pdata->mclk_rsc_ref, 0);
		cancel_delayed_work_sync(&pdata->enable_mclk_work);
@@ -589,7 +590,6 @@ static int msm8x16_enable_codec_ext_clk(struct snd_soc_codec *codec,
				&pdata->digital_cdc_clk);
		atomic_set(&pdata->dis_work_mclk, false);
		mutex_unlock(&pdata->cdc_mclk_mutex);
		msm8x16_wcd_mclk_enable(codec, 0, dapm);
	}
	return ret;
}