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
@ -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_HALF_DUPLEX 0x00100000 /* only half duplex */
|
||||||
#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
|
#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_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;
|
typedef int __bitwise snd_pcm_state_t;
|
||||||
#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */
|
#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_INFO 1
|
||||||
#define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2
|
#define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2
|
||||||
#define SNDRV_PCM_IOCTL1_GSTATE 3
|
#define SNDRV_PCM_IOCTL1_GSTATE 3
|
||||||
|
#define SNDRV_PCM_IOCTL1_FIFO_SIZE 4
|
||||||
|
|
||||||
#define SNDRV_PCM_TRIGGER_STOP 0
|
#define SNDRV_PCM_TRIGGER_STOP 0
|
||||||
#define SNDRV_PCM_TRIGGER_START 1
|
#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;
|
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
|
* snd_pcm_lib_ioctl - a generic PCM ioctl callback
|
||||||
* @substream: the pcm substream instance
|
* @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);
|
return snd_pcm_lib_ioctl_reset(substream, arg);
|
||||||
case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
|
case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
|
||||||
return snd_pcm_lib_ioctl_channel_info(substream, arg);
|
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;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
|
@ -312,9 +312,18 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
hw = &substream->runtime->hw;
|
hw = &substream->runtime->hw;
|
||||||
if (!params->info)
|
if (!params->info)
|
||||||
params->info = hw->info;
|
params->info = hw->info & ~SNDRV_PCM_INFO_FIFO_IN_FRAMES;
|
||||||
if (!params->fifo_size)
|
if (!params->fifo_size) {
|
||||||
params->fifo_size = hw->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;
|
params->rmask = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user