diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index 00cba88b6082..a1d8b04d08ac 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -625,11 +625,30 @@ struct audproc_softvolume_params { */ #define AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT 0x00010913 +/* ID of the Channel Mixer module, which is used to configure + * channel-mixer related parameters. + * This module supports the AUDPROC_CHMIXER_PARAM_ID_COEFF parameter ID. + */ +#define AUDPROC_MODULE_ID_CHMIXER 0x00010341 + /* ID of the Coefficient parameter used by AUDPROC_MODULE_ID_CHMIXER to *configure the channel mixer weighting coefficients. */ #define AUDPROC_CHMIXER_PARAM_ID_COEFF 0x00010342 +/* Payload of the per-session, per-device parameter data of the + * #ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5 command or + * #ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V6 command. + * Immediately following this structure are param_size bytes of parameter + * data. The structure and size depend on the module_id/param_id pair. + */ +struct adm_pspd_param_data_t { + uint32_t module_id; + uint32_t param_id; + uint16_t param_size; + uint16_t reserved; +} __packed; + struct audproc_mfc_output_media_fmt { struct adm_cmd_set_pp_params_v5 params; struct adm_param_data_v5 data; diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c index 24dbbedf0be7..cc89408fcb39 100644 --- a/sound/soc/msm/msm-dai-fe.c +++ b/sound/soc/msm/msm-dai-fe.c @@ -2641,6 +2641,101 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .name = "MultiMedia20", .probe = fe_dai_probe, }, + { + .playback = { + .stream_name = "MultiMedia21 Playback", + .aif_name = "MM_DL21", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia21", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "MultiMedia22 Playback", + .aif_name = "MM_DL22", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia22", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "MultiMedia23 Playback", + .aif_name = "MM_DL23", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia23", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "MultiMedia24 Playback", + .aif_name = "MM_DL24", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia24", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "MultiMedia25 Playback", + .aif_name = "MM_DL25", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia25", + .probe = fe_dai_probe, + }, }; static int msm_fe_dai_dev_probe(struct platform_device *pdev) diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index 46a3324d2d6b..de769e8b806c 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -1603,6 +1603,262 @@ done: return ret; } +static int msm_pcm_playback_pan_scale_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = 0; + int len = 0; + int i = 0; + struct snd_pcm_usr *usr_info = snd_kcontrol_chip(kcontrol); + struct snd_pcm_substream *substream; + struct msm_audio *prtd; + struct asm_stream_pan_ctrl_params pan_param; + + if (!usr_info) { + pr_err("%s: usr_info is null\n", __func__); + ret = -EINVAL; + goto done; + } + + substream = usr_info->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + if (!substream) { + pr_err("%s substream not found\n", __func__); + ret = -EINVAL; + goto done; + } + + if (!substream->runtime) { + pr_err("%s substream runtime not found\n", __func__); + ret = -EINVAL; + goto done; + } + prtd = substream->runtime->private_data; + if (!prtd) { + ret = -EINVAL; + goto done; + } + pan_param.num_output_channels = + ucontrol->value.integer.value[len++]; + if (pan_param.num_output_channels > + PCM_FORMAT_MAX_NUM_CHANNEL) { + ret = -EINVAL; + goto done; + } + pan_param.num_input_channels = + ucontrol->value.integer.value[len++]; + if (pan_param.num_input_channels > + PCM_FORMAT_MAX_NUM_CHANNEL) { + ret = -EINVAL; + goto done; + } + + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < pan_param.num_output_channels; i++) { + pan_param.output_channel_map[i] = + ucontrol->value.integer.value[len++]; + } + } + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < pan_param.num_input_channels; i++) { + pan_param.input_channel_map[i] = + ucontrol->value.integer.value[len++]; + } + } + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < pan_param.num_output_channels * + pan_param.num_input_channels; i++) { + pan_param.gain[i] = + !(ucontrol->value.integer.value[len++] > 0) ? + 0 : 2 << 13; + } + } + + ret = q6asm_set_mfc_panning_params(prtd->audio_client, + &pan_param); + len -= pan_param.num_output_channels * + pan_param.num_input_channels; + for (i = 0; i < pan_param.num_output_channels * + pan_param.num_input_channels; i++) { + pan_param.gain[i] = + ucontrol->value.integer.value[len++]; + } + ret = q6asm_set_vol_ctrl_gain_pair(prtd->audio_client, + &pan_param); + +done: + return ret; +} + +static int msm_pcm_playback_pan_scale_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int msm_add_stream_pan_scale_controls(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm; + struct snd_pcm_usr *pan_ctl_info; + struct snd_kcontrol *kctl; + const char *playback_mixer_ctl_name = "Audio Stream"; + const char *deviceNo = "NN"; + const char *suffix = "Pan Scale Control"; + int ctl_len, ret = 0; + + if (!rtd) { + pr_err("%s: rtd is NULL\n", __func__); + ret = -EINVAL; + goto done; + } + + pcm = rtd->pcm; + ctl_len = strlen(playback_mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + + strlen(suffix) + 1; + + ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, + NULL, 1, ctl_len, rtd->dai_link->be_id, + &pan_ctl_info); + + if (ret < 0) { + pr_err("%s: failed add ctl %s. err = %d\n", + __func__, suffix, ret); + goto done; + } + kctl = pan_ctl_info->kctl; + snprintf(kctl->id.name, ctl_len, "%s %d %s", playback_mixer_ctl_name, + rtd->pcm->device, suffix); + kctl->put = msm_pcm_playback_pan_scale_ctl_put; + kctl->get = msm_pcm_playback_pan_scale_ctl_get; + pr_debug("%s: Registering new mixer ctl = %s\n", __func__, + kctl->id.name); +done: + return ret; + +} + +static int msm_pcm_playback_dnmix_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int msm_pcm_playback_dnmix_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = 0; + int len = 0; + int i = 0; + struct snd_pcm_usr *usr_info = snd_kcontrol_chip(kcontrol); + struct snd_pcm_substream *substream; + struct msm_audio *prtd; + struct asm_stream_pan_ctrl_params dnmix_param; + + int be_id = ucontrol->value.integer.value[len]; + int stream_id = 0; + + if (!usr_info) { + pr_err("%s usr_info is null\n", __func__); + ret = -EINVAL; + goto done; + } + substream = usr_info->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + if (!substream) { + pr_err("%s substream not found\n", __func__); + ret = -EINVAL; + goto done; + } + if (!substream->runtime) { + pr_err("%s substream runtime not found\n", __func__); + ret = -EINVAL; + goto done; + } + prtd = substream->runtime->private_data; + if (!prtd) { + ret = -EINVAL; + goto done; + } + stream_id = prtd->audio_client->session; + dnmix_param.num_output_channels = + ucontrol->value.integer.value[len++]; + if (dnmix_param.num_output_channels > + PCM_FORMAT_MAX_NUM_CHANNEL) { + ret = -EINVAL; + goto done; + } + dnmix_param.num_input_channels = + ucontrol->value.integer.value[len++]; + if (dnmix_param.num_input_channels > + PCM_FORMAT_MAX_NUM_CHANNEL) { + ret = -EINVAL; + goto done; + } + + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < dnmix_param.num_output_channels; i++) { + dnmix_param.output_channel_map[i] = + ucontrol->value.integer.value[len++]; + } + } + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < dnmix_param.num_input_channels; i++) { + dnmix_param.input_channel_map[i] = + ucontrol->value.integer.value[len++]; + } + } + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < dnmix_param.num_output_channels * + dnmix_param.num_input_channels; i++) { + dnmix_param.gain[i] = + ucontrol->value.integer.value[len++]; + } + } + msm_routing_set_downmix_control_data(be_id, + stream_id, + &dnmix_param); + +done: + return ret; +} + +static int msm_add_device_down_mix_controls(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm; + struct snd_pcm_usr *usr_info; + struct snd_kcontrol *kctl; + const char *playback_mixer_ctl_name = "Audio Device"; + const char *deviceNo = "NN"; + const char *suffix = "Downmix Control"; + int ctl_len, ret = 0; + + if (!rtd) { + pr_err("%s: rtd is NULL\n", __func__); + ret = -EINVAL; + goto done; + } + + pcm = rtd->pcm; + ctl_len = strlen(playback_mixer_ctl_name) + 1 + + strlen(deviceNo) + 1 + strlen(suffix) + 1; + ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, + NULL, 1, ctl_len, rtd->dai_link->be_id, + &usr_info); + if (ret < 0) { + pr_err("%s: downmix control add failed: %d\n", + __func__, ret); + goto done; + } + + kctl = usr_info->kctl; + snprintf(kctl->id.name, ctl_len, "%s %d %s", + playback_mixer_ctl_name, rtd->pcm->device, suffix); + kctl->put = msm_pcm_playback_dnmix_ctl_put; + kctl->get = msm_pcm_playback_dnmix_ctl_get; + pr_debug("%s: downmix control name = %s\n", + __func__, playback_mixer_ctl_name); +done: + return ret; +} + static int msm_pcm_capture_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1719,6 +1975,14 @@ static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd) if (ret) pr_err("%s: pcm add app type controls failed:%d\n", __func__, ret); + ret = msm_add_stream_pan_scale_controls(rtd); + if (ret) + pr_err("%s: pcm add pan scale controls failed:%d\n", + __func__, ret); + ret = msm_add_device_down_mix_controls(rtd); + if (ret) + pr_err("%s: pcm add dnmix controls failed:%d\n", + __func__, ret); return ret; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 974d4a582540..bf7a9ef07ed3 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include "msm-pcm-routing-v2.h" #include "msm-pcm-routing-devdep.h" @@ -4090,6 +4092,21 @@ static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_SLIMBUS_0_RX, MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia23", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA23, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia24", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA24, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia25", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA25, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new mi2s_rx_mixer_controls[] = { @@ -4612,6 +4629,21 @@ static const struct snd_kcontrol_new hdmi_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_HDMI_RX, MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia23", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA23, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia24", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA24, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia25", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA25, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new display_port_mixer_controls[] = { @@ -4760,6 +4792,21 @@ static const struct snd_kcontrol_new slimbus_6_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SLIMBUS_6_RX, MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia23", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA23, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia24", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA24, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia25", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA25, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new slimbus_7_rx_mixer_controls[] = { @@ -4811,6 +4858,21 @@ static const struct snd_kcontrol_new slimbus_7_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SLIMBUS_7_RX, MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia23", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA23, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia24", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA24, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia25", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA25, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new usb_audio_rx_mixer_controls[] = { @@ -11314,6 +11376,11 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_IN("MM_DL15", "MultiMedia15 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("MM_DL16", "MultiMedia16 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("MM_DL20", "MultiMedia20 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL21", "MultiMedia21 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL22", "MultiMedia22 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL23", "MultiMedia23 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL24", "MultiMedia24 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL25", "MultiMedia25 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0), @@ -12450,6 +12517,11 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_0_RX Audio Mixer", "MultiMedia14", "MM_DL14"}, {"SLIMBUS_0_RX Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SLIMBUS_0_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia22", "MM_DL22"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia23", "MM_DL23"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia24", "MM_DL24"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia25", "MM_DL25"}, {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"}, {"SLIMBUS_2_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, @@ -12504,6 +12576,11 @@ static const struct snd_soc_dapm_route intercon[] = { {"HDMI Mixer", "MultiMedia14", "MM_DL14"}, {"HDMI Mixer", "MultiMedia15", "MM_DL15"}, {"HDMI Mixer", "MultiMedia16", "MM_DL16"}, + {"HDMI Mixer", "MultiMedia21", "MM_DL21"}, + {"HDMI Mixer", "MultiMedia22", "MM_DL22"}, + {"HDMI Mixer", "MultiMedia23", "MM_DL23"}, + {"HDMI Mixer", "MultiMedia24", "MM_DL24"}, + {"HDMI Mixer", "MultiMedia25", "MM_DL25"}, {"HDMI", NULL, "HDMI Mixer"}, {"DISPLAY_PORT Mixer", "MultiMedia1", "MM_DL1"}, @@ -12575,6 +12652,11 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_6_RX Audio Mixer", "MultiMedia14", "MM_DL14"}, {"SLIMBUS_6_RX Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SLIMBUS_6_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia22", "MM_DL22"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia23", "MM_DL23"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia24", "MM_DL24"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia25", "MM_DL25"}, {"SLIMBUS_6_RX", NULL, "SLIMBUS_6_RX Audio Mixer"}, {"SLIMBUS_7_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, @@ -12593,6 +12675,11 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_7_RX Audio Mixer", "MultiMedia14", "MM_DL14"}, {"SLIMBUS_7_RX Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SLIMBUS_7_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia22", "MM_DL22"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia23", "MM_DL23"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia24", "MM_DL24"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia25", "MM_DL25"}, {"SLIMBUS_7_RX", NULL, "SLIMBUS_7_RX Audio Mixer"}, {"USB_AUDIO_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, @@ -15486,6 +15573,93 @@ static struct snd_pcm_ops msm_routing_pcm_ops = { .prepare = msm_pcm_routing_prepare, }; +int msm_routing_set_downmix_control_data(int be_id, int session_id, + struct asm_stream_pan_ctrl_params *dnmix_param) +{ + int i, rc = 0; + struct adm_pspd_param_data_t data; + struct audproc_chmixer_param_coeff dnmix_cfg; + uint16_t variable_payload = 0; + char *adm_params = NULL; + int port_id, copp_idx = 0; + uint32_t params_length = 0; + + if (be_id >= MSM_BACKEND_DAI_MAX) { + rc = -EINVAL; + return rc; + } + port_id = msm_bedais[be_id].port_id; + copp_idx = adm_get_default_copp_idx(port_id); + pr_debug("%s: port_id - %d, copp_idx %d session id - %d\n", + __func__, port_id, copp_idx, session_id); + + variable_payload = dnmix_param->num_output_channels * sizeof(uint16_t)+ + dnmix_param->num_input_channels * sizeof(uint16_t) + + dnmix_param->num_output_channels * sizeof(uint16_t) * + dnmix_param->num_input_channels * sizeof(uint16_t); + i = (variable_payload % sizeof(uint32_t)); + variable_payload += (i == 0) ? 0 : sizeof(uint32_t) - i; + + params_length = variable_payload + + sizeof(struct adm_pspd_param_data_t) + + sizeof(struct audproc_chmixer_param_coeff); + adm_params = kzalloc(params_length, GFP_KERNEL); + if (!adm_params) { + rc = -ENOMEM; + goto end; + } + + data.module_id = AUDPROC_MODULE_ID_CHMIXER; + data.param_id = AUDPROC_CHMIXER_PARAM_ID_COEFF; + data.param_size = sizeof(struct audproc_chmixer_param_coeff) + + variable_payload; + data.reserved = 0; + memcpy((u8 *)adm_params, &data, sizeof(struct adm_pspd_param_data_t)); + + dnmix_cfg.index = 0; + dnmix_cfg.num_output_channels = dnmix_param->num_output_channels; + dnmix_cfg.num_input_channels = dnmix_param->num_input_channels; + memcpy(((u8 *)adm_params + + sizeof(struct adm_pspd_param_data_t)), + &dnmix_cfg, sizeof(struct audproc_chmixer_param_coeff)); + + memcpy(((u8 *)adm_params + + sizeof(struct adm_pspd_param_data_t) + + sizeof(struct audproc_chmixer_param_coeff)), + dnmix_param->output_channel_map, + dnmix_param->num_output_channels * sizeof(uint16_t)); + memcpy(((u8 *)adm_params + + sizeof(struct adm_pspd_param_data_t) + + sizeof(struct audproc_chmixer_param_coeff) + + dnmix_param->num_output_channels * sizeof(uint16_t)), + dnmix_param->input_channel_map, + dnmix_param->num_input_channels * sizeof(uint16_t)); + memcpy(((u8 *)adm_params + + sizeof(struct adm_pspd_param_data_t) + + sizeof(struct audproc_chmixer_param_coeff) + + (dnmix_param->num_output_channels * sizeof(uint16_t)) + + (dnmix_param->num_input_channels * sizeof(uint16_t))), + dnmix_param->gain, + (dnmix_param->num_output_channels * sizeof(uint16_t)) * + (dnmix_param->num_input_channels * sizeof(uint16_t))); + + if (params_length) { + rc = adm_set_pspd_matrix_params(port_id, + copp_idx, + session_id, + adm_params, + params_length); + if (rc) { + pr_err("%s: send params failed rc=%d\n", __func__, rc); + rc = -EINVAL; + } + } +end: + kfree(adm_params); + return rc; +} + + /* Not used but frame seems to require it */ static int msm_routing_probe(struct snd_soc_platform *platform) { diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h index 19e726001d25..fa948abd1b4c 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h @@ -193,6 +193,11 @@ enum { MSM_FRONTEND_DAI_MULTIMEDIA18, MSM_FRONTEND_DAI_MULTIMEDIA19, MSM_FRONTEND_DAI_MULTIMEDIA20, + MSM_FRONTEND_DAI_MULTIMEDIA21, + MSM_FRONTEND_DAI_MULTIMEDIA22, + MSM_FRONTEND_DAI_MULTIMEDIA23, + MSM_FRONTEND_DAI_MULTIMEDIA24, + MSM_FRONTEND_DAI_MULTIMEDIA25, MSM_FRONTEND_DAI_CS_VOICE, MSM_FRONTEND_DAI_VOIP, MSM_FRONTEND_DAI_AFE_RX, @@ -218,8 +223,8 @@ enum { MSM_FRONTEND_DAI_MAX, }; -#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA20 + 1) -#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA20 +#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA25 + 1) +#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA25 enum { MSM_BACKEND_DAI_PRI_I2S_RX = 0, @@ -483,4 +488,6 @@ int msm_pcm_routing_reg_stream_app_type_cfg( int msm_pcm_routing_get_stream_app_type_cfg( int fedai_id, int session_type, int *be_id, struct msm_pcm_stream_app_type_cfg *cfg_data); +int msm_routing_set_downmix_control_data(int be_id, int session_id, + struct asm_stream_pan_ctrl_params *pan_param); #endif /*_MSM_PCM_H*/