summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/apr_audio-v2.h83
-rw-r--r--include/sound/q6adm-v2.h8
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c98
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h18
-rw-r--r--sound/soc/msm/qdsp6v2/q6adm.c108
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;
}
}