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; }
/* 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; }
__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); }