Esempio n. 1
0
/*
 * prepare playback/capture stream
 */
static int snd_pmac_pcm_prepare(struct snd_pmac *chip, struct pmac_stream *rec, struct snd_pcm_substream *subs)
{
	int i;
	volatile struct dbdma_cmd __iomem *cp;
	struct snd_pcm_runtime *runtime = subs->runtime;
	int rate_index;
	long offset;
	struct pmac_stream *astr;

	rec->dma_size = snd_pcm_lib_buffer_bytes(subs);
	rec->period_size = snd_pcm_lib_period_bytes(subs);
	rec->nperiods = rec->dma_size / rec->period_size;
	rec->cur_period = 0;
	rate_index = snd_pmac_rate_index(chip, rec, runtime->rate);

	/* set up constraints */
	astr = snd_pmac_get_stream(chip, another_stream(rec->stream));
	if (! astr)
		return -EINVAL;
	astr->cur_freqs = 1 << rate_index;
	astr->cur_formats = 1 << runtime->format;
	chip->rate_index = rate_index;
	chip->format = runtime->format;

	/* We really want to execute a DMA stop command, after the AWACS
	 * is initialized.
	 * For reasons I don't understand, it stops the hissing noise
	 * common to many PowerBook G3 systems and random noise otherwise
	 * captured on iBook2's about every third time. -ReneR
	 */
	spin_lock_irq(&chip->reg_lock);
	snd_pmac_dma_stop(rec);
	chip->extra_dma.cmds->command = cpu_to_le16(DBDMA_STOP);
	snd_pmac_dma_set_command(rec, &chip->extra_dma);
	snd_pmac_dma_run(rec, RUN);
	spin_unlock_irq(&chip->reg_lock);
	mdelay(5);
	spin_lock_irq(&chip->reg_lock);
	/* continuous DMA memory type doesn't provide the physical address,
	 * so we need to resolve the address here...
	 */
	offset = runtime->dma_addr;
	for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) {
		cp->phy_addr = cpu_to_le32(offset);
		cp->req_count = cpu_to_le16(rec->period_size);
		/*cp->res_count = cpu_to_le16(0);*/
		cp->xfer_status = cpu_to_le16(0);
		offset += rec->period_size;
	}
	/* make loop */
	cp->command = cpu_to_le16(DBDMA_NOP + BR_ALWAYS);
	cp->cmd_dep = cpu_to_le32(rec->cmd.addr);

	snd_pmac_dma_stop(rec);
	snd_pmac_dma_set_command(rec, &rec->cmd);
	spin_unlock_irq(&chip->reg_lock);

	return 0;
}
static int snd_pmac_pcm_close(struct snd_pmac *chip, struct pmac_stream *rec,
			      struct snd_pcm_substream *subs)
{
	struct pmac_stream *astr;

	snd_pmac_dma_stop(rec);

	astr = snd_pmac_get_stream(chip, another_stream(rec->stream));
	if (! astr)
		return -EINVAL;

	/* reset constraints */
	astr->cur_freqs = chip->freqs_ok;
	astr->cur_formats = chip->formats_ok;
	
	return 0;
}