Browse Source

Merge "asoc: lahaina: add support to send power mode for voice usecase"

qctecmdr 4 years ago
parent
commit
344b47efbe
5 changed files with 382 additions and 0 deletions
  1. 95 0
      asoc/lahaina.c
  2. 137 0
      asoc/msm-dai-q6-v2.c
  3. 131 0
      dsp/q6afe.c
  4. 16 0
      include/dsp/apr_audio-v2.h
  5. 3 0
      include/dsp/q6afe-v2.h

+ 95 - 0
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;

+ 137 - 0
asoc/msm-dai-q6-v2.c

@@ -1280,6 +1280,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)
 {
@@ -1359,6 +1436,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
@@ -12322,6 +12447,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;
@@ -12765,6 +12898,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,
@@ -12815,6 +12949,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,
@@ -12939,6 +13074,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,
@@ -12989,6 +13125,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
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;
@@ -2872,6 +2873,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)
 {
@@ -2921,6 +2997,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;
@@ -4268,6 +4349,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
@@ -10479,6 +10609,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
include/dsp/apr_audio-v2.h

@@ -4929,6 +4929,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.
@@ -4942,6 +4945,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
include/dsp/q6afe-v2.h

@@ -398,6 +398,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);
@@ -489,6 +491,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(