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

Commit 3794a136 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: msm: support 5 and 7 channel for TDM hw param"

parents aef0000e 9f7dcd45
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -2145,7 +2145,9 @@ Required properties:
		"qcom,apq8096-asoc-snd-adp-agave" for adp agave codec and
		node is "sound-adp-agave",
		"qcom,apq8096-asoc-snd-adp-mmxf" for adp mmxf codec and
		node is "sound-adp-mmxf".
		node is "sound-adp-mmxf",
		"qcom,apq8096-asoc-snd-auto-custom" for auto custom codec and
		node is "sound-auto-custom".
- qcom,model : The user-visible name of this sound card.
- asoc-platform: This is phandle list containing the references to platform device
		nodes that are used as part of the sound card dai-links.
+294 −57
Original line number Diff line number Diff line
@@ -118,6 +118,9 @@ static int msm_ec_ref_ch = 4;
static int msm_ec_ref_bit_format = SNDRV_PCM_FORMAT_S16_LE;
static int msm_ec_ref_sampling_rate = SAMPLING_RATE_48KHZ;

static int msm_tdm_slot_width = 32;
static int msm_tdm_num_slots = 8;

static void *adsp_state_notifier;
static bool dummy_device_registered;

@@ -298,6 +301,62 @@ static unsigned int tdm_slot_offset_adp_mmxf[TDM_MAX][TDM_SLOT_OFFSET_MAX] = {
	{0xFFFF}, /* not used */
};

static unsigned int tdm_slot_offset_custom[TDM_MAX][TDM_SLOT_OFFSET_MAX] = {
	/* QUAT_TDM_RX */
	{0, 2, 0xFFFF},
	{4, 6, 8, 10, 12, 14, 16, 18},
	{20, 22, 24, 26, 28, 30, 0xFFFF},
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	/* QUAT_TDM_TX */
	{0, 2, 0xFFFF},
	{4, 6, 8, 10, 12, 14, 16, 18},
	{20, 22, 24, 26, 28, 30, 0xFFFF},
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	/* TERT_TDM_RX */
	{0, 2, 0xFFFF},
	{4, 0xFFFF},
	{6, 0xFFFF},
	{8, 0xFFFF},
	{10, 0xFFFF},
	{12, 14, 16, 18, 20, 22, 24, 26},
	{28, 30, 0xFFFF},
	{0xFFFF}, /* not used */
	/* TERT_TDM_TX */
	{0, 2, 4, 6, 8, 10, 12, 0xFFFF},
	{14, 16, 0xFFFF},
	{18, 20, 22, 24, 26, 28, 30, 0xFFFF},
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	/* SEC_TDM_RX */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	/* SEC_TDM_TX */
	{0xFFFF},
	{0xFFFF},
	{0xFFFF},
	{0xFFFF},
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
	{0xFFFF}, /* not used */
};

static char const *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five",
					"Six", "Seven", "Eight"};
@@ -2316,13 +2375,12 @@ static int apq8096_tdm_snd_hw_params(struct snd_pcm_substream *substream,
	pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id);

	channels = params_channels(params);
	switch (channels) {
	case 1:
	case 2:
	case 3:
	case 4:
	case 6:
	case 8:
	if (channels < 1 || channels > 8) {
		pr_err("%s: invalid param channels %d\n",
			__func__, channels);
		return -EINVAL;
	}

	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S32_LE:
	case SNDRV_PCM_FORMAT_S24_LE:
@@ -2332,14 +2390,15 @@ static int apq8096_tdm_snd_hw_params(struct snd_pcm_substream *substream,
		 * use 32 bit slot width for max support of
		 * stream bit width. (slot_width > bit_width)
		 */
			slot_width = 32;
		slot_width = msm_tdm_slot_width;
		break;
	default:
		pr_err("%s: invalid param format 0x%x\n",
			__func__, params_format(params));
		return -EINVAL;
	}
		slots = 8;

	slots = msm_tdm_num_slots;
	slot_mask = tdm_param_set_slot_mask(cpu_dai->id,
		slot_width, slots);
	if (!slot_mask) {
@@ -2347,12 +2406,6 @@ static int apq8096_tdm_snd_hw_params(struct snd_pcm_substream *substream,
			__func__, slot_mask);
		return -EINVAL;
	}
		break;
	default:
		pr_err("%s: invalid param channels %d\n",
			__func__, channels);
		return -EINVAL;
	}

	switch (cpu_dai->id) {
	case AFE_PORT_ID_SECONDARY_TDM_RX:
@@ -2725,7 +2778,7 @@ static int apq8096_get_ll_qos_val(struct snd_pcm_runtime *runtime)
	return usecs;
}

static int apq8096_mm5_prepare(struct snd_pcm_substream *substream)
static int apq8096_ll_prepare(struct snd_pcm_substream *substream)
{
	if (pm_qos_request_active(&substream->latency_pm_qos_req))
		pm_qos_remove_request(&substream->latency_pm_qos_req);
@@ -2735,8 +2788,8 @@ static int apq8096_mm5_prepare(struct snd_pcm_substream *substream)
	return 0;
}

static struct snd_soc_ops apq8096_mm5_ops = {
	.prepare = apq8096_mm5_prepare,
static struct snd_soc_ops apq8096_ll_ops = {
	.prepare = apq8096_ll_prepare,
};

/* Digital audio interface glue - connects codec <---> CPU */
@@ -3003,7 +3056,7 @@ static struct snd_soc_dai_link apq8096_common_dai_links[] = {
		/* this dainlink has playback support */
		.ignore_pmdown_time = 1,
		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
		.ops = &apq8096_mm5_ops,
		.ops = &apq8096_ll_ops,
	},
	{
		.name = "Listen 1 Audio Service",
@@ -3712,6 +3765,143 @@ static struct snd_soc_dai_link apq8096_auto_fe_dai_links[] = {
	},
};

static struct snd_soc_dai_link apq8096_custom_fe_dai_links[] = {
	/* FrontEnd DAI Links */
	{
		.name = "MSM8996 Media1",
		.stream_name = "MultiMedia1",
		.cpu_dai_name = "MultiMedia1",
		.platform_name = "msm-pcm-dsp.1",
		.dynamic = 1,
		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
		.dpcm_playback = 1,
		.dpcm_capture = 1,
		.codec_dai_name = "snd-soc-dummy-dai",
		.codec_name = "snd-soc-dummy",
		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
				SND_SOC_DPCM_TRIGGER_POST},
		.ignore_suspend = 1,
		/* this dainlink has playback support */
		.ignore_pmdown_time = 1,
		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA1,
		.ops = &apq8096_ll_ops,
	},
	{
		.name = "MSM8996 Media2",
		.stream_name = "MultiMedia2",
		.cpu_dai_name = "MultiMedia2",
		.platform_name = "msm-pcm-dsp.1",
		.dynamic = 1,
		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
		.dpcm_playback = 1,
		.dpcm_capture = 1,
		.codec_dai_name = "snd-soc-dummy-dai",
		.codec_name = "snd-soc-dummy",
		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
				SND_SOC_DPCM_TRIGGER_POST},
		.ignore_suspend = 1,
		/* this dainlink has playback support */
		.ignore_pmdown_time = 1,
		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
		.ops = &apq8096_ll_ops,
	},
	{
		.name = "MSM8996 Media3",
		.stream_name = "MultiMedia3",
		.cpu_dai_name = "MultiMedia3",
		.platform_name = "msm-pcm-dsp.1",
		.dynamic = 1,
		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
		.dpcm_playback = 1,
		.dpcm_capture = 1,
		.codec_dai_name = "snd-soc-dummy-dai",
		.codec_name = "snd-soc-dummy",
		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
				SND_SOC_DPCM_TRIGGER_POST},
		.ignore_suspend = 1,
		/* this dainlink has playback support */
		.ignore_pmdown_time = 1,
		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
		.ops = &apq8096_ll_ops,
	},
	{
		.name = "MSM8996 Media5",
		.stream_name = "MultiMedia5",
		.cpu_dai_name = "MultiMedia5",
		.platform_name = "msm-pcm-dsp.1",
		.dynamic = 1,
		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
		.dpcm_playback = 1,
		.dpcm_capture = 1,
		.codec_dai_name = "snd-soc-dummy-dai",
		.codec_name = "snd-soc-dummy",
		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
				SND_SOC_DPCM_TRIGGER_POST},
		.ignore_suspend = 1,
		/* this dainlink has playback support */
		.ignore_pmdown_time = 1,
		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
		.ops = &apq8096_ll_ops,
	},
	{
		.name = "MSM8996 Media6",
		.stream_name = "MultiMedia6",
		.cpu_dai_name = "MultiMedia6",
		.platform_name = "msm-pcm-dsp.1",
		.dynamic = 1,
		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
		.dpcm_playback = 1,
		.dpcm_capture = 1,
		.codec_dai_name = "snd-soc-dummy-dai",
		.codec_name = "snd-soc-dummy",
		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
				SND_SOC_DPCM_TRIGGER_POST},
		.ignore_suspend = 1,
		/* this dainlink has playback support */
		.ignore_pmdown_time = 1,
		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA6,
		.ops = &apq8096_ll_ops,
	},
	{
		.name = "MSM8996 Media8",
		.stream_name = "MultiMedia8",
		.cpu_dai_name = "MultiMedia8",
		.platform_name = "msm-pcm-dsp.1",
		.dynamic = 1,
		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
		.dpcm_playback = 1,
		.dpcm_capture = 1,
		.codec_dai_name = "snd-soc-dummy-dai",
		.codec_name = "snd-soc-dummy",
		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
				SND_SOC_DPCM_TRIGGER_POST},
		.ignore_suspend = 1,
		/* this dainlink has playback support */
		.ignore_pmdown_time = 1,
		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
		.ops = &apq8096_ll_ops,
	},
	{
		.name = "MSM8996 Media9",
		.stream_name = "MultiMedia9",
		.cpu_dai_name = "MultiMedia9",
		.platform_name = "msm-pcm-dsp.1",
		.dynamic = 1,
		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
		.dpcm_playback = 1,
		.dpcm_capture = 1,
		.codec_dai_name = "snd-soc-dummy-dai",
		.codec_name = "snd-soc-dummy",
		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
				SND_SOC_DPCM_TRIGGER_POST},
		.ignore_suspend = 1,
		/* this dainlink has playback support */
		.ignore_pmdown_time = 1,
		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA9,
		.ops = &apq8096_ll_ops,
	},
};

static struct snd_soc_dai_link apq8096_common_be_dai_links[] = {
	/* Backend AFE DAI Links */
	{
@@ -4194,6 +4384,13 @@ static struct snd_soc_dai_link apq8096_auto_dai_links[
			 ARRAY_SIZE(apq8096_auto_be_dai_links) +
			 ARRAY_SIZE(apq8096_hdmi_dai_link)];

static struct snd_soc_dai_link apq8096_auto_custom_dai_links[
			 ARRAY_SIZE(apq8096_custom_fe_dai_links) +
			 ARRAY_SIZE(apq8096_auto_fe_dai_links) +
			 ARRAY_SIZE(apq8096_common_be_dai_links) +
			 ARRAY_SIZE(apq8096_auto_be_dai_links) +
			 ARRAY_SIZE(apq8096_hdmi_dai_link)];

struct snd_soc_card snd_soc_card_auto_apq8096 = {
	.name = "apq8096-auto-snd-card",
};
@@ -4206,6 +4403,10 @@ struct snd_soc_card snd_soc_card_adp_mmxf_apq8096 = {
	.name = "apq8096-adp-mmxf-snd-card",
};

struct snd_soc_card snd_soc_card_auto_custom_apq8096 = {
	.name = "apq8096-auto-custom-snd-card",
};

static int apq8096_populate_dai_link_component_of_node(
					struct snd_soc_card *card)
{
@@ -4299,6 +4500,8 @@ static const struct of_device_id apq8096_asoc_machine_of_match[] = {
	  .data = "adp_agave_codec"},
	{ .compatible = "qcom,apq8096-asoc-snd-adp-mmxf",
	  .data = "adp_mmxf_codec"},
	{ .compatible = "qcom,apq8096-asoc-snd-auto-custom",
	  .data = "auto_custom_codec"},
	{},
};

@@ -4322,13 +4525,35 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
		card = &snd_soc_card_adp_agave_apq8096;
	else if (!strcmp(match->data, "adp_mmxf_codec"))
		card = &snd_soc_card_adp_mmxf_apq8096;
	else {
	else if (!strcmp(match->data, "auto_custom_codec")) {
		card = &snd_soc_card_auto_custom_apq8096;
	} else {
		dev_err(dev, "%s: Codec not supported\n",
			__func__);
		return NULL;
	}

	/* same FE and BE used for all codec */
	if (!strcmp(match->data, "auto_custom_codec")) {
		len_1 = ARRAY_SIZE(apq8096_custom_fe_dai_links);
		len_2 = len_1 + ARRAY_SIZE(apq8096_auto_fe_dai_links);
		len_3 = len_2 + ARRAY_SIZE(apq8096_common_be_dai_links);

		memcpy(apq8096_auto_custom_dai_links,
			apq8096_custom_fe_dai_links,
			sizeof(apq8096_custom_fe_dai_links));
		memcpy(apq8096_auto_custom_dai_links + len_1,
			apq8096_auto_fe_dai_links,
			sizeof(apq8096_auto_fe_dai_links));
		memcpy(apq8096_auto_custom_dai_links + len_2,
			apq8096_common_be_dai_links,
			sizeof(apq8096_common_be_dai_links));
		memcpy(apq8096_auto_custom_dai_links + len_3,
			apq8096_auto_be_dai_links,
			sizeof(apq8096_auto_be_dai_links));

		dailink = apq8096_auto_custom_dai_links;
	} else {
		/* same FE and BE used for all non-custom codec */
		len_1 = ARRAY_SIZE(apq8096_common_dai_links);
		len_2 = len_1 + ARRAY_SIZE(apq8096_auto_fe_dai_links);
		len_3 = len_2 + ARRAY_SIZE(apq8096_common_be_dai_links);
@@ -4347,6 +4572,8 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
			sizeof(apq8096_auto_be_dai_links));

		dailink = apq8096_auto_dai_links;
	}

	len_4 = len_3 + ARRAY_SIZE(apq8096_auto_be_dai_links);

	if (of_property_read_bool(dev->of_node, "qcom,hdmi-audio-rx")) {
@@ -4387,10 +4614,20 @@ static int apq8096_init_tdm_dev(struct device *dev)
		memcpy(tdm_slot_offset,
			tdm_slot_offset_adp_mmxf,
			sizeof(tdm_slot_offset_adp_mmxf));
	} else if (!strcmp(match->data, "auto_custom_codec")) {
		dev_dbg(dev, "%s: custom tdm slot offset\n", __func__);
		msm_tdm_slot_width = 16;
		msm_tdm_num_slots = 16;
		memcpy(tdm_slot_offset,
			tdm_slot_offset_custom,
			sizeof(tdm_slot_offset_custom));
	} else {
		dev_dbg(dev, "%s: DEFAULT tdm slot offset\n", __func__);
	}

	dev_dbg(dev, "%s: tdm slot_width %d, num_slots %d\n",
		__func__, msm_tdm_slot_width, msm_tdm_num_slots);

	return 0;
}