Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: hda: Modify stream stripe mask only when needed

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>

+18 -7
+1
include/sound/hdaudio.h
··· 493 493 bool prepared:1; 494 494 bool no_period_wakeup:1; 495 495 bool locked:1; 496 + bool stripe:1; /* apply stripe control */ 496 497 497 498 /* timestamp */ 498 499 unsigned long start_wallclk; /* start + minimum wallclk */
+12 -7
sound/hda/hdac_stream.c
··· 96 96 1 << azx_dev->index, 97 97 1 << azx_dev->index); 98 98 /* set stripe control */ 99 - if (azx_dev->substream) 100 - stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream); 101 - else 102 - stripe_ctl = 0; 103 - snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 104 - stripe_ctl); 99 + if (azx_dev->stripe) { 100 + if (azx_dev->substream) 101 + stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream); 102 + else 103 + stripe_ctl = 0; 104 + snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 105 + stripe_ctl); 106 + } 105 107 /* set DMA start and interrupt mask */ 106 108 snd_hdac_stream_updateb(azx_dev, SD_CTL, 107 109 0, SD_CTL_DMA_START | SD_INT_MASK); ··· 120 118 snd_hdac_stream_updateb(azx_dev, SD_CTL, 121 119 SD_CTL_DMA_START | SD_INT_MASK, 0); 122 120 snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ 123 - snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0); 121 + if (azx_dev->stripe) { 122 + snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0); 123 + azx_dev->stripe = 0; 124 + } 124 125 azx_dev->running = false; 125 126 } 126 127 EXPORT_SYMBOL_GPL(snd_hdac_stream_clear);
+5
sound/pci/hda/patch_hdmi.c
··· 32 32 #include <sound/hda_codec.h> 33 33 #include "hda_local.h" 34 34 #include "hda_jack.h" 35 + #include "hda_controller.h" 35 36 36 37 static bool static_hdmi_pcm; 37 38 module_param(static_hdmi_pcm, bool, 0644); ··· 1249 1248 per_pin = get_pin(spec, pin_idx); 1250 1249 per_pin->cvt_nid = per_cvt->cvt_nid; 1251 1250 hinfo->nid = per_cvt->cvt_nid; 1251 + 1252 + /* flip stripe flag for the assigned stream if supported */ 1253 + if (get_wcaps(codec, per_cvt->cvt_nid) & AC_WCAP_STRIPE) 1254 + azx_stream(get_azx_dev(substream))->stripe = 1; 1252 1255 1253 1256 snd_hda_set_dev_select(codec, per_pin->pin_nid, per_pin->dev_id); 1254 1257 snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,