X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fpci%2Femu10k1%2Firq.c;h=4f18f7e8bcfb11842bc261d14c5238979c65985e;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=70f4020603c2cc09a82adc5e1049996b71c2b698;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c index 70f402060..4f18f7e8b 100644 --- a/sound/pci/emu10k1/irq.c +++ b/sound/pci/emu10k1/irq.c @@ -30,18 +30,22 @@ #include #include -irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) { - emu10k1_t *emu = dev_id; - unsigned int status, orig_status; + struct snd_emu10k1 *emu = dev_id; + unsigned int status, status2, orig_status, orig_status2; int handled = 0; while ((status = inl(emu->port + IPR)) != 0) { - // printk("irq - status = 0x%x\n", status); + //snd_printk(KERN_INFO "emu10k1 irq - status = 0x%x\n", status); orig_status = status; handled = 1; + if ((status & 0xffffffff) == 0xffffffff) { + snd_printk(KERN_INFO "snd-emu10k1: Suspected sound card removal\n"); + break; + } if (status & IPR_PCIERROR) { - snd_printk("interrupt: PCI error\n"); + snd_printk(KERN_ERR "interrupt: PCI error\n"); snd_emu10k1_intr_disable(emu, INTE_PCIERRORENABLE); status &= ~IPR_PCIERROR; } @@ -56,7 +60,7 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) int voice; int voice_max = status & IPR_CHANNELNUMBERMASK; u32 val; - emu10k1_voice_t *pvoice = emu->voices; + struct snd_emu10k1_voice *pvoice = emu->voices; val = snd_emu10k1_ptr_read(emu, CLIPL, 0); for (voice = 0; voice <= voice_max; voice++) { @@ -73,6 +77,21 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) val >>= 1; pvoice++; } + val = snd_emu10k1_ptr_read(emu, HLIPL, 0); + for (voice = 0; voice <= voice_max; voice++) { + if (voice == 0x20) + val = snd_emu10k1_ptr_read(emu, HLIPH, 0); + if (val & 1) { + if (pvoice->use && pvoice->interrupt != NULL) { + pvoice->interrupt(emu, pvoice); + snd_emu10k1_voice_half_loop_intr_ack(emu, voice); + } else { + snd_emu10k1_voice_half_loop_intr_disable(emu, voice); + } + } + val >>= 1; + pvoice++; + } status &= ~IPR_CHANNELLOOP; } status &= ~IPR_CHANNELNUMBERMASK; @@ -132,6 +151,33 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE); status &= ~IPR_FXDSP; } + if (status & IPR_P16V) { + while ((status2 = inl(emu->port + IPR2)) != 0) { + u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */ + struct snd_emu10k1_voice *pvoice = &(emu->p16v_voices[0]); + struct snd_emu10k1_voice *cvoice = &(emu->p16v_capture_voice); + + //printk(KERN_INFO "status2=0x%x\n", status2); + orig_status2 = status2; + if(status2 & mask) { + if(pvoice->use) { + snd_pcm_period_elapsed(pvoice->epcm->substream); + } else { + snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use); + } + } + if(status2 & 0x110000) { + //printk(KERN_INFO "capture int found\n"); + if(cvoice->use) { + //printk(KERN_INFO "capture period_elapsed\n"); + snd_pcm_period_elapsed(cvoice->epcm->substream); + } + } + outl(orig_status2, emu->port + IPR2); /* ack all */ + } + status &= ~IPR_P16V; + } + if (status) { unsigned int bits; snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);