From 44c6cc4fdcd255a53db882e747f95b3c465855e2 Mon Sep 17 00:00:00 2001 From: Kunlei Zhang Date: Fri, 17 Apr 2020 15:42:32 +0800 Subject: [PATCH 1/2] dsp: Add support to set island cfg and power mode Add new APIs to set/reset power mode along with island config before afe_port_start. Change-Id: Ibd9487b04b691be5ab829cfa32c89953838f3192 Signed-off-by: Kunlei Zhang --- asoc/msm-dai-q6-v2.c | 137 +++++++++++++++++++++++++++++++++++++ dsp/q6afe.c | 131 +++++++++++++++++++++++++++++++++++ include/dsp/apr_audio-v2.h | 16 +++++ include/dsp/q6afe-v2.h | 3 + 4 files changed, 287 insertions(+) diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c index dbedb55d2e..fc8c672e4b 100644 --- a/asoc/msm-dai-q6-v2.c +++ b/asoc/msm-dai-q6-v2.c @@ -1279,6 +1279,83 @@ static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai) return 0; } +static int msm_dai_q6_power_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int value = ucontrol->value.integer.value[0]; + u16 port_id = (u16)kcontrol->private_value; + + pr_debug("%s: power mode = %d\n", __func__, value); + trace_printk("%s: power mode = %d\n", __func__, value); + + afe_set_power_mode_cfg(port_id, value); + return 0; +} + +static int msm_dai_q6_power_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int value; + u16 port_id = (u16)kcontrol->private_value; + + afe_get_power_mode_cfg(port_id, &value); + ucontrol->value.integer.value[0] = value; + return 0; +} + +static void power_mode_mx_ctl_private_free(struct snd_kcontrol *kcontrol) +{ + struct snd_kcontrol_new *knew = snd_kcontrol_chip(kcontrol); + kfree(knew); +} + +static int msm_dai_q6_add_power_mode_mx_ctls(struct snd_card *card, + const char *dai_name, + int dai_id, void *dai_data) +{ + const char *mx_ctl_name = "Power Mode"; + char *mixer_str = NULL; + int dai_str_len = 0, ctl_len = 0; + int rc = 0; + struct snd_kcontrol_new *knew = NULL; + struct snd_kcontrol *kctl = NULL; + + dai_str_len = strlen(dai_name) + 1; + + ctl_len = dai_str_len + strlen(mx_ctl_name) + 1; + mixer_str = kzalloc(ctl_len, GFP_KERNEL); + if (!mixer_str) + return -ENOMEM; + + snprintf(mixer_str, ctl_len, "%s %s", dai_name, mx_ctl_name); + + knew = kzalloc(sizeof(struct snd_kcontrol_new), GFP_KERNEL); + if (!knew) { + kfree(mixer_str); + return -ENOMEM; + } + knew->iface = SNDRV_CTL_ELEM_IFACE_MIXER; + knew->info = snd_ctl_boolean_mono_info; + knew->get = msm_dai_q6_power_mode_get; + knew->put = msm_dai_q6_power_mode_put; + knew->name = mixer_str; + knew->private_value = dai_id; + kctl = snd_ctl_new1(knew, knew); + if (!kctl) { + kfree(knew); + kfree(mixer_str); + return -ENOMEM; + } + kctl->private_free = power_mode_mx_ctl_private_free; + rc = snd_ctl_add(card, kctl); + if (rc < 0) + pr_err("%s: err add config ctl, DAI = %s\n", + __func__, dai_name); + kfree(mixer_str); + + return rc; +} + static int msm_dai_q6_island_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1358,6 +1435,54 @@ static int msm_dai_q6_add_island_mx_ctls(struct snd_card *card, return rc; } +static int msm_dai_q6_add_isconfig_config_mx_ctls(struct snd_card *card, + const char *dai_name, + int dai_id, void *dai_data) + +{ + const char *mx_ctl_name = "Island Config"; + char *mixer_str = NULL; + int dai_str_len = 0, ctl_len = 0; + int rc = 0; + struct snd_kcontrol_new *knew = NULL; + struct snd_kcontrol *kctl = NULL; + + dai_str_len = strlen(dai_name) + 1; + + ctl_len = dai_str_len + strlen(mx_ctl_name) + 1; + mixer_str = kzalloc(ctl_len, GFP_KERNEL); + if (!mixer_str) + return -ENOMEM; + + snprintf(mixer_str, ctl_len, "%s %s", dai_name, mx_ctl_name); + + knew = kzalloc(sizeof(struct snd_kcontrol_new), GFP_KERNEL); + if (!knew) { + kfree(mixer_str); + return -ENOMEM; + } + knew->iface = SNDRV_CTL_ELEM_IFACE_MIXER; + knew->info = snd_ctl_boolean_mono_info; + knew->get = msm_dai_q6_island_mode_get; + knew->put = msm_dai_q6_island_mode_put; + knew->name = mixer_str; + knew->private_value = dai_id; + kctl = snd_ctl_new1(knew, knew); + if (!kctl) { + kfree(knew); + kfree(mixer_str); + return -ENOMEM; + } + kctl->private_free = island_mx_ctl_private_free; + rc = snd_ctl_add(card, kctl); + if (rc < 0) + pr_err("%s: err add config ctl, DAI = %s\n", + __func__, dai_name); + kfree(mixer_str); + + return rc; +} + /* * For single CPU DAI registration, the dai id needs to be * set explicitly in the dai probe as ASoC does not read @@ -12195,6 +12320,14 @@ static int msm_dai_q6_dai_cdc_dma_probe(struct snd_soc_dai *dai) dai->component->card->snd_card, dai->name, dai->id, (void *)dai_data); + rc = msm_dai_q6_add_power_mode_mx_ctls( + dai->component->card->snd_card, + dai->name, dai->id, + (void *)dai_data); + rc= msm_dai_q6_add_isconfig_config_mx_ctls( + dai->component->card->snd_card, + dai->name, dai->id, + (void *)dai_data); rc = msm_dai_q6_dai_add_route(dai); return rc; @@ -12624,6 +12757,7 @@ static struct snd_soc_dai_driver msm_dai_q6_cdc_dma_dai[] = { .rate_min = 8000, .rate_max = 384000, }, + .name = "RX_CDC_DMA_RX_0", .ops = &msm_dai_q6_cdc_dma_ops, .id = AFE_PORT_ID_RX_CODEC_DMA_RX_0, .probe = msm_dai_q6_dai_cdc_dma_probe, @@ -12674,6 +12808,7 @@ static struct snd_soc_dai_driver msm_dai_q6_cdc_dma_dai[] = { .rate_min = 8000, .rate_max = 384000, }, + .name = "RX_CDC_DMA_RX_1", .ops = &msm_dai_q6_cdc_dma_ops, .id = AFE_PORT_ID_RX_CODEC_DMA_RX_1, .probe = msm_dai_q6_dai_cdc_dma_probe, @@ -12798,6 +12933,7 @@ static struct snd_soc_dai_driver msm_dai_q6_cdc_dma_dai[] = { .rate_min = 8000, .rate_max = 384000, }, + .name = "TX_CDC_DMA_TX_3", .ops = &msm_dai_q6_cdc_dma_ops, .id = AFE_PORT_ID_TX_CODEC_DMA_TX_3, .probe = msm_dai_q6_dai_cdc_dma_probe, @@ -12848,6 +12984,7 @@ static struct snd_soc_dai_driver msm_dai_q6_cdc_dma_dai[] = { .rate_min = 8000, .rate_max = 384000, }, + .name = "TX_CDC_DMA_TX_4", .ops = &msm_dai_q6_cdc_dma_ops, .id = AFE_PORT_ID_TX_CODEC_DMA_TX_4, .probe = msm_dai_q6_dai_cdc_dma_probe, diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 13379ce1c5..9fe94891fc 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -176,6 +176,7 @@ struct afe_ctl { /* cal info for AFE */ struct afe_fw_info *fw_data; u32 island_mode[AFE_MAX_PORTS]; + u32 power_mode[AFE_MAX_PORTS]; struct vad_config vad_cfg[AFE_MAX_PORTS]; struct work_struct afe_dc_work; struct notifier_block event_notifier; @@ -2843,6 +2844,81 @@ done: } +static int afe_get_power_mode(u16 port_id, u32 *power_mode) +{ + int ret = 0; + int index = 0; + *power_mode = 0; + + index = q6audio_get_port_index(port_id); + if (index < 0 || index >= AFE_MAX_PORTS) { + pr_err("%s: AFE port index[%d] invalid!\n", + __func__, index); + return -EINVAL; + } + *power_mode = this_afe.power_mode[index]; + return ret; +} + +/** + * afe_send_port_power_mode - + * for sending power mode to AFE + * + * @port_id: AFE port id number + * Returns 0 on success or error on failure. + */ +int afe_send_port_power_mode(u16 port_id) +{ + struct afe_param_id_power_mode_cfg_t power_mode_cfg; + struct param_hdr_v3 param_info; + u32 power_mode = 0; + int ret = 0; + + if (!(q6core_get_avcs_api_version_per_service( + APRV2_IDS_SERVICE_ID_ADSP_AFE_V) >= AFE_API_VERSION_V4)) { + pr_debug("%s: AFE port[%d] API version is invalid!\n", + __func__, port_id); + return 0; + } + + memset(&power_mode_cfg, 0, sizeof(power_mode_cfg)); + memset(¶m_info, 0, sizeof(param_info)); + + ret = afe_get_power_mode(port_id, &power_mode); + if (ret) { + pr_err("%s: AFE port[%d] get power mode is invalid!\n", + __func__, port_id); + return ret; + } + if (power_mode == 0) { + pr_debug("%s: AFE port[%d] power mode is not enabled\n", + __func__, port_id); + return ret; + } + param_info.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE; + param_info.instance_id = INSTANCE_ID_0; + param_info.param_id = AFE_PARAM_ID_POWER_MODE_CONFIG; + param_info.param_size = sizeof(power_mode_cfg); + + power_mode_cfg.power_mode_cfg_minor_version = + AFE_API_VERSION_POWER_MODE_CONFIG; + power_mode_cfg.power_mode_enable = power_mode; + + ret = q6afe_pack_and_set_param_in_band(port_id, + q6audio_get_port_index(port_id), + param_info, (u8 *) &power_mode_cfg); + if (ret) { + pr_err("%s: AFE set power mode enable for port 0x%x failed %d\n", + __func__, port_id, ret); + return ret; + } + pr_debug("%s: AFE set power mode 0x%x enable for port 0x%x ret %d\n", + __func__, power_mode, port_id, ret); + trace_printk("%s: AFE set power mode 0x%x enable for port 0x%x ret %d\n", + __func__, power_mode, port_id, ret); + return ret; +} +EXPORT_SYMBOL(afe_send_port_power_mode); static int afe_get_island_mode(u16 port_id, u32 *island_mode) { @@ -2892,6 +2968,11 @@ int afe_send_port_island_mode(u16 port_id) __func__, port_id); return ret; } + if (island_mode == 0) { + pr_debug("%s: AFE port[%d] island mode is not enabled\n", + __func__, port_id); + return ret; + } param_info.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE; param_info.instance_id = INSTANCE_ID_0; param_info.param_id = AFE_PARAM_ID_ISLAND_CONFIG; @@ -4239,6 +4320,55 @@ void afe_set_island_mode_cfg(u16 port_id, u32 enable_flag) } EXPORT_SYMBOL(afe_set_island_mode_cfg); +/** + * afe_get_power_mode_cfg - + * get power mode configuration + * @port_id: AFE port id number + * @enable_flag: Enable or Disable + */ +int afe_get_power_mode_cfg(u16 port_id, u32 *enable_flag) +{ + uint16_t port_index; + int ret = 0; + + if (enable_flag) { + port_index = afe_get_port_index(port_id); + if (port_index < 0 || port_index >= AFE_MAX_PORTS) { + pr_err("%s: AFE port index[%d] invalid!\n", + __func__, port_index); + return -EINVAL; + } + *enable_flag = this_afe.power_mode[port_index]; + } + return ret; +} +EXPORT_SYMBOL(afe_get_power_mode_cfg); + +/** + * afe_set_power_mode_cfg - + * set power mode configuration + * @port_id: AFE port id number + * @enable_flag: Enable or Disable + */ +int afe_set_power_mode_cfg(u16 port_id, u32 enable_flag) +{ + uint16_t port_index; + int ret= 0; + + port_index = afe_get_port_index(port_id); + if (port_index < 0 || port_index >= AFE_MAX_PORTS) { + pr_err("%s: AFE port index[%d] invalid!\n", + __func__, port_index); + return -EINVAL; + } + this_afe.power_mode[port_index] = enable_flag; + + trace_printk("%s: set power mode cfg 0x%x for port 0x%x\n", + __func__, this_afe.power_mode[port_index], port_id); + return ret; +} +EXPORT_SYMBOL(afe_set_power_mode_cfg); + /** * afe_set_routing_callback - * Update callback function for routing @@ -10199,6 +10329,7 @@ int __init afe_init(void) this_afe.afe_sample_rates[i] = 0; this_afe.dev_acdb_id[i] = 0; this_afe.island_mode[i] = 0; + this_afe.power_mode[i] = 0; this_afe.vad_cfg[i].is_enable = 0; this_afe.vad_cfg[i].pre_roll = 0; init_waitqueue_head(&this_afe.wait[i]); diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index 2860016c6e..54892a7687 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -4876,6 +4876,9 @@ struct avs_dec_congestion_buffer_param_t { /* Payload of the AFE_PARAM_ID_ISLAND_CONFIG parameter used by * AFE_MODULE_AUDIO_DEV_INTERFACE. */ + +#define AFE_PARAM_ID_POWER_MODE_CONFIG 0x0002002c +#define AFE_API_VERSION_POWER_MODE_CONFIG 0x1 struct afe_param_id_island_cfg_t { uint32_t island_cfg_minor_version; /* Tracks the configuration of this parameter. @@ -4889,6 +4892,19 @@ struct afe_param_id_island_cfg_t { */ } __packed; +struct afe_param_id_power_mode_cfg_t { + uint32_t power_mode_cfg_minor_version; + /* Tracks the configuration of this parameter + * Supported values: #AFE_API_VERSION_POWER_MODE_CONFIG + */ + + uint32_t power_mode_enable; + /* Specifies whether island mode should be enabled or disabled for the + * use-case being setup. + * Supported values: 0 - Disable, 1 - Enable + */ +} __packed; + /* ID of the parameter used by #AFE_MODULE_AUDIO_DEV_INTERFACE to configure * the Codec DMA interface. */ diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h index d8fcaeaf6c..3d3fa00e4d 100644 --- a/include/dsp/q6afe-v2.h +++ b/include/dsp/q6afe-v2.h @@ -396,6 +396,8 @@ void afe_set_vad_cfg(u32 vad_enable, u32 preroll_config, void afe_set_island_mode_cfg(u16 port_id, u32 enable_flag); void afe_get_island_mode_cfg(u16 port_id, u32 *enable_flag); int afe_send_cdc_dma_data_align(u16 port_id, u32 cdc_dma_data_align); +int afe_set_power_mode_cfg(u16 port_id, u32 enable_flag); +int afe_get_power_mode_cfg(u16 port_id, u32 *enable_flag); int afe_port_start(u16 port_id, union afe_port_config *afe_config, u32 rate); int afe_set_tws_channel_mode(u32 foramt, u16 port_id, u32 channel_mode); @@ -482,6 +484,7 @@ int afe_get_sp_rx_tmax_xmax_logging_data( u16 port_id); int afe_cal_init_hwdep(void *card); int afe_send_port_island_mode(u16 port_id); +int afe_send_port_power_mode(u16 port_id); int afe_send_port_vad_cfg_params(u16 port_id); int afe_send_cmd_wakeup_register(void *handle, bool enable); void afe_register_wakeup_irq_callback( From 02b06f5634d3623acab501c135e16ab34e5207b3 Mon Sep 17 00:00:00 2001 From: Kunlei Zhang Date: Thu, 28 May 2020 15:46:33 +0800 Subject: [PATCH 2/2] asoc: lahaina: add support to send power mode for voice usecase Add support in lahaina machine driver to send power mode along with island for voice usecase. Change-Id: I4223bc7e36644e3843995832798683017de22ece Signed-off-by: Kunlei Zhang --- asoc/lahaina.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/asoc/lahaina.c b/asoc/lahaina.c index f026c5c3d3..9387f95903 100644 --- a/asoc/lahaina.c +++ b/asoc/lahaina.c @@ -2723,6 +2723,63 @@ static int msm_get_port_id(int be_id) case MSM_BACKEND_DAI_VA_CDC_DMA_TX_2: afe_port_id = AFE_PORT_ID_VA_CODEC_DMA_TX_2; break; + case MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0: + afe_port_id = AFE_PORT_ID_WSA_CODEC_DMA_RX_0; + break; + case MSM_BACKEND_DAI_WSA_CDC_DMA_TX_0: + afe_port_id = AFE_PORT_ID_WSA_CODEC_DMA_TX_0; + break; + case MSM_BACKEND_DAI_WSA_CDC_DMA_RX_1: + afe_port_id = AFE_PORT_ID_WSA_CODEC_DMA_RX_1; + break; + case MSM_BACKEND_DAI_WSA_CDC_DMA_TX_1: + afe_port_id = AFE_PORT_ID_WSA_CODEC_DMA_TX_1; + break; + case MSM_BACKEND_DAI_WSA_CDC_DMA_TX_2: + afe_port_id = AFE_PORT_ID_WSA_CODEC_DMA_TX_2; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_0: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_0; + break; + case MSM_BACKEND_DAI_TX_CDC_DMA_TX_0: + afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_0; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_1: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_1; + break; + case MSM_BACKEND_DAI_TX_CDC_DMA_TX_1: + afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_1; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_2: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_2; + break; + case MSM_BACKEND_DAI_TX_CDC_DMA_TX_2: + afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_2; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_3: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_3; + break; + case MSM_BACKEND_DAI_TX_CDC_DMA_TX_3: + afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_3; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_4: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_4; + break; + case MSM_BACKEND_DAI_TX_CDC_DMA_TX_4: + afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_4; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_5: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_5; + break; + case MSM_BACKEND_DAI_TX_CDC_DMA_TX_5: + afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_5; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_6: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_6; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_7: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_7; + break; default: pr_err("%s: Invalid BE id: %d\n", __func__, be_id); afe_port_id = -EINVAL; @@ -4124,6 +4181,38 @@ static int lahaina_send_island_va_config(int32_t be_id) return rc; } +static int lahaina_send_power_mode(int32_t be_id) +{ + int rc = 0; + int port_id = 0xFFFF; + + port_id = msm_get_port_id(be_id); + if (port_id < 0) { + pr_err("%s: Invalid power interface, be_id: %d\n", + __func__, be_id); + rc = -EINVAL; + } else { + /* + * send island mode config + * This should be the first configuration + * + */ + rc = afe_send_port_island_mode(port_id); + if (rc) + pr_err("%s: afe send island mode failed %d\n", + __func__, rc); + /* + * send power mode config + * This should be set after island configuration + */ + rc = afe_send_port_power_mode(port_id); + if (rc) + pr_err("%s: afe send power mode failed %d\n", + __func__, rc); + } + return rc; +} + static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -4887,6 +4976,12 @@ static int msm_snd_cdc_dma_startup(struct snd_pcm_substream *substream) pr_err("%s: send island va cfg failed, err: %d\n", __func__, ret); break; + default: + ret = lahaina_send_power_mode(dai_link->id); + if (ret) + pr_err("%s: send power mode failed, err: %d\n", + __func__, ret); + break; } return ret;