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;
}
Exemplo n.º 2
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);
        }
    }
}
Exemplo n.º 5
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 = 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++;
			}
		} */
}