Browse Source

Merge "ASoC: update swr dmic device down mechanism"

qctecmdr 4 years ago
parent
commit
1b53e55fd0

+ 35 - 44
asoc/codecs/swr-dmic.c

@@ -31,6 +31,7 @@
 #include "swr-dmic.h"
 
 #define NUM_ATTEMPTS 5
+#define SWRS_SCP_CONTROL    0x44
 
 static int swr_master_channel_map[] = {
 	ZERO,
@@ -66,6 +67,7 @@ struct swr_dmic_priv {
 	int is_en_supply;
 	int port_type;
 	u8 tx_master_port_map[SWR_DMIC_MAX_PORTS];
+	struct notifier_block nblock;
 };
 
 const char *codec_name_list[] = {
@@ -245,38 +247,6 @@ static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w,
 	return ret;
 }
 
-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_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 wname: %s event: %d\n", __func__,
-		w->name, event);
-
-	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;
-	}
-
-	if (ret)
-		dev_dbg(component->dev, "%s wname: %s event: %d ret : %d\n",
-			__func__, w->name, event, ret);
-
-	return ret;
-}
-
 static const char * const tx_master_port_text[] = {
 	"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",
@@ -306,10 +276,6 @@ static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = {
 
 	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_OUT_DRV_E("SMIC_PORT_EN", SND_SOC_NOPM, 0, 0, NULL, 0,
 				swr_dmic_port_enable,
 				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -317,7 +283,6 @@ static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = {
 };
 
 static const struct snd_soc_dapm_route swr_dmic_audio_map[] = {
-	{"SWR_DMIC", NULL, "SMIC_SUPPLY"},
 	{"SWR_DMIC_MIXER", "Switch", "SWR_DMIC"},
 	{"SMIC_PORT_EN", NULL, "SWR_DMIC_MIXER"},
 	{"SWR_DMIC_OUTPUT", NULL, "SMIC_PORT_EN"},
@@ -393,6 +358,8 @@ static int enable_wcd_codec_supply(struct swr_dmic_priv *swr_dmic, bool enable)
 		pr_err("%s: component is NULL\n", __func__);
 		return -EINVAL;
 	}
+	dev_dbg(component->dev, "%s: supply %d micbias: %d enable: %d\n",
+		__func__, swr_dmic->is_en_supply, micb_num, enable);
 
 	if (enable)
 		rc = wcd938x_codec_force_enable_micbias_v2(component,
@@ -441,6 +408,29 @@ static struct snd_soc_dai_driver swr_dmic_dai[] = {
 	},
 };
 
+static int swr_dmic_event_notify(struct notifier_block *block,
+				unsigned long val,
+				void *data)
+{
+	u16 event = (val & 0xffff);
+	int ret = 0;
+	struct swr_dmic_priv *swr_dmic = container_of(block,
+					struct swr_dmic_priv,
+					nblock);
+	switch (event) {
+	case WCD938X_EVT_SSR_DOWN:
+		ret = swr_dmic_down(swr_dmic->swr_slave);
+		break;
+	case WCD938X_EVT_SSR_UP:
+		ret = swr_dmic_up(swr_dmic->swr_slave);
+		if (!ret)
+			ret = swr_dmic_reset(swr_dmic->swr_slave);
+		break;
+	}
+
+	return ret;
+}
+
 static int swr_dmic_probe(struct swr_device *pdev)
 {
 	int ret = 0;
@@ -526,7 +516,7 @@ static int swr_dmic_probe(struct swr_device *pdev)
 			"%s get devnum %d for dev addr %llx failed\n",
 			__func__, swr_devnum, pdev->addr);
 		ret = -EPROBE_DEFER;
-		goto err;
+		goto dev_err;
 	}
 	pdev->dev_num = swr_devnum;
 
@@ -596,10 +586,9 @@ static int swr_dmic_probe(struct swr_device *pdev)
 			strlen(swr_dmic_name_prefix_of) + 1);
 	component->name_prefix = prefix_name;
 
-	if (swr_dmic->is_en_supply == 1) {
-		enable_wcd_codec_supply(swr_dmic, false);
-		--swr_dmic->is_en_supply;
-	}
+	swr_dmic->nblock.notifier_call = swr_dmic_event_notify;
+	wcd938x_swr_dmic_register_notifier(swr_dmic->supply_component,
+					&swr_dmic->nblock, true);
 
 	return 0;
 
@@ -624,7 +613,10 @@ static int swr_dmic_remove(struct swr_device *pdev)
 		dev_err(&pdev->dev, "%s: swr_dmic is NULL\n", __func__);
 		return -EINVAL;
 	}
-
+	if (swr_dmic->is_en_supply == 1) {
+		enable_wcd_codec_supply(swr_dmic, false);
+		--swr_dmic->is_en_supply;
+	}
 	snd_soc_unregister_component(&pdev->dev);
 	swr_set_dev_data(pdev, NULL);
 	return 0;
@@ -743,7 +735,6 @@ static struct swr_driver swr_dmic_driver = {
 	.probe = swr_dmic_probe,
 	.remove = swr_dmic_remove,
 	.id_table = swr_dmic_id,
-	.device_down = swr_dmic_down,
 };
 
 static int __init swr_dmic_init(void)

+ 3 - 0
asoc/codecs/wcd938x/internal.h

@@ -106,6 +106,9 @@ struct wcd938x_priv {
 	bool dev_up;
 	u8 tx_master_ch_map[WCD938X_MAX_SLAVE_CH_TYPES];
 	bool usbc_hs_status;
+	/* wcd to swr dmic notification */
+	bool notify_swr_dmic;
+	struct blocking_notifier_head notifier;
 };
 
 struct wcd938x_micbias_setting {

+ 46 - 2
asoc/codecs/wcd938x/wcd938x.c

@@ -2033,6 +2033,27 @@ static bool get_usbc_hs_status(struct snd_soc_component *component,
 	return false;
 }
 
+int wcd938x_swr_dmic_register_notifier(struct snd_soc_component *component,
+					struct notifier_block *nblock,
+					bool enable)
+{
+	struct wcd938x_priv *wcd938x_priv;
+	if(NULL == component) {
+		pr_err("%s: wcd938x component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	wcd938x_priv = snd_soc_component_get_drvdata(component);
+	wcd938x_priv->notify_swr_dmic = enable;
+	if (enable)
+		return blocking_notifier_chain_register(&wcd938x_priv->notifier,
+							nblock);
+	else
+		return blocking_notifier_chain_unregister(
+				&wcd938x_priv->notifier, nblock);
+}
+EXPORT_SYMBOL(wcd938x_swr_dmic_register_notifier);
+
 static int wcd938x_event_notify(struct notifier_block *block,
 				unsigned long val,
 				void *data)
@@ -2080,6 +2101,10 @@ static int wcd938x_event_notify(struct notifier_block *block,
 		break;
 	case BOLERO_WCD_EVT_SSR_DOWN:
 		wcd938x->dev_up = false;
+		if(wcd938x->notify_swr_dmic)
+			blocking_notifier_call_chain(&wcd938x->notifier,
+						     WCD938X_EVT_SSR_DOWN,
+						     NULL);
 		wcd938x->mbhc->wcd_mbhc.deinit_in_progress = true;
 		wcd938x->mbhc->wcd_mbhc.plug_before_ssr =
 					wcd938x->mbhc->wcd_mbhc.current_plug;
@@ -2113,6 +2138,10 @@ static int wcd938x_event_notify(struct notifier_block *block,
 		}
 		wcd938x->mbhc->wcd_mbhc.deinit_in_progress = false;
 		wcd938x->dev_up = true;
+		if(wcd938x->notify_swr_dmic)
+			blocking_notifier_call_chain(&wcd938x->notifier,
+						     WCD938X_EVT_SSR_UP,
+						     NULL);
 		break;
 	case BOLERO_WCD_EVT_CLK_NOTIFY:
 		snd_soc_component_update_bits(component,
@@ -2296,6 +2325,9 @@ static int wcd938x_enable_micbias(struct wcd938x_priv *wcd938x,
 		return -EINVAL;
 	};
 
+	pr_debug("%s: req: %d micb_num: %d  micb_ref: %d pullup_ref: %d\n",
+		__func__, req, micb_num, wcd938x->micb_ref[micb_index],
+		wcd938x->pullup_ref[micb_index]);
 	mutex_lock(&wcd938x->micb_lock);
 
 	switch (req) {
@@ -2360,6 +2392,8 @@ int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *component,
 					int event, int micb_num)
 {
 	struct wcd938x_priv *wcd938x_priv = NULL;
+	int ret = 0;
+	int micb_index = micb_num - 1;
 
 	if(NULL == component) {
 		pr_err("%s: wcd938x component is NULL\n", __func__);
@@ -2376,6 +2410,15 @@ int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *component,
 
 	wcd938x_priv = snd_soc_component_get_drvdata(component);
 
+	if (!wcd938x_priv->dev_up) {
+		if ((wcd938x_priv->pullup_ref[micb_index] > 0) &&
+			(event == SND_SOC_DAPM_POST_PMD)) {
+			wcd938x_priv->pullup_ref[micb_index]--;
+			ret = -ENODEV;
+			goto done;
+		}
+	}
+
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
 		wcd938x_wakeup(wcd938x_priv, true);
@@ -2389,7 +2432,8 @@ int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *component,
 		break;
 	}
 
-	return 0;
+done:
+	return ret;
 }
 EXPORT_SYMBOL(wcd938x_codec_force_enable_micbias_v2);
 
@@ -3728,7 +3772,6 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
 			return ret;
 		}
 	}
-	wcd938x->dev_up = true;
 	return ret;
 
 err_hwdep:
@@ -4088,6 +4131,7 @@ static int wcd938x_bind(struct device *dev)
 				__func__);
 		goto err_irq;
 	}
+	wcd938x->dev_up = true;
 
 	return ret;
 err_irq:

+ 9 - 0
asoc/codecs/wcd938x/wcd938x.h

@@ -17,6 +17,12 @@ enum {
 	WCD9385 = 5,
 };
 
+/* from WCD to SWR DMIC events */
+enum {
+	WCD938X_EVT_SSR_DOWN,
+	WCD938X_EVT_SSR_UP,
+};
+
 struct swr_slave_ch_map {
 	u8 ch_type;
 	u8 index;
@@ -62,6 +68,9 @@ int wcd938x_info_create_codec_entry(struct snd_info_entry *codec_root,
 int wcd938x_get_codec_variant(struct snd_soc_component *component);
 int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *wcd938x,
 					int event, int micb_num);
+int wcd938x_swr_dmic_register_notifier(struct snd_soc_component *wcd938x,
+                                        struct notifier_block *nblock,
+                                        bool enable);
 
 static inline int wcd938x_slave_get_master_ch_val(int ch)
 {