Hello!

  This is a solution to an old problem with full duplex on SB16 cards,
described in detail in

http://www.mail-archive.com/alsa-user@;lists.sourceforge.net/msg02194.html

  The core of this problem is, that ALSA is sending SB_DSP_DMA[8|16]_OFF
0xd0/0xd5 command instead of SB_DSP_DMA[8/16]_EXIT commands 0xda/0xd9.
SB_DSP_DMA*_OFF command in fact only "pause" DMA transfer and does not
clear pending interrupt in sb16 chip. But the problem with
SB_DSP_DMA*_EXIT command is, that it causes unwanted repeat of last period
as SNDRV_PCM_TRIGGER_STOP command is sent after last period. Thus, at the
end of playback/capture, sb16 IRQ will not be acknowledged, and no further
interrupts will occur.

  In a problem description, I can find:

start capture -> ack 16bit IRQ in snd_sb16_setup_rate() function
start playback -> ack 8bit IRQ
stop playback -> 8bit IRQ is pending
stop capture -> 8bit IRQ is pending

start playback -> clear 16bit IRQ

In this state, 8bit IRQ is still pending! It looks that with some SB DSP
chip versions, this will block generation of 8 _and_ 16bit IRQs.

Attached patch (untested!) acknowledges [16|8] bit interrupt, but adds
[8|16] bit acknowledge, if secondary channel is not in use at the moment.

Please, could someone with described problems test this patch.

  Another problem, described in

http://www.mail-archive.com/alsa-user@;lists.sourceforge.net/msg04960.html

  is perhaps connected with the way sb16 driver reports mutual sample
rate, when one channel is already in use. Locked rate will be reported
only when second channel is opened, so it is possible that selected rate
won't be programmed to sb16 chip if capture and playback channels are
opened simultaneously and no playback/capture has started yet.

        Uros.
Index: sb16_main.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/isa/sb/sb16_main.c,v
retrieving revision 1.12
diff -u -r1.12 sb16_main.c
--- sb16_main.c 23 Oct 2002 19:07:44 -0000      1.12
+++ sb16_main.c 7 Nov 2002 12:23:09 -0000
@@ -224,10 +224,30 @@
        unsigned long flags;
 
        spin_lock_irqsave(&chip->reg_lock, flags);
-       if (chip->mode & (channel == SNDRV_PCM_STREAM_PLAYBACK ? SB_MODE_PLAYBACK_16 : 
SB_MODE_CAPTURE_16))
-               snd_sb_ack_16bit(chip);
-       else
-               snd_sb_ack_8bit(chip);
+
+       /* acknowledge stalled interrupts */
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               if (chip->mode & SB_MODE_PLAYBACK_16) {
+                       snd_sb_ack_16bit(chip);
+                       if (! (chip->mode & SB_RATE_LOCK_CAPTURE))
+                               snd_sb_ack_8bit(chip);
+               } else {
+                       snd_sb_ack_8bit(chip);
+                       if (! (chip->mode & SB_RATE_LOCK_CAPTURE))
+                               snd_sb_ack_16bit(chip);
+               }
+       } else {
+               if (chip->mode & SB_MODE_CAPTURE_16) {
+                       snd_sb_ack_16bit(chip);
+                       if (! (chip->mode & SB_RATE_LOCK_PLAYBACK))
+                               snd_sb_ack_8bit(chip);
+               } else {
+                       snd_sb_ack_8bit(chip);
+                       if (! (chip->mode & SB_RATE_LOCK_PLAYBACK))
+                               snd_sb_ack_16bit(chip);
+               }
+       }
+
        if (!(chip->mode & SB_RATE_LOCK)) {
                chip->locked_rate = rate;
                snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE_IN);

Reply via email to