ASoC: qcom: audioreach: cleanup and calibration

Merge series from srinivas.kandagatla@oss.qualcomm.com:

Sorry to resend this series once again, as some of the patches seems
to be dropped/rejected by email client from previous send.

This patchset:
 - cleans up some of the audioreach tokens which are unused
 - adds missing documentation
 - add support for static calibration support which is required for ECNS
   an speaker protection support.

Tested this with Single Mic ECNS on SM8450 platform.
This commit is contained in:
Mark Brown 2025-08-19 18:45:33 +01:00
commit 132e098ef9
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
4 changed files with 86 additions and 20 deletions

View File

@ -3,6 +3,8 @@
#ifndef __SND_AR_TOKENS_H__
#define __SND_AR_TOKENS_H__
#include <linux/types.h>
#define APM_SUB_GRAPH_PERF_MODE_LOW_POWER 0x1
#define APM_SUB_GRAPH_PERF_MODE_LOW_LATENCY 0x2
@ -118,6 +120,12 @@ enum ar_event_types {
* LPAIF_WSA = 2,
* LPAIF_VA = 3,
* LPAIF_AXI = 4
* Possible values for MI2S
* I2S_INTF_TYPE_PRIMARY = 0,
* I2S_INTF_TYPE_SECONDARY = 1,
* I2S_INTF_TYPE_TERTIARY = 2,
* I2S_INTF_TYPE_QUATERNARY = 3,
* I2S_INTF_TYPE_QUINARY = 4,
*
* %AR_TKN_U32_MODULE_FMT_INTERLEAVE: PCM Interleaving
* PCM_INTERLEAVED = 1,
@ -184,8 +192,8 @@ enum ar_event_types {
#define AR_TKN_U32_MODULE_INSTANCE_ID 201
#define AR_TKN_U32_MODULE_MAX_IP_PORTS 202
#define AR_TKN_U32_MODULE_MAX_OP_PORTS 203
#define AR_TKN_U32_MODULE_IN_PORTS 204
#define AR_TKN_U32_MODULE_OUT_PORTS 205
#define AR_TKN_U32_MODULE_IN_PORTS 204 /* deprecated */
#define AR_TKN_U32_MODULE_OUT_PORTS 205 /* deprecated */
#define AR_TKN_U32_MODULE_SRC_OP_PORT_ID 206
#define AR_TKN_U32_MODULE_DST_IN_PORT_ID 207
#define AR_TKN_U32_MODULE_SRC_INSTANCE_ID 208
@ -232,4 +240,12 @@ enum ar_event_types {
#define AR_TKN_U32_MODULE_LOG_TAP_POINT_ID 260
#define AR_TKN_U32_MODULE_LOG_MODE 261
#define SND_SOC_AR_TPLG_MODULE_CFG_TYPE 0x01001006
struct audioreach_module_priv_data {
__le32 size; /* size in bytes of the array, including all elements */
__le32 type; /* SND_SOC_AR_TPLG_MODULE_CFG_TYPE */
__le32 priv[2]; /* Private data for future expansion */
__le32 data[0]; /* config data */
};
#endif /* __SND_AR_TOKENS_H__ */

View File

@ -811,6 +811,30 @@ static int audioreach_gapless_set_media_format(struct q6apm_graph *graph,
EARLY_EOS_DELAY_MS);
}
static int audioreach_set_module_config(struct q6apm_graph *graph,
struct audioreach_module *module,
struct audioreach_module_config *cfg)
{
int payload_size = module->data->size;
struct gpr_pkt *pkt;
int rc;
void *p;
pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
if (IS_ERR(pkt))
return PTR_ERR(pkt);
p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
memcpy(p, module->data->data, payload_size);
rc = q6apm_send_cmd_sync(graph->apm, pkt, 0);
kfree(pkt);
return rc;
}
static int audioreach_mfc_set_media_format(struct q6apm_graph *graph,
struct audioreach_module *module,
struct audioreach_module_config *cfg)
@ -1247,6 +1271,9 @@ int audioreach_set_media_format(struct q6apm_graph *graph, struct audioreach_mod
case MODULE_ID_DISPLAY_PORT_SINK:
rc = audioreach_display_port_set_media_format(graph, module, cfg);
break;
case MODULE_ID_SMECNS_V2:
rc = audioreach_set_module_config(graph, module, cfg);
break;
case MODULE_ID_I2S_SOURCE:
case MODULE_ID_I2S_SINK:
rc = audioreach_i2s_set_media_format(graph, module, cfg);

View File

@ -4,6 +4,7 @@
#define __AUDIOREACH_H__
#include <linux/types.h>
#include <linux/soc/qcom/apr.h>
#include <uapi/sound/snd_ar_tokens.h>
#include <sound/soc.h>
struct q6apm;
struct q6apm_graph;
@ -17,15 +18,16 @@ struct q6apm_graph;
#define MODULE_ID_PCM_DEC 0x07001005
#define MODULE_ID_PLACEHOLDER_ENCODER 0x07001008
#define MODULE_ID_PLACEHOLDER_DECODER 0x07001009
#define MODULE_ID_SAL 0x07001010
#define MODULE_ID_MFC 0x07001015
#define MODULE_ID_CODEC_DMA_SINK 0x07001023
#define MODULE_ID_CODEC_DMA_SOURCE 0x07001024
#define MODULE_ID_I2S_SINK 0x0700100A
#define MODULE_ID_I2S_SOURCE 0x0700100B
#define MODULE_ID_SAL 0x07001010
#define MODULE_ID_MFC 0x07001015
#define MODULE_ID_DATA_LOGGING 0x0700101A
#define MODULE_ID_AAC_DEC 0x0700101F
#define MODULE_ID_CODEC_DMA_SINK 0x07001023
#define MODULE_ID_CODEC_DMA_SOURCE 0x07001024
#define MODULE_ID_FLAC_DEC 0x0700102F
#define MODULE_ID_SMECNS_V2 0x07001031
#define MODULE_ID_MP3_DECODE 0x0700103B
#define MODULE_ID_GAPLESS 0x0700104D
#define MODULE_ID_DISPLAY_PORT_SINK 0x07001069
@ -461,8 +463,8 @@ struct param_id_i2s_intf_cfg {
} __packed;
#define I2S_INTF_TYPE_PRIMARY 0
#define I2S_INTF_TYPE_SECOINDARY 1
#define I2S_INTF_TYPE_TERTINARY 2
#define I2S_INTF_TYPE_SECONDARY 1
#define I2S_INTF_TYPE_TERTIARY 2
#define I2S_INTF_TYPE_QUATERNARY 3
#define I2S_INTF_TYPE_QUINARY 4
#define I2S_SD0 1
@ -707,9 +709,6 @@ struct audioreach_module {
uint32_t max_ip_port;
uint32_t max_op_port;
uint32_t in_port;
uint32_t out_port;
uint32_t num_connections;
/* Connections */
uint32_t src_mod_inst_id;
@ -745,6 +744,7 @@ struct audioreach_module {
struct list_head node;
struct audioreach_container *container;
struct snd_soc_dapm_widget *widget;
struct audioreach_module_priv_data *data;
};
struct audioreach_module_config {

View File

@ -305,6 +305,34 @@ static struct snd_soc_tplg_vendor_array *audioreach_get_module_array(
return NULL;
}
static struct audioreach_module_priv_data *audioreach_get_module_priv_data(
struct snd_soc_tplg_private *private)
{
int sz;
for (sz = 0; sz < le32_to_cpu(private->size); ) {
struct snd_soc_tplg_vendor_array *mod_array;
mod_array = (struct snd_soc_tplg_vendor_array *)((u8 *)private->array + sz);
if (mod_array->type == SND_SOC_AR_TPLG_MODULE_CFG_TYPE) {
struct audioreach_module_priv_data *pdata;
pdata = kzalloc(struct_size(pdata, data, le32_to_cpu(mod_array->size)),
GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
memcpy(pdata, ((u8 *)private->data + sz), struct_size(pdata, data,
le32_to_cpu(mod_array->size)));
return pdata;
}
sz = sz + le32_to_cpu(mod_array->size);
}
return NULL;
}
static struct audioreach_sub_graph *audioreach_parse_sg_tokens(struct q6apm *apm,
struct snd_soc_tplg_private *private)
{
@ -412,7 +440,7 @@ static struct audioreach_module *audioreach_parse_common_tokens(struct q6apm *ap
struct snd_soc_tplg_private *private,
struct snd_soc_dapm_widget *w)
{
uint32_t max_ip_port = 0, max_op_port = 0, in_port = 0, out_port = 0;
uint32_t max_ip_port = 0, max_op_port = 0;
uint32_t src_mod_op_port_id[AR_MAX_MOD_LINKS] = { 0, };
uint32_t dst_mod_inst_id[AR_MAX_MOD_LINKS] = { 0, };
uint32_t dst_mod_ip_port_id[AR_MAX_MOD_LINKS] = { 0, };
@ -455,12 +483,6 @@ static struct audioreach_module *audioreach_parse_common_tokens(struct q6apm *ap
case AR_TKN_U32_MODULE_MAX_OP_PORTS:
max_op_port = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_IN_PORTS:
in_port = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_OUT_PORTS:
out_port = le32_to_cpu(mod_elem->value);
break;
case AR_TKN_U32_MODULE_SRC_INSTANCE_ID:
src_mod_inst_id = le32_to_cpu(mod_elem->value);
break;
@ -550,8 +572,6 @@ static struct audioreach_module *audioreach_parse_common_tokens(struct q6apm *ap
mod->module_id = module_id;
mod->max_ip_port = max_ip_port;
mod->max_op_port = max_op_port;
mod->in_port = in_port;
mod->out_port = out_port;
mod->src_mod_inst_id = src_mod_inst_id;
for (pn = 0; pn < mod->max_op_port; pn++) {
if (src_mod_op_port_id[pn] && dst_mod_inst_id[pn] &&
@ -590,6 +610,8 @@ static int audioreach_widget_load_module_common(struct snd_soc_component *compon
if (IS_ERR(mod))
return PTR_ERR(mod);
mod->data = audioreach_get_module_priv_data(&tplg_w->priv);
dobj = &w->dobj;
dobj->private = mod;
@ -947,6 +969,7 @@ static int audioreach_widget_unload(struct snd_soc_component *scomp,
cont->num_modules--;
list_del(&mod->node);
kfree(mod->data);
kfree(mod);
/* Graph Info has N sub-graphs, sub-graph has N containers, Container has N Modules */
if (list_empty(&cont->modules_list)) { /* if no modules in the container then remove it */