diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-03-23 19:36:21 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-03-23 19:36:21 -0400 |
commit | d0807323345f1cd8ab578b09aab04d10862e9414 (patch) | |
tree | 0a1cca9055d4534590779f014199116c7c802d57 /sound/isa/wss | |
parent | d7b6df5d1af11544401ca051aaf68b6e7f110c0e (diff) | |
parent | 453e37b37521b613f0927fcf53ccd93ad3a8b3ae (diff) |
Merge branch 'topic/sscape-fix' into for-linus
Diffstat (limited to 'sound/isa/wss')
-rw-r--r-- | sound/isa/wss/wss_lib.c | 81 |
1 files changed, 53 insertions, 28 deletions
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index ac27832b2c6f..5d2ba1b749ab 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c | |||
@@ -181,25 +181,6 @@ static void snd_wss_wait(struct snd_wss *chip) | |||
181 | udelay(100); | 181 | udelay(100); |
182 | } | 182 | } |
183 | 183 | ||
184 | static void snd_wss_outm(struct snd_wss *chip, unsigned char reg, | ||
185 | unsigned char mask, unsigned char value) | ||
186 | { | ||
187 | unsigned char tmp = (chip->image[reg] & mask) | value; | ||
188 | |||
189 | snd_wss_wait(chip); | ||
190 | #ifdef CONFIG_SND_DEBUG | ||
191 | if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | ||
192 | snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | ||
193 | #endif | ||
194 | chip->image[reg] = tmp; | ||
195 | if (!chip->calibrate_mute) { | ||
196 | wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); | ||
197 | wmb(); | ||
198 | wss_outb(chip, CS4231P(REG), tmp); | ||
199 | mb(); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | static void snd_wss_dout(struct snd_wss *chip, unsigned char reg, | 184 | static void snd_wss_dout(struct snd_wss *chip, unsigned char reg, |
204 | unsigned char value) | 185 | unsigned char value) |
205 | { | 186 | { |
@@ -597,7 +578,15 @@ static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute) | |||
597 | chip->image[CS4231_RIGHT_INPUT]); | 578 | chip->image[CS4231_RIGHT_INPUT]); |
598 | snd_wss_dout(chip, CS4231_LOOPBACK, | 579 | snd_wss_dout(chip, CS4231_LOOPBACK, |
599 | chip->image[CS4231_LOOPBACK]); | 580 | chip->image[CS4231_LOOPBACK]); |
581 | } else { | ||
582 | snd_wss_dout(chip, CS4231_LEFT_INPUT, | ||
583 | 0); | ||
584 | snd_wss_dout(chip, CS4231_RIGHT_INPUT, | ||
585 | 0); | ||
586 | snd_wss_dout(chip, CS4231_LOOPBACK, | ||
587 | 0xfd); | ||
600 | } | 588 | } |
589 | |||
601 | snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT, | 590 | snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT, |
602 | mute | chip->image[CS4231_AUX1_LEFT_INPUT]); | 591 | mute | chip->image[CS4231_AUX1_LEFT_INPUT]); |
603 | snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT, | 592 | snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT, |
@@ -640,7 +629,6 @@ static void snd_wss_playback_format(struct snd_wss *chip, | |||
640 | int full_calib = 1; | 629 | int full_calib = 1; |
641 | 630 | ||
642 | mutex_lock(&chip->mce_mutex); | 631 | mutex_lock(&chip->mce_mutex); |
643 | snd_wss_calibrate_mute(chip, 1); | ||
644 | if (chip->hardware == WSS_HW_CS4231A || | 632 | if (chip->hardware == WSS_HW_CS4231A || |
645 | (chip->hardware & WSS_HW_CS4232_MASK)) { | 633 | (chip->hardware & WSS_HW_CS4232_MASK)) { |
646 | spin_lock_irqsave(&chip->reg_lock, flags); | 634 | spin_lock_irqsave(&chip->reg_lock, flags); |
@@ -656,6 +644,24 @@ static void snd_wss_playback_format(struct snd_wss *chip, | |||
656 | full_calib = 0; | 644 | full_calib = 0; |
657 | } | 645 | } |
658 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 646 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
647 | } else if (chip->hardware == WSS_HW_AD1845) { | ||
648 | unsigned rate = params_rate(params); | ||
649 | |||
650 | /* | ||
651 | * Program the AD1845 correctly for the playback stream. | ||
652 | * Note that we do NOT need to toggle the MCE bit because | ||
653 | * the PLAYBACK_ENABLE bit of the Interface Configuration | ||
654 | * register is set. | ||
655 | * | ||
656 | * NOTE: We seem to need to write to the MSB before the LSB | ||
657 | * to get the correct sample frequency. | ||
658 | */ | ||
659 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
660 | snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (pdfr & 0xf0)); | ||
661 | snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); | ||
662 | snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); | ||
663 | full_calib = 0; | ||
664 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
659 | } | 665 | } |
660 | if (full_calib) { | 666 | if (full_calib) { |
661 | snd_wss_mce_up(chip); | 667 | snd_wss_mce_up(chip); |
@@ -673,7 +679,6 @@ static void snd_wss_playback_format(struct snd_wss *chip, | |||
673 | udelay(100); /* this seems to help */ | 679 | udelay(100); /* this seems to help */ |
674 | snd_wss_mce_down(chip); | 680 | snd_wss_mce_down(chip); |
675 | } | 681 | } |
676 | snd_wss_calibrate_mute(chip, 0); | ||
677 | mutex_unlock(&chip->mce_mutex); | 682 | mutex_unlock(&chip->mce_mutex); |
678 | } | 683 | } |
679 | 684 | ||
@@ -685,7 +690,6 @@ static void snd_wss_capture_format(struct snd_wss *chip, | |||
685 | int full_calib = 1; | 690 | int full_calib = 1; |
686 | 691 | ||
687 | mutex_lock(&chip->mce_mutex); | 692 | mutex_lock(&chip->mce_mutex); |
688 | snd_wss_calibrate_mute(chip, 1); | ||
689 | if (chip->hardware == WSS_HW_CS4231A || | 693 | if (chip->hardware == WSS_HW_CS4231A || |
690 | (chip->hardware & WSS_HW_CS4232_MASK)) { | 694 | (chip->hardware & WSS_HW_CS4232_MASK)) { |
691 | spin_lock_irqsave(&chip->reg_lock, flags); | 695 | spin_lock_irqsave(&chip->reg_lock, flags); |
@@ -700,6 +704,24 @@ static void snd_wss_capture_format(struct snd_wss *chip, | |||
700 | full_calib = 0; | 704 | full_calib = 0; |
701 | } | 705 | } |
702 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 706 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
707 | } else if (chip->hardware == WSS_HW_AD1845) { | ||
708 | unsigned rate = params_rate(params); | ||
709 | |||
710 | /* | ||
711 | * Program the AD1845 correctly for the capture stream. | ||
712 | * Note that we do NOT need to toggle the MCE bit because | ||
713 | * the PLAYBACK_ENABLE bit of the Interface Configuration | ||
714 | * register is set. | ||
715 | * | ||
716 | * NOTE: We seem to need to write to the MSB before the LSB | ||
717 | * to get the correct sample frequency. | ||
718 | */ | ||
719 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
720 | snd_wss_out(chip, CS4231_REC_FORMAT, (cdfr & 0xf0)); | ||
721 | snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); | ||
722 | snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); | ||
723 | full_calib = 0; | ||
724 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
703 | } | 725 | } |
704 | if (full_calib) { | 726 | if (full_calib) { |
705 | snd_wss_mce_up(chip); | 727 | snd_wss_mce_up(chip); |
@@ -724,7 +746,6 @@ static void snd_wss_capture_format(struct snd_wss *chip, | |||
724 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 746 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
725 | snd_wss_mce_down(chip); | 747 | snd_wss_mce_down(chip); |
726 | } | 748 | } |
727 | snd_wss_calibrate_mute(chip, 0); | ||
728 | mutex_unlock(&chip->mce_mutex); | 749 | mutex_unlock(&chip->mce_mutex); |
729 | } | 750 | } |
730 | 751 | ||
@@ -781,6 +802,7 @@ static void snd_wss_init(struct snd_wss *chip) | |||
781 | { | 802 | { |
782 | unsigned long flags; | 803 | unsigned long flags; |
783 | 804 | ||
805 | snd_wss_calibrate_mute(chip, 1); | ||
784 | snd_wss_mce_down(chip); | 806 | snd_wss_mce_down(chip); |
785 | 807 | ||
786 | #ifdef SNDRV_DEBUG_MCE | 808 | #ifdef SNDRV_DEBUG_MCE |
@@ -804,6 +826,8 @@ static void snd_wss_init(struct snd_wss *chip) | |||
804 | 826 | ||
805 | snd_wss_mce_up(chip); | 827 | snd_wss_mce_up(chip); |
806 | spin_lock_irqsave(&chip->reg_lock, flags); | 828 | spin_lock_irqsave(&chip->reg_lock, flags); |
829 | chip->image[CS4231_IFACE_CTRL] &= ~CS4231_AUTOCALIB; | ||
830 | snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); | ||
807 | snd_wss_out(chip, | 831 | snd_wss_out(chip, |
808 | CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); | 832 | CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); |
809 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 833 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
@@ -837,6 +861,7 @@ static void snd_wss_init(struct snd_wss *chip) | |||
837 | chip->image[CS4231_REC_FORMAT]); | 861 | chip->image[CS4231_REC_FORMAT]); |
838 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 862 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
839 | snd_wss_mce_down(chip); | 863 | snd_wss_mce_down(chip); |
864 | snd_wss_calibrate_mute(chip, 0); | ||
840 | 865 | ||
841 | #ifdef SNDRV_DEBUG_MCE | 866 | #ifdef SNDRV_DEBUG_MCE |
842 | snd_printk(KERN_DEBUG "init: (5)\n"); | 867 | snd_printk(KERN_DEBUG "init: (5)\n"); |
@@ -895,8 +920,6 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) | |||
895 | mutex_unlock(&chip->open_mutex); | 920 | mutex_unlock(&chip->open_mutex); |
896 | return; | 921 | return; |
897 | } | 922 | } |
898 | snd_wss_calibrate_mute(chip, 1); | ||
899 | |||
900 | /* disable IRQ */ | 923 | /* disable IRQ */ |
901 | spin_lock_irqsave(&chip->reg_lock, flags); | 924 | spin_lock_irqsave(&chip->reg_lock, flags); |
902 | if (!(chip->hardware & WSS_HW_AD1848_MASK)) | 925 | if (!(chip->hardware & WSS_HW_AD1848_MASK)) |
@@ -929,8 +952,6 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) | |||
929 | wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ | 952 | wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ |
930 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 953 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
931 | 954 | ||
932 | snd_wss_calibrate_mute(chip, 0); | ||
933 | |||
934 | chip->mode = 0; | 955 | chip->mode = 0; |
935 | mutex_unlock(&chip->open_mutex); | 956 | mutex_unlock(&chip->open_mutex); |
936 | } | 957 | } |
@@ -1123,7 +1144,7 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id) | |||
1123 | if (chip->hardware & WSS_HW_AD1848_MASK) | 1144 | if (chip->hardware & WSS_HW_AD1848_MASK) |
1124 | wss_outb(chip, CS4231P(STATUS), 0); | 1145 | wss_outb(chip, CS4231P(STATUS), 0); |
1125 | else | 1146 | else |
1126 | snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0); | 1147 | snd_wss_out(chip, CS4231_IRQ_STATUS, status); |
1127 | spin_unlock(&chip->reg_lock); | 1148 | spin_unlock(&chip->reg_lock); |
1128 | return IRQ_HANDLED; | 1149 | return IRQ_HANDLED; |
1129 | } | 1150 | } |
@@ -1325,6 +1346,10 @@ static int snd_wss_probe(struct snd_wss *chip) | |||
1325 | chip->image[CS4231_ALT_FEATURE_2] = | 1346 | chip->image[CS4231_ALT_FEATURE_2] = |
1326 | chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; | 1347 | chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; |
1327 | } | 1348 | } |
1349 | /* enable fine grained frequency selection */ | ||
1350 | if (chip->hardware == WSS_HW_AD1845) | ||
1351 | chip->image[AD1845_PWR_DOWN] = 8; | ||
1352 | |||
1328 | ptr = (unsigned char *) &chip->image; | 1353 | ptr = (unsigned char *) &chip->image; |
1329 | regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32; | 1354 | regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32; |
1330 | snd_wss_mce_down(chip); | 1355 | snd_wss_mce_down(chip); |