Example #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;
}
/*
 * handling beep
 */
void snd_pmac_beep_dma_start(struct snd_pmac *chip, int bytes, unsigned long addr, int speed)
{
	struct pmac_stream *rec = &chip->playback;

	snd_pmac_dma_stop(rec);
	st_le16(&chip->extra_dma.cmds->req_count, bytes);
	st_le16(&chip->extra_dma.cmds->xfer_status, 0);
	st_le32(&chip->extra_dma.cmds->cmd_dep, chip->extra_dma.addr);
	st_le32(&chip->extra_dma.cmds->phy_addr, addr);
	st_le16(&chip->extra_dma.cmds->command, OUTPUT_MORE + BR_ALWAYS);
	out_le32(&chip->awacs->control,
		 (in_le32(&chip->awacs->control) & ~0x1f00)
		 | (speed << 8));
	out_le32(&chip->awacs->byteswap, 0);
	snd_pmac_dma_set_command(rec, &chip->extra_dma);
	snd_pmac_dma_run(rec, RUN);
}
Example #3
0
/*
 * PCM trigger/stop
 */
static int snd_pmac_pcm_trigger(struct snd_pmac *chip, struct pmac_stream *rec,
				struct snd_pcm_substream *subs, int cmd)
{
	volatile struct dbdma_cmd __iomem *cp;
	int i, command;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
		if (rec->running)
			return -EBUSY;
		command = (subs->stream == SNDRV_PCM_STREAM_PLAYBACK ?
			   OUTPUT_MORE : INPUT_MORE) + INTR_ALWAYS;
		spin_lock(&chip->reg_lock);
		snd_pmac_beep_stop(chip);
		snd_pmac_pcm_set_format(chip);
		for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++)
			out_le16(&cp->command, command);
		snd_pmac_dma_set_command(rec, &rec->cmd);
		(void)in_le32(&rec->dma->status);
		snd_pmac_dma_run(rec, RUN|WAKE);
		rec->running = 1;
		spin_unlock(&chip->reg_lock);
		break;

	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
		spin_lock(&chip->reg_lock);
		rec->running = 0;
		/*printk(KERN_DEBUG "stopped!!\n");*/
		snd_pmac_dma_stop(rec);
		for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++)
			out_le16(&cp->command, DBDMA_STOP);
		spin_unlock(&chip->reg_lock);
		break;

	default:
		return -EINVAL;
	}

	return 0;
}