From e7ecc27e520a9c9891362c6dabd18c4da9885946 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Jun 2013 14:00:23 +0200 Subject: ALSA: hda - Introduce bit flags to snd_hda_codec_read/write() snd_hda_codec_read(), snd_hda_codec_write() & co take the argument "direct" that indicates whether the given NID is a direct reference or an indirect reference. However, the indirect reference is practically unimplemented and never exists. And moreover, we don't need the indication of indirect reference at this high level, as NID can be represented in 16bit values at this point. Meanwhile, there are some cases where it'd be nice to give some operational options to these functions. So, we can reuse this argument as a new bit flag! Pretty frugal, eh? All callers so far pass zero to this argument, thus there is no behavior change by this replacement. The real usage of this new bit option will be added in the following patches. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/pci/hda/hda_codec.h') diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index c93f9021f45..39a658e0298 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -945,9 +945,9 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec); * low level functions */ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, - int direct, + int flags, unsigned int verb, unsigned int parm); -int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, +int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags, unsigned int verb, unsigned int parm); #define snd_hda_param_read(codec, nid, param) \ snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param) @@ -986,11 +986,11 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex); /* cached write */ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, - int direct, unsigned int verb, unsigned int parm); + int flags, unsigned int verb, unsigned int parm); void snd_hda_sequence_write_cache(struct hda_codec *codec, const struct hda_verb *seq); int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, - int direct, unsigned int verb, unsigned int parm); + int flags, unsigned int verb, unsigned int parm); void snd_hda_codec_resume_cache(struct hda_codec *codec); /* both for cmd & amp caches */ void snd_hda_codec_flush_cache(struct hda_codec *codec); -- cgit v1.2.3-70-g09d2 From 63e51fd708f511a5989da04c669647993bc1a512 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Jun 2013 14:20:19 +0200 Subject: 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 --- sound/pci/hda/hda_codec.c | 7 ++++++- sound/pci/hda/hda_codec.h | 3 +++ sound/pci/hda/hda_intel.c | 3 +++ 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'sound/pci/hda/hda_codec.h') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 503869aad7f..35090b3acba 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); diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 39a658e0298..701c2e069b1 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -679,6 +679,7 @@ struct hda_bus { unsigned int response_reset:1; /* controller was reset */ unsigned int in_reset:1; /* during reset operation */ unsigned int power_keep_link_on:1; /* don't power off HDA link */ + unsigned int no_response_fallback:1; /* don't fallback at RIRB error */ int primary_dig_out_type; /* primary digital out PCM type */ }; @@ -930,6 +931,8 @@ enum { HDA_INPUT, HDA_OUTPUT }; +/* snd_hda_codec_read/write optional flags */ +#define HDA_RW_NO_RESPONSE_FALLBACK (1 << 0) /* * constructors diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 49dfad4a099..f089fa0aa03 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, } } + if (!bus->no_response_fallback) + return -1; + if (!chip->polling_mode && chip->poll_count < 2) { snd_printdd(SFX "%s: azx_get_response timeout, " "polling the codec once: last cmd=0x%08x\n", -- cgit v1.2.3-70-g09d2