diff options
-rw-r--r-- | include/sound/apr_audio-v2.h | 83 | ||||
-rw-r--r-- | include/sound/q6adm-v2.h | 8 | ||||
-rw-r--r-- | sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c | 98 | ||||
-rw-r--r-- | sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h | 18 | ||||
-rw-r--r-- | sound/soc/msm/qdsp6v2/q6adm.c | 108 |
5 files changed, 262 insertions, 53 deletions
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index a1d8b04d08ac..2680a13721c2 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -446,6 +446,88 @@ struct adm_param_data_v5 { */ } __packed; + +struct param_data_v6 { + /* Unique ID of the module. */ + u32 module_id; + /* Unique ID of the instance. */ + u16 instance_id; + /* Reserved for future enhancements. + * This field must be set to zero. + */ + u16 reserved; + /* Unique ID of the parameter. */ + u32 param_id; + /* Data size of the param_id/module_id combination. + * This value is a + * multiple of 4 bytes. + */ + u32 param_size; +} __packed; + +/* ADM_CMD_SET_MTMX_STRTR_DEV_PARAMS_V1 command is used to set + * calibration data to the ADSP Matrix Mixer the payload is + * of struct adm_cmd_set_mtmx_params_v1. + * + * ADM_CMD_GET_MTMX_STRTR_DEV_PARAMS_V1 can be used to get + * the calibration data from the ADSP Matrix Mixer and + * ADM_CMDRSP_GET_MTMX_STRTR_DEV_PARAMS_V1 is the response + * ioctl to ADM_CMD_GET_MTMX_STRTR_DEV_PARAMS_V1. + */ +#define ADM_CMD_SET_MTMX_STRTR_DEV_PARAMS_V1 0x00010367 +#define ADM_CMD_GET_MTMX_STRTR_DEV_PARAMS_V1 0x00010368 +#define ADM_CMDRSP_GET_MTMX_STRTR_DEV_PARAMS_V1 0x00010369 + +/* Payload of the #define ADM_CMD_SET_MTMX_STRTR_DEV_PARAMS_V1 command. + * If the data_payload_addr_lsw and data_payload_addr_msw element + * are NULL, a series of struct param_data_v6 structures immediately + * follows, whose total size is payload_size bytes. + */ +struct adm_cmd_set_mtmx_params_v1 { + struct apr_hdr hdr; + /* LSW of parameter data payload address.*/ + u32 payload_addr_lsw; + + /* MSW of parameter data payload address.*/ + u32 payload_addr_msw; + + /* Memory map handle returned by ADM_CMD_SHARED_MEM_MAP_REGIONS + * command. + * If mem_map_handle is zero it implies the message is in + * the payload + */ + u32 mem_map_handle; + + /* Size in bytes of the variable payload accompanying this + * message or in shared memory. This is used for parsing + * the parameter payload. + */ + u32 payload_size; + + /* COPP ID/Device ID */ + u16 copp_id; + + /* For alignment, must be set to 0 */ + u16 reserved; +} __packed; + +struct enable_param_v6 { + /* + * Specifies whether the Audio processing module is enabled. + * This parameter is generic/common parameter to configure or + * determine the state of any audio processing module. + */ + struct param_data_v6 param; + + /* @values 0 : Disable 1: Enable */ + uint32_t enable; +} __packed; + +/* Defined in ADSP as VOICE_MODULE_TX_STREAM_LIMITER but + * used for RX stream limiter on matrix input to ADM. + */ +#define ADM_MTMX_MODULE_STREAM_LIMITER 0x00010F15 + #define ASM_STREAM_CMD_REGISTER_PP_EVENTS 0x00013213 #define ASM_STREAM_PP_EVENT 0x00013214 #define ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE 0x13333 @@ -9224,7 +9306,6 @@ struct srs_trumedia_params { } __packed; /* SRS TruMedia end */ -#define AUDPROC_PARAM_ID_ENABLE 0x00010904 #define ASM_STREAM_POSTPROC_TOPO_ID_SA_PLUS 0x1000FFFF /* DTS Eagle */ #define AUDPROC_MODULE_ID_DTS_HPX_PREMIX 0x0001077C diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h index 8c53bb9762ce..65c42ee18914 100644 --- a/include/sound/q6adm-v2.h +++ b/include/sound/q6adm-v2.h @@ -51,6 +51,13 @@ enum { ADM_CLIENT_ID_MAX, }; +/* ENUM for adm_status & route_status */ +enum adm_status_flags { + ADM_STATUS_CALIBRATION_REQUIRED = 0, + ADM_STATUS_LIMITER, + ADM_STATUS_MAX, +}; + #define MAX_COPPS_PER_PORT 0x8 #define ADM_MAX_CHANNELS 8 @@ -61,6 +68,7 @@ struct route_payload { int app_type[MAX_COPPS_PER_PORT]; int acdb_dev_id[MAX_COPPS_PER_PORT]; int sample_rate[MAX_COPPS_PER_PORT]; + unsigned long route_status[MAX_COPPS_PER_PORT]; unsigned short num_copps; unsigned int session_id; }; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index b64bd7ed8fc7..9d1e20f71829 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -120,17 +120,13 @@ static const char * const lsm_port_text[] = { }; struct msm_pcm_route_bdai_pp_params { - u16 port_id; /* AFE port ID */ unsigned long pp_params_config; bool mute_on; int latency; }; static struct msm_pcm_route_bdai_pp_params - msm_bedais_pp_params[MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX] = { - {HDMI_RX, 0, 0, 0}, - {DISPLAY_PORT_RX, 0, 0, 0}, -}; + msm_bedais_pp_params[MSM_BACKEND_DAI_MAX]; /* * The be_dai_name_table is passed to HAL so that it can specify the @@ -144,6 +140,7 @@ struct msm_pcm_route_bdai_name { }; static struct msm_pcm_route_bdai_name be_dai_name_table[MSM_BACKEND_DAI_MAX]; +static bool msm_pcm_routing_test_pp_param(int be_idx, long param_bit); static int msm_routing_send_device_pp_params(int port_id, int copp_idx, int fe_id); @@ -955,7 +952,7 @@ static void msm_pcm_routing_build_matrix(int fedai_id, int sess_type, uint32_t passthr_mode) { int i, port_type, j, num_copps = 0; - struct route_payload payload; + struct route_payload payload = { {0} }; port_type = ((path_type == ADM_PATH_PLAYBACK || path_type == ADM_PATH_COMPRESSED_RX) ? @@ -985,6 +982,11 @@ static void msm_pcm_routing_build_matrix(int fedai_id, int sess_type, fe_dai_app_type_cfg [fedai_id][sess_type][i] .sample_rate; + if (msm_pcm_routing_test_pp_param(i, + ADM_PP_PARAM_LIMITER_BIT)) + set_bit(ADM_STATUS_LIMITER, + &payload.route_status + [num_copps]); num_copps++; } } @@ -1206,6 +1208,11 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, fe_dai_app_type_cfg [fe_id][session_type][i] .sample_rate; + if (msm_pcm_routing_test_pp_param(i, + ADM_PP_PARAM_LIMITER_BIT)) + set_bit(ADM_STATUS_LIMITER, + &payload.route_status + [num_copps]); num_copps++; } } @@ -1436,6 +1443,11 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, fe_dai_app_type_cfg [fedai_id][session_type] [i].sample_rate; + if (msm_pcm_routing_test_pp_param(i, + ADM_PP_PARAM_LIMITER_BIT)) + set_bit(ADM_STATUS_LIMITER, + &payload.route_status + [num_copps]); num_copps++; } } @@ -15335,7 +15347,7 @@ done: static int msm_routing_send_device_pp_params(int port_id, int copp_idx, int fe_id) { - int index, topo_id, be_idx; + int topo_id, be_idx; unsigned long pp_config = 0; bool mute_on; int latency; @@ -15359,16 +15371,6 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx, return -EINVAL; } - for (index = 0; index < MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX; index++) { - if (msm_bedais_pp_params[index].port_id == port_id) - break; - } - if (index >= MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX) { - pr_err("%s: Invalid backend pp params index %d\n", - __func__, index); - return -EINVAL; - } - topo_id = adm_get_topology_for_port_copp_idx(port_id, copp_idx); if (topo_id != COMPRESSED_PASSTHROUGH_DEFAULT_TOPOLOGY) { pr_err("%s: Invalid passthrough topology 0x%x\n", @@ -15380,11 +15382,11 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx, (msm_bedais[be_idx].passthr_mode[fe_id] == LISTEN)) compr_passthr_mode = false; - pp_config = msm_bedais_pp_params[index].pp_params_config; + pp_config = msm_bedais_pp_params[be_idx].pp_params_config; if (test_bit(ADM_PP_PARAM_MUTE_BIT, &pp_config)) { pr_debug("%s: ADM_PP_PARAM_MUTE\n", __func__); clear_bit(ADM_PP_PARAM_MUTE_BIT, &pp_config); - mute_on = msm_bedais_pp_params[index].mute_on; + mute_on = msm_bedais_pp_params[be_idx].mute_on; if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_mute(port_id, copp_idx, @@ -15394,7 +15396,7 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx, pr_debug("%s: ADM_PP_PARAM_LATENCY\n", __func__); clear_bit(ADM_PP_PARAM_LATENCY_BIT, &pp_config); - latency = msm_bedais_pp_params[index].latency; + latency = msm_bedais_pp_params[be_idx].latency; if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_latency(port_id, copp_idx, @@ -15403,18 +15405,47 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx, return 0; } +static bool msm_pcm_routing_test_pp_param(int be_idx, long param_bit) +{ + return test_bit(param_bit, + &msm_bedais_pp_params[be_idx].pp_params_config); +} + +static void msm_routing_set_pp_param(long param_bit, int value) +{ + int be_idx; + + if (value) { + for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) + set_bit(param_bit, + &msm_bedais_pp_params[be_idx]. + pp_params_config); + } else { + for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) + clear_bit(param_bit, + &msm_bedais_pp_params[be_idx]. + pp_params_config); + } +} + static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int pp_id = ucontrol->value.integer.value[0]; + int value = ucontrol->value.integer.value[1]; int port_id = 0; - int index, be_idx, i, topo_id, idx; + int be_idx, i, topo_id, idx; bool mute; int latency; bool compr_passthr_mode = true; pr_debug("%s: pp_id: 0x%x\n", __func__, pp_id); + if (pp_id == ADM_PP_PARAM_LIMITER_ID) { + msm_routing_set_pp_param(ADM_PP_PARAM_LIMITER_BIT, value); + goto done; + } + for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) { port_id = msm_bedais[be_idx].port_id; if (port_id == HDMI_RX || port_id == DISPLAY_PORT_RX) @@ -15426,16 +15457,6 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, return -EINVAL; } - for (index = 0; index < MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX; index++) { - if (msm_bedais_pp_params[index].port_id == port_id) - break; - } - if (index >= MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX) { - pr_err("%s: Invalid pp params backend index %d\n", - __func__, index); - return -EINVAL; - } - for_each_set_bit(i, &msm_bedais[be_idx].fe_sessions[0], MSM_FRONTEND_DAI_MM_SIZE) { if ((msm_bedais[be_idx].passthr_mode[i] == LEGACY_PCM) || @@ -15458,22 +15479,20 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, switch (pp_id) { case ADM_PP_PARAM_MUTE_ID: pr_debug("%s: ADM_PP_PARAM_MUTE\n", __func__); - mute = ucontrol->value.integer.value[1] ? true : false; - msm_bedais_pp_params[index].mute_on = mute; + mute = value ? true : false; + msm_bedais_pp_params[be_idx].mute_on = mute; set_bit(ADM_PP_PARAM_MUTE_BIT, - &msm_bedais_pp_params[index].pp_params_config); + &msm_bedais_pp_params[be_idx].pp_params_config); if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_mute(port_id, idx, mute); break; case ADM_PP_PARAM_LATENCY_ID: pr_debug("%s: ADM_PP_PARAM_LATENCY\n", __func__); - msm_bedais_pp_params[index].latency = - ucontrol->value.integer.value[1]; + msm_bedais_pp_params[be_idx].latency = value; set_bit(ADM_PP_PARAM_LATENCY_BIT, - &msm_bedais_pp_params[index].pp_params_config); - latency = msm_bedais_pp_params[index].latency = - ucontrol->value.integer.value[1]; + &msm_bedais_pp_params[be_idx].pp_params_config); + latency = msm_bedais_pp_params[be_idx].latency = value; if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_latency(port_id, idx, latency); @@ -15485,6 +15504,7 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, } } } +done: return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h index fa948abd1b4c..a8daff09db58 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h @@ -397,12 +397,20 @@ enum { #define RELEASE_LOCK 0 #define ACQUIRE_LOCK 1 -#define MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX 2 #define HDMI_RX_ID 0x8001 -#define ADM_PP_PARAM_MUTE_ID 0 -#define ADM_PP_PARAM_MUTE_BIT 1 -#define ADM_PP_PARAM_LATENCY_ID 1 -#define ADM_PP_PARAM_LATENCY_BIT 2 + +enum { + ADM_PP_PARAM_MUTE_ID, + ADM_PP_PARAM_LATENCY_ID, + ADM_PP_PARAM_LIMITER_ID +}; + +enum { + ADM_PP_PARAM_MUTE_BIT = 0x1, + ADM_PP_PARAM_LATENCY_BIT = 0x2, + ADM_PP_PARAM_LIMITER_BIT = 0x4 +}; + #define BE_DAI_PORT_SESSIONS_IDX_MAX 4 #define BE_DAI_FE_SESSIONS_IDX_MAX 2 diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index 4aad16db3e0f..e1bfc950d0e3 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -48,12 +48,6 @@ #define DS2_ADM_COPP_TOPOLOGY_ID 0xFFFFFFFF #endif -/* ENUM for adm_status */ -enum adm_cal_status { - ADM_STATUS_CALIBRATION_REQUIRED = 0, - ADM_STATUS_MAX, -}; - struct adm_copp { atomic_t id[AFE_MAX_PORTS][MAX_COPPS_PER_PORT]; @@ -1413,6 +1407,7 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) case ADM_CMD_DEVICE_OPEN_V5: case ADM_CMD_DEVICE_CLOSE_V5: case ADM_CMD_DEVICE_OPEN_V6: + case ADM_CMD_SET_MTMX_STRTR_DEV_PARAMS_V1: pr_debug("%s: Basic callback received, wake up.\n", __func__); atomic_set(&this_adm.copp.stat[port_idx] @@ -2695,6 +2690,97 @@ fail_cmd: return; } + +static int adm_set_mtmx_params_v1(int port_idx, int copp_idx, + int params_length, void *params) +{ + struct adm_cmd_set_mtmx_params_v1 *adm_params = NULL; + int rc = 0; + int sz; + + sz = sizeof(*adm_params) + params_length; + adm_params = kzalloc(sz, GFP_KERNEL); + if (!adm_params) + return -ENOMEM; + + memcpy(((u8 *)adm_params + sizeof(*adm_params)), + params, params_length); + adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + adm_params->hdr.pkt_size = sz; + adm_params->hdr.src_svc = APR_SVC_ADM; + adm_params->hdr.src_domain = APR_DOMAIN_APPS; + adm_params->hdr.src_port = 0; + adm_params->hdr.dest_svc = APR_SVC_ADM; + adm_params->hdr.dest_domain = APR_DOMAIN_ADSP; + adm_params->hdr.dest_port = + atomic_read(&this_adm.copp.id[port_idx][copp_idx]); + adm_params->hdr.token = port_idx << 16 | copp_idx; + adm_params->hdr.opcode = ADM_CMD_SET_MTMX_STRTR_DEV_PARAMS_V1; + adm_params->payload_addr_lsw = 0; + adm_params->payload_addr_msw = 0; + adm_params->mem_map_handle = 0; + adm_params->payload_size = params_length; + adm_params->copp_id = atomic_read(&this_adm.copp. + id[port_idx][copp_idx]); + + atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1); + rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params); + if (rc < 0) { + pr_err("%s: Set params failed port_idx = 0x%x rc %d\n", + __func__, port_idx, rc); + rc = -EINVAL; + goto send_param_return; + } + /* Wait for the callback */ + rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx], + atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0, + msecs_to_jiffies(TIMEOUT_MS)); + if (!rc) { + pr_err("%s: Set params timed out port_idx = 0x%x\n", + __func__, port_idx); + rc = -EINVAL; + goto send_param_return; + } else if (atomic_read(&this_adm.copp.stat + [port_idx][copp_idx]) > 0) { + pr_err("%s: DSP returned error[%s]\n", + __func__, adsp_err_get_err_str( + atomic_read(&this_adm.copp.stat + [port_idx][copp_idx]))); + rc = adsp_err_get_lnx_err_code( + atomic_read(&this_adm.copp.stat + [port_idx][copp_idx])); + goto send_param_return; + } + rc = 0; +send_param_return: + kfree(adm_params); + return rc; +} + +static void adm_enable_mtmx_limiter(int port_idx, int copp_idx) +{ + int rc; + struct enable_param_v6 adm_param = { {0} }; + + adm_param.param.module_id = ADM_MTMX_MODULE_STREAM_LIMITER; + adm_param.param.param_id = AUDPROC_PARAM_ID_ENABLE; + adm_param.param.param_size = sizeof(adm_param.enable); + adm_param.enable = 1; + + rc = adm_set_mtmx_params_v1(port_idx, copp_idx, + sizeof(adm_param), &adm_param); + if (rc < 0) { + pr_err("%s: adm_set_mtmx_params_v1 failed port_idx = 0x%x rc %d\n", + __func__, port_idx, rc); + goto done; + } + set_bit(ADM_STATUS_LIMITER, + (void *)&this_adm.copp.adm_status[port_idx][copp_idx]); +done: + return; +} + static void route_set_opcode_matrix_id( struct adm_cmd_matrix_map_routings_v5 **route_addr, int path, uint32_t passthr_mode) @@ -2791,6 +2877,11 @@ int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode, copp_idx = payload_map.copp_idx[i]; copps_list[i] = atomic_read(&this_adm.copp.id[port_idx] [copp_idx]); + if (test_bit(ADM_STATUS_LIMITER, + (void *)&payload_map.route_status) && + ((path == ADM_PATH_PLAYBACK) || + (path == ADM_PATH_COMPRESSED_RX))) + adm_enable_mtmx_limiter(port_idx, copp_idx); } atomic_set(&this_adm.matrix_map_stat, -1); @@ -2991,6 +3082,8 @@ int adm_close(int port_id, int perf_mode, int copp_idx) clear_bit(ADM_STATUS_CALIBRATION_REQUIRED, (void *)&this_adm.copp.adm_status[port_idx][copp_idx]); + clear_bit(ADM_STATUS_LIMITER, + (void *)&this_adm.copp.adm_status[port_idx][copp_idx]); ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close); if (ret < 0) { @@ -4807,8 +4900,7 @@ static int __init adm_init(void) &this_adm.copp.adm_delay_wait[i][j]); atomic_set(&this_adm.copp.topology[i][j], 0); this_adm.copp.adm_delay[i][j] = 0; - this_adm.copp.adm_status[i][j] = - ADM_STATUS_CALIBRATION_REQUIRED; + this_adm.copp.adm_status[i][j] = 0; } } |