Browse Source

ASoC: swr-dmics: Enable soundwire DMICs on lahaina

Soundwire DMICs provide the same quality as regular DMICs but
the interface is soundwire. This reduces the number of pins
on the MSM. Enable soundwire DMICs on lahaina.

Change-Id: I4245369fdcb29cf96f315ebc1d2e9a83a0fbc14b
Signed-off-by: Sudheer Papothi <[email protected]>
Sudheer Papothi 5 years ago
parent
commit
34e6984323

+ 7 - 1
asoc/codecs/bolero/bolero-cdc-registers.h

@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _BOLERO_CDC_REGISTERS_H
@@ -25,6 +25,12 @@
 #define BOLERO_CDC_TX_TOP_CSR_SWR_DMIC3_CTL	(TX_START_OFFSET + 0x00CC)
 #define BOLERO_CDC_TX_TOP_CSR_SWR_AMIC0_CTL	(TX_START_OFFSET + 0x00D0)
 #define BOLERO_CDC_TX_TOP_CSR_SWR_AMIC1_CTL	(TX_START_OFFSET + 0x00D4)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_MIC2_CTL	(TX_START_OFFSET + 0x00C0)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_MIC3_CTL	(TX_START_OFFSET + 0x00C4)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_MIC4_CTL	(TX_START_OFFSET + 0x00C8)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_MIC5_CTL	(TX_START_OFFSET + 0x00CC)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_MIC0_CTL	(TX_START_OFFSET + 0x00D0)
+#define BOLERO_CDC_TX_TOP_CSR_SWR_MIC1_CTL	(TX_START_OFFSET + 0x00D4)
 #define BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0	(TX_START_OFFSET + 0x0100)
 #define BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1	(TX_START_OFFSET + 0x0104)
 #define BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0	(TX_START_OFFSET + 0x0108)

+ 37 - 0
asoc/codecs/bolero/tx-macro.c

@@ -904,6 +904,7 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
 	u16 hpf_gate_reg = 0;
 	u16 tx_gain_ctl_reg = 0;
 	u8 hpf_cut_off_freq = 0;
+	u16 adc_mux_reg = 0;
 	int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS;
 	int unmute_delay = TX_MACRO_DMIC_UNMUTE_DELAY_MS;
 	struct device *tx_dev = NULL;
@@ -925,6 +926,8 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
 				TX_MACRO_TX_PATH_OFFSET * decimator;
 	tx_gain_ctl_reg = BOLERO_CDC_TX0_TX_VOL_CTL +
 				TX_MACRO_TX_PATH_OFFSET * decimator;
+	adc_mux_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+			TX_MACRO_ADC_MUX_CFG_OFFSET * decimator;
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
@@ -1008,6 +1011,32 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
 					BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40,
 					0x40);
 		}
+		if (tx_priv->version == BOLERO_VERSION_2_0) {
+			if (snd_soc_component_read32(component, adc_mux_reg)
+							& SWR_MIC) {
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_CTRL,
+					0x01, 0x01);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC0_CTL,
+					0x0E, 0x0C);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC1_CTL,
+					0x0E, 0x0C);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC2_CTL,
+					0x0E, 0x00);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC3_CTL,
+					0x0E, 0x00);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC4_CTL,
+					0x0E, 0x00);
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_MIC5_CTL,
+					0x0E, 0x00);
+			}
+		}
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
 		hpf_cut_off_freq =
@@ -1036,6 +1065,14 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
 		}
 		cancel_delayed_work_sync(
 				&tx_priv->tx_mute_dwork[decimator].dwork);
+
+		if (tx_priv->version == BOLERO_VERSION_2_0) {
+			if (snd_soc_component_read32(component, adc_mux_reg)
+							& SWR_MIC)
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX_TOP_CSR_SWR_CTRL,
+					0x01, 0x00);
+		}
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		snd_soc_component_update_bits(component, tx_vol_ctl_reg,

+ 190 - 264
asoc/codecs/swr-dmic.c

@@ -27,13 +27,25 @@
 #include <asoc/msm-cdc-pinctrl.h>
 #include <asoc/msm-cdc-supply.h>
 #include <dt-bindings/sound/audio-codec-port-types.h>
+#include "wcd938x/wcd938x.h"
 #include "swr-dmic.h"
 
-#define itoa(x)                   ('0' + x)
-#define DAI_NAME_NUM_INDEX        11
-#define AIF_NAME_NUM_INDEX        12
-#define DEFAULT_CODEC_NAME        "swr_dmic_tx0"
-#define DEFAULT_AIF_NAME          "SWR_DMIC_AIF0 Playback"
+static int swr_master_channel_map[] = {
+	ZERO,
+	SWRM_TX1_CH1,
+	SWRM_TX1_CH2,
+	SWRM_TX1_CH3,
+	SWRM_TX1_CH4,
+	SWRM_TX2_CH1,
+	SWRM_TX2_CH2,
+	SWRM_TX2_CH3,
+	SWRM_TX2_CH4,
+	SWRM_TX3_CH1,
+	SWRM_TX3_CH2,
+	SWRM_TX3_CH3,
+	SWRM_TX3_CH4,
+	SWRM_PCM_IN,
+};
 
 /*
  * Private data Structure for swr-dmic. All parameters related to
@@ -44,12 +56,12 @@ struct swr_dmic_priv {
 	struct swr_device *swr_slave;
 	struct snd_soc_component *component;
 	struct snd_soc_component_driver *driver;
-	struct snd_soc_dai_driver *dai_driver;
-	const char *supply_name;
+	struct snd_soc_component *supply_component;
+	u32 micb_num;
 	struct device_node *wcd_handle;
-	struct cdc_wcd_supply *cdc_supply;
 	bool is_wcd_supply;
-	int tx_mode;
+	int is_en_supply;
+	int port_type;
 	u8 tx_master_port_map[SWR_DMIC_MAX_PORTS];
 };
 
@@ -58,127 +70,34 @@ const char *codec_name_list[] = {
 	"swr-dmic-02",
 	"swr-dmic-03",
 	"swr-dmic-04",
-	"swr-dmic-05",
 };
 
-static int get_master_port(int val)
-{
-	int master_port = 0;
-
-	switch(val) {
-	case 0:
-		master_port = SWRM_TX1_CH1;
-		break;
-	case 1:
-		master_port = SWRM_TX1_CH2;
-		break;
-	case 2:
-		master_port = SWRM_TX1_CH3;
-		break;
-	case 3:
-		master_port = SWRM_TX1_CH4;
-		break;
-	case 4:
-		master_port = SWRM_TX2_CH1;
-		break;
-	case 5:
-		master_port = SWRM_TX2_CH2;
-		break;
-	case 6:
-		master_port = SWRM_TX2_CH3;
-		break;
-	case 7:
-		master_port = SWRM_TX2_CH4;
-		break;
-	case 8:
-		master_port = SWRM_TX3_CH1;
-		break;
-	case 9:
-		master_port = SWRM_TX3_CH2;
-		break;
-	case 10:
-		master_port = SWRM_TX3_CH3;
-		break;
-	case 11:
-		master_port = SWRM_TX3_CH4;
-		break;
-	case 12:
-		master_port = SWRM_PCM_IN;
-		break;
-	default:
-		master_port = SWRM_TX1_CH1;
-		pr_debug("%s: undefined value, fall back to default master_port: %d\n",
-			 __func__, master_port);
-		break;
-	}
-
-	pr_debug("%s: master_port: %d\n", __func__, master_port);
-	return master_port;
-}
-
-static int get_master_port_val(int master_port)
-{
-	int val = 0;
+const char *dai_name_list[] = {
+	"swr_dmic_tx0",
+	"swr_dmic_tx1",
+	"swr_dmic_tx2",
+	"swr_dmic_tx3",
+};
 
-	switch (master_port) {
-	case SWRM_TX1_CH1:
-		val = 0;
-		break;
-	case SWRM_TX1_CH2:
-		val = 1;
-		break;
-	case SWRM_TX1_CH3:
-		val = 2;
-		break;
-	case SWRM_TX1_CH4:
-		val = 3;
-		break;
-	case SWRM_TX2_CH1:
-		val = 4;
-		break;
-	case SWRM_TX2_CH2:
-		val = 5;
-		break;
-	case SWRM_TX2_CH3:
-		val = 6;
-		break;
-	case SWRM_TX2_CH4:
-		val = 7;
-		break;
-	case SWRM_TX3_CH1:
-		val = 8;
-		break;
-	case SWRM_TX3_CH2:
-		val = 9;
-		break;
-	case SWRM_TX3_CH3:
-		val = 10;
-		break;
-	case SWRM_TX3_CH4:
-		val = 11;
-		break;
-	case SWRM_PCM_IN:
-		val = 12;
-		break;
-	default:
-		val = 0;
-		pr_debug("%s: undefined master_port:%d, fallback to default val: %d\n",
-			 __func__, master_port, val);
-		break;
-	}
+const char *aif_name_list[] = {
+	"SWR_DMIC_AIF0 Playback",
+	"SWR_DMIC_AIF1 Playback",
+	"SWR_DMIC_AIF2 Playback",
+	"SWR_DMIC_AIF3 Playback",
+};
 
-	pr_debug("%s: master_port:%d val: %d\n", __func__, master_port, val);
-	return val;
-}
+static int swr_dmic_reset(struct swr_device *pdev);
+static int swr_dmic_up(struct swr_device *pdev);
+static int swr_dmic_down(struct swr_device *pdev);
 
 static inline int swr_dmic_tx_get_slave_port_type_idx(const char *wname,
 				      unsigned int *port_idx)
 {
 	u8 port_type;
 
-	if (strnstr(wname, "HIFI", sizeof("HIFI")))
+	if (strnstr(wname, "HIFI", strlen(wname)))
 		port_type = SWR_DMIC_HIFI_PORT;
-	else if (strnstr(wname, "LP", sizeof("LP")))
+	else if (strnstr(wname, "LP", strlen(wname)))
 		port_type = SWR_DMIC_LP_PORT;
 	else
 		return -EINVAL;
@@ -187,6 +106,16 @@ static inline int swr_dmic_tx_get_slave_port_type_idx(const char *wname,
 	return 0;
 }
 
+static inline int swr_dmic_get_master_port_val(int port)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(swr_master_channel_map); i++)
+		if (port == swr_master_channel_map[i])
+			return i;
+	return 0;
+}
+
 static int swr_dmic_tx_master_port_get(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
@@ -202,14 +131,15 @@ static int swr_dmic_tx_master_port_get(struct snd_kcontrol *kcontrol,
 		dev_dbg(component->dev, "%s: invalid port string\n", __func__);
 		return ret;
 	}
+	swr_dmic->port_type = slave_port_idx;
 
-	if (slave_port_idx >= 0 &&
-		slave_port_idx < SWR_DMIC_MAX_PORTS)
-		ucontrol->value.integer.value[0] = get_master_port_val(
+	ucontrol->value.integer.value[0] =
+			swr_dmic_get_master_port_val(
 				swr_dmic->tx_master_port_map[slave_port_idx]);
 
 	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
 			__func__, ucontrol->value.integer.value[0]);
+
 	return 0;
 }
 
@@ -228,17 +158,13 @@ static int swr_dmic_tx_master_port_put(struct snd_kcontrol *kcontrol,
 		dev_dbg(component->dev, "%s: invalid port string\n", __func__);
 		return ret;
 	}
+	swr_dmic->port_type = slave_port_idx;
 
-
-	dev_dbg(component->dev, "%s: slave_port_idx: %d",
-			__func__, slave_port_idx);
-	dev_dbg(component->dev, "%s: ucontrol->value.enumerated.item[0] = %ld\n",
-			__func__, ucontrol->value.enumerated.item[0]);
-	if (slave_port_idx >= 0 &&
-		slave_port_idx < SWR_DMIC_MAX_PORTS)
-		swr_dmic->tx_master_port_map[slave_port_idx] =
-				get_master_port(
-					ucontrol->value.enumerated.item[0]);
+	swr_dmic->tx_master_port_map[slave_port_idx] =
+		swr_master_channel_map[ucontrol->value.enumerated.item[0]];
+	dev_dbg(component->dev, "%s: slv port id: %d, master_port_type: %d\n",
+		__func__, slave_port_idx,
+		swr_dmic->tx_master_port_map[slave_port_idx]);
 
 	return 0;
 }
@@ -254,20 +180,27 @@ static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w,
 
 	u8 num_ch = 1;
 	u8 ch_mask = 0x01; // only DpnChannelEN1 register is available
-	u8 port_type = 0;
-	u32 ch_rate = 0;
+	u32 ch_rate = SWR_CLK_RATE_4P8MHZ;
 	u8 num_port = 1;
+	u8 port_type = 0;
+	u8 port_id = swr_dmic->port_type;
+
 	/*
 	 * Port 1 is high quality / 2.4 or 3.072 Mbps
 	 * Port 2 is listen low power / 0.6 or 0.768 Mbps
 	 */
-	u8 port_id = swr_dmic->tx_mode;
+	if(swr_dmic->port_type)
+		ch_rate = SWR_CLK_RATE_2P4MHZ;
+	else
+		ch_rate = SWR_CLK_RATE_4P8MHZ;
+
 	port_type = swr_dmic->tx_master_port_map[port_id];
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		ret = swr_connect_port(swr_dmic->swr_slave, &port_id, num_port,
-			&ch_mask, &ch_rate, &num_ch, &port_type);
+		ret = swr_connect_port(swr_dmic->swr_slave, &port_id,
+					num_port, &ch_mask, &ch_rate,
+					&num_ch, &port_type);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		ret = swr_slvdev_datapath_control(swr_dmic->swr_slave,
@@ -278,56 +211,48 @@ static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w,
 			swr_dmic->swr_slave->dev_num, false);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		ret = swr_disconnect_port(swr_dmic->swr_slave, &port_id,
-					  num_port, &ch_mask, &port_type);
+		ret = swr_disconnect_port(swr_dmic->swr_slave,
+				&port_id, num_port, &ch_mask, &port_type);
 		break;
 	};
 
 	return ret;
 }
 
-static const char * const tx_mode_text_swr_mic[] = {
-	"MIC_HIFI", "MIC_LP",
-};
-
-static int swr_mic_tx_mode_put(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *ucontrol)
+static int swr_dmic_enable_supply(struct snd_soc_dapm_widget *w,
+			       struct snd_kcontrol *kcontrol,
+			       int event)
 {
 	struct snd_soc_component *component =
-			snd_soc_kcontrol_component(kcontrol);
+			snd_soc_dapm_to_component(w->dapm);
 	struct swr_dmic_priv *swr_dmic =
 			snd_soc_component_get_drvdata(component);
+	int ret = 0;
 
-	dev_dbg(component->dev, "%s: tx_mode  = %ld\n",
-		__func__, ucontrol->value.integer.value[0]);
-
-	swr_dmic->tx_mode =  ucontrol->value.integer.value[0];
-
-	return 0;
-}
-
-static int swr_mic_tx_mode_get(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_component *component =
-			snd_soc_kcontrol_component(kcontrol);
-	struct swr_dmic_priv *swr_dmic =
-			snd_soc_component_get_drvdata(component);
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
 
-	ucontrol->value.integer.value[0] = swr_dmic->tx_mode;
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = swr_dmic_up(swr_dmic->swr_slave);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		ret = swr_dmic_reset(swr_dmic->swr_slave);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		ret = swr_dmic_down(swr_dmic->swr_slave);
+		break;
+	}
 
-	dev_dbg(component->dev, "%s: tx_mode = 0x%x\n", __func__,
-			swr_dmic->tx_mode);
+	if (ret)
+		dev_dbg(component->dev, "%s wname: %s event: %d ret : %d\n",
+			__func__, w->name, event, ret);
 
-	return 0;
+	return ret;
 }
 
-static const struct soc_enum tx_mode_enum_swr_mic =
-	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tx_mode_text_swr_mic),
-			    tx_mode_text_swr_mic);
-
 static const char * const tx_master_port_text[] = {
-	"SWRM_TX1_CH1", "SWRM_TX1_CH2", "SWRM_TX1_CH3", "SWRM_TX1_CH4",
+	"ZERO", "SWRM_TX1_CH1", "SWRM_TX1_CH2", "SWRM_TX1_CH3", "SWRM_TX1_CH4",
 	"SWRM_TX2_CH1", "SWRM_TX2_CH2", "SWRM_TX2_CH3", "SWRM_TX2_CH4",
 	"SWRM_TX3_CH1", "SWRM_TX3_CH2", "SWRM_TX3_CH3", "SWRM_TX3_CH4",
 	"SWRM_PCM_IN",
@@ -338,9 +263,6 @@ static const struct soc_enum tx_master_port_enum =
 				tx_master_port_text);
 
 static const struct snd_kcontrol_new swr_dmic_snd_controls[] = {
-	SOC_ENUM_EXT("TX MODE", tx_mode_enum_swr_mic,
-			swr_mic_tx_mode_get, swr_mic_tx_mode_put),
-
 	SOC_ENUM_EXT("HIFI PortMap", tx_master_port_enum,
 		swr_dmic_tx_master_port_get, swr_dmic_tx_master_port_put),
 	SOC_ENUM_EXT("LP PortMap", tx_master_port_enum,
@@ -352,17 +274,23 @@ static const struct snd_kcontrol_new dmic_switch[] = {
 };
 
 static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = {
-	SND_SOC_DAPM_MIXER_E("DMIC_SWR_MIXER", SND_SOC_NOPM, 0, 0,
+	SND_SOC_DAPM_MIXER_E("SWR_DMIC_MIXER", SND_SOC_NOPM, 0, 0,
 			dmic_switch, ARRAY_SIZE(dmic_switch), dmic_swr_ctrl,
 			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 			SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_INPUT("SWR_DMIC"),
 
+	SND_SOC_DAPM_SUPPLY_S("SMIC_SUPPLY", 1, SND_SOC_NOPM, 0, 0,
+				swr_dmic_enable_supply,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+
 	SND_SOC_DAPM_OUTPUT("SWR_DMIC_OUTPUT"),
 };
 
 static const struct snd_soc_dapm_route swr_dmic_audio_map[] = {
+	{"SWR_DMIC", NULL, "SMIC_SUPPLY"},
 	{"SWR_DMIC_MIXER", "Switch", "SWR_DMIC"},
 	{"SWR_DMIC_OUTPUT", NULL, "SWR_DMIC_MIXER"},
 };
@@ -400,55 +328,63 @@ static const struct snd_soc_component_driver soc_codec_dev_swr_dmic = {
 	.num_dapm_routes = ARRAY_SIZE(swr_dmic_audio_map),
 };
 
-static struct snd_soc_dai_ops wsa_dai_ops = {
-};
+static int enable_wcd_codec_supply(struct swr_dmic_priv *swr_dmic, bool enable)
+{
+	int rc = 0;
+	int micb_num = swr_dmic->micb_num;
+	struct snd_soc_component *component = swr_dmic->supply_component;
 
-static struct snd_soc_dai_driver swr_dmic_dai[] = {
-	{
-		.name = "",
-		.id = 0,
-		.playback = {
-			.stream_name = "",
-			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
-				SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |
-				SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000),
-			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
-				SNDRV_PCM_FMTBIT_S24_LE |
-				SNDRV_PCM_FMTBIT_S32_LE),
-			.rate_max = 192000,
-			.rate_min = 8000,
-			.channels_min = 1,
-			.channels_max = 2,
-		},
-		.ops = &wsa_dai_ops,
-	},
-};
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (enable)
+		rc = wcd938x_codec_force_enable_micbias_v2(component,
+					SND_SOC_DAPM_PRE_PMU, micb_num);
+	else
+		rc = wcd938x_codec_force_enable_micbias_v2(component,
+					SND_SOC_DAPM_POST_PMD, micb_num);
+
+	return rc;
+}
+
+static int swr_dmic_parse_supply(struct device_node *np,
+				struct swr_dmic_priv *swr_dmic)
+{
+	struct platform_device *pdev = NULL;
+
+	if (!np || !swr_dmic)
+		return -EINVAL;
+
+	pdev = of_find_device_by_node(np);
+	if (!pdev)
+		return -EINVAL;
+
+	swr_dmic->supply_component = snd_soc_lookup_component(&pdev->dev, NULL);
+
+	return 0;
+}
 
 static int swr_dmic_probe(struct swr_device *pdev)
 {
 	int ret = 0;
-	struct swr_dmic_priv *swr_dmic;
 	int i = 0;
-	u8 devnum = 0;
+	u8 swr_devnum = 0;
+	int dev_index = -1;
+	char* prefix_name = NULL;
+	struct swr_dmic_priv *swr_dmic = NULL;
 	const char *swr_dmic_name_prefix_of = NULL;
 	const char *swr_dmic_codec_name_of = NULL;
-	struct snd_soc_component *component;
-	char *dai_name;
-	char *aif_name;
+	struct snd_soc_component *component = NULL;
 
 	swr_dmic = devm_kzalloc(&pdev->dev, sizeof(struct swr_dmic_priv),
 			    GFP_KERNEL);
 	if (!swr_dmic)
 		return -ENOMEM;
 
-	swr_dmic->cdc_supply = devm_kzalloc(&pdev->dev,
-					sizeof(struct cdc_wcd_supply),
-					GFP_KERNEL);
-	if (!swr_dmic->cdc_supply)
-		return -ENOMEM;
-
-	ret = of_property_read_string(pdev->dev.of_node, "qcom,swr-dmic-supply",
-				&swr_dmic->supply_name);
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,swr-dmic-supply",
+				&swr_dmic->micb_num);
 	if (ret) {
 		dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n",
 		__func__, "qcom,swr-dmic-supply",
@@ -462,17 +398,17 @@ static int swr_dmic_probe(struct swr_device *pdev)
 			__func__);
 		swr_dmic->is_wcd_supply = false;
 	} else {
-		msm_cdc_init_wcd_supply(swr_dmic->wcd_handle,
-				swr_dmic->supply_name, swr_dmic->cdc_supply);
+		swr_dmic_parse_supply(swr_dmic->wcd_handle, swr_dmic);
 		swr_dmic->is_wcd_supply = true;
 	}
 
 	if (swr_dmic->is_wcd_supply) {
-		ret = msm_cdc_enable_wcd_supply(swr_dmic->cdc_supply, true);
+		ret = enable_wcd_codec_supply(swr_dmic, true);
 		if (ret) {
 			ret = -EPROBE_DEFER;
-			goto err;
+			goto dev_err;
 		}
+		++swr_dmic->is_en_supply;
 	}
 
 	swr_set_dev_data(pdev, swr_dmic);
@@ -485,7 +421,7 @@ static int swr_dmic_probe(struct swr_device *pdev)
 		dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n",
 		__func__, "qcom,swr-dmic-prefix",
 		pdev->dev.of_node->full_name);
-		goto err;
+		goto dev_err;
 	}
 
 	ret = of_property_read_string(pdev->dev.of_node, "qcom,codec-name",
@@ -494,7 +430,7 @@ static int swr_dmic_probe(struct swr_device *pdev)
 		dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n",
 		__func__, "qcom,codec-name",
 		pdev->dev.of_node->full_name);
-		goto err;
+		goto dev_err;
 	}
 
 	/*
@@ -503,14 +439,16 @@ static int swr_dmic_probe(struct swr_device *pdev)
 	 * as per HW requirement.
 	 */
 	usleep_range(5000, 5010);
-	ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum);
+	ret = swr_get_logical_dev_num(pdev, pdev->addr, &swr_devnum);
 	if (ret) {
 		dev_dbg(&pdev->dev,
 			"%s get devnum %d for dev addr %lx failed\n",
-			__func__, devnum, pdev->addr);
+			__func__, swr_devnum, pdev->addr);
+		ret = -EPROBE_DEFER;
 		goto dev_err;
 	}
-	pdev->dev_num = devnum;
+	pdev->dev_num = swr_devnum;
+
 
 	swr_dmic->driver = devm_kzalloc(&pdev->dev,
 			sizeof(struct snd_soc_component_driver), GFP_KERNEL);
@@ -521,53 +459,23 @@ static int swr_dmic_probe(struct swr_device *pdev)
 
 	memcpy(swr_dmic->driver, &soc_codec_dev_swr_dmic,
 			sizeof(struct snd_soc_component_driver));
-	swr_dmic->driver->name = devm_kzalloc(&pdev->dev,
-			strlen(swr_dmic_codec_name_of), GFP_KERNEL);
-	if (!swr_dmic->driver->name) {
-		ret = -ENOMEM;
-		goto dev_err;
-	}
 
 	for (i = 0; i < ARRAY_SIZE(codec_name_list); i++) {
-		if (!strcmp(swr_dmic_codec_name_of, codec_name_list[i]))
+		if (!strcmp(swr_dmic_codec_name_of, codec_name_list[i])) {
+			dev_index = i;
 			break;
-	}
-	if (i == ARRAY_SIZE(codec_name_list))
-		goto dev_err;
-
-	swr_dmic->dai_driver = devm_kzalloc(&pdev->dev,
-			sizeof(struct snd_soc_dai_driver), GFP_KERNEL);
-	if (!swr_dmic->dai_driver) {
-		ret = -ENOMEM;
-		goto dev_err;
-	}
-
-	memcpy(swr_dmic->dai_driver, swr_dmic_dai,
-			sizeof(struct snd_soc_dai_driver));
-	dai_name = devm_kzalloc(&pdev->dev, strlen(DEFAULT_CODEC_NAME),
-			GFP_KERNEL);
-	if (!dai_name) {
-		ret = -ENOMEM;
-		goto dev_err;
+		}
 	}
 
-	memcpy(dai_name, DEFAULT_CODEC_NAME, strlen(DEFAULT_CODEC_NAME));
-	dai_name[DAI_NAME_NUM_INDEX] = itoa(i);
-	swr_dmic->dai_driver->name = dai_name;
-	swr_dmic->dai_driver->id = i;
-	aif_name = devm_kzalloc(&pdev->dev, strlen(DEFAULT_AIF_NAME),
-			GFP_KERNEL);
-	if (!aif_name) {
-		ret = -ENOMEM;
+	if (dev_index < 0) {
+		ret = -EINVAL;
 		goto dev_err;
 	}
 
-	memcpy(aif_name, DEFAULT_AIF_NAME, strlen(DEFAULT_AIF_NAME));
-	aif_name[AIF_NAME_NUM_INDEX] = itoa(i);
-	swr_dmic->dai_driver->playback.stream_name = aif_name;
+	swr_dmic->driver->name = dai_name_list[dev_index];
 
 	ret = snd_soc_register_component(&pdev->dev, swr_dmic->driver,
-				swr_dmic->dai_driver, 1);
+				NULL, 0);
 	if (ret) {
 		dev_err(&pdev->dev, "%s: Codec registration failed\n",
 			__func__);
@@ -577,19 +485,26 @@ static int swr_dmic_probe(struct swr_device *pdev)
 	component = snd_soc_lookup_component(&pdev->dev,
 						swr_dmic->driver->name);
 	swr_dmic->component = component;
-	component->name_prefix = devm_kzalloc(&pdev->dev,
+	prefix_name = devm_kzalloc(&pdev->dev,
 					strlen(swr_dmic_name_prefix_of),
-	   GFP_KERNEL);
-	if (!component->name_prefix) {
+					GFP_KERNEL);
+	if (!prefix_name) {
 		ret = -ENOMEM;
 		goto dev_err;
 	}
+	strlcpy(prefix_name, swr_dmic_name_prefix_of,
+			strlen(swr_dmic_name_prefix_of));
+	component->name_prefix = prefix_name;
 
 	return 0;
 
 dev_err:
-	if (swr_dmic->is_wcd_supply)
-		msm_cdc_enable_wcd_supply(swr_dmic->cdc_supply, false);
+	if (swr_dmic->is_en_supply == 1) {
+		enable_wcd_codec_supply(swr_dmic, false);
+		--swr_dmic->is_en_supply;
+	}
+	swr_dmic->is_wcd_supply = false;
+	swr_dmic->wcd_handle = NULL;
 	swr_remove_device(pdev);
 err:
 	return ret;
@@ -620,8 +535,10 @@ static int swr_dmic_up(struct swr_device *pdev)
 		dev_err(&pdev->dev, "%s: swr_dmic is NULL\n", __func__);
 		return -EINVAL;
 	}
-	if (swr_dmic->is_wcd_supply)
-		ret = msm_cdc_enable_wcd_supply(swr_dmic->cdc_supply, true);
+
+	++swr_dmic->is_en_supply;
+	if (swr_dmic->is_en_supply == 1)
+		ret = enable_wcd_codec_supply(swr_dmic, true);
 
 	return ret;
 }
@@ -636,9 +553,18 @@ static int swr_dmic_down(struct swr_device *pdev)
 		dev_err(&pdev->dev, "%s: swr_dmic is NULL\n", __func__);
 		return -EINVAL;
 	}
-	if (swr_dmic->is_wcd_supply)
-		ret = msm_cdc_enable_wcd_supply(swr_dmic->cdc_supply, false);
 
+	--swr_dmic->is_en_supply;
+	if (swr_dmic->is_en_supply < 0) {
+		dev_warn(&pdev->dev, "%s: mismatch in supply count %d\n",
+			__func__, swr_dmic->is_en_supply);
+		swr_dmic->is_en_supply = 0;
+		goto done;
+	}
+	if (!swr_dmic->is_en_supply)
+		enable_wcd_codec_supply(swr_dmic, false);
+
+done:
 	return ret;
 }
 

+ 3 - 5
asoc/lahaina-port-config.h

@@ -43,11 +43,9 @@ static struct port_params rx_frame_params_dsd[SWR_MSTR_PORT_LEN] = {
 
 /* TX UC1: TX1: 1ch, TX2: 2chs, TX3: 1ch(MBHC) */
 static struct port_params tx_frame_params_default[SWR_MSTR_PORT_LEN] = {
-	{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},/* PCM OUT */
-	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},  /* TX1 */
-	{1,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1},  /* TX2 */
-	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},  /* TX3 */
-	{3,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1},  /* TX4 */
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},  /* TX1 */
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},  /* TX2 */
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},  /* TX3 */
 };
 
 /* TX UC1: TX1: 1ch, TX2: 2chs, TX3: 1ch(MBHC) */