Просмотр исходного кода

Merge "wsa: soundwire: Add support for 4p8MHz DAC rate"

qctecmdr 3 лет назад
Родитель
Сommit
590d8a9823

+ 62 - 2
asoc/codecs/bolero/wsa-macro.c

@@ -233,6 +233,7 @@ struct wsa_macro_priv {
 			[WSA_MACRO_CHILD_DEVICES_MAX];
 	int child_count;
 	int ear_spkr_gain;
+	int wsa_spkrrecv;
 	int spkr_gain_offset;
 	int spkr_mode;
 	int is_softclip_on[WSA_MACRO_SOFTCLIP_MAX];
@@ -291,6 +292,11 @@ static const struct snd_kcontrol_new wsa_int1_vbat_mix_switch[] = {
 	SOC_DAPM_SINGLE("WSA RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
 };
 
+static const char *const wsa_macro_ear_spkrrecv_text[] = {
+	"OFF", "ON"
+};
+static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_ear_spkrrecv_enum,
+				wsa_macro_ear_spkrrecv_text);
 static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_ear_spkr_pa_gain_enum,
 				wsa_macro_ear_spkr_pa_gain_text);
 static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_spkr_boost_stage_enum,
@@ -1703,6 +1709,14 @@ static int wsa_macro_config_ear_spkr_gain(struct snd_soc_component *component,
 			dev_dbg(wsa_priv->dev, "%s: RX0 Volume %d dB\n",
 				__func__, val);
 		}
+		if(wsa_priv->wsa_spkrrecv) {
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x00);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80);
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x00);
+		}
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		/*
@@ -1717,6 +1731,12 @@ static int wsa_macro_config_ear_spkr_gain(struct snd_soc_component *component,
 			dev_dbg(wsa_priv->dev, "%s: Reset RX0 Volume to 0 dB\n",
 				__func__);
 		}
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01);
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x00);
 		break;
 	}
 
@@ -2093,6 +2113,43 @@ static int wsa_macro_set_compander(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+static int wsa_macro_ear_spkrrecv_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->wsa_spkrrecv;
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		 __func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int wsa_macro_ear_spkrrecv_put(struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_value *ucontrol)
+{
+        struct snd_soc_component *component =
+                                snd_soc_kcontrol_component(kcontrol);
+        struct device *wsa_dev = NULL;
+        struct wsa_macro_priv *wsa_priv = NULL;
+
+        if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+                return -EINVAL;
+        wsa_priv->wsa_spkrrecv = ucontrol->value.integer.value[0];
+
+        dev_dbg(component->dev, "%s:spkrrecv status = %d\n",
+                 __func__, wsa_priv->wsa_spkrrecv);
+
+        return 0;
+}
+
 static int wsa_macro_ear_spkr_pa_gain_get(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
@@ -2354,6 +2411,9 @@ static int wsa_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol,
 }
 
 static const struct snd_kcontrol_new wsa_macro_snd_controls[] = {
+	SOC_ENUM_EXT("WSA SPKRRECV", wsa_macro_ear_spkrrecv_enum,
+			wsa_macro_ear_spkrrecv_get,
+			wsa_macro_ear_spkrrecv_put),
 	SOC_ENUM_EXT("EAR SPKR PA Gain", wsa_macro_ear_spkr_pa_gain_enum,
 		     wsa_macro_ear_spkr_pa_gain_get,
 		     wsa_macro_ear_spkr_pa_gain_put),
@@ -2742,10 +2802,10 @@ static const struct snd_soc_dapm_route wsa_audio_map[] = {
 static const struct wsa_macro_reg_mask_val wsa_macro_reg_init[] = {
 	{BOLERO_CDC_WSA_BOOST0_BOOST_CFG1, 0x3F, 0x12},
 	{BOLERO_CDC_WSA_BOOST0_BOOST_CFG2, 0x1C, 0x08},
-	{BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x1E, 0x0C},
+	{BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x1E, 0x18},
 	{BOLERO_CDC_WSA_BOOST1_BOOST_CFG1, 0x3F, 0x12},
 	{BOLERO_CDC_WSA_BOOST1_BOOST_CFG2, 0x1C, 0x08},
-	{BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x1E, 0x0C},
+	{BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x1E, 0x18},
 	{BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x70, 0x58},
 	{BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x70, 0x58},
 	{BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08},

+ 59 - 3
asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.c

@@ -279,7 +279,7 @@ struct lpass_cdc_wsa_macro_priv {
 	struct platform_device *pdev_child_devices
 			[LPASS_CDC_WSA_MACRO_CHILD_DEVICES_MAX];
 	int child_count;
-	int ear_spkr_gain;
+	int wsa_spkrrecv;
 	int spkr_gain_offset;
 	int spkr_mode;
 	int is_softclip_on[LPASS_CDC_WSA_MACRO_SOFTCLIP_MAX];
@@ -323,6 +323,10 @@ static const char * const lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_text[] = {
 	"OFF", "ON"
 };
 
+static const char *const lpass_cdc_wsa_macro_ear_spkrrecv_text[] = {
+	"OFF", "ON"
+};
+
 static const char * const lpass_cdc_wsa_macro_comp_mode_text[] = {
 	"G_21_DB", "G_19P5_DB", "G_18_DB", "G_16P5_DB", "G_15_DB",
 	"G_13P5_DB", "G_12_DB", "G_10P5_DB", "G_9_DB"
@@ -336,6 +340,8 @@ static const struct snd_kcontrol_new wsa_int1_vbat_mix_switch[] = {
 	SOC_DAPM_SINGLE("WSA RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
 };
 
+static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa_macro_ear_spkrrecv_enum,
+				lpass_cdc_wsa_macro_ear_spkrrecv_text);
 static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_enum,
 			lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_text);
 static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa_macro_comp_mode_enum,
@@ -1527,6 +1533,9 @@ static int lpass_cdc_wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w
 	u8 gain = 0;
 	u16 reg = 0;
 
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
 	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
 		return -EINVAL;
 
@@ -1578,8 +1587,14 @@ static int lpass_cdc_wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w
 
 		lpass_cdc_wsa_macro_config_compander(component, w->shift, event);
 		lpass_cdc_wsa_macro_config_softclip(component, w->shift, event);
+		if(wsa_priv->wsa_spkrrecv)
+			snd_soc_component_update_bits(component,
+					LPASS_CDC_WSA_RX0_RX_PATH_CFG1,
+					0x08, 0x00);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA_RX0_RX_PATH_CFG1,	0x08, 0x08);
 		lpass_cdc_wsa_macro_config_compander(component, w->shift, event);
 		lpass_cdc_wsa_macro_config_softclip(component, w->shift, event);
 		lpass_cdc_wsa_macro_enable_prim_interpolator(component, reg, event);
@@ -2028,6 +2043,44 @@ static int lpass_cdc_wsa_macro_set_compander(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+static int lpass_cdc_wsa_macro_ear_spkrrecv_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->wsa_spkrrecv;
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		 __func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_ear_spkrrecv_put(struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_value *ucontrol)
+{
+        struct snd_soc_component *component =
+                                snd_soc_kcontrol_component(kcontrol);
+        struct device *wsa_dev = NULL;
+        struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+        if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+                return -EINVAL;
+
+        wsa_priv->wsa_spkrrecv = ucontrol->value.integer.value[0];
+
+        dev_dbg(component->dev, "%s:spkrrecv status = %d\n",
+                 __func__, wsa_priv->wsa_spkrrecv);
+
+        return 0;
+}
+
 static int lpass_cdc_wsa_macro_comp_mode_get(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
@@ -2239,6 +2292,9 @@ static int lpass_cdc_wsa_macro_soft_clip_enable_put(struct snd_kcontrol *kcontro
 }
 
 static const struct snd_kcontrol_new lpass_cdc_wsa_macro_snd_controls[] = {
+	SOC_ENUM_EXT("WSA SPKRRECV", lpass_cdc_wsa_macro_ear_spkrrecv_enum,
+			lpass_cdc_wsa_macro_ear_spkrrecv_get,
+			lpass_cdc_wsa_macro_ear_spkrrecv_put),
 	SOC_ENUM_EXT("GSM mode Enable", lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_enum,
 		     lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_func_get,
 		     lpass_cdc_wsa_macro_vbat_bcl_gsm_mode_func_put),
@@ -2659,10 +2715,10 @@ static const struct lpass_cdc_wsa_macro_reg_mask_val
 				lpass_cdc_wsa_macro_reg_init[] = {
 	{LPASS_CDC_WSA_BOOST0_BOOST_CFG1, 0x3F, 0x12},
 	{LPASS_CDC_WSA_BOOST0_BOOST_CFG2, 0x1C, 0x08},
-	{LPASS_CDC_WSA_COMPANDER0_CTL7, 0x1E, 0x0C},
+	{LPASS_CDC_WSA_COMPANDER0_CTL7, 0x1E, 0x18},
 	{LPASS_CDC_WSA_BOOST1_BOOST_CFG1, 0x3F, 0x12},
 	{LPASS_CDC_WSA_BOOST1_BOOST_CFG2, 0x1C, 0x08},
-	{LPASS_CDC_WSA_COMPANDER1_CTL7, 0x1E, 0x0C},
+	{LPASS_CDC_WSA_COMPANDER1_CTL7, 0x1E, 0x18},
 	{LPASS_CDC_WSA_BOOST0_BOOST_CTL, 0x70, 0x58},
 	{LPASS_CDC_WSA_BOOST1_BOOST_CTL, 0x70, 0x58},
 	{LPASS_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08},

+ 58 - 2
asoc/codecs/lpass-cdc/lpass-cdc-wsa2-macro.c

@@ -272,6 +272,7 @@ struct lpass_cdc_wsa2_macro_priv {
 	struct snd_soc_component *component;
 	int rx_0_count;
 	int rx_1_count;
+	int wsa_spkrrecv;
 	unsigned long active_ch_mask[LPASS_CDC_WSA2_MACRO_MAX_DAIS];
 	unsigned long active_ch_cnt[LPASS_CDC_WSA2_MACRO_MAX_DAIS];
 	int rx_port_value[LPASS_CDC_WSA2_MACRO_RX_MAX];
@@ -320,6 +321,10 @@ static const char * const lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_text[] = {
 	"OFF", "ON"
 };
 
+static const char *const lpass_cdc_wsa2_macro_ear_spkrrecv_text[] = {
+	"OFF", "ON"
+};
+
 static const char * const lpass_cdc_wsa2_macro_comp_mode_text[] = {
 	"G_21_DB", "G_19P5_DB", "G_18_DB", "G_16P5_DB", "G_15_DB",
 	"G_13P5_DB", "G_12_DB", "G_10P5_DB", "G_9_DB"
@@ -333,6 +338,8 @@ static const struct snd_kcontrol_new wsa2_int1_vbat_mix_switch[] = {
 	SOC_DAPM_SINGLE("WSA2 RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
 };
 
+static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa2_macro_ear_spkrrecv_enum,
+				lpass_cdc_wsa2_macro_ear_spkrrecv_text);
 static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_enum,
 			lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_text);
 static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa2_macro_comp_mode_enum,
@@ -1526,6 +1533,9 @@ static int lpass_cdc_wsa2_macro_enable_interpolator(struct snd_soc_dapm_widget *
 	u8 gain = 0;
 	u16 reg = 0;
 
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
 	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
 		return -EINVAL;
 
@@ -1577,8 +1587,14 @@ static int lpass_cdc_wsa2_macro_enable_interpolator(struct snd_soc_dapm_widget *
 
 		lpass_cdc_wsa2_macro_config_compander(component, w->shift, event);
 		lpass_cdc_wsa2_macro_config_softclip(component, w->shift, event);
+		if(wsa2_priv->wsa_spkrrecv)
+			snd_soc_component_update_bits(component,
+					LPASS_CDC_WSA2_RX0_RX_PATH_CFG1,
+					0x08, 0x00);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component,
+				LPASS_CDC_WSA2_RX0_RX_PATH_CFG1, 0x08, 0x08);
 		lpass_cdc_wsa2_macro_config_compander(component, w->shift, event);
 		lpass_cdc_wsa2_macro_config_softclip(component, w->shift, event);
 		lpass_cdc_wsa2_macro_enable_prim_interpolator(component, reg, event);
@@ -2027,6 +2043,43 @@ static int lpass_cdc_wsa2_macro_set_compander(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+static int lpass_cdc_wsa2_macro_ear_spkrrecv_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa2_priv->wsa_spkrrecv;
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		 __func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_ear_spkrrecv_put(struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_value *ucontrol)
+{
+        struct snd_soc_component *component =
+                                snd_soc_kcontrol_component(kcontrol);
+        struct device *wsa2_dev = NULL;
+        struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+        if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+                return -EINVAL;
+        wsa2_priv->wsa_spkrrecv = ucontrol->value.integer.value[0];
+
+        dev_dbg(component->dev, "%s:spkrrecv status = %d\n",
+                 __func__, wsa2_priv->wsa_spkrrecv);
+
+        return 0;
+}
+
 static int lpass_cdc_wsa2_macro_comp_mode_get(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
@@ -2238,6 +2291,9 @@ static int lpass_cdc_wsa2_macro_soft_clip_enable_put(struct snd_kcontrol *kcontr
 }
 
 static const struct snd_kcontrol_new lpass_cdc_wsa2_macro_snd_controls[] = {
+	SOC_ENUM_EXT("WSA2 SPKRRECV", lpass_cdc_wsa2_macro_ear_spkrrecv_enum,
+			lpass_cdc_wsa2_macro_ear_spkrrecv_get,
+			lpass_cdc_wsa2_macro_ear_spkrrecv_put),
 	SOC_ENUM_EXT("WSA2_GSM mode Enable", lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_enum,
 		     lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_func_get,
 		     lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_func_put),
@@ -2658,10 +2714,10 @@ static const struct lpass_cdc_wsa2_macro_reg_mask_val
 				lpass_cdc_wsa2_macro_reg_init[] = {
 	{LPASS_CDC_WSA2_BOOST0_BOOST_CFG1, 0x3F, 0x12},
 	{LPASS_CDC_WSA2_BOOST0_BOOST_CFG2, 0x1C, 0x08},
-	{LPASS_CDC_WSA2_COMPANDER0_CTL7, 0x1E, 0x0C},
+	{LPASS_CDC_WSA2_COMPANDER0_CTL7, 0x1E, 0x18},
 	{LPASS_CDC_WSA2_BOOST1_BOOST_CFG1, 0x3F, 0x12},
 	{LPASS_CDC_WSA2_BOOST1_BOOST_CFG2, 0x1C, 0x08},
-	{LPASS_CDC_WSA2_COMPANDER1_CTL7, 0x1E, 0x0C},
+	{LPASS_CDC_WSA2_COMPANDER1_CTL7, 0x1E, 0x18},
 	{LPASS_CDC_WSA2_BOOST0_BOOST_CTL, 0x70, 0x58},
 	{LPASS_CDC_WSA2_BOOST1_BOOST_CTL, 0x70, 0x58},
 	{LPASS_CDC_WSA2_RX0_RX_PATH_CFG1, 0x08, 0x08},

+ 32 - 2
asoc/codecs/wsa883x/wsa883x.c

@@ -530,6 +530,12 @@ static const char * const wsa_dev_mode_text[] = {
 	"speaker", "receiver", "ultrasound"
 };
 
+enum {
+	SPEAKER,
+	RECEIVER,
+	ULTRASOUND,
+};
+
 static const struct soc_enum wsa_dev_mode_enum =
 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wsa_dev_mode_text), wsa_dev_mode_text);
 
@@ -1035,6 +1041,8 @@ static int wsa883x_enable_swr_dac_port(struct snd_soc_dapm_widget *w,
 				&port_id[num_port], &num_ch[num_port],
 				&ch_mask[num_port], &ch_rate[num_port],
 				&port_type[num_port]);
+		if (wsa883x->dev_mode == RECEIVER)
+			ch_rate[num_port] = SWR_CLK_RATE_4P8MHZ;
 		++num_port;
 
 		if (wsa883x->comp_enable) {
@@ -1107,13 +1115,35 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w,
 	dev_dbg(component->dev, "%s: %s %d\n", __func__, w->name, event);
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
+		if (wsa883x->dev_mode == RECEIVER) {
+			snd_soc_component_update_bits(component,
+						WSA883X_CDC_PATH_MODE,
+						0x02, 0x02);
+			snd_soc_component_update_bits(component,
+						WSA883X_SPKR_PWM_CLK_CTL,
+						0x08, 0x08);
+			snd_soc_component_update_bits(component,
+						WSA883X_DRE_CTL_0,
+						0xF0, 0x00);
+		} else if (wsa883x->dev_mode == SPEAKER) {
+			snd_soc_component_update_bits(component,
+						WSA883X_CDC_PATH_MODE,
+						0x02, 0x00);
+			snd_soc_component_update_bits(component,
+						WSA883X_SPKR_PWM_CLK_CTL,
+						0x08, 0x00);
+			snd_soc_component_update_bits(component,
+						WSA883X_DRE_CTL_0,
+						0xF0, 0x90);
+		}
 		swr_slvdev_datapath_control(wsa883x->swr_slave,
 					    wsa883x->swr_slave->dev_num,
 					    true);
 		/* Added delay as per HW sequence */
 		usleep_range(250, 300);
-		snd_soc_component_update_bits(component, WSA883X_DRE_CTL_1,
-						0x01, 0x01);
+		snd_soc_component_update_bits(component,
+					WSA883X_DRE_CTL_1,
+					0x01, 0x01);
 		/* Added delay as per HW sequence */
 		usleep_range(250, 300);
 

+ 14 - 1
asoc/lahaina-port-config.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _LAHAINA_PORT_CONFIG
@@ -27,6 +27,17 @@ static struct port_params wsa_frame_params_default[SWR_MSTR_PORT_LEN] = {
 	{15, 10, 0,    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
 };
 
+static struct port_params wsa_frame_params_receiver[SWR_MSTR_PORT_LEN] = {
+	{3,  1,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
+	{31, 2,  3,    0xFF, 0xFF, 0xFF, 0x1, 0xFF, 0xFF, 0x00, 0x00},
+	{63, 7,  0,   0xFF, 0xFF, 0xFF,  0xFF, 0xFF, 0xFF, 0x00, 0x00},
+	{3,  6,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
+	{31, 18, 0,    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
+	{63, 13, 31,   0xFF, 0xFF, 0xFF,  0x1, 0xFF, 0xFF, 0x00, 0x00},
+	{15, 3,  0,    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
+	{15, 10, 0,    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
+};
+
 static struct port_params rx_frame_params_dsd[SWR_MSTR_PORT_LEN] = {
 	{3,  0,  0,  0xFF, 0xFF, 1,    0xFF, 0xFF, 1, 0x00, 0x00},
 	{31, 0,  0,  3,    6,    7,    0,    0xFF, 0, 0x00, 0x00},
@@ -60,6 +71,7 @@ static struct swr_mstr_port_map sm_port_map[] = {
 	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
 	{RX_MACRO, SWR_UC2, rx_frame_params_44p1KHz},
 	{WSA_MACRO, SWR_UC0, wsa_frame_params_default},
+	{WSA_MACRO, SWR_UC1, wsa_frame_params_receiver},
 };
 
 static struct swr_mstr_port_map sm_port_map_shima[] = {
@@ -67,6 +79,7 @@ static struct swr_mstr_port_map sm_port_map_shima[] = {
 	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
 	{RX_MACRO, SWR_UC2, rx_frame_params_44p1KHz},
 	{WSA_MACRO, SWR_UC0, wsa_frame_params_default},
+	{WSA_MACRO, SWR_UC1, wsa_frame_params_receiver},
 };
 
 #endif /* _LAHAINA_PORT_CONFIG */

+ 13 - 0
asoc/waipio-port-config.h

@@ -26,6 +26,17 @@ static struct port_params wsa_frame_params_default[SWR_MSTR_PORT_LEN] = {
 	{15, 10, 0,    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
 };
 
+static struct port_params wsa_frame_params_receiver[SWR_MSTR_PORT_LEN] = {
+	{3,  1,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
+	{31, 2,  3,    0xFF, 0xFF, 0xFF, 0x1, 0xFF, 0xFF, 0x00, 0x00},
+	{63, 7,  0,   0xFF, 0xFF, 0xFF,  0xFF, 0xFF, 0xFF, 0x00, 0x00},
+	{3,  6,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
+	{31, 18, 0,    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
+	{63, 13, 31,   0xFF, 0xFF, 0xFF,  0x1, 0xFF, 0xFF, 0x00, 0x00},
+	{15, 3,  0,    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
+	{15, 10, 0,    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
+};
+
 static struct port_params rx_frame_params_dsd[SWR_MSTR_PORT_LEN] = {
 	{3,  0,  0,  0xFF, 0xFF, 1,    0xFF, 0xFF, 1, 0x00, 0x00},
 	{31, 0,  0,  3,    6,    7,    0,    0xFF, 0, 0x00, 0x02},
@@ -59,7 +70,9 @@ static struct swr_mstr_port_map sm_port_map[] = {
 	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
 	{RX_MACRO, SWR_UC2, rx_frame_params_44p1KHz},
 	{WSA_MACRO, SWR_UC0, wsa_frame_params_default},
+	{WSA_MACRO, SWR_UC1, wsa_frame_params_receiver},
 	{WSA2_MACRO, SWR_UC0, wsa_frame_params_default},
+	{WSA2_MACRO, SWR_UC1, wsa_frame_params_receiver},
 };
 
 #endif /* _WAIPIO_PORT_CONFIG */

+ 18 - 2
soc/swr-mstr-ctrl.c

@@ -40,6 +40,8 @@
 
 #define SWRM_DSD_PARAMS_PORT 4
 
+#define SWRM_SPK_DAC_PORT_RECEIVER 0
+
 #define SWR_BROADCAST_CMD_ID            0x0F
 #define SWR_DEV_ID_MASK			0xFFFFFFFFFFFF
 #define SWR_REG_VAL_PACK(data, dev, id, reg)	\
@@ -748,6 +750,12 @@ static int swrm_get_port_config(struct swr_mstr_ctrl *swrm)
 		(swrm->bus_clk == SWR_CLK_RATE_11P2896MHZ))
 		usecase = 2;
 
+	if ((swrm->master_id == MASTER_ID_WSA) &&
+	    swrm->mport_cfg[SWRM_SPK_DAC_PORT_RECEIVER].port_en &&
+	    swrm->mport_cfg[SWRM_SPK_DAC_PORT_RECEIVER].ch_rate ==
+			SWR_CLK_RATE_4P8MHZ)
+		usecase = 1;
+
 	params = swrm->port_param[usecase];
 	copy_port_tables(swrm, params);
 
@@ -1522,8 +1530,7 @@ static void swrm_copy_data_port_config(struct swr_master *master, u8 bank)
 						port_req->dev_num, 0x00,
 						SWRS_DP_BLOCK_CONTROL_1(slv_id));
 			}
-			if (port_req->blk_pack_mode != SWR_INVALID_PARAM
-					&& swrm->master_id != MASTER_ID_WSA) {
+			if (port_req->blk_pack_mode != SWR_INVALID_PARAM) {
 				reg[len] = SWRM_CMD_FIFO_WR_CMD;
 				val[len++] =
 					SWR_REG_VAL_PACK(
@@ -1858,6 +1865,15 @@ static int swrm_connect_port(struct swr_master *master,
 				swrm->dynamic_port_map_supported) {
 			mport->ch_rate += portinfo->ch_rate[i];
 			swrm_update_bus_clk(swrm);
+		} else {
+			/*
+			 * Fallback to assign slave port ch_rate
+			 * as master port uses same ch_rate as slave
+			 * unlike soundwire TX master ports where
+			 * unified ports and multiple slave port
+			 * channels can attach to same master port
+			 */
+			mport->ch_rate = portinfo->ch_rate[i];
 		}
 	}
 	master->num_port += portinfo->num_port;