Esempio n. 1
0
int DMAbuf_activate_recording(int dev, struct dma_buffparms *dmap)
{
	struct audio_operations *adev = audio_devs[dev];
	int  err;

	if (!(adev->open_mode & OPEN_READ))
		return 0;
	if (!(adev->enable_bits & PCM_ENABLE_INPUT))
		return 0;
	if (dmap->dma_mode == DMODE_OUTPUT) {	/* Direction change */
		DMAbuf_sync(dev);
		DMAbuf_reset(dev);
		dmap->dma_mode = DMODE_NONE;
	}
	if (!dmap->dma_mode) {
		reorganize_buffers(dev, dmap, 1);
		if ((err = adev->d->prepare_for_input(dev,
				dmap->fragment_size, dmap->nbufs)) < 0)
			return err;
		dmap->dma_mode = DMODE_INPUT;
	}
	if (!(dmap->flags & DMA_ACTIVE)) {
		if (dmap->needs_reorg)
			reorganize_buffers(dev, dmap, 0);
		local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use, DMA_MODE_READ);
		adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size,
				     dmap->fragment_size, 0);
		dmap->flags |= DMA_ACTIVE;
		if (adev->d->trigger)
			adev->d->trigger(dev, adev->enable_bits * adev->go);
	}
	return 0;
}
Esempio n. 2
0
/* acquires lock  */
int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock)
{
	struct audio_operations *adev = audio_devs[dev];
	unsigned long flags;
	int err = -EIO;
	struct dma_buffparms *dmap = adev->dmap_out;

	if (dmap->mapping_flags & DMA_MAP_MAPPED) {
/*		printk(KERN_DEBUG "Sound: Can't write to mmapped device (3)\n");*/
		return -EINVAL;
	}
	spin_lock_irqsave(&dmap->lock,flags);
	if (dmap->needs_reorg)
		reorganize_buffers(dev, dmap, 0);

	if (dmap->dma_mode == DMODE_INPUT) {	/* Direction change */
		spin_unlock_irqrestore(&dmap->lock,flags);
		DMAbuf_reset(dev);
		spin_lock_irqsave(&dmap->lock,flags);
	}
	dmap->dma_mode = DMODE_OUTPUT;

	while (find_output_space(dev, buf, size) <= 0) {
		spin_unlock_irqrestore(&dmap->lock,flags);
		if ((err = output_sleep(dev, dontblock)) < 0) {
			return err;
		}
		spin_lock_irqsave(&dmap->lock,flags);
	}

	spin_unlock_irqrestore(&dmap->lock,flags);
	return 0;
}
Esempio n. 3
0
/* MUST be called with holding the dmap->lock */
void DMAbuf_launch_output(int dev, struct dma_buffparms *dmap)
{
	struct audio_operations *adev = audio_devs[dev];

	if (!((adev->enable_bits * adev->go) & PCM_ENABLE_OUTPUT))
		return;		/* Don't start DMA yet */
	dmap->dma_mode = DMODE_OUTPUT;

	if (!(dmap->flags & DMA_ACTIVE) || !(adev->flags & DMA_AUTOMODE) || (dmap->flags & DMA_NODMA)) {
		if (!(dmap->flags & DMA_STARTED)) {
			reorganize_buffers(dev, dmap, 0);
			if (adev->d->prepare_for_output(dev, dmap->fragment_size, dmap->nbufs))
				return;
			if (!(dmap->flags & DMA_NODMA))
				local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use,DMA_MODE_WRITE);
			dmap->flags |= DMA_STARTED;
		}
		if (dmap->counts[dmap->qhead] == 0)
			dmap->counts[dmap->qhead] = dmap->fragment_size;
		dmap->dma_mode = DMODE_OUTPUT;
		adev->d->output_block(dev, dmap->raw_buf_phys + dmap->qhead * dmap->fragment_size,
				      dmap->counts[dmap->qhead], 1);
		if (adev->d->trigger)
			adev->d->trigger(dev,adev->enable_bits * adev->go);
	}
	dmap->flags |= DMA_ACTIVE;
}
Esempio n. 4
0
/* acquires lock */
int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock)
{
	struct audio_operations *adev = audio_devs[dev];
	unsigned long flags;
	int err = 0, n = 0;
	struct dma_buffparms *dmap = adev->dmap_in;
	int go;

	if (!(adev->open_mode & OPEN_READ))
		return -EIO;
	spin_lock_irqsave(&dmap->lock,flags);
	if (dmap->needs_reorg)
		reorganize_buffers(dev, dmap, 0);
	if (adev->dmap_in->mapping_flags & DMA_MAP_MAPPED) {
/*		  printk(KERN_WARNING "Sound: Can't read from mmapped device (1)\n");*/
		  spin_unlock_irqrestore(&dmap->lock,flags);
		  return -EINVAL;
	} else while (dmap->qlen <= 0 && n++ < 10) {
		long timeout = MAX_SCHEDULE_TIMEOUT;
		if (!(adev->enable_bits & PCM_ENABLE_INPUT) || !adev->go) {
			spin_unlock_irqrestore(&dmap->lock,flags);
			return -EAGAIN;
		}
		if ((err = DMAbuf_activate_recording(dev, dmap)) < 0) {
			spin_unlock_irqrestore(&dmap->lock,flags);
			return err;
		}
		/* Wait for the next block */

		if (dontblock) {
			spin_unlock_irqrestore(&dmap->lock,flags);
			return -EAGAIN;
		}
		if ((go = adev->go))
			timeout = dmabuf_timeout(dmap);

		spin_unlock_irqrestore(&dmap->lock,flags);
		timeout = interruptible_sleep_on_timeout(&adev->in_sleeper,
							 timeout);
		if (!timeout) {
			/* FIXME: include device name */
			err = -EIO;
			printk(KERN_WARNING "Sound: DMA (input) timed out - IRQ/DRQ config error?\n");
			dma_reset_input(dev);
		} else
			err = -EINTR;
		spin_lock_irqsave(&dmap->lock,flags);
	}
	spin_unlock_irqrestore(&dmap->lock,flags);

	if (dmap->qlen <= 0)
		return err ? err : -EINTR;
	*buf = &dmap->raw_buf[dmap->qhead * dmap->fragment_size + dmap->counts[dmap->qhead]];
	*len = dmap->fragment_size - dmap->counts[dmap->qhead];

	return dmap->qhead;
}
Esempio n. 5
0
static void dma_reset_input(int dev)
{
        struct audio_operations *adev = audio_devs[dev];
	unsigned long flags;
	struct dma_buffparms *dmap = adev->dmap_in;

	spin_lock_irqsave(&dmap->lock,flags);
	if (!(adev->flags & DMA_DUPLEX) || !adev->d->halt_input)
		adev->d->halt_io(dev);
	else
		adev->d->halt_input(dev);
	adev->dmap_in->flags &= ~DMA_STARTED;

	dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0;
	dmap->byte_counter = 0;
	reorganize_buffers(dev, adev->dmap_in, 1);
	spin_unlock_irqrestore(&dmap->lock,flags);
}
Esempio n. 6
0
static void dma_reset_output(int dev)
{
	struct audio_operations *adev = audio_devs[dev];
	unsigned long flags,f ;
	struct dma_buffparms *dmap = adev->dmap_out;

	if (!(dmap->flags & DMA_STARTED))	/* DMA is not active */
		return;

	/*
	 *	First wait until the current fragment has been played completely
	 */
	spin_lock_irqsave(&dmap->lock,flags);
	adev->dmap_out->flags |= DMA_SYNCING;

	adev->dmap_out->underrun_count = 0;
	if (!signal_pending(current) && adev->dmap_out->qlen && 
	    adev->dmap_out->underrun_count == 0){
		spin_unlock_irqrestore(&dmap->lock,flags);
		interruptible_sleep_on_timeout(&adev->out_sleeper,
					       dmabuf_timeout(dmap));
		spin_lock_irqsave(&dmap->lock,flags);
	}
	adev->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE);

	/*
	 *	Finally shut the device off
	 */
	if (!(adev->flags & DMA_DUPLEX) || !adev->d->halt_output)
		adev->d->halt_io(dev);
	else
		adev->d->halt_output(dev);
	adev->dmap_out->flags &= ~DMA_STARTED;
	
	f=claim_dma_lock();
	clear_dma_ff(dmap->dma);
	disable_dma(dmap->dma);
	release_dma_lock(f);
	
	dmap->byte_counter = 0;
	reorganize_buffers(dev, adev->dmap_out, 0);
	dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0;
	spin_unlock_irqrestore(&dmap->lock,flags);
}
Esempio n. 7
0
/* called with dmap->lock held in irq context */
static void do_inputintr(int dev)
{
	struct audio_operations *adev = audio_devs[dev];
	struct dma_buffparms *dmap = adev->dmap_in;

	if (dmap->raw_buf == NULL) {
		printk(KERN_ERR "Sound: Fatal error. Audio interrupt after freeing buffers.\n");
		return;
	}
	if (dmap->mapping_flags & DMA_MAP_MAPPED) {
		dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
		if (dmap->qtail == 0) {		/* Wrapped */
			dmap->byte_counter += dmap->bytes_in_use;
			if (dmap->byte_counter >= dmap->max_byte_counter) {	/* Overflow */
				long decr = dmap->byte_counter;
				dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use;
				decr -= dmap->byte_counter;
				dmap->user_counter -= decr;
			}
		}
		dmap->qlen++;

		if (!(adev->flags & DMA_AUTOMODE)) {
			if (dmap->needs_reorg)
				reorganize_buffers(dev, dmap, 0);
			local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use,DMA_MODE_READ);
			adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size,
					     dmap->fragment_size, 1);
			if (adev->d->trigger)
				adev->d->trigger(dev, adev->enable_bits * adev->go);
		}
		dmap->flags |= DMA_ACTIVE;
	} else if (dmap->qlen >= (dmap->nbufs - 1)) {
		printk(KERN_WARNING "Sound: Recording overrun\n");
		dmap->underrun_count++;

		/* Just throw away the oldest fragment but keep the engine running */
		dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
		dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
	} else if (dmap->qlen >= 0 && dmap->qlen < dmap->nbufs) {
		dmap->qlen++;
		dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
		if (dmap->qtail == 0) {		/* Wrapped */
			dmap->byte_counter += dmap->bytes_in_use;
			if (dmap->byte_counter >= dmap->max_byte_counter) {	/* Overflow */
				long decr = dmap->byte_counter;
				dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use;
				decr -= dmap->byte_counter;
				dmap->user_counter -= decr;
			}
		}
	}
	if (!(adev->flags & DMA_AUTOMODE) || (dmap->flags & DMA_NODMA)) {
		local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use, DMA_MODE_READ);
		adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size, dmap->fragment_size, 1);
		if (adev->d->trigger)
			adev->d->trigger(dev,adev->enable_bits * adev->go);
	}
	dmap->flags |= DMA_ACTIVE;
	if (dmap->qlen > 0)
	{
		wake_up(&adev->in_sleeper);
		wake_up(&adev->poll_sleeper);
	}
}