コード例 #1
0
ファイル: wmt-pdm-pcm.c プロジェクト: wondermedia/wm8850
static snd_pcm_uframes_t wmt_pdm_pcm_pointer(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct audio_stream_a *prtd = runtime->private_data;
	int stream_id = substream->pstr->stream;
	struct audio_stream_a *s = &prtd[stream_id];
	dma_addr_t ptr;
	snd_pcm_uframes_t offset = 0;

	//DBG_DETAIL();
	
	ptr = wmt_get_dma_pos(s->dmach);
	/*
	if (((runtime->channels == 1) && (runtime->format == SNDRV_PCM_FORMAT_S16_LE)) || 
		((runtime->channels == 2) && (runtime->format == SNDRV_PCM_FORMAT_U8))) {
		offset = bytes_to_frames(runtime, (ptr - dump_buf[stream_id].addr) >> 1);
	}
	else if ((runtime->channels == 1) && (runtime->format == SNDRV_PCM_FORMAT_U8)) {
		offset = bytes_to_frames(runtime, (ptr - dump_buf[stream_id].addr) >> 2);
	}
	else if ((runtime->channels == 2) && (runtime->format == SNDRV_PCM_FORMAT_FLOAT)) {
		offset = bytes_to_frames(runtime, (ptr - dump_buf[stream_id].addr) << 1);
	}
	else if ((runtime->channels == 1) && (runtime->format == SNDRV_PCM_FORMAT_FLOAT)) {
		offset = bytes_to_frames(runtime, ptr - dump_buf[stream_id].addr);
	}	
	else
		offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
	*/
	if (((runtime->channels == 2) && (runtime->format == SNDRV_PCM_FORMAT_S16_LE))  ||
		((runtime->channels == 1) && (runtime->format == SNDRV_PCM_FORMAT_S16_LE))) {
		offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
	}

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

	spin_lock(&s->dma_lock);

	if (s->periods > 0 && s->periods < 2) {
		if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
			if (snd_pcm_playback_hw_avail(runtime) >= 2 * runtime->period_size)
				audio_process_dma(s);
		}
		else {
			if (snd_pcm_capture_hw_avail(runtime) >= 2* runtime->period_size)
				audio_process_dma(s);
		}
		
	}
	spin_unlock(&s->dma_lock);

	//DPRINTK("offset = %x", (unsigned int)offset);
	return offset;
}
コード例 #2
0
ファイル: ksound-core.c プロジェクト: Audioniek/Fortis-4G
/* call with interrupts locked? */
static int _ksnd_pcm_update_appl_ptr(snd_pcm_substream_t *substream,
									 snd_pcm_uframes_t appl_ptr)
{
	snd_pcm_runtime_t *runtime = substream->runtime;
	snd_pcm_sframes_t hw_avail;
	int err;
	runtime->control->appl_ptr = appl_ptr;
	if (substream->ops->ack)
		substream->ops->ack(substream);
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		hw_avail = snd_pcm_playback_hw_avail(runtime);
	else
		hw_avail = snd_pcm_capture_hw_avail(runtime);
	if (runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
			hw_avail >= (snd_pcm_sframes_t) runtime->start_threshold)
	{
		err = snd_pcm_start(substream);
		if (err < 0)
			return err;
	}
	return 0;
}
コード例 #3
0
__s32 i2sirx_i2so_mix_engine
(
    void *param
)
{
    __u32                        mix_len;
    __u32                        i2so_len;    
    __u32                        i2sirx_len;  
    __u32                        mix_free;  
    uint32_t                     drop_ms;
    uint32_t                     align_ms;
    struct i2sirx_i2so_mix_info *mix;

    mix = &i2sirx_i2so_mix_info;
    
    for (;;)
    {
        if (kthread_should_stop())
        {
            printk("%s,%d,now exit.\n", __FUNCTION__, __LINE__);

            return(-__LINE__);
        }
        
        if (I2SIRX_I2SO_MIX_STATE_RUN != mix->state)
        {
            msleep_interruptible(40);

            continue;
        }
     
        mix_free = snd_pcm_capture_hw_avail(mix->capture_subs->runtime);
        mix_free = frames_to_bytes(mix->capture_subs->runtime, mix_free);

        if (mix_free < mix->period_bytes)
        {
            msleep_interruptible(40);
            continue;
        }

        i2so_len = i2so_see2main_ring_avail();
        if (i2so_len < mix->period_bytes)
        {
            msleep_interruptible(40);
            continue;
        }   

        i2sirx_len = i2sirx_see2main_ring_avail();
        if (i2sirx_len < mix->period_bytes / 4)
        {
            msleep_interruptible(40);
            continue;
        }

        /* Drop first 500ms data to march up with kalaok pictures.
         * Drop duration(in ms) could be customized by user space.
        */
        drop_ms = ali_alsa_i2sirx_i2so_mix_drop_ms_get();
        if (time_before(jiffies, mix->open_jiffies + drop_ms))
        {
            i2so_see2main_ring_read(i2so_see2main_read_buf, mix->period_bytes);
            i2sirx_see2main_ring_read(i2sirx_see2main_read_buf,
                mix->period_bytes / 4);
            continue;
        }   

        /* Compensate SPO PCM delay caused by SEE audio buffer. 
         * Align duration(in ms) could be customized by user space.
        */
        if (0 == mix->i2so_see2main_1st_jiffies)
        {
            mix->i2so_see2main_1st_jiffies = jiffies;         
        }

        align_ms = ali_alsa_i2sirx_i2so_mix_align_ms_get();
        
        if (time_after(jiffies, mix->i2so_see2main_1st_jiffies + align_ms))
        {
            i2so_see2main_ring_read(i2so_see2main_read_buf, mix->period_bytes);
    
            /* For debug.
            */
            if (1 == ali_alsa_i2so_see2main_dump_en_get())
            {
                ali_alsa_dump_data("/data/data/ali_alsa_i2so_see2main_dump.pcm",
                    i2so_see2main_read_buf, mix->period_bytes);     
            }
        }
        else
        {
            memset(i2so_see2main_read_buf, 0, mix->period_bytes);
        }

        /* Read data from MIC, prepair for mixing.
        */
        i2sirx_len = i2sirx_see2main_ring_read(i2sirx_see2main_read_buf,
            mix->period_bytes / 4);

        /* For debug.
        */
        if (1 == ali_alsa_i2sirx_see2main_dump_en_get())
        {
            ali_alsa_dump_data("/data/data/ali_alsa_i2sirx_see2main_dump.pcm",
                i2sirx_see2main_read_buf, i2sirx_len);    
        }

		/* Mix it.
		 * SPO: 44.1K, 32 bit, LE;
		 * MIC: 44.1K, 16 bit, LE.
		*/
        i2sirx_i2so_mix(i2so_see2main_read_buf, mix->period_bytes,
            i2sirx_see2main_read_buf, i2sirx_len, i2sirx_i2so_mix_buf);  

        /* For debug.
        */
        if (1 == ali_alsa_i2sirx_i2so_mix_dump_en_get())
        {
            ali_alsa_dump_data("/data/data/ali_alsa_i2sirx_i2so_mix_dump.pcm",
                i2sirx_i2so_mix_buf, mix->period_bytes);          
        }
        
        i2sirx_i2so_mix_ring_write(i2sirx_i2so_mix_buf, mix->period_bytes);
        
        snd_pcm_period_elapsed(mix->capture_subs);
    }

    return(0);
}