Loading include/sound/apr_audio-v2.h +14 −4 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ #define ADM_MAX_COPPS 5 /* make sure this matches with msm_audio_calibration */ #define SP_V2_NUM_MAX_SPKR 2 /* Session map node structure. * Immediately following this structure are num_copps Loading Loading @@ -6860,8 +6862,10 @@ struct cmd_set_topologies { */ #define AFE_MODULE_FB_SPKR_PROT_RX 0x0001021C #define AFE_MODULE_FB_SPKR_PROT_V2_RX 0x0001025F #define AFE_PARAM_ID_FBSP_MODE_RX_CFG 0x0001021D #define AFE_PARAM_ID_FBSP_PTONE_RAMP_CFG 0x00010260 struct asm_fbsp_mode_rx_cfg { uint32_t minor_version; Loading @@ -6878,25 +6882,31 @@ struct asm_fbsp_mode_rx_cfg { */ #define AFE_MODULE_FB_SPKR_PROT_VI_PROC 0x00010226 #define AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2 0x0001026A #define AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG 0x0001022A #define AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2 0x0001026B struct asm_spkr_calib_vi_proc_cfg { uint32_t minor_version; int32_t r0_cali_q24; int16_t t0_cali_q6; int16_t reserved; uint32_t operation_mode; uint32_t r0_t0_selection_flag[SP_V2_NUM_MAX_SPKR]; int32_t r0_cali_q24[SP_V2_NUM_MAX_SPKR]; int16_t t0_cali_q6[SP_V2_NUM_MAX_SPKR]; uint32_t quick_calib_flag; } __packed; #define AFE_PARAM_ID_CALIB_RES_CFG 0x0001022B #define AFE_PARAM_ID_CALIB_RES_CFG_V2 0x0001026E struct asm_calib_res_cfg { uint32_t minor_version; int32_t r0_cali_q24; int32_t r0_cali_q24[SP_V2_NUM_MAX_SPKR]; uint32_t th_vi_ca_state; } __packed; #define AFE_PARAM_ID_FEEDBACK_PATH_CFG 0x0001022C #define AFE_MODULE_FEEDBACK 0x00010257 struct asm_feedback_path_cfg { uint32_t minor_version; Loading include/uapi/linux/msm_audio_calibration.h +10 −3 Original line number Diff line number Diff line Loading @@ -249,16 +249,23 @@ enum msm_spkr_prot_states { MSM_SPKR_PROT_NOT_CALIBRATED }; enum msm_spkr_count { SP_V2_SPKR_1, SP_V2_SPKR_2, SP_V2_NUM_MAX_SPKRS }; struct audio_cal_info_spk_prot_cfg { int32_t r0; int32_t t0; int32_t r0[SP_V2_NUM_MAX_SPKRS]; int32_t t0[SP_V2_NUM_MAX_SPKRS]; uint32_t quick_calib_flag; uint32_t mode; /*0 - Start spk prot 1 - Start calib 2 - Disable spk prot*/ }; struct audio_cal_info_msm_spk_prot_status { int32_t r0; int32_t r0[SP_V2_NUM_MAX_SPKRS]; int32_t status; }; Loading sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +70 −1 Original line number Diff line number Diff line Loading @@ -88,7 +88,6 @@ static const char * const mad_audio_mux_text[] = { TERT_MI2S_TX_TEXT }; static void msm_pcm_routing_cfg_pp(int port_id, int copp_idx, int topology, int channels) { Loading Loading @@ -3742,6 +3741,44 @@ static int spkr_prot_put_vi_lch_port(struct snd_kcontrol *kcontrol, return ret; } static int spkr_prot_put_vi_rch_port(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int ret = 0; int item; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; pr_debug("%s item is %d\n", __func__, ucontrol->value.enumerated.item[0]); mutex_lock(&routing_lock); item = ucontrol->value.enumerated.item[0]; if (item < e->max) { pr_debug("%s RX DAI ID %d TX DAI id %d\n", __func__, e->shift_l , e->values[item]); if (e->shift_l < MSM_BACKEND_DAI_MAX && e->values[item] < MSM_BACKEND_DAI_MAX) /* Enable feedback TX path */ ret = afe_spk_prot_feed_back_cfg( msm_bedais[e->values[item]].port_id, msm_bedais[e->shift_l].port_id, 1, 1, 1); else { pr_debug("%s values are out of range item %d\n", __func__, e->values[item]); /* Disable feedback TX path */ if (e->values[item] == MSM_BACKEND_DAI_MAX) ret = afe_spk_prot_feed_back_cfg(0, 0, 0, 0, 0); else ret = -EINVAL; } } else { pr_err("%s item value is out of range item\n", __func__); ret = -EINVAL; } mutex_unlock(&routing_lock); return ret; } static int spkr_prot_get_vi_lch_port(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading @@ -3749,23 +3786,50 @@ static int spkr_prot_get_vi_lch_port(struct snd_kcontrol *kcontrol, return 0; } static int spkr_prot_get_vi_rch_port(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { pr_debug("%s\n", __func__); ucontrol->value.enumerated.item[0] = 0; return 0; } static const char * const slim0_rx_vi_fb_tx_lch_mux_text[] = { "ZERO", "SLIM4_TX" }; static const char * const slim0_rx_vi_fb_tx_rch_mux_text[] = { "ZERO", "SLIM4_TX" }; static const int const slim0_rx_vi_fb_tx_lch_value[] = { MSM_BACKEND_DAI_MAX, MSM_BACKEND_DAI_SLIMBUS_4_TX }; static const int const slim0_rx_vi_fb_tx_rch_value[] = { MSM_BACKEND_DAI_MAX, MSM_BACKEND_DAI_SLIMBUS_4_TX }; static const struct soc_enum slim0_rx_vi_fb_lch_mux_enum = SOC_VALUE_ENUM_DOUBLE(0, MSM_BACKEND_DAI_SLIMBUS_0_RX, 0, 0, ARRAY_SIZE(slim0_rx_vi_fb_tx_lch_mux_text), slim0_rx_vi_fb_tx_lch_mux_text, slim0_rx_vi_fb_tx_lch_value); static const struct soc_enum slim0_rx_vi_fb_rch_mux_enum = SOC_VALUE_ENUM_DOUBLE(0, MSM_BACKEND_DAI_SLIMBUS_0_RX, 0, 0, ARRAY_SIZE(slim0_rx_vi_fb_tx_rch_mux_text), slim0_rx_vi_fb_tx_rch_mux_text, slim0_rx_vi_fb_tx_rch_value); static const struct snd_kcontrol_new slim0_rx_vi_fb_lch_mux = SOC_DAPM_ENUM_EXT("SLIM0_RX_VI_FB_LCH_MUX", slim0_rx_vi_fb_lch_mux_enum, spkr_prot_get_vi_lch_port, spkr_prot_put_vi_lch_port); static const struct snd_kcontrol_new slim0_rx_vi_fb_rch_mux = SOC_DAPM_ENUM_EXT("SLIM0_RX_VI_FB_RCH_MUX", slim0_rx_vi_fb_rch_mux_enum, spkr_prot_get_vi_rch_port, spkr_prot_put_vi_rch_port); static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { /* Frontend AIF */ /* Widget name equals to Front-End DAI name<Need confirmation>, Loading Loading @@ -4179,6 +4243,9 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MUX("SLIM0_RX_VI_FB_LCH_MUX", SND_SOC_NOPM, 0, 0, &slim0_rx_vi_fb_lch_mux), SND_SOC_DAPM_MUX("SLIM0_RX_VI_FB_RCH_MUX", SND_SOC_NOPM, 0, 0, &slim0_rx_vi_fb_rch_mux), SND_SOC_DAPM_MUX("VOC_EXT_EC MUX", SND_SOC_NOPM, 0, 0, &voc_ext_ec_mux), SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL1 MUX", SND_SOC_NOPM, 0, 0, Loading Loading @@ -5066,7 +5133,9 @@ static const struct snd_soc_dapm_route intercon[] = { {"INCALL_RECORD_TX", NULL, "BE_IN"}, {"INCALL_RECORD_RX", NULL, "BE_IN"}, {"SLIM0_RX_VI_FB_LCH_MUX", "SLIM4_TX", "SLIMBUS_4_TX"}, {"SLIM0_RX_VI_FB_RCH_MUX", "SLIM4_TX", "SLIMBUS_4_TX"}, {"SLIMBUS_0_RX", NULL, "SLIM0_RX_VI_FB_LCH_MUX"}, {"SLIMBUS_0_RX", NULL, "SLIM0_RX_VI_FB_RCH_MUX"}, }; static int msm_pcm_routing_hw_params(struct snd_pcm_substream *substream, Loading sound/soc/msm/qdsp6v2/q6afe.c +180 −42 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <linux/jiffies.h> #include <linux/sched.h> #include <linux/msm_audio_ion.h> #include <linux/delay.h> #include <sound/apr_audio-v2.h> #include <sound/q6afe-v2.h> #include <sound/q6audio-v2.h> Loading @@ -34,6 +35,35 @@ enum { MAX_AFE_CAL_TYPES }; enum calibration_state { CALIB_INCORRECT_OP_MODE, CALIB_INACTIVE, CALIB_WARMUP, CALIB_IN_PROGRESS, CALIB_SUCCESS, CALIB_FAILED, MAX_CALIB_STATE }; static char cali_state[MAX_CALIB_STATE][50] = { [CALIB_INCORRECT_OP_MODE] = "incorrect operation mode", [CALIB_INACTIVE] = "port not started", [CALIB_WARMUP] = "waiting for warmup", [CALIB_IN_PROGRESS] = "in calibration state", [CALIB_SUCCESS] = "success", [CALIB_FAILED] = "failed" }; enum { USE_CALIBRATED_R0TO, USE_SAFE_R0TO }; enum { QUICK_CALIB_DISABLE, QUICK_CALIB_ENABLE }; struct afe_ctl { void *apr; atomic_t state; Loading Loading @@ -160,9 +190,10 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) sizeof(this_afe.calib_data)); if (!this_afe.calib_data.status) { atomic_set(&this_afe.state, 0); pr_err("%s: rest = %d state = 0x%x\n", __func__ , this_afe.calib_data.res_cfg.r0_cali_q24, this_afe.calib_data.res_cfg.th_vi_ca_state); pr_err("%s: rest = %d %d state = %s\n", __func__ , this_afe.calib_data.res_cfg.r0_cali_q24[SP_V2_SPKR_1], this_afe.calib_data.res_cfg.r0_cali_q24[SP_V2_SPKR_2], cali_state[this_afe.calib_data.res_cfg.th_vi_ca_state]); } else atomic_set(&this_afe.state, -1); wake_up(&this_afe.wait[data->token]); Loading Loading @@ -483,6 +514,73 @@ done: return result; } static int afe_spk_ramp_dn_cfg(int port) { int ret = -EINVAL; int index = 0; struct afe_spkr_prot_config_command config; if (afe_get_port_type(port) != MSM_AFE_PORT_TYPE_RX) { pr_debug("%s: port doesn't match 0x%x\n", __func__, port); return 0; } if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_DISABLED) { pr_debug("%s: spkr protection disabled port 0x%x %d\n", __func__, port, ret); return 0; } memset(&config, 0 , sizeof(config)); ret = q6audio_validate_port(port); if (ret < 0) { pr_err("%s: Invalid port 0x%x ret %d", __func__, port, ret); ret = -EINVAL; goto fail_cmd; } index = q6audio_get_port_index(port); config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); config.hdr.pkt_size = sizeof(config); config.hdr.src_port = 0; config.hdr.dest_port = 0; config.hdr.token = index; config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2; config.param.port_id = q6audio_get_port_id(port); config.param.payload_size = sizeof(config) - sizeof(config.hdr) - sizeof(config.param) - sizeof(config.prot_config); config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX; config.pdata.param_id = AFE_PARAM_ID_FBSP_PTONE_RAMP_CFG; config.pdata.param_size = 0; atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config); if (ret < 0) { pr_err("%s: port = 0x%x param = 0x%x failed %d\n", __func__, port, config.pdata.param_id, ret); goto fail_cmd; } ret = wait_event_timeout(this_afe.wait[index], (atomic_read(&this_afe.state) == 0), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); ret = -EINVAL; goto fail_cmd; } if (atomic_read(&this_afe.status) != 0) { pr_err("%s: config cmd failed\n", __func__); ret = -EINVAL; goto fail_cmd; } /* dsp needs atleast 15ms to ramp down pilot tone*/ usleep_range(15000, 15010); ret = 0; fail_cmd: pr_debug("%s: config.pdata.param_id 0x%x status %d\n", __func__, config.pdata.param_id, ret); return ret; } static int afe_spk_prot_prepare(int port, int param_id, union afe_spkr_prot_config *prot_config) { Loading @@ -504,13 +602,14 @@ static int afe_spk_prot_prepare(int port, int param_id, index = q6audio_get_port_index(port); switch (param_id) { case AFE_PARAM_ID_FBSP_MODE_RX_CFG: config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_RX; config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX; break; case AFE_PARAM_ID_FEEDBACK_PATH_CFG: this_afe.vi_tx_port = port; case AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG: case AFE_PARAM_ID_MODE_VI_PROC_CFG: config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC; config.pdata.module_id = AFE_MODULE_FEEDBACK; break; case AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2: config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2; break; default: pr_err("%s: default case 0x%x\n", __func__, param_id); Loading Loading @@ -572,29 +671,45 @@ static void afe_send_cal_spkr_prot_tx(int port_id) (this_afe.vi_tx_port == port_id)) { afe_spk_config.mode_rx_cfg.minor_version = 1; if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) afe_spk_config.mode_rx_cfg.mode = MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) { afe_spk_config.vi_proc_cfg.operation_mode = Q6AFE_MSM_SPKR_CALIBRATION; else afe_spk_config.mode_rx_cfg.mode = afe_spk_config.vi_proc_cfg.quick_calib_flag = this_afe.prot_cfg.quick_calib_flag; } else { afe_spk_config.vi_proc_cfg.operation_mode = Q6AFE_MSM_SPKR_PROCESSING; if (afe_spk_prot_prepare(port_id, AFE_PARAM_ID_MODE_VI_PROC_CFG, &afe_spk_config)) pr_err("%s: TX VI_PROC_CFG failed\n", __func__); if (this_afe.prot_cfg.mode != MSM_SPKR_PROT_NOT_CALIBRATED) { } afe_spk_config.vi_proc_cfg.minor_version = 1; afe_spk_config.vi_proc_cfg.r0_cali_q24 = (uint32_t) this_afe.prot_cfg.r0; afe_spk_config.vi_proc_cfg.t0_cali_q6 = (uint32_t) this_afe.prot_cfg.t0; afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_1] = (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_1]; afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_2] = (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_2]; afe_spk_config.vi_proc_cfg.t0_cali_q6[SP_V2_SPKR_1] = (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_1]; afe_spk_config.vi_proc_cfg.t0_cali_q6[SP_V2_SPKR_2] = (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_2]; if (this_afe.prot_cfg.mode != MSM_SPKR_PROT_NOT_CALIBRATED) { struct asm_spkr_calib_vi_proc_cfg *vi_proc_cfg; vi_proc_cfg = &afe_spk_config.vi_proc_cfg; vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_1] = USE_CALIBRATED_R0TO; vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_2] = USE_CALIBRATED_R0TO; } else { struct asm_spkr_calib_vi_proc_cfg *vi_proc_cfg; vi_proc_cfg = &afe_spk_config.vi_proc_cfg; vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_1] = USE_SAFE_R0TO; vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_2] = USE_SAFE_R0TO; } if (afe_spk_prot_prepare(port_id, AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG, AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2, &afe_spk_config)) pr_err("%s: SPKR_CALIB_VI_PROC_CFG failed\n", __func__); } } mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock); done: return; Loading Loading @@ -737,8 +852,10 @@ static void send_afe_cal_type(int cal_index, int port_id) mutex_lock(&this_afe.cal_data[cal_index]->lock); cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]); if (cal_block == NULL) if (cal_block == NULL) { pr_err("%s cal_block not found!!\n", __func__); goto unlock; } pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index); Loading Loading @@ -3460,6 +3577,13 @@ int afe_close(int port_id) __func__, ret); } /* * even if ramp down configuration failed it is not serious enough to * warrant bailaing out. */ if (afe_spk_ramp_dn_cfg(port_id) < 0) pr_err("%s: ramp down configuration failed\n", __func__); stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); stop.hdr.pkt_size = sizeof(stop); Loading Loading @@ -3760,15 +3884,15 @@ int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib_resp) calib_resp->hdr.token = index; calib_resp->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2; calib_resp->get_param.mem_map_handle = 0; calib_resp->get_param.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC; calib_resp->get_param.param_id = AFE_PARAM_ID_CALIB_RES_CFG; calib_resp->get_param.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2; calib_resp->get_param.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2; calib_resp->get_param.payload_address_lsw = 0; calib_resp->get_param.payload_address_msw = 0; calib_resp->get_param.payload_size = sizeof(*calib_resp) - sizeof(calib_resp->get_param) - sizeof(calib_resp->hdr); calib_resp->get_param.port_id = q6audio_get_port_id(port); calib_resp->pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC; calib_resp->pdata.param_id = AFE_PARAM_ID_CALIB_RES_CFG; calib_resp->pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2; calib_resp->pdata.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2; calib_resp->pdata.param_size = sizeof(calib_resp->res_cfg); atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *)calib_resp); Loading @@ -3792,9 +3916,10 @@ int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib_resp) } memcpy(&calib_resp->res_cfg , &this_afe.calib_data.res_cfg, sizeof(this_afe.calib_data.res_cfg)); pr_info("%s: state %d resistance %d\n", __func__, calib_resp->res_cfg.th_vi_ca_state, calib_resp->res_cfg.r0_cali_q24); pr_info("%s: state %s resistance %d %d\n", __func__, cali_state[calib_resp->res_cfg.th_vi_ca_state], calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_1], calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_2]); ret = 0; fail_cmd: return ret; Loading Loading @@ -3837,6 +3962,7 @@ int afe_spk_prot_feed_back_cfg(int src_port, int dst_port, prot_config.feedback_path_cfg.chan_info[index++] = 4; } prot_config.feedback_path_cfg.num_channels = index; pr_debug("%s no of channels: %d\n", __func__, index); prot_config.feedback_path_cfg.minor_version = 1; ret = afe_spk_prot_prepare(src_port, AFE_PARAM_ID_FEEDBACK_PATH_CFG, &prot_config); Loading Loading @@ -4077,31 +4203,43 @@ static int afe_get_cal_fb_spkr_prot(int32_t cal_type, size_t data_size, mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock); if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_CALIBRATED) { cal_data->cal_info.r0 = this_afe.prot_cfg.r0; cal_data->cal_info.r0[SP_V2_SPKR_1] = this_afe.prot_cfg.r0[SP_V2_SPKR_1]; cal_data->cal_info.r0[SP_V2_SPKR_2] = this_afe.prot_cfg.r0[SP_V2_SPKR_2]; cal_data->cal_info.status = 0; } else if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) { /*Call AFE to query the status*/ cal_data->cal_info.status = -EINVAL; cal_data->cal_info.r0 = -1; cal_data->cal_info.r0[SP_V2_SPKR_1] = -1; cal_data->cal_info.r0[SP_V2_SPKR_2] = -1; if (!afe_spk_prot_get_calib_data(&calib_resp)) { if (calib_resp.res_cfg.th_vi_ca_state == 1) if (calib_resp.res_cfg.th_vi_ca_state == CALIB_IN_PROGRESS) cal_data->cal_info.status = -EAGAIN; else if (calib_resp.res_cfg.th_vi_ca_state == 2) { else if (calib_resp.res_cfg.th_vi_ca_state == CALIB_SUCCESS) { cal_data->cal_info.status = 0; cal_data->cal_info.r0 = calib_resp.res_cfg.r0_cali_q24; cal_data->cal_info.r0[SP_V2_SPKR_1] = calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_1]; cal_data->cal_info.r0[SP_V2_SPKR_2] = calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_2]; } } if (!cal_data->cal_info.status) { this_afe.prot_cfg.mode = MSM_SPKR_PROT_CALIBRATED; this_afe.prot_cfg.r0 = cal_data->cal_info.r0; this_afe.prot_cfg.r0[SP_V2_SPKR_1] = cal_data->cal_info.r0[SP_V2_SPKR_1]; this_afe.prot_cfg.r0[SP_V2_SPKR_2] = cal_data->cal_info.r0[SP_V2_SPKR_2]; } } else { /*Indicates calibration data is invalid*/ cal_data->cal_info.status = -EINVAL; cal_data->cal_info.r0 = -1; cal_data->cal_info.r0[SP_V2_SPKR_1] = -1; cal_data->cal_info.r0[SP_V2_SPKR_2] = -1; } mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock); done: Loading Loading
include/sound/apr_audio-v2.h +14 −4 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ #define ADM_MAX_COPPS 5 /* make sure this matches with msm_audio_calibration */ #define SP_V2_NUM_MAX_SPKR 2 /* Session map node structure. * Immediately following this structure are num_copps Loading Loading @@ -6860,8 +6862,10 @@ struct cmd_set_topologies { */ #define AFE_MODULE_FB_SPKR_PROT_RX 0x0001021C #define AFE_MODULE_FB_SPKR_PROT_V2_RX 0x0001025F #define AFE_PARAM_ID_FBSP_MODE_RX_CFG 0x0001021D #define AFE_PARAM_ID_FBSP_PTONE_RAMP_CFG 0x00010260 struct asm_fbsp_mode_rx_cfg { uint32_t minor_version; Loading @@ -6878,25 +6882,31 @@ struct asm_fbsp_mode_rx_cfg { */ #define AFE_MODULE_FB_SPKR_PROT_VI_PROC 0x00010226 #define AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2 0x0001026A #define AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG 0x0001022A #define AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2 0x0001026B struct asm_spkr_calib_vi_proc_cfg { uint32_t minor_version; int32_t r0_cali_q24; int16_t t0_cali_q6; int16_t reserved; uint32_t operation_mode; uint32_t r0_t0_selection_flag[SP_V2_NUM_MAX_SPKR]; int32_t r0_cali_q24[SP_V2_NUM_MAX_SPKR]; int16_t t0_cali_q6[SP_V2_NUM_MAX_SPKR]; uint32_t quick_calib_flag; } __packed; #define AFE_PARAM_ID_CALIB_RES_CFG 0x0001022B #define AFE_PARAM_ID_CALIB_RES_CFG_V2 0x0001026E struct asm_calib_res_cfg { uint32_t minor_version; int32_t r0_cali_q24; int32_t r0_cali_q24[SP_V2_NUM_MAX_SPKR]; uint32_t th_vi_ca_state; } __packed; #define AFE_PARAM_ID_FEEDBACK_PATH_CFG 0x0001022C #define AFE_MODULE_FEEDBACK 0x00010257 struct asm_feedback_path_cfg { uint32_t minor_version; Loading
include/uapi/linux/msm_audio_calibration.h +10 −3 Original line number Diff line number Diff line Loading @@ -249,16 +249,23 @@ enum msm_spkr_prot_states { MSM_SPKR_PROT_NOT_CALIBRATED }; enum msm_spkr_count { SP_V2_SPKR_1, SP_V2_SPKR_2, SP_V2_NUM_MAX_SPKRS }; struct audio_cal_info_spk_prot_cfg { int32_t r0; int32_t t0; int32_t r0[SP_V2_NUM_MAX_SPKRS]; int32_t t0[SP_V2_NUM_MAX_SPKRS]; uint32_t quick_calib_flag; uint32_t mode; /*0 - Start spk prot 1 - Start calib 2 - Disable spk prot*/ }; struct audio_cal_info_msm_spk_prot_status { int32_t r0; int32_t r0[SP_V2_NUM_MAX_SPKRS]; int32_t status; }; Loading
sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +70 −1 Original line number Diff line number Diff line Loading @@ -88,7 +88,6 @@ static const char * const mad_audio_mux_text[] = { TERT_MI2S_TX_TEXT }; static void msm_pcm_routing_cfg_pp(int port_id, int copp_idx, int topology, int channels) { Loading Loading @@ -3742,6 +3741,44 @@ static int spkr_prot_put_vi_lch_port(struct snd_kcontrol *kcontrol, return ret; } static int spkr_prot_put_vi_rch_port(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int ret = 0; int item; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; pr_debug("%s item is %d\n", __func__, ucontrol->value.enumerated.item[0]); mutex_lock(&routing_lock); item = ucontrol->value.enumerated.item[0]; if (item < e->max) { pr_debug("%s RX DAI ID %d TX DAI id %d\n", __func__, e->shift_l , e->values[item]); if (e->shift_l < MSM_BACKEND_DAI_MAX && e->values[item] < MSM_BACKEND_DAI_MAX) /* Enable feedback TX path */ ret = afe_spk_prot_feed_back_cfg( msm_bedais[e->values[item]].port_id, msm_bedais[e->shift_l].port_id, 1, 1, 1); else { pr_debug("%s values are out of range item %d\n", __func__, e->values[item]); /* Disable feedback TX path */ if (e->values[item] == MSM_BACKEND_DAI_MAX) ret = afe_spk_prot_feed_back_cfg(0, 0, 0, 0, 0); else ret = -EINVAL; } } else { pr_err("%s item value is out of range item\n", __func__); ret = -EINVAL; } mutex_unlock(&routing_lock); return ret; } static int spkr_prot_get_vi_lch_port(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading @@ -3749,23 +3786,50 @@ static int spkr_prot_get_vi_lch_port(struct snd_kcontrol *kcontrol, return 0; } static int spkr_prot_get_vi_rch_port(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { pr_debug("%s\n", __func__); ucontrol->value.enumerated.item[0] = 0; return 0; } static const char * const slim0_rx_vi_fb_tx_lch_mux_text[] = { "ZERO", "SLIM4_TX" }; static const char * const slim0_rx_vi_fb_tx_rch_mux_text[] = { "ZERO", "SLIM4_TX" }; static const int const slim0_rx_vi_fb_tx_lch_value[] = { MSM_BACKEND_DAI_MAX, MSM_BACKEND_DAI_SLIMBUS_4_TX }; static const int const slim0_rx_vi_fb_tx_rch_value[] = { MSM_BACKEND_DAI_MAX, MSM_BACKEND_DAI_SLIMBUS_4_TX }; static const struct soc_enum slim0_rx_vi_fb_lch_mux_enum = SOC_VALUE_ENUM_DOUBLE(0, MSM_BACKEND_DAI_SLIMBUS_0_RX, 0, 0, ARRAY_SIZE(slim0_rx_vi_fb_tx_lch_mux_text), slim0_rx_vi_fb_tx_lch_mux_text, slim0_rx_vi_fb_tx_lch_value); static const struct soc_enum slim0_rx_vi_fb_rch_mux_enum = SOC_VALUE_ENUM_DOUBLE(0, MSM_BACKEND_DAI_SLIMBUS_0_RX, 0, 0, ARRAY_SIZE(slim0_rx_vi_fb_tx_rch_mux_text), slim0_rx_vi_fb_tx_rch_mux_text, slim0_rx_vi_fb_tx_rch_value); static const struct snd_kcontrol_new slim0_rx_vi_fb_lch_mux = SOC_DAPM_ENUM_EXT("SLIM0_RX_VI_FB_LCH_MUX", slim0_rx_vi_fb_lch_mux_enum, spkr_prot_get_vi_lch_port, spkr_prot_put_vi_lch_port); static const struct snd_kcontrol_new slim0_rx_vi_fb_rch_mux = SOC_DAPM_ENUM_EXT("SLIM0_RX_VI_FB_RCH_MUX", slim0_rx_vi_fb_rch_mux_enum, spkr_prot_get_vi_rch_port, spkr_prot_put_vi_rch_port); static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { /* Frontend AIF */ /* Widget name equals to Front-End DAI name<Need confirmation>, Loading Loading @@ -4179,6 +4243,9 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MUX("SLIM0_RX_VI_FB_LCH_MUX", SND_SOC_NOPM, 0, 0, &slim0_rx_vi_fb_lch_mux), SND_SOC_DAPM_MUX("SLIM0_RX_VI_FB_RCH_MUX", SND_SOC_NOPM, 0, 0, &slim0_rx_vi_fb_rch_mux), SND_SOC_DAPM_MUX("VOC_EXT_EC MUX", SND_SOC_NOPM, 0, 0, &voc_ext_ec_mux), SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL1 MUX", SND_SOC_NOPM, 0, 0, Loading Loading @@ -5066,7 +5133,9 @@ static const struct snd_soc_dapm_route intercon[] = { {"INCALL_RECORD_TX", NULL, "BE_IN"}, {"INCALL_RECORD_RX", NULL, "BE_IN"}, {"SLIM0_RX_VI_FB_LCH_MUX", "SLIM4_TX", "SLIMBUS_4_TX"}, {"SLIM0_RX_VI_FB_RCH_MUX", "SLIM4_TX", "SLIMBUS_4_TX"}, {"SLIMBUS_0_RX", NULL, "SLIM0_RX_VI_FB_LCH_MUX"}, {"SLIMBUS_0_RX", NULL, "SLIM0_RX_VI_FB_RCH_MUX"}, }; static int msm_pcm_routing_hw_params(struct snd_pcm_substream *substream, Loading
sound/soc/msm/qdsp6v2/q6afe.c +180 −42 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <linux/jiffies.h> #include <linux/sched.h> #include <linux/msm_audio_ion.h> #include <linux/delay.h> #include <sound/apr_audio-v2.h> #include <sound/q6afe-v2.h> #include <sound/q6audio-v2.h> Loading @@ -34,6 +35,35 @@ enum { MAX_AFE_CAL_TYPES }; enum calibration_state { CALIB_INCORRECT_OP_MODE, CALIB_INACTIVE, CALIB_WARMUP, CALIB_IN_PROGRESS, CALIB_SUCCESS, CALIB_FAILED, MAX_CALIB_STATE }; static char cali_state[MAX_CALIB_STATE][50] = { [CALIB_INCORRECT_OP_MODE] = "incorrect operation mode", [CALIB_INACTIVE] = "port not started", [CALIB_WARMUP] = "waiting for warmup", [CALIB_IN_PROGRESS] = "in calibration state", [CALIB_SUCCESS] = "success", [CALIB_FAILED] = "failed" }; enum { USE_CALIBRATED_R0TO, USE_SAFE_R0TO }; enum { QUICK_CALIB_DISABLE, QUICK_CALIB_ENABLE }; struct afe_ctl { void *apr; atomic_t state; Loading Loading @@ -160,9 +190,10 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) sizeof(this_afe.calib_data)); if (!this_afe.calib_data.status) { atomic_set(&this_afe.state, 0); pr_err("%s: rest = %d state = 0x%x\n", __func__ , this_afe.calib_data.res_cfg.r0_cali_q24, this_afe.calib_data.res_cfg.th_vi_ca_state); pr_err("%s: rest = %d %d state = %s\n", __func__ , this_afe.calib_data.res_cfg.r0_cali_q24[SP_V2_SPKR_1], this_afe.calib_data.res_cfg.r0_cali_q24[SP_V2_SPKR_2], cali_state[this_afe.calib_data.res_cfg.th_vi_ca_state]); } else atomic_set(&this_afe.state, -1); wake_up(&this_afe.wait[data->token]); Loading Loading @@ -483,6 +514,73 @@ done: return result; } static int afe_spk_ramp_dn_cfg(int port) { int ret = -EINVAL; int index = 0; struct afe_spkr_prot_config_command config; if (afe_get_port_type(port) != MSM_AFE_PORT_TYPE_RX) { pr_debug("%s: port doesn't match 0x%x\n", __func__, port); return 0; } if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_DISABLED) { pr_debug("%s: spkr protection disabled port 0x%x %d\n", __func__, port, ret); return 0; } memset(&config, 0 , sizeof(config)); ret = q6audio_validate_port(port); if (ret < 0) { pr_err("%s: Invalid port 0x%x ret %d", __func__, port, ret); ret = -EINVAL; goto fail_cmd; } index = q6audio_get_port_index(port); config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); config.hdr.pkt_size = sizeof(config); config.hdr.src_port = 0; config.hdr.dest_port = 0; config.hdr.token = index; config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2; config.param.port_id = q6audio_get_port_id(port); config.param.payload_size = sizeof(config) - sizeof(config.hdr) - sizeof(config.param) - sizeof(config.prot_config); config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX; config.pdata.param_id = AFE_PARAM_ID_FBSP_PTONE_RAMP_CFG; config.pdata.param_size = 0; atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config); if (ret < 0) { pr_err("%s: port = 0x%x param = 0x%x failed %d\n", __func__, port, config.pdata.param_id, ret); goto fail_cmd; } ret = wait_event_timeout(this_afe.wait[index], (atomic_read(&this_afe.state) == 0), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); ret = -EINVAL; goto fail_cmd; } if (atomic_read(&this_afe.status) != 0) { pr_err("%s: config cmd failed\n", __func__); ret = -EINVAL; goto fail_cmd; } /* dsp needs atleast 15ms to ramp down pilot tone*/ usleep_range(15000, 15010); ret = 0; fail_cmd: pr_debug("%s: config.pdata.param_id 0x%x status %d\n", __func__, config.pdata.param_id, ret); return ret; } static int afe_spk_prot_prepare(int port, int param_id, union afe_spkr_prot_config *prot_config) { Loading @@ -504,13 +602,14 @@ static int afe_spk_prot_prepare(int port, int param_id, index = q6audio_get_port_index(port); switch (param_id) { case AFE_PARAM_ID_FBSP_MODE_RX_CFG: config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_RX; config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX; break; case AFE_PARAM_ID_FEEDBACK_PATH_CFG: this_afe.vi_tx_port = port; case AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG: case AFE_PARAM_ID_MODE_VI_PROC_CFG: config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC; config.pdata.module_id = AFE_MODULE_FEEDBACK; break; case AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2: config.pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2; break; default: pr_err("%s: default case 0x%x\n", __func__, param_id); Loading Loading @@ -572,29 +671,45 @@ static void afe_send_cal_spkr_prot_tx(int port_id) (this_afe.vi_tx_port == port_id)) { afe_spk_config.mode_rx_cfg.minor_version = 1; if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) afe_spk_config.mode_rx_cfg.mode = MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) { afe_spk_config.vi_proc_cfg.operation_mode = Q6AFE_MSM_SPKR_CALIBRATION; else afe_spk_config.mode_rx_cfg.mode = afe_spk_config.vi_proc_cfg.quick_calib_flag = this_afe.prot_cfg.quick_calib_flag; } else { afe_spk_config.vi_proc_cfg.operation_mode = Q6AFE_MSM_SPKR_PROCESSING; if (afe_spk_prot_prepare(port_id, AFE_PARAM_ID_MODE_VI_PROC_CFG, &afe_spk_config)) pr_err("%s: TX VI_PROC_CFG failed\n", __func__); if (this_afe.prot_cfg.mode != MSM_SPKR_PROT_NOT_CALIBRATED) { } afe_spk_config.vi_proc_cfg.minor_version = 1; afe_spk_config.vi_proc_cfg.r0_cali_q24 = (uint32_t) this_afe.prot_cfg.r0; afe_spk_config.vi_proc_cfg.t0_cali_q6 = (uint32_t) this_afe.prot_cfg.t0; afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_1] = (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_1]; afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_2] = (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_2]; afe_spk_config.vi_proc_cfg.t0_cali_q6[SP_V2_SPKR_1] = (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_1]; afe_spk_config.vi_proc_cfg.t0_cali_q6[SP_V2_SPKR_2] = (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_2]; if (this_afe.prot_cfg.mode != MSM_SPKR_PROT_NOT_CALIBRATED) { struct asm_spkr_calib_vi_proc_cfg *vi_proc_cfg; vi_proc_cfg = &afe_spk_config.vi_proc_cfg; vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_1] = USE_CALIBRATED_R0TO; vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_2] = USE_CALIBRATED_R0TO; } else { struct asm_spkr_calib_vi_proc_cfg *vi_proc_cfg; vi_proc_cfg = &afe_spk_config.vi_proc_cfg; vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_1] = USE_SAFE_R0TO; vi_proc_cfg->r0_t0_selection_flag[SP_V2_SPKR_2] = USE_SAFE_R0TO; } if (afe_spk_prot_prepare(port_id, AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG, AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2, &afe_spk_config)) pr_err("%s: SPKR_CALIB_VI_PROC_CFG failed\n", __func__); } } mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock); done: return; Loading Loading @@ -737,8 +852,10 @@ static void send_afe_cal_type(int cal_index, int port_id) mutex_lock(&this_afe.cal_data[cal_index]->lock); cal_block = cal_utils_get_only_cal_block(this_afe.cal_data[cal_index]); if (cal_block == NULL) if (cal_block == NULL) { pr_err("%s cal_block not found!!\n", __func__); goto unlock; } pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index); Loading Loading @@ -3460,6 +3577,13 @@ int afe_close(int port_id) __func__, ret); } /* * even if ramp down configuration failed it is not serious enough to * warrant bailaing out. */ if (afe_spk_ramp_dn_cfg(port_id) < 0) pr_err("%s: ramp down configuration failed\n", __func__); stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); stop.hdr.pkt_size = sizeof(stop); Loading Loading @@ -3760,15 +3884,15 @@ int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib_resp) calib_resp->hdr.token = index; calib_resp->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2; calib_resp->get_param.mem_map_handle = 0; calib_resp->get_param.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC; calib_resp->get_param.param_id = AFE_PARAM_ID_CALIB_RES_CFG; calib_resp->get_param.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2; calib_resp->get_param.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2; calib_resp->get_param.payload_address_lsw = 0; calib_resp->get_param.payload_address_msw = 0; calib_resp->get_param.payload_size = sizeof(*calib_resp) - sizeof(calib_resp->get_param) - sizeof(calib_resp->hdr); calib_resp->get_param.port_id = q6audio_get_port_id(port); calib_resp->pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC; calib_resp->pdata.param_id = AFE_PARAM_ID_CALIB_RES_CFG; calib_resp->pdata.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2; calib_resp->pdata.param_id = AFE_PARAM_ID_CALIB_RES_CFG_V2; calib_resp->pdata.param_size = sizeof(calib_resp->res_cfg); atomic_set(&this_afe.state, 1); ret = apr_send_pkt(this_afe.apr, (uint32_t *)calib_resp); Loading @@ -3792,9 +3916,10 @@ int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib_resp) } memcpy(&calib_resp->res_cfg , &this_afe.calib_data.res_cfg, sizeof(this_afe.calib_data.res_cfg)); pr_info("%s: state %d resistance %d\n", __func__, calib_resp->res_cfg.th_vi_ca_state, calib_resp->res_cfg.r0_cali_q24); pr_info("%s: state %s resistance %d %d\n", __func__, cali_state[calib_resp->res_cfg.th_vi_ca_state], calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_1], calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_2]); ret = 0; fail_cmd: return ret; Loading Loading @@ -3837,6 +3962,7 @@ int afe_spk_prot_feed_back_cfg(int src_port, int dst_port, prot_config.feedback_path_cfg.chan_info[index++] = 4; } prot_config.feedback_path_cfg.num_channels = index; pr_debug("%s no of channels: %d\n", __func__, index); prot_config.feedback_path_cfg.minor_version = 1; ret = afe_spk_prot_prepare(src_port, AFE_PARAM_ID_FEEDBACK_PATH_CFG, &prot_config); Loading Loading @@ -4077,31 +4203,43 @@ static int afe_get_cal_fb_spkr_prot(int32_t cal_type, size_t data_size, mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock); if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_CALIBRATED) { cal_data->cal_info.r0 = this_afe.prot_cfg.r0; cal_data->cal_info.r0[SP_V2_SPKR_1] = this_afe.prot_cfg.r0[SP_V2_SPKR_1]; cal_data->cal_info.r0[SP_V2_SPKR_2] = this_afe.prot_cfg.r0[SP_V2_SPKR_2]; cal_data->cal_info.status = 0; } else if (this_afe.prot_cfg.mode == MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) { /*Call AFE to query the status*/ cal_data->cal_info.status = -EINVAL; cal_data->cal_info.r0 = -1; cal_data->cal_info.r0[SP_V2_SPKR_1] = -1; cal_data->cal_info.r0[SP_V2_SPKR_2] = -1; if (!afe_spk_prot_get_calib_data(&calib_resp)) { if (calib_resp.res_cfg.th_vi_ca_state == 1) if (calib_resp.res_cfg.th_vi_ca_state == CALIB_IN_PROGRESS) cal_data->cal_info.status = -EAGAIN; else if (calib_resp.res_cfg.th_vi_ca_state == 2) { else if (calib_resp.res_cfg.th_vi_ca_state == CALIB_SUCCESS) { cal_data->cal_info.status = 0; cal_data->cal_info.r0 = calib_resp.res_cfg.r0_cali_q24; cal_data->cal_info.r0[SP_V2_SPKR_1] = calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_1]; cal_data->cal_info.r0[SP_V2_SPKR_2] = calib_resp.res_cfg.r0_cali_q24[SP_V2_SPKR_2]; } } if (!cal_data->cal_info.status) { this_afe.prot_cfg.mode = MSM_SPKR_PROT_CALIBRATED; this_afe.prot_cfg.r0 = cal_data->cal_info.r0; this_afe.prot_cfg.r0[SP_V2_SPKR_1] = cal_data->cal_info.r0[SP_V2_SPKR_1]; this_afe.prot_cfg.r0[SP_V2_SPKR_2] = cal_data->cal_info.r0[SP_V2_SPKR_2]; } } else { /*Indicates calibration data is invalid*/ cal_data->cal_info.status = -EINVAL; cal_data->cal_info.r0 = -1; cal_data->cal_info.r0[SP_V2_SPKR_1] = -1; cal_data->cal_info.r0[SP_V2_SPKR_2] = -1; } mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock); done: Loading