diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c index 92d20838433a..afec883e3265 100755 --- a/asoc/msm-dai-q6-v2.c +++ b/asoc/msm-dai-q6-v2.c @@ -394,6 +394,12 @@ static const struct soc_enum tdm_config_enum[] = { SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tdm_header_type), tdm_header_type), }; +static u16 afe_port_logging_port_id; + +static bool afe_port_logging_item[IDX_TDM_MAX]; + +static int afe_port_loggging_control_added; + static DEFINE_MUTEX(tdm_mutex); static atomic_t tdm_group_ref[IDX_GROUP_TDM_MAX]; @@ -9272,6 +9278,87 @@ static int msm_dai_q6_tdm_set_clk( return rc; } +static int msm_pcm_afe_port_logging_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info* ucontrol) +{ + ucontrol->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + /* two int values: port_id and enable/disable */ + ucontrol->count = 2; + /* Valid range is all positive values to support above controls */ + ucontrol->value.integer.min = 0; + ucontrol->value.integer.max = INT_MAX; + return 0; +} + +static int msm_pcm_afe_port_logging_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int port_idx = afe_port_logging_port_id - AFE_PORT_ID_TDM_PORT_RANGE_START; + + ucontrol->value.integer.value[0] = afe_port_logging_port_id; + ucontrol->value.integer.value[1] = afe_port_logging_item[port_idx]; + + return 0; +} + +static int msm_pcm_afe_port_logging_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u16 port_id; + struct afe_param_id_port_data_log_disable_t log_disable; + struct param_hdr_v3 param_hdr; + int ret = -EINVAL, port_idx; + + pr_debug("%s: enter\n", __func__); + memset(¶m_hdr, 0, sizeof(param_hdr)); + + port_id = ucontrol->value.integer.value[0]; + log_disable.disable_logging_flag = ucontrol->value.integer.value[1]; + + ret = afe_port_send_logging_cfg(port_id, &log_disable); + if (ret) + pr_err("%s: AFE port logging setting for port 0x%x failed %d\n", + __func__, port_id, ret); + + afe_port_logging_port_id = port_id; + port_idx = port_id - AFE_PORT_ID_TDM_PORT_RANGE_START; + afe_port_logging_item[port_idx] = ucontrol->value.integer.value[1]; + + return ret; +} + +static int msm_pcm_add_afe_port_logging_control(struct snd_soc_dai *dai) +{ + const char* afe_port_logging_ctl_name = "AFE_port_logging_disable"; + int rc = 0; + struct snd_kcontrol_new *knew = NULL; + struct snd_kcontrol* kctl = NULL; + + /* Add AFE port logging controls */ + knew = kzalloc(sizeof(struct snd_kcontrol_new), GFP_KERNEL); + if (!knew) { + return -ENOMEM; + } + knew->iface = SNDRV_CTL_ELEM_IFACE_MIXER; + knew->info = msm_pcm_afe_port_logging_info; + knew->get = msm_pcm_afe_port_logging_ctl_get; + knew->put = msm_pcm_afe_port_logging_ctl_put; + knew->name = afe_port_logging_ctl_name; + knew->private_value = dai->id; + kctl = snd_ctl_new1(knew, knew); + if (!kctl) { + kfree(knew); + return -ENOMEM; + } + + rc = snd_ctl_add(dai->component->card->snd_card, kctl); + if (rc < 0) + pr_err("%s: err add AFE port logging disable control, DAI = %s\n", + __func__, dai->name); + + return rc; +} + static int msm_dai_q6_dai_tdm_probe(struct snd_soc_dai *dai) { int rc = 0; @@ -9348,6 +9435,18 @@ static int msm_dai_q6_dai_tdm_probe(struct snd_soc_dai *dai) } } + /* add AFE port logging controls */ + if (!afe_port_loggging_control_added) { + rc = msm_pcm_add_afe_port_logging_control(dai); + if (rc < 0) { + dev_err(dai->dev, "%s: add AFE port logging control failed DAI: %s\n", + __func__, dai->name); + goto rtn; + } + + afe_port_loggging_control_added = 1; + } + if (tdm_dai_data->is_island_dai) rc = msm_dai_q6_add_island_mx_ctls( dai->component->card->snd_card, diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 6a145210f250..7ba22b1709d4 100755 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -4800,6 +4800,40 @@ void afe_set_routing_callback(routing_cb cb) } EXPORT_SYMBOL(afe_set_routing_callback); +/** + * afe_port_send_logging_cfg - + * set AFE port logging status + * + * @port_id: AFE port id number + * @log_disable: logging payload + * + * Returns 0 on success or error value on set param failure + */ +int afe_port_send_logging_cfg(u16 port_id, + struct afe_param_id_port_data_log_disable_t *log_disable) +{ + struct param_hdr_v3 param_hdr; + int ret = -EINVAL; + + pr_debug("%s: enter, port: 0x%x logging flag: %x\n", __func__, port_id, + log_disable->disable_logging_flag); + memset(¶m_hdr, 0, sizeof(param_hdr)); + + param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE; + param_hdr.instance_id = INSTANCE_ID_0; + param_hdr.param_id = AFE_PARAM_ID_PORT_DATA_LOGGING_DISABLE; + param_hdr.param_size = sizeof(&log_disable); + + ret = q6afe_pack_and_set_param_in_band(port_id, + q6audio_get_port_index(port_id), param_hdr, (u8*)log_disable); + if (ret) + pr_err("%s: AFE port logging setting for port 0x%x failed %d\n", + __func__, port_id, ret); + + return ret; +} +EXPORT_SYMBOL(afe_port_send_logging_cfg); + int afe_port_send_usb_dev_param(u16 port_id, union afe_port_config *afe_config) { struct afe_param_id_usb_audio_dev_params usb_dev; diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index 182a0c87b696..5abaf15a81e2 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -13414,4 +13414,44 @@ struct afe_param_id_tdm_lane_cfg { */ }; +/** ID of the parameter used to set the AFE port data logging to enable or disable state. + * For non-group device use cases, #AFE_MODULE_AUDIO_DEV_INTERFACE uses this + * parameter to configure the flag used for data logging in afe_data_logging_t + * of the respective port to enabled or disabled state. + * The HLOS client can use this parameter to configure the data logging + * disable flag for it's respective port. + * The reason for this parameter addition is if a number of ports are + * configured and running, Upon enabling logging through 0x1586 tap point, + * we will get input/output logs for all the enabled ports. + * In order to disabled logging for a specific port for which data logging + * is not needed, the HLOS client can make use of AFE_PORT_DATA_LOGGING_DISABLE flag. + * This flag will set to AFE_PORT_DATA_LOGGING_ENABLE during port initialization and also + * during port stop. If port is restarted, the set param should be called again + * by the HLOS client if needed to disable data logging. + * @par + * If HLOS client doesn't set this paramter, by default the disable flag = AFE_PORT_DATA_LOGGING_ENABLE. + * If HLOS client sets the flag = AFE_PORT_DATA_LOGGING_DISABLE, the respective port will be disabled for data logging. + */ +#define AFE_PARAM_ID_PORT_DATA_LOGGING_DISABLE 0x000102E9 + + /** Enable flag for port data logging. */ +#define AFE_PORT_DATA_LOGGING_ENABLE 0 + +/** Disable flag for port data logging. */ +#define AFE_PORT_DATA_LOGGING_DISABLE 1 + +/* + * Payload of the AFE_PARAM_ID_PORT_DATA_LOGGING_DISABLE parameter used by + * AFE_MODULE_AUDIO_DEV_INTERFACE + */ +struct afe_param_id_port_data_log_disable_t +{ + uint32_t disable_logging_flag; + /** Flag for enabling or disabling data logging. + * @values + * - AFE_PORT_DATA_LOGGING_ENABLE - enable data logging. + * - AFE_PORT_DATA_LOGGING_DISABLE - disable data logging. + */ +} __packed; + #endif /*_APR_AUDIO_V2_H_ */ diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h index 5ac9637eae33..ba4e19be3535 100644 --- a/include/dsp/q6afe-v2.h +++ b/include/dsp/q6afe-v2.h @@ -520,6 +520,8 @@ int afe_send_custom_tdm_header_cfg( int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port, u32 rate, u16 num_groups); void afe_set_routing_callback(routing_cb cb); +int afe_port_send_logging_cfg(u16 port_id, + struct afe_param_id_port_data_log_disable_t *log_disable); int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats, u16 port); int afe_get_sp_rx_tmax_xmax_logging_data(