summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHonghao Liu <honghaol@codeaurora.org>2017-03-08 16:36:35 -0500
committerGerrit - the friendly Code Review server <code-review@localhost>2017-03-23 11:12:46 -0700
commitf7d9f43f02d3d2838a55414d15367dc91c1ce00a (patch)
treeb1836f0eab5ecb569b23fccfb026e87791d6dd7d
parent630218f7109215471e1f43c2200f6bdc98f92f93 (diff)
ASoC: msm: add support for customized sound card
Add support for customized sound card that uses customized TDM slot mapping and DAI links for automotive platform. CRs-fixed: 2020063 Change-Id: I887b33d23d2af8af61cf15b499d14afbc9544e37 Signed-off-by: Honghao Liu <honghaol@codeaurora.org>
-rw-r--r--Documentation/devicetree/bindings/sound/qcom-audio-dev.txt4
-rw-r--r--sound/soc/msm/apq8096-auto.c295
2 files changed, 272 insertions, 27 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..94367b5f680b 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"};
@@ -2272,14 +2331,14 @@ 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) {
@@ -2660,7 +2719,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 +2729,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 +2997,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 +3706,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 +4311,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 +4330,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 +4427,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 +4452,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 +4541,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;
}