static snd_pcm_uframes_t aml_i2s_pointer( struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct aml_runtime_data *prtd = runtime->private_data; audio_stream_t *s = &prtd->s; unsigned int addr, ptr; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (s->device_type == AML_AUDIO_I2SOUT) { ptr = read_i2s_rd_ptr(); } else { ptr = read_iec958_rd_ptr(); } addr = ptr - s->I2S_addr; return bytes_to_frames(runtime, addr); } else { if (s->device_type == AML_AUDIO_I2SIN) { ptr = audio_in_i2s_wr_ptr(); } else { ptr = audio_in_spdif_wr_ptr(); } addr = ptr - s->I2S_addr; return bytes_to_frames(runtime, addr) / 2; } return 0; }
static void aml_pcm_timer_callback(unsigned long data) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data; struct snd_pcm_runtime *runtime = substream->runtime; struct aml_runtime_data *prtd = runtime->private_data; audio_stream_t *s = &prtd->s; unsigned int last_ptr, size; if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ if(s->active == 1){ spin_lock(&s->lock); last_ptr = read_i2s_rd_ptr(); if (last_ptr < s->last_ptr) { size = runtime->dma_bytes + last_ptr - (s->last_ptr); } else { size = last_ptr - (s->last_ptr); } s->last_ptr = last_ptr; s->size += bytes_to_frames(substream->runtime, size); if (s->size >= runtime->period_size) { s->size %= runtime->period_size; spin_unlock(&s->lock); snd_pcm_period_elapsed(substream); spin_lock(&s->lock); } mod_timer(&prtd->timer, jiffies + 1); spin_unlock(&s->lock); }else{ mod_timer(&prtd->timer, jiffies + 1); } }else{ if(s->active == 1){ spin_lock(&s->lock); last_ptr = (audio_in_i2s_wr_ptr() - s->I2S_addr) / 2; if (last_ptr < s->last_ptr) { size = runtime->dma_bytes + last_ptr - (s->last_ptr); } else { size = last_ptr - (s->last_ptr); } s->last_ptr = last_ptr; s->size += bytes_to_frames(substream->runtime, size); if (s->size >= runtime->period_size) { s->size %= runtime->period_size; spin_unlock(&s->lock); snd_pcm_period_elapsed(substream); spin_lock(&s->lock); } mod_timer(&prtd->timer, jiffies + 1); spin_unlock(&s->lock); }else{ mod_timer(&prtd->timer, jiffies + 1); } } }
static enum hrtimer_restart aml_i2s_hrtimer_callback(struct hrtimer* timer) { struct aml_runtime_data* prtd = container_of(timer, struct aml_runtime_data, hrtimer); audio_stream_t* s = &prtd->s; struct snd_pcm_substream* substream = prtd->substream; struct snd_pcm_runtime* runtime = substream->runtime; unsigned int last_ptr, size; //unsigned long flag; //printk("------------->hrtimer start\n"); if (s->active == 0) { hrtimer_forward_now(timer, ns_to_ktime(HRTIMER_PERIOD)); return HRTIMER_RESTART; } //spin_lock_irqsave(&s->lock, flag); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { last_ptr = read_i2s_rd_ptr(); if (last_ptr < s->last_ptr) { size = runtime->dma_bytes + last_ptr - s->last_ptr; } else { size = last_ptr - s->last_ptr; } s->last_ptr = last_ptr; s->size += bytes_to_frames(substream->runtime, size); if (s->size >= runtime->period_size) { s->size %= runtime->period_size; snd_pcm_period_elapsed(substream); } } else{ last_ptr = (audio_in_i2s_wr_ptr() - s->I2S_addr) / 2; if (last_ptr < s->last_ptr) { size = runtime->dma_bytes + last_ptr - s->last_ptr; } else{ size = last_ptr - s->last_ptr; } s->last_ptr = last_ptr; s->size += bytes_to_frames(runtime, size); if (s->size >= runtime->period_size) { s->size %= runtime->period_size; snd_pcm_period_elapsed(substream); } } //spin_unlock_irqrestore(&s->lock, flag); hrtimer_forward_now(timer, ns_to_ktime(HRTIMER_PERIOD)); return HRTIMER_RESTART; }
static void aml_i2s_timer_callback(unsigned long data) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data; struct snd_pcm_runtime *runtime = substream->runtime; struct aml_runtime_data *prtd = runtime->private_data; audio_stream_t *s = &prtd->s; unsigned int last_ptr, size = 0; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (s->active == 1) { spin_lock(&s->lock); if (s->device_type == AML_AUDIO_I2SOUT) { last_ptr = read_i2s_rd_ptr(); } else { last_ptr = read_iec958_rd_ptr(); } if (last_ptr < s->last_ptr) { size = runtime->dma_bytes + last_ptr - (s->last_ptr); } else { size = last_ptr - (s->last_ptr); } s->last_ptr = last_ptr; s->size += bytes_to_frames(substream->runtime, size); if (s->size >= runtime->period_size) { s->size %= runtime->period_size; spin_unlock(&s->lock); snd_pcm_period_elapsed(substream); spin_lock(&s->lock); } mod_timer(&prtd->timer, jiffies + 1); spin_unlock(&s->lock); } else { mod_timer(&prtd->timer, jiffies + 1); } } else { if (s->active == 1) { spin_lock(&s->lock); if (s->device_type == AML_AUDIO_I2SIN) { last_ptr = audio_in_i2s_wr_ptr() ; } else { last_ptr = audio_in_spdif_wr_ptr(); } if (last_ptr < s->last_ptr) { size = runtime->dma_bytes + (last_ptr - (s->last_ptr)) / 2; } else if (last_ptr == s->last_ptr) { if (s->xrun_num++ > 100) { printk(KERN_INFO "alsa capture long time no data, quit xrun!\n"); s->xrun_num = 0; s->size = runtime->period_size; } } else { size = (last_ptr - (s->last_ptr)) / 2; } s->last_ptr = last_ptr; s->size += bytes_to_frames(substream->runtime, size); if (s->size >= runtime->period_size) { s->size %= runtime->period_size; spin_unlock(&s->lock); snd_pcm_period_elapsed(substream); spin_lock(&s->lock); } mod_timer(&prtd->timer, jiffies + 1); spin_unlock(&s->lock); } else { mod_timer(&prtd->timer, jiffies + 1); } } }
static void aml_pcm_timer_callback(unsigned long data) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data; struct snd_pcm_runtime *runtime = substream->runtime; struct aml_runtime_data *prtd = runtime->private_data; audio_stream_t *s = &prtd->s; unsigned int last_ptr = 0, size = 0; if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ if(s->active == 1){ spin_lock(&s->lock); last_ptr = read_i2s_rd_ptr(); if (last_ptr < s->last_ptr) { size = runtime->dma_bytes + last_ptr - (s->last_ptr); } else { size = last_ptr - (s->last_ptr); } s->last_ptr = last_ptr; s->size += bytes_to_frames(substream->runtime, size); if (s->size >= runtime->period_size) { s->size %= runtime->period_size; spin_unlock(&s->lock); snd_pcm_period_elapsed(substream); spin_lock(&s->lock); } mod_timer(&prtd->timer, jiffies + 1); //codec_power = 1; spin_unlock(&s->lock); }else{ mod_timer(&prtd->timer, jiffies + 1); // codec_power = 0; } }else{ if(s->active == 1){ spin_lock(&s->lock); last_ptr = (audio_in_i2s_wr_ptr() - s->I2S_addr) / 2; if (last_ptr < s->last_ptr) { size = runtime->dma_bytes + last_ptr - (s->last_ptr); } else if(last_ptr == s->last_ptr){ if(s->xrun_num ++ > 100){ printk(KERN_INFO "alsa capture long time no data, quit xrun !\n"); s->xrun_num = 0; s->size = runtime->period_size; } } else { size = last_ptr - (s->last_ptr); } s->last_ptr = last_ptr; s->size += bytes_to_frames(substream->runtime, size); if (s->size >= runtime->period_size) { s->size %= runtime->period_size; spin_unlock(&s->lock); snd_pcm_period_elapsed(substream); spin_lock(&s->lock); } mod_timer(&prtd->timer, jiffies + 1); spin_unlock(&s->lock); }else{ mod_timer(&prtd->timer, jiffies + 1); } } /* if((codec_power==0) && (num==500)) { num=0; flag=1; schedule_work(&aml_pcm_work.aml_codec_workqueue); } else if((codec_power==1) && (num <= 500)) { num=0; flag = 0; } else if((codec_power==0) && (num<500)) { if(flag==1) {} else { num++; } } */ }