Exemplo n.º 1
0
/* CAUTION: call it with irq disabled (due to internal call to snd_pcm_update_hw_ptr) */
static inline snd_pcm_uframes_t _ksnd_pcm_avail_update(snd_pcm_substream_t
													   *substream)
{
	snd_pcm_runtime_t *runtime = substream->runtime;
	/*NICK added if to remove real updates which we do not want*/
#if defined(__TDT__) \
 && (defined(FORTIS_HDBOX) \
 || defined(UFS922) \
 || defined(UFC960) \
 || defined(HL101) \
 || defined(VIP1_V2) \
 || defined(VIP2_V1) \
 || defined(OCTAGON1008) \
 || defined(IPBOX9900) \
 || defined(IPBOX99) \
 || defined(IPBOX55) \
 || defined(CUBEREVO_250HD) \
 || defined(CUBEREVO))
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
	if (runtime->sleep_min == 0 &&
			_ksnd_pcm_state(substream) == SNDRV_PCM_STATE_RUNNING)
		snd_pcm_update_hw_ptr(substream);
#else
	if (_ksnd_pcm_state(substream) == SNDRV_PCM_STATE_RUNNING)
		snd_pcm_update_hw_ptr(substream);
#endif
#endif
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		return snd_pcm_playback_avail(runtime);
	else
		return snd_pcm_capture_avail(runtime);
}
Exemplo n.º 2
0
snd_pcm_sframes_t ksnd_pcm_mmap_commit(ksnd_pcm_t *pcm,
									   snd_pcm_uframes_t offset,
									   snd_pcm_uframes_t frames)
{
	snd_pcm_substream_t *substream = pcm->substream;
	snd_pcm_runtime_t *runtime = substream->runtime;
	snd_pcm_uframes_t appl_ptr;
	snd_pcm_sframes_t res = frames;
	int err;
	if (snd_BUG_ON(!substream))
		return -EFAULT;
	/* for SPDIF we need to run though the just committed PCM samples and
	 * add formating (unless raw mode is enabled)
	 */
//      BUG_ON(substream->pcm->card->number == 2); /* TODO: magic number */
	snd_pcm_stream_lock_irq(substream);
	switch (_ksnd_pcm_state(substream))
	{
		case SNDRV_PCM_STATE_XRUN:
			res = -EPIPE;
			goto _end_unlock;
		case SNDRV_PCM_STATE_SUSPENDED:
			res = -ESTRPIPE;
			goto _end_unlock;
	}
	appl_ptr = runtime->control->appl_ptr;
	/* verify no-one is interleaving access to the playback */
	// TODO: what about capture?
	BUG_ON(substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
		   (appl_ptr % runtime->buffer_size) != offset);
	appl_ptr += frames;
	if (appl_ptr >= runtime->boundary)
		appl_ptr = 0;
	err = _ksnd_pcm_update_appl_ptr(substream, appl_ptr);
	if (err < 0)
		res = err;
_end_unlock:
	snd_pcm_stream_unlock_irq(substream);
	return res;
}
Exemplo n.º 3
0
static int _ksnd_pcm_wait(snd_pcm_substream_t *substream, int timeout)
{
	snd_pcm_runtime_t *runtime = substream->runtime;
	snd_pcm_uframes_t avail;
	int res = 1; /* success is a positive integer */
	snd_pcm_stream_lock_irq(substream);
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		avail = snd_pcm_playback_avail(runtime);
	else
		avail = snd_pcm_capture_avail(runtime);
	if (avail < runtime->control->avail_min)
	{
		wait_queue_t wait;
		long jiffies;
		if (timeout >= 0)
			jiffies = (timeout * HZ) / 1000;
		else
			jiffies = 10 * HZ;
		init_waitqueue_entry(&wait, current);
		add_wait_queue(&runtime->sleep, &wait);
		do
		{
			if (signal_pending(current))
			{
				res = -ERESTARTSYS;
				break;
			}
			set_current_state(TASK_INTERRUPTIBLE);
			snd_pcm_stream_unlock_irq(substream);
			jiffies = schedule_timeout(jiffies);
			snd_pcm_stream_lock_irq(substream);
			if (jiffies == 0)
			{
				if (timeout < 0)
				{
					snd_printd("ksnd: [hw:%d,%d] playback write error "
							   "(DMA or IRQ trouble?)\n",
							   substream->pcm->card->number,
							   substream->pcm->device);
					jiffies = 10 * HZ;
				}
				else
				{
					res = 0; /* timeout */
				}
			}
			switch (_ksnd_pcm_state(substream))
			{
				case SNDRV_PCM_STATE_SETUP:
				case SNDRV_PCM_STATE_XRUN:
				case SNDRV_PCM_STATE_DRAINING:
					res = -EPIPE;
					break;
				case SNDRV_PCM_STATE_SUSPENDED:
					printk("%s: result ESTRPIPE %d\n",
						   __FUNCTION__, __LINE__);
					res = -ESTRPIPE;
					break;
				case SNDRV_PCM_STATE_PAUSED:
					printk("%s: Waiting for buffer %d\n",
						   __FUNCTION__, __LINE__);
					break;
				default:
					break;
			}
			if (1 != res)
				break;
			if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
				avail = snd_pcm_playback_avail(runtime);
			else
				avail = snd_pcm_capture_avail(runtime);
		}
		while (avail < runtime->control->avail_min);
		remove_wait_queue(&runtime->sleep, &wait);
	}
	snd_pcm_stream_unlock_irq(substream);
	return res;
}
Exemplo n.º 4
0
snd_pcm_state_t ksnd_pcm_state(ksnd_pcm_t *pcm)
{
	return _ksnd_pcm_state(pcm->substream);
}
Exemplo n.º 5
0
static int _ksnd_pcm_writei1(snd_pcm_substream_t *substream,
							 unsigned long data,
							 snd_pcm_uframes_t size,
							 int srcchannels, transfer_f transfer)
{
	snd_pcm_runtime_t *runtime = substream->runtime;
	snd_pcm_uframes_t xfer = 0;
	snd_pcm_uframes_t offset = 0;
	int err = 0;
	if (size == 0)
		return 0;
	snd_pcm_stream_lock_irq(substream);
	switch (_ksnd_pcm_state(substream))
	{
		case SNDRV_PCM_STATE_PREPARED:
		case SNDRV_PCM_STATE_RUNNING:
		case SNDRV_PCM_STATE_PAUSED:
			break;
		case SNDRV_PCM_STATE_XRUN:
			err = -EPIPE;
			goto _end_unlock;
		case SNDRV_PCM_STATE_SUSPENDED:
			err = -ESTRPIPE;
			goto _end_unlock;
		default:
			err = -EBADFD;
			goto _end_unlock;
	}
	while (size > 0)
	{
		snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
		snd_pcm_uframes_t avail;
		snd_pcm_uframes_t cont;
		avail = _ksnd_pcm_avail_update(substream);
#if defined(__TDT__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
		// attribute xfer_align is not used any more
		/* #warning Do we have to check the values 'size' and 'avail'? */
		if ((avail < runtime->control->avail_min) && (size > avail))
		{
#else
		if (((avail < runtime->control->avail_min && size > avail) ||
				(size >= runtime->xfer_align
				 && avail < runtime->xfer_align)))
		{
#endif
			int res;
			snd_pcm_stream_unlock_irq(substream);
			do
			{
				res = _ksnd_pcm_wait(substream, 10000);
			}
			while (res == 0 &&
					_ksnd_pcm_state(substream) !=
					SNDRV_PCM_STATE_PREPARED
					&& _ksnd_pcm_state(substream) !=
					SNDRV_PCM_STATE_PAUSED);
			snd_pcm_stream_lock_irq(substream);
			if (res == 0)   /* timeout */
			{
				if (_ksnd_pcm_state(substream) ==
						SNDRV_PCM_STATE_SUSPENDED)
				{
					err = -ESTRPIPE;
					goto _end_unlock;
				}
				else
				{
					snd_printd("playback write error "
							   "(DMA or IRQ trouble?)\n");
					err = -EIO;
					goto _end_unlock;
				}
			}
			else if (res < 0)       /* error */
			{
				err = res;
				goto _end_unlock;
			}
			avail = snd_pcm_playback_avail(runtime);
		}
		frames = size > avail ? avail : size;
		cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
		if (frames > cont)
			frames = cont;
		if (snd_BUG_ON(!frames))
		{
			snd_pcm_stream_unlock_irq(substream);
			return -EINVAL;
		}
		appl_ptr = runtime->control->appl_ptr;
		appl_ofs = appl_ptr % runtime->buffer_size;
		snd_pcm_stream_unlock_irq(substream);
		err = transfer(substream, appl_ofs, data, offset, frames, srcchannels);
		snd_pcm_stream_lock_irq(substream);
		if (err < 0)
			goto _end;
		switch (_ksnd_pcm_state(substream))
		{
			case SNDRV_PCM_STATE_XRUN:
				err = -EPIPE;
				goto _end_unlock;
			case SNDRV_PCM_STATE_SUSPENDED:
				err = -ESTRPIPE;
				goto _end_unlock;
			default:
				break;
		}
		appl_ptr += frames;
		if (appl_ptr >= runtime->boundary)
		{
			runtime->control->appl_ptr = 0;
		}
		else
		{
			runtime->control->appl_ptr = appl_ptr;
		}
		if (substream->ops->ack)
			substream->ops->ack(substream);
		offset += frames;
		size -= frames;
		xfer += frames;
		if (_ksnd_pcm_state(substream) == SNDRV_PCM_STATE_PREPARED &&
				snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t) runtime->start_threshold)
		{
			err = snd_pcm_start(substream);
			if (err < 0)
				goto _end_unlock;
		}
	}
_end_unlock:
	snd_pcm_stream_unlock_irq(substream);
_end:
	return xfer > 0 ? (snd_pcm_sframes_t) xfer : err;
}

int ksnd_pcm_writei(ksnd_pcm_t *kpcm,
					int *data, unsigned int size, unsigned int srcchannels)
{
	snd_pcm_substream_t *substream = kpcm->substream;
	snd_pcm_runtime_t *runtime;
	int err;
	transfer_f out_func = 0;
	runtime = substream->runtime;
	if (substream->pcm->card->number == 2)
	{
		out_func = _ksnd_pcm_IEC60958_transfer;
	}
	else
	{
		out_func = _ksnd_pcm_write_transfer;
	}
	if (_ksnd_pcm_state(substream) == SNDRV_PCM_STATE_OPEN)
		return -EBADFD;
	if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED
			&& runtime->channels > 1)
		return -EINVAL;
	if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
		return -EINVAL;
	if (size == 0)
		return 0;
	do
	{
		err =
			_ksnd_pcm_writei1(substream, (unsigned long)data, size,
							  srcchannels, out_func);
		if (err < 0)
		{
			if (err == -EAGAIN)
			{
				continue;
			}
			if (err == -EPIPE)
			{
				printk("ALSA Aud underrun for hw:%d,%d\n",
					   substream->pcm->card->number,
					   substream->pcm->device);
				if ((err = ksnd_pcm_prepare(kpcm)) < 0)
					return err;
				continue;
			}
			return err;
		}
		else
		{
			data += samples_to_bytes(runtime, err * srcchannels);
			size -= err;
		}
	}
	while (size > 0);
	return 0;
}