|
@@ -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 @@ int wsa881x_get_temp(struct thermal_zone_device *thermal,
|
|
|
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, ®);
|
|
@@ -108,6 +123,8 @@ temp_retry:
|
|
|
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 @@ static struct thermal_zone_device_ops wsa881x_thermal_ops = {
|
|
|
.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 @@ int wsa881x_init_thermal(struct wsa881x_tz_priv *tz_pdata)
|
|
|
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);
|
|
|
}
|