Merge branch 'topic/hda-sync-power' into for-next
Pull the HD-audio power sync fix. This is shared with ASoC. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
commit
bafeca673f
|
@ -146,6 +146,8 @@ int snd_hdac_codec_write(struct hdac_device *hdac, hda_nid_t nid,
|
||||||
int flags, unsigned int verb, unsigned int parm);
|
int flags, unsigned int verb, unsigned int parm);
|
||||||
bool snd_hdac_check_power_state(struct hdac_device *hdac,
|
bool snd_hdac_check_power_state(struct hdac_device *hdac,
|
||||||
hda_nid_t nid, unsigned int target_state);
|
hda_nid_t nid, unsigned int target_state);
|
||||||
|
unsigned int snd_hdac_sync_power_state(struct hdac_device *hdac,
|
||||||
|
hda_nid_t nid, unsigned int target_state);
|
||||||
/**
|
/**
|
||||||
* snd_hdac_read_parm - read a codec parameter
|
* snd_hdac_read_parm - read a codec parameter
|
||||||
* @codec: the codec object
|
* @codec: the codec object
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -1064,3 +1065,37 @@ bool snd_hdac_check_power_state(struct hdac_device *hdac,
|
||||||
return (state == target_state);
|
return (state == target_state);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_hdac_check_power_state);
|
EXPORT_SYMBOL_GPL(snd_hdac_check_power_state);
|
||||||
|
/**
|
||||||
|
* snd_hdac_sync_power_state - wait until actual power state matches
|
||||||
|
* with the target state
|
||||||
|
*
|
||||||
|
* @hdac: the HDAC device
|
||||||
|
* @nid: NID to send the command
|
||||||
|
* @target_state: target state to check for
|
||||||
|
*
|
||||||
|
* Return power state or PS_ERROR if codec rejects GET verb.
|
||||||
|
*/
|
||||||
|
unsigned int snd_hdac_sync_power_state(struct hdac_device *codec,
|
||||||
|
hda_nid_t nid, unsigned int power_state)
|
||||||
|
{
|
||||||
|
unsigned long end_time = jiffies + msecs_to_jiffies(500);
|
||||||
|
unsigned int state, actual_state, count;
|
||||||
|
|
||||||
|
for (count = 0; count < 500; count++) {
|
||||||
|
state = snd_hdac_codec_read(codec, nid, 0,
|
||||||
|
AC_VERB_GET_POWER_STATE, 0);
|
||||||
|
if (state & AC_PWRST_ERROR) {
|
||||||
|
msleep(20);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
actual_state = (state >> 4) & 0x0f;
|
||||||
|
if (actual_state == power_state)
|
||||||
|
break;
|
||||||
|
if (time_after_eq(jiffies, end_time))
|
||||||
|
break;
|
||||||
|
/* wait until the codec reachs to the target state */
|
||||||
|
msleep(1);
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_hdac_sync_power_state);
|
||||||
|
|
|
@ -2702,32 +2702,6 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_hda_codec_set_power_to_all);
|
EXPORT_SYMBOL_GPL(snd_hda_codec_set_power_to_all);
|
||||||
|
|
||||||
/*
|
|
||||||
* wait until the state is reached, returns the current state
|
|
||||||
*/
|
|
||||||
static unsigned int hda_sync_power_state(struct hda_codec *codec,
|
|
||||||
hda_nid_t fg,
|
|
||||||
unsigned int power_state)
|
|
||||||
{
|
|
||||||
unsigned long end_time = jiffies + msecs_to_jiffies(500);
|
|
||||||
unsigned int state, actual_state;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
state = snd_hda_codec_read(codec, fg, 0,
|
|
||||||
AC_VERB_GET_POWER_STATE, 0);
|
|
||||||
if (state & AC_PWRST_ERROR)
|
|
||||||
break;
|
|
||||||
actual_state = (state >> 4) & 0x0f;
|
|
||||||
if (actual_state == power_state)
|
|
||||||
break;
|
|
||||||
if (time_after_eq(jiffies, end_time))
|
|
||||||
break;
|
|
||||||
/* wait until the codec reachs to the target state */
|
|
||||||
msleep(1);
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_hda_codec_eapd_power_filter - A power filter callback for EAPD
|
* snd_hda_codec_eapd_power_filter - A power filter callback for EAPD
|
||||||
* @codec: the HDA codec
|
* @codec: the HDA codec
|
||||||
|
@ -2790,7 +2764,7 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
|
||||||
state);
|
state);
|
||||||
snd_hda_codec_set_power_to_all(codec, fg, power_state);
|
snd_hda_codec_set_power_to_all(codec, fg, power_state);
|
||||||
}
|
}
|
||||||
state = hda_sync_power_state(codec, fg, power_state);
|
state = snd_hda_sync_power_state(codec, fg, power_state);
|
||||||
if (!(state & AC_PWRST_ERROR))
|
if (!(state & AC_PWRST_ERROR))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -622,7 +622,11 @@ snd_hda_check_power_state(struct hda_codec *codec, hda_nid_t nid,
|
||||||
{
|
{
|
||||||
return snd_hdac_check_power_state(&codec->core, nid, target_state);
|
return snd_hdac_check_power_state(&codec->core, nid, target_state);
|
||||||
}
|
}
|
||||||
|
static inline bool snd_hda_sync_power_state(struct hda_codec *codec,
|
||||||
|
hda_nid_t nid, unsigned int target_state)
|
||||||
|
{
|
||||||
|
return snd_hdac_sync_power_state(&codec->core, nid, target_state);
|
||||||
|
}
|
||||||
unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
|
unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
|
||||||
hda_nid_t nid,
|
hda_nid_t nid,
|
||||||
unsigned int power_state);
|
unsigned int power_state);
|
||||||
|
|
Loading…
Reference in New Issue