aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2009-04-27 09:44:40 +0200
committerTakashi Iwai <tiwai@suse.de>2009-05-29 11:47:33 +0200
commit8bea869c5e56234990e6bad92a543437115bfc18 (patch)
tree7d0a5c4eeeeb69623066eccb363f35e0f2e3fda6
parente93721a70263afefbac781f575bfe851c6f95d84 (diff)
downloadkernel_samsung_tuna-8bea869c5e56234990e6bad92a543437115bfc18.zip
kernel_samsung_tuna-8bea869c5e56234990e6bad92a543437115bfc18.tar.gz
kernel_samsung_tuna-8bea869c5e56234990e6bad92a543437115bfc18.tar.bz2
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.h1
-rw-r--r--include/sound/pcm.h1
-rw-r--r--sound/core/pcm_lib.c19
-rw-r--r--sound/core/pcm_native.c15
4 files changed, 33 insertions, 3 deletions
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 6add80f..82aed3f 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -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 */
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 267effd..8a69b5c 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -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
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index d659995..adc2b0b 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,
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;
}
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 45dc53f..84da3ba 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,
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(&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;
return 0;
}