summaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-06-06 14:20:19 +0200
committerTakashi Iwai <tiwai@suse.de>2013-06-06 14:20:19 +0200
commit63e51fd708f511a5989da04c669647993bc1a512 (patch)
treeeaa604d5faae416c0a51b5cdba78d625ca62cf2b /sound/pci/hda/hda_codec.c
parente7ecc27e520a9c9891362c6dabd18c4da9885946 (diff)
downloadop-kernel-dev-63e51fd708f511a5989da04c669647993bc1a512.zip
op-kernel-dev-63e51fd708f511a5989da04c669647993bc1a512.tar.gz
ALSA: hda - Don't take unresponsive D3 transition too serious
When a codec is powered off, some systems don't respond properly after D3 FG transition, while the driver still expects the response and tries to fall back to different modes (polling and single-cmd). When the fallback happens, the driver stays in that mode, and falling back to the single-cmd mode means it'll loose the unsol event handling, too. The unresponsiveness at D3 isn't too serious, thus this fallback is mostly superfluous. We can gracefully ignore the error there so that the driver keeps the normal operation mode. This patch adds a new bit flag for codec read/write, set in the power transition stage, which is notified to the controller driver via a new bus->no_response_fallback flag. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r--sound/pci/hda/hda_codec.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 503869a..35090b3 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -221,6 +221,8 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
again:
snd_hda_power_up(codec);
mutex_lock(&bus->cmd_mutex);
+ if (flags & HDA_RW_NO_RESPONSE_FALLBACK)
+ bus->no_response_fallback = 1;
for (;;) {
trace_hda_send_cmd(codec, cmd);
err = bus->ops.command(bus, cmd);
@@ -233,6 +235,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
*res = bus->ops.get_response(bus, codec->addr);
trace_hda_get_response(codec, *res);
}
+ bus->no_response_fallback = 0;
mutex_unlock(&bus->cmd_mutex);
snd_hda_power_down(codec);
if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) {
@@ -3805,11 +3808,13 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
hda_nid_t fg = codec->afg ? codec->afg : codec->mfg;
int count;
unsigned int state;
+ int flags = 0;
/* this delay seems necessary to avoid click noise at power-down */
if (power_state == AC_PWRST_D3) {
/* transition time less than 10ms for power down */
msleep(codec->epss ? 10 : 100);
+ flags = HDA_RW_NO_RESPONSE_FALLBACK;
}
/* repeat power states setting at most 10 times*/
@@ -3818,7 +3823,7 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
codec->patch_ops.set_power_state(codec, fg,
power_state);
else {
- snd_hda_codec_read(codec, fg, 0,
+ snd_hda_codec_read(codec, fg, flags,
AC_VERB_SET_POWER_STATE,
power_state);
snd_hda_codec_set_power_to_all(codec, fg, power_state);
OpenPOWER on IntegriCloud