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

Commit 82514ee3 authored by Aviral Gupta's avatar Aviral Gupta
Browse files

ASoC: msm8x16-wcd: update codec driver to lock read and write access



Lock critical variables with the mutex while accessing the codec AHB
read and write registers.

CRs-Fixed: 646488
Change-Id: I026d3159f1322402292749b5c621c72b975ecbe3
Signed-off-by: default avatarAviral Gupta <aviralg@codeaurora.org>
parent 0e55037e
Loading
Loading
Loading
Loading
+10 −12
Original line number Diff line number Diff line
@@ -330,10 +330,8 @@ static int __msm8x16_wcd_reg_read(struct snd_soc_codec *codec,
	if (MSM8X16_WCD_IS_TOMBAK_REG(reg))
		ret = msm8x16_wcd_spmi_read(reg, 1, &temp);
	else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) {
		if ((atomic_read(&pdata->mclk_rsc_ref) == 0) &&
			(pdata->snd_card_on == true) &&
			(atomic_read(&pdata->dis_work_mclk) == false)) {
		mutex_lock(&pdata->cdc_mclk_mutex);
		if (atomic_read(&pdata->dis_work_mclk) == false) {
			pdata->digital_cdc_clk.clk_val = 9600000;
			ret = afe_set_digital_codec_core_clock(
					AFE_PORT_ID_PRIMARY_MI2S_RX,
@@ -343,16 +341,17 @@ static int __msm8x16_wcd_reg_read(struct snd_soc_codec *codec,
				goto err;
			}
			pr_debug("%s: MCLK not enabled\n", __func__);
			atomic_set(&pdata->dis_work_mclk, true);
			schedule_delayed_work(&pdata->enable_mclk_work, 50);
			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);
err:
			mutex_unlock(&pdata->cdc_mclk_mutex);
			mutex_unlock(&msm8x16_wcd->io_lock);
			return temp;
		}
		ret = msm8x16_wcd_ahb_read_device(msm8x16_wcd, reg, 1, &temp);
		mutex_unlock(&pdata->cdc_mclk_mutex);
	}
	mutex_unlock(&msm8x16_wcd->io_lock);

@@ -381,11 +380,9 @@ static int __msm8x16_wcd_reg_write(struct snd_soc_codec *codec,
	if (MSM8X16_WCD_IS_TOMBAK_REG(reg))
		ret = msm8x16_wcd_spmi_write(reg, 1, &val);
	else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) {
		if ((atomic_read(&pdata->mclk_rsc_ref) == 0) &&
			(pdata->snd_card_on == true) &&
			(atomic_read(&pdata->dis_work_mclk) == false)) {
			pr_debug("MCLK not enabled %s:\n", __func__);
		mutex_lock(&pdata->cdc_mclk_mutex);
		if (atomic_read(&pdata->dis_work_mclk) == false) {
			pr_debug("MCLK not enabled %s:\n", __func__);
			pdata->digital_cdc_clk.clk_val = 9600000;
			ret = afe_set_digital_codec_core_clock(
					AFE_PORT_ID_PRIMARY_MI2S_RX,
@@ -395,16 +392,17 @@ static int __msm8x16_wcd_reg_write(struct snd_soc_codec *codec,
				ret = 0;
				goto err;
			}
			atomic_set(&pdata->dis_work_mclk, true);
			schedule_delayed_work(&pdata->enable_mclk_work, 50);
			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);
err:
			mutex_unlock(&pdata->cdc_mclk_mutex);
			mutex_unlock(&msm8x16_wcd->io_lock);
			return ret;
		}
		ret = msm8x16_wcd_ahb_write_device(msm8x16_wcd, reg, &val, 1);
		mutex_unlock(&pdata->cdc_mclk_mutex);
	}
	mutex_unlock(&msm8x16_wcd->io_lock);

+0 −1
Original line number Diff line number Diff line
@@ -119,7 +119,6 @@ struct msm8x16_wcd_regulator {

struct msm8916_asoc_mach_data {
	int codec_type;
	int snd_card_on;
	atomic_t mclk_rsc_ref;
	atomic_t dis_work_mclk;
	struct mutex cdc_mclk_mutex;
+37 −39
Original line number Diff line number Diff line
@@ -307,36 +307,38 @@ static int msm8x16_enable_codec_ext_clk(struct snd_soc_codec *codec,
	struct msm8916_asoc_mach_data *pdata = NULL;

	pdata = snd_soc_card_get_drvdata(codec->card);
	mutex_lock(&pdata->cdc_mclk_mutex);
	pr_debug("%s: enable = %d  codec name %s enable %d mclk ref counter %d\n",
		   __func__, enable, codec->name, enable,
	pr_debug("%s: codec name %s enable %d mclk ref counter %d\n",
		   __func__, codec->name, enable,
		   atomic_read(&pdata->mclk_rsc_ref));
	if (enable) {
		if (atomic_inc_return(&pdata->mclk_rsc_ref) == 1) {
			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 = 9600000;
				afe_set_digital_codec_core_clock(
						AFE_PORT_ID_PRIMARY_MI2S_RX,
						&pdata->digital_cdc_clk);
				atomic_set(&pdata->dis_work_mclk, true);
			}
			mutex_unlock(&pdata->cdc_mclk_mutex);
			msm8x16_wcd_mclk_enable(codec, 1, dapm);
			cancel_delayed_work_sync(&pdata->enable_mclk_work);
		}
	} else {
		if ((atomic_read(&pdata->mclk_rsc_ref) - 1) == 0) {
		if (atomic_dec_return(&pdata->mclk_rsc_ref) == 0) {
			mutex_lock(&pdata->cdc_mclk_mutex);
			cancel_delayed_work_sync(&pdata->enable_mclk_work);
			pdata->digital_cdc_clk.clk_val = 0;
			msm8x16_wcd_mclk_enable(codec, 0, dapm);
			afe_set_digital_codec_core_clock(
					AFE_PORT_ID_PRIMARY_MI2S_RX,
					&pdata->digital_cdc_clk);
			if (atomic_read(&pdata->dis_work_mclk) == true) {
				pr_debug("add work in disable of %s\n",
						__func__);
				schedule_delayed_work(
					&pdata->enable_mclk_work, 10);
			}
			atomic_set(&pdata->dis_work_mclk, false);
			mutex_unlock(&pdata->cdc_mclk_mutex);
			msm8x16_wcd_mclk_enable(codec, 0, dapm);
		}
		atomic_dec(&pdata->mclk_rsc_ref);
	}
	mutex_unlock(&pdata->cdc_mclk_mutex);
	return ret;
}

@@ -978,14 +980,13 @@ void enable_mclk(struct work_struct *work)
	struct delayed_work *dwork;
	int ret = 0;

	pr_info("%s:\n", __func__);
	pr_debug("%s:\n", __func__);
	dwork = to_delayed_work(work);
	pdata = container_of(dwork, struct msm8916_asoc_mach_data,
				enable_mclk_work);
	if (atomic_read(&pdata->mclk_rsc_ref) == 0) {
	mutex_lock(&pdata->cdc_mclk_mutex);
	if (atomic_read(&pdata->dis_work_mclk) == true) {
		pr_debug("clock enabled now disable\n");
			mutex_lock(&pdata->cdc_mclk_mutex);
		pdata->digital_cdc_clk.clk_val = 0;
		ret = afe_set_digital_codec_core_clock(
				AFE_PORT_ID_PRIMARY_MI2S_RX,
@@ -993,9 +994,8 @@ void enable_mclk(struct work_struct *work)
		if (ret < 0)
			pr_err("failed to disable the MCLK\n");
		atomic_set(&pdata->dis_work_mclk, false);
			mutex_unlock(&pdata->cdc_mclk_mutex);
		}
	}
	mutex_unlock(&pdata->cdc_mclk_mutex);
}

static int msm8x16_asoc_machine_probe(struct platform_device *pdev)
@@ -1068,10 +1068,14 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev)
	card->dev = &pdev->dev;
	platform_set_drvdata(pdev, card);
	snd_soc_card_set_drvdata(card, pdata);
	pdata->snd_card_on = false;
	ret = snd_soc_of_parse_card_name(card, "qcom,model");
	if (ret)
		goto err;
	/* initialize timer */
	INIT_DELAYED_WORK(&pdata->enable_mclk_work, enable_mclk);
	mutex_init(&pdata->cdc_mclk_mutex);
	atomic_set(&pdata->mclk_rsc_ref, 0);
	atomic_set(&pdata->dis_work_mclk, false);

	ret = snd_soc_of_parse_audio_routing(card,
			"qcom,audio-routing");
@@ -1084,12 +1088,6 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev)
			ret);
		goto err;
	}
	/* initialize timer */
	INIT_DELAYED_WORK(&pdata->enable_mclk_work, enable_mclk);
	pdata->snd_card_on = true;
	mutex_init(&pdata->cdc_mclk_mutex);
	atomic_set(&pdata->mclk_rsc_ref, 0);
	atomic_set(&pdata->dis_work_mclk, false);
	return 0;
err:
	devm_kfree(&pdev->dev, pdata);