Loading include/sound/apr_audio-v2.h +5 −0 Original line number Diff line number Diff line Loading @@ -443,6 +443,11 @@ struct adm_param_data_v5 { */ } __packed; #define ASM_STREAM_CMD_REGISTER_PP_EVENTS 0x00013213 #define ASM_STREAM_PP_EVENT 0x00013214 #define DSP_STREAM_CMD "ADSP Stream Cmd" #define DSP_STREAM_CALLBACK "ADSP Stream Callback Event" /* set customized mixing on matrix mixer */ #define ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5 0x00010344 struct adm_cmd_set_pspd_mtmx_strtr_params_v5 { Loading include/sound/q6asm-v2.h +3 −0 Original line number Diff line number Diff line Loading @@ -618,6 +618,9 @@ int q6asm_get_session_time_legacy(struct audio_client *ac, uint64_t *tstamp); int q6asm_send_audio_effects_params(struct audio_client *ac, char *params, uint32_t params_length); int q6asm_send_stream_cmd(struct audio_client *ac, uint32_t opcode, void *param, uint32_t params_length); /* Client can set the IO mode to either AIO/SIO mode */ int q6asm_set_io_mode(struct audio_client *ac, uint32_t mode); Loading sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +209 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ #include <sound/msm-dts-eagle.h> #include "msm-pcm-routing-v2.h" #include "msm-qti-pp-config.h" #define DSP_PP_BUFFERING_IN_MSEC 25 #define PARTIAL_DRAIN_ACK_EARLY_BY_MSEC 150 Loading Loading @@ -543,12 +544,19 @@ static void compr_event_handler(uint32_t opcode, unsigned long flags; uint64_t read_size; uint32_t *buff_addr; struct snd_soc_pcm_runtime *rtd; int ret = 0; if (!prtd) { pr_err("%s: prtd is NULL\n", __func__); return; } cstream = prtd->cstream; if (!cstream) { pr_err("%s: cstream is NULL\n", __func__); return; } ac = prtd->audio_client; /* Loading Loading @@ -715,6 +723,23 @@ static void compr_event_handler(uint32_t opcode, if (prtd->gapless_state.gapless_transition) prtd->gapless_state.gapless_transition = 0; spin_unlock_irqrestore(&prtd->lock, flags); break; case ASM_STREAM_PP_EVENT: pr_debug("%s: ASM_STREAM_PP_EVENT\n", __func__); rtd = cstream->private_data; if (!rtd) { pr_err("%s: rtd is NULL\n", __func__); return; } ret = msm_adsp_inform_mixer_ctl(rtd, DSP_STREAM_CALLBACK, payload); if (ret) { pr_err("%s: failed to inform mixer ctrl. err = %d\n", __func__, ret); return; } break; case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY: case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY: { Loading Loading @@ -815,6 +840,10 @@ static void compr_event_handler(uint32_t opcode, } atomic_set(&prtd->close, 0); break; case ASM_STREAM_CMD_REGISTER_PP_EVENTS: pr_debug("%s: ASM_STREAM_CMD_REGISTER_PP_EVENTS:", __func__); break; default: break; } Loading Loading @@ -3578,6 +3607,65 @@ end: return rc; } static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); unsigned long fe_id = kcontrol->private_value; struct msm_compr_pdata *pdata = (struct msm_compr_pdata *) snd_soc_component_get_drvdata(comp); struct snd_compr_stream *cstream = NULL; struct msm_compr_audio *prtd; int ret = 0, param_length = 0; if (fe_id >= MSM_FRONTEND_DAI_MAX) { pr_err("%s Received invalid fe_id %lu\n", __func__, fe_id); ret = -EINVAL; goto done; } cstream = pdata->cstream[fe_id]; if (cstream == NULL) { pr_err("%s cstream is null.\n", __func__); ret = -EINVAL; goto done; } prtd = cstream->runtime->private_data; if (!prtd) { pr_err("%s: prtd is null.\n", __func__); ret = -EINVAL; goto done; } if (prtd->audio_client == NULL) { pr_err("%s: audio_client is null.\n", __func__); ret = -EINVAL; goto done; } memcpy(¶m_length, ucontrol->value.bytes.data, sizeof(param_length)); if ((param_length + sizeof(param_length)) >= sizeof(ucontrol->value.bytes.data)) { pr_err("%s param length=%d exceeds limit", __func__, param_length); ret = -EINVAL; goto done; } ret = q6asm_send_stream_cmd(prtd->audio_client, ASM_STREAM_CMD_REGISTER_PP_EVENTS, ucontrol->value.bytes.data + sizeof(param_length), param_length); if (ret < 0) pr_err("%s: failed to register pp event. err = %d\n", __func__, ret); done: return ret; } static int msm_compr_gapless_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading Loading @@ -3854,6 +3942,117 @@ static int msm_compr_add_query_audio_effect_control( return 0; } static int msm_compr_add_audio_adsp_stream_cmd_control( struct snd_soc_pcm_runtime *rtd) { const char *mixer_ctl_name = DSP_STREAM_CMD; const char *deviceNo = "NN"; char *mixer_str = NULL; int ctl_len = 0, ret = 0; struct snd_kcontrol_new fe_audio_adsp_stream_cmd_config_control[1] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_adsp_stream_cmd_info, .put = msm_compr_adsp_stream_cmd_put, .private_value = 0, } }; if (!rtd) { pr_err("%s NULL rtd\n", __func__); ret = -EINVAL; goto done; } ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; mixer_str = kzalloc(ctl_len, GFP_KERNEL); if (!mixer_str) { ret = -ENOMEM; goto done; } snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); fe_audio_adsp_stream_cmd_config_control[0].name = mixer_str; fe_audio_adsp_stream_cmd_config_control[0].private_value = rtd->dai_link->be_id; pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str); ret = snd_soc_add_platform_controls(rtd->platform, fe_audio_adsp_stream_cmd_config_control, ARRAY_SIZE(fe_audio_adsp_stream_cmd_config_control)); if (ret < 0) pr_err("%s: failed to add ctl %s. err = %d\n", __func__, mixer_str, ret); kfree(mixer_str); done: return ret; } static int msm_compr_add_audio_adsp_stream_callback_control( struct snd_soc_pcm_runtime *rtd) { const char *mixer_ctl_name = DSP_STREAM_CALLBACK; const char *deviceNo = "NN"; char *mixer_str = NULL; int ctl_len = 0, ret = 0; struct snd_kcontrol *kctl; struct snd_kcontrol_new fe_audio_adsp_callback_config_control[1] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_adsp_stream_callback_info, .get = msm_adsp_stream_callback_get, .put = msm_adsp_stream_callback_put, .private_value = 0, } }; if (!rtd) { pr_err("%s: rtd is NULL\n", __func__); ret = -EINVAL; goto done; } ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; mixer_str = kzalloc(ctl_len, GFP_KERNEL); if (!mixer_str) { ret = -ENOMEM; goto done; } snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); fe_audio_adsp_callback_config_control[0].name = mixer_str; fe_audio_adsp_callback_config_control[0].private_value = rtd->dai_link->be_id; pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str); ret = snd_soc_add_platform_controls(rtd->platform, fe_audio_adsp_callback_config_control, ARRAY_SIZE(fe_audio_adsp_callback_config_control)); if (ret < 0) { pr_err("%s: failed to add ctl %s. err = %d\n", __func__, mixer_str, ret); ret = -EINVAL; goto free_mixer_str; } kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str); if (!kctl) { pr_err("%s: failed to get kctl %s.\n", __func__, mixer_str); ret = -EINVAL; goto free_mixer_str; } kctl->private_data = NULL; free_mixer_str: kfree(mixer_str); done: return ret; } static int msm_compr_add_dec_runtime_params_control( struct snd_soc_pcm_runtime *rtd) { Loading Loading @@ -4048,6 +4247,16 @@ static int msm_compr_new(struct snd_soc_pcm_runtime *rtd) pr_err("%s: Could not add Compr Audio Effects Control\n", __func__); rc = msm_compr_add_audio_adsp_stream_cmd_control(rtd); if (rc) pr_err("%s: Could not add Compr ADSP Stream Cmd Control\n", __func__); rc = msm_compr_add_audio_adsp_stream_callback_control(rtd); if (rc) pr_err("%s: Could not add Compr ADSP Stream Callback Control\n", __func__); rc = msm_compr_add_query_audio_effect_control(rtd); if (rc) pr_err("%s: Could not add Compr Query Audio Effect Control\n", Loading sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +211 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ #include "msm-pcm-q6-v2.h" #include "msm-pcm-routing-v2.h" #include "msm-qti-pp-config.h" enum stream_state { IDLE = 0, Loading Loading @@ -147,6 +148,8 @@ static void event_handler(uint32_t opcode, uint32_t idx = 0; uint32_t size = 0; uint8_t buf_index; struct snd_soc_pcm_runtime *rtd; int ret = 0; switch (opcode) { case ASM_DATA_EVENT_WRITE_DONE_V2: { Loading Loading @@ -223,6 +226,29 @@ static void event_handler(uint32_t opcode, } break; } case ASM_STREAM_PP_EVENT: { pr_debug("%s: ASM_STREAM_PP_EVENT\n", __func__); if (!substream) { pr_err("%s: substream is NULL.\n", __func__); return; } rtd = substream->private_data; if (!rtd) { pr_err("%s: rtd is NULL\n", __func__); return; } ret = msm_adsp_inform_mixer_ctl(rtd, DSP_STREAM_CALLBACK, payload); if (ret) { pr_err("%s: failed to inform mixer ctl. err = %d\n", __func__, ret); return; } break; } case APR_BASIC_RSP_RESULT: { switch (payload[0]) { case ASM_SESSION_CMD_RUN_V2: Loading Loading @@ -252,6 +278,10 @@ static void event_handler(uint32_t opcode, } atomic_set(&prtd->start, 1); break; case ASM_STREAM_CMD_REGISTER_PP_EVENTS: pr_debug("%s: ASM_STREAM_CMD_REGISTER_PP_EVENTS:", __func__); break; default: pr_debug("%s:Payload = [0x%x]stat[0x%x]\n", __func__, payload[0], payload[1]); Loading Loading @@ -1036,6 +1066,177 @@ static struct snd_pcm_ops msm_pcm_ops = { .mmap = msm_pcm_mmap, }; static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *pcm = snd_kcontrol_chip(kcontrol); struct snd_soc_platform *platform = snd_soc_component_to_platform(pcm); struct msm_plat_data *pdata = dev_get_drvdata(platform->dev); struct snd_pcm_substream *substream; struct msm_audio *prtd; int ret = 0, param_length = 0; if (!pdata) { pr_err("%s pdata is NULL\n", __func__); ret = -ENODEV; goto done; } substream = pdata->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->audio_client == NULL) { pr_err("%s prtd is null.\n", __func__); ret = -EINVAL; goto done; } memcpy(¶m_length, ucontrol->value.bytes.data, sizeof(param_length)); if ((param_length + sizeof(param_length)) >= sizeof(ucontrol->value.bytes.data)) { pr_err("%s param length=%d exceeds limit", __func__, param_length); ret = -EINVAL; goto done; } ret = q6asm_send_stream_cmd(prtd->audio_client, ASM_STREAM_CMD_REGISTER_PP_EVENTS, ucontrol->value.bytes.data + sizeof(param_length), param_length); if (ret < 0) pr_err("%s: failed to register pp event. err = %d\n", __func__, ret); done: return ret; } static int msm_pcm_add_audio_adsp_stream_cmd_control( struct snd_soc_pcm_runtime *rtd) { const char *mixer_ctl_name = DSP_STREAM_CMD; const char *deviceNo = "NN"; char *mixer_str = NULL; int ctl_len = 0, ret = 0; struct snd_kcontrol_new fe_audio_adsp_stream_cmd_config_control[1] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_adsp_stream_cmd_info, .put = msm_pcm_adsp_stream_cmd_put, .private_value = 0, } }; if (!rtd) { pr_err("%s rtd is NULL\n", __func__); ret = -EINVAL; goto done; } ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; mixer_str = kzalloc(ctl_len, GFP_KERNEL); if (!mixer_str) { ret = -ENOMEM; goto done; } snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); fe_audio_adsp_stream_cmd_config_control[0].name = mixer_str; fe_audio_adsp_stream_cmd_config_control[0].private_value = rtd->dai_link->be_id; pr_debug("Registering new mixer ctl %s\n", mixer_str); ret = snd_soc_add_platform_controls(rtd->platform, fe_audio_adsp_stream_cmd_config_control, ARRAY_SIZE(fe_audio_adsp_stream_cmd_config_control)); if (ret < 0) pr_err("%s: failed add ctl %s. err = %d\n", __func__, mixer_str, ret); kfree(mixer_str); done: return ret; } static int msm_pcm_add_audio_adsp_stream_callback_control( struct snd_soc_pcm_runtime *rtd) { const char *mixer_ctl_name = DSP_STREAM_CALLBACK; const char *deviceNo = "NN"; char *mixer_str = NULL; int ctl_len = 0, ret = 0; struct snd_kcontrol *kctl; struct snd_kcontrol_new fe_audio_adsp_callback_config_control[1] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_adsp_stream_callback_info, .get = msm_adsp_stream_callback_get, .put = msm_adsp_stream_callback_put, .private_value = 0, } }; if (!rtd) { pr_err("%s NULL rtd\n", __func__); ret = -EINVAL; goto done; } pr_debug("%s: added new pcm FE with name %s, id %d, cpu dai %s, device no %d\n", __func__, rtd->dai_link->name, rtd->dai_link->be_id, rtd->dai_link->cpu_dai_name, rtd->pcm->device); ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; mixer_str = kzalloc(ctl_len, GFP_KERNEL); if (!mixer_str) { ret = -ENOMEM; goto done; } snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); fe_audio_adsp_callback_config_control[0].name = mixer_str; fe_audio_adsp_callback_config_control[0].private_value = rtd->dai_link->be_id; pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str); ret = snd_soc_add_platform_controls(rtd->platform, fe_audio_adsp_callback_config_control, ARRAY_SIZE(fe_audio_adsp_callback_config_control)); if (ret < 0) { pr_err("%s: failed to add ctl %s. err = %d\n", __func__, mixer_str, ret); ret = -EINVAL; goto free_mixer_str; } kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str); if (!kctl) { pr_err("%s: failed to get kctl %s.\n", __func__, mixer_str); ret = -EINVAL; goto free_mixer_str; } kctl->private_data = NULL; free_mixer_str: kfree(mixer_str); done: return ret; } static int msm_pcm_set_volume(struct msm_audio *prtd, uint32_t volume) { int rc = 0; Loading Loading @@ -1549,6 +1750,16 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd) pr_err("%s: Could not add pcm Compress Control %d\n", __func__, ret); ret = msm_pcm_add_audio_adsp_stream_cmd_control(rtd); if (ret) pr_err("%s: Could not add pcm ADSP Stream Cmd Control\n", __func__); ret = msm_pcm_add_audio_adsp_stream_callback_control(rtd); if (ret) pr_err("%s: Could not add pcm ADSP Stream Callback Control\n", __func__); return ret; } Loading sound/soc/msm/qdsp6v2/msm-qti-pp-config.c +130 −0 Original line number Diff line number Diff line Loading @@ -817,6 +817,136 @@ static int msm_qti_pp_asphere_set(struct snd_kcontrol *kcontrol, return 0; } int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd, const char *mixer_ctl_name, uint32_t *payload) { /* adsp pp event notifier */ struct snd_kcontrol *kctl; struct snd_ctl_elem_value control; uint32_t payload_size = 0; const char *deviceNo = "NN"; char *mixer_str = NULL; int ctl_len = 0, ret = 0; if (!rtd || !payload) { pr_err("%s: %s is NULL\n", __func__, (!rtd) ? "rtd" : "payload"); ret = -EINVAL; goto done; } ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; mixer_str = kzalloc(ctl_len, GFP_ATOMIC); if (!mixer_str) { ret = -EINVAL; goto done; } snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str); kfree(mixer_str); if (!kctl) { pr_err("%s: failed to get kctl.\n", __func__); ret = -EINVAL; goto done; } control.id = kctl->id; payload_size = payload[0]; /* Copy complete payload */ memcpy(control.value.bytes.data, (void *)payload, sizeof(payload_size) + payload_size); kctl->put(kctl, &control); if (rtd->card->snd_card == NULL) { pr_err("%s: snd_card is null.\n", __func__); ret = -EINVAL; goto done; } snd_ctl_notify(rtd->card->snd_card, SNDRV_CTL_EVENT_MASK_INFO, &control.id); done: return ret; } int msm_adsp_stream_cmd_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; uinfo->count = 512; return 0; } int msm_adsp_stream_callback_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { uint32_t payload_size = 0, last_payload_size = 0; /* fetch payload size in first four bytes */ memcpy(&payload_size, ucontrol->value.bytes.data, sizeof(uint32_t)); if (kcontrol->private_data == NULL) { /* buffer is empty */ kcontrol->private_data = kzalloc(payload_size + sizeof(payload_size), GFP_ATOMIC); if (kcontrol->private_data == NULL) return -ENOMEM; } else { memcpy(&last_payload_size, kcontrol->private_data, sizeof(uint32_t)); if (last_payload_size < payload_size) { /* new payload size exceeds old one. * reallocate buffer */ kfree(kcontrol->private_data); kcontrol->private_data = kzalloc(payload_size + sizeof(payload_size), GFP_ATOMIC); if (kcontrol->private_data == NULL) return -ENOMEM; } } memcpy(kcontrol->private_data, ucontrol->value.bytes.data, sizeof(uint32_t) + payload_size); return 0; } int msm_adsp_stream_callback_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { uint32_t payload_size = 0; if (kcontrol->private_data == NULL) { pr_err("%s: ASM Stream PP Event Data Unavailable\n", __func__); return -EINVAL; } memcpy(&payload_size, kcontrol->private_data, sizeof(uint32_t)); memcpy(ucontrol->value.bytes.data, kcontrol->private_data, sizeof(uint32_t) + payload_size); kfree(kcontrol->private_data); kcontrol->private_data = NULL; return 0; } int msm_adsp_stream_callback_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; uinfo->count = 512; return 0; } static int msm_multichannel_ec_primary_mic_ch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading Loading
include/sound/apr_audio-v2.h +5 −0 Original line number Diff line number Diff line Loading @@ -443,6 +443,11 @@ struct adm_param_data_v5 { */ } __packed; #define ASM_STREAM_CMD_REGISTER_PP_EVENTS 0x00013213 #define ASM_STREAM_PP_EVENT 0x00013214 #define DSP_STREAM_CMD "ADSP Stream Cmd" #define DSP_STREAM_CALLBACK "ADSP Stream Callback Event" /* set customized mixing on matrix mixer */ #define ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5 0x00010344 struct adm_cmd_set_pspd_mtmx_strtr_params_v5 { Loading
include/sound/q6asm-v2.h +3 −0 Original line number Diff line number Diff line Loading @@ -618,6 +618,9 @@ int q6asm_get_session_time_legacy(struct audio_client *ac, uint64_t *tstamp); int q6asm_send_audio_effects_params(struct audio_client *ac, char *params, uint32_t params_length); int q6asm_send_stream_cmd(struct audio_client *ac, uint32_t opcode, void *param, uint32_t params_length); /* Client can set the IO mode to either AIO/SIO mode */ int q6asm_set_io_mode(struct audio_client *ac, uint32_t mode); Loading
sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +209 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ #include <sound/msm-dts-eagle.h> #include "msm-pcm-routing-v2.h" #include "msm-qti-pp-config.h" #define DSP_PP_BUFFERING_IN_MSEC 25 #define PARTIAL_DRAIN_ACK_EARLY_BY_MSEC 150 Loading Loading @@ -543,12 +544,19 @@ static void compr_event_handler(uint32_t opcode, unsigned long flags; uint64_t read_size; uint32_t *buff_addr; struct snd_soc_pcm_runtime *rtd; int ret = 0; if (!prtd) { pr_err("%s: prtd is NULL\n", __func__); return; } cstream = prtd->cstream; if (!cstream) { pr_err("%s: cstream is NULL\n", __func__); return; } ac = prtd->audio_client; /* Loading Loading @@ -715,6 +723,23 @@ static void compr_event_handler(uint32_t opcode, if (prtd->gapless_state.gapless_transition) prtd->gapless_state.gapless_transition = 0; spin_unlock_irqrestore(&prtd->lock, flags); break; case ASM_STREAM_PP_EVENT: pr_debug("%s: ASM_STREAM_PP_EVENT\n", __func__); rtd = cstream->private_data; if (!rtd) { pr_err("%s: rtd is NULL\n", __func__); return; } ret = msm_adsp_inform_mixer_ctl(rtd, DSP_STREAM_CALLBACK, payload); if (ret) { pr_err("%s: failed to inform mixer ctrl. err = %d\n", __func__, ret); return; } break; case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY: case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY: { Loading Loading @@ -815,6 +840,10 @@ static void compr_event_handler(uint32_t opcode, } atomic_set(&prtd->close, 0); break; case ASM_STREAM_CMD_REGISTER_PP_EVENTS: pr_debug("%s: ASM_STREAM_CMD_REGISTER_PP_EVENTS:", __func__); break; default: break; } Loading Loading @@ -3578,6 +3607,65 @@ end: return rc; } static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); unsigned long fe_id = kcontrol->private_value; struct msm_compr_pdata *pdata = (struct msm_compr_pdata *) snd_soc_component_get_drvdata(comp); struct snd_compr_stream *cstream = NULL; struct msm_compr_audio *prtd; int ret = 0, param_length = 0; if (fe_id >= MSM_FRONTEND_DAI_MAX) { pr_err("%s Received invalid fe_id %lu\n", __func__, fe_id); ret = -EINVAL; goto done; } cstream = pdata->cstream[fe_id]; if (cstream == NULL) { pr_err("%s cstream is null.\n", __func__); ret = -EINVAL; goto done; } prtd = cstream->runtime->private_data; if (!prtd) { pr_err("%s: prtd is null.\n", __func__); ret = -EINVAL; goto done; } if (prtd->audio_client == NULL) { pr_err("%s: audio_client is null.\n", __func__); ret = -EINVAL; goto done; } memcpy(¶m_length, ucontrol->value.bytes.data, sizeof(param_length)); if ((param_length + sizeof(param_length)) >= sizeof(ucontrol->value.bytes.data)) { pr_err("%s param length=%d exceeds limit", __func__, param_length); ret = -EINVAL; goto done; } ret = q6asm_send_stream_cmd(prtd->audio_client, ASM_STREAM_CMD_REGISTER_PP_EVENTS, ucontrol->value.bytes.data + sizeof(param_length), param_length); if (ret < 0) pr_err("%s: failed to register pp event. err = %d\n", __func__, ret); done: return ret; } static int msm_compr_gapless_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading Loading @@ -3854,6 +3942,117 @@ static int msm_compr_add_query_audio_effect_control( return 0; } static int msm_compr_add_audio_adsp_stream_cmd_control( struct snd_soc_pcm_runtime *rtd) { const char *mixer_ctl_name = DSP_STREAM_CMD; const char *deviceNo = "NN"; char *mixer_str = NULL; int ctl_len = 0, ret = 0; struct snd_kcontrol_new fe_audio_adsp_stream_cmd_config_control[1] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_adsp_stream_cmd_info, .put = msm_compr_adsp_stream_cmd_put, .private_value = 0, } }; if (!rtd) { pr_err("%s NULL rtd\n", __func__); ret = -EINVAL; goto done; } ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; mixer_str = kzalloc(ctl_len, GFP_KERNEL); if (!mixer_str) { ret = -ENOMEM; goto done; } snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); fe_audio_adsp_stream_cmd_config_control[0].name = mixer_str; fe_audio_adsp_stream_cmd_config_control[0].private_value = rtd->dai_link->be_id; pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str); ret = snd_soc_add_platform_controls(rtd->platform, fe_audio_adsp_stream_cmd_config_control, ARRAY_SIZE(fe_audio_adsp_stream_cmd_config_control)); if (ret < 0) pr_err("%s: failed to add ctl %s. err = %d\n", __func__, mixer_str, ret); kfree(mixer_str); done: return ret; } static int msm_compr_add_audio_adsp_stream_callback_control( struct snd_soc_pcm_runtime *rtd) { const char *mixer_ctl_name = DSP_STREAM_CALLBACK; const char *deviceNo = "NN"; char *mixer_str = NULL; int ctl_len = 0, ret = 0; struct snd_kcontrol *kctl; struct snd_kcontrol_new fe_audio_adsp_callback_config_control[1] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_adsp_stream_callback_info, .get = msm_adsp_stream_callback_get, .put = msm_adsp_stream_callback_put, .private_value = 0, } }; if (!rtd) { pr_err("%s: rtd is NULL\n", __func__); ret = -EINVAL; goto done; } ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; mixer_str = kzalloc(ctl_len, GFP_KERNEL); if (!mixer_str) { ret = -ENOMEM; goto done; } snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); fe_audio_adsp_callback_config_control[0].name = mixer_str; fe_audio_adsp_callback_config_control[0].private_value = rtd->dai_link->be_id; pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str); ret = snd_soc_add_platform_controls(rtd->platform, fe_audio_adsp_callback_config_control, ARRAY_SIZE(fe_audio_adsp_callback_config_control)); if (ret < 0) { pr_err("%s: failed to add ctl %s. err = %d\n", __func__, mixer_str, ret); ret = -EINVAL; goto free_mixer_str; } kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str); if (!kctl) { pr_err("%s: failed to get kctl %s.\n", __func__, mixer_str); ret = -EINVAL; goto free_mixer_str; } kctl->private_data = NULL; free_mixer_str: kfree(mixer_str); done: return ret; } static int msm_compr_add_dec_runtime_params_control( struct snd_soc_pcm_runtime *rtd) { Loading Loading @@ -4048,6 +4247,16 @@ static int msm_compr_new(struct snd_soc_pcm_runtime *rtd) pr_err("%s: Could not add Compr Audio Effects Control\n", __func__); rc = msm_compr_add_audio_adsp_stream_cmd_control(rtd); if (rc) pr_err("%s: Could not add Compr ADSP Stream Cmd Control\n", __func__); rc = msm_compr_add_audio_adsp_stream_callback_control(rtd); if (rc) pr_err("%s: Could not add Compr ADSP Stream Callback Control\n", __func__); rc = msm_compr_add_query_audio_effect_control(rtd); if (rc) pr_err("%s: Could not add Compr Query Audio Effect Control\n", Loading
sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +211 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ #include "msm-pcm-q6-v2.h" #include "msm-pcm-routing-v2.h" #include "msm-qti-pp-config.h" enum stream_state { IDLE = 0, Loading Loading @@ -147,6 +148,8 @@ static void event_handler(uint32_t opcode, uint32_t idx = 0; uint32_t size = 0; uint8_t buf_index; struct snd_soc_pcm_runtime *rtd; int ret = 0; switch (opcode) { case ASM_DATA_EVENT_WRITE_DONE_V2: { Loading Loading @@ -223,6 +226,29 @@ static void event_handler(uint32_t opcode, } break; } case ASM_STREAM_PP_EVENT: { pr_debug("%s: ASM_STREAM_PP_EVENT\n", __func__); if (!substream) { pr_err("%s: substream is NULL.\n", __func__); return; } rtd = substream->private_data; if (!rtd) { pr_err("%s: rtd is NULL\n", __func__); return; } ret = msm_adsp_inform_mixer_ctl(rtd, DSP_STREAM_CALLBACK, payload); if (ret) { pr_err("%s: failed to inform mixer ctl. err = %d\n", __func__, ret); return; } break; } case APR_BASIC_RSP_RESULT: { switch (payload[0]) { case ASM_SESSION_CMD_RUN_V2: Loading Loading @@ -252,6 +278,10 @@ static void event_handler(uint32_t opcode, } atomic_set(&prtd->start, 1); break; case ASM_STREAM_CMD_REGISTER_PP_EVENTS: pr_debug("%s: ASM_STREAM_CMD_REGISTER_PP_EVENTS:", __func__); break; default: pr_debug("%s:Payload = [0x%x]stat[0x%x]\n", __func__, payload[0], payload[1]); Loading Loading @@ -1036,6 +1066,177 @@ static struct snd_pcm_ops msm_pcm_ops = { .mmap = msm_pcm_mmap, }; static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *pcm = snd_kcontrol_chip(kcontrol); struct snd_soc_platform *platform = snd_soc_component_to_platform(pcm); struct msm_plat_data *pdata = dev_get_drvdata(platform->dev); struct snd_pcm_substream *substream; struct msm_audio *prtd; int ret = 0, param_length = 0; if (!pdata) { pr_err("%s pdata is NULL\n", __func__); ret = -ENODEV; goto done; } substream = pdata->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->audio_client == NULL) { pr_err("%s prtd is null.\n", __func__); ret = -EINVAL; goto done; } memcpy(¶m_length, ucontrol->value.bytes.data, sizeof(param_length)); if ((param_length + sizeof(param_length)) >= sizeof(ucontrol->value.bytes.data)) { pr_err("%s param length=%d exceeds limit", __func__, param_length); ret = -EINVAL; goto done; } ret = q6asm_send_stream_cmd(prtd->audio_client, ASM_STREAM_CMD_REGISTER_PP_EVENTS, ucontrol->value.bytes.data + sizeof(param_length), param_length); if (ret < 0) pr_err("%s: failed to register pp event. err = %d\n", __func__, ret); done: return ret; } static int msm_pcm_add_audio_adsp_stream_cmd_control( struct snd_soc_pcm_runtime *rtd) { const char *mixer_ctl_name = DSP_STREAM_CMD; const char *deviceNo = "NN"; char *mixer_str = NULL; int ctl_len = 0, ret = 0; struct snd_kcontrol_new fe_audio_adsp_stream_cmd_config_control[1] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_adsp_stream_cmd_info, .put = msm_pcm_adsp_stream_cmd_put, .private_value = 0, } }; if (!rtd) { pr_err("%s rtd is NULL\n", __func__); ret = -EINVAL; goto done; } ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; mixer_str = kzalloc(ctl_len, GFP_KERNEL); if (!mixer_str) { ret = -ENOMEM; goto done; } snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); fe_audio_adsp_stream_cmd_config_control[0].name = mixer_str; fe_audio_adsp_stream_cmd_config_control[0].private_value = rtd->dai_link->be_id; pr_debug("Registering new mixer ctl %s\n", mixer_str); ret = snd_soc_add_platform_controls(rtd->platform, fe_audio_adsp_stream_cmd_config_control, ARRAY_SIZE(fe_audio_adsp_stream_cmd_config_control)); if (ret < 0) pr_err("%s: failed add ctl %s. err = %d\n", __func__, mixer_str, ret); kfree(mixer_str); done: return ret; } static int msm_pcm_add_audio_adsp_stream_callback_control( struct snd_soc_pcm_runtime *rtd) { const char *mixer_ctl_name = DSP_STREAM_CALLBACK; const char *deviceNo = "NN"; char *mixer_str = NULL; int ctl_len = 0, ret = 0; struct snd_kcontrol *kctl; struct snd_kcontrol_new fe_audio_adsp_callback_config_control[1] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_adsp_stream_callback_info, .get = msm_adsp_stream_callback_get, .put = msm_adsp_stream_callback_put, .private_value = 0, } }; if (!rtd) { pr_err("%s NULL rtd\n", __func__); ret = -EINVAL; goto done; } pr_debug("%s: added new pcm FE with name %s, id %d, cpu dai %s, device no %d\n", __func__, rtd->dai_link->name, rtd->dai_link->be_id, rtd->dai_link->cpu_dai_name, rtd->pcm->device); ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; mixer_str = kzalloc(ctl_len, GFP_KERNEL); if (!mixer_str) { ret = -ENOMEM; goto done; } snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); fe_audio_adsp_callback_config_control[0].name = mixer_str; fe_audio_adsp_callback_config_control[0].private_value = rtd->dai_link->be_id; pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str); ret = snd_soc_add_platform_controls(rtd->platform, fe_audio_adsp_callback_config_control, ARRAY_SIZE(fe_audio_adsp_callback_config_control)); if (ret < 0) { pr_err("%s: failed to add ctl %s. err = %d\n", __func__, mixer_str, ret); ret = -EINVAL; goto free_mixer_str; } kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str); if (!kctl) { pr_err("%s: failed to get kctl %s.\n", __func__, mixer_str); ret = -EINVAL; goto free_mixer_str; } kctl->private_data = NULL; free_mixer_str: kfree(mixer_str); done: return ret; } static int msm_pcm_set_volume(struct msm_audio *prtd, uint32_t volume) { int rc = 0; Loading Loading @@ -1549,6 +1750,16 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd) pr_err("%s: Could not add pcm Compress Control %d\n", __func__, ret); ret = msm_pcm_add_audio_adsp_stream_cmd_control(rtd); if (ret) pr_err("%s: Could not add pcm ADSP Stream Cmd Control\n", __func__); ret = msm_pcm_add_audio_adsp_stream_callback_control(rtd); if (ret) pr_err("%s: Could not add pcm ADSP Stream Callback Control\n", __func__); return ret; } Loading
sound/soc/msm/qdsp6v2/msm-qti-pp-config.c +130 −0 Original line number Diff line number Diff line Loading @@ -817,6 +817,136 @@ static int msm_qti_pp_asphere_set(struct snd_kcontrol *kcontrol, return 0; } int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd, const char *mixer_ctl_name, uint32_t *payload) { /* adsp pp event notifier */ struct snd_kcontrol *kctl; struct snd_ctl_elem_value control; uint32_t payload_size = 0; const char *deviceNo = "NN"; char *mixer_str = NULL; int ctl_len = 0, ret = 0; if (!rtd || !payload) { pr_err("%s: %s is NULL\n", __func__, (!rtd) ? "rtd" : "payload"); ret = -EINVAL; goto done; } ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; mixer_str = kzalloc(ctl_len, GFP_ATOMIC); if (!mixer_str) { ret = -EINVAL; goto done; } snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str); kfree(mixer_str); if (!kctl) { pr_err("%s: failed to get kctl.\n", __func__); ret = -EINVAL; goto done; } control.id = kctl->id; payload_size = payload[0]; /* Copy complete payload */ memcpy(control.value.bytes.data, (void *)payload, sizeof(payload_size) + payload_size); kctl->put(kctl, &control); if (rtd->card->snd_card == NULL) { pr_err("%s: snd_card is null.\n", __func__); ret = -EINVAL; goto done; } snd_ctl_notify(rtd->card->snd_card, SNDRV_CTL_EVENT_MASK_INFO, &control.id); done: return ret; } int msm_adsp_stream_cmd_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; uinfo->count = 512; return 0; } int msm_adsp_stream_callback_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { uint32_t payload_size = 0, last_payload_size = 0; /* fetch payload size in first four bytes */ memcpy(&payload_size, ucontrol->value.bytes.data, sizeof(uint32_t)); if (kcontrol->private_data == NULL) { /* buffer is empty */ kcontrol->private_data = kzalloc(payload_size + sizeof(payload_size), GFP_ATOMIC); if (kcontrol->private_data == NULL) return -ENOMEM; } else { memcpy(&last_payload_size, kcontrol->private_data, sizeof(uint32_t)); if (last_payload_size < payload_size) { /* new payload size exceeds old one. * reallocate buffer */ kfree(kcontrol->private_data); kcontrol->private_data = kzalloc(payload_size + sizeof(payload_size), GFP_ATOMIC); if (kcontrol->private_data == NULL) return -ENOMEM; } } memcpy(kcontrol->private_data, ucontrol->value.bytes.data, sizeof(uint32_t) + payload_size); return 0; } int msm_adsp_stream_callback_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { uint32_t payload_size = 0; if (kcontrol->private_data == NULL) { pr_err("%s: ASM Stream PP Event Data Unavailable\n", __func__); return -EINVAL; } memcpy(&payload_size, kcontrol->private_data, sizeof(uint32_t)); memcpy(ucontrol->value.bytes.data, kcontrol->private_data, sizeof(uint32_t) + payload_size); kfree(kcontrol->private_data); kcontrol->private_data = NULL; return 0; } int msm_adsp_stream_callback_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; uinfo->count = 512; return 0; } static int msm_multichannel_ec_primary_mic_ch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading