.fifo_size =            0,
 };
 
-static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime)
-{
-       struct snd_emu10k1_pcm *epcm = runtime->private_data;
-
-       kfree(epcm);
-}
-
 /* open_playback callback */
 static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id)
 {
-       struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
-        struct snd_emu10k1_voice *channel = &(emu->p16v_voices[channel_id]);
-       struct snd_emu10k1_pcm *epcm;
        struct snd_pcm_runtime *runtime = substream->runtime;
        int err;
 
-       epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
-       /* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */
-
-       if (epcm == NULL)
-               return -ENOMEM;
-       epcm->emu = emu;
-       epcm->substream = substream;
        /*
        dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n",
                   substream->pcm->device, channel_id);
        */
-       runtime->private_data = epcm;
-       runtime->private_free = snd_p16v_pcm_free_substream;
   
        runtime->hw = snd_p16v_playback_hw;
 
-        channel->number = channel_id;
-
-        channel->use=1;
 #if 0 /* debug */
        dev_dbg(emu->card->dev,
                   "p16v: open channel_id=%d, channel=%p, use=0x%x\n",
               channel_id, chip, channel);
 #endif /* debug */
        /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */
-       channel->epcm = epcm;
        err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
        if (err < 0)
                 return err;
 
        return 0;
 }
+
 /* open_capture callback */
 static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream, int channel_id)
 {
-       struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
-       struct snd_emu10k1_voice *channel = &(emu->p16v_capture_voice);
-       struct snd_emu10k1_pcm *epcm;
        struct snd_pcm_runtime *runtime = substream->runtime;
        int err;
 
-       epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
-       /* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */
-
-       if (epcm == NULL)
-               return -ENOMEM;
-       epcm->emu = emu;
-       epcm->substream = substream;
        /*
        dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n",
                   substream->pcm->device, channel_id);
        */
-       runtime->private_data = epcm;
-       runtime->private_free = snd_p16v_pcm_free_substream;
   
        runtime->hw = snd_p16v_capture_hw;
 
-       channel->number = channel_id;
-
-       channel->use=1;
-#if 0 /* debug */
-       dev_dbg(emu->card->dev,
-                  "p16v: open channel_id=%d, channel=%p, use=0x%x\n",
-                  channel_id, channel, channel->use);
-       dev_dbg(emu->card->dev, "open:channel_id=%d, chip=%p, channel=%p\n",
-              channel_id, chip, channel);
-#endif /* debug */
-       /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */
-       channel->epcm = epcm;
        err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
        if (err < 0)
                return err;
 /* close callback */
 static int snd_p16v_pcm_close_playback(struct snd_pcm_substream *substream)
 {
-       struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
-       //struct snd_pcm_runtime *runtime = substream->runtime;
-       //struct snd_emu10k1_pcm *epcm = runtime->private_data;
-       emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use = 0;
-       /* FIXME: maybe zero others */
        return 0;
 }
 
 /* close callback */
 static int snd_p16v_pcm_close_capture(struct snd_pcm_substream *substream)
 {
-       struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
-       //struct snd_pcm_runtime *runtime = substream->runtime;
-       //struct snd_emu10k1_pcm *epcm = runtime->private_data;
-       emu->p16v_capture_voice.use = 0;
-       /* FIXME: maybe zero others */
        return 0;
 }
 
        spin_unlock_irqrestore(&emu->emu_lock, flags);
 }
 
+static void snd_p16v_interrupt(struct snd_emu10k1 *emu)
+{
+       unsigned int status;
+
+       while ((status = inl(emu->port + IPR2)) != 0) {
+               u32 mask = INTE2_PLAYBACK_CH_0_LOOP;  /* Full Loop */
+
+               /* dev_dbg(emu->card->dev, "p16v status=0x%x\n", status); */
+               if (status & mask) {
+                       struct snd_pcm_substream *substream =
+                                       emu->pcm_p16v->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+                       struct snd_pcm_runtime *runtime = substream->runtime;
+
+                       if (runtime && runtime->private_data) {
+                               snd_pcm_period_elapsed(substream);
+                       } else {
+                               dev_err(emu->card->dev,
+                                       "p16v: status: 0x%08x, mask=0x%08x\n",
+                                       status, mask);
+                       }
+               }
+               if (status & 0x110000) {
+                       struct snd_pcm_substream *substream =
+                                       emu->pcm_p16v->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+                       struct snd_pcm_runtime *runtime = substream->runtime;
+
+                       /* dev_info(emu->card->dev, "capture int found\n"); */
+                       if (runtime && runtime->private_data) {
+                               /* dev_info(emu->card->dev, "capture period_elapsed\n"); */
+                               snd_pcm_period_elapsed(substream);
+                       }
+               }
+               outl(status, emu->port + IPR2); /* ack all */
+       }
+}
+
 /* trigger_playback callback */
 static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
                                    int cmd)
 {
        struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime;
-       struct snd_emu10k1_pcm *epcm;
        int channel;
        int result = 0;
         struct snd_pcm_substream *s;
                    s->stream != SNDRV_PCM_STREAM_PLAYBACK)
                        continue;
                runtime = s->runtime;
-               epcm = runtime->private_data;
                channel = substream->pcm->device-emu->p16v_device_offset;
                /* dev_dbg(emu->card->dev, "p16v channel=%d\n", channel); */
-               epcm->running = running;
+               runtime->private_data = (void *)(ptrdiff_t)running;
                basic |= (0x1<<channel);
                inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel);
                 snd_pcm_trigger_done(s, substream);
 {
        struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
-       struct snd_emu10k1_pcm *epcm = runtime->private_data;
        int channel = 0;
        int result = 0;
        u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP;
        case SNDRV_PCM_TRIGGER_START:
                snd_p16v_intr_enable(emu, inte);
                snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
-               epcm->running = 1;
+               runtime->private_data = (void *)1;
                break;
        case SNDRV_PCM_TRIGGER_STOP:
                snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
                snd_p16v_intr_disable(emu, inte);
                //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
-               epcm->running = 0;
+               runtime->private_data = NULL;
                break;
        default:
                result = -EINVAL;
 {
        struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
-       struct snd_emu10k1_pcm *epcm = runtime->private_data;
        snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
        int channel = substream->pcm->device - emu->p16v_device_offset;
-       if (!epcm->running)
+
+       if (!runtime->private_data)
                return 0;
 
        ptr3 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel);
 {
        struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
-       struct snd_emu10k1_pcm *epcm = runtime->private_data;
        snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
        int channel = 0;
 
-       if (!epcm->running)
+       if (!runtime->private_data)
                return 0;
 
        ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel);
        pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
        strcpy(pcm->name, "p16v");
        emu->pcm_p16v = pcm;
+       emu->p16v_interrupt = snd_p16v_interrupt;
 
        for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; 
            substream;