diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 81 |
1 files changed, 29 insertions, 52 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index f560051a949e..a6c34dc6dac1 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -4205,7 +4205,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) * * This function returns 0 if successful, or a negative error code. */ -int __devinit snd_hda_build_pcms(struct hda_bus *bus) +int snd_hda_build_pcms(struct hda_bus *bus) { struct hda_codec *codec; @@ -4432,19 +4432,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 D3 to complete. A pending D3 transition is indicated * 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) { struct hda_bus *bus = codec->bus; - spin_lock(&codec->power_lock); - codec->power_count++; /* Return if power_on or transitioning to power_on, unless currently * powering down. */ if ((codec->power_on || codec->power_transition > 0) && - !(wait_power_down && codec->power_transition < 0)) { - spin_unlock(&codec->power_lock); + !(wait_power_down && codec->power_transition < 0)) return; - } spin_unlock(&codec->power_lock); cancel_delayed_work_sync(&codec->power_work); @@ -4456,9 +4453,9 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) if (codec->power_on) { if (codec->power_transition < 0) codec->power_transition = 0; - spin_unlock(&codec->power_lock); return; } + trace_hda_power_up(codec); snd_hda_update_power_acct(codec); codec->power_on = 1; @@ -4472,65 +4469,45 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) spin_lock(&codec->power_lock); codec->power_transition = 0; - spin_unlock(&codec->power_lock); -} - -/** - * 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. - */ -void snd_hda_power_up(struct hda_codec *codec) -{ - __snd_hda_power_up(codec, false); -} -EXPORT_SYMBOL_HDA(snd_hda_power_up); - -/** - * 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. - */ -void snd_hda_power_up_d3wait(struct hda_codec *codec) -{ - /* This will cancel and wait for pending power_work to complete. */ - __snd_hda_power_up(codec, true); } -EXPORT_SYMBOL_HDA(snd_hda_power_up_d3wait); #define power_save(codec) \ ((codec)->bus->power_save ? *(codec)->bus->power_save : 0) -/** - * 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. - */ -void snd_hda_power_down(struct hda_codec *codec) +/* Transition to powered down */ +static void __snd_hda_power_down(struct hda_codec *codec) { - spin_lock(&codec->power_lock); - --codec->power_count; - if (!codec->power_on || codec->power_count || codec->power_transition) { - spin_unlock(&codec->power_lock); + if (!codec->power_on || codec->power_count || codec->power_transition) return; - } + 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)); } +} + +/** + * snd_hda_power_save - Power-up/down/sync the codec + * @codec: HD-audio codec + * @delta: the counter delta to change + * + * Change the power-up counter via @delta, and power up or down the hardware + * appropriately. For the power-down, queue to the delayed action. + * Passing zero to @delta means to synchronize the power state. + */ +void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait) +{ + spin_lock(&codec->power_lock); + codec->power_count += delta; + trace_hda_power_count(codec); + if (delta > 0) + __snd_hda_power_up(codec, d3wait); + else + __snd_hda_power_down(codec); 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 |