From 2e13d955062bbabf7cddc65554909441da7137a1 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Wed, 20 Feb 2019 15:05:39 +0530 Subject: [PATCH] dsp: q6afe: Add v-validation support for speaker With speaker protection in v-validation mode, speaker samples can be tested in early factory mode. Add support for v-validation feature from driver. Change-Id: I92493d6d2784cf4dd58021746bffe01180f89d23 Signed-off-by: Laxminath Kasam --- dsp/audio_cal_utils.c | 8 +- dsp/q6afe.c | 198 ++++++++++++++++++++++++++++++++++--- include/dsp/apr_audio-v2.h | 48 +++++++++ 3 files changed, 240 insertions(+), 14 deletions(-) diff --git a/dsp/audio_cal_utils.c b/dsp/audio_cal_utils.c index 19c71fc55208..7e243e88609b 100644 --- a/dsp/audio_cal_utils.c +++ b/dsp/audio_cal_utils.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. */ #include #include @@ -16,6 +16,7 @@ static int unmap_memory(struct cal_type_data *cal_type, size_t get_cal_info_size(int32_t cal_type) { size_t size = 0; + size_t size1 = 0, size2 = 0; switch (cal_type) { case CVP_VOC_RX_TOPOLOGY_CAL_TYPE: @@ -93,8 +94,11 @@ size_t get_cal_info_size(int32_t cal_type) * Since get and set parameter structures are different in size * use the maximum size of get and set parameter structure */ - size = max(sizeof(struct audio_cal_info_sp_th_vi_ftm_cfg), + size1 = max(sizeof(struct audio_cal_info_sp_th_vi_ftm_cfg), sizeof(struct audio_cal_info_sp_th_vi_param)); + size2 = max(sizeof(struct audio_cal_info_sp_th_vi_v_vali_cfg), + sizeof(struct audio_cal_info_sp_th_vi_v_vali_param)); + size = max(size1, size2); break; case AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE: /* diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 62d4851f00ac..5000b9f46477 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -59,6 +59,16 @@ static char fbsp_state[MAX_FBSP_STATE][50] = { [FBSP_FAILED] = "failed" }; +enum v_vali_state { + V_VALI_FAILED, + V_VALI_SUCCESS, + V_VALI_INCORRECT_OP_MODE, + V_VALI_INACTIVE, + V_VALI_WARMUP, + V_VALI_IN_PROGRESS, + MAX_V_VALI_STATE +}; + enum { USE_CALIBRATED_R0TO, USE_SAFE_R0TO @@ -72,7 +82,8 @@ enum { enum { Q6AFE_MSM_SPKR_PROCESSING = 0, Q6AFE_MSM_SPKR_CALIBRATION, - Q6AFE_MSM_SPKR_FTM_MODE + Q6AFE_MSM_SPKR_FTM_MODE, + Q6AFE_MSM_SPKR_V_VALI_MODE }; enum { @@ -124,8 +135,10 @@ struct afe_ctl { struct audio_cal_info_spk_prot_cfg prot_cfg; struct afe_spkr_prot_calib_get_resp calib_data; struct audio_cal_info_sp_th_vi_ftm_cfg th_ftm_cfg; + struct audio_cal_info_sp_th_vi_v_vali_cfg v_vali_cfg; struct audio_cal_info_sp_ex_vi_ftm_cfg ex_ftm_cfg; struct afe_sp_th_vi_get_param_resp th_vi_resp; + struct afe_sp_th_vi_v_vali_get_param_resp th_vi_v_vali_resp; struct afe_sp_ex_vi_get_param_resp ex_vi_resp; struct afe_av_dev_drift_get_param_resp av_dev_drift_resp; struct afe_doa_tracking_mon_get_param_resp doa_tracking_mon_resp; @@ -364,6 +377,10 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload, expected_size += sizeof(struct afe_sp_th_vi_ftm_params); data_dest = (u32 *) &this_afe.th_vi_resp; break; + case AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_PARAMS: + expected_size += sizeof(struct afe_sp_th_vi_v_vali_params); + data_dest = (u32 *) &this_afe.th_vi_v_vali_resp; + break; case AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS: expected_size += sizeof(struct afe_sp_ex_vi_ftm_params); data_dest = (u32 *) &this_afe.ex_vi_resp; @@ -1606,10 +1623,12 @@ static int afe_spk_prot_prepare(int src_port, int dst_port, int param_id, break; /* * AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2 is same as - * AFE_PARAM_ID_SP_V2_TH_VI_MODE_CFG + * AFE_PARAM_ID_SP_V2_TH_VI_MODE_CFG. V_VALI_CFG uses + * same module TH_VI. */ case AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2: case AFE_PARAM_ID_SP_V2_TH_VI_FTM_CFG: + case AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_CFG: param_info.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI; break; case AFE_PARAM_ID_SP_V2_EX_VI_MODE_CFG: @@ -1737,6 +1756,10 @@ static void afe_send_cal_spkr_prot_tx(int port_id) if (this_afe.th_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE) afe_spk_config.vi_proc_cfg.operation_mode = Q6AFE_MSM_SPKR_FTM_MODE; + else if (this_afe.v_vali_cfg.mode == + MSM_SPKR_PROT_IN_V_VALI_MODE) + afe_spk_config.vi_proc_cfg.operation_mode = + Q6AFE_MSM_SPKR_V_VALI_MODE; afe_spk_config.vi_proc_cfg.minor_version = 1; afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_1] = (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_1]; @@ -1789,6 +1812,25 @@ static void afe_send_cal_spkr_prot_tx(int port_id) &afe_spk_config)) pr_err("%s: th vi ftm cfg failed\n", __func__); this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED; + } else if ((this_afe.v_vali_cfg.mode == + MSM_SPKR_PROT_IN_V_VALI_MODE) && + (this_afe.vi_tx_port == port_id)) { + afe_spk_config.th_vi_v_vali_cfg.minor_version = 1; + afe_spk_config.th_vi_v_vali_cfg.wait_time_ms[SP_V2_SPKR_1] = + this_afe.v_vali_cfg.wait_time[SP_V2_SPKR_1]; + afe_spk_config.th_vi_v_vali_cfg.wait_time_ms[SP_V2_SPKR_2] = + this_afe.v_vali_cfg.wait_time[SP_V2_SPKR_2]; + afe_spk_config.th_vi_v_vali_cfg.vali_time_ms[SP_V2_SPKR_1] = + this_afe.v_vali_cfg.vali_time[SP_V2_SPKR_1]; + afe_spk_config.th_vi_v_vali_cfg.vali_time_ms[SP_V2_SPKR_2] = + this_afe.v_vali_cfg.vali_time[SP_V2_SPKR_2]; + + if (afe_spk_prot_prepare(port_id, 0, + AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_CFG, + &afe_spk_config)) + pr_err("%s: th vi v-vali cfg failed\n", __func__); + + this_afe.v_vali_cfg.mode = MSM_SPKR_PROT_DISABLED; } mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock); @@ -7453,6 +7495,46 @@ int q6afe_check_osr_clk_freq(u32 freq) } EXPORT_SYMBOL(q6afe_check_osr_clk_freq); +static int afe_get_sp_th_vi_v_vali_data( + struct afe_sp_th_vi_v_vali_get_param *th_vi_v_vali) +{ + struct param_hdr_v3 param_hdr; + int port = SLIMBUS_4_TX; + int ret = -EINVAL; + + if (!th_vi_v_vali) { + pr_err("%s: Invalid params\n", __func__); + goto done; + } + if (this_afe.vi_tx_port != -1) + port = this_afe.vi_tx_port; + + memset(¶m_hdr, 0, sizeof(param_hdr)); + + param_hdr.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI; + param_hdr.instance_id = INSTANCE_ID_0; + param_hdr.param_id = AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_PARAMS; + param_hdr.param_size = sizeof(struct afe_sp_th_vi_v_vali_params); + + ret = q6afe_get_params(port, NULL, ¶m_hdr); + if (ret) { + pr_err("%s: Failed to get TH VI V-Vali data\n", __func__); + goto done; + } + + th_vi_v_vali->pdata = param_hdr; + memcpy(&th_vi_v_vali->param, &this_afe.th_vi_v_vali_resp.param, + sizeof(this_afe.th_vi_v_vali_resp.param)); + pr_debug("%s: Vrms %d %d status %d %d\n", __func__, + th_vi_v_vali->param.vrms_q24[SP_V2_SPKR_1], + th_vi_v_vali->param.vrms_q24[SP_V2_SPKR_2], + th_vi_v_vali->param.status[SP_V2_SPKR_1], + th_vi_v_vali->param.status[SP_V2_SPKR_2]); + ret = 0; +done: + return ret; +} + int afe_get_sp_th_vi_ftm_data(struct afe_sp_th_vi_get_param *th_vi) { struct param_hdr_v3 param_hdr; @@ -7952,21 +8034,57 @@ done: return ret; } +static int afe_set_cal_sp_th_vi_v_vali_cfg(int32_t cal_type, size_t data_size, + void *data) +{ + int ret = 0; + struct audio_cal_type_sp_th_vi_v_vali_cfg *cal_data = data; + + if (cal_data == NULL || data_size != sizeof(*cal_data)) + goto done; + + memcpy(&this_afe.v_vali_cfg, &cal_data->cal_info, + sizeof(this_afe.v_vali_cfg)); +done: + return ret; +} + static int afe_set_cal_sp_th_vi_ftm_cfg(int32_t cal_type, size_t data_size, void *data) { int ret = 0; struct audio_cal_type_sp_th_vi_ftm_cfg *cal_data = data; - if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL || - cal_data == NULL || - data_size != sizeof(*cal_data)) + if (cal_data == NULL || data_size != sizeof(*cal_data)) goto done; - pr_debug("%s: cal_type = %d\n", __func__, cal_type); - mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock); memcpy(&this_afe.th_ftm_cfg, &cal_data->cal_info, sizeof(this_afe.th_ftm_cfg)); +done: + return ret; +} + +static int afe_set_cal_sp_th_vi_cfg(int32_t cal_type, size_t data_size, + void *data) +{ + int ret = 0; + struct audio_cal_type_sp_th_vi_ftm_cfg *cal_data = data; + uint32_t mode; + + if (cal_data == NULL || + this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL) + goto done; + + mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock); + mode = cal_data->cal_info.mode; + pr_debug("%s: cal_type = %d, mode = %d\n", __func__, cal_type, mode); + if (mode == MSM_SPKR_PROT_IN_FTM_MODE) { + ret = afe_set_cal_sp_th_vi_ftm_cfg(cal_type, + data_size, data); + } else if (mode == MSM_SPKR_PROT_IN_V_VALI_MODE) { + ret = afe_set_cal_sp_th_vi_v_vali_cfg(cal_type, + data_size, data); + } mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock); done: return ret; @@ -8017,6 +8135,41 @@ done: return ret; } +static int afe_get_cal_sp_th_vi_v_vali_param(int32_t cal_type, size_t data_size, + void *data) +{ + int i, ret = 0; + struct audio_cal_type_sp_th_vi_v_vali_param *cal_data = data; + struct afe_sp_th_vi_v_vali_get_param th_vi_v_vali; + + if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL || + cal_data == NULL || + data_size != sizeof(*cal_data)) + goto done; + + for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) { + cal_data->cal_info.status[i] = -EINVAL; + cal_data->cal_info.vrms_q24[i] = -1; + } + if (!afe_get_sp_th_vi_v_vali_data(&th_vi_v_vali)) { + for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) { + pr_debug("%s: v-vali param status = %d\n", + __func__, th_vi_v_vali.param.status[i]); + if (th_vi_v_vali.param.status[i] == + V_VALI_IN_PROGRESS) { + cal_data->cal_info.status[i] = -EAGAIN; + } else if (th_vi_v_vali.param.status[i] == + V_VALI_SUCCESS) { + cal_data->cal_info.status[i] = V_VALI_SUCCESS; + cal_data->cal_info.vrms_q24[i] = + th_vi_v_vali.param.vrms_q24[i]; + } + } + } +done: + return ret; +} + static int afe_get_cal_sp_th_vi_ftm_param(int32_t cal_type, size_t data_size, void *data) { @@ -8024,13 +8177,11 @@ static int afe_get_cal_sp_th_vi_ftm_param(int32_t cal_type, size_t data_size, struct audio_cal_type_sp_th_vi_param *cal_data = data; struct afe_sp_th_vi_get_param th_vi; - pr_debug("%s: cal_type = %d\n", __func__, cal_type); if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL || cal_data == NULL || data_size != sizeof(*cal_data)) goto done; - mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock); for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) { cal_data->cal_info.status[i] = -EINVAL; cal_data->cal_info.r_dc_q24[i] = -1; @@ -8051,11 +8202,34 @@ static int afe_get_cal_sp_th_vi_ftm_param(int32_t cal_type, size_t data_size, } } } - mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock); done: return ret; } +static int afe_get_cal_sp_th_vi_param(int32_t cal_type, size_t data_size, + void *data) +{ + struct audio_cal_type_sp_th_vi_param *cal_data = data; + uint32_t mode; + int ret = 0; + + if (cal_data == NULL || + this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL) + return 0; + + mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock); + mode = cal_data->cal_info.mode; + pr_debug("%s: cal_type = %d,mode = %d\n", __func__, cal_type, mode); + if (mode == MSM_SPKR_PROT_IN_V_VALI_MODE) + ret = afe_get_cal_sp_th_vi_v_vali_param(cal_type, + data_size, data); + else + ret = afe_get_cal_sp_th_vi_ftm_param(cal_type, + data_size, data); + mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock); + return ret; +} + static int afe_get_cal_sp_ex_vi_ftm_param(int32_t cal_type, size_t data_size, void *data) { @@ -8313,8 +8487,8 @@ static int afe_init_cal_data(void) cal_utils_match_buf_num} }, {{AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE, - {NULL, NULL, NULL, afe_set_cal_sp_th_vi_ftm_cfg, - afe_get_cal_sp_th_vi_ftm_param, NULL} }, + {NULL, NULL, NULL, afe_set_cal_sp_th_vi_cfg, + afe_get_cal_sp_th_vi_param, NULL} }, {NULL, NULL, cal_utils_match_buf_num} }, {{AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE, diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index d2cab24e6a51..3f50d1041180 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -10468,6 +10468,8 @@ struct asm_mode_vi_proc_cfg { #define AFE_PARAM_ID_SP_V2_TH_VI_MODE_CFG 0x0001026B #define AFE_PARAM_ID_SP_V2_TH_VI_FTM_CFG 0x0001029F #define AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS 0x000102A0 +#define AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_CFG 0x000102BF +#define AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_PARAMS 0x000102C0 struct afe_sp_th_vi_mode_cfg { uint32_t minor_version; @@ -10557,6 +10559,51 @@ struct afe_sp_th_vi_get_param_resp { struct afe_sp_th_vi_ftm_params param; } __packed; +struct afe_sp_th_vi_v_vali_cfg { + uint32_t minor_version; + uint32_t wait_time_ms[SP_V2_NUM_MAX_SPKR]; + /* + * Wait time to heat up speaker before collecting statistics + * for V validation mode in ms. + * values 100 to 1000 ms + */ + uint32_t vali_time_ms[SP_V2_NUM_MAX_SPKR]; + /* + * duration for which V VALIDATION statistics are collected in ms. + * values 1000 to 3000 ms + */ +} __packed; + +struct afe_sp_th_vi_v_vali_params { + uint32_t minor_version; + uint32_t vrms_q24[SP_V2_NUM_MAX_SPKR]; + /* + * Vrms value in q24 format + * values [0 33554432] Q24 (0 - 2Vrms) + */ + uint32_t status[SP_V2_NUM_MAX_SPKR]; + /* + * v-vali packet status + * 0 - Failed. + * 1 - Success. + * 2 - Incorrect operation mode.This status is returned + * when GET_PARAM is called in non v-vali Mode + * 3 - Inactive mode -- Port is not yet started. + * 4 - Wait state. wait_time_ms has not yet elapsed + * 5 - In progress state. ftm_time_ms has not yet elapsed. + */ +} __packed; + +struct afe_sp_th_vi_v_vali_get_param { + struct param_hdr_v3 pdata; + struct afe_sp_th_vi_v_vali_params param; +} __packed; + +struct afe_sp_th_vi_v_vali_get_param_resp { + uint32_t status; + struct param_hdr_v3 pdata; + struct afe_sp_th_vi_v_vali_params param; +} __packed; #define AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI 0x0001026F #define AFE_PARAM_ID_SP_V2_EX_VI_MODE_CFG 0x000102A1 @@ -10641,6 +10688,7 @@ union afe_spkr_prot_config { struct asm_mode_vi_proc_cfg mode_vi_proc_cfg; struct afe_sp_th_vi_mode_cfg th_vi_mode_cfg; struct afe_sp_th_vi_ftm_cfg th_vi_ftm_cfg; + struct afe_sp_th_vi_v_vali_cfg th_vi_v_vali_cfg; struct afe_sp_ex_vi_mode_cfg ex_vi_mode_cfg; struct afe_sp_ex_vi_ftm_cfg ex_vi_ftm_cfg; struct afe_sp_rx_limiter_th_param limiter_th_cfg;