ASoC: Add support for automatically going to BIAS_OFF on suspend
There is a substantial amount of drivers that in go to SND_SOC_BIAS_OFF on suspend and go back to SND_SOC_BIAS_SUSPEND on resume (Often this is even the only thing done in the suspend and resume handlers). This patch introduces a new suspend_bias_off flag, which when set by a driver will let the ASoC core automatically put the device's DAPM context at the SND_SOC_BIAS_OFF level during suspend. Once the device is resumed the DAPM context will go back to SND_SOC_BIAS_STANDBY (if the context is idle, otherwise to SND_SOC_BIAS_ON). This will allow us to remove a fair bit of duplicated code from the drivers. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
1c325f771a
commit
86dbf2ac6f
|
@ -587,7 +587,8 @@ struct snd_soc_dapm_context {
|
||||||
enum snd_soc_bias_level suspend_bias_level;
|
enum snd_soc_bias_level suspend_bias_level;
|
||||||
struct delayed_work delayed_work;
|
struct delayed_work delayed_work;
|
||||||
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
|
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
|
||||||
|
/* Go to BIAS_OFF in suspend if the DAPM context is idle */
|
||||||
|
unsigned int suspend_bias_off:1;
|
||||||
void (*seq_notifier)(struct snd_soc_dapm_context *,
|
void (*seq_notifier)(struct snd_soc_dapm_context *,
|
||||||
enum snd_soc_dapm_type, int);
|
enum snd_soc_dapm_type, int);
|
||||||
|
|
||||||
|
|
|
@ -848,6 +848,7 @@ struct snd_soc_codec_driver {
|
||||||
int (*set_bias_level)(struct snd_soc_codec *,
|
int (*set_bias_level)(struct snd_soc_codec *,
|
||||||
enum snd_soc_bias_level level);
|
enum snd_soc_bias_level level);
|
||||||
bool idle_bias_off;
|
bool idle_bias_off;
|
||||||
|
bool suspend_bias_off;
|
||||||
|
|
||||||
void (*seq_notifier)(struct snd_soc_dapm_context *,
|
void (*seq_notifier)(struct snd_soc_dapm_context *,
|
||||||
enum snd_soc_dapm_type, int);
|
enum snd_soc_dapm_type, int);
|
||||||
|
|
|
@ -4402,6 +4402,7 @@ int snd_soc_register_codec(struct device *dev,
|
||||||
codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time;
|
codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time;
|
||||||
codec->dapm.codec = codec;
|
codec->dapm.codec = codec;
|
||||||
codec->dapm.idle_bias_off = codec_drv->idle_bias_off;
|
codec->dapm.idle_bias_off = codec_drv->idle_bias_off;
|
||||||
|
codec->dapm.suspend_bias_off = codec_drv->suspend_bias_off;
|
||||||
if (codec_drv->seq_notifier)
|
if (codec_drv->seq_notifier)
|
||||||
codec->dapm.seq_notifier = codec_drv->seq_notifier;
|
codec->dapm.seq_notifier = codec_drv->seq_notifier;
|
||||||
if (codec_drv->set_bias_level)
|
if (codec_drv->set_bias_level)
|
||||||
|
|
|
@ -1683,6 +1683,22 @@ static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm)
|
||||||
|
{
|
||||||
|
if (dapm->idle_bias_off)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
switch (snd_power_get_state(dapm->card->snd_card)) {
|
||||||
|
case SNDRV_CTL_POWER_D3hot:
|
||||||
|
case SNDRV_CTL_POWER_D3cold:
|
||||||
|
return dapm->suspend_bias_off;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan each dapm widget for complete audio path.
|
* Scan each dapm widget for complete audio path.
|
||||||
* A complete path is a route that has valid endpoints i.e.:-
|
* A complete path is a route that has valid endpoints i.e.:-
|
||||||
|
@ -1706,7 +1722,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
|
||||||
trace_snd_soc_dapm_start(card);
|
trace_snd_soc_dapm_start(card);
|
||||||
|
|
||||||
list_for_each_entry(d, &card->dapm_list, list) {
|
list_for_each_entry(d, &card->dapm_list, list) {
|
||||||
if (d->idle_bias_off)
|
if (dapm_idle_bias_off(d))
|
||||||
d->target_bias_level = SND_SOC_BIAS_OFF;
|
d->target_bias_level = SND_SOC_BIAS_OFF;
|
||||||
else
|
else
|
||||||
d->target_bias_level = SND_SOC_BIAS_STANDBY;
|
d->target_bias_level = SND_SOC_BIAS_STANDBY;
|
||||||
|
@ -1772,7 +1788,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
|
||||||
if (d->target_bias_level > bias)
|
if (d->target_bias_level > bias)
|
||||||
bias = d->target_bias_level;
|
bias = d->target_bias_level;
|
||||||
list_for_each_entry(d, &card->dapm_list, list)
|
list_for_each_entry(d, &card->dapm_list, list)
|
||||||
if (!d->idle_bias_off)
|
if (!dapm_idle_bias_off(d))
|
||||||
d->target_bias_level = bias;
|
d->target_bias_level = bias;
|
||||||
|
|
||||||
trace_snd_soc_dapm_walk_done(card);
|
trace_snd_soc_dapm_walk_done(card);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user