|
3 | 3 | */
|
4 | 4 |
|
5 | 5 | #include <linux/init.h>
|
| 6 | +#include <linux/delay.h> |
6 | 7 | #include <linux/device.h>
|
7 | 8 | #include <linux/slab.h>
|
8 | 9 | #include <linux/module.h>
|
@@ -1064,3 +1065,37 @@ bool snd_hdac_check_power_state(struct hdac_device *hdac,
|
1064 | 1065 | return (state == target_state);
|
1065 | 1066 | }
|
1066 | 1067 | EXPORT_SYMBOL_GPL(snd_hdac_check_power_state);
|
| 1068 | +/** |
| 1069 | + * snd_hdac_sync_power_state - wait until actual power state matches |
| 1070 | + * with the target state |
| 1071 | + * |
| 1072 | + * @hdac: the HDAC device |
| 1073 | + * @nid: NID to send the command |
| 1074 | + * @target_state: target state to check for |
| 1075 | + * |
| 1076 | + * Return power state or PS_ERROR if codec rejects GET verb. |
| 1077 | + */ |
| 1078 | +unsigned int snd_hdac_sync_power_state(struct hdac_device *codec, |
| 1079 | + hda_nid_t nid, unsigned int power_state) |
| 1080 | +{ |
| 1081 | + unsigned long end_time = jiffies + msecs_to_jiffies(500); |
| 1082 | + unsigned int state, actual_state, count; |
| 1083 | + |
| 1084 | + for (count = 0; count < 500; count++) { |
| 1085 | + state = snd_hdac_codec_read(codec, nid, 0, |
| 1086 | + AC_VERB_GET_POWER_STATE, 0); |
| 1087 | + if (state & AC_PWRST_ERROR) { |
| 1088 | + msleep(20); |
| 1089 | + break; |
| 1090 | + } |
| 1091 | + actual_state = (state >> 4) & 0x0f; |
| 1092 | + if (actual_state == power_state) |
| 1093 | + break; |
| 1094 | + if (time_after_eq(jiffies, end_time)) |
| 1095 | + break; |
| 1096 | + /* wait until the codec reachs to the target state */ |
| 1097 | + msleep(1); |
| 1098 | + } |
| 1099 | + return state; |
| 1100 | +} |
| 1101 | +EXPORT_SYMBOL_GPL(snd_hdac_sync_power_state); |
0 commit comments