aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2009-01-09 17:10:52 -0500
committerTakashi Iwai <tiwai@suse.de>2009-01-11 07:09:05 -0500
commit199f7978730a4bbd88038fd84212b30759579f1a (patch)
treeee3deea40e2db5a38967fce16cb55a3b6103d154
parentc59765042f53a79a7a65585042ff463b69cb248c (diff)
ALSA: wss-lib: move AD1845 frequency setting into wss-lib
This is required to allow the sscape driver to autodetect installed codec. Also, do not create a timer if detected codec has no hardware timer (e.g. AD1848). Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Cc: Rene Herman Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/isa/sscape.c113
-rw-r--r--sound/isa/wss/wss_lib.c40
2 files changed, 48 insertions, 105 deletions
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 48a16d865834..bc449166d18d 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -129,9 +129,6 @@ enum GA_REG {
129#define DMA_8BIT 0x80 129#define DMA_8BIT 0x80
130 130
131 131
132#define AD1845_FREQ_SEL_MSB 0x16
133#define AD1845_FREQ_SEL_LSB 0x17
134
135enum card_type { 132enum card_type {
136 SSCAPE, 133 SSCAPE,
137 SSCAPE_PNP, 134 SSCAPE_PNP,
@@ -955,82 +952,6 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned l
955 952
956 953
957/* 954/*
958 * Override for the CS4231 playback format function.
959 * The AD1845 has much simpler format and rate selection.
960 */
961static void ad1845_playback_format(struct snd_wss *chip,
962 struct snd_pcm_hw_params *params,
963 unsigned char format)
964{
965 unsigned long flags;
966 unsigned rate = params_rate(params);
967
968 /*
969 * The AD1845 can't handle sample frequencies
970 * outside of 4 kHZ to 50 kHZ
971 */
972 if (rate > 50000)
973 rate = 50000;
974 else if (rate < 4000)
975 rate = 4000;
976
977 spin_lock_irqsave(&chip->reg_lock, flags);
978
979 /*
980 * Program the AD1845 correctly for the playback stream.
981 * Note that we do NOT need to toggle the MCE bit because
982 * the PLAYBACK_ENABLE bit of the Interface Configuration
983 * register is set.
984 *
985 * NOTE: We seem to need to write to the MSB before the LSB
986 * to get the correct sample frequency.
987 */
988 snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0));
989 snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
990 snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
991
992 spin_unlock_irqrestore(&chip->reg_lock, flags);
993}
994
995/*
996 * Override for the CS4231 capture format function.
997 * The AD1845 has much simpler format and rate selection.
998 */
999static void ad1845_capture_format(struct snd_wss *chip,
1000 struct snd_pcm_hw_params *params,
1001 unsigned char format)
1002{
1003 unsigned long flags;
1004 unsigned rate = params_rate(params);
1005
1006 /*
1007 * The AD1845 can't handle sample frequencies
1008 * outside of 4 kHZ to 50 kHZ
1009 */
1010 if (rate > 50000)
1011 rate = 50000;
1012 else if (rate < 4000)
1013 rate = 4000;
1014
1015 spin_lock_irqsave(&chip->reg_lock, flags);
1016
1017 /*
1018 * Program the AD1845 correctly for the playback stream.
1019 * Note that we do NOT need to toggle the MCE bit because
1020 * the CAPTURE_ENABLE bit of the Interface Configuration
1021 * register is set.
1022 *
1023 * NOTE: We seem to need to write to the MSB before the LSB
1024 * to get the correct sample frequency.
1025 */
1026 snd_wss_out(chip, CS4231_REC_FORMAT, (format & 0xf0));
1027 snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
1028 snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
1029
1030 spin_unlock_irqrestore(&chip->reg_lock, flags);
1031}
1032
1033/*
1034 * Create an AD1845 PCM subdevice on the SoundScape. The AD1845 955 * Create an AD1845 PCM subdevice on the SoundScape. The AD1845
1035 * is very much like a CS4231, with a few extra bits. We will 956 * is very much like a CS4231, with a few extra bits. We will
1036 * try to support at least some of the extra bits by overriding 957 * try to support at least some of the extra bits by overriding
@@ -1055,11 +976,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
1055 unsigned long flags; 976 unsigned long flags;
1056 struct snd_pcm *pcm; 977 struct snd_pcm *pcm;
1057 978
1058#define AD1845_FREQ_SEL_ENABLE 0x08
1059
1060#define AD1845_PWR_DOWN_CTRL 0x1b
1061#define AD1845_CRYS_CLOCK_SEL 0x1d
1062
1063/* 979/*
1064 * It turns out that the PLAYBACK_ENABLE bit is set 980 * It turns out that the PLAYBACK_ENABLE bit is set
1065 * by the lowlevel driver ... 981 * by the lowlevel driver ...
@@ -1074,7 +990,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
1074 */ 990 */
1075 991
1076 if (sscape->type != SSCAPE_VIVO) { 992 if (sscape->type != SSCAPE_VIVO) {
1077 int val;
1078 /* 993 /*
1079 * The input clock frequency on the SoundScape must 994 * The input clock frequency on the SoundScape must
1080 * be 14.31818 MHz, because we must set this register 995 * be 14.31818 MHz, because we must set this register
@@ -1082,22 +997,10 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
1082 */ 997 */
1083 snd_wss_mce_up(chip); 998 snd_wss_mce_up(chip);
1084 spin_lock_irqsave(&chip->reg_lock, flags); 999 spin_lock_irqsave(&chip->reg_lock, flags);
1085 snd_wss_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); 1000 snd_wss_out(chip, AD1845_CLOCK, 0x20);
1086 spin_unlock_irqrestore(&chip->reg_lock, flags); 1001 spin_unlock_irqrestore(&chip->reg_lock, flags);
1087 snd_wss_mce_down(chip); 1002 snd_wss_mce_down(chip);
1088 1003
1089 /*
1090 * More custom configuration:
1091 * a) select "mode 2" and provide a current drive of 8mA
1092 * b) enable frequency selection (for capture/playback)
1093 */
1094 spin_lock_irqsave(&chip->reg_lock, flags);
1095 snd_wss_out(chip, CS4231_MISC_INFO,
1096 CS4231_MODE2 | 0x10);
1097 val = snd_wss_in(chip, AD1845_PWR_DOWN_CTRL);
1098 snd_wss_out(chip, AD1845_PWR_DOWN_CTRL,
1099 val | AD1845_FREQ_SEL_ENABLE);
1100 spin_unlock_irqrestore(&chip->reg_lock, flags);
1101 } 1004 }
1102 1005
1103 err = snd_wss_pcm(chip, 0, &pcm); 1006 err = snd_wss_pcm(chip, 0, &pcm);
@@ -1113,11 +1016,13 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
1113 "for AD1845 chip\n"); 1016 "for AD1845 chip\n");
1114 goto _error; 1017 goto _error;
1115 } 1018 }
1116 err = snd_wss_timer(chip, 0, NULL); 1019 if (chip->hardware != WSS_HW_AD1848) {
1117 if (err < 0) { 1020 err = snd_wss_timer(chip, 0, NULL);
1118 snd_printk(KERN_ERR "sscape: No timer device " 1021 if (err < 0) {
1119 "for AD1845 chip\n"); 1022 snd_printk(KERN_ERR "sscape: No timer device "
1120 goto _error; 1023 "for AD1845 chip\n");
1024 goto _error;
1025 }
1121 } 1026 }
1122 1027
1123 if (sscape->type != SSCAPE_VIVO) { 1028 if (sscape->type != SSCAPE_VIVO) {
@@ -1128,8 +1033,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
1128 "MIDI mixer control\n"); 1033 "MIDI mixer control\n");
1129 goto _error; 1034 goto _error;
1130 } 1035 }
1131 chip->set_playback_format = ad1845_playback_format;
1132 chip->set_capture_format = ad1845_capture_format;
1133 } 1036 }
1134 1037
1135 strcpy(card->driver, "SoundScape"); 1038 strcpy(card->driver, "SoundScape");
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 3d6c5f2838af..13299aebd077 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -646,6 +646,24 @@ static void snd_wss_playback_format(struct snd_wss *chip,
646 full_calib = 0; 646 full_calib = 0;
647 } 647 }
648 spin_unlock_irqrestore(&chip->reg_lock, flags); 648 spin_unlock_irqrestore(&chip->reg_lock, flags);
649 } else if (chip->hardware == WSS_HW_AD1845) {
650 unsigned rate = params_rate(params);
651
652 /*
653 * Program the AD1845 correctly for the playback stream.
654 * Note that we do NOT need to toggle the MCE bit because
655 * the PLAYBACK_ENABLE bit of the Interface Configuration
656 * register is set.
657 *
658 * NOTE: We seem to need to write to the MSB before the LSB
659 * to get the correct sample frequency.
660 */
661 spin_lock_irqsave(&chip->reg_lock, flags);
662 snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (pdfr & 0xf0));
663 snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff);
664 snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff);
665 full_calib = 0;
666 spin_unlock_irqrestore(&chip->reg_lock, flags);
649 } 667 }
650 if (full_calib) { 668 if (full_calib) {
651 snd_wss_mce_up(chip); 669 snd_wss_mce_up(chip);
@@ -690,6 +708,24 @@ static void snd_wss_capture_format(struct snd_wss *chip,
690 full_calib = 0; 708 full_calib = 0;
691 } 709 }
692 spin_unlock_irqrestore(&chip->reg_lock, flags); 710 spin_unlock_irqrestore(&chip->reg_lock, flags);
711 } else if (chip->hardware == WSS_HW_AD1845) {
712 unsigned rate = params_rate(params);
713
714 /*
715 * Program the AD1845 correctly for the capture stream.
716 * Note that we do NOT need to toggle the MCE bit because
717 * the PLAYBACK_ENABLE bit of the Interface Configuration
718 * register is set.
719 *
720 * NOTE: We seem to need to write to the MSB before the LSB
721 * to get the correct sample frequency.
722 */
723 spin_lock_irqsave(&chip->reg_lock, flags);
724 snd_wss_out(chip, CS4231_REC_FORMAT, (cdfr & 0xf0));
725 snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff);
726 snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff);
727 full_calib = 0;
728 spin_unlock_irqrestore(&chip->reg_lock, flags);
693 } 729 }
694 if (full_calib) { 730 if (full_calib) {
695 snd_wss_mce_up(chip); 731 snd_wss_mce_up(chip);
@@ -1314,6 +1350,10 @@ static int snd_wss_probe(struct snd_wss *chip)
1314 chip->image[CS4231_ALT_FEATURE_2] = 1350 chip->image[CS4231_ALT_FEATURE_2] =
1315 chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; 1351 chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01;
1316 } 1352 }
1353 /* enable fine grained frequency selection */
1354 if (chip->hardware == WSS_HW_AD1845)
1355 chip->image[AD1845_PWR_DOWN] = 8;
1356
1317 ptr = (unsigned char *) &chip->image; 1357 ptr = (unsigned char *) &chip->image;
1318 regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32; 1358 regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32;
1319 snd_wss_mce_down(chip); 1359 snd_wss_mce_down(chip);