summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-04-04 12:10:25 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-04-04 12:10:25 -0700
commit835bd1f84a61dbcdee370e6d17f7d64aa74fbb16 (patch)
tree0a35f554b2097b99ca5e3bdbbd08fec5e5963c3e
parent025198c38230defaee679f1b5727e814a29020a6 (diff)
parent55df1580aa9ca4041e135abdeea578ba7aa376b0 (diff)
Merge "ASoC: msm: support 5 and 7 channel for TDM hw param"
-rw-r--r--Documentation/devicetree/bindings/sound/qcom-audio-dev.txt4
-rw-r--r--sound/soc/msm/apq8096-auto.c351
2 files changed, 297 insertions, 58 deletions
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 6f0d99d560cd..acf12239c813 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -2107,7 +2107,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.
diff --git a/sound/soc/msm/apq8096-auto.c b/sound/soc/msm/apq8096-auto.c
index 138f4a02452c..7b363bdca291 100644
--- a/sound/soc/msm/apq8096-auto.c
+++ b/sound/soc/msm/apq8096-auto.c
@@ -115,6 +115,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;
@@ -295,6 +298,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"};
@@ -2256,44 +2315,38 @@ 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:
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S32_LE:
- case SNDRV_PCM_FORMAT_S24_LE:
- case SNDRV_PCM_FORMAT_S16_LE:
- /*
- * up to 8 channel HW configuration should
- * use 32 bit slot width for max support of
- * stream bit width. (slot_width > bit_width)
- */
- slot_width = 32;
- break;
- default:
- pr_err("%s: invalid param format 0x%x\n",
- __func__, params_format(params));
- return -EINVAL;
- }
- slots = 8;
- slot_mask = tdm_param_set_slot_mask(cpu_dai->id,
- slot_width, slots);
- if (!slot_mask) {
- pr_err("%s: invalid slot_mask 0x%x\n",
- __func__, slot_mask);
- return -EINVAL;
- }
- break;
- default:
+ 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:
+ case SNDRV_PCM_FORMAT_S16_LE:
+ /*
+ * up to 8 channel HW configuration should
+ * use 32 bit slot width for max support of
+ * stream bit width. (slot_width > bit_width)
+ */
+ slot_width = msm_tdm_slot_width;
+ break;
+ default:
+ pr_err("%s: invalid param format 0x%x\n",
+ __func__, params_format(params));
+ return -EINVAL;
+ }
+
+ slots = msm_tdm_num_slots;
+ slot_mask = tdm_param_set_slot_mask(cpu_dai->id,
+ slot_width, slots);
+ if (!slot_mask) {
+ pr_err("%s: invalid slot_mask 0x%x\n",
+ __func__, slot_mask);
+ return -EINVAL;
+ }
+
switch (cpu_dai->id) {
case AFE_PORT_ID_SECONDARY_TDM_RX:
slot_offset = tdm_slot_offset[SECONDARY_TDM_RX_0];
@@ -2660,7 +2713,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);
@@ -2670,8 +2723,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 */
@@ -2938,7 +2991,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",
@@ -3647,6 +3700,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 */
{
@@ -4115,6 +4305,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",
};
@@ -4127,6 +4324,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)
{
@@ -4220,6 +4421,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"},
{},
};
@@ -4243,31 +4446,55 @@ 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 */
- 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);
-
- memcpy(apq8096_auto_dai_links,
- apq8096_common_dai_links,
- sizeof(apq8096_common_dai_links));
- memcpy(apq8096_auto_dai_links + len_1,
- apq8096_auto_fe_dai_links,
- sizeof(apq8096_auto_fe_dai_links));
- memcpy(apq8096_auto_dai_links + len_2,
- apq8096_common_be_dai_links,
- sizeof(apq8096_common_be_dai_links));
- memcpy(apq8096_auto_dai_links + len_3,
- apq8096_auto_be_dai_links,
- sizeof(apq8096_auto_be_dai_links));
-
- dailink = apq8096_auto_dai_links;
+ 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);
+
+ memcpy(apq8096_auto_dai_links,
+ apq8096_common_dai_links,
+ sizeof(apq8096_common_dai_links));
+ memcpy(apq8096_auto_dai_links + len_1,
+ apq8096_auto_fe_dai_links,
+ sizeof(apq8096_auto_fe_dai_links));
+ memcpy(apq8096_auto_dai_links + len_2,
+ apq8096_common_be_dai_links,
+ sizeof(apq8096_common_be_dai_links));
+ memcpy(apq8096_auto_dai_links + len_3,
+ apq8096_auto_be_dai_links,
+ 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")) {
@@ -4308,10 +4535,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;
}