static void ad1889_interrupt(int irq, void *dev_id, struct pt_regs *regs) { u32 stat; ad1889_dev_t *dev = (ad1889_dev_t *)dev_id; stat = AD1889_READL(dev, AD_DMADISR); /* clear ISR */ AD1889_WRITEL(dev, AD_DMADISR, stat); if (stat & 0x8) { /* WAVI */ DBG("WAV interrupt\n"); dev->stats.wav_intrs++; if (dev->state[AD_WAV_STATE].dmabuf.ready) { ad1889_stop_wav(&dev->state[AD_WAV_STATE]); /* clean up */ ad1889_start_wav(&dev->state[AD_WAV_STATE]); /* start new */ } } if (stat & 0x2 && dev->state[AD_ADC_STATE].dmabuf.ready) { /* ADCI */ DBG("ADC interrupt\n"); dev->stats.adc_intrs++; } }
static irqreturn_t ad1889_interrupt(int irq, void *dev_id) { u32 stat; ad1889_dev_t *dev = (ad1889_dev_t *)dev_id; stat = AD1889_READL(dev, AD_DMA_DISR); /* clear ISR */ AD1889_WRITEL(dev, AD_DMA_DISR, stat); if (stat & 0x8) { /* WAVI */ DBG("WAV interrupt\n"); dev->stats.wav_intrs++; if (dev->state[AD_WAV_STATE].dmabuf.ready) { ad1889_stop_wav(&dev->state[AD_WAV_STATE]); /* clean up */ ad1889_start_wav(&dev->state[AD_WAV_STATE]); /* start new */ } } if ((stat & 0x2) && dev->state[AD_ADC_STATE].dmabuf.ready) { /* ADCI */ DBG("ADC interrupt\n"); dev->stats.adc_intrs++; } if(stat) return IRQ_HANDLED; return IRQ_NONE; }
static void ad1889_start_wav(ad1889_state_t *state) { unsigned long flags; struct dmabuf *dmabuf = &state->dmabuf; int cnt; u16 tmp; spin_lock_irqsave(&state->card->lock, flags); if (dmabuf->dma_len) /* DMA already in flight */ goto skip_dma; /* setup dma */ cnt = dmabuf->wr_ptr - dmabuf->rd_ptr; if (cnt == 0) /* done - don't need to do anything */ goto skip_dma; /* If the wr_ptr has wrapped, only map to the end */ if (cnt < 0) cnt = DMA_SIZE - dmabuf->rd_ptr; dmabuf->dma_handle = pci_map_single(ad1889_dev->pci, dmabuf->rawbuf + dmabuf->rd_ptr, cnt, PCI_DMA_TODEVICE); dmabuf->dma_len = cnt; dmabuf->ready = 1; DBG("Starting playback at 0x%p for %ld bytes\n", dmabuf->rawbuf + dmabuf->rd_ptr, dmabuf->dma_len); /* load up the current register set */ AD1889_WRITEL(ad1889_dev, AD_DMAWAVCC, cnt); AD1889_WRITEL(ad1889_dev, AD_DMAWAVICC, cnt); AD1889_WRITEL(ad1889_dev, AD_DMAWAVCA, dmabuf->dma_handle); /* TODO: for now we load the base registers with the same thing */ AD1889_WRITEL(ad1889_dev, AD_DMAWAVBC, cnt); AD1889_WRITEL(ad1889_dev, AD_DMAWAVIBC, cnt); AD1889_WRITEL(ad1889_dev, AD_DMAWAVBA, dmabuf->dma_handle); /* and we're off to the races... */ AD1889_WRITEL(ad1889_dev, AD_DMACHSS, 0x8); tmp = AD1889_READW(ad1889_dev, AD_DSWSMC); tmp |= 0x0400; /* set WAEN */ AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp); (void) AD1889_READW(ad1889_dev, AD_DSWSMC); /* flush posted PCI write */ dmabuf->enable |= DAC_RUNNING; skip_dma: spin_unlock_irqrestore(&state->card->lock, flags); }
static void ad1889_initcfg(ad1889_dev_t *dev) { u16 tmp16; u32 tmp32; /* make sure the interrupt bits are setup the way we want */ tmp32 = AD1889_READL(dev, AD_DMAWAVCTRL); tmp32 &= ~0xff; /* flat dma, no sg, mask out the intr bits */ tmp32 |= 0x6; /* intr on count, loop */ AD1889_WRITEL(dev, AD_DMAWAVCTRL, tmp32); /* unmute... */ tmp16 = AD1889_READW(dev, AD_DSWADA); tmp16 &= ~0x8080; AD1889_WRITEW(dev, AD_DSWADA, tmp16); }