Merge "ASoC: msm: support 5 and 7 channel for TDM hw param"
This commit is contained in:
commit
835bd1f84a
2 changed files with 295 additions and 56 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
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_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));
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue