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

Commit 6521c6e0 authored by Viraja Kommaraju's avatar Viraja Kommaraju Committed by Gerrit - the friendly Code Review server
Browse files

asoc: sdm660: update machine driver for QCS605 LC variant



Add clock support for digital codec MCLK in machine driver
And support for logic of parsing digital codec node only.

Change-Id: I13da7a737f4bce0dbf83dea944e47341356941a1
Signed-off-by: default avatarViraja Kommaraju <virajak@codeaurora.org>
parent 6d75bc03
Loading
Loading
Loading
Loading
+36 −4
Original line number Diff line number Diff line
@@ -3043,10 +3043,30 @@ static int msm_populate_dai_link_component_of_node(
				index = of_property_match_string(cdev->of_node,
							"asoc-codec-names",
							PMIC_INT_ANALOG_CODEC);
				phandle = of_parse_phandle(
							cdev->of_node,
							"asoc-codec",
							index);
				dai_link[i].codecs[ANA_CDC].of_node =
								phandle;
			}
		}
		if (pdata->snd_card_val == INT_DIG_SND_CARD) {
			if ((dai_link[i].id ==
					MSM_BACKEND_DAI_INT0_MI2S_RX) ||
			    (dai_link[i].id ==
					MSM_BACKEND_DAI_INT1_MI2S_RX) ||
			    (dai_link[i].id ==
					MSM_BACKEND_DAI_INT2_MI2S_TX) ||
			    (dai_link[i].id ==
					MSM_BACKEND_DAI_INT3_MI2S_TX)) {
				index = of_property_match_string(cdev->of_node,
							"asoc-codec-names",
							MSM_INT_DIGITAL_CODEC);
				phandle = of_parse_phandle(cdev->of_node,
							   "asoc-codec",
							   index);
				dai_link[i].codecs[ANA_CDC].of_node = phandle;
				dai_link[i].codec_of_node = phandle;
			}
		}
	}
@@ -3342,6 +3362,8 @@ static const struct of_device_id sdm660_asoc_machine_of_match[] = {
	  .data = "tasha_codec"},
	{ .compatible = "qcom,sdm670-asoc-snd-tavil",
	  .data = "tavil_codec"},
	{ .compatible = "qcom,qcs605-dig-asoc-snd",
	  .data = "digital_codec"},
	{},
};

@@ -3388,6 +3410,11 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
		ret = msm_int_cdc_init(pdev, pdata, &card, &mbhc_cfg);
		if (ret)
			goto err;
	} else if (!strcmp(match->data, "digital_codec")) {
		pdata->snd_card_val = INT_DIG_SND_CARD;
		ret = msm_int_cdc_init(pdev, pdata, &card, NULL);
		if (ret)
			goto err;
	} else {
		dev_err(&pdev->dev,
			"%s: Not a matching DT sound node\n", __func__);
@@ -3408,6 +3435,11 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
					"qcom,cdc-ext-spk-gpios", 0);
	}

	if (pdata->snd_card_val == INT_DIG_SND_CARD) {
		/*reading the gpio configurations from dtsi file*/
		pdata->dmic_gpio_p = of_parse_phandle(pdev->dev.of_node,
					"qcom,cdc-dmic-gpios", 0);
	}
	pdata->mi2s_gpio_p[PRIM_MI2S] = of_parse_phandle(pdev->dev.of_node,
					"qcom,pri-mi2s-gpios", 0);
	pdata->mi2s_gpio_p[SEC_MI2S] = of_parse_phandle(pdev->dev.of_node,
@@ -3479,7 +3511,7 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
			ret);
		goto err;
	}
	if (pdata->snd_card_val != INT_SND_CARD)
	if (pdata->snd_card_val > INT_MAX_SND_CARD)
		msm_ext_register_audio_notifier(pdev);

	return 0;
@@ -3510,7 +3542,7 @@ static int msm_asoc_machine_remove(struct platform_device *pdev)
	struct snd_soc_card *card = platform_get_drvdata(pdev);
	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);

	if (pdata->snd_card_val == INT_SND_CARD)
	if (pdata->snd_card_val <= INT_MAX_SND_CARD)
		mutex_destroy(&pdata->cdc_int_mclk0_mutex);

	if (gpio_is_valid(pdata->us_euro_gpio)) {
@@ -3526,7 +3558,7 @@ static int msm_asoc_machine_remove(struct platform_device *pdev)
		pdata->hph_en0_gpio = 0;
	}

	if (pdata->snd_card_val != INT_SND_CARD)
	if (pdata->snd_card_val > INT_MAX_SND_CARD)
		audio_notifier_deregister("sdm660");

	snd_soc_unregister_card(card);
+3 −1
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -87,6 +87,8 @@ struct sdm660_codec {

enum {
	INT_SND_CARD,
	INT_DIG_SND_CARD,
	INT_MAX_SND_CARD = INT_DIG_SND_CARD,
	EXT_SND_CARD_TASHA,
	EXT_SND_CARD_TAVIL,
};
+240 −20
Original line number Diff line number Diff line
@@ -177,7 +177,10 @@ static int msm_int_enable_dig_cdc_clk(struct snd_soc_codec *codec, int enable,
				      bool dapm);
static int msm_int_mclk0_event(struct snd_soc_dapm_widget *w,
			      struct snd_kcontrol *kcontrol, int event);
static int msm_int_dig_mclk0_event(struct snd_soc_dapm_widget *w,
			      struct snd_kcontrol *kcontrol, int event);
static int msm_int_mi2s_snd_startup(struct snd_pcm_substream *substream);
static int msm_int_dig_mi2s_snd_startup(struct snd_pcm_substream *substream);
static void msm_int_mi2s_snd_shutdown(struct snd_pcm_substream *substream);

static struct wcd_mbhc_config *mbhc_cfg_ptr;
@@ -449,6 +452,15 @@ static const struct snd_soc_dapm_widget msm_int_dapm_widgets[] = {
	SND_SOC_DAPM_MIC("Digital Mic4", msm_dmic_event),
};

static const struct snd_soc_dapm_widget msm_int_dig_dapm_widgets[] = {
	SND_SOC_DAPM_SUPPLY_S("INT_MCLK0", -1, SND_SOC_NOPM, 0, 0,
	msm_int_dig_mclk0_event, SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIC("Digital Mic1", msm_dmic_event),
	SND_SOC_DAPM_MIC("Digital Mic2", msm_dmic_event),
	SND_SOC_DAPM_MIC("Digital Mic3", msm_dmic_event),
	SND_SOC_DAPM_MIC("Digital Mic4", msm_dmic_event),
};

static int msm_config_hph_compander_gpio(bool enable,
					 struct snd_soc_codec *codec)
{
@@ -918,13 +930,16 @@ static const struct snd_kcontrol_new msm_snd_controls[] = {
			int_mi2s_ch_get, int_mi2s_ch_put),
	SOC_ENUM_EXT("INT3_MI2S_TX Channels", int3_mi2s_tx_chs,
			int_mi2s_ch_get, int_mi2s_ch_put),
	SOC_ENUM_EXT("Loopback MCLK", loopback_mclk_en,
		     loopback_mclk_get, loopback_mclk_put),
	SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
			msm_bt_sample_rate_get,
			msm_bt_sample_rate_put),
};

static const struct snd_kcontrol_new msm_loopback_snd_controls[] = {
	SOC_ENUM_EXT("Loopback MCLK", loopback_mclk_en,
		     loopback_mclk_get, loopback_mclk_put),
};

static const struct snd_kcontrol_new msm_sdw_controls[] = {
	SOC_ENUM_EXT("INT4_MI2S_RX Format", int4_mi2s_rx_format,
		     int_mi2s_bit_format_get, int_mi2s_bit_format_put),
@@ -1011,6 +1026,31 @@ static int msm_int_mclk0_event(struct snd_soc_dapm_widget *w,
	return 0;
}

static int msm_int_dig_mclk0_event(struct snd_soc_dapm_widget *w,
			       struct snd_kcontrol *kcontrol, int event)
{
	struct msm_asoc_mach_data *pdata = NULL;
	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);

	pdata = snd_soc_card_get_drvdata(codec->component.card);
	pr_debug("%s: event = %d\n", __func__, event);
	switch (event) {
	case SND_SOC_DAPM_POST_PMD:
		pr_debug("%s: mclk_res_ref = %d\n",
				__func__, atomic_read(
				&pdata->int_mclk0_rsc_ref));
		if (atomic_read(&pdata->int_mclk0_rsc_ref) == 0) {
			pr_debug("%s: disabling MCLK\n", __func__);
			msm_int_enable_dig_cdc_clk(codec, 0, true);
		}
		break;
	default:
		pr_err("%s: invalid DAPM event %d\n", __func__, event);
		return -EINVAL;
	}
	return 0;
}

static int int_mi2s_get_port_id(int id)
{
	int afe_port_id;
@@ -1194,6 +1234,36 @@ static int msm_int_mi2s_snd_startup(struct snd_pcm_substream *substream)
	return ret;
}

static int msm_int_dig_mi2s_snd_startup(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_codec *codec = rtd->codec;
	int ret = 0;
	struct msm_asoc_mach_data *pdata = NULL;

	pdata = snd_soc_card_get_drvdata(codec->component.card);
	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
		 substream->name, substream->stream);

	ret = int_mi2s_set_sclk(substream, true);
	if (ret < 0) {
		pr_err("%s: failed to enable sclk %d\n",
				__func__, ret);
		return ret;
	}
	ret =  msm_int_enable_dig_cdc_clk(codec, 1, true);
	if (ret < 0) {
		pr_err("%s: failed to enable mclk\n", __func__);
		return ret;
	}
	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
	if (ret < 0)
		pr_err("%s: set fmt cpu dai failed; ret=%d\n", __func__, ret);

	return ret;
}

static void msm_int_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
{
	int ret;
@@ -1275,6 +1345,15 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
			__func__, ret);
		return ret;
	}

	ret = snd_soc_add_codec_controls(ana_cdc, msm_loopback_snd_controls,
				   ARRAY_SIZE(msm_loopback_snd_controls));
	if (ret < 0) {
		pr_err("%s: add_codec_controls failed: %d\n",
			__func__, ret);
		return ret;
	}

	ret = snd_soc_add_codec_controls(ana_cdc, msm_common_snd_controls,
				   msm_common_snd_controls_size());
	if (ret < 0) {
@@ -1328,6 +1407,59 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
	return 0;
}

static int msm_dig_audrx_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_codec *dig_cdc = rtd->codec;
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(dig_cdc);
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(rtd->card);
	struct snd_card *card;
	int ret = -ENOMEM;

	pr_debug("%s(),dev_name%s\n", __func__, dev_name(cpu_dai->dev));

	ret = snd_soc_add_codec_controls(dig_cdc, msm_snd_controls,
				   ARRAY_SIZE(msm_snd_controls));
	if (ret < 0) {
		pr_err("%s: add_codec_controls failed: %d\n",
			__func__, ret);
		return ret;
	}
	ret = snd_soc_add_codec_controls(dig_cdc, msm_common_snd_controls,
				   msm_common_snd_controls_size());
	if (ret < 0) {
		pr_err("%s: add common snd controls failed: %d\n",
			__func__, ret);
		return ret;
	}

	snd_soc_dapm_new_controls(dapm, msm_int_dig_dapm_widgets,
				  ARRAY_SIZE(msm_int_dig_dapm_widgets));

	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");

	snd_soc_dapm_ignore_suspend(dapm, "DMIC1");
	snd_soc_dapm_ignore_suspend(dapm, "DMIC2");
	snd_soc_dapm_ignore_suspend(dapm, "DMIC3");
	snd_soc_dapm_ignore_suspend(dapm, "DMIC4");

	card = rtd->card->snd_card;
	if (!codec_root)
		codec_root = snd_info_create_subdir(card->module, "codecs",
						      card->proc_root);
	if (!codec_root) {
		pr_debug("%s: Cannot create codecs module entry\n",
			 __func__);
		goto done;
	}
	pdata->codec_root = codec_root;
	msm_dig_codec_info_create_codec_entry(codec_root, dig_cdc);
done:
	msm_set_codec_reg_done(true);
	return 0;
}

static int msm_sdw_audrx_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_codec *codec = rtd->codec;
@@ -1632,6 +1764,11 @@ static struct snd_soc_ops msm_int_mi2s_be_ops = {
	.shutdown = msm_int_mi2s_snd_shutdown,
};

static struct snd_soc_ops msm_int_dig_mi2s_be_ops = {
	.startup = msm_int_dig_mi2s_snd_startup,
	.shutdown = msm_int_mi2s_snd_shutdown,
};

static struct snd_soc_ops msm_sdw_mi2s_be_ops = {
	.startup = msm_sdw_mi2s_snd_startup,
	.shutdown = msm_sdw_mi2s_snd_shutdown,
@@ -2484,6 +2621,60 @@ static struct snd_soc_dai_link msm_int_be_dai[] = {
		.ops = &msm_int_mi2s_be_ops,
		.ignore_suspend = 1,
	},
};

static struct snd_soc_dai_link msm_int_dig_be_dai[] = {
    /* DIG Codec Backend DAI Links */
	{
		.name = LPASS_BE_INT0_MI2S_RX,
		.stream_name = "INT0 MI2S Playback",
		.cpu_dai_name = "msm-dai-q6-mi2s.7",
		.platform_name = "msm-pcm-routing",
		.codec_dai_name = "msm_dig_cdc_dai_rx1",
		.no_pcm = 1,
		.dpcm_playback = 1,
		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
			ASYNC_DPCM_SND_SOC_HW_PARAMS,
		.id = MSM_BACKEND_DAI_INT0_MI2S_RX,
		.init = &msm_dig_audrx_init,
		.be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
		.ops = &msm_int_dig_mi2s_be_ops,
		.ignore_suspend = 1,
	},
	{
		.name = LPASS_BE_INT3_MI2S_TX,
		.stream_name = "INT3 MI2S Capture",
		.cpu_dai_name = "msm-dai-q6-mi2s.10",
		.platform_name = "msm-pcm-routing",
		.codec_dai_name = "msm_dig_cdc_dai_tx1",
		.no_pcm = 1,
		.dpcm_capture = 1,
		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
			ASYNC_DPCM_SND_SOC_HW_PARAMS,
		.id = MSM_BACKEND_DAI_INT3_MI2S_TX,
		.be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
		.ops = &msm_int_dig_mi2s_be_ops,
		.ignore_suspend = 1,
	},
	{
		.name = LPASS_BE_INT2_MI2S_TX,
		.stream_name = "INT2 MI2S Capture",
		.cpu_dai_name = "msm-dai-q6-mi2s.9",
		.platform_name = "msm-pcm-routing",
		.codec_dai_name = "msm_dig_cdc_dai_tx2",
		.no_pcm = 1,
		.dpcm_capture = 1,
		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
			ASYNC_DPCM_SND_SOC_HW_PARAMS,
		.id = MSM_BACKEND_DAI_INT2_MI2S_TX,
		.be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
		.ops = &msm_int_dig_mi2s_be_ops,
		.ignore_suspend = 1,
	},
};

static struct snd_soc_dai_link msm_int_common_be_dai[] = {
	/* Backend I2S DAI Links */
	{
		.name = LPASS_BE_AFE_PCM_RX,
		.stream_name = "AFE Playback",
@@ -3139,6 +3330,8 @@ ARRAY_SIZE(msm_int_dai) +
ARRAY_SIZE(msm_int_wsa_dai) +
ARRAY_SIZE(msm_int_compress_capture_dai) +
ARRAY_SIZE(msm_int_be_dai) +
ARRAY_SIZE(msm_int_dig_be_dai) +
ARRAY_SIZE(msm_int_common_be_dai) +
ARRAY_SIZE(msm_mi2s_be_dai_links) +
ARRAY_SIZE(msm_auxpcm_be_dai_links)+
ARRAY_SIZE(msm_wcn_be_dai_links) +
@@ -3153,6 +3346,13 @@ static struct snd_soc_card sdm660_card = {
	.late_probe	= msm_snd_card_late_probe,
};

static struct snd_soc_card qcs605_dig_card = {
	/* snd_soc_card_qcs605 */
	.name		= "qcs605-dig-snd-card",
	.dai_link	= msm_int_dai,
	.num_links	= ARRAY_SIZE(msm_int_dai),
};

static void msm_disable_int_mclk0(struct work_struct *work)
{
	struct msm_asoc_mach_data *pdata = NULL;
@@ -3199,12 +3399,17 @@ static void msm_int_dt_parse_cap_info(struct platform_device *pdev,
}

static struct snd_soc_card *msm_int_populate_sndcard_dailinks(
						struct device *dev)
					struct device *dev, int snd_card_val)
{
	struct snd_soc_card *card = &sdm660_card;
	struct snd_soc_card *card;
	struct snd_soc_dai_link *dailink;
	int len1;

	if (snd_card_val == INT_SND_CARD)
		card = &sdm660_card;
	else
		card = &qcs605_dig_card;

	card->name = dev_name(dev);
	len1 = ARRAY_SIZE(msm_int_dai);
	memcpy(msm_int_dai_links, msm_int_dai, sizeof(msm_int_dai));
@@ -3220,8 +3425,18 @@ static struct snd_soc_card *msm_int_populate_sndcard_dailinks(
		sizeof(msm_int_compress_capture_dai));
	len1 += ARRAY_SIZE(msm_int_compress_capture_dai);

	if (snd_card_val == INT_SND_CARD) {
		memcpy(dailink + len1, msm_int_be_dai, sizeof(msm_int_be_dai));
		len1 += ARRAY_SIZE(msm_int_be_dai);
	} else {
		memcpy(dailink + len1, msm_int_dig_be_dai,
			sizeof(msm_int_dig_be_dai));
		len1 += ARRAY_SIZE(msm_int_dig_be_dai);
	}

	memcpy(dailink + len1, msm_int_common_be_dai,
		sizeof(msm_int_common_be_dai));
	len1 += ARRAY_SIZE(msm_int_common_be_dai);

	if (of_property_read_bool(dev->of_node,
				  "qcom,mi2s-audio-intf")) {
@@ -3278,6 +3493,7 @@ static int msm_internal_init(struct platform_device *pdev,
			"%s: doesn't support external speaker pa\n",
			__func__);

	if (pdata->snd_card_val != INT_DIG_SND_CARD) {
		ret = of_property_read_string(pdev->dev.of_node,
				      hs_micbias_type, &type);
		if (ret) {
@@ -3285,6 +3501,7 @@ static int msm_internal_init(struct platform_device *pdev,
				__func__, hs_micbias_type);
			goto err;
		}

		if (!strcmp(type, "external")) {
			dev_dbg(&pdev->dev, "Headset is using external micbias\n");
			mbhc_cfg_ptr->hs_ext_micbias = true;
@@ -3292,6 +3509,7 @@ static int msm_internal_init(struct platform_device *pdev,
			dev_dbg(&pdev->dev, "Headset is using internal micbias\n");
			mbhc_cfg_ptr->hs_ext_micbias = false;
		}
	}

	/* initialize the int_mclk0 */
	pdata->digital_cdc_core_clk.clk_set_minor_version =
@@ -3308,6 +3526,7 @@ static int msm_internal_init(struct platform_device *pdev,
	/* Initialize loopback mode to false */
	pdata->lb_mode = false;

	if (pdata->snd_card_val != INT_DIG_SND_CARD)
		msm_int_dt_parse_cap_info(pdev, pdata);

	card->dev = &pdev->dev;
@@ -3347,7 +3566,8 @@ int msm_int_cdc_init(struct platform_device *pdev,
{
	mbhc_cfg_ptr = mbhc_cfg;

	*card = msm_int_populate_sndcard_dailinks(&pdev->dev);
	*card = msm_int_populate_sndcard_dailinks(&pdev->dev,
						  pdata->snd_card_val);
	msm_internal_init(pdev, pdata, *card);
	return 0;
}