aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa/sscape.c
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2009-09-27 17:08:40 -0400
committerTakashi Iwai <tiwai@suse.de>2009-09-28 05:31:36 -0400
commitf0968e3f7a8ea30728d2580d3043a30ea9994ec6 (patch)
tree4e9adca4a7b7b33e8497eeb5c21935f0538f7624 /sound/isa/sscape.c
parent4f272341c7a42a71586523f196b242bccde3be8c (diff)
ALSA: sscape: add supoort for SPEA Media FX/Reveal SC-600
Move code from the OSS sscape driver in order to support old Soundscape OEM models. Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/isa/sscape.c')
-rw-r--r--sound/isa/sscape.c116
1 files changed, 82 insertions, 34 deletions
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 66187122377..b11c35f6aef 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -127,7 +127,8 @@ enum GA_REG {
127 127
128 128
129enum card_type { 129enum card_type {
130 SSCAPE, 130 MEDIA_FX, /* Sequoia S-1000 */
131 SSCAPE, /* Sequoia S-2000 */
131 SSCAPE_PNP, 132 SSCAPE_PNP,
132 SSCAPE_VIVO, 133 SSCAPE_VIVO,
133}; 134};
@@ -784,20 +785,25 @@ static struct snd_kcontrol_new midi_mixer_ctl = {
784 * These IRQs are encoded as bit patterns so that they can be 785 * These IRQs are encoded as bit patterns so that they can be
785 * written to the control registers. 786 * written to the control registers.
786 */ 787 */
787static unsigned __devinit get_irq_config(int irq) 788static unsigned __devinit get_irq_config(int sscape_type, int irq)
788{ 789{
789 static const int valid_irq[] = { 9, 5, 7, 10 }; 790 static const int valid_irq[] = { 9, 5, 7, 10 };
791 static const int old_irq[] = { 9, 7, 5, 15 };
790 unsigned cfg; 792 unsigned cfg;
791 793
792 for (cfg = 0; cfg < ARRAY_SIZE(valid_irq); ++cfg) { 794 if (sscape_type == MEDIA_FX) {
793 if (irq == valid_irq[cfg]) 795 for (cfg = 0; cfg < ARRAY_SIZE(old_irq); ++cfg)
794 return cfg; 796 if (irq == old_irq[cfg])
795 } /* for */ 797 return cfg;
798 } else {
799 for (cfg = 0; cfg < ARRAY_SIZE(valid_irq); ++cfg)
800 if (irq == valid_irq[cfg])
801 return cfg;
802 }
796 803
797 return INVALID_IRQ; 804 return INVALID_IRQ;
798} 805}
799 806
800
801/* 807/*
802 * Perform certain arcane port-checks to see whether there 808 * Perform certain arcane port-checks to see whether there
803 * is a SoundScape board lurking behind the given ports. 809 * is a SoundScape board lurking behind the given ports.
@@ -842,11 +848,39 @@ static int __devinit detect_sscape(struct soundscape *s, long wss_io)
842 if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e) 848 if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e)
843 goto _done; 849 goto _done;
844 850
845 d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f; 851 if (s->ic_type == IC_OPUS)
846 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); 852 activate_ad1845_unsafe(s->io_base);
847 853
848 if (s->type == SSCAPE_VIVO) 854 if (s->type == SSCAPE_VIVO)
849 wss_io += 4; 855 wss_io += 4;
856
857 d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f;
858 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
859
860 /* wait for WSS codec */
861 for (d = 0; d < 500; d++) {
862 if ((inb(wss_io) & 0x80) == 0)
863 break;
864 spin_unlock_irqrestore(&s->lock, flags);
865 msleep(1);
866 spin_lock_irqsave(&s->lock, flags);
867 }
868 snd_printd(KERN_INFO "init delay = %d ms\n", d);
869
870 if ((inb(wss_io) & 0x80) != 0)
871 goto _done;
872
873 if (inb(wss_io + 2) == 0xff)
874 goto _done;
875
876 d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f;
877 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d);
878
879 if ((inb(wss_io) & 0x80) != 0)
880 s->type = MEDIA_FX;
881
882 d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f;
883 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
850 /* wait for WSS codec */ 884 /* wait for WSS codec */
851 for (d = 0; d < 500; d++) { 885 for (d = 0; d < 500; d++) {
852 if ((inb(wss_io) & 0x80) == 0) 886 if ((inb(wss_io) & 0x80) == 0)
@@ -954,9 +988,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
954 if (sscape->type == SSCAPE_VIVO) 988 if (sscape->type == SSCAPE_VIVO)
955 port += 4; 989 port += 4;
956 990
957 if (dma1 == dma2)
958 dma2 = -1;
959
960 err = snd_wss_create(card, port, -1, irq, dma1, dma2, 991 err = snd_wss_create(card, port, -1, irq, dma1, dma2,
961 WSS_HW_DETECT, WSS_HWSHARE_DMA1, &chip); 992 WSS_HW_DETECT, WSS_HWSHARE_DMA1, &chip);
962 if (!err) { 993 if (!err) {
@@ -1051,21 +1082,7 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
1051 struct resource *wss_res; 1082 struct resource *wss_res;
1052 unsigned long flags; 1083 unsigned long flags;
1053 int err; 1084 int err;
1054 1085 const char *name;
1055 /*
1056 * Check that the user didn't pass us garbage data ...
1057 */
1058 irq_cfg = get_irq_config(irq[dev]);
1059 if (irq_cfg == INVALID_IRQ) {
1060 snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
1061 return -ENXIO;
1062 }
1063
1064 mpu_irq_cfg = get_irq_config(mpu_irq[dev]);
1065 if (mpu_irq_cfg == INVALID_IRQ) {
1066 printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
1067 return -ENXIO;
1068 }
1069 1086
1070 /* 1087 /*
1071 * Grab IO ports that we will need to probe so that we 1088 * Grab IO ports that we will need to probe so that we
@@ -1109,8 +1126,41 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
1109 goto _release_dma; 1126 goto _release_dma;
1110 } 1127 }
1111 1128
1112 printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n", 1129 switch (sscape->type) {
1113 sscape->io_base, irq[dev], dma[dev]); 1130 case MEDIA_FX:
1131 name = "MediaFX/SoundFX";
1132 break;
1133 case SSCAPE:
1134 name = "Soundscape";
1135 break;
1136 case SSCAPE_PNP:
1137 name = "Soundscape PnP";
1138 break;
1139 case SSCAPE_VIVO:
1140 name = "Soundscape VIVO";
1141 break;
1142 default:
1143 name = "unknown Soundscape";
1144 break;
1145 }
1146
1147 printk(KERN_INFO "sscape: %s card detected at 0x%x, using IRQ %d, DMA %d\n",
1148 name, sscape->io_base, irq[dev], dma[dev]);
1149
1150 /*
1151 * Check that the user didn't pass us garbage data ...
1152 */
1153 irq_cfg = get_irq_config(sscape->type, irq[dev]);
1154 if (irq_cfg == INVALID_IRQ) {
1155 snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
1156 return -ENXIO;
1157 }
1158
1159 mpu_irq_cfg = get_irq_config(sscape->type, mpu_irq[dev]);
1160 if (mpu_irq_cfg == INVALID_IRQ) {
1161 printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
1162 return -ENXIO;
1163 }
1114 1164
1115 if (sscape->type != SSCAPE_VIVO) { 1165 if (sscape->type != SSCAPE_VIVO) {
1116 /* 1166 /*
@@ -1141,8 +1191,6 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
1141 */ 1191 */
1142 spin_lock_irqsave(&sscape->lock, flags); 1192 spin_lock_irqsave(&sscape->lock, flags);
1143 1193
1144 activate_ad1845_unsafe(sscape->io_base);
1145
1146 sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x00); /* disable */ 1194 sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x00); /* disable */
1147 sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e); 1195 sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e);
1148 sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00); 1196 sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00);
@@ -1151,12 +1199,12 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
1151 * Enable and configure the DMA channels ... 1199 * Enable and configure the DMA channels ...
1152 */ 1200 */
1153 sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50); 1201 sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50);
1154 dma_cfg = (sscape->ic_type == IC_ODIE ? 0x70 : 0x40); 1202 dma_cfg = (sscape->ic_type == IC_OPUS ? 0x40 : 0x70);
1155 sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg); 1203 sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg);
1156 sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20); 1204 sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20);
1157 1205
1158 sscape_write_unsafe(sscape->io_base, 1206 mpu_irq_cfg |= mpu_irq_cfg << 2;
1159 GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg); 1207 sscape_write_unsafe(sscape->io_base, GA_INTCFG_REG, 0xf0 | mpu_irq_cfg);
1160 sscape_write_unsafe(sscape->io_base, 1208 sscape_write_unsafe(sscape->io_base,
1161 GA_CDCFG_REG, 0x09 | DMA_8BIT 1209 GA_CDCFG_REG, 0x09 | DMA_8BIT
1162 | (dma[dev] << 4) | (irq_cfg << 1)); 1210 | (dma[dev] << 4) | (irq_cfg << 1));