Messages in this thread |  | | Date | Fri, 22 Aug 2025 11:55:15 +0100 | | Subject | Re: [PATCH 2/2] ASoC: qcom: audioreach: Add support for VI Sense module | | From | Srinivas Kandagatla <> |
| |
On 8/21/25 3:16 PM, Krzysztof Kozlowski wrote: > VI Sense module in ADSP is responsible for feedback loop for measuring > current and voltage of amplifiers, necessary for proper calibration of > Speaker Protection algorightms. Implement parsing > MODULE_ID_SPEAKER_PROTECTION_VI from Audioreach topology and sending it > as command to the ADSP. > > Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> > --- > sound/soc/qcom/qdsp6/audioreach.c | 112 ++++++++++++++++++++++++++++++ > sound/soc/qcom/qdsp6/audioreach.h | 27 +++++++ > 2 files changed, 139 insertions(+) > > diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c > index b7f1fc835dc2..f2b7f18e29ae 100644 > --- a/sound/soc/qcom/qdsp6/audioreach.c > +++ b/sound/soc/qcom/qdsp6/audioreach.c > @@ -202,6 +202,31 @@ struct apm_display_port_module_intf_cfg { > } __packed; > } > > +static int audioreach_speaker_protection_vi(struct q6apm_graph *graph, > + struct audioreach_module *module, > + struct audioreach_module_config *mcfg) > +{ > + uint32_t num_channels = mcfg->num_channels; > + struct apm_module_sp_vi_op_mode_cfg *op_cfg; > + struct apm_module_sp_vi_channel_map_cfg *cm_cfg; > + struct apm_module_sp_vi_ex_mode_cfg *ex_cfg; > + int op_sz, cm_sz, ex_sz; > + struct apm_module_param_data *param_data; > + int rc, i, payload_size; > + struct gpr_pkt *pkt; > + void *p; > + > + if (num_channels > 2) { > + dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels); > + return -EINVAL; > + } > + > + op_sz = APM_SP_VI_OP_MODE_CFG_PSIZE(num_channels); > + /* Channel mapping for Isense and Vsense, thus twice number of speakers. */ > + cm_sz = APM_SP_VI_CH_MAP_CFG_PSIZE(num_channels * 2); > + ex_sz = APM_SP_VI_EX_MODE_CFG_PSIZE; > + > + payload_size = op_sz + cm_sz + ex_sz; > + > + 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; > + > + op_cfg = p; > + param_data = &op_cfg->param_data; > + param_data->module_instance_id = module->instance_id; > + param_data->error_code = 0; > + param_data->param_id = PARAM_ID_SP_VI_OP_MODE_CFG; > + param_data->param_size = op_sz - APM_MODULE_PARAM_DATA_SIZE; > + > + op_cfg->cfg.num_channels = num_channels; > + op_cfg->cfg.operation_mode = PARAM_ID_SP_VI_OP_MODE_CALIBRATION; > + op_cfg->cfg.quick_calibration = 1; > + /* > + * op_cfg->cfg.r0_t0_selection should be set only for normal mode, keep > + * as 0 for calibration
How do we move from calibration to a normal mode?
--srini > + */ > + p += op_sz; > + > + cm_cfg = p; > + param_data = &cm_cfg->param_data; > + param_data->module_instance_id = module->instance_id; > + param_data->error_code = 0; > + param_data->param_id = PARAM_ID_SP_VI_CHANNEL_MAP_CFG; > + param_data->param_size = cm_sz - APM_MODULE_PARAM_DATA_SIZE; > + > + cm_cfg->cfg.num_channels = num_channels * 2; > + for (i = 0; i < num_channels; i++) { > + /* > + * Map speakers into Vsense and then Isense of each channel. > + * E.g. for PCM_CHANNEL_FL and PCM_CHANNEL_FR to: > + * [ 1, 2, 3, 4] > + */ > + cm_cfg->cfg.channel_mapping[2 * i] = (mcfg->channel_map[i] - 1) * 2 + 1; > + cm_cfg->cfg.channel_mapping[2 * i + 1] = (mcfg->channel_map[i] - 1) * 2 + 2; > + } > + > + p += cm_sz; > + > + ex_cfg = p; > + param_data = &ex_cfg->param_data; > + param_data->module_instance_id = module->instance_id; > + param_data->error_code = 0; > + param_data->param_id = PARAM_ID_SP_VI_EX_MODE_CFG; > + param_data->param_size = ex_sz - APM_MODULE_PARAM_DATA_SIZE; > + > + ex_cfg->cfg.factory_mode = 0; > + > + rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); > + > + kfree(pkt); > + > + return rc; > +}
|  |