From b20f3b834673be9ead83a3c6f07fa3881d1a990f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 2 Jun 2009 01:20:22 +0200 Subject: [PATCH] ALSA: hda - Limit codec-verb retry to limited hardwares The reset of a BUS controller during operations is somehow risky and shouldn't be done inevitably for devices that have apparently no such codec-communication problems. This patch adds the check of the hardware and limits the bus-reset capability. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 12 ++---------- sound/pci/hda/hda_codec.h | 3 +++ sound/pci/hda/hda_intel.c | 2 +- sound/pci/hda/patch_sigmatel.c | 9 +++++++++ 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index aa0e1c18b606..562403a23488 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -214,11 +214,6 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, } EXPORT_SYMBOL_HDA(snd_hda_codec_read); -/* Define the below to send and receive verbs synchronously. - * If you often get any codec communication errors, this is worth to try. - */ -/* #define SND_HDA_SUPPORT_SYNC_WRITE */ - /** * snd_hda_codec_write - send a single command without waiting for response * @codec: the HDA codec @@ -235,12 +230,9 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, unsigned int verb, unsigned int parm) { unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm); -#ifdef SND_HDA_SUPPORT_SYNC_WRITE unsigned int res; - return codec_exec_verb(codec, cmd, &res); -#else - return codec_exec_verb(codec, cmd, NULL); -#endif + return codec_exec_verb(codec, cmd, + codec->bus->sync_write ? &res : NULL); } EXPORT_SYMBOL_HDA(snd_hda_codec_write); diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index f5fa5d1f223c..cad79efaabc9 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -624,6 +624,9 @@ struct hda_bus { /* misc op flags */ unsigned int needs_damn_long_delay :1; + unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */ + unsigned int sync_write:1; /* sync after verb write */ + /* status for codec/controller */ unsigned int shutdown :1; /* being unloaded */ unsigned int rirb_error:1; /* error in codec communication */ unsigned int response_reset:1; /* controller was reset */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 44f9a0aa20c5..9f44645a1d04 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -665,7 +665,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus) * to the single_cmd mode */ bus->rirb_error = 1; - if (!bus->response_reset && !bus->in_reset) { + if (bus->allow_bus_reset && !bus->response_reset && !bus->in_reset) { bus->response_reset = 1; return -1; /* give a chance to retry */ } diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 48f4a36c4813..42f944bb641d 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -5375,6 +5375,15 @@ again: if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) snd_hda_sequence_write_cache(codec, unmute_init); + /* Some HP machines seem to have unstable codec communications + * especially with ATI fglrx driver. For recovering from the + * CORB/RIRB stall, allow the BUS reset and keep always sync + */ + if (spec->board_config == STAC_HP_DV5) { + codec->bus->sync_write = 1; + codec->bus->allow_bus_reset = 1; + } + spec->aloopback_ctl = stac92hd71bxx_loopback; spec->aloopback_mask = 0x50; spec->aloopback_shift = 0; -- 2.11.0