aboutsummaryrefslogtreecommitdiffstats
path: root/sound/arm
diff options
context:
space:
mode:
Diffstat (limited to 'sound/arm')
-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)
490 return 0; 490 return 0;
491} 491}
492 492
493/* Channel to slot mask */
494static 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
493static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, 500static 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 */
554static 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
560static 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
582static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) 566static 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
658static 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
672static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun) 642static 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,