ALSA: PCM midlevel: improve fifo_size handling
Move the fifo_size assignment to hw->ioctl callback to allow lowlevel drivers overwrite the default behaviour. fifo_size is in frames not bytes as specified in asound.h and alsa-lib's documentation, but most hardware have fixed byte based FIFOs. Introduce internal SNDRV_PCM_INFO_FIFO_IN_FRAMES. Signed-off-by: Jaroslav Kysela <perex@perex.cz> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
					parent
					
						
							
								e93721a702
							
						
					
				
			
			
				commit
				
					
						8bea869c5e
					
				
			
		
					 4 changed files with 33 additions and 3 deletions
				
			
		|  | @ -255,6 +255,7 @@ typedef int __bitwise snd_pcm_subformat_t; | |||
| #define SNDRV_PCM_INFO_HALF_DUPLEX	0x00100000	/* only half duplex */ | ||||
| #define SNDRV_PCM_INFO_JOINT_DUPLEX	0x00200000	/* playback and capture stream are somewhat correlated */ | ||||
| #define SNDRV_PCM_INFO_SYNC_START	0x00400000	/* pcm support some kind of sync go */ | ||||
| #define SNDRV_PCM_INFO_FIFO_IN_FRAMES	0x80000000	/* internal kernel flag - FIFO size is in frames */ | ||||
| 
 | ||||
| typedef int __bitwise snd_pcm_state_t; | ||||
| #define	SNDRV_PCM_STATE_OPEN		((__force snd_pcm_state_t) 0) /* stream is open */ | ||||
|  |  | |||
|  | @ -98,6 +98,7 @@ struct snd_pcm_ops { | |||
| #define SNDRV_PCM_IOCTL1_INFO		1 | ||||
| #define SNDRV_PCM_IOCTL1_CHANNEL_INFO	2 | ||||
| #define SNDRV_PCM_IOCTL1_GSTATE		3 | ||||
| #define SNDRV_PCM_IOCTL1_FIFO_SIZE	4 | ||||
| 
 | ||||
| #define SNDRV_PCM_TRIGGER_STOP		0 | ||||
| #define SNDRV_PCM_TRIGGER_START		1 | ||||
|  |  | |||
|  | @ -1524,6 +1524,23 @@ static int snd_pcm_lib_ioctl_channel_info(struct snd_pcm_substream *substream, | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream, | ||||
| 				       void *arg) | ||||
| { | ||||
| 	struct snd_pcm_hw_params *params = arg; | ||||
| 	snd_pcm_format_t format; | ||||
| 	int channels, width; | ||||
| 
 | ||||
| 	params->fifo_size = substream->runtime->hw.fifo_size; | ||||
| 	if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_FIFO_IN_FRAMES)) { | ||||
| 		format = params_format(params); | ||||
| 		channels = params_channels(params); | ||||
| 		width = snd_pcm_format_physical_width(format); | ||||
| 		params->fifo_size /= width * channels; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * snd_pcm_lib_ioctl - a generic PCM ioctl callback | ||||
|  * @substream: the pcm substream instance | ||||
|  | @ -1545,6 +1562,8 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, | |||
| 		return snd_pcm_lib_ioctl_reset(substream, arg); | ||||
| 	case SNDRV_PCM_IOCTL1_CHANNEL_INFO: | ||||
| 		return snd_pcm_lib_ioctl_channel_info(substream, arg); | ||||
| 	case SNDRV_PCM_IOCTL1_FIFO_SIZE: | ||||
| 		return snd_pcm_lib_ioctl_fifo_size(substream, arg); | ||||
| 	} | ||||
| 	return -ENXIO; | ||||
| } | ||||
|  |  | |||
|  | @ -312,9 +312,18 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, | |||
| 
 | ||||
| 	hw = &substream->runtime->hw; | ||||
| 	if (!params->info) | ||||
| 		params->info = hw->info; | ||||
| 	if (!params->fifo_size) | ||||
| 		params->fifo_size = hw->fifo_size; | ||||
| 		params->info = hw->info & ~SNDRV_PCM_INFO_FIFO_IN_FRAMES; | ||||
| 	if (!params->fifo_size) { | ||||
| 		if (snd_mask_min(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT]) == | ||||
| 		    snd_mask_max(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT]) && | ||||
|                     snd_mask_min(¶ms->masks[SNDRV_PCM_HW_PARAM_CHANNELS]) == | ||||
|                     snd_mask_max(¶ms->masks[SNDRV_PCM_HW_PARAM_CHANNELS])) { | ||||
| 			changed = substream->ops->ioctl(substream, | ||||
| 					SNDRV_PCM_IOCTL1_FIFO_SIZE, params); | ||||
| 			if (params < 0) | ||||
| 				return changed; | ||||
| 		} | ||||
| 	} | ||||
| 	params->rmask = 0; | ||||
| 	return 0; | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jaroslav Kysela
				Jaroslav Kysela