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 <kunleiz@codeaurora.org>
This commit is contained in:
Kunlei Zhang 2020-04-17 15:42:32 +08:00
commit 44c6cc4fdc
4 changed files with 287 additions and 0 deletions

View file

@ -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,

View file

@ -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(&param_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]);

View file

@ -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.
*/

View file

@ -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(