Loading asoc/msm-lsm-client.c +72 −1 Original line number Diff line number Diff line Loading @@ -2425,6 +2425,7 @@ static int msm_lsm_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct lsm_priv *prtd; struct snd_soc_pcm_runtime *rtd = substream->private_data; int ret = 0; pr_debug("%s\n", __func__); Loading Loading @@ -2488,6 +2489,8 @@ static int msm_lsm_open(struct snd_pcm_substream *substream) prtd->lsm_client->perf_mode = 0; prtd->lsm_client->event_mode = LSM_EVENT_NON_TIME_STAMP_MODE; prtd->lsm_client->event_type = LSM_DET_EVENT_TYPE_LEGACY; prtd->lsm_client->fe_id = rtd->dai_link->id; prtd->lsm_client->unprocessed_data = 0; return 0; } Loading Loading @@ -2958,6 +2961,70 @@ static int msm_lsm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd) return 0; } static int msm_lsm_afe_data_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u64 fe_id = kcontrol->private_value; uint16_t afe_data_format = 0; int ret = 0; afe_data_format = ucontrol->value.integer.value[0]; pr_debug("%s: afe data is %s\n", __func__, afe_data_format ? "unprocessed" : "processed"); ret = q6lsm_set_afe_data_format(fe_id, afe_data_format); if (ret) pr_err("%s: q6lsm_set_afe_data_format failed, ret = %d\n", __func__, ret); return ret; } static int msm_lsm_afe_data_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u64 fe_id = kcontrol->private_value; uint16_t afe_data_format = 0; int ret = 0; q6lsm_get_afe_data_format(fe_id, &afe_data_format); ucontrol->value.integer.value[0] = afe_data_format; pr_debug("%s: afe data is %s\n", __func__, afe_data_format ? "unprocessed" : "processed"); return ret; } static int msm_lsm_add_afe_data_controls(struct snd_soc_pcm_runtime *rtd) { struct snd_pcm *pcm = rtd->pcm; struct snd_pcm_usr *afe_data_info; struct snd_kcontrol *kctl; const char *mixer_ctl_name = "Listen Stream"; const char *deviceNo = "NN"; const char *suffix = "Unprocessed Data"; int ctl_len, ret = 0; ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + strlen(suffix) + 1; pr_debug("%s: Adding Listen afe data cntrls\n", __func__); ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE, NULL, 1, ctl_len, rtd->dai_link->id, &afe_data_info); if (ret < 0) { pr_err("%s: Adding Listen afe data cntrls failed: %d\n", __func__, ret); return ret; } kctl = afe_data_info->kctl; snprintf(kctl->id.name, ctl_len, "%s %d %s", mixer_ctl_name, rtd->pcm->device, suffix); kctl->put = msm_lsm_afe_data_ctl_put; kctl->get = msm_lsm_afe_data_ctl_get; return 0; } static int msm_lsm_add_controls(struct snd_soc_pcm_runtime *rtd) { int ret = 0; Loading @@ -2966,6 +3033,10 @@ static int msm_lsm_add_controls(struct snd_soc_pcm_runtime *rtd) if (ret) pr_err("%s, add app type controls failed:%d\n", __func__, ret); ret = msm_lsm_add_afe_data_controls(rtd); if (ret) pr_err("%s, add afe data controls failed:%d\n", __func__, ret); return ret; } Loading dsp/q6lsm.c +80 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,13 @@ static int q6lsm_memory_map_regions(struct lsm_client *client, static int q6lsm_memory_unmap_regions(struct lsm_client *client, uint32_t handle); struct lsm_client_afe_data { uint64_t fe_id; uint16_t unprocessed_data; }; static struct lsm_client_afe_data lsm_client_afe_data[LSM_MAX_SESSION_ID + 1]; static int q6lsm_get_session_id_from_lsm_client(struct lsm_client *client) { int n; Loading Loading @@ -255,6 +262,8 @@ static void q6lsm_session_free(struct lsm_client *client) pr_debug("%s: Freeing session ID %d\n", __func__, client->session); spin_lock_irqsave(&lsm_session_lock, flags); lsm_session[client->session] = NULL; lsm_client_afe_data[client->session].fe_id = 0; lsm_client_afe_data[client->session].unprocessed_data = 0; spin_unlock_irqrestore(&lsm_session_lock, flags); client->session = LSM_INVALID_SESSION_ID; } Loading Loading @@ -1062,6 +1071,72 @@ int get_lsm_port(void) return lsm_afe_port; } /** * q6lsm_set_afe_data_format - * command to set afe data format * * @fe_id: FrontEnd DAI link ID * @afe_data_format: afe data format * * Returns 0 on success or -EINVAL on failure */ int q6lsm_set_afe_data_format(uint64_t fe_id, uint16_t afe_data_format) { int n = 0; if (0 != afe_data_format && 1 != afe_data_format) goto done; pr_debug("%s: afe data is %s\n", __func__, afe_data_format ? "unprocessed" : "processed"); for (n = LSM_MIN_SESSION_ID; n <= LSM_MAX_SESSION_ID; n++) { if (0 == lsm_client_afe_data[n].fe_id) { lsm_client_afe_data[n].fe_id = fe_id; lsm_client_afe_data[n].unprocessed_data = afe_data_format; pr_debug("%s: session ID is %d, fe_id is %d\n", __func__, n, fe_id); return 0; } } pr_err("%s: all lsm sessions are taken\n", __func__); done: return -EINVAL; } EXPORT_SYMBOL(q6lsm_set_afe_data_format); /** * q6lsm_get_afe_data_format - * command to get afe data format * * @fe_id: FrontEnd DAI link ID * @afe_data_format: afe data format * */ void q6lsm_get_afe_data_format(uint64_t fe_id, uint16_t *afe_data_format) { int n = 0; if (NULL == afe_data_format) { pr_err("%s: Pointer afe_data_format is NULL\n", __func__); return; } for (n = LSM_MIN_SESSION_ID; n <= LSM_MAX_SESSION_ID; n++) { if (fe_id == lsm_client_afe_data[n].fe_id) { *afe_data_format = lsm_client_afe_data[n].unprocessed_data; pr_debug("%s: session: %d, fe_id: %d, afe data: %s\n", __func__, n, fe_id, *afe_data_format ? "unprocessed" : "processed"); return; } } } EXPORT_SYMBOL(q6lsm_get_afe_data_format); /** * q6lsm_set_port_connected - * command to set LSM port connected Loading Loading @@ -1092,14 +1167,19 @@ int q6lsm_set_port_connected(struct lsm_client *client) connectport_hdr.param_size = sizeof(connect_port); client->connect_to_port = get_lsm_port(); if (ADM_LSM_PORT_ID != client->connect_to_port) q6lsm_get_afe_data_format(client->fe_id, &client->unprocessed_data); connect_port.minor_version = QLSM_PARAM_ID_MINOR_VERSION; connect_port.port_id = client->connect_to_port; connect_port.unprocessed_data = client->unprocessed_data; rc = q6lsm_pack_and_set_params(client, &connectport_hdr, (uint8_t *) &connect_port, set_param_opcode); if (rc) pr_err("%s: Failed set_params, rc %d\n", __func__, rc); return rc; } EXPORT_SYMBOL(q6lsm_set_port_connected); Loading include/dsp/q6lsm.h +6 −2 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. */ #ifndef __Q6LSM_H__ #define __Q6LSM_H__ Loading Loading @@ -102,6 +102,8 @@ struct lsm_client { uint32_t event_type; uint32_t num_stages; struct lsm_stage_config stage_cfg[LSM_MAX_STAGES_PER_SESSION]; uint64_t fe_id; uint16_t unprocessed_data; }; struct lsm_stream_cmd_open_tx { Loading Loading @@ -159,7 +161,7 @@ struct lsm_param_connect_to_port { uint32_t minor_version; /* AFE port id that receives voice wake up data */ uint16_t port_id; uint16_t reserved; uint16_t unprocessed_data; } __packed; struct lsm_param_poll_enable { Loading Loading @@ -295,4 +297,6 @@ int q6lsm_set_media_fmt_v2_params(struct lsm_client *client); int q6lsm_lab_out_ch_cfg(struct lsm_client *client, u8 *ch_map, struct lsm_params_info_v2 *p_info); bool q6lsm_adsp_supports_multi_stage_detection(void); int q6lsm_set_afe_data_format(uint64_t fe_id, uint16_t afe_data_format); void q6lsm_get_afe_data_format(uint64_t fe_id, uint16_t *afe_data_format); #endif /* __Q6LSM_H__ */ Loading
asoc/msm-lsm-client.c +72 −1 Original line number Diff line number Diff line Loading @@ -2425,6 +2425,7 @@ static int msm_lsm_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct lsm_priv *prtd; struct snd_soc_pcm_runtime *rtd = substream->private_data; int ret = 0; pr_debug("%s\n", __func__); Loading Loading @@ -2488,6 +2489,8 @@ static int msm_lsm_open(struct snd_pcm_substream *substream) prtd->lsm_client->perf_mode = 0; prtd->lsm_client->event_mode = LSM_EVENT_NON_TIME_STAMP_MODE; prtd->lsm_client->event_type = LSM_DET_EVENT_TYPE_LEGACY; prtd->lsm_client->fe_id = rtd->dai_link->id; prtd->lsm_client->unprocessed_data = 0; return 0; } Loading Loading @@ -2958,6 +2961,70 @@ static int msm_lsm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd) return 0; } static int msm_lsm_afe_data_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u64 fe_id = kcontrol->private_value; uint16_t afe_data_format = 0; int ret = 0; afe_data_format = ucontrol->value.integer.value[0]; pr_debug("%s: afe data is %s\n", __func__, afe_data_format ? "unprocessed" : "processed"); ret = q6lsm_set_afe_data_format(fe_id, afe_data_format); if (ret) pr_err("%s: q6lsm_set_afe_data_format failed, ret = %d\n", __func__, ret); return ret; } static int msm_lsm_afe_data_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u64 fe_id = kcontrol->private_value; uint16_t afe_data_format = 0; int ret = 0; q6lsm_get_afe_data_format(fe_id, &afe_data_format); ucontrol->value.integer.value[0] = afe_data_format; pr_debug("%s: afe data is %s\n", __func__, afe_data_format ? "unprocessed" : "processed"); return ret; } static int msm_lsm_add_afe_data_controls(struct snd_soc_pcm_runtime *rtd) { struct snd_pcm *pcm = rtd->pcm; struct snd_pcm_usr *afe_data_info; struct snd_kcontrol *kctl; const char *mixer_ctl_name = "Listen Stream"; const char *deviceNo = "NN"; const char *suffix = "Unprocessed Data"; int ctl_len, ret = 0; ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + strlen(suffix) + 1; pr_debug("%s: Adding Listen afe data cntrls\n", __func__); ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE, NULL, 1, ctl_len, rtd->dai_link->id, &afe_data_info); if (ret < 0) { pr_err("%s: Adding Listen afe data cntrls failed: %d\n", __func__, ret); return ret; } kctl = afe_data_info->kctl; snprintf(kctl->id.name, ctl_len, "%s %d %s", mixer_ctl_name, rtd->pcm->device, suffix); kctl->put = msm_lsm_afe_data_ctl_put; kctl->get = msm_lsm_afe_data_ctl_get; return 0; } static int msm_lsm_add_controls(struct snd_soc_pcm_runtime *rtd) { int ret = 0; Loading @@ -2966,6 +3033,10 @@ static int msm_lsm_add_controls(struct snd_soc_pcm_runtime *rtd) if (ret) pr_err("%s, add app type controls failed:%d\n", __func__, ret); ret = msm_lsm_add_afe_data_controls(rtd); if (ret) pr_err("%s, add afe data controls failed:%d\n", __func__, ret); return ret; } Loading
dsp/q6lsm.c +80 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,13 @@ static int q6lsm_memory_map_regions(struct lsm_client *client, static int q6lsm_memory_unmap_regions(struct lsm_client *client, uint32_t handle); struct lsm_client_afe_data { uint64_t fe_id; uint16_t unprocessed_data; }; static struct lsm_client_afe_data lsm_client_afe_data[LSM_MAX_SESSION_ID + 1]; static int q6lsm_get_session_id_from_lsm_client(struct lsm_client *client) { int n; Loading Loading @@ -255,6 +262,8 @@ static void q6lsm_session_free(struct lsm_client *client) pr_debug("%s: Freeing session ID %d\n", __func__, client->session); spin_lock_irqsave(&lsm_session_lock, flags); lsm_session[client->session] = NULL; lsm_client_afe_data[client->session].fe_id = 0; lsm_client_afe_data[client->session].unprocessed_data = 0; spin_unlock_irqrestore(&lsm_session_lock, flags); client->session = LSM_INVALID_SESSION_ID; } Loading Loading @@ -1062,6 +1071,72 @@ int get_lsm_port(void) return lsm_afe_port; } /** * q6lsm_set_afe_data_format - * command to set afe data format * * @fe_id: FrontEnd DAI link ID * @afe_data_format: afe data format * * Returns 0 on success or -EINVAL on failure */ int q6lsm_set_afe_data_format(uint64_t fe_id, uint16_t afe_data_format) { int n = 0; if (0 != afe_data_format && 1 != afe_data_format) goto done; pr_debug("%s: afe data is %s\n", __func__, afe_data_format ? "unprocessed" : "processed"); for (n = LSM_MIN_SESSION_ID; n <= LSM_MAX_SESSION_ID; n++) { if (0 == lsm_client_afe_data[n].fe_id) { lsm_client_afe_data[n].fe_id = fe_id; lsm_client_afe_data[n].unprocessed_data = afe_data_format; pr_debug("%s: session ID is %d, fe_id is %d\n", __func__, n, fe_id); return 0; } } pr_err("%s: all lsm sessions are taken\n", __func__); done: return -EINVAL; } EXPORT_SYMBOL(q6lsm_set_afe_data_format); /** * q6lsm_get_afe_data_format - * command to get afe data format * * @fe_id: FrontEnd DAI link ID * @afe_data_format: afe data format * */ void q6lsm_get_afe_data_format(uint64_t fe_id, uint16_t *afe_data_format) { int n = 0; if (NULL == afe_data_format) { pr_err("%s: Pointer afe_data_format is NULL\n", __func__); return; } for (n = LSM_MIN_SESSION_ID; n <= LSM_MAX_SESSION_ID; n++) { if (fe_id == lsm_client_afe_data[n].fe_id) { *afe_data_format = lsm_client_afe_data[n].unprocessed_data; pr_debug("%s: session: %d, fe_id: %d, afe data: %s\n", __func__, n, fe_id, *afe_data_format ? "unprocessed" : "processed"); return; } } } EXPORT_SYMBOL(q6lsm_get_afe_data_format); /** * q6lsm_set_port_connected - * command to set LSM port connected Loading Loading @@ -1092,14 +1167,19 @@ int q6lsm_set_port_connected(struct lsm_client *client) connectport_hdr.param_size = sizeof(connect_port); client->connect_to_port = get_lsm_port(); if (ADM_LSM_PORT_ID != client->connect_to_port) q6lsm_get_afe_data_format(client->fe_id, &client->unprocessed_data); connect_port.minor_version = QLSM_PARAM_ID_MINOR_VERSION; connect_port.port_id = client->connect_to_port; connect_port.unprocessed_data = client->unprocessed_data; rc = q6lsm_pack_and_set_params(client, &connectport_hdr, (uint8_t *) &connect_port, set_param_opcode); if (rc) pr_err("%s: Failed set_params, rc %d\n", __func__, rc); return rc; } EXPORT_SYMBOL(q6lsm_set_port_connected); Loading
include/dsp/q6lsm.h +6 −2 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. */ #ifndef __Q6LSM_H__ #define __Q6LSM_H__ Loading Loading @@ -102,6 +102,8 @@ struct lsm_client { uint32_t event_type; uint32_t num_stages; struct lsm_stage_config stage_cfg[LSM_MAX_STAGES_PER_SESSION]; uint64_t fe_id; uint16_t unprocessed_data; }; struct lsm_stream_cmd_open_tx { Loading Loading @@ -159,7 +161,7 @@ struct lsm_param_connect_to_port { uint32_t minor_version; /* AFE port id that receives voice wake up data */ uint16_t port_id; uint16_t reserved; uint16_t unprocessed_data; } __packed; struct lsm_param_poll_enable { Loading Loading @@ -295,4 +297,6 @@ int q6lsm_set_media_fmt_v2_params(struct lsm_client *client); int q6lsm_lab_out_ch_cfg(struct lsm_client *client, u8 *ch_map, struct lsm_params_info_v2 *p_info); bool q6lsm_adsp_supports_multi_stage_detection(void); int q6lsm_set_afe_data_format(uint64_t fe_id, uint16_t afe_data_format); void q6lsm_get_afe_data_format(uint64_t fe_id, uint16_t *afe_data_format); #endif /* __Q6LSM_H__ */