예제 #1
0
static void musb_sysdma_completion(int lch, u16 ch_status, void *data)
{
	u32 addr;
	unsigned long flags;

	struct dma_channel *channel;

	struct musb_dma_channel *musb_channel =
					(struct musb_dma_channel *) data;
	struct musb_dma_controller *controller = musb_channel->controller;
	struct musb *musb = controller->private_data;
	void __iomem *mbase = controller->base;

	channel = &musb_channel->channel;

	DBG(2, "lch = 0x%d, ch_status = 0x%x\n", lch, ch_status);
	spin_lock_irqsave(&musb->lock, flags);

	if (musb_channel->transmit)
		addr = (u32) omap_get_dma_src_pos(musb_channel->sysdma_channel);
	else
		addr = (u32) omap_get_dma_dst_pos(musb_channel->sysdma_channel);

	if (musb_channel->len == 0)
		channel->actual_len = 0;
	else
		channel->actual_len = addr - musb_channel->start_addr;

	DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n",
		channel, musb_channel->start_addr, addr,
		channel->actual_len, musb_channel->len,
		(channel->actual_len < musb_channel->len) ?
		"=> reconfig 0 " : " => complete");

	channel->status = MUSB_DMA_STATUS_FREE;

	/* completed */
	if ((musb_channel->transmit) && (channel->desired_mode == 0)
		&& (channel->actual_len == musb_channel->max_packet_sz)) {

		u8  epnum  = musb_channel->epnum;
		int offset = MUSB_EP_OFFSET(musb, epnum, MUSB_TXCSR);
		u16 txcsr;

		/*
		 * The programming guide says that we
		 * must clear DMAENAB before DMAMODE.
		 */
		musb_ep_select(musb, mbase, epnum);
		txcsr = musb_readw(mbase, offset);
		txcsr |=  MUSB_TXCSR_TXPKTRDY;
		musb_writew(mbase, offset, txcsr);
	}

	musb_dma_completion(musb, musb_channel->epnum, musb_channel->transmit);

	spin_unlock_irqrestore(&musb->lock, flags);
	return;
}
예제 #2
0
static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct omap_runtime_data *prtd = runtime->private_data;
	dma_addr_t ptr;
	snd_pcm_uframes_t offset;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		ptr = omap_get_dma_src_pos(prtd->dma_ch);
	else
		ptr = omap_get_dma_dst_pos(prtd->dma_ch);

	offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
	if (offset >= runtime->buffer_size)
		offset = 0;

	return offset;
}
예제 #3
0
/***************************************************************************************
 *
 * Get the dma posn
 *
 **************************************************************************************/
u_int audio_get_dma_pos(audio_stream_t * s)
{
	audio_buf_t *b = &s->buffers[s->dma_tail];
	u_int offset;

	FN_IN;
	if (b->dma_ref) {
		offset = omap_get_dma_src_pos(s->lch[s->dma_q_head]) - b->dma_addr;
		if (offset >= s->fragsize)
			offset = s->fragsize - 4;
	} else if (s->pending_frags) {
		offset = b->offset;
	} else {
		offset = 0;
	}
	FN_OUT(offset);
	return offset;
}
예제 #4
0
static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct omap_runtime_data *prtd = runtime->private_data;
	dma_addr_t ptr;
	snd_pcm_uframes_t offset;

	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
		ptr = omap_get_dma_dst_pos(prtd->dma_ch);
		offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
	} else if (!(cpu_is_omap1510())) {
		ptr = omap_get_dma_src_pos(prtd->dma_ch);
		offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
	} else
		offset = prtd->period_index * runtime->period_size;

	if (offset >= runtime->buffer_size)
		offset = 0;

	return offset;
}