Commit 8bea869c authored by Jaroslav Kysela's avatar Jaroslav Kysela Committed by Takashi Iwai

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: default avatarJaroslav Kysela <perex@perex.cz>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent e93721a7
...@@ -255,6 +255,7 @@ typedef int __bitwise snd_pcm_subformat_t; ...@@ -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 { ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT]) ==
snd_mask_max(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT]) &&
snd_mask_min(&params->masks[SNDRV_PCM_HW_PARAM_CHANNELS]) ==
snd_mask_max(&params->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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment