Commit c376e2c7 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Implement snd_hda_power_sync() helper function

Added a new helper function snd_hda_power_sync() to trigger the
power-saving manually.  It's an inline function call to
snd_hda_power_save() helper function.

Together with this addition, snd_hda_power_up*() and
snd_hda_power_down() functions are inlined to a call of the same
snd_hda_power_save() helper function.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent b244d335
...@@ -4411,20 +4411,16 @@ void snd_hda_update_power_acct(struct hda_codec *codec) ...@@ -4411,20 +4411,16 @@ void snd_hda_update_power_acct(struct hda_codec *codec)
/* Transition to powered up, if wait_power_down then wait for a pending /* Transition to powered up, if wait_power_down then wait for a pending
* transition to D3 to complete. A pending D3 transition is indicated * transition to D3 to complete. A pending D3 transition is indicated
* with power_transition == -1. */ * with power_transition == -1. */
/* call this with codec->power_lock held! */
static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
{ {
struct hda_bus *bus = codec->bus; struct hda_bus *bus = codec->bus;
spin_lock(&codec->power_lock);
codec->power_count++;
trace_hda_power_count(codec);
/* Return if power_on or transitioning to power_on, unless currently /* Return if power_on or transitioning to power_on, unless currently
* powering down. */ * powering down. */
if ((codec->power_on || codec->power_transition > 0) && if ((codec->power_on || codec->power_transition > 0) &&
!(wait_power_down && codec->power_transition < 0)) { !(wait_power_down && codec->power_transition < 0))
spin_unlock(&codec->power_lock);
return; return;
}
spin_unlock(&codec->power_lock); spin_unlock(&codec->power_lock);
cancel_delayed_work_sync(&codec->power_work); cancel_delayed_work_sync(&codec->power_work);
...@@ -4433,10 +4429,9 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) ...@@ -4433,10 +4429,9 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
/* If the power down delayed work was cancelled above before starting, /* If the power down delayed work was cancelled above before starting,
* then there is no need to go through power up here. * then there is no need to go through power up here.
*/ */
if (codec->power_on) { if (codec->power_on)
spin_unlock(&codec->power_lock);
return; return;
}
trace_hda_power_up(codec); trace_hda_power_up(codec);
snd_hda_update_power_acct(codec); snd_hda_update_power_acct(codec);
codec->power_on = 1; codec->power_on = 1;
...@@ -4450,66 +4445,45 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) ...@@ -4450,66 +4445,45 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
spin_lock(&codec->power_lock); spin_lock(&codec->power_lock);
codec->power_transition = 0; codec->power_transition = 0;
spin_unlock(&codec->power_lock);
} }
/** #define power_save(codec) \
* snd_hda_power_up - Power-up the codec ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
* @codec: HD-audio codec
*
* Increment the power-up counter and power up the hardware really when
* not turned on yet.
*/
void snd_hda_power_up(struct hda_codec *codec)
{
__snd_hda_power_up(codec, false);
}
EXPORT_SYMBOL_HDA(snd_hda_power_up);
/** /* Transition to powered down */
* snd_hda_power_up_d3wait - Power-up the codec after waiting for any pending static void __snd_hda_power_down(struct hda_codec *codec)
* D3 transition to complete. This differs from snd_hda_power_up() when
* power_transition == -1. snd_hda_power_up sees this case as a nop,
* snd_hda_power_up_d3wait waits for the D3 transition to complete then powers
* back up.
* @codec: HD-audio codec
*
* Cancel any power down operation hapenning on the work queue, then power up.
*/
void snd_hda_power_up_d3wait(struct hda_codec *codec)
{ {
/* This will cancel and wait for pending power_work to complete. */ if (!codec->power_on || codec->power_count || codec->power_transition)
__snd_hda_power_up(codec, true); return;
}
EXPORT_SYMBOL_HDA(snd_hda_power_up_d3wait);
#define power_save(codec) \ if (power_save(codec)) {
((codec)->bus->power_save ? *(codec)->bus->power_save : 0) codec->power_transition = -1; /* avoid reentrance */
queue_delayed_work(codec->bus->workq, &codec->power_work,
msecs_to_jiffies(power_save(codec) * 1000));
}
}
/** /**
* snd_hda_power_down - Power-down the codec * snd_hda_power_save - Power-up/down/sync the codec
* @codec: HD-audio codec * @codec: HD-audio codec
* @delta: the counter delta to change
* *
* Decrement the power-up counter and schedules the power-off work if * Change the power-up counter via @delta, and power up or down the hardware
* the counter rearches to zero. * appropriately. For the power-down, queue to the delayed action.
* Passing zero to @delta means to synchronize the power state.
*/ */
void snd_hda_power_down(struct hda_codec *codec) void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait)
{ {
spin_lock(&codec->power_lock); spin_lock(&codec->power_lock);
--codec->power_count; codec->power_count += delta;
trace_hda_power_count(codec); trace_hda_power_count(codec);
if (!codec->power_on || codec->power_count || codec->power_transition) { if (delta > 0)
spin_unlock(&codec->power_lock); __snd_hda_power_up(codec, d3wait);
return; else
} __snd_hda_power_down(codec);
if (power_save(codec)) {
codec->power_transition = -1; /* avoid reentrance */
queue_delayed_work(codec->bus->workq, &codec->power_work,
msecs_to_jiffies(power_save(codec) * 1000));
}
spin_unlock(&codec->power_lock); spin_unlock(&codec->power_lock);
} }
EXPORT_SYMBOL_HDA(snd_hda_power_down); EXPORT_SYMBOL_HDA(snd_hda_power_save);
/** /**
* snd_hda_check_amp_list_power - Check the amp list and update the power * snd_hda_check_amp_list_power - Check the amp list and update the power
......
...@@ -1062,16 +1062,64 @@ const char *snd_hda_get_jack_location(u32 cfg); ...@@ -1062,16 +1062,64 @@ const char *snd_hda_get_jack_location(u32 cfg);
* power saving * power saving
*/ */
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
void snd_hda_power_up(struct hda_codec *codec); void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait);
void snd_hda_power_up_d3wait(struct hda_codec *codec);
void snd_hda_power_down(struct hda_codec *codec);
void snd_hda_update_power_acct(struct hda_codec *codec); void snd_hda_update_power_acct(struct hda_codec *codec);
#else #else
static inline void snd_hda_power_up(struct hda_codec *codec) {} static inline void snd_hda_power_save(struct hda_codec *codec, int delta,
static inline void snd_hda_power_up_d3wait(struct hda_codec *codec) {} bool d3wait) {}
static inline void snd_hda_power_down(struct hda_codec *codec) {}
#endif #endif
/**
* snd_hda_power_up - Power-up the codec
* @codec: HD-audio codec
*
* Increment the power-up counter and power up the hardware really when
* not turned on yet.
*/
static inline void snd_hda_power_up(struct hda_codec *codec)
{
snd_hda_power_save(codec, 1, false);
}
/**
* snd_hda_power_up_d3wait - Power-up the codec after waiting for any pending
* D3 transition to complete. This differs from snd_hda_power_up() when
* power_transition == -1. snd_hda_power_up sees this case as a nop,
* snd_hda_power_up_d3wait waits for the D3 transition to complete then powers
* back up.
* @codec: HD-audio codec
*
* Cancel any power down operation hapenning on the work queue, then power up.
*/
static inline void snd_hda_power_up_d3wait(struct hda_codec *codec)
{
snd_hda_power_save(codec, 1, true);
}
/**
* snd_hda_power_down - Power-down the codec
* @codec: HD-audio codec
*
* Decrement the power-up counter and schedules the power-off work if
* the counter rearches to zero.
*/
static inline void snd_hda_power_down(struct hda_codec *codec)
{
snd_hda_power_save(codec, -1, false);
}
/**
* snd_hda_power_sync - Synchronize the power-save status
* @codec: HD-audio codec
*
* Synchronize the actual power state with the power account;
* called when power_save parameter is changed
*/
static inline void snd_hda_power_sync(struct hda_codec *codec)
{
snd_hda_power_save(codec, 0, false);
}
#ifdef CONFIG_SND_HDA_PATCH_LOADER #ifdef CONFIG_SND_HDA_PATCH_LOADER
/* /*
* patch firmware * patch firmware
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment