diff options
| author | Jaroslav Kysela <perex@perex.cz> | 2009-04-27 03:44:40 -0400 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2009-05-29 05:47:33 -0400 |
| commit | 8bea869c5e56234990e6bad92a543437115bfc18 (patch) | |
| tree | 7d0a5c4eeeeb69623066eccb363f35e0f2e3fda6 | |
| parent | e93721a70263afefbac781f575bfe851c6f95d84 (diff) | |
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>
| -rw-r--r-- | include/sound/asound.h | 1 | ||||
| -rw-r--r-- | include/sound/pcm.h | 1 | ||||
| -rw-r--r-- | sound/core/pcm_lib.c | 19 | ||||
| -rw-r--r-- | sound/core/pcm_native.c | 15 |
4 files changed, 33 insertions, 3 deletions
diff --git a/include/sound/asound.h b/include/sound/asound.h index 6add80fc2512..82aed3f47534 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h | |||
| @@ -255,6 +255,7 @@ typedef int __bitwise snd_pcm_subformat_t; | |||
| 255 | #define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */ | 255 | #define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */ |
| 256 | #define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */ | 256 | #define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */ |
| 257 | #define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */ | 257 | #define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */ |
| 258 | #define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ | ||
| 258 | 259 | ||
| 259 | typedef int __bitwise snd_pcm_state_t; | 260 | typedef int __bitwise snd_pcm_state_t; |
| 260 | #define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */ | 261 | #define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */ |
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 267effddb070..8a69b5c1e1c4 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
| @@ -98,6 +98,7 @@ struct snd_pcm_ops { | |||
| 98 | #define SNDRV_PCM_IOCTL1_INFO 1 | 98 | #define SNDRV_PCM_IOCTL1_INFO 1 |
| 99 | #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2 | 99 | #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2 |
| 100 | #define SNDRV_PCM_IOCTL1_GSTATE 3 | 100 | #define SNDRV_PCM_IOCTL1_GSTATE 3 |
| 101 | #define SNDRV_PCM_IOCTL1_FIFO_SIZE 4 | ||
| 101 | 102 | ||
| 102 | #define SNDRV_PCM_TRIGGER_STOP 0 | 103 | #define SNDRV_PCM_TRIGGER_STOP 0 |
| 103 | #define SNDRV_PCM_TRIGGER_START 1 | 104 | #define SNDRV_PCM_TRIGGER_START 1 |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index d659995ac3ac..adc2b0bd1132 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
| @@ -1524,6 +1524,23 @@ static int snd_pcm_lib_ioctl_channel_info(struct snd_pcm_substream *substream, | |||
| 1524 | return 0; | 1524 | return 0; |
| 1525 | } | 1525 | } |
| 1526 | 1526 | ||
| 1527 | static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream, | ||
| 1528 | void *arg) | ||
| 1529 | { | ||
| 1530 | struct snd_pcm_hw_params *params = arg; | ||
| 1531 | snd_pcm_format_t format; | ||
| 1532 | int channels, width; | ||
| 1533 | |||
| 1534 | params->fifo_size = substream->runtime->hw.fifo_size; | ||
| 1535 | if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_FIFO_IN_FRAMES)) { | ||
| 1536 | format = params_format(params); | ||
| 1537 | channels = params_channels(params); | ||
| 1538 | width = snd_pcm_format_physical_width(format); | ||
| 1539 | params->fifo_size /= width * channels; | ||
| 1540 | } | ||
| 1541 | return 0; | ||
| 1542 | } | ||
| 1543 | |||
| 1527 | /** | 1544 | /** |
| 1528 | * snd_pcm_lib_ioctl - a generic PCM ioctl callback | 1545 | * snd_pcm_lib_ioctl - a generic PCM ioctl callback |
| 1529 | * @substream: the pcm substream instance | 1546 | * @substream: the pcm substream instance |
| @@ -1545,6 +1562,8 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, | |||
| 1545 | return snd_pcm_lib_ioctl_reset(substream, arg); | 1562 | return snd_pcm_lib_ioctl_reset(substream, arg); |
| 1546 | case SNDRV_PCM_IOCTL1_CHANNEL_INFO: | 1563 | case SNDRV_PCM_IOCTL1_CHANNEL_INFO: |
| 1547 | return snd_pcm_lib_ioctl_channel_info(substream, arg); | 1564 | return snd_pcm_lib_ioctl_channel_info(substream, arg); |
| 1565 | case SNDRV_PCM_IOCTL1_FIFO_SIZE: | ||
| 1566 | return snd_pcm_lib_ioctl_fifo_size(substream, arg); | ||
| 1548 | } | 1567 | } |
| 1549 | return -ENXIO; | 1568 | return -ENXIO; |
| 1550 | } | 1569 | } |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 45dc53fcfa2f..84da3ba17c86 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
| @@ -312,9 +312,18 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, | |||
| 312 | 312 | ||
| 313 | hw = &substream->runtime->hw; | 313 | hw = &substream->runtime->hw; |
| 314 | if (!params->info) | 314 | if (!params->info) |
| 315 | params->info = hw->info; | 315 | params->info = hw->info & ~SNDRV_PCM_INFO_FIFO_IN_FRAMES; |
| 316 | if (!params->fifo_size) | 316 | if (!params->fifo_size) { |
| 317 | params->fifo_size = hw->fifo_size; | 317 | if (snd_mask_min(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT]) == |
| 318 | snd_mask_max(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT]) && | ||
| 319 | snd_mask_min(¶ms->masks[SNDRV_PCM_HW_PARAM_CHANNELS]) == | ||
| 320 | snd_mask_max(¶ms->masks[SNDRV_PCM_HW_PARAM_CHANNELS])) { | ||
| 321 | changed = substream->ops->ioctl(substream, | ||
| 322 | SNDRV_PCM_IOCTL1_FIFO_SIZE, params); | ||
| 323 | if (params < 0) | ||
| 324 | return changed; | ||
| 325 | } | ||
| 326 | } | ||
| 318 | params->rmask = 0; | 327 | params->rmask = 0; |
| 319 | return 0; | 328 | return 0; |
| 320 | } | 329 | } |
