diff --git a/asoc/msm-audio-effects-q6-v2.c b/asoc/msm-audio-effects-q6-v2.c index cb795f5bef45..4a7b4b32654e 100644 --- a/asoc/msm-audio-effects-q6-v2.c +++ b/asoc/msm-audio-effects-q6-v2.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2013-2021, The Linux Foundation. All rights reserved. * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -1091,7 +1092,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, u32 packed_data_size = 0; u8 *eq_config_data = NULL; u32 *updt_config_data = NULL; - int config_param_length; + int config_param_length, prev_config_param_length = 0; pr_debug("%s\n", __func__); if (!ac || (devices == -EINVAL) || (num_commands == -EINVAL)) { @@ -1211,7 +1212,12 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, if (!eq_config_data) eq_config_data = kzalloc(config_param_length, GFP_KERNEL); - else + else if (config_param_length != prev_config_param_length) { + if (eq_config_data) + kfree(eq_config_data); + eq_config_data = kzalloc(config_param_length, + GFP_KERNEL); + } else memset(eq_config_data, 0, config_param_length); if (!eq_config_data) { pr_err("%s, EQ_CONFIG:memory alloc failed\n", @@ -1238,6 +1244,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, *updt_config_data++ = eq->per_band_cfg[idx].band_idx; } + prev_config_param_length = config_param_length; break; case EQ_BAND_INDEX: if (length != 1 || index_offset != 0) { @@ -1320,7 +1327,8 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, pr_debug("%s: did not send pp params\n", __func__); invalid_config: kfree(params); - kfree(eq_config_data); + if (eq_config_data) + kfree(eq_config_data); return rc; } EXPORT_SYMBOL(msm_audio_effects_popless_eq_handler); diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c index 14f549310547..df48c414b05b 100644 --- a/asoc/msm-compress-q6-v2.c +++ b/asoc/msm-compress-q6-v2.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.​ */ @@ -4219,6 +4220,7 @@ static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, return -EINVAL; } + mutex_lock(&pdata->lock); cstream = pdata->cstream[fe_id]; if (cstream == NULL) { pr_err("%s cstream is null\n", __func__); @@ -4231,7 +4233,6 @@ static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, return -EINVAL; } - mutex_lock(&pdata->lock); if (prtd->audio_client == NULL) { pr_err("%s: audio_client is null\n", __func__); ret = -EINVAL; diff --git a/asoc/msm-lsm-client.c b/asoc/msm-lsm-client.c index bd9b73571263..7d69b97ca7c6 100644 --- a/asoc/msm-lsm-client.c +++ b/asoc/msm-lsm-client.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include #include @@ -42,6 +42,11 @@ #define LSM_IS_LAST_STAGE(client, stage_idx) \ (client->num_stages == (stage_idx + 1)) +struct lsm_char_dev { + /* Protects access to LSM client sessions and shared resources */ + struct mutex lock; +}; + static struct snd_pcm_hardware msm_pcm_hardware_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -683,15 +688,47 @@ static int msm_lsm_set_conf(struct snd_pcm_substream *substream, struct lsm_params_info_v2 *p_info) { struct snd_pcm_runtime *runtime = substream->runtime; - struct lsm_priv *prtd = runtime->private_data; + struct lsm_priv *prtd = NULL; struct snd_soc_pcm_runtime *rtd = substream->private_data; int rc = 0; + struct lsm_char_dev *lsm_dev; + struct snd_soc_component *component = NULL; + + if (!rtd) { + pr_err("%s substream runtime or private_data not found\n", + __func__); + return -EINVAL; + } + component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); + if (!component || !component->dev) { + pr_err("%s: invalid component\n", __func__); + return -EINVAL; + } + lsm_dev = (struct lsm_char_dev *) dev_get_drvdata(component->dev); + if (!lsm_dev) { + pr_err("%s: platform data is NULL\n", __func__); + return -EINVAL; + } + + mutex_lock(&lsm_dev->lock); + if (!runtime) { + pr_err("%s: Invalid runtime", __func__); + mutex_unlock(&lsm_dev->lock); + return -EINVAL; + } + prtd = runtime->private_data; + if (!prtd || !prtd->lsm_client) { + pr_err("%s: No LSM session active\n", __func__); + mutex_unlock(&lsm_dev->lock); + return -EINVAL; + } if (p_info->param_type == LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS) { if (p_info->param_size > MAX_KEYWORDS_SUPPORTED) { dev_err(rtd->dev, "%s: invalid number of snd_model keywords %d, the max is %d\n", __func__, p_info->param_size, MAX_KEYWORDS_SUPPORTED); + mutex_unlock(&lsm_dev->lock); return -EINVAL; } @@ -702,6 +739,7 @@ static int msm_lsm_set_conf(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: get_conf_levels failed for snd_model %d, err = %d\n", __func__, p_info->model_id, rc); + mutex_unlock(&lsm_dev->lock); return rc; } @@ -722,6 +760,7 @@ static int msm_lsm_set_conf(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: invalid confidence levels %d\n", __func__, p_info->param_size); + mutex_unlock(&lsm_dev->lock); return -EINVAL; } @@ -733,6 +772,7 @@ static int msm_lsm_set_conf(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: get_conf_levels failed, err = %d\n", __func__, rc); + mutex_unlock(&lsm_dev->lock); return rc; } @@ -749,6 +789,7 @@ static int msm_lsm_set_conf(struct snd_pcm_substream *substream, prtd->lsm_client->confidence_levels = NULL; } } + mutex_unlock(&lsm_dev->lock); return rc; } @@ -989,23 +1030,63 @@ static int msm_lsm_check_and_set_lab_controls(struct snd_pcm_substream *substrea u32 enable, struct lsm_params_info_v2 *p_info) { struct snd_pcm_runtime *runtime = substream->runtime; - struct lsm_priv *prtd = runtime->private_data; + struct lsm_priv *prtd = NULL; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct lsm_hw_params *out_hw_params = &prtd->lsm_client->out_hw_params; + struct lsm_hw_params *out_hw_params = NULL; + struct snd_soc_component *component = NULL; + struct lsm_char_dev *lsm_dev = NULL; u8 *chmap = NULL; u32 ch_idx; int rc = 0, stage_idx = p_info->stage_idx; + if (!rtd) { + pr_err("%s substream runtime or private_data not found\n", + __func__); + return -EINVAL; + } + component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); + if (!component || !component->dev) { + pr_err("%s: invalid component\n", __func__); + return -EINVAL; + } + lsm_dev = (struct lsm_char_dev *) dev_get_drvdata(component->dev); + if (!lsm_dev) { + pr_err("%s: platform data is NULL\n", __func__); + return -EINVAL; + } + + mutex_lock(&lsm_dev->lock); + if (!runtime) { + pr_err("%s: Invalid runtime", __func__); + mutex_unlock(&lsm_dev->lock); + return -EINVAL; + } + prtd = runtime->private_data; + if (!prtd || !prtd->lsm_client) { + pr_err("%s: No LSM session active\n", __func__); + mutex_unlock(&lsm_dev->lock); + return -EINVAL; + } + out_hw_params = &prtd->lsm_client->out_hw_params; + if (!out_hw_params) { + pr_err("%s: Invalid hw params\n", __func__); + mutex_unlock(&lsm_dev->lock); + return -EINVAL; + } + if (prtd->lsm_client->stage_cfg[stage_idx].lab_enable == enable) { dev_dbg(rtd->dev, "%s: Lab for session %d, stage %d already %s\n", __func__, prtd->lsm_client->session, stage_idx, enable ? "enabled" : "disabled"); + mutex_unlock(&lsm_dev->lock); return rc; } chmap = kzalloc(out_hw_params->num_chs, GFP_KERNEL); - if (!chmap) + if (!chmap) { + mutex_unlock(&lsm_dev->lock); return -ENOMEM; + } rc = q6lsm_lab_control(prtd->lsm_client, enable, p_info); if (rc) { @@ -1046,6 +1127,7 @@ static int msm_lsm_check_and_set_lab_controls(struct snd_pcm_substream *substrea fail: kfree(chmap); + mutex_unlock(&lsm_dev->lock); return rc; } @@ -3106,9 +3188,11 @@ static int msm_lsm_close(struct snd_pcm_substream *substream) { unsigned long flags; struct snd_pcm_runtime *runtime = substream->runtime; - struct lsm_priv *prtd = runtime->private_data; + struct lsm_priv *prtd = NULL; struct snd_soc_pcm_runtime *rtd; struct msm_pcm_stream_app_type_cfg cfg_data = {0}; + struct lsm_char_dev *lsm_dev; + struct snd_soc_component *component = NULL; int ret = 0; int be_id = 0; int fe_id = 0; @@ -3117,12 +3201,29 @@ static int msm_lsm_close(struct snd_pcm_substream *substream) pr_err("%s: Invalid private_data", __func__); return -EINVAL; } - if (!prtd || !prtd->lsm_client) { - pr_err("%s: No LSM session active\n", __func__); + if (!component || !component->dev) { + pr_err("%s: Invalid component\n", __func__); return -EINVAL; } rtd = substream->private_data; + lsm_dev = (struct lsm_char_dev *) dev_get_drvdata(component->dev); + if (!lsm_dev) { + pr_err("%s: platform data is NULL\n", __func__); + return -EINVAL; + } + mutex_lock(&lsm_dev->lock); + if (!runtime) { + pr_err("%s: Invalid runtime", __func__); + mutex_unlock(&lsm_dev->lock); + return -EINVAL; + } + prtd = runtime->private_data; + if (!prtd || !prtd->lsm_client) { + pr_err("%s: No LSM session active\n", __func__); + mutex_unlock(&lsm_dev->lock); + return -EINVAL; + } dev_dbg(rtd->dev, "%s\n", __func__); if (prtd->lsm_client->started) { if (prtd->lsm_client->lab_enable) { @@ -3232,6 +3333,7 @@ static int msm_lsm_close(struct snd_pcm_substream *substream) mutex_destroy(&prtd->lsm_api_lock); kfree(prtd); runtime->private_data = NULL; + mutex_unlock(&lsm_dev->lock); return 0; } @@ -3240,21 +3342,36 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; - struct lsm_priv *prtd = runtime->private_data; + struct lsm_priv *prtd = NULL; struct lsm_hw_params *out_hw_params = NULL; struct lsm_hw_params *in_hw_params = NULL; struct snd_soc_pcm_runtime *rtd; + struct lsm_char_dev *lsm_dev = NULL; + struct snd_soc_component *component = NULL; if (!substream->private_data) { pr_err("%s: Invalid private_data", __func__); return -EINVAL; } rtd = substream->private_data; + component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); + if (!component || !component->dev) { + pr_err("%s: Invalid component\n", __func__); + return -EINVAL; + } + lsm_dev = (struct lsm_char_dev *) dev_get_drvdata(component->dev); + if (!lsm_dev) { + pr_err("%s: platform data is NULL\n", __func__); + return -EINVAL; + } + mutex_lock(&lsm_dev->lock); + prtd = runtime->private_data; if (!prtd || !params) { dev_err(rtd->dev, "%s: invalid params prtd %pK params %pK", __func__, prtd, params); + mutex_unlock(&lsm_dev->lock); return -EINVAL; } in_hw_params = &prtd->lsm_client->in_hw_params; @@ -3269,6 +3386,7 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream, "%s: Invalid Params sample rate %d period count %d\n", __func__, out_hw_params->sample_rate, out_hw_params->period_count); + mutex_unlock(&lsm_dev->lock); return -EINVAL; } @@ -3279,6 +3397,7 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream, } else { dev_err(rtd->dev, "%s: Invalid Format 0x%x\n", __func__, params_format(params)); + mutex_unlock(&lsm_dev->lock); return -EINVAL; } @@ -3299,6 +3418,7 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream, */ memcpy(in_hw_params, out_hw_params, sizeof(struct lsm_hw_params)); + mutex_unlock(&lsm_dev->lock); return 0; } @@ -3629,6 +3749,14 @@ static struct snd_soc_component_driver msm_soc_component = { static int msm_lsm_probe(struct platform_device *pdev) { + struct lsm_char_dev *lsm_dev; + + lsm_dev = devm_kzalloc(&pdev->dev, sizeof(*lsm_dev), GFP_KERNEL); + if (!lsm_dev) + return -ENOMEM; + + mutex_init(&lsm_dev->lock); + dev_set_drvdata(&pdev->dev, lsm_dev); return snd_soc_register_component(&pdev->dev, &msm_soc_component, NULL, 0); @@ -3636,6 +3764,10 @@ static int msm_lsm_probe(struct platform_device *pdev) static int msm_lsm_remove(struct platform_device *pdev) { + struct lsm_char_dev *lsm_dev; + lsm_dev = dev_get_drvdata(&pdev->dev); + mutex_destroy(&lsm_dev->lock); + snd_soc_unregister_component(&pdev->dev); return 0; diff --git a/asoc/msm_dailink.h b/asoc/msm_dailink.h index c7353b9ae05d..ef588206d321 100644 --- a/asoc/msm_dailink.h +++ b/asoc/msm_dailink.h @@ -957,7 +957,8 @@ SND_SOC_DAILINK_DEFS(quat_mi2s_tx, SND_SOC_DAILINK_DEFS(quin_mi2s_rx, DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-mi2s.8")), - DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")), + DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx"), + COMP_CODEC("acm8625s_codec", "acm8625s-hifi")), DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing"))); SND_SOC_DAILINK_DEFS(quin_mi2s_tx,