aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-06-06 08:20:19 -0400
committerTakashi Iwai <tiwai@suse.de>2013-06-06 08:20:19 -0400
commit63e51fd708f511a5989da04c669647993bc1a512 (patch)
treeeaa604d5faae416c0a51b5cdba78d625ca62cf2b /sound/pci
parente7ecc27e520a9c9891362c6dabd18c4da9885946 (diff)
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')
-rw-r--r--sound/pci/hda/hda_codec.c7
-rw-r--r--sound/pci/hda/hda_codec.h3
-rw-r--r--sound/pci/hda/hda_intel.c3
3 files changed, 12 insertions, 1 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 503869aad7f9..35090b3acbac 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,
221 again: 221 again:
222 snd_hda_power_up(codec); 222 snd_hda_power_up(codec);
223 mutex_lock(&bus->cmd_mutex); 223 mutex_lock(&bus->cmd_mutex);
224 if (flags & HDA_RW_NO_RESPONSE_FALLBACK)
225 bus->no_response_fallback = 1;
224 for (;;) { 226 for (;;) {
225 trace_hda_send_cmd(codec, cmd); 227 trace_hda_send_cmd(codec, cmd);
226 err = bus->ops.command(bus, cmd); 228 err = bus->ops.command(bus, cmd);
@@ -233,6 +235,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
233 *res = bus->ops.get_response(bus, codec->addr); 235 *res = bus->ops.get_response(bus, codec->addr);
234 trace_hda_get_response(codec, *res); 236 trace_hda_get_response(codec, *res);
235 } 237 }
238 bus->no_response_fallback = 0;
236 mutex_unlock(&bus->cmd_mutex); 239 mutex_unlock(&bus->cmd_mutex);
237 snd_hda_power_down(codec); 240 snd_hda_power_down(codec);
238 if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) { 241 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,
3805 hda_nid_t fg = codec->afg ? codec->afg : codec->mfg; 3808 hda_nid_t fg = codec->afg ? codec->afg : codec->mfg;
3806 int count; 3809 int count;
3807 unsigned int state; 3810 unsigned int state;
3811 int flags = 0;
3808 3812
3809 /* this delay seems necessary to avoid click noise at power-down */ 3813 /* this delay seems necessary to avoid click noise at power-down */
3810 if (power_state == AC_PWRST_D3) { 3814 if (power_state == AC_PWRST_D3) {
3811 /* transition time less than 10ms for power down */ 3815 /* transition time less than 10ms for power down */
3812 msleep(codec->epss ? 10 : 100); 3816 msleep(codec->epss ? 10 : 100);
3817 flags = HDA_RW_NO_RESPONSE_FALLBACK;
3813 } 3818 }
3814 3819
3815 /* repeat power states setting at most 10 times*/ 3820 /* repeat power states setting at most 10 times*/
@@ -3818,7 +3823,7 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
3818 codec->patch_ops.set_power_state(codec, fg, 3823 codec->patch_ops.set_power_state(codec, fg,
3819 power_state); 3824 power_state);
3820 else { 3825 else {
3821 snd_hda_codec_read(codec, fg, 0, 3826 snd_hda_codec_read(codec, fg, flags,
3822 AC_VERB_SET_POWER_STATE, 3827 AC_VERB_SET_POWER_STATE,
3823 power_state); 3828 power_state);
3824 snd_hda_codec_set_power_to_all(codec, fg, power_state); 3829 snd_hda_codec_set_power_to_all(codec, fg, power_state);
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 39a658e02988..701c2e069b10 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -679,6 +679,7 @@ struct hda_bus {
679 unsigned int response_reset:1; /* controller was reset */ 679 unsigned int response_reset:1; /* controller was reset */
680 unsigned int in_reset:1; /* during reset operation */ 680 unsigned int in_reset:1; /* during reset operation */
681 unsigned int power_keep_link_on:1; /* don't power off HDA link */ 681 unsigned int power_keep_link_on:1; /* don't power off HDA link */
682 unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
682 683
683 int primary_dig_out_type; /* primary digital out PCM type */ 684 int primary_dig_out_type; /* primary digital out PCM type */
684}; 685};
@@ -930,6 +931,8 @@ enum {
930 HDA_INPUT, HDA_OUTPUT 931 HDA_INPUT, HDA_OUTPUT
931}; 932};
932 933
934/* snd_hda_codec_read/write optional flags */
935#define HDA_RW_NO_RESPONSE_FALLBACK (1 << 0)
933 936
934/* 937/*
935 * constructors 938 * constructors
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 49dfad4a099e..f089fa0aa03d 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -942,6 +942,9 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
942 } 942 }
943 } 943 }
944 944
945 if (!bus->no_response_fallback)
946 return -1;
947
945 if (!chip->polling_mode && chip->poll_count < 2) { 948 if (!chip->polling_mode && chip->poll_count < 2) {
946 snd_printdd(SFX "%s: azx_get_response timeout, " 949 snd_printdd(SFX "%s: azx_get_response timeout, "
947 "polling the codec once: last cmd=0x%08x\n", 950 "polling the codec once: last cmd=0x%08x\n",