Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44c6cc4f authored by Kunlei Zhang's avatar Kunlei Zhang
Browse files

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: default avatarKunlei Zhang <kunleiz@codeaurora.org>
parent 127718f3
Loading
Loading
Loading
Loading
+137 −0
Original line number Diff line number Diff line
@@ -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,
+131 −0
Original line number Diff line number Diff line
@@ -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 @@ static int afe_send_port_topology_id(u16 port_id)

}

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]);
+16 −0
Original line number Diff line number Diff line
@@ -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.
 */
+3 −0
Original line number Diff line number Diff line
@@ -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(