ALSA: hda - Limit codec-verb retry to limited hardwares
authorTakashi Iwai <tiwai@suse.de>
Mon, 1 Jun 2009 23:20:22 +0000 (01:20 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 1 Jun 2009 23:21:30 +0000 (01:21 +0200)
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 <tiwai@suse.de>
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_sigmatel.c

index aa0e1c18b606ace798eb6827f4f16a4b7751846c..562403a2348801aa9f6ba0dfc5b9a1f653347aef 100644 (file)
@@ -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);
 
index f5fa5d1f223c11fdbae91144fee3f03cddf37ba7..cad79efaabc95dfdfa480153fbe7d1dcc076c382 100644 (file)
@@ -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 */
index 44f9a0aa20c5f23225a3064f9ee89528324ce7a2..9f44645a1d044b23931f2561aefa4bf3f8096b28 100644 (file)
@@ -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 */
        }
index 48f4a36c4813849b827a30b88df011dcf195caa8..42f944bb641db9db3b443d7b43174f27808edaf4 100644 (file)
@@ -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;