📄 ad1816a_lib.c
字号:
if ((status & AD1816A_PLAYBACK_IRQ_PENDING) && chip->playback_substream) snd_pcm_period_elapsed(chip->playback_substream); if ((status & AD1816A_CAPTURE_IRQ_PENDING) && chip->capture_substream) snd_pcm_period_elapsed(chip->capture_substream); if ((status & AD1816A_TIMER_IRQ_PENDING) && chip->timer) snd_timer_interrupt(chip->timer, chip->timer->sticks); spin_lock(&chip->lock); snd_ad1816a_out(chip, AD1816A_INTERRUPT_STATUS, 0x00); spin_unlock(&chip->lock); return IRQ_HANDLED;}static struct snd_pcm_hardware snd_ad1816a_playback = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP_VALID), .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE), .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, .rate_min = 4000, .rate_max = 55200, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = (128*1024), .period_bytes_min = 64, .period_bytes_max = (128*1024), .periods_min = 1, .periods_max = 1024, .fifo_size = 0,};static struct snd_pcm_hardware snd_ad1816a_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP_VALID), .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE), .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, .rate_min = 4000, .rate_max = 55200, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = (128*1024), .period_bytes_min = 64, .period_bytes_max = (128*1024), .periods_min = 1, .periods_max = 1024, .fifo_size = 0,};#if 0 /* not used now */static int snd_ad1816a_timer_close(struct snd_timer *timer){ struct snd_ad1816a *chip = snd_timer_chip(timer); snd_ad1816a_close(chip, AD1816A_MODE_TIMER); return 0;}static int snd_ad1816a_timer_open(struct snd_timer *timer){ struct snd_ad1816a *chip = snd_timer_chip(timer); snd_ad1816a_open(chip, AD1816A_MODE_TIMER); return 0;}static unsigned long snd_ad1816a_timer_resolution(struct snd_timer *timer){ snd_assert(timer != NULL, return 0); return 10000;}static int snd_ad1816a_timer_start(struct snd_timer *timer){ unsigned short bits; unsigned long flags; struct snd_ad1816a *chip = snd_timer_chip(timer); spin_lock_irqsave(&chip->lock, flags); bits = snd_ad1816a_read(chip, AD1816A_INTERRUPT_ENABLE); if (!(bits & AD1816A_TIMER_ENABLE)) { snd_ad1816a_write(chip, AD1816A_TIMER_BASE_COUNT, timer->sticks & 0xffff); snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, AD1816A_TIMER_ENABLE, 0xffff); } spin_unlock_irqrestore(&chip->lock, flags); return 0;}static int snd_ad1816a_timer_stop(struct snd_timer *timer){ unsigned long flags; struct snd_ad1816a *chip = snd_timer_chip(timer); spin_lock_irqsave(&chip->lock, flags); snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, AD1816A_TIMER_ENABLE, 0x0000); spin_unlock_irqrestore(&chip->lock, flags); return 0;}static struct snd_timer_hardware snd_ad1816a_timer_table = { .flags = SNDRV_TIMER_HW_AUTO, .resolution = 10000, .ticks = 65535, .open = snd_ad1816a_timer_open, .close = snd_ad1816a_timer_close, .c_resolution = snd_ad1816a_timer_resolution, .start = snd_ad1816a_timer_start, .stop = snd_ad1816a_timer_stop,};#endif /* not used now */static int snd_ad1816a_playback_open(struct snd_pcm_substream *substream){ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; int error; if ((error = snd_ad1816a_open(chip, AD1816A_MODE_PLAYBACK)) < 0) return error; runtime->hw = snd_ad1816a_playback; snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max); snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max); chip->playback_substream = substream; return 0;}static int snd_ad1816a_capture_open(struct snd_pcm_substream *substream){ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; int error; if ((error = snd_ad1816a_open(chip, AD1816A_MODE_CAPTURE)) < 0) return error; runtime->hw = snd_ad1816a_capture; snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max); chip->capture_substream = substream; return 0;}static int snd_ad1816a_playback_close(struct snd_pcm_substream *substream){ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); chip->playback_substream = NULL; snd_ad1816a_close(chip, AD1816A_MODE_PLAYBACK); return 0;}static int snd_ad1816a_capture_close(struct snd_pcm_substream *substream){ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); chip->capture_substream = NULL; snd_ad1816a_close(chip, AD1816A_MODE_CAPTURE); return 0;}static void __devinit snd_ad1816a_init(struct snd_ad1816a *chip){ unsigned long flags; spin_lock_irqsave(&chip->lock, flags); snd_ad1816a_out(chip, AD1816A_INTERRUPT_STATUS, 0x00); snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, AD1816A_PLAYBACK_ENABLE | AD1816A_PLAYBACK_PIO, 0x00); snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, AD1816A_CAPTURE_ENABLE | AD1816A_CAPTURE_PIO, 0x00); snd_ad1816a_write(chip, AD1816A_INTERRUPT_ENABLE, 0x0000); snd_ad1816a_write_mask(chip, AD1816A_CHIP_CONFIG, AD1816A_CAPTURE_NOT_EQUAL | AD1816A_WSS_ENABLE, 0xffff); snd_ad1816a_write(chip, AD1816A_DSP_CONFIG, 0x0000); snd_ad1816a_write(chip, AD1816A_POWERDOWN_CTRL, 0x0000); spin_unlock_irqrestore(&chip->lock, flags);}static int __devinit snd_ad1816a_probe(struct snd_ad1816a *chip){ unsigned long flags; spin_lock_irqsave(&chip->lock, flags); switch (chip->version = snd_ad1816a_read(chip, AD1816A_VERSION_ID)) { case 0: chip->hardware = AD1816A_HW_AD1815; break; case 1: chip->hardware = AD1816A_HW_AD18MAX10; break; case 3: chip->hardware = AD1816A_HW_AD1816A; break; default: chip->hardware = AD1816A_HW_AUTO; } spin_unlock_irqrestore(&chip->lock, flags); return 0;}static int snd_ad1816a_free(struct snd_ad1816a *chip){ release_and_free_resource(chip->res_port); if (chip->irq >= 0) free_irq(chip->irq, (void *) chip); if (chip->dma1 >= 0) { snd_dma_disable(chip->dma1); free_dma(chip->dma1); } if (chip->dma2 >= 0) { snd_dma_disable(chip->dma2); free_dma(chip->dma2); } kfree(chip); return 0;}static int snd_ad1816a_dev_free(struct snd_device *device){ struct snd_ad1816a *chip = device->device_data; return snd_ad1816a_free(chip);}static const char __devinit *snd_ad1816a_chip_id(struct snd_ad1816a *chip){ switch (chip->hardware) { case AD1816A_HW_AD1816A: return "AD1816A"; case AD1816A_HW_AD1815: return "AD1815"; case AD1816A_HW_AD18MAX10: return "AD18max10"; default: snd_printk("Unknown chip version %d:%d.\n", chip->version, chip->hardware); return "AD1816A - unknown"; }}int __devinit snd_ad1816a_create(struct snd_card *card, unsigned long port, int irq, int dma1, int dma2, struct snd_ad1816a **rchip){ static struct snd_device_ops ops = { .dev_free = snd_ad1816a_dev_free, }; int error; struct snd_ad1816a *chip; *rchip = NULL; chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; chip->irq = -1; chip->dma1 = -1; chip->dma2 = -1; if ((chip->res_port = request_region(port, 16, "AD1816A")) == NULL) { snd_printk(KERN_ERR "ad1816a: can't grab port 0x%lx\n", port); snd_ad1816a_free(chip); return -EBUSY; } if (request_irq(irq, snd_ad1816a_interrupt, IRQF_DISABLED, "AD1816A", (void *) chip)) { snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq); snd_ad1816a_free(chip); return -EBUSY; } chip->irq = irq; if (request_dma(dma1, "AD1816A - 1")) { snd_printk(KERN_ERR "ad1816a: can't grab DMA1 %d\n", dma1); snd_ad1816a_free(chip); return -EBUSY; } chip->dma1 = dma1; if (request_dma(dma2, "AD1816A - 2")) { snd_printk(KERN_ERR "ad1816a: can't grab DMA2 %d\n", dma2); snd_ad1816a_free(chip); return -EBUSY; } chip->dma2 = dma2; chip->card = card; chip->port = port; spin_lock_init(&chip->lock); if ((error = snd_ad1816a_probe(chip))) { snd_ad1816a_free(chip); return error; } snd_ad1816a_init(chip); /* Register device */ if ((error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { snd_ad1816a_free(chip); return error; } *rchip = chip; return 0;}static struct snd_pcm_ops snd_ad1816a_playback_ops = { .open = snd_ad1816a_playback_open, .close = snd_ad1816a_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_ad1816a_hw_params, .hw_free = snd_ad1816a_hw_free, .prepare = snd_ad1816a_playback_prepare, .trigger = snd_ad1816a_playback_trigger, .pointer = snd_ad1816a_playback_pointer,};static struct snd_pcm_ops snd_ad1816a_capture_ops = {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -