mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	pcm: rate: fix the hw_ptr update until the boundary available
For long time test case, the slave_hw_ptr will exceed the boundary and wraparound the slave_hw_ptr. This slave boundary wraparound will cause the rate->hw_ptr to wraparound irrespective of the rate->boundary availability and due to that the available size goes wrong. Hence, to get the correct available size, - Its necessary to increment the rate->hw_ptr upto the rate->boundary and then wraparound the rate->hw_ptr. - While handling fraction part of slave period, rounded value will be introduced by input_frames(). To eliminate rounding issue on rate->hw_ptr, subtract last rounded value from rate->hw_ptr and add new rounded value of present slave_hw_ptr fraction part to rate->hw_ptr. Signed-off-by: mahendran.k <mahendran.kuppusamy@in.bosch.com> Signed-off-by: Mounesh Sutar <mounesh_sutar@mentor.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
							parent
							
								
									8eeee1ab7d
								
							
						
					
					
						commit
						7570e5d775
					
				
					 1 changed files with 25 additions and 6 deletions
				
			
		| 
						 | 
					@ -50,7 +50,7 @@ typedef struct _snd_pcm_rate snd_pcm_rate_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct _snd_pcm_rate {
 | 
					struct _snd_pcm_rate {
 | 
				
			||||||
	snd_pcm_generic_t gen;
 | 
						snd_pcm_generic_t gen;
 | 
				
			||||||
	snd_pcm_uframes_t appl_ptr, hw_ptr;
 | 
						snd_pcm_uframes_t appl_ptr, hw_ptr, last_slave_hw_ptr;
 | 
				
			||||||
	snd_pcm_uframes_t last_commit_ptr;
 | 
						snd_pcm_uframes_t last_commit_ptr;
 | 
				
			||||||
	snd_pcm_uframes_t orig_avail_min;
 | 
						snd_pcm_uframes_t orig_avail_min;
 | 
				
			||||||
	snd_pcm_sw_params_t sw_params;
 | 
						snd_pcm_sw_params_t sw_params;
 | 
				
			||||||
| 
						 | 
					@ -563,14 +563,31 @@ static inline void snd_pcm_rate_sync_hwptr0(snd_pcm_t *pcm, snd_pcm_uframes_t sl
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	snd_pcm_rate_t *rate = pcm->private_data;
 | 
						snd_pcm_rate_t *rate = pcm->private_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						snd_pcm_sframes_t slave_hw_ptr_diff = slave_hw_ptr - rate->last_slave_hw_ptr;
 | 
				
			||||||
 | 
						snd_pcm_sframes_t last_slave_hw_ptr_frac;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
 | 
						if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	/* FIXME: boundary overlap of slave hw_ptr isn't evaluated here!
 | 
					
 | 
				
			||||||
	 *        e.g. if slave rate is small... 
 | 
						if (slave_hw_ptr_diff < 0)
 | 
				
			||||||
 | 
							slave_hw_ptr_diff += rate->gen.slave->boundary; /* slave boundary wraparound */
 | 
				
			||||||
 | 
						else if (slave_hw_ptr_diff == 0)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						last_slave_hw_ptr_frac = rate->last_slave_hw_ptr % rate->gen.slave->period_size;
 | 
				
			||||||
 | 
						/* While handling fraction part fo slave period, rounded value will be
 | 
				
			||||||
 | 
						 * introduced by input_frames().
 | 
				
			||||||
 | 
						 * To eliminate rounding issue on rate->hw_ptr, subtract last rounded
 | 
				
			||||||
 | 
						 * value from rate->hw_ptr and add new rounded value of present
 | 
				
			||||||
 | 
						 * slave_hw_ptr fraction part to rate->hw_ptr. Hence,
 | 
				
			||||||
 | 
						 * rate->hw_ptr += [ (no. of updated slave periods * pcm rate period size) -
 | 
				
			||||||
 | 
						 * 	fractional part of last_slave_hw_ptr rounded value +
 | 
				
			||||||
 | 
						 * 	fractional part of updated slave hw ptr's rounded value ]
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	rate->hw_ptr =
 | 
						rate->hw_ptr += (
 | 
				
			||||||
		(slave_hw_ptr / rate->gen.slave->period_size) * pcm->period_size +
 | 
								(((last_slave_hw_ptr_frac + slave_hw_ptr_diff) / rate->gen.slave->period_size) * pcm->period_size) -
 | 
				
			||||||
		rate->ops.input_frames(rate->obj, slave_hw_ptr % rate->gen.slave->period_size);
 | 
								rate->ops.input_frames(rate->obj, last_slave_hw_ptr_frac) +
 | 
				
			||||||
 | 
								rate->ops.input_frames(rate->obj, (last_slave_hw_ptr_frac + slave_hw_ptr_diff) % rate->gen.slave->period_size));
 | 
				
			||||||
 | 
						rate->last_slave_hw_ptr = slave_hw_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rate->hw_ptr %= pcm->boundary;
 | 
						rate->hw_ptr %= pcm->boundary;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -635,6 +652,7 @@ static int snd_pcm_rate_prepare(snd_pcm_t *pcm)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
	*pcm->hw.ptr = 0;
 | 
						*pcm->hw.ptr = 0;
 | 
				
			||||||
	*pcm->appl.ptr = 0;
 | 
						*pcm->appl.ptr = 0;
 | 
				
			||||||
 | 
						rate->last_slave_hw_ptr = 0;
 | 
				
			||||||
	err = snd_pcm_rate_init(pcm);
 | 
						err = snd_pcm_rate_init(pcm);
 | 
				
			||||||
	if (err < 0)
 | 
						if (err < 0)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
| 
						 | 
					@ -650,6 +668,7 @@ static int snd_pcm_rate_reset(snd_pcm_t *pcm)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
	*pcm->hw.ptr = 0;
 | 
						*pcm->hw.ptr = 0;
 | 
				
			||||||
	*pcm->appl.ptr = 0;
 | 
						*pcm->appl.ptr = 0;
 | 
				
			||||||
 | 
						rate->last_slave_hw_ptr = 0;
 | 
				
			||||||
	err = snd_pcm_rate_init(pcm);
 | 
						err = snd_pcm_rate_init(pcm);
 | 
				
			||||||
	if (err < 0)
 | 
						if (err < 0)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue