static int atmel_ac97c_playback_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, OCA);
	int retval;

	chip->playback_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, OCA, word);

	/* configure sample format and size */
	word = ac97c_readl(chip, CAMR);
	if (chip->opened <= 1)
		word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;
	else
		word |= AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;

	switch (runtime->format) {
	case SNDRV_PCM_FORMAT_S16_LE:
		if (cpu_is_at32ap7000())
			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, OCA);
		word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
		ac97c_writel(chip, OCA, word);
		return -EINVAL;
	}

	/* Enable underrun interrupt on channel A */
	word |= AC97C_CSR_UNRUN;

	ac97c_writel(chip, CAMR, word);

	/* 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_FRONT_DAC_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_TX_READY, &chip->flags))
			retval = atmel_ac97c_prepare_dma(chip, substream,
					DMA_TO_DEVICE);
	} else {
		/* Initialize and start the PDC */
		writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR);
		writel(block_size / 2, chip->regs + ATMEL_PDC_TCR);
		writel(runtime->dma_addr + block_size,
				chip->regs + ATMEL_PDC_TNPR);
		writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR);
	}

	return retval;
}
Beispiel #2
0
static int snd_cs5535audio_capture_prepare(struct snd_pcm_substream *substream)
{
	struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
	return snd_ac97_set_rate(cs5535au->ac97, AC97_PCM_LR_ADC_RATE,
				 substream->runtime->rate);
}
Beispiel #3
0
int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
		      enum ac97_pcm_cfg cfg, unsigned short slots)
{
	struct snd_ac97_bus *bus;
	int i, cidx, r, ok_flag;
	unsigned int reg_ok[4] = {0,0,0,0};
	unsigned char reg;
	int err = 0;

	r = rate > 48000;
	bus = pcm->bus;
	if (cfg == AC97_PCM_CFG_SPDIF) {
		for (cidx = 0; cidx < 4; cidx++)
			if (bus->codec[cidx] && (bus->codec[cidx]->ext_id & AC97_EI_SPDIF)) {
				err = set_spdif_rate(bus->codec[cidx], rate);
				if (err < 0)
					return err;
			}
	}
	spin_lock_irq(&pcm->bus->bus_lock);
	for (i = 3; i < 12; i++) {
		if (!(slots & (1 << i)))
			continue;
		ok_flag = 0;
		for (cidx = 0; cidx < 4; cidx++) {
			if (bus->used_slots[pcm->stream][cidx] & (1 << i)) {
				spin_unlock_irq(&pcm->bus->bus_lock);
				err = -EBUSY;
				goto error;
			}
			if (pcm->r[r].rslots[cidx] & (1 << i)) {
				bus->used_slots[pcm->stream][cidx] |= (1 << i);
				ok_flag++;
			}
		}
		if (!ok_flag) {
			spin_unlock_irq(&pcm->bus->bus_lock);
			snd_printk(KERN_ERR "cannot find configuration for AC97 slot %i\n", i);
			err = -EAGAIN;
			goto error;
		}
	}
	pcm->cur_dbl = r;
	spin_unlock_irq(&pcm->bus->bus_lock);
	for (i = 3; i < 12; i++) {
		if (!(slots & (1 << i)))
			continue;
		for (cidx = 0; cidx < 4; cidx++) {
			if (pcm->r[r].rslots[cidx] & (1 << i)) {
				reg = get_slot_reg(pcm, cidx, i, r);
				if (reg == 0xff) {
					snd_printk(KERN_ERR "invalid AC97 slot %i?\n", i);
					continue;
				}
				if (reg_ok[cidx] & (1 << (reg - AC97_PCM_FRONT_DAC_RATE)))
					continue;
				//printk(KERN_DEBUG "setting ac97 reg 0x%x to rate %d\n", reg, rate);
				err = snd_ac97_set_rate(pcm->r[r].codec[cidx], reg, rate);
				if (err < 0)
					snd_printk(KERN_ERR "error in snd_ac97_set_rate: cidx=%d, reg=0x%x, rate=%d, err=%d\n", cidx, reg, rate, err);
				else
					reg_ok[cidx] |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE));
			}
		}
	}
	pcm->aslots = slots;
	return 0;

 error:
	pcm->aslots = slots;
	snd_ac97_pcm_close(pcm);
	return err;
}
Beispiel #4
0
static int snd_cs5535audio_playback_prepare(struct snd_pcm_substream *substream)
{
	struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
	return snd_ac97_set_rate(cs5535au->ac97, AC97_PCM_FRONT_DAC_RATE,
				 substream->runtime->rate);
}