mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	ALSA: pcm: calculate non-mask/non-interval parameters always when possible
A structure for parameters of PCM runtime has parameters which are not classified as mask/interval type. They are decided only when corresponding normal parameters have unique values. * struct snd_pcm_hw_params.msbits * struct snd_pcm_hw_params.rate_num * struct snd_pcm_hw_params.rate_den * struct snd_pcm_hw_params.fifo_size Current implementation of hw_params ioctl sometimes doesn't decide these parameters even if corresponding parameters are fixed, because these parameters are evaluated before a call of snd_pcm_hw_params_choose(). This commit adds a helper function to process the parameters and call it in proper positions. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
							parent
							
								
									e02de47e3c
								
							
						
					
					
						commit
						f9a076bff0
					
				
					 1 changed files with 44 additions and 26 deletions
				
			
		| 
						 | 
					@ -440,12 +440,45 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
 | 
				
			||||||
 | 
									     struct snd_pcm_hw_params *params)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct snd_interval *i;
 | 
				
			||||||
 | 
						const struct snd_mask *m;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!params->msbits) {
 | 
				
			||||||
 | 
							i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
 | 
				
			||||||
 | 
							if (snd_interval_single(i))
 | 
				
			||||||
 | 
								params->msbits = snd_interval_value(i);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!params->rate_den) {
 | 
				
			||||||
 | 
							i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
 | 
				
			||||||
 | 
							if (snd_interval_single(i)) {
 | 
				
			||||||
 | 
								params->rate_num = snd_interval_value(i);
 | 
				
			||||||
 | 
								params->rate_den = 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!params->fifo_size) {
 | 
				
			||||||
 | 
							m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
 | 
				
			||||||
 | 
							i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
 | 
				
			||||||
 | 
							if (snd_mask_single(m) && snd_interval_single(i)) {
 | 
				
			||||||
 | 
								err = substream->ops->ioctl(substream,
 | 
				
			||||||
 | 
										SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
 | 
				
			||||||
 | 
								if (err < 0)
 | 
				
			||||||
 | 
									return err;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
 | 
					int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
 | 
				
			||||||
		      struct snd_pcm_hw_params *params)
 | 
							      struct snd_pcm_hw_params *params)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct snd_pcm_hardware *hw;
 | 
						struct snd_pcm_hardware *hw;
 | 
				
			||||||
	const struct snd_interval *i;
 | 
					 | 
				
			||||||
	const struct snd_mask *m;
 | 
					 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params->info = 0;
 | 
						params->info = 0;
 | 
				
			||||||
| 
						 | 
					@ -469,20 +502,6 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
 | 
				
			||||||
	if (err < 0)
 | 
						if (err < 0)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!params->msbits) {
 | 
					 | 
				
			||||||
		i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
 | 
					 | 
				
			||||||
		if (snd_interval_single(i))
 | 
					 | 
				
			||||||
			params->msbits = snd_interval_value(i);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!params->rate_den) {
 | 
					 | 
				
			||||||
		i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
 | 
					 | 
				
			||||||
		if (snd_interval_single(i)) {
 | 
					 | 
				
			||||||
			params->rate_num = snd_interval_value(i);
 | 
					 | 
				
			||||||
			params->rate_den = 1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	hw = &substream->runtime->hw;
 | 
						hw = &substream->runtime->hw;
 | 
				
			||||||
	if (!params->info) {
 | 
						if (!params->info) {
 | 
				
			||||||
		params->info = hw->info & ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES |
 | 
							params->info = hw->info & ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES |
 | 
				
			||||||
| 
						 | 
					@ -491,16 +510,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
 | 
				
			||||||
			params->info &= ~(SNDRV_PCM_INFO_MMAP |
 | 
								params->info &= ~(SNDRV_PCM_INFO_MMAP |
 | 
				
			||||||
					  SNDRV_PCM_INFO_MMAP_VALID);
 | 
										  SNDRV_PCM_INFO_MMAP_VALID);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (!params->fifo_size) {
 | 
					
 | 
				
			||||||
		m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
 | 
					 | 
				
			||||||
		i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
 | 
					 | 
				
			||||||
		if (snd_mask_single(m) && snd_interval_single(i)) {
 | 
					 | 
				
			||||||
			err = substream->ops->ioctl(substream,
 | 
					 | 
				
			||||||
					SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
 | 
					 | 
				
			||||||
			if (err < 0)
 | 
					 | 
				
			||||||
				return err;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	params->rmask = 0;
 | 
						params->rmask = 0;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -517,6 +527,8 @@ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
 | 
				
			||||||
		return PTR_ERR(params);
 | 
							return PTR_ERR(params);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = snd_pcm_hw_refine(substream, params);
 | 
						err = snd_pcm_hw_refine(substream, params);
 | 
				
			||||||
 | 
						if (err >= 0)
 | 
				
			||||||
 | 
							err = fixup_unreferenced_params(substream, params);
 | 
				
			||||||
	if (copy_to_user(_params, params, sizeof(*params))) {
 | 
						if (copy_to_user(_params, params, sizeof(*params))) {
 | 
				
			||||||
		if (!err)
 | 
							if (!err)
 | 
				
			||||||
			err = -EFAULT;
 | 
								err = -EFAULT;
 | 
				
			||||||
| 
						 | 
					@ -596,6 +608,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
 | 
				
			||||||
	if (err < 0)
 | 
						if (err < 0)
 | 
				
			||||||
		goto _error;
 | 
							goto _error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = fixup_unreferenced_params(substream, params);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							goto _error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (substream->ops->hw_params != NULL) {
 | 
						if (substream->ops->hw_params != NULL) {
 | 
				
			||||||
		err = substream->ops->hw_params(substream, params);
 | 
							err = substream->ops->hw_params(substream, params);
 | 
				
			||||||
		if (err < 0)
 | 
							if (err < 0)
 | 
				
			||||||
| 
						 | 
					@ -3621,6 +3637,8 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	snd_pcm_hw_convert_from_old_params(params, oparams);
 | 
						snd_pcm_hw_convert_from_old_params(params, oparams);
 | 
				
			||||||
	err = snd_pcm_hw_refine(substream, params);
 | 
						err = snd_pcm_hw_refine(substream, params);
 | 
				
			||||||
 | 
						if (err >= 0)
 | 
				
			||||||
 | 
							err = fixup_unreferenced_params(substream, params);
 | 
				
			||||||
	snd_pcm_hw_convert_to_old_params(oparams, params);
 | 
						snd_pcm_hw_convert_to_old_params(oparams, params);
 | 
				
			||||||
	if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
 | 
						if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
 | 
				
			||||||
		if (!err)
 | 
							if (!err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue