static irqreturn_t snd_ad1889_interrupt(int irq, void *dev_id) { unsigned long st; struct snd_ad1889 *chip = dev_id; st = ad1889_readl(chip, AD_DMA_DISR); /* clear ISR */ ad1889_writel(chip, AD_DMA_DISR, st); st &= AD_INTR_MASK; if (unlikely(!st)) return IRQ_NONE; if (st & (AD_DMA_DISR_PMAI|AD_DMA_DISR_PTAI)) ad1889_debug("Unexpected master or target abort interrupt!\n"); if ((st & AD_DMA_DISR_WAVI) && chip->psubs) snd_pcm_period_elapsed(chip->psubs); if ((st & AD_DMA_DISR_ADCI) && chip->csubs) snd_pcm_period_elapsed(chip->csubs); return IRQ_HANDLED; }
static int snd_ad1889_free(struct snd_ad1889 *chip) { if (chip->irq < 0) goto skip_hw; spin_lock_irq(&chip->lock); ad1889_mute(chip); /* Turn off interrupt on count and zero DMA registers */ ad1889_channel_reset(chip, AD_CHAN_WAV | AD_CHAN_ADC); /* clear DISR. If we don't, we'd better jump off the Eiffel Tower */ ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PTAI | AD_DMA_DISR_PMAI); ad1889_readl(chip, AD_DMA_DISR); /* flush, dammit! */ spin_unlock_irq(&chip->lock); synchronize_irq(chip->irq); if (chip->irq >= 0) free_irq(chip->irq, chip); skip_hw: if (chip->iobase) iounmap(chip->iobase); pci_release_regions(chip->pci); pci_disable_device(chip->pci); kfree(chip); return 0; }
static int snd_ad1889_free(struct snd_ad1889 *chip) { if (chip->irq < 0) goto skip_hw; spin_lock_irq(&chip->lock); ad1889_mute(chip); ad1889_channel_reset(chip, AD_CHAN_WAV | AD_CHAN_ADC); ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PTAI | AD_DMA_DISR_PMAI); ad1889_readl(chip, AD_DMA_DISR); spin_unlock_irq(&chip->lock); if (chip->irq >= 0) free_irq(chip->irq, chip); skip_hw: if (chip->iobase) iounmap(chip->iobase); pci_release_regions(chip->pci); pci_disable_device(chip->pci); kfree(chip); return 0; }
/* this is called in atomic context with IRQ disabled. Must be as fast as possible and not sleep. DMA should be *triggered* by this call. The RAMC "ADEN" bit triggers DMA ADC On/Off */ static int snd_ad1889_capture_trigger(struct snd_pcm_substream *ss, int cmd) { u16 ramc; struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); ramc = ad1889_readw(chip, AD_DS_RAMC); switch (cmd) { case SNDRV_PCM_TRIGGER_START: /* enable DMA loop & interrupts */ ad1889_writew(chip, AD_DMA_ADC, AD_DMA_LOOP | AD_DMA_IM_CNT); ramc |= AD_DS_RAMC_ADEN; /* 1 to clear CHSS bit */ ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_ADCS); break; case SNDRV_PCM_TRIGGER_STOP: ramc &= ~AD_DS_RAMC_ADEN; break; default: return -EINVAL; } chip->ramc.reg = ramc; ad1889_writew(chip, AD_DS_RAMC, ramc); ad1889_readw(chip, AD_DS_RAMC); /* flush */ /* reset the chip when STOP - will disable IRQs */ if (cmd == SNDRV_PCM_TRIGGER_STOP) ad1889_channel_reset(chip, AD_CHAN_ADC); return 0; }
static int snd_ad1889_capture_trigger(struct snd_pcm_substream *ss, int cmd) { u16 ramc; struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); ramc = ad1889_readw(chip, AD_DS_RAMC); switch (cmd) { case SNDRV_PCM_TRIGGER_START: ad1889_writew(chip, AD_DMA_ADC, AD_DMA_LOOP | AD_DMA_IM_CNT); ramc |= AD_DS_RAMC_ADEN; ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_ADCS); break; case SNDRV_PCM_TRIGGER_STOP: ramc &= ~AD_DS_RAMC_ADEN; break; default: return -EINVAL; } chip->ramc.reg = ramc; ad1889_writew(chip, AD_DS_RAMC, ramc); ad1889_readw(chip, AD_DS_RAMC); if (cmd == SNDRV_PCM_TRIGGER_STOP) ad1889_channel_reset(chip, AD_CHAN_ADC); return 0; }
static int __devinit snd_ad1889_init(struct snd_ad1889 *chip) { ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */ ad1889_readw(chip, AD_DS_CCS); /* flush posted write */ mdelay(10); /* enable Master and Target abort interrupts */ ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE); return 0; }
static int __devinit snd_ad1889_init(struct snd_ad1889 *chip) { ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); ad1889_readw(chip, AD_DS_CCS); mdelay(10); ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE); return 0; }
/* this is called in atomic context with IRQ disabled. Must be as fast as possible and not sleep. DMA should be *triggered* by this call. The WSMC "WAEN" bit triggers DMA Wave On/Off */ static int snd_ad1889_playback_trigger(struct snd_pcm_substream *ss, int cmd) { u16 wsmc; struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); wsmc = ad1889_readw(chip, AD_DS_WSMC); switch (cmd) { case SNDRV_PCM_TRIGGER_START: /* enable DMA loop & interrupts */ ad1889_writew(chip, AD_DMA_WAV, AD_DMA_LOOP | AD_DMA_IM_CNT); wsmc |= AD_DS_WSMC_WAEN; /* 1 to clear CHSS bit */ ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_WAVS); ad1889_unmute(chip); break; case SNDRV_PCM_TRIGGER_STOP: ad1889_mute(chip); wsmc &= ~AD_DS_WSMC_WAEN; break; default: snd_BUG(); return -EINVAL; } chip->wave.reg = wsmc; ad1889_writew(chip, AD_DS_WSMC, wsmc); ad1889_readw(chip, AD_DS_WSMC); /* flush */ /* reset the chip when STOP - will disable IRQs */ if (cmd == SNDRV_PCM_TRIGGER_STOP) ad1889_channel_reset(chip, AD_CHAN_WAV); return 0; }
static int snd_ad1889_playback_trigger(struct snd_pcm_substream *ss, int cmd) { u16 wsmc; struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); wsmc = ad1889_readw(chip, AD_DS_WSMC); switch (cmd) { case SNDRV_PCM_TRIGGER_START: ad1889_writew(chip, AD_DMA_WAV, AD_DMA_LOOP | AD_DMA_IM_CNT); wsmc |= AD_DS_WSMC_WAEN; ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_WAVS); ad1889_unmute(chip); break; case SNDRV_PCM_TRIGGER_STOP: ad1889_mute(chip); wsmc &= ~AD_DS_WSMC_WAEN; break; default: snd_BUG(); return -EINVAL; } chip->wave.reg = wsmc; ad1889_writew(chip, AD_DS_WSMC, wsmc); ad1889_readw(chip, AD_DS_WSMC); if (cmd == SNDRV_PCM_TRIGGER_STOP) ad1889_channel_reset(chip, AD_CHAN_WAV); return 0; }
static inline void ad1889_load_wave_interrupt_count(struct snd_ad1889 *chip, u32 count) { ad1889_writel(chip, AD_DMA_WAVIB, count); ad1889_writel(chip, AD_DMA_WAVIC, count); }
static inline void ad1889_load_wave_buffer_count(struct snd_ad1889 *chip, u32 count) { ad1889_writel(chip, AD_DMA_WAVBC, count); ad1889_writel(chip, AD_DMA_WAVCC, count); }
static inline void ad1889_load_wave_buffer_address(struct snd_ad1889 *chip, u32 address) { ad1889_writel(chip, AD_DMA_WAVBA, address); ad1889_writel(chip, AD_DMA_WAVCA, address); }
static inline void ad1889_load_adc_buffer_count(struct snd_ad1889 *chip, u32 count) { ad1889_writel(chip, AD_DMA_ADCBC, count); ad1889_writel(chip, AD_DMA_ADCCC, count); }
static inline void ad1889_load_adc_buffer_address(struct snd_ad1889 *chip, u32 address) { ad1889_writel(chip, AD_DMA_ADCBA, address); ad1889_writel(chip, AD_DMA_ADCCA, address); }