]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ALSA: hda: Modify stream stripe mask only when needed
authorTakashi Iwai <tiwai@suse.de>
Mon, 2 Dec 2019 07:49:47 +0000 (08:49 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 13 Dec 2019 07:48:58 +0000 (08:48 +0100)
commit e38e486d66e2a3b902768fd71c32dbf10f77e1cb upstream.

The recent commit in HD-audio stream management for changing the
stripe control seems causing a regression on some platforms.  The
stripe control is currently used only by HDMI codec, and applying the
stripe mask unconditionally may lead to scratchy and static noises as
seen on some MacBooks.

For addressing the regression, this patch changes the stream
management code to apply the stripe mask conditionally only when the
codec driver requested.

Fixes: 9b6f7e7a296e ("ALSA: hda: program stripe bits for controller")
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=204477
Tested-by: Michael Pobega <mpobega@neverware.com>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20191202074947.1617-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
include/sound/hdaudio.h
sound/hda/hdac_stream.c
sound/pci/hda/patch_hdmi.c

index 612a17e375d026b0215572f6d9dec83e04ad0c37..3f0330a505b3999ed4eeeede7d500c7be129079f 100644 (file)
@@ -504,6 +504,7 @@ struct hdac_stream {
        bool prepared:1;
        bool no_period_wakeup:1;
        bool locked:1;
+       bool stripe:1;                  /* apply stripe control */
 
        /* timestamp */
        unsigned long start_wallclk;    /* start + minimum wallclk */
index 55d53b89ac21583e5f55308350dc54ed26b82843..581706acf48695f1129fcb0d388033a8de1de2cb 100644 (file)
@@ -96,12 +96,14 @@ void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start)
                              1 << azx_dev->index,
                              1 << azx_dev->index);
        /* set stripe control */
-       if (azx_dev->substream)
-               stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream);
-       else
-               stripe_ctl = 0;
-       snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK,
-                               stripe_ctl);
+       if (azx_dev->stripe) {
+               if (azx_dev->substream)
+                       stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream);
+               else
+                       stripe_ctl = 0;
+               snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK,
+                                       stripe_ctl);
+       }
        /* set DMA start and interrupt mask */
        snd_hdac_stream_updateb(azx_dev, SD_CTL,
                                0, SD_CTL_DMA_START | SD_INT_MASK);
@@ -118,7 +120,10 @@ void snd_hdac_stream_clear(struct hdac_stream *azx_dev)
        snd_hdac_stream_updateb(azx_dev, SD_CTL,
                                SD_CTL_DMA_START | SD_INT_MASK, 0);
        snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
-       snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
+       if (azx_dev->stripe) {
+               snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
+               azx_dev->stripe = 0;
+       }
        azx_dev->running = false;
 }
 EXPORT_SYMBOL_GPL(snd_hdac_stream_clear);
index ff99f5feaace97bb11beeba3accc3f01d598700e..b8cd566629a440b11f527575f3d4d33871b31d60 100644 (file)
@@ -31,6 +31,7 @@
 #include <sound/hda_codec.h>
 #include "hda_local.h"
 #include "hda_jack.h"
+#include "hda_controller.h"
 
 static bool static_hdmi_pcm;
 module_param(static_hdmi_pcm, bool, 0644);
@@ -1226,6 +1227,10 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
        per_pin->cvt_nid = per_cvt->cvt_nid;
        hinfo->nid = per_cvt->cvt_nid;
 
+       /* flip stripe flag for the assigned stream if supported */
+       if (get_wcaps(codec, per_cvt->cvt_nid) & AC_WCAP_STRIPE)
+               azx_stream(get_azx_dev(substream))->stripe = 1;
+
        snd_hda_set_dev_select(codec, per_pin->pin_nid, per_pin->dev_id);
        snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
                            AC_VERB_SET_CONNECT_SEL,