summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2011-01-26 16:59:39 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-01-26 20:24:10 +0000
commit58e8a4741b519910cdabdd55c23f258e40cf6a3a (patch)
tree2781f2a841319e2320c0108046309687081277c3
parente831d80b453a3586f1e1664a705c153a4ced39b8 (diff)
ALSA: AACI: fix channel mask selection
When double-rate mode was selected, we weren't setting the additional two channel mask bits to allow double-rate to work. Rearrange the hw_params code to allow the correct channel mask to be selected. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--sound/arm/aaci.c70
1 files changed, 20 insertions, 50 deletions
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index ab66d462d865..8915e56d1b51 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -490,12 +490,21 @@ static int aaci_pcm_hw_free(struct snd_pcm_substream *substream)
return 0;
}
+/* Channel to slot mask */
+static const u32 channels_to_slotmask[] = {
+ [2] = CR_SL3 | CR_SL4,
+ [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8,
+ [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,
+};
+
static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
- struct aaci_runtime *aacirun,
struct snd_pcm_hw_params *params)
{
+ struct aaci_runtime *aacirun = substream->runtime->private_data;
+ unsigned int channels = params_channels(params);
+ unsigned int rate = params_rate(params);
+ int dbl = rate > 48000;
int err;
- struct aaci *aaci = substream->private_data;
aaci_pcm_hw_free(substream);
if (aacirun->pcm_open) {
@@ -503,18 +512,21 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
aacirun->pcm_open = 0;
}
+ /* channels is already limited to 2, 4, or 6 by aaci_rule_channels */
+ if (dbl && channels != 2)
+ return -EINVAL;
+
err = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(params));
if (err >= 0) {
- unsigned int rate = params_rate(params);
- int dbl = rate > 48000;
+ struct aaci *aaci = substream->private_data;
- err = snd_ac97_pcm_open(aacirun->pcm, rate,
- params_channels(params),
+ err = snd_ac97_pcm_open(aacirun->pcm, rate, channels,
aacirun->pcm->r[dbl].slots);
aacirun->pcm_open = err == 0;
aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
+ aacirun->cr |= channels_to_slotmask[channels + dbl * 2];
aacirun->fifosz = aaci->fifosize * 4;
if (aacirun->cr & CR_COMPACT)
@@ -551,34 +563,6 @@ static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream)
/*
* Playback specific ALSA stuff
*/
-static const u32 channels_to_txmask[] = {
- [2] = CR_SL3 | CR_SL4,
- [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8,
- [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,
-};
-
-static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct aaci_runtime *aacirun = substream->runtime->private_data;
- unsigned int channels = params_channels(params);
- int ret;
-
- WARN_ON(channels >= ARRAY_SIZE(channels_to_txmask) ||
- !channels_to_txmask[channels]);
-
- ret = aaci_pcm_hw_params(substream, aacirun, params);
-
- /*
- * Enable FIFO, compact mode, 16 bits per sample.
- * FIXME: double rate slots?
- */
- if (ret >= 0)
- aacirun->cr |= channels_to_txmask[channels];
-
- return ret;
-}
-
static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
{
u32 ie;
@@ -648,27 +632,13 @@ static struct snd_pcm_ops aaci_playback_ops = {
.open = aaci_pcm_open,
.close = aaci_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
- .hw_params = aaci_pcm_playback_hw_params,
+ .hw_params = aaci_pcm_hw_params,
.hw_free = aaci_pcm_hw_free,
.prepare = aaci_pcm_prepare,
.trigger = aaci_pcm_playback_trigger,
.pointer = aaci_pcm_pointer,
};
-static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct aaci_runtime *aacirun = substream->runtime->private_data;
- int ret;
-
- ret = aaci_pcm_hw_params(substream, aacirun, params);
- if (ret >= 0)
- /* Line in record: slot 3 and 4 */
- aacirun->cr |= CR_SL3 | CR_SL4;
-
- return ret;
-}
-
static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun)
{
u32 ie;
@@ -765,7 +735,7 @@ static struct snd_pcm_ops aaci_capture_ops = {
.open = aaci_pcm_open,
.close = aaci_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
- .hw_params = aaci_pcm_capture_hw_params,
+ .hw_params = aaci_pcm_hw_params,
.hw_free = aaci_pcm_hw_free,
.prepare = aaci_pcm_capture_prepare,
.trigger = aaci_pcm_capture_trigger,