[alsa-devel] 1.0.16->1.0.17 regression for some HDA NVidia's

Takashi Iwai tiwai at suse.de
Tue Jul 15 12:46:39 CEST 2008


At Sun, 13 Jul 2008 08:45:55 +0200,
Hans-Frieder Vogt wrote:
> 
> Just a few more things to add (maybe it gets clearer):
> On a GeForce 8200 board (MCP78S), using the pcm example program from alsa-lib-1.0.17rc2/test,
> kernel driver version 1.0.17rc3:
> (ignoring my general sound distortion problem which I will address again in another post)
> 
> bdl_pos_adj=0
> both devices "default" and "plughw:0,0" work, i.e. give continuous sound
> 
> bdl_pos_adj=1
> bdl_pos_adj=2
> bdl_pos_adj=8
> no sound, pcm seems to gets stuck (example program does not return)
> 
> bdl_pos_adj=16
> bdl_pos_adj=32
> bdl_pos_adj=64
> bdl_pos_adj=128
> bdl_pos_adj=256
> bdl_pos_adj=512
> bdl_pos_adj=1024
> bdl_pos_adj=2048
> default device: works, i.e. sound
> plughw:0,0: no sound, pcm gets stuck
> 
> bdl_pos_adj=4096
> bdl_pos_adj=8192
> ALSA /home/haef/Treiber/alsa-driver-1.0.17rc3/pci/hda/../../alsa-kernel/pci/hda/hda_intel.c:1056: Too big adjustment 4096
> default device: works, i.e. sound
> plughw:0,0: just one beep (approx. 0.5s of sound), then pcm gets stuck
> 
> Any ideas?

Thanks, that's really good to know.  Does this happen with aplay, too? 

Now you don't need to play so many bdl_pos_adj values any more.
Checking 1 and 32 should suffice.

Could you check /proc/asound/card0/pcm0p/sub0/* at non-working time
with bdl_pos_adj=32?

Also, try the patch below.  If my guess is right, the problem is
unaligned period size.


Takashi

---
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 16715a6..ef9f072 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1047,9 +1047,13 @@ static int azx_setup_periods(struct azx *chip,
 	pos_adj = bdl_pos_adj[chip->dev_index];
 	if (pos_adj > 0) {
 		struct snd_pcm_runtime *runtime = substream->runtime;
+		int pos_align = pos_adj;
 		pos_adj = (pos_adj * runtime->rate + 47999) / 48000;
 		if (!pos_adj)
-			pos_adj = 1;
+			pos_adj = pos_align;
+		else
+			pos_adj = ((pos_adj + pos_align - 1) / pos_align) *
+				pos_align;
 		pos_adj = frames_to_bytes(runtime, pos_adj);
 		if (pos_adj >= period_bytes) {
 			snd_printk(KERN_WARNING "Too big adjustment %d\n",


More information about the Alsa-devel mailing list