Пример #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);
}
Пример #2
0
static int saudio_data_trigger_process(struct saudio_stream *stream,
					   struct saudio_msg *msg)
{
	int32_t result = 0;
	struct sblock blk = { 0 };
	struct cmd_common *common = NULL;
	struct snd_pcm_runtime *runtime = stream->substream->runtime;
	ADEBUG();

	if (stream->stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
		stream->periods_avail = snd_pcm_playback_avail(runtime) /
		    runtime->period_size;
	} else {
		stream->periods_avail = snd_pcm_capture_avail(runtime) /
		    runtime->period_size;
	}

	pr_debug("saudio.c:stream->periods_avail is %d,block count is %d",
		 stream->periods_avail, sblock_get_free_count(stream->dst,
							      stream->channel));

	stream->periods_tosend = runtime->periods - stream->periods_avail;

	ADEBUG();

	while (stream->periods_tosend) {

		result = sblock_get(stream->dst, stream->channel, &blk, 0);
		if (result) {
			break;
		}
		stream->last_getblk_count++;
		common = (struct cmd_common *)blk.addr;
		blk.length = frames_to_bytes(runtime, runtime->period_size);
		common->command = SAUDIO_DATA_PCM;
		common->sub_cmd = stream->stream_id;
		common->reserved1 =
		    stream->substream->dma_buffer.addr +
		    stream->period * blk.length;

		sblock_send(stream->dst, stream->channel, &blk);

		stream->period++;
		stream->period = stream->period % runtime->periods;
		stream->periods_tosend--;
	}

	pr_debug(":sblock_getblock_count trigger is %d \n",
		 stream->last_getblk_count);

	return result;
}
    static int
vaudio_snd_trigger (struct snd_pcm_substream* substream, int cmd)
{
    const NkVaudio          chip = snd_pcm_substream_chip(substream);
    const int               stream_id = substream->pstr->stream;
    const int               dev = substream->pcm->device;
    struct vaudio_stream*   s = &chip->s[dev][stream_id];
    struct snd_pcm_runtime* runtime = substream->runtime;
    NkVaudioCtrl*           ctrl  = s->ctrl;
    NkDevVlink*             vlink = chip->vlink;

    ADEBUG();
	/* Local interrupts are already disabled in the midlevel code */
    switch (cmd) {
    case SNDRV_PCM_TRIGGER_START:
	    /* Requested stream startup */
	s->active = 1;
	if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
	    s->periods_avail = snd_pcm_playback_avail(runtime) /
				  runtime->period_size;
	} else {
	    s->periods_avail = snd_pcm_capture_avail(runtime) /
				  runtime->period_size;
	}
	s->periods_tosend = runtime->periods - s->periods_avail;
	while (s->periods_tosend) {
	    if (vaudio_send_data(s) < 0) break;
	    s->periods_tosend--;
	}
	ctrl->command = NK_VAUDIO_COMMAND_START;
	nkops.nk_xirq_trigger(ctrl->cxirq, vlink->s_id);
	    /* This command is asynchronous, no waiting on down() */
	return 0;

    case SNDRV_PCM_TRIGGER_STOP:
	    /* Requested stream shutdown */
	s->active = 0;
	ctrl->command = NK_VAUDIO_COMMAND_STOP;
	nkops.nk_xirq_trigger(ctrl->cxirq, vlink->s_id);
	    /* This command is asynchronous, no waiting on down() */
	return 0;

    default:
	break;
    }
    return -EINVAL;
}
static void lutimer_handler(unsigned long data)
{
    if (vaudio_sync_force_close && vrs && vrs->stream) {
        struct vaudio_stream *s = vrs;
        struct snd_pcm_runtime *runtime = s->stream->runtime;
        int periods_avail = runtime->periods - snd_pcm_capture_avail(runtime) / runtime->period_size;
        printk("vaudio dummy capture data flushing\n");
        memset(s->stream->dma_buffer.area, 0, NK_VAUDIO_MAX_RING_SIZE);
        while (periods_avail-- > 2) {
            s->hwptr_done++;
            s->hwptr_done %= runtime->periods;
            snd_pcm_period_elapsed(s->stream);
            s->periods_avail = 2;
        }
        mod_timer(&lutimer, jiffies + VAUDIO_VTIMER_ROUND_JIFFIES);
    } else {
        printk("vaudio dummy capture exit automatically[%d]...\n", vaudio_sync_force_close);
    }
}
Пример #5
0
static void _ksnd_pcm_mmap_begin(snd_pcm_substream_t *substream,
								 snd_pcm_uframes_t *offset,
								 snd_pcm_uframes_t *frames)
{
	snd_pcm_runtime_t *runtime = substream->runtime;
	snd_pcm_uframes_t avail, f, cont, appl_ptr;
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		avail = snd_pcm_playback_avail(runtime);
	else
		avail = snd_pcm_capture_avail(runtime);
	f = *frames;
	if (f > avail)
		f = avail;
	cont =
		runtime->buffer_size -
		runtime->control->appl_ptr % runtime->buffer_size;
	if (f > cont)
		f = cont;
	appl_ptr = runtime->control->appl_ptr;
	*frames = f;
	*offset = appl_ptr % runtime->buffer_size;
}
Пример #6
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;
}
    static void
vaudio_intr_data (void* cookie, NkXIrq xirq)
{
    struct vaudio_stream* s = (struct vaudio_stream*) cookie;
    NkDevRing*   ring   = s->ring;
    nku32_f	 oresp  = s->resp;
    const nku32_f mask   = ring->imask;
    const nku32_f nresp  = ring->iresp;
    bool	 trigger = 0;
#if VAUDIO_PROC_SYNC
    if (vaudio_sync_force_close &&
        s->stream->pcm->device == 0 &&
        s->stream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
        while (vaudio_send_data(s) >= 0);
        // memset(s->stream->dma_buffer.area, 0, NK_VAUDIO_MAX_RING_SIZE);
        return;
    }
#endif
    (void) xirq;
    if (s->active) {
	struct snd_pcm_runtime* runtime = s->stream->runtime;
	int periods_avail;
	int periods_tosend;

	if (s->stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
	    periods_avail = snd_pcm_playback_avail(runtime) /
				    runtime->period_size;
	} else {
	    periods_avail = snd_pcm_capture_avail(runtime) /
				    runtime->period_size;
	}
	DTRACE ("%d %d %d\n",
		s->periods_avail, periods_avail, s->periods_tosend);
	periods_tosend = s->periods_avail - periods_avail;
	if (periods_tosend > 0) {
	    s->periods_tosend += periods_tosend;
	}
	s->periods_avail = periods_avail;
	while (s->periods_tosend) {
	    const int res = vaudio_send_data(s);
	    if (res < 0) break;
	    if (res == 1) trigger = 1;
	    s->periods_tosend--;
	}
    }
    while (oresp != nresp) {
	NkRingDesc*  desc = s->rbase + (oresp & mask);

	if (desc->status == (nku32_f) NK_VAUDIO_STATUS_ERROR) {
	    snd_pcm_stop(s->stream, SNDRV_PCM_STATE_XRUN);
	} else {
	    if (s->active) {
		struct snd_pcm_runtime* runtime = s->stream->runtime;

		s->hwptr_done++;
		s->hwptr_done %= runtime->periods;
		snd_pcm_period_elapsed(s->stream);
		s->periods_avail++;
	    }
	}
	oresp++;
    }
    s->resp = oresp;
    if (trigger) {
	nkops.nk_xirq_trigger(ring->cxirq, s->vaudio->vlink->s_id);
    }
}
Пример #8
0
static int saudio_data_transfer_process(struct saudio_stream *stream,
					    struct saudio_msg *msg)
{
	struct snd_pcm_runtime *runtime = stream->substream->runtime;
	struct sblock blk = { 0 };
	int32_t result = 0;
	struct cmd_common *common = NULL;

	int32_t elapsed_blks = 0;
	int32_t periods_avail;
	int32_t periods_tosend;
	int32_t cur_blk_count = 0;

	cur_blk_count = sblock_get_free_count(stream->dst, stream->channel);

	elapsed_blks =
	    (cur_blk_count + stream->last_getblk_count - stream->blk_count) -
	    stream->last_elapsed_count;

	if (stream->stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
		periods_avail = snd_pcm_playback_avail(runtime) /
		    runtime->period_size;
	} else {
		periods_avail = snd_pcm_capture_avail(runtime) /
		    runtime->period_size;
	}

	periods_tosend = stream->periods_avail - periods_avail;
	if (periods_tosend > 0) {
		stream->periods_tosend += periods_tosend;
	}

	if (stream->periods_tosend) {
		while (stream->periods_tosend) {
			result =
			    sblock_get(stream->dst, stream->channel, &blk, 0);
			if (result) {
				break;
			}
			stream->last_getblk_count++;
			common = (struct cmd_common *)blk.addr;
			blk.length =
			    frames_to_bytes(runtime, runtime->period_size);
			common->command = SAUDIO_DATA_PCM;
			common->sub_cmd = stream->stream_id;
			common->reserved1 =
			    stream->substream->dma_buffer.addr +
			    stream->period * blk.length;

			sblock_send(stream->dst, stream->channel, &blk);

			stream->periods_tosend--;
			stream->period++;
			stream->period = stream->period % runtime->periods;
		}

	} else {
		pr_debug("saudio.c: saudio no data to send ");
		if (sblock_get_free_count(stream->dst, stream->channel) ==
		    SAUDIO_STREAM_BLOCK_COUNT) {
			pr_debug
			    ("saudio.c: saudio no data to send and  is empty ");
			result =
			    sblock_get(stream->dst, stream->channel, &blk, 0);
			if (result) {
				ETRACE("saudio.c: no data and no blk\n");
			} else {
				stream->last_getblk_count++;
				common = (struct cmd_common *)blk.addr;
				common->command = SAUDIO_DATA_SILENCE;
				common->sub_cmd = stream->stream_id;

				sblock_send(stream->dst, stream->channel, &blk);
				stream->last_elapsed_count++;
				schedule_timeout(msecs_to_jiffies(1));
			}
		}
	}

	while (elapsed_blks) {
		elapsed_blks--;
		stream->hwptr_done++;
		stream->hwptr_done %= runtime->periods;
		snd_pcm_period_elapsed(stream->substream);
		stream->periods_avail++;
		stream->last_elapsed_count++;
	}

	return 0;
}