示例#1
0
void audio_ldm_suspend(void *data)
{
        audio_state_t *state = data;
        audio_stream_t *is = state->input_stream;
	audio_stream_t *os = state->output_stream;
	int stopstate;

        if (is && is->dma_regs) 
        {
	        stopstate = is->stopped;
		audio_stop_dma(is);
		DMA_CLEAR(is);
		is->dma_spinref = 0;
		is->stopped = stopstate;
	}
	if (os && os->dma_regs) 
        {
		stopstate = os->stopped;
		audio_stop_dma(os);
		DMA_CLEAR(os);
		os->dma_spinref = 0;
		os->stopped = stopstate;
	}
	if (AUDIO_ACTIVE(state) && state->hw_shutdown)
		state->hw_shutdown(state->data);
}
示例#2
0
static int audio_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
{
	audio_state_t *state = pm_dev->data;
	audio_stream_t *is = state->input_stream;
	audio_stream_t *os = state->output_stream;
	int stopstate;

	switch (req) {
	case PM_SUSPEND: /* enter D1-D3 */
		if (is && is->dma_regs) {
			stopstate = is->stopped;
			audio_stop_dma(is);
			DMA_CLEAR(is);
			is->dma_spinref = 0;
			is->stopped = stopstate;
		}
		if (os && os->dma_regs) {
			stopstate = os->stopped;
			audio_stop_dma(os);
			DMA_CLEAR(os);
			os->dma_spinref = 0;
			os->stopped = stopstate;
		}
		if (AUDIO_ACTIVE(state) && state->hw_shutdown)
			state->hw_shutdown(state->data);
		break;
	case PM_RESUME:  /* enter D0 */
		if (AUDIO_ACTIVE(state) && state->hw_init)
			state->hw_init(state->data);
		if (os && os->dma_regs) {
			DMA_RESET(os);
			audio_process_dma(os);
		}
		if (is && is->dma_regs) {
			DMA_RESET(is);
			audio_process_dma(is);
		}
		break;
	}
	return 0;
}
示例#3
0
static void audio_process_dma(audio_stream_t *s)
{
	int ret;

	DPRINTK(__FUNCTION__ ": pending_frags = %d, usr_head = %d, dma_head = %d, dma_tail = %d, bytecount = %d, fragcount = %d\n",
		s->pending_frags, s->usr_head, s->dma_head, s->dma_tail, s->bytecount, s->fragcount);
	if (s->stopped)
		goto spin;

	if (s->dma_spinref > 0 && s->pending_frags) {
		s->dma_spinref = 0;
		DMA_CLEAR(s);
	}

	while (s->pending_frags) {
		audio_buf_t *b = &s->buffers[s->dma_head];
		u_int dma_size = s->fragsize - b->offset;
		if (dma_size > MAX_DMA_SIZE)
			dma_size = CUT_DMA_SIZE;
		ret = DMA_START(s, b->dma_addr + b->offset, dma_size);
		if (ret)
			return;
		b->dma_ref++;
		b->offset += dma_size;
		if (b->offset >= s->fragsize) {
			s->pending_frags--;
			if (++s->dma_head >= s->nbfrags)
				s->dma_head = 0;
		}
	}

spin:
	if (s->spin_idle) {
		int spincnt = 0;
		while (DMA_START(s, SPIN_ADDR, SPIN_SIZE) == 0)
			spincnt++;
		/*
		 * Note: if there is still a data buffer being
		 * processed then the ref count is negative.  This
		 * allows for the DMA termination to be accounted in
		 * the proper order.  Of course dma_spinref can't be
		 * greater than 0 if dma_ref is not 0 since we kill
		 * the spinning above as soon as there is real data to process.
		 */
		if (s->buffers && s->buffers[s->dma_tail].dma_ref)
			spincnt = -spincnt;
		s->dma_spinref += spincnt;
	}
}
示例#4
0
static void audio_stop_dma(audio_stream_t *s)
{
	u_int pos;
	unsigned long flags;
	audio_buf_t *b;

	if (s->dma_spinref > 0 || !s->buffers)
		return;

	local_irq_save(flags);
	s->stopped = 1;
	DMA_STOP(s);
	pos = audio_get_dma_pos(s);
	DMA_CLEAR(s);
	if (s->spin_idle) {
		DMA_START(s, SPIN_ADDR, SPIN_SIZE);
		DMA_START(s, SPIN_ADDR, SPIN_SIZE);
		s->dma_spinref = 2;
	} else
		s->dma_spinref = 0;
	local_irq_restore(flags);

	/* back up pointers to be ready to restart from the same spot */
	while (s->dma_head != s->dma_tail) {
		b = &s->buffers[s->dma_head];
		if (b->dma_ref) {
			b->dma_ref = 0;
			b->offset = 0;
		}
		s->pending_frags++;
		if (s->dma_head == 0)
			s->dma_head = s->nbfrags;
		s->dma_head--;
	}
	b = &s->buffers[s->dma_head];
	if (b->dma_ref) {
		b->offset = pos;
		b->dma_ref = 0;
	}
}
示例#5
0
/***************************************************************************************
 *
 * Process DMA requests - This will end up starting the transfer. Proper fragments of
 * Transfers will be initiated.
 *
 **************************************************************************************/
int audio_process_dma(audio_stream_t * s)
{
	int ret = 0;
	unsigned long flags;
	FN_IN;

	/* Dont let the ISR over ride touching the in_use flag */
	local_irq_save(flags);
	if (1 == s->in_use) {
		local_irq_restore(flags);
		ERR("Called again while In Use\n");
		return 0;
	}
	s->in_use = 1;
	local_irq_restore(flags);

	if (s->stopped)
		goto spin;

	if (s->dma_spinref > 0 && s->pending_frags) {
		s->dma_spinref = 0;
		DMA_CLEAR(s);
	}
	while (s->pending_frags) {
		audio_buf_t *b = &s->buffers[s->dma_head];
		u_int dma_size = s->fragsize - b->offset;
		if (dma_size > MAX_DMA_SIZE)
			dma_size = CUT_DMA_SIZE;
		ret =
		    omap_start_sound_dma(s, b->dma_addr + b->offset, dma_size);
		if (ret) {
			goto process_out;
		}
		b->dma_ref++;
		b->offset += dma_size;
		if (b->offset >= s->fragsize) {
			s->pending_frags--;
			if (++s->dma_head >= s->nbfrags)
				s->dma_head = 0;
		}
	}
      spin:
	if (s->spin_idle) {
		int spincnt = 0;
		ERR("we are spinning\n");
		while (omap_start_sound_dma(s, SPIN_ADDR, SPIN_SIZE) == 0)
			spincnt++;
		/*
		 * Note: if there is still a data buffer being
		 * processed then the ref count is negative.  This
		 * allows for the DMA termination to be accounted in
		 * the proper order.  Of course dma_spinref can't be
		 * greater than 0 if dma_ref is not 0 since we kill
		 * the spinning above as soon as there is real data to process.
		 */
		if (s->buffers && s->buffers[s->dma_tail].dma_ref)
			spincnt = -spincnt;
		s->dma_spinref += spincnt;
	}

      process_out:
	s->in_use = 0;

	FN_OUT(ret);
	return ret;
}