Just forget about the last patch, I've discovered a serious bug in the variable period
size implementation. Everything got an explication, well and
now jackd behaves correctly, no more infinite amount of xruns.

I hope that should work OK now ...

/Benny
diff --exclude=CVS -Naur alsa-kernel/include/cs46xx.h 
../cvs/alsa-kernel/include/cs46xx.h
--- alsa-kernel/include/cs46xx.h        Sat Nov  2 00:00:15 2002
+++ ../cvs/alsa-kernel/include/cs46xx.h Sun Nov  3 21:03:28 2002
@@ -1766,6 +1766,7 @@
 int snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
 int snd_cs46xx_mixer(cs46xx_t *chip);
 int snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rmidi);
+int snd_cs46xx_start_dsp(cs46xx_t *chip);
 void snd_cs46xx_gameport(cs46xx_t *chip);
 
 #ifdef CONFIG_PM
diff --exclude=CVS -Naur alsa-kernel/include/cs46xx_dsp_spos.h 
../cvs/alsa-kernel/include/cs46xx_dsp_spos.h
--- alsa-kernel/include/cs46xx_dsp_spos.h       Sat Nov  2 00:00:15 2002
+++ ../cvs/alsa-kernel/include/cs46xx_dsp_spos.h        Sun Nov  3 20:12:31 2002
@@ -36,20 +36,20 @@
 #define SEGTYPE_SP_COEFFICIENT          0x00000004
 
 #define DSP_SPOS_UU      0x0deadul     /* unused */
-#define DSP_SPOS_DC      0x0badul     /* dont care */
-#define DSP_SPOS_DC_DC   0x0bad0badul     /* dont care */
+#define DSP_SPOS_DC      0x0badul      /* dont care */
+#define DSP_SPOS_DC_DC   0x0bad0badul  /* dont care */
 #define DSP_SPOS_UUUU    0xdeadc0edul  /* unused */
 #define DSP_SPOS_UUHI    0xdeadul
 #define DSP_SPOS_UULO    0xc0edul
-#define DSP_SPOS_DCDC    0x0badf1d0ul /* dont care */
+#define DSP_SPOS_DCDC    0x0badf1d0ul  /* dont care */
 #define DSP_SPOS_DCDCHI  0x0badul
 #define DSP_SPOS_DCDCLO  0xf1d0ul
 
-#define DSP_MAX_TASK_NAME 60
+#define DSP_MAX_TASK_NAME   60
 #define DSP_MAX_SYMBOL_NAME 100
-#define DSP_MAX_SCB_NAME  60
-#define DSP_MAX_SCB_DESC  200
-#define DSP_MAX_TASK_DESC 50
+#define DSP_MAX_SCB_NAME    60
+#define DSP_MAX_SCB_DESC    200
+#define DSP_MAX_TASK_DESC   50
 
 #define DSP_MAX_PCM_CHANNELS 32
 #define DSP_MAX_SRC_NR       6
@@ -59,6 +59,10 @@
 #define DSP_PCM_CENTER_CHANNEL  3
 #define DSP_PCM_LFE_CHANNEL     4
 #define DSP_IEC958_CHANNEL      5
+
+#define DSP_SDPIF_STATUS_OUTPUT_ENABLED 1
+#define DSP_SDPIF_STATUS_PLAYBACK_OPEN  2
+#define DSP_SDPIF_STATUS_HW_ENABLED     4
 
 struct _dsp_module_desc_t;
 
diff --exclude=CVS -Naur alsa-kernel/pci/cs46xx/cs46xx.c 
../cvs/alsa-kernel/pci/cs46xx/cs46xx.c
--- alsa-kernel/pci/cs46xx/cs46xx.c     Sat Nov  2 00:00:21 2002
+++ ../cvs/alsa-kernel/pci/cs46xx/cs46xx.c      Sun Nov  3 21:09:14 2002
@@ -110,14 +110,16 @@
                snd_card_free(card);
                return err;
        }
-    if ((err = snd_cs46xx_pcm_rear(chip,1, NULL)) < 0) {
-        snd_card_free(card);
-        return err;
-    }
-    if ((err = snd_cs46xx_pcm_iec958(chip,2,NULL)) < 0) {
-        snd_card_free(card);
-        return err;
-    }
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+       if ((err = snd_cs46xx_pcm_rear(chip,1, NULL)) < 0) {
+               snd_card_free(card);
+               return err;
+       }
+       if ((err = snd_cs46xx_pcm_iec958(chip,2,NULL)) < 0) {
+               snd_card_free(card);
+               return err;
+       }
+#endif
        if ((err = snd_cs46xx_mixer(chip)) < 0) {
                snd_card_free(card);
                return err;
@@ -126,6 +128,12 @@
                snd_card_free(card);
                return err;
        }
+       if ((err = snd_cs46xx_start_dsp(chip)) < 0) {
+               snd_card_free(card);
+               return err;
+       }
+
+
        snd_cs46xx_gameport(chip);
 
        strcpy(card->driver, "CS46xx");
diff --exclude=CVS -Naur alsa-kernel/pci/cs46xx/cs46xx_lib.c 
../cvs/alsa-kernel/pci/cs46xx/cs46xx_lib.c
--- alsa-kernel/pci/cs46xx/cs46xx_lib.c Sat Nov  2 00:00:23 2002
+++ ../cvs/alsa-kernel/pci/cs46xx/cs46xx_lib.c  Mon Nov  4 02:04:58 2002
@@ -445,19 +445,19 @@
        snd_cs46xx_poke(chip, BA1_FRMT, 0xadf);
 }
 
-static int cs46xx_wait_for_fifo(cs46xx_t * chip) 
+static int cs46xx_wait_for_fifo(cs46xx_t * chip,int retry_timeout) 
 {
        u32 i, status;
        /*
         * Make sure the previous FIFO write operation has completed.
         */
-       for(i = 0; i < 20; i++){
+       for(i = 0; i < 50; i++){
                status = snd_cs46xx_peekBA0(chip, BA0_SERBST);
     
                if( !(status & SERBST_WBSY) )
                        break;
 
-               udelay(50);
+               mdelay(retry_timeout);
        }
   
        if(status & SERBST_WBSY) {
@@ -498,7 +498,7 @@
                /*
                 *  Make sure the previous FIFO write operation has completed.
                 */
-               if (cs46xx_wait_for_fifo(chip)) {
+               if (cs46xx_wait_for_fifo(chip,1)) {
                        snd_printdd ("failed waiting for FIFO at addr (%02X)\n",idx);
 
                        if (powerdown)
@@ -728,6 +728,8 @@
        snd_pcm_runtime_t *runtime = substream->runtime;
        snd_pcm_sframes_t diff;
        cs46xx_pcm_t * cpcm;
+       int buffer_size = runtime->period_size * CS46XX_FRAGS * 4;
+
        cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return 
-ENXIO);
 
        diff = runtime->control->appl_ptr - cpcm->appl_ptr;
@@ -738,11 +740,11 @@
        }
        cpcm->sw_ready += frames << cpcm->shift;
        cpcm->appl_ptr = runtime->control->appl_ptr + frames;
-       while (cpcm->hw_ready < CS46XX_BUFFER_SIZE && 
+       while (cpcm->hw_ready < buffer_size && 
               cpcm->sw_ready > 0) {
-               size_t hw_to_end = CS46XX_BUFFER_SIZE - cpcm->hw_data;
+               size_t hw_to_end = buffer_size - cpcm->hw_data;
                size_t sw_to_end = cpcm->sw_bufsize - cpcm->sw_data;
-               size_t bytes = CS46XX_BUFFER_SIZE - cpcm->hw_ready;
+               size_t bytes = buffer_size - cpcm->hw_ready;
                if (cpcm->sw_ready < bytes)
                        bytes = cpcm->sw_ready;
                if (hw_to_end < bytes)
@@ -753,7 +755,7 @@
                       runtime->dma_area + cpcm->sw_data,
                       bytes);
                cpcm->hw_data += bytes;
-               if (cpcm->hw_data == CS46XX_BUFFER_SIZE)
+               if (cpcm->hw_data == buffer_size)
                        cpcm->hw_data = 0;
                cpcm->sw_data += bytes;
                if (cpcm->sw_data == cpcm->sw_bufsize)
@@ -770,6 +772,7 @@
        cs46xx_t *chip = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
        snd_pcm_sframes_t diff = runtime->control->appl_ptr - chip->capt.appl_ptr;
+       int buffer_size = runtime->period_size * CS46XX_FRAGS * 4;
        if (diff) {
                if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
                        diff += runtime->boundary;
@@ -779,7 +782,7 @@
        chip->capt.appl_ptr = runtime->control->appl_ptr + frames;
        while (chip->capt.hw_ready > 0 && 
               chip->capt.sw_ready < chip->capt.sw_bufsize) {
-               size_t hw_to_end = CS46XX_BUFFER_SIZE - chip->capt.hw_data;
+               size_t hw_to_end = buffer_size - chip->capt.hw_data;
                size_t sw_to_end = chip->capt.sw_bufsize - chip->capt.sw_data;
                size_t bytes = chip->capt.sw_bufsize - chip->capt.sw_ready;
                if (chip->capt.hw_ready < bytes)
@@ -792,7 +795,7 @@
                       chip->capt.hw_area + chip->capt.hw_data,
                       bytes);
                chip->capt.hw_data += bytes;
-               if (chip->capt.hw_data == CS46XX_BUFFER_SIZE)
+               if (chip->capt.hw_data == buffer_size)
                        chip->capt.hw_data = 0;
                chip->capt.sw_data += bytes;
                if (chip->capt.sw_data == chip->capt.sw_bufsize)
@@ -825,6 +828,7 @@
        size_t ptr;
        cs46xx_pcm_t *cpcm = snd_magic_cast(cs46xx_pcm_t, 
substream->runtime->private_data, return -ENXIO);
        ssize_t bytes;
+       int buffer_size = substream->runtime->period_size * CS46XX_FRAGS * 4;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        snd_assert (cpcm->pcm_channel,return -ENXIO);
@@ -837,7 +841,7 @@
        bytes = ptr - cpcm->hw_io;
 
        if (bytes < 0)
-               bytes += CS46XX_BUFFER_SIZE;
+               bytes += buffer_size;
        cpcm->hw_io = ptr;
        cpcm->hw_ready -= bytes;
        cpcm->sw_io += bytes;
@@ -859,8 +863,10 @@
        cs46xx_t *chip = snd_pcm_substream_chip(substream);
        size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_addr;
        ssize_t bytes = ptr - chip->capt.hw_io;
+       int buffer_size = substream->runtime->period_size * CS46XX_FRAGS * 4;
+
        if (bytes < 0)
-               bytes += CS46XX_BUFFER_SIZE;
+               bytes += buffer_size;
        chip->capt.hw_io = ptr;
        chip->capt.hw_ready += bytes;
        chip->capt.sw_io += bytes;
@@ -1023,6 +1029,7 @@
        int err;
        cs46xx_t *chip = snd_pcm_substream_chip(substream);
        int sample_rate = params_rate(hw_params);
+       int period_size = params_period_size(hw_params);
        cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -1047,8 +1054,8 @@
                cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel);
 
                if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, 
sample_rate, cpcm, 
-                                                                 cpcm->hw_addr,
-                                                                 
cpcm->pcm_channel->pcm_channel_id)) == NULL) {
+                                                                        cpcm->hw_addr,
+                                                                        
+cpcm->pcm_channel->pcm_channel_id)) == NULL) {
                        snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM 
channel\n");
                        up (&chip->spos_mutex);
                        return -ENXIO;
@@ -1058,6 +1065,12 @@
                cpcm->pcm_channel->sample_rate = sample_rate;
        }
 
+       if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size * 
+4)) {
+                up (&chip->spos_mutex);
+                return -EINVAL;
+        }
+       snd_printdd ("period_size (%d), periods (%d)\n",
+                    period_size, params_periods(hw_params));
 #endif
 
        if (params_periods(hw_params) == CS46XX_FRAGS) {
@@ -1089,7 +1102,9 @@
                        runtime->dma_bytes = 0;
                }
                if ((err = snd_pcm_lib_malloc_pages(substream, 
params_buffer_bytes(hw_params))) < 0) {
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
                        up (&chip->spos_mutex);
+#endif
                        return err;
                }
 
@@ -1211,7 +1226,13 @@
        cs46xx_t *chip = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
        int err;
+       int period_size = params_period_size(hw_params);
 
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+       snd_printdd ("capture period size (%d)\n",period_size);
+
+       cs46xx_dsp_pcm_ostream_set_period (chip,period_size * 4);
+#endif
        if (runtime->periods == CS46XX_FRAGS) {
                if (runtime->dma_area != chip->capt.hw_area)
                        snd_pcm_lib_free_pages(substream);
@@ -1368,8 +1389,8 @@
        .channels_min =         1,
        .channels_max =         2,
        .buffer_bytes_max =     (256 * 1024),
-       .period_bytes_min =     CS46XX_PERIOD_SIZE,
-       .period_bytes_max =     CS46XX_PERIOD_SIZE,
+       .period_bytes_min =     CS46XX_MIN_PERIOD_SIZE,
+       .period_bytes_max =     CS46XX_MAX_PERIOD_SIZE,
        .periods_min =          CS46XX_FRAGS,
        .periods_max =          1024,
        .fifo_size =            0,
@@ -1388,13 +1409,23 @@
        .channels_min =         2,
        .channels_max =         2,
        .buffer_bytes_max =     (256 * 1024),
-       .period_bytes_min =     CS46XX_PERIOD_SIZE,
-       .period_bytes_max =     CS46XX_PERIOD_SIZE,
+       .period_bytes_min =     CS46XX_MIN_PERIOD_SIZE,
+       .period_bytes_max =     CS46XX_MAX_PERIOD_SIZE,
        .periods_min =          CS46XX_FRAGS,
        .periods_max =          1024,
        .fifo_size =            0,
 };
 
+static unsigned int period_sizes[] = { 8, 16, 32, 64, 128, 256, 512 };
+
+#define PERIOD_SIZES sizeof(period_sizes) / sizeof(period_sizes[0])
+
+static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
+       .count = PERIOD_SIZES,
+       .list = period_sizes,
+       .mask = 0
+};
+
 static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
        cs46xx_pcm_t * cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, 
return);
@@ -1435,6 +1466,8 @@
                return -ENOMEM;
        }
 
+       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 
+                                  &hw_constraints_period_sizes);
        up (&chip->spos_mutex);
 #else
        chip->playback_pcm = cpcm; /* HACK */
@@ -1467,7 +1500,10 @@
        cs46xx_t *chip = snd_pcm_substream_chip(substream);
 
        snd_printdd("open raw iec958 channel\n");
+
+       down (&chip->spos_mutex);
        cs46xx_iec958_pre_open (chip);
+       up (&chip->spos_mutex);
 
        return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL);
 }
@@ -1479,8 +1515,13 @@
        int err;
        cs46xx_t *chip = snd_pcm_substream_chip(substream);
   
+       snd_printdd("close raw iec958 channel\n");
+
        err = snd_cs46xx_playback_close(substream);
+
+       down (&chip->spos_mutex);
        cs46xx_iec958_post_close (chip);
+       up (&chip->spos_mutex);
 
        return err;
 }
@@ -1501,6 +1542,10 @@
        chip->active_ctrl(chip, 1);
        chip->amplifier_ctrl(chip, 1);
 
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+       snd_pcm_hw_constraint_list(substream->runtime, 0, 
+SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 
+                                  &hw_constraints_period_sizes);
+#endif
        return 0;
 }
 
@@ -1645,6 +1690,7 @@
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
 static void snd_cs46xx_pcm_rear_free(snd_pcm_t *pcm)
 {
        cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
@@ -1659,7 +1705,6 @@
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
-#ifdef CONFIG_SND_CS46XX_NEW_DSP
 #define MAX_PLAYBACK_CHANNELS  (DSP_MAX_PCM_CHANNELS - 1)
 #else
 #define MAX_PLAYBACK_CHANNELS  1
@@ -1846,7 +1891,7 @@
        int reg = kcontrol->private_value;
 
        if (reg == CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT)
-               ucontrol->value.integer.value[0] = 
chip->dsp_spos_instance->spdif_status_out;
+               ucontrol->value.integer.value[0] = 
+(chip->dsp_spos_instance->spdif_status_out & DSP_SDPIF_STATUS_OUTPUT_ENABLED);
        else
                ucontrol->value.integer.value[0] = 
chip->dsp_spos_instance->spdif_status_in;
 
@@ -1861,13 +1906,15 @@
 
        switch (kcontrol->private_value) {
        case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT:
-               change = chip->dsp_spos_instance->spdif_status_out;
+               down (&chip->spos_mutex);
+               change = (chip->dsp_spos_instance->spdif_status_out & 
+DSP_SDPIF_STATUS_OUTPUT_ENABLED);
                if (ucontrol->value.integer.value[0] && !change) 
                        cs46xx_dsp_enable_spdif_out(chip);
                else if (change && !ucontrol->value.integer.value[0])
                        cs46xx_dsp_disable_spdif_out(chip);
 
-               res = (change != chip->dsp_spos_instance->spdif_status_out);
+               res = (change != (chip->dsp_spos_instance->spdif_status_out & 
+DSP_SDPIF_STATUS_OUTPUT_ENABLED));
+               up (&chip->spos_mutex);
                break;
        case CS46XX_MIXER_SPDIF_INPUT_ELEMENT:
                change = chip->dsp_spos_instance->spdif_status_in;
@@ -2785,10 +2832,8 @@
 /*
  *  initialize chip
  */
-
 static int snd_cs46xx_chip_init(cs46xx_t *chip, int busywait)
 {
-       unsigned int tmp;
        int timeout;
 
        /* 
@@ -2897,6 +2942,7 @@
        snd_cs46xx_pokeBA0(chip, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
        snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
 
+
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        snd_cs46xx_pokeBA0(chip, BA0_SERC7, SERC7_ASDI2EN);
        snd_cs46xx_pokeBA0(chip, BA0_SERC3, 0);
@@ -2907,6 +2953,7 @@
 
        mdelay(5);
 
+
        /*
         * Wait for the codec ready signal from the AC97 codec.
         */
@@ -2959,6 +3006,7 @@
        snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
 #endif
 
+
        /*
         *  Wait until we've sampled input slots 3 and 4 as valid, meaning that
         *  the codec is pumping ADC data across the AC-link.
@@ -2987,7 +3035,10 @@
         *  Now, assert valid frame and the slot 3 and 4 valid bits.  This will
         *  commense the transfer of digital audio data to the AC97 codec.
         */
-       snd_cs46xx_pokeBA0(chip, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4 | ACOSV_SLV7 | 
ACOSV_SLV8);
+
+       snd_cs46xx_pokeBA0(chip, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4 | 
+                          ACOSV_SLV7 | ACOSV_SLV8);
+
 
        /*
         *  Power down the DAC and ADC.  We will power them up (if) when we need
@@ -3002,13 +3053,21 @@
        /* tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE; */
        /* snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); */
 
+       return 0;
+}
+
+/*
+ *  start and load DSP 
+ */
+int __devinit snd_cs46xx_start_dsp(cs46xx_t *chip)
+{      
+       unsigned int tmp;
        /*
-         *  Reset the processor.
-         */
+        *  Reset the processor.
+        */
        snd_cs46xx_reset(chip);
-
        /*
-         *  Download the image to the processor.
+        *  Download the image to the processor.
         */
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 #if 0
@@ -3040,7 +3099,6 @@
 
        if (cs46xx_dsp_scb_and_task_init(chip) < 0)
                return -EIO;
-       snd_printdd("[get here]\n");
 #else
        /* old image */
        if (snd_cs46xx_download_image(chip) < 0) {
@@ -3074,7 +3132,7 @@
         *  Enable interrupts on the part.
         */
        snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);
-
+        
        tmp = snd_cs46xx_peek(chip, BA1_PFIE);
        tmp &= ~0x0000f03f;
        snd_cs46xx_poke(chip, BA1_PFIE, tmp);   /* playback interrupt enable */
@@ -3084,19 +3142,24 @@
        tmp |=  0x00000001;
        snd_cs46xx_poke(chip, BA1_CIE, tmp);    /* capture interrupt enable */
        
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
        /* set the attenuation to 0dB */ 
-       snd_cs46xx_poke(chip, BA1_PVOL, 0x80008000);
-       snd_cs46xx_poke(chip, BA1_CVOL, 0x80008000);
+       snd_cs46xx_poke(chip, (MASTERMIX_SCB_ADDR + 0xE) << 2, 0x80008000); 
+       snd_cs46xx_poke(chip, (VARIDECIMATE_SCB_ADDR + 0xE) << 2, 0x80008000);
+
+       /*
+        * Initialize cs46xx SPDIF controller
+        */
 
-#ifdef CONFIG_SND_CS46XX_NEW_DSP
        /* time countdown enable */
        cs46xx_poke_via_dsp (chip,SP_ASER_COUNTDOWN, 0x80000000);
-        
+
        /* SPDIF input MASTER ENABLE */
        cs46xx_poke_via_dsp (chip,SP_SPDIN_CONTROL, 0x800003ff);
-
-       /* mute spdif out */
-       cs46xx_dsp_disable_spdif_out(chip);
+#else
+       /* set the attenuation to 0dB */ 
+       snd_cs46xx_poke(chip, BA1_PVOL, 0x80008000);
+       snd_cs46xx_poke(chip, BA1_CVOL, 0x80008000);
 #endif
 
        return 0;
@@ -3175,21 +3238,16 @@
        valid_slots |= 0x200;
        snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots);
 
-       valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV2);
-       valid_slots |= 0x200;
-       snd_cs46xx_pokeBA0(chip, BA0_ACOSV2, valid_slots);
+       if ( cs46xx_wait_for_fifo(chip,1) ) {
+         snd_printdd("FIFO is busy\n");
+         
+         return -EINVAL;
+       }
 
        /*
         * Fill slots 12 with the correct value for the GPIO pins. 
         */
        for(idx = 0x90; idx <= 0x9F; idx++) {
-
-               if ( cs46xx_wait_for_fifo(chip) ) {
-                       snd_printdd("failed waiting for FIFO at addr (%02X)\n",idx);
-
-                       return -EINVAL;
-               }
-
                /*
                 * Initialize the fifo so that bits 7 and 8 are on.
                 *
@@ -3197,6 +3255,15 @@
                 * the left.  0x1800 corresponds to bits 7 and 8.
                 */
                snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0x1800);
+
+               /*
+                * Wait for command to complete
+                */
+               if ( cs46xx_wait_for_fifo(chip,200) ) {
+                       snd_printdd("failed waiting for FIFO at addr (%02X)\n",idx);
+
+                       return -EINVAL;
+               }
             
                /*
                 * Write the serial port FIFO index.
@@ -3207,14 +3274,10 @@
                 * Tell the serial port to load the new value into the FIFO location.
                 */
                snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);
-
-               /*
-                * Wait for command to complete
-                */
        }
 
        /* wait for last command to complete */
-       cs46xx_wait_for_fifo(chip);
+       cs46xx_wait_for_fifo(chip,200);
 
        /*
         *  Now, if we powered up the devices, then power them back down again.
@@ -3690,7 +3753,7 @@
                snd_cs46xx_free(chip);
                return err;
        }
-
+       
        chip->active_ctrl(chip, -1);
 
        *rchip = chip;
diff --exclude=CVS -Naur alsa-kernel/pci/cs46xx/cs46xx_lib.h 
../cvs/alsa-kernel/pci/cs46xx/cs46xx_lib.h
--- alsa-kernel/pci/cs46xx/cs46xx_lib.h Sat Nov  2 00:00:23 2002
+++ ../cvs/alsa-kernel/pci/cs46xx/cs46xx_lib.h  Mon Nov  4 01:59:15 2002
@@ -35,9 +35,17 @@
 #define CS46XX_BA1_REG_SIZE      0x0100
 
 
-#define CS46XX_PERIOD_SIZE 2048
+
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+#define CS46XX_MIN_PERIOD_SIZE 1
+#define CS46XX_MAX_PERIOD_SIZE 1024*1024
+#else
+#define CS46XX_MIN_PERIOD_SIZE 2048
+#define CS46XX_MAX_PERIOD_SIZE 2048
+#endif
+
 #define CS46XX_FRAGS 2
-#define CS46XX_BUFFER_SIZE CS46XX_PERIOD_SIZE * CS46XX_FRAGS
+/* #define CS46XX_BUFFER_SIZE CS46XX_MAX_PERIOD_SIZE * CS46XX_FRAGS */
 
 #define SCB_NO_PARENT             0
 #define SCB_ON_PARENT_NEXT_SCB    1
@@ -100,6 +108,7 @@
                                             unsigned long len);
 int                    snd_cs46xx_clear_BA1(cs46xx_t *chip,unsigned long 
offset,unsigned long len);
 int                    cs46xx_dsp_enable_spdif_out (cs46xx_t *chip);
+int                    cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip);
 int                    cs46xx_dsp_disable_spdif_out (cs46xx_t *chip);
 int                    cs46xx_dsp_enable_spdif_in (cs46xx_t *chip);
 int                    cs46xx_dsp_disable_spdif_in (cs46xx_t *chip);
@@ -199,8 +208,13 @@
 int                        cs46xx_dsp_pcm_link (cs46xx_t * 
chip,pcm_channel_descriptor_t * pcm_channel);
 dsp_scb_descriptor_t *     cs46xx_add_record_source (cs46xx_t 
*chip,dsp_scb_descriptor_t * source,
                                                      u16 addr,char * scb_name);
-int                         cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * 
src);
-int                         cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * 
src);
-int                         cs46xx_iec958_pre_open (cs46xx_t *chip);
-int                         cs46xx_iec958_post_close (cs46xx_t *chip);
+int                        cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * 
+src);
+int                        cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src);
+int                        cs46xx_iec958_pre_open (cs46xx_t *chip);
+int                        cs46xx_iec958_post_close (cs46xx_t *chip);
+int                        cs46xx_dsp_pcm_channel_set_period (cs46xx_t * chip,
+                                                              
+pcm_channel_descriptor_t * pcm_channel,
+                                                              int period_size);
+int                        cs46xx_dsp_pcm_ostream_set_period (cs46xx_t * chip,
+                                                             int period_size);
 #endif /* __CS46XX_LIB_H__ */
diff --exclude=CVS -Naur alsa-kernel/pci/cs46xx/dsp_spos.c 
../cvs/alsa-kernel/pci/cs46xx/dsp_spos.c
--- alsa-kernel/pci/cs46xx/dsp_spos.c   Sat Nov  2 00:00:23 2002
+++ ../cvs/alsa-kernel/pci/cs46xx/dsp_spos.c    Sun Nov  3 21:10:49 2002
@@ -1021,8 +1021,6 @@
        dsp_scb_descriptor_t * record_mix_scb;
        dsp_scb_descriptor_t * write_back_scb;
        dsp_scb_descriptor_t * vari_decimate_scb;
-       dsp_scb_descriptor_t * pcm_serial_input_task;
-       dsp_scb_descriptor_t * asynch_tx_scb;
        dsp_scb_descriptor_t * sec_codec_out_scb;
        dsp_scb_descriptor_t * magic_snoop_scb;
 
@@ -1096,6 +1094,7 @@
                ins->the_null_scb->sub_list_ptr = ins->the_null_scb;
                ins->the_null_scb->next_scb_ptr = ins->the_null_scb;
                ins->the_null_scb->parent_scb_ptr = NULL;
+               cs46xx_dsp_proc_register_scb_desc (chip,ins->the_null_scb);
        }
 
        {
@@ -1265,9 +1264,9 @@
 
        /* create codec in */
        codec_in_scb = cs46xx_dsp_create_codec_in_scb(chip,"CodecInSCB",0x0010,0x00A0,
-                                                  CODEC_INPUT_BUF1,
-                                                  CODECIN_SCB_ADDR,codec_out_scb,
-                                                  SCB_ON_PARENT_NEXT_SCB);
+                                                     CODEC_INPUT_BUF1,
+                                                     CODECIN_SCB_ADDR,codec_out_scb,
+                                                     SCB_ON_PARENT_NEXT_SCB);
        if (!codec_in_scb) goto _fail_end;
        ins->codec_in_scb = codec_in_scb;
 
@@ -1318,10 +1317,10 @@
 
        /* create the rear PCM channel  mixer SCB */
        rear_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RearMixerSCB",
-                                                  MIX_SAMPLE_BUF3,
-                                                  REAR_MIXER_SCB_ADDR,
-                                                  sec_codec_out_scb,
-                                                  SCB_ON_PARENT_SUBLIST_SCB);
+                                                     MIX_SAMPLE_BUF3,
+                                                     REAR_MIXER_SCB_ADDR,
+                                                     sec_codec_out_scb,
+                                                     SCB_ON_PARENT_SUBLIST_SCB);
        ins->rear_mix_scb = rear_mix_scb;
        if (!rear_mix_scb) goto _fail_end;
 
@@ -1336,29 +1335,9 @@
        if (!magic_snoop_scb) goto _fail_end;
        ins->ref_snoop_scb = magic_snoop_scb;
 
-
-       /* The asynch. transfer task */
-       asynch_tx_scb = 
cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR,
-                                                          SPDIFO_SCB_INST,
-                                                          SPDIFO_IP_OUTPUT_BUFFER1,
-                                                          master_mix_scb,
-                                                          SCB_ON_PARENT_NEXT_SCB);
-
-       if (!asynch_tx_scb) goto _fail_end;
-       ins->asynch_tx_scb = asynch_tx_scb;
-
-       /* pcm input */
-       pcm_serial_input_task = 
cs46xx_dsp_create_pcm_serial_input_scb(chip,"PCMSerialInput_II",
-                                                                      
PCMSERIALINII_SCB_ADDR,
-                                                                      
magic_snoop_scb,asynch_tx_scb,
-                                                                      
SCB_ON_PARENT_SUBLIST_SCB);
-  
-       if (!pcm_serial_input_task) goto _fail_end;
-       ins->spdif_pcm_input_scb = pcm_serial_input_task; 
-
        /* SP IO access */
        if (!cs46xx_dsp_create_spio_write_scb(chip,"SPIOWriteSCB",SPIOWRITE_SCB_ADDR,
-                                             asynch_tx_scb,
+                                             magic_snoop_scb,
                                              SCB_ON_PARENT_NEXT_SCB))
                goto _fail_end;
 
@@ -1518,6 +1497,7 @@
                };
 
                spdifo_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFOSCB",(u32 
*)&spdifo_scb,SPDIFO_SCB_INST);
+
                snd_assert(spdifo_scb_desc, return -EIO);
                spdifi_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFISCB",(u32 
*)&spdifi_scb,SPDIFI_SCB_INST);
                snd_assert(spdifi_scb_desc, return -EIO);
@@ -1543,6 +1523,11 @@
                   is the FG task tree */
                fg_entry->parent_scb_ptr = spdifo_scb_desc;
 
+               /* for proc fs */
+               cs46xx_dsp_proc_register_scb_desc (chip,spdifo_scb_desc);
+               cs46xx_dsp_proc_register_scb_desc (chip,spdifi_scb_desc);
+               cs46xx_dsp_proc_register_scb_desc (chip,async_codec_scb_desc);
+
                /* Async MASTER ENABLE, affects both SPDIF input and output */
                snd_cs46xx_pokeBA0(chip, BA0_ASER_MASTER, 0x1 );
        }
@@ -1550,7 +1535,7 @@
        return 0;
 }
 
-int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip)
+int cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip)
 {
        dsp_spos_instance_t * ins = chip->dsp_spos_instance;
 
@@ -1560,29 +1545,11 @@
        /* SPDIF output MASTER ENABLE */
        cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0x80000000);
 
-       /* right and left validate bit 
-          NOTE: 0x80000000 and enables the SCMC protection on stream 
-       */
+       /* right and left validate bit */
        cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x00000000 | (1 << 13) | (1 << 12));
 
        /* monitor state */
-       ins->spdif_status_out = 1;
-
-       return 0;
-}
-
-int  cs46xx_dsp_disable_spdif_out (cs46xx_t *chip)
-{
-       dsp_spos_instance_t * ins = chip->dsp_spos_instance;
-
-       /* disable  SPDIF output FIFO slot */
-       snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, 0);
-
-       /* SPDIF output MASTER DISABLE */
-       cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0x0);
-
-       /* monitor state */
-       ins->spdif_status_out = 0;
+       ins->spdif_status_out |= DSP_SDPIF_STATUS_HW_ENABLED;
 
        return 0;
 }
diff --exclude=CVS -Naur alsa-kernel/pci/cs46xx/dsp_spos.h 
../cvs/alsa-kernel/pci/cs46xx/dsp_spos.h
--- alsa-kernel/pci/cs46xx/dsp_spos.h   Sat Nov  2 00:00:23 2002
+++ ../cvs/alsa-kernel/pci/cs46xx/dsp_spos.h    Sat Nov  2 19:27:36 2002
@@ -183,5 +183,14 @@
 #define SP_SPDOUT_CONTROL 0x804D
 #define SP_SPDOUT_CSUV    0x808E
 
+static inline void cs46xx_dsp_spos_update_scb (cs46xx_t * chip,dsp_scb_descriptor_t * 
+scb) 
+{
+       /* update nextSCB and subListPtr in SCB */
+       snd_cs46xx_poke(chip,
+                       (scb->address + SCBsubListPtr) << 2,
+                       (scb->sub_list_ptr->address << 0x10) |
+                       (scb->next_scb_ptr->address));  
+}
+
 #endif /* __DSP_SPOS_H__ */
 #endif /* CONFIG_SND_CS46XX_NEW_DSP  */
diff --exclude=CVS -Naur alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c 
../cvs/alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c
--- alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c   Sat Nov  2 00:00:23 2002
+++ ../cvs/alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c    Sun Nov  3 22:44:21 2002
@@ -150,17 +150,11 @@
                spin_lock_irqsave(&chip->reg_lock, flags);    
 
                /* update parent first entry in DSP RAM */
-               snd_cs46xx_poke(chip,
-                               (scb->parent_scb_ptr->address + SCBsubListPtr) << 2,
-                               (scb->parent_scb_ptr->sub_list_ptr->address << 0x10) |
-                               (scb->parent_scb_ptr->next_scb_ptr->address));
+               cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr);
 
                /* then update entry in DSP RAM */
-               snd_cs46xx_poke(chip,
-                               (scb->address + SCBsubListPtr) << 2,
-                               (scb->sub_list_ptr->address << 0x10) |
-                               (scb->next_scb_ptr->address));
-    
+               cs46xx_dsp_spos_update_scb(chip,scb);
+
                scb->parent_scb_ptr = NULL;
                spin_unlock_irqrestore(&chip->reg_lock, flags);
        }
@@ -173,6 +167,7 @@
   
        for (i = 0; i < dword_count ; ++i ) {
                writel(0, dst);
+               dst += 4;
        }  
 }
 
@@ -328,11 +323,9 @@
                }
 
                spin_lock_irqsave(&chip->reg_lock, flags);
+
                /* update entry in DSP RAM */
-               snd_cs46xx_poke(chip,
-                               (scb->parent_scb_ptr->address + SCBsubListPtr) << 2,
-                               (scb->parent_scb_ptr->sub_list_ptr->address << 0x10) |
-                               (scb->parent_scb_ptr->next_scb_ptr->address));
+               cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr);
 
                spin_unlock_irqrestore(&chip->reg_lock, flags);
        }
@@ -1242,6 +1235,83 @@
        return (ins->pcm_channels + pcm_index);
 }
 
+int cs46xx_dsp_pcm_channel_set_period (cs46xx_t * chip,
+                                      pcm_channel_descriptor_t * pcm_channel,
+                                      int period_size)
+{
+       u32 temp = snd_cs46xx_peek (chip,pcm_channel->pcm_reader_scb->address << 2);
+       temp &= ~DMA_RQ_C1_SOURCE_SIZE_MASK;
+
+       switch (period_size) {
+       case 2048:
+               temp |= DMA_RQ_C1_SOURCE_MOD1024;
+               break;
+       case 1024:
+               temp |= DMA_RQ_C1_SOURCE_MOD512;
+               break;
+       case 512:
+               temp |= DMA_RQ_C1_SOURCE_MOD256;
+               break;
+       case 256:
+               temp |= DMA_RQ_C1_SOURCE_MOD128;
+               break;
+       case 128:
+               temp |= DMA_RQ_C1_SOURCE_MOD64;
+               break;
+       case 64:
+               temp |= DMA_RQ_C1_SOURCE_MOD32;
+               break;                
+       case 32:
+               temp |= DMA_RQ_C1_SOURCE_MOD16;
+               break; 
+       default:
+               snd_printdd ("period size (%d) not supported by HW\n");
+               return -EINVAL;
+       }
+
+       snd_cs46xx_poke (chip,pcm_channel->pcm_reader_scb->address << 2,temp);
+
+       return 0;
+}
+
+int cs46xx_dsp_pcm_ostream_set_period (cs46xx_t * chip,
+                                      int period_size)
+{
+       u32 temp = snd_cs46xx_peek (chip,WRITEBACK_SCB_ADDR << 2);
+       temp &= ~DMA_RQ_C1_DEST_SIZE_MASK;
+
+       switch (period_size) {
+       case 2048:
+               temp |= DMA_RQ_C1_DEST_MOD1024;
+               break;
+       case 1024:
+               temp |= DMA_RQ_C1_DEST_MOD512;
+               break;
+       case 512:
+               temp |= DMA_RQ_C1_DEST_MOD256;
+               break;
+       case 256:
+               temp |= DMA_RQ_C1_DEST_MOD128;
+               break;
+       case 128:
+               temp |= DMA_RQ_C1_DEST_MOD64;
+               break;
+       case 64:
+               temp |= DMA_RQ_C1_DEST_MOD32;
+               break;                
+       case 32:
+               temp |= DMA_RQ_C1_DEST_MOD16;
+               break; 
+       default:
+               snd_printdd ("period size (%d) not supported by HW\n");
+               return -EINVAL;
+       }
+
+       snd_cs46xx_poke (chip,WRITEBACK_SCB_ADDR << 2,temp);
+
+       return 0;
+}
+
 void cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip,pcm_channel_descriptor_t * 
pcm_channel)
 {
        dsp_spos_instance_t * ins = chip->dsp_spos_instance;
@@ -1323,17 +1393,13 @@
        snd_assert (pcm_channel->pcm_reader_scb->parent_scb_ptr == NULL, ; );
        pcm_channel->pcm_reader_scb->parent_scb_ptr = parent_scb;
 
-       /* update entry in DSP RAM */
        spin_lock_irqsave(&chip->reg_lock, flags);
-       snd_cs46xx_poke(chip,
-                       (pcm_channel->pcm_reader_scb->address + SCBsubListPtr) << 2,
-                       (pcm_channel->pcm_reader_scb->sub_list_ptr->address << 0x10) |
-                       (pcm_channel->pcm_reader_scb->next_scb_ptr->address));
-    
-       snd_cs46xx_poke(chip,
-                       (parent_scb->address + SCBsubListPtr) << 2,
-                       (parent_scb->sub_list_ptr->address << 0x10) |
-                       (parent_scb->next_scb_ptr->address));
+
+       /* update SCB entry in DSP RAM */
+       cs46xx_dsp_spos_update_scb(chip,pcm_channel->pcm_reader_scb);
+
+       /* update parent SCB entry */
+       cs46xx_dsp_spos_update_scb(chip,parent_scb);
 
        pcm_channel->unlinked = 0;
        spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -1455,47 +1521,136 @@
        src->parent_scb_ptr = parent_scb;
 
        /* update entry in DSP RAM */
-       snd_cs46xx_poke(chip,
-                       (parent_scb->address + SCBsubListPtr) << 2,
-                       (parent_scb->sub_list_ptr->address << 0x10) |
-                       (parent_scb->next_scb_ptr->address));
+       cs46xx_dsp_spos_update_scb(chip,parent_scb);
   
        return 0;
 }
 
-int cs46xx_iec958_pre_open (cs46xx_t *chip)
+int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip)
 {
        dsp_spos_instance_t * ins = chip->dsp_spos_instance;
 
-       snd_assert (ins->spdif_pcm_input_scb != NULL);
-       snd_assert (ins->asynch_tx_scb->sub_list_ptr == ins->spdif_pcm_input_scb);
+       if ( ! (ins->spdif_status_out & DSP_SDPIF_STATUS_PLAYBACK_OPEN) ) {
+               cs46xx_dsp_enable_spdif_hw (chip);
+       }
+
+       /* dont touch anything if SPDIF is open */
+       if ( ins->spdif_status_out & DSP_SDPIF_STATUS_PLAYBACK_OPEN) {
+               /* when cs46xx_iec958_post_close(...) is called it
+                  will call this function if necesary depending on
+                  this bit */
+               ins->spdif_status_out |= DSP_SDPIF_STATUS_OUTPUT_ENABLED;
+
+               return -EBUSY;
+       }
+
+       snd_assert (ins->asynch_tx_scb == NULL, return -EINVAL);
+       snd_assert (ins->master_mix_scb->next_scb_ptr == ins->the_null_scb, return 
+-EINVAL);
+
+       /* reset output snooper sample buffer pointer */
+       snd_cs46xx_poke (chip, (ins->ref_snoop_scb->address + 2) << 2,
+                        (OUTPUT_SNOOP_BUFFER + 0x10) << 0x10 );
+       
+       /* The asynch. transfer task */
+       ins->asynch_tx_scb = 
+cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR,
+                                                               SPDIFO_SCB_INST,
+                                                               
+SPDIFO_IP_OUTPUT_BUFFER1,
+                                                               ins->master_mix_scb,
+                                                               
+SCB_ON_PARENT_NEXT_SCB);
+       if (!ins->asynch_tx_scb) return -ENOMEM;
+
+       ins->spdif_pcm_input_scb = 
+cs46xx_dsp_create_pcm_serial_input_scb(chip,"PCMSerialInput_II",
+                                                                         
+PCMSERIALINII_SCB_ADDR,
+                                                                         
+ins->ref_snoop_scb,
+                                                                         
+ins->asynch_tx_scb,
+                                                                         
+SCB_ON_PARENT_SUBLIST_SCB);
+  
+       
+       if (!ins->spdif_pcm_input_scb) return -ENOMEM;
 
-       /*cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x00000000 | (1 << 13) | (1 << 12) 
| (1 << 2)); */
+       /* monitor state */
+       ins->spdif_status_out |= DSP_SDPIF_STATUS_OUTPUT_ENABLED;
 
-       _dsp_unlink_scb (chip,ins->spdif_pcm_input_scb);
        return 0;
 }
 
-int cs46xx_iec958_post_close (cs46xx_t *chip)
+int  cs46xx_dsp_disable_spdif_out (cs46xx_t *chip)
 {
        dsp_spos_instance_t * ins = chip->dsp_spos_instance;
 
-       snd_assert (ins->spdif_pcm_input_scb != NULL);
-       snd_assert (ins->asynch_tx_scb->sub_list_ptr == ins->the_null_scb);
-       snd_assert (ins->spdif_pcm_input_scb->parent_scb_ptr == NULL);
+       /* dont touch anything if SPDIF is open */
+       if ( ins->spdif_status_out & DSP_SDPIF_STATUS_PLAYBACK_OPEN) {
+               ins->spdif_status_out &= ~DSP_SDPIF_STATUS_OUTPUT_ENABLED;
+               return -EBUSY;
+       }
+
+       /* check integrety */
+       snd_assert (ins->asynch_tx_scb != NULL, return -EINVAL);
+       snd_assert (ins->spdif_pcm_input_scb != NULL,return -EINVAL);
+       snd_assert (ins->master_mix_scb->next_scb_ptr == ins->asynch_tx_scb, return 
+-EINVAL);
+       snd_assert (ins->asynch_tx_scb->parent_scb_ptr == ins->master_mix_scb, return 
+-EINVAL);
+
+       cs46xx_dsp_remove_scb (chip,ins->spdif_pcm_input_scb);
+       cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb);
 
-       /* relink the SPDIF output PCM ref */
-       ins->asynch_tx_scb->sub_list_ptr = ins->spdif_pcm_input_scb;
-       ins->spdif_pcm_input_scb->parent_scb_ptr = ins->asynch_tx_scb;
+       ins->spdif_pcm_input_scb = NULL;
+       ins->asynch_tx_scb = NULL;
 
+       /* clear buffer to prevent any undesired noise */
+       _dsp_clear_sample_buffer(chip,SPDIFO_IP_OUTPUT_BUFFER1,256);
 
-       /* cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x00000000 | (1 << 13) | (1 << 
12)); */
+       /* monitor state */
+       ins->spdif_status_out  &= ~DSP_SDPIF_STATUS_OUTPUT_ENABLED;
 
-       /* update entry in DSP RAM */
-       snd_cs46xx_poke(chip,
-                       (ins->asynch_tx_scb->address + SCBsubListPtr) << 2,
-                       (ins->asynch_tx_scb->sub_list_ptr->address << 0x10) |
-                       (ins->asynch_tx_scb->next_scb_ptr->address));
 
+       return 0;
+}
+
+int cs46xx_iec958_pre_open (cs46xx_t *chip)
+{
+       dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+
+       if ( ins->spdif_status_out & DSP_SDPIF_STATUS_OUTPUT_ENABLED ) {
+               /* remove AsynchFGTxSCB and and PCMSerialInput_II */
+               cs46xx_dsp_disable_spdif_out (chip);
+
+               /* save state */
+               ins->spdif_status_out |= DSP_SDPIF_STATUS_OUTPUT_ENABLED;
+       }
+
+       /* Create the asynch. transfer task  for playback */
+       ins->asynch_tx_scb = 
+cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR,
+                                                               SPDIFO_SCB_INST,
+                                                               
+SPDIFO_IP_OUTPUT_BUFFER1,
+                                                               ins->master_mix_scb,
+                                                               
+SCB_ON_PARENT_NEXT_SCB);
+
+       /* cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x00000000 | (1 << 15) | 
+          (1 << 14) | (1 << 2) | (1 << 3)); */
+
+       ins->spdif_status_out  |= DSP_SDPIF_STATUS_PLAYBACK_OPEN;
+
+       return 0;
+}
+
+int cs46xx_iec958_post_close (cs46xx_t *chip)
+{
+       dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+
+       snd_assert (ins->asynch_tx_scb != NULL, return -EINVAL);
+
+       ins->spdif_status_out  &= ~DSP_SDPIF_STATUS_PLAYBACK_OPEN;
+
+       /*cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x00000000 | (1 << 13) | (1 << 
+12));*/
+       
+       /* deallocate stuff */
+       cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb);
+       ins->asynch_tx_scb = NULL;
+
+       /* restore state */
+       if ( ins->spdif_status_out & DSP_SDPIF_STATUS_OUTPUT_ENABLED ) {
+               cs46xx_dsp_enable_spdif_out (chip);
+       }
+       
        return 0;
 }


Reply via email to