Merge "asoc: codecs: add wcd9360 objects for kernel build option" into audio-drivers.lnx.3.0
diff --git a/asoc/codecs/wsa881x-temp-sensor.c b/asoc/codecs/wsa881x-temp-sensor.c
index 5ab0ecf..b2ed963 100644
--- a/asoc/codecs/wsa881x-temp-sensor.c
+++ b/asoc/codecs/wsa881x-temp-sensor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017-2018 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,6 +12,7 @@
 
 #include <linux/bitops.h>
 #include <linux/kernel.h>
+#include <linux/suspend.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/thermal.h>
@@ -61,6 +62,20 @@
 		pr_err("%s: pdata is NULL\n", __func__);
 		return -EINVAL;
 	}
+	if (atomic_cmpxchg(&pdata->is_suspend_spk, 1, 0)) {
+		/*
+		 * get_temp query happens as part of POST_PM_SUSPEND
+		 * from thermal core. To avoid calls to slimbus
+		 * as part of this thermal query, return default temp
+		 * and reset the suspend flag.
+		 */
+		if (!pdata->t0_init) {
+			if (temp)
+				*temp = pdata->curr_temp;
+			return 0;
+		}
+	}
+
 temp_retry:
 	if (pdata->wsa_temp_reg_read) {
 		ret = pdata->wsa_temp_reg_read(codec, &reg);
@@ -108,6 +123,8 @@
 			goto temp_retry;
 		}
 	}
+	pdata->curr_temp = temp_val;
+
 	if (temp)
 		*temp = temp_val;
 	pr_debug("%s: t0 measured: %d dmeas = %d, d1 = %d, d2 = %d\n",
@@ -120,6 +137,23 @@
 	.get_temp = wsa881x_get_temp,
 };
 
+
+static int wsa881x_pm_notify(struct notifier_block *nb,
+				unsigned long mode, void *_unused)
+{
+	struct wsa881x_tz_priv *pdata =
+			container_of(nb, struct wsa881x_tz_priv, pm_nb);
+
+	switch (mode) {
+	case PM_SUSPEND_PREPARE:
+		atomic_set(&pdata->is_suspend_spk, 1);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
 int wsa881x_init_thermal(struct wsa881x_tz_priv *tz_pdata)
 {
 	struct thermal_zone_device *tz_dev;
@@ -137,12 +171,23 @@
 		return -EINVAL;
 	}
 	tz_pdata->tz_dev = tz_dev;
+	tz_pdata->pm_nb.notifier_call = wsa881x_pm_notify;
+	register_pm_notifier(&tz_pdata->pm_nb);
+	atomic_set(&tz_pdata->is_suspend_spk, 0);
+
 	return 0;
 }
 EXPORT_SYMBOL(wsa881x_init_thermal);
 
 void wsa881x_deinit_thermal(struct thermal_zone_device *tz_dev)
 {
+	struct wsa881x_tz_priv *pdata;
+
+	if (tz_dev && tz_dev->devdata) {
+		pdata = tz_dev->devdata;
+		if (pdata)
+			unregister_pm_notifier(&pdata->pm_nb);
+	}
 	if (tz_dev)
 		thermal_zone_device_unregister(tz_dev);
 }
diff --git a/asoc/codecs/wsa881x-temp-sensor.h b/asoc/codecs/wsa881x-temp-sensor.h
index d6c1eb7..26828b7 100644
--- a/asoc/codecs/wsa881x-temp-sensor.h
+++ b/asoc/codecs/wsa881x-temp-sensor.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2018 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -31,6 +31,10 @@
 	struct wsa_temp_register *wsa_temp_reg;
 	char name[80];
 	wsa_temp_register_read wsa_temp_reg_read;
+	struct notifier_block pm_nb;
+	atomic_t is_suspend_spk;
+	int t0_init;
+	int curr_temp;
 };
 
 int wsa881x_get_temp(struct thermal_zone_device *tz_dev, int *temp);
diff --git a/asoc/codecs/wsa881x.c b/asoc/codecs/wsa881x.c
index 0755cdc..2ef9e0a 100644
--- a/asoc/codecs/wsa881x.c
+++ b/asoc/codecs/wsa881x.c
@@ -200,12 +200,40 @@
 	return 0;
 }
 
+static int wsa881x_get_t0_init(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct wsa881x_priv *wsa881x = snd_soc_codec_get_drvdata(codec);
+	struct wsa881x_tz_priv *pdata = &wsa881x->tz_pdata;
+
+	ucontrol->value.integer.value[0] = pdata->t0_init;
+	dev_dbg(codec->dev, "%s: t0 init %d\n", __func__, pdata->t0_init);
+
+	return 0;
+}
+
+static int wsa881x_set_t0_init(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct wsa881x_priv *wsa881x = snd_soc_codec_get_drvdata(codec);
+	struct wsa881x_tz_priv *pdata = &wsa881x->tz_pdata;
+
+	pdata->t0_init = ucontrol->value.integer.value[0];
+	dev_dbg(codec->dev, "%s: t0 init %d\n", __func__, pdata->t0_init);
+
+	return 0;
+}
 
 static const struct snd_kcontrol_new wsa_snd_controls[] = {
 	SOC_ENUM_EXT("WSA PA Gain", wsa_pa_gain_enum,
 		     wsa_pa_gain_get, wsa_pa_gain_put),
 	SOC_SINGLE_EXT("WSA PA Mute", SND_SOC_NOPM, 0, 1, 0,
 		wsa881x_get_mute, wsa881x_set_mute),
+	SOC_SINGLE_EXT("WSA T0 Init", SND_SOC_NOPM, 0, 1, 0,
+		wsa881x_get_t0_init, wsa881x_set_t0_init),
 };
 
 static int codec_debug_open(struct inode *inode, struct file *file)