diff options
Diffstat (limited to 'dsp/q6afe.c')
-rw-r--r-- | dsp/q6afe.c | 230 |
1 files changed, 180 insertions, 50 deletions
diff --git a/dsp/q6afe.c b/dsp/q6afe.c index c9a5c95e..88124df9 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -27,6 +27,7 @@ #define AFE_CLK_TOKEN 1024 #define SP_V4_NUM_MAX_SPKRS SP_V2_NUM_MAX_SPKRS +#define MAX_LSM_SESSIONS 8 struct afe_avcs_payload_port_mapping { u16 port_id; @@ -246,6 +247,10 @@ struct afe_ctl { /* FTM spk params */ uint32_t initial_cal; uint32_t v_vali_flag; + uint32_t num_spkrs; + uint32_t cps_ch_mask; + struct afe_cps_hw_intf_cfg *cps_config; + int lsm_afe_ports[MAX_LSM_SESSIONS]; }; struct afe_clkinfo_per_port { @@ -300,6 +305,8 @@ bool afe_close_done[2] = {true, true}; #define SIZEOF_CFG_CMD(y) \ (sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y))) +static bool q6afe_is_afe_lsm_port(int port_id); + static void q6afe_unload_avcs_modules(u16 port_id, int index) { int ret = 0; @@ -2172,6 +2179,70 @@ fail_cmd: return ret; } +static int afe_send_cps_config(int src_port) +{ + int i = 0; + struct param_hdr_v3 param_info; + int ret = -EINVAL; + u8 *packed_payload = NULL; + int cpy_size = 0; + int ch_copied = 0; + size_t param_size = 0; + + if ((-1 == this_afe.vi_tx_port) || (!this_afe.cps_ch_mask) || + (!this_afe.cps_config)) { + pr_err("%s: speaker prot not configured for 0x%x\n", __func__, + src_port); + return -EINVAL; + } + + param_size = sizeof(struct afe_cps_hw_intf_cfg) - + sizeof(this_afe.cps_config->spkr_dep_cfg) + + (sizeof(struct lpass_swr_spkr_dep_cfg_t) + * this_afe.num_spkrs); + + this_afe.cps_config->hw_reg_cfg.num_spkr = this_afe.num_spkrs; + packed_payload = kzalloc(param_size, GFP_KERNEL); + if (packed_payload == NULL) + return -ENOMEM; + + cpy_size = sizeof(struct afe_cps_hw_intf_cfg) - + sizeof(this_afe.cps_config->spkr_dep_cfg); + memcpy(packed_payload, this_afe.cps_config, cpy_size); + + while (ch_copied < this_afe.num_spkrs) { + if (!(this_afe.cps_ch_mask & (1 << i))) { + i++; + continue; + } + + memcpy(packed_payload + cpy_size, + &this_afe.cps_config->spkr_dep_cfg[i], + sizeof(struct lpass_swr_spkr_dep_cfg_t)); + cpy_size += sizeof(struct lpass_swr_spkr_dep_cfg_t); + ch_copied++; + i++; + } + + memset(¶m_info, 0, sizeof(param_info)); + param_info.module_id = AFE_MODULE_SPEAKER_PROTECTION_V4_RX; + param_info.instance_id = INSTANCE_ID_0; + param_info.param_id = AFE_PARAM_ID_CPS_LPASS_HW_INTF_CFG; + param_info.param_size = param_size; + + ret = q6afe_pack_and_set_param_in_band(src_port, + q6audio_get_port_index(src_port), + param_info, packed_payload); + if (ret) + pr_err("%s: port = 0x%x param = 0x%x failed %d\n", __func__, + src_port, param_info.param_id, ret); + + pr_debug("%s: config.pdata.param_id 0x%x status %d 0x%x\n", __func__, + param_info.param_id, ret, src_port); + kfree(packed_payload); + return ret; +} + static int afe_spk_prot_prepare(int src_port, int dst_port, int param_id, union afe_spkr_prot_config *prot_config, uint32_t param_size) { @@ -2312,6 +2383,7 @@ static void afe_send_cal_spv4_tx(int port_id) struct afe_sp_v4_channel_v_vali_cfg *ch_v_vali_cfg; struct afe_sp_v4_param_ex_vi_ftm_cfg *ex_vi_ftm_cfg; struct afe_sp_v4_channel_ex_vi_ftm *ch_ex_vi_ftm_cfg; + uint32_t i = 0; pr_debug("%s: Entry.. port_id %d\n", __func__, port_id); @@ -2372,7 +2444,7 @@ static void afe_send_cal_spv4_tx(int port_id) v4_vi_op_mode->th_r0t0_selection_flag[SP_V2_SPKR_2] = USE_SAFE_R0TO; } - afe_spk_config.v4_vi_op_mode.num_speakers = SP_V2_NUM_MAX_SPKRS; + afe_spk_config.v4_vi_op_mode.num_speakers = this_afe.num_spkrs; if (afe_spk_prot_prepare(port_id, 0, AFE_PARAM_ID_SP_V4_VI_OP_MODE_CFG, &afe_spk_config, @@ -2381,7 +2453,7 @@ static void afe_send_cal_spv4_tx(int port_id) __func__); size = sizeof(struct afe_sp_v4_param_th_vi_r0t0_cfg) + - (SP_V2_NUM_MAX_SPKRS * sizeof(struct afe_sp_v4_channel_r0t0)); + (this_afe.num_spkrs * sizeof(struct afe_sp_v4_channel_r0t0)); tmp_ptr = kzalloc(size, GFP_KERNEL); if (!tmp_ptr) { mutex_unlock( @@ -2395,15 +2467,13 @@ static void afe_send_cal_spv4_tx(int port_id) ch_r0t0_cfg = (struct afe_sp_v4_channel_r0t0 *)(th_vi_r0t0_cfg + 1); - th_vi_r0t0_cfg->num_speakers = SP_V2_NUM_MAX_SPKRS; - ch_r0t0_cfg[SP_V2_SPKR_1].r0_cali_q24 = - (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_1]; - ch_r0t0_cfg[SP_V2_SPKR_2].r0_cali_q24 = - (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_2]; - ch_r0t0_cfg[SP_V2_SPKR_1].t0_cali_q6 = - (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_1]; - ch_r0t0_cfg[SP_V2_SPKR_2].t0_cali_q6 = - (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_2]; + th_vi_r0t0_cfg->num_speakers = this_afe.num_spkrs; + for (i = 0; i < this_afe.num_spkrs; i++) { + ch_r0t0_cfg[i].r0_cali_q24 = + (uint32_t) this_afe.prot_cfg.r0[i]; + ch_r0t0_cfg[i].t0_cali_q6 = + (uint32_t) this_afe.prot_cfg.t0[i]; + } if (afe_spk_prot_prepare(port_id, 0, AFE_PARAM_ID_SP_V4_VI_R0T0_CFG, (union afe_spkr_prot_config *)tmp_ptr, size)) @@ -2418,7 +2488,7 @@ static void afe_send_cal_spv4_tx(int port_id) (this_afe.vi_tx_port == port_id) && (this_afe.prot_cfg.sp_version >= AFE_API_VERSION_V9)) { size = sizeof(struct afe_sp_v4_param_th_vi_ftm_cfg) + - (SP_V2_NUM_MAX_SPKRS*sizeof(struct afe_sp_v4_channel_ftm_cfg)); + (this_afe.num_spkrs * sizeof(struct afe_sp_v4_channel_ftm_cfg)); tmp_ptr = kzalloc(size, GFP_KERNEL); if (!tmp_ptr) { mutex_unlock( @@ -2431,16 +2501,13 @@ static void afe_send_cal_spv4_tx(int port_id) ch_ftm_cfg = (struct afe_sp_v4_channel_ftm_cfg *)(th_vi_ftm_cfg+1); - th_vi_ftm_cfg->num_ch = SP_V2_NUM_MAX_SPKRS; - ch_ftm_cfg[SP_V2_SPKR_1].wait_time_ms = - this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_1]; - ch_ftm_cfg[SP_V2_SPKR_2].wait_time_ms = - this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_2]; - ch_ftm_cfg[SP_V2_SPKR_1].ftm_time_ms = - this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_1]; - ch_ftm_cfg[SP_V2_SPKR_2].ftm_time_ms = - this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_2]; - + th_vi_ftm_cfg->num_ch = this_afe.num_spkrs; + for (i = 0; i < this_afe.num_spkrs; i++) { + ch_ftm_cfg[i].wait_time_ms = + this_afe.th_ftm_cfg.wait_time[i]; + ch_ftm_cfg[i].ftm_time_ms = + this_afe.th_ftm_cfg.ftm_time[i]; + } if (afe_spk_prot_prepare(port_id, 0, AFE_PARAM_ID_SP_V4_TH_VI_FTM_CFG, (union afe_spkr_prot_config *)tmp_ptr, size)) @@ -2452,8 +2519,8 @@ static void afe_send_cal_spv4_tx(int port_id) MSM_SPKR_PROT_IN_V_VALI_MODE) && (this_afe.vi_tx_port == port_id)) { size = sizeof(struct afe_sp_v4_param_th_vi_v_vali_cfg) + - (SP_V2_NUM_MAX_SPKRS * - sizeof(struct afe_sp_v4_channel_v_vali_cfg)); + (this_afe.num_spkrs * + sizeof(struct afe_sp_v4_channel_v_vali_cfg)); tmp_ptr = kzalloc(size, GFP_KERNEL); if (!tmp_ptr) { mutex_unlock( @@ -2467,16 +2534,13 @@ static void afe_send_cal_spv4_tx(int port_id) ch_v_vali_cfg = (struct afe_sp_v4_channel_v_vali_cfg *)(th_vi_v_vali_cfg + 1); - th_vi_v_vali_cfg->num_ch = SP_V2_NUM_MAX_SPKRS; - ch_v_vali_cfg[SP_V2_SPKR_1].wait_time_ms = - this_afe.v_vali_cfg.wait_time[SP_V2_SPKR_1]; - ch_v_vali_cfg[SP_V2_SPKR_2].wait_time_ms = - this_afe.v_vali_cfg.wait_time[SP_V2_SPKR_2]; - ch_v_vali_cfg[SP_V2_SPKR_1].vali_time_ms = - this_afe.v_vali_cfg.vali_time[SP_V2_SPKR_1]; - ch_v_vali_cfg[SP_V2_SPKR_2].vali_time_ms = - this_afe.v_vali_cfg.vali_time[SP_V2_SPKR_2]; - + th_vi_v_vali_cfg->num_ch = this_afe.num_spkrs; + for (i = 0; i < this_afe.num_spkrs; i++) { + ch_v_vali_cfg[i].wait_time_ms = + this_afe.v_vali_cfg.wait_time[i]; + ch_v_vali_cfg[i].vali_time_ms = + this_afe.v_vali_cfg.vali_time[i]; + } if (afe_spk_prot_prepare(port_id, 0, AFE_PARAM_ID_SP_V4_TH_VI_V_VALI_CFG, (union afe_spkr_prot_config *)tmp_ptr, size)) @@ -2492,7 +2556,7 @@ static void afe_send_cal_spv4_tx(int port_id) (this_afe.vi_tx_port == port_id) && (this_afe.prot_cfg.sp_version >= AFE_API_VERSION_V9)) { size = sizeof(struct afe_sp_v4_param_ex_vi_ftm_cfg) + - (SP_V2_NUM_MAX_SPKRS * + (this_afe.num_spkrs * sizeof(struct afe_sp_v4_channel_ex_vi_ftm)); tmp_ptr = kzalloc(size, GFP_KERNEL); if (!tmp_ptr) { @@ -2514,17 +2578,14 @@ static void afe_send_cal_spv4_tx(int port_id) sizeof(struct afe_sp_v4_param_ex_vi_mode_cfg))) pr_info("%s: ex vi mode cfg failed\n", __func__); - ex_vi_ftm_cfg->num_ch = SP_V2_NUM_MAX_SPKRS; - - ch_ex_vi_ftm_cfg[SP_V2_SPKR_1].wait_time_ms = - this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_1]; - ch_ex_vi_ftm_cfg[SP_V2_SPKR_2].wait_time_ms = - this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_2]; - ch_ex_vi_ftm_cfg[SP_V2_SPKR_1].ftm_time_ms = - this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_1]; - ch_ex_vi_ftm_cfg[SP_V2_SPKR_2].ftm_time_ms = - this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_2]; + ex_vi_ftm_cfg->num_ch = this_afe.num_spkrs; + for (i = 0; i < this_afe.num_spkrs; i++) { + ch_ex_vi_ftm_cfg[i].wait_time_ms = + this_afe.ex_ftm_cfg.wait_time[i]; + ch_ex_vi_ftm_cfg[i].ftm_time_ms = + this_afe.ex_ftm_cfg.ftm_time[i]; + } if (afe_spk_prot_prepare(port_id, 0, AFE_PARAM_ID_SP_V4_EX_VI_FTM_CFG, (union afe_spkr_prot_config *)tmp_ptr, size)) @@ -2954,7 +3015,7 @@ static int afe_send_port_topology_id(u16 port_id) } ret = afe_get_cal_topology_id(port_id, &topology_id, AFE_TOPOLOGY_CAL); - if (ret < 0) { + if (ret < 0 && q6afe_is_afe_lsm_port(port_id)) { pr_debug("%s: Check for LSM topology\n", __func__); ret = afe_get_cal_topology_id(port_id, &topology_id, AFE_LSM_TOPOLOGY_CAL); @@ -3291,7 +3352,7 @@ static int send_afe_cal_type(int cal_index, int port_id) this_afe.cal_data[cal_index]); if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) { - pr_err("%s cal_block not found!!\n", __func__); + pr_err_ratelimited("%s cal_block not found!!\n", __func__); ret = -EINVAL; goto unlock; } @@ -3327,7 +3388,7 @@ void afe_send_cal(u16 port_id) if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) { afe_send_cal_spkr_prot_tx(port_id); ret = send_afe_cal_type(AFE_COMMON_TX_CAL, port_id); - if (ret < 0) + if (ret < 0 && q6afe_is_afe_lsm_port(port_id)) send_afe_cal_type(AFE_LSM_TX_CAL, port_id); } else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) { send_afe_cal_type(AFE_COMMON_RX_CAL, port_id); @@ -5277,6 +5338,11 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, afe_send_hw_delay(port_id, rate); } + if ((this_afe.cps_config) && + (this_afe.vi_rx_port == port_id)) { + afe_send_cps_config(port_id); + } + /* Start SW MAD module */ mad_type = afe_port_get_mad_type(port_id); pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id, @@ -8432,8 +8498,11 @@ int afe_close(int port_id) * 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__); + if (q6core_get_avcs_api_version_per_service( + APRV2_IDS_SERVICE_ID_ADSP_AFE_V) < AFE_API_VERSION_V9) { + if (afe_spk_ramp_dn_cfg(port_id) < 0) + pr_err("%s: ramp down config failed\n", __func__); + } stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); @@ -9574,6 +9643,7 @@ int afe_spk_prot_feed_back_cfg(int src_port, int dst_port, this_afe.v4_ch_map_cfg.chan_info[index++] = 4; } this_afe.v4_ch_map_cfg.num_channels = index; + this_afe.num_spkrs = index / 2; pr_debug("%s no of channels: %d\n", __func__, index); this_afe.vi_tx_port = src_port; this_afe.vi_rx_port = dst_port; @@ -10609,6 +10679,8 @@ int __init afe_init(void) init_waitqueue_head(&this_afe.wait_wakeup); init_waitqueue_head(&this_afe.lpass_core_hw_wait); init_waitqueue_head(&this_afe.clk_wait); + for (i = 0; i < MAX_LSM_SESSIONS; i++) + this_afe.lsm_afe_ports[i] = 0xffff; ret = afe_init_cal_data(); if (ret) pr_err("%s: could not init cal data! %d\n", __func__, ret); @@ -10816,3 +10888,61 @@ done: return ret; } EXPORT_SYMBOL(afe_unvote_lpass_core_hw); + +/** + * afe_set_cps_config - + * to set cps speaker protection configuration + * + * @src_port: source port to send configuration to + * @cps_config: cps speaker protection v4 configuration + * @ch_mask: channel mask + * + */ +void afe_set_cps_config(int src_port, + struct afe_cps_hw_intf_cfg *cps_config, + u32 ch_mask) +{ + this_afe.cps_config = NULL; + this_afe.cps_ch_mask = 0; + + if (!cps_config) { + pr_err("%s: cps config is NULL\n", __func__); + return; + } + + if (q6audio_validate_port(src_port) < 0) { + pr_err("%s: Invalid src port 0x%x\n", __func__, src_port); + return; + } + + this_afe.cps_ch_mask = ch_mask; + this_afe.cps_config = cps_config; +} +EXPORT_SYMBOL(afe_set_cps_config); + +static bool q6afe_is_afe_lsm_port(int port_id) +{ + int i = 0; + + for (i = 0; i < MAX_LSM_SESSIONS; i++) { + if (port_id == this_afe.lsm_afe_ports[i]) + return true; + } + return false; +} + +/** + * afe_set_lsm_afe_port_id - + * Update LSM AFE port + * idx: LSM port index + * lsm_port: LSM port id +*/ +void afe_set_lsm_afe_port_id(int idx, int lsm_port) +{ + if (idx < 0 || idx >= MAX_LSM_SESSIONS) { + pr_err("%s: %d Invalid lsm port index\n", __func__, idx); + return; + } + this_afe.lsm_afe_ports[idx] = lsm_port; +} +EXPORT_SYMBOL(afe_set_lsm_afe_port_id); |