static int snd_ad1816a_capture_prepare(struct snd_pcm_substream *substream) { struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); unsigned long flags; struct snd_pcm_runtime *runtime = substream->runtime; unsigned int size, rate; spin_lock_irqsave(&chip->lock, flags); chip->c_dma_size = size = snd_pcm_lib_buffer_bytes(substream); snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, AD1816A_CAPTURE_ENABLE | AD1816A_CAPTURE_PIO, 0x00); snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); rate = runtime->rate; if (chip->clock_freq) rate = (rate * 33000) / chip->clock_freq; snd_ad1816a_write(chip, AD1816A_CAPTURE_SAMPLE_RATE, rate); snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, AD1816A_FMT_ALL | AD1816A_FMT_STEREO, snd_ad1816a_get_format(chip, runtime->format, runtime->channels)); snd_ad1816a_write(chip, AD1816A_CAPTURE_BASE_COUNT, snd_pcm_lib_period_bytes(substream) / 4 - 1); spin_unlock_irqrestore(&chip->lock, flags); return 0; }
static int snd_ad1816a_trigger(struct snd_ad1816a *chip, unsigned char what, int channel, int cmd, int iscapture) { int error = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_STOP: spin_lock(&chip->lock); cmd = (cmd == SNDRV_PCM_TRIGGER_START) ? 0xff: 0x00; /* if (what & AD1816A_PLAYBACK_ENABLE) */ /* That is not valid, because playback and capture enable * are the same bit pattern, just to different addresses */ if (! iscapture) snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, AD1816A_PLAYBACK_ENABLE, cmd); else snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, AD1816A_CAPTURE_ENABLE, cmd); spin_unlock(&chip->lock); break; default: snd_printk(KERN_WARNING "invalid trigger mode 0x%x.\n", what); error = -EINVAL; } return error; }
static void snd_ad1816a_close(struct snd_ad1816a *chip, unsigned int mode) { unsigned long flags; spin_lock_irqsave(&chip->lock, flags); switch ((mode &= AD1816A_MODE_OPEN)) { case AD1816A_MODE_PLAYBACK: snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, AD1816A_PLAYBACK_IRQ_PENDING, 0x00); snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, AD1816A_PLAYBACK_IRQ_ENABLE, 0x0000); break; case AD1816A_MODE_CAPTURE: snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, AD1816A_CAPTURE_IRQ_PENDING, 0x00); snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, AD1816A_CAPTURE_IRQ_ENABLE, 0x0000); break; case AD1816A_MODE_TIMER: snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, AD1816A_TIMER_IRQ_PENDING, 0x00); snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, AD1816A_TIMER_IRQ_ENABLE, 0x0000); } if (!((chip->mode &= ~mode) & AD1816A_MODE_OPEN)) chip->mode = 0; spin_unlock_irqrestore(&chip->lock, flags); }
static int snd_ad1816a_open(struct snd_ad1816a *chip, unsigned int mode) { unsigned long flags; spin_lock_irqsave(&chip->lock, flags); if (chip->mode & mode) { spin_unlock_irqrestore(&chip->lock, flags); return -EAGAIN; } switch ((mode &= AD1816A_MODE_OPEN)) { case AD1816A_MODE_PLAYBACK: snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, AD1816A_PLAYBACK_IRQ_PENDING, 0x00); snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, AD1816A_PLAYBACK_IRQ_ENABLE, 0xffff); break; case AD1816A_MODE_CAPTURE: snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, AD1816A_CAPTURE_IRQ_PENDING, 0x00); snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, AD1816A_CAPTURE_IRQ_ENABLE, 0xffff); break; case AD1816A_MODE_TIMER: snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, AD1816A_TIMER_IRQ_PENDING, 0x00); snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, AD1816A_TIMER_IRQ_ENABLE, 0xffff); } chip->mode |= mode; spin_unlock_irqrestore(&chip->lock, flags); return 0; }
static int snd_ad1816a_trigger(struct snd_ad1816a *chip, unsigned char what, int channel, int cmd, int iscapture) { int error = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_STOP: spin_lock(&chip->lock); cmd = (cmd == SNDRV_PCM_TRIGGER_START) ? 0xff: 0x00; if (! iscapture) snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, AD1816A_PLAYBACK_ENABLE, cmd); else snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, AD1816A_CAPTURE_ENABLE, cmd); spin_unlock(&chip->lock); break; default: snd_printk(KERN_WARNING "invalid trigger mode 0x%x.\n", what); error = -EINVAL; } return error; }
static int snd_ad1816a_playback_prepare(snd_pcm_substream_t *substream) { ad1816a_t *chip = snd_pcm_substream_chip(substream); unsigned long flags; snd_pcm_runtime_t *runtime = substream->runtime; unsigned int size; spin_lock_irqsave(&chip->lock, flags); chip->p_dma_size = size = snd_pcm_lib_buffer_bytes(substream); snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, AD1816A_PLAYBACK_ENABLE | AD1816A_PLAYBACK_PIO, 0x00); snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); snd_ad1816a_write(chip, AD1816A_PLAYBACK_SAMPLE_RATE, runtime->rate); snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, AD1816A_FMT_ALL | AD1816A_FMT_STEREO, snd_ad1816a_get_format(chip, runtime->format, runtime->channels)); snd_ad1816a_write(chip, AD1816A_PLAYBACK_BASE_COUNT, snd_pcm_lib_period_bytes(substream) / 4 - 1); spin_unlock_irqrestore(&chip->lock, flags); 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); }