Merge "ASoC: wsa881x: Avoid query temp during suspend" into audio-drivers.lnx.3.0
This commit is contained in:
commit
fbc1f4eb40
3 changed files with 79 additions and 2 deletions
|
@ -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 @@ int wsa881x_get_temp(struct thermal_zone_device *thermal,
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -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 wsa881x_tz_priv {
|
|||
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);
|
||||
|
|
|
@ -200,12 +200,40 @@ static int wsa881x_set_mute(struct snd_kcontrol *kcontrol,
|
|||
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)
|
||||
|
|
Loading…
Add table
Reference in a new issue