diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-26 11:59:39 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-26 15:24:10 -0500 |
commit | 58e8a4741b519910cdabdd55c23f258e40cf6a3a (patch) | |
tree | 2781f2a841319e2320c0108046309687081277c3 /sound/arm | |
parent | e831d80b453a3586f1e1664a705c153a4ced39b8 (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>
Diffstat (limited to 'sound/arm')
-rw-r--r-- | sound/arm/aaci.c | 70 |
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) | |||
490 | return 0; | 490 | return 0; |
491 | } | 491 | } |
492 | 492 | ||
493 | /* Channel to slot mask */ | ||
494 | static const u32 channels_to_slotmask[] = { | ||
495 | [2] = CR_SL3 | CR_SL4, | ||
496 | [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8, | ||
497 | [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9, | ||
498 | }; | ||
499 | |||
493 | static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, | 500 | static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, |
494 | struct aaci_runtime *aacirun, | ||
495 | struct snd_pcm_hw_params *params) | 501 | struct snd_pcm_hw_params *params) |
496 | { | 502 | { |
503 | struct aaci_runtime *aacirun = substream->runtime->private_data; | ||
504 | unsigned int channels = params_channels(params); | ||
505 | unsigned int rate = params_rate(params); | ||
506 | int dbl = rate > 48000; | ||
497 | int err; | 507 | int err; |
498 | struct aaci *aaci = substream->private_data; | ||
499 | 508 | ||
500 | aaci_pcm_hw_free(substream); | 509 | aaci_pcm_hw_free(substream); |
501 | if (aacirun->pcm_open) { | 510 | if (aacirun->pcm_open) { |
@@ -503,18 +512,21 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, | |||
503 | aacirun->pcm_open = 0; | 512 | aacirun->pcm_open = 0; |
504 | } | 513 | } |
505 | 514 | ||
515 | /* channels is already limited to 2, 4, or 6 by aaci_rule_channels */ | ||
516 | if (dbl && channels != 2) | ||
517 | return -EINVAL; | ||
518 | |||
506 | err = snd_pcm_lib_malloc_pages(substream, | 519 | err = snd_pcm_lib_malloc_pages(substream, |
507 | params_buffer_bytes(params)); | 520 | params_buffer_bytes(params)); |
508 | if (err >= 0) { | 521 | if (err >= 0) { |
509 | unsigned int rate = params_rate(params); | 522 | struct aaci *aaci = substream->private_data; |
510 | int dbl = rate > 48000; | ||
511 | 523 | ||
512 | err = snd_ac97_pcm_open(aacirun->pcm, rate, | 524 | err = snd_ac97_pcm_open(aacirun->pcm, rate, channels, |
513 | params_channels(params), | ||
514 | aacirun->pcm->r[dbl].slots); | 525 | aacirun->pcm->r[dbl].slots); |
515 | 526 | ||
516 | aacirun->pcm_open = err == 0; | 527 | aacirun->pcm_open = err == 0; |
517 | aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; | 528 | aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; |
529 | aacirun->cr |= channels_to_slotmask[channels + dbl * 2]; | ||
518 | aacirun->fifosz = aaci->fifosize * 4; | 530 | aacirun->fifosz = aaci->fifosize * 4; |
519 | 531 | ||
520 | if (aacirun->cr & CR_COMPACT) | 532 | if (aacirun->cr & CR_COMPACT) |
@@ -551,34 +563,6 @@ static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream) | |||
551 | /* | 563 | /* |
552 | * Playback specific ALSA stuff | 564 | * Playback specific ALSA stuff |
553 | */ | 565 | */ |
554 | static const u32 channels_to_txmask[] = { | ||
555 | [2] = CR_SL3 | CR_SL4, | ||
556 | [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8, | ||
557 | [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9, | ||
558 | }; | ||
559 | |||
560 | static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream, | ||
561 | struct snd_pcm_hw_params *params) | ||
562 | { | ||
563 | struct aaci_runtime *aacirun = substream->runtime->private_data; | ||
564 | unsigned int channels = params_channels(params); | ||
565 | int ret; | ||
566 | |||
567 | WARN_ON(channels >= ARRAY_SIZE(channels_to_txmask) || | ||
568 | !channels_to_txmask[channels]); | ||
569 | |||
570 | ret = aaci_pcm_hw_params(substream, aacirun, params); | ||
571 | |||
572 | /* | ||
573 | * Enable FIFO, compact mode, 16 bits per sample. | ||
574 | * FIXME: double rate slots? | ||
575 | */ | ||
576 | if (ret >= 0) | ||
577 | aacirun->cr |= channels_to_txmask[channels]; | ||
578 | |||
579 | return ret; | ||
580 | } | ||
581 | |||
582 | static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) | 566 | static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) |
583 | { | 567 | { |
584 | u32 ie; | 568 | u32 ie; |
@@ -648,27 +632,13 @@ static struct snd_pcm_ops aaci_playback_ops = { | |||
648 | .open = aaci_pcm_open, | 632 | .open = aaci_pcm_open, |
649 | .close = aaci_pcm_close, | 633 | .close = aaci_pcm_close, |
650 | .ioctl = snd_pcm_lib_ioctl, | 634 | .ioctl = snd_pcm_lib_ioctl, |
651 | .hw_params = aaci_pcm_playback_hw_params, | 635 | .hw_params = aaci_pcm_hw_params, |
652 | .hw_free = aaci_pcm_hw_free, | 636 | .hw_free = aaci_pcm_hw_free, |
653 | .prepare = aaci_pcm_prepare, | 637 | .prepare = aaci_pcm_prepare, |
654 | .trigger = aaci_pcm_playback_trigger, | 638 | .trigger = aaci_pcm_playback_trigger, |
655 | .pointer = aaci_pcm_pointer, | 639 | .pointer = aaci_pcm_pointer, |
656 | }; | 640 | }; |
657 | 641 | ||
658 | static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream, | ||
659 | struct snd_pcm_hw_params *params) | ||
660 | { | ||
661 | struct aaci_runtime *aacirun = substream->runtime->private_data; | ||
662 | int ret; | ||
663 | |||
664 | ret = aaci_pcm_hw_params(substream, aacirun, params); | ||
665 | if (ret >= 0) | ||
666 | /* Line in record: slot 3 and 4 */ | ||
667 | aacirun->cr |= CR_SL3 | CR_SL4; | ||
668 | |||
669 | return ret; | ||
670 | } | ||
671 | |||
672 | static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun) | 642 | static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun) |
673 | { | 643 | { |
674 | u32 ie; | 644 | u32 ie; |
@@ -765,7 +735,7 @@ static struct snd_pcm_ops aaci_capture_ops = { | |||
765 | .open = aaci_pcm_open, | 735 | .open = aaci_pcm_open, |
766 | .close = aaci_pcm_close, | 736 | .close = aaci_pcm_close, |
767 | .ioctl = snd_pcm_lib_ioctl, | 737 | .ioctl = snd_pcm_lib_ioctl, |
768 | .hw_params = aaci_pcm_capture_hw_params, | 738 | .hw_params = aaci_pcm_hw_params, |
769 | .hw_free = aaci_pcm_hw_free, | 739 | .hw_free = aaci_pcm_hw_free, |
770 | .prepare = aaci_pcm_capture_prepare, | 740 | .prepare = aaci_pcm_capture_prepare, |
771 | .trigger = aaci_pcm_capture_trigger, | 741 | .trigger = aaci_pcm_capture_trigger, |