📄 es1688_lib.c
字号:
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));}static int snd_es1688_hw_free(snd_pcm_substream_t * substream){ return snd_pcm_lib_free_pages(substream);}static int snd_es1688_playback_prepare(snd_pcm_substream_t * substream){ unsigned long flags; es1688_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; unsigned int size = snd_pcm_lib_buffer_bytes(substream); unsigned int count = snd_pcm_lib_period_bytes(substream); chip->dma_size = size; spin_lock_irqsave(&chip->reg_lock, flags); snd_es1688_reset(chip); snd_es1688_set_rate(chip, substream); snd_es1688_write(chip, 0xb8, 4); /* auto init DMA mode */ snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels)); snd_es1688_write(chip, 0xb9, 2); /* demand mode (4 bytes/request) */ if (runtime->channels == 1) { if (snd_pcm_format_width(runtime->format) == 8) { /* 8. bit mono */ snd_es1688_write(chip, 0xb6, 0x80); snd_es1688_write(chip, 0xb7, 0x51); snd_es1688_write(chip, 0xb7, 0xd0); } else { /* 16. bit mono */ snd_es1688_write(chip, 0xb6, 0x00); snd_es1688_write(chip, 0xb7, 0x71); snd_es1688_write(chip, 0xb7, 0xf4); } } else { if (snd_pcm_format_width(runtime->format) == 8) { /* 8. bit stereo */ snd_es1688_write(chip, 0xb6, 0x80); snd_es1688_write(chip, 0xb7, 0x51); snd_es1688_write(chip, 0xb7, 0x98); } else { /* 16. bit stereo */ snd_es1688_write(chip, 0xb6, 0x00); snd_es1688_write(chip, 0xb7, 0x71); snd_es1688_write(chip, 0xb7, 0xbc); } } snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50); snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50); snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKON); spin_unlock_irqrestore(&chip->reg_lock, flags); /* --- */ count = -count; snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); spin_lock_irqsave(&chip->reg_lock, flags); snd_es1688_write(chip, 0xa4, (unsigned char) count); snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8)); spin_unlock_irqrestore(&chip->reg_lock, flags); return 0;}static int snd_es1688_playback_trigger(snd_pcm_substream_t * substream, int cmd){ es1688_t *chip = snd_pcm_substream_chip(substream); return snd_es1688_trigger(chip, cmd, 0x05);}static int snd_es1688_capture_prepare(snd_pcm_substream_t * substream){ unsigned long flags; es1688_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; unsigned int size = snd_pcm_lib_buffer_bytes(substream); unsigned int count = snd_pcm_lib_period_bytes(substream); chip->dma_size = size; spin_lock_irqsave(&chip->reg_lock, flags); snd_es1688_reset(chip); snd_es1688_set_rate(chip, substream); snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKOFF); snd_es1688_write(chip, 0xb8, 0x0e); /* auto init DMA mode */ snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels)); snd_es1688_write(chip, 0xb9, 2); /* demand mode (4 bytes/request) */ if (runtime->channels == 1) { if (snd_pcm_format_width(runtime->format) == 8) { /* 8. bit mono */ snd_es1688_write(chip, 0xb7, 0x51); snd_es1688_write(chip, 0xb7, 0xd0); } else { /* 16. bit mono */ snd_es1688_write(chip, 0xb7, 0x71); snd_es1688_write(chip, 0xb7, 0xf4); } } else { if (snd_pcm_format_width(runtime->format) == 8) { /* 8. bit stereo */ snd_es1688_write(chip, 0xb7, 0x51); snd_es1688_write(chip, 0xb7, 0x98); } else { /* 16. bit stereo */ snd_es1688_write(chip, 0xb7, 0x71); snd_es1688_write(chip, 0xb7, 0xbc); } } snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50); snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50); spin_unlock_irqrestore(&chip->reg_lock, flags); /* --- */ count = -count; snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); spin_lock_irqsave(&chip->reg_lock, flags); snd_es1688_write(chip, 0xa4, (unsigned char) count); snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8)); spin_unlock_irqrestore(&chip->reg_lock, flags); return 0;}static int snd_es1688_capture_trigger(snd_pcm_substream_t * substream, int cmd){ es1688_t *chip = snd_pcm_substream_chip(substream); return snd_es1688_trigger(chip, cmd, 0x0f);}irqreturn_t snd_es1688_interrupt(int irq, void *dev_id, struct pt_regs *regs){ es1688_t *chip = snd_magic_cast(es1688_t, dev_id, return IRQ_NONE); if (chip->trigger_value == 0x05) /* ok.. playback is active */ snd_pcm_period_elapsed(chip->playback_substream); if (chip->trigger_value == 0x0f) /* ok.. capture is active */ snd_pcm_period_elapsed(chip->capture_substream); inb(ES1688P(chip, DATA_AVAIL)); /* ack interrupt */ return IRQ_HANDLED;}static snd_pcm_uframes_t snd_es1688_playback_pointer(snd_pcm_substream_t * substream){ es1688_t *chip = snd_pcm_substream_chip(substream); size_t ptr; if (chip->trigger_value != 0x05) return 0; ptr = snd_dma_pointer(chip->dma8, chip->dma_size); return bytes_to_frames(substream->runtime, ptr);}static snd_pcm_uframes_t snd_es1688_capture_pointer(snd_pcm_substream_t * substream){ es1688_t *chip = snd_pcm_substream_chip(substream); size_t ptr; if (chip->trigger_value != 0x0f) return 0; ptr = snd_dma_pointer(chip->dma8, chip->dma_size); return bytes_to_frames(substream->runtime, ptr);}/* */static snd_pcm_hardware_t snd_es1688_playback ={ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP_VALID), .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, .rate_min = 4000, .rate_max = 48000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = 65536, .period_bytes_min = 64, .period_bytes_max = 65536, .periods_min = 1, .periods_max = 1024, .fifo_size = 0,};static snd_pcm_hardware_t snd_es1688_capture ={ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP_VALID), .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, .rate_min = 4000, .rate_max = 48000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = 65536, .period_bytes_min = 64, .period_bytes_max = 65536, .periods_min = 1, .periods_max = 1024, .fifo_size = 0,};/* */static int snd_es1688_playback_open(snd_pcm_substream_t * substream){ es1688_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; if (chip->capture_substream != NULL) return -EAGAIN; chip->playback_substream = substream; runtime->hw = snd_es1688_playback; snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_clocks); return 0;}static int snd_es1688_capture_open(snd_pcm_substream_t * substream){ es1688_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; if (chip->playback_substream != NULL) return -EAGAIN; chip->capture_substream = substream; runtime->hw = snd_es1688_capture; snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_clocks); return 0;}static int snd_es1688_playback_close(snd_pcm_substream_t * substream){ es1688_t *chip = snd_pcm_substream_chip(substream); chip->playback_substream = NULL; return 0;}static int snd_es1688_capture_close(snd_pcm_substream_t * substream){ es1688_t *chip = snd_pcm_substream_chip(substream); chip->capture_substream = NULL; return 0;}static int snd_es1688_free(es1688_t *chip){ if (chip->res_port) { snd_es1688_init(chip, 0); release_resource(chip->res_port); kfree_nocheck(chip->res_port); } if (chip->irq >= 0) free_irq(chip->irq, (void *) chip); if (chip->dma8 >= 0) { disable_dma(chip->dma8); free_dma(chip->dma8); } snd_magic_kfree(chip); return 0;}static int snd_es1688_dev_free(snd_device_t *device){ es1688_t *chip = snd_magic_cast(es1688_t, device->device_data, return -ENXIO); return snd_es1688_free(chip);}static const char *snd_es1688_chip_id(es1688_t *chip){ static char tmp[16]; sprintf(tmp, "ES%s688 rev %i", chip->hardware == ES1688_HW_688 ? "" : "1", chip->version & 0x0f); return tmp;}int snd_es1688_create(snd_card_t * card, unsigned long port, unsigned long mpu_port, int irq, int mpu_irq, int dma8, unsigned short hardware, es1688_t **rchip){ static snd_device_ops_t ops = { .dev_free = snd_es1688_dev_free, }; es1688_t *chip; int err; *rchip = NULL; chip = snd_magic_kcalloc(es1688_t, 0, GFP_KERNEL); if (chip == NULL) return -ENOMEM; chip->irq = -1; chip->dma8 = -1; if ((chip->res_port = request_region(port + 4, 12, "ES1688")) == NULL) { snd_printk(KERN_ERR "es1688: can't grab port 0x%lx\n", port + 4); snd_es1688_free(chip); return -EBUSY; } if (request_irq(irq, snd_es1688_interrupt, SA_INTERRUPT, "ES1688", (void *) chip)) { snd_printk(KERN_ERR "es1688: can't grab IRQ %d\n", irq); snd_es1688_free(chip); return -EBUSY; } chip->irq = irq; if (request_dma(dma8, "ES1688")) { snd_printk(KERN_ERR "es1688: can't grab DMA8 %d\n", dma8); snd_es1688_free(chip); return -EBUSY; } chip->dma8 = dma8; spin_lock_init(&chip->reg_lock); spin_lock_init(&chip->mixer_lock); chip->card = card; chip->port = port; mpu_port &= ~0x000f; if (mpu_port < 0x300 || mpu_port > 0x330) mpu_port = 0; chip->mpu_port = mpu_port; chip->mpu_irq = mpu_irq; chip->hardware = hardware; if ((err = snd_es1688_probe(chip)) < 0) { snd_es1688_free(chip); return err; } if ((err = snd_es1688_init(chip, 1)) < 0) { snd_es1688_free(chip); return err; } /* Register device */ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { snd_es1688_free(chip); return err; } *rchip = chip; return 0;}static snd_pcm_ops_t snd_es1688_playback_ops = { .open = snd_es1688_playback_open, .close = snd_es1688_playback_close, .ioctl = snd_es1688_ioctl, .hw_params = snd_es1688_hw_params, .hw_free = snd_es1688_hw_free,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -