コード例 #1
0
static int
atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
	unsigned long camr, ptcr = 0;
	int retval = 0;

	camr = ac97c_readl(chip, CAMR);
	ptcr = readl(chip->regs + ATMEL_PDC_PTSR);

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
	case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
	case SNDRV_PCM_TRIGGER_START:
		if (cpu_is_at32ap7000()) {
			retval = dw_dma_cyclic_start(chip->dma.rx_chan);
			if (retval)
				goto out;
		} else {
			ptcr = ATMEL_PDC_RXTEN;
		}
		camr |= AC97C_CMR_CENA | AC97C_CSR_ENDRX;
		break;
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
	case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
	case SNDRV_PCM_TRIGGER_STOP:
		if (cpu_is_at32ap7000())
			dw_dma_cyclic_stop(chip->dma.rx_chan);
		else
			ptcr |= (ATMEL_PDC_RXTDIS);
		if (chip->opened <= 1)
			camr &= ~AC97C_CMR_CENA;
		break;
	default:
		retval = -EINVAL;
		break;
	}

	ac97c_writel(chip, CAMR, camr);
	if (!cpu_is_at32ap7000())
		writel(ptcr, chip->regs + ATMEL_PDC_PTCR);
out:
	return retval;
}
コード例 #2
0
static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
{
	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
	struct snd_pcm_runtime *runtime = substream->runtime;
	int block_size = frames_to_bytes(runtime, runtime->period_size);
	unsigned long word = ac97c_readl(chip, ICA);
	int retval;

	chip->period = 0;
	word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));

	/* assign channels to AC97C channel A */
	switch (runtime->channels) {
	case 1:
		word |= AC97C_CH_ASSIGN(PCM_LEFT, A);
		break;
	case 2:
		word |= AC97C_CH_ASSIGN(PCM_LEFT, A)
			| AC97C_CH_ASSIGN(PCM_RIGHT, A);
		break;
	default:
		/* TODO: support more than two channels */
		return -EINVAL;
	}
	ac97c_writel(chip, ICA, word);

	/* configure sample format and size */
	word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;

	switch (runtime->format) {
	case SNDRV_PCM_FORMAT_S16_LE:
		word |= AC97C_CMR_CEM_LITTLE;
		break;
	case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
		word &= ~(AC97C_CMR_CEM_LITTLE);
		break;
	default:
		word = ac97c_readl(chip, ICA);
		word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
		ac97c_writel(chip, ICA, word);
		return -EINVAL;
	}

	/* Enable overrun interrupt on channel A */
	word |= AC97C_CSR_OVRUN;

	ac97c_writel(chip, CAMR, word);
	/* Enable channel A event interrupt */
	word = ac97c_readl(chip, IMR);
	word |= AC97C_SR_CAEVT;
	ac97c_writel(chip, IER, /*word*/AC97C_SR_CAEVT);

	/* Enable channel A event interrupt */
	/*word = ac97c_readl(chip, IMR);
	word |= AC97C_SR_CAEVT;
	ac97c_writel(chip, IER, word);*/

	/* set variable rate if needed */
	if (runtime->rate != 48000) {
		word = ac97c_readl(chip, MR);
		word |= AC97C_MR_VRA;
		ac97c_writel(chip, MR, word);
	} else {
		word = ac97c_readl(chip, MR);
		word &= ~(AC97C_MR_VRA);
		ac97c_writel(chip, MR, word);
	}

	retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE,
			runtime->rate);
	if (retval)
		dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n",
				runtime->rate);

	if (cpu_is_at32ap7000()) {
		if (!test_bit(DMA_RX_READY, &chip->flags))
			retval = atmel_ac97c_prepare_dma(chip, substream,
					DMA_FROM_DEVICE);
	} else {
		/* Initialize and start the PDC */
		writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR);
		writel(block_size / 2, chip->regs + ATMEL_PDC_RCR);
		writel(runtime->dma_addr + block_size,
				chip->regs + ATMEL_PDC_RNPR);
		writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR);
	}

	return retval;
}