X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Foss%2Fsscape.c;h=30c36d1f35d7a9641428ebb8b91bc5d02586cf28;hb=refs%2Fheads%2Fvserver;hp=733bfc1872025b7baebb0601d9ec036302192be2;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/sound/oss/sscape.c b/sound/oss/sscape.c index 733bfc187..30c36d1f3 100644 --- a/sound/oss/sscape.c +++ b/sound/oss/sscape.c @@ -1,5 +1,5 @@ /* - * sound/sscape.c + * sound/oss/sscape.c * * Low level driver for Ensoniq SoundScape * @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "coproc.h" @@ -600,10 +601,10 @@ static coproc_operations sscape_coproc_operations = &adev_info }; -static int sscape_detected; +static struct resource *sscape_ports; static int sscape_is_pnp; -void __init attach_sscape(struct address_info *hw_config) +static void __init attach_sscape(struct address_info *hw_config) { #ifndef SSCAPE_REGS /* @@ -638,10 +639,6 @@ void __init attach_sscape(struct address_info *hw_config) int i, irq_bits = 0xff; - if (sscape_detected != hw_config->io_base) - return; - - request_region(devc->base + 2, 6, "SoundScape"); if (old_hardware) { valid_interrupts = valid_interrupts_old; @@ -650,7 +647,7 @@ void __init attach_sscape(struct address_info *hw_config) else conf_printf("Ensoniq SoundScape", hw_config); - for (i = 0; i < sizeof(valid_interrupts); i++) + for (i = 0; i < 4; i++) { if (hw_config->irq == valid_interrupts[i]) { @@ -661,45 +658,32 @@ void __init attach_sscape(struct address_info *hw_config) if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff)) { printk(KERN_ERR "Invalid IRQ%d\n", hw_config->irq); + release_region(devc->base, 2); + release_region(devc->base + 2, 6); + if (sscape_is_pnp) + release_region(devc->codec, 2); return; } if (!sscape_is_pnp) { spin_lock_irqsave(&devc->lock,flags); - for (i = 1; i < 10; i++) - { - switch (i) - { - case 1: /* Host interrupt enable */ - sscape_write(devc, i, 0xf0); /* All interrupts enabled */ - break; - - case 2: /* DMA A status/trigger register */ - case 3: /* DMA B status/trigger register */ - sscape_write(devc, i, 0x20); /* DMA channel disabled */ - break; - - case 4: /* Host interrupt config reg */ - sscape_write(devc, i, 0xf0 | (irq_bits << 2) | irq_bits); - break; - - case 5: /* Don't destroy CD-ROM DMA config bits (0xc0) */ - sscape_write(devc, i, (regs[i] & 0x3f) | (sscape_read(devc, i) & 0xc0)); - break; - - case 6: /* CD-ROM config (WSS codec actually) */ - sscape_write(devc, i, regs[i]); - break; - - case 9: /* Master control reg. Don't modify CR-ROM bits. Disable SB emul */ - sscape_write(devc, i, (sscape_read(devc, i) & 0xf0) | 0x08); - break; - - default: - sscape_write(devc, i, regs[i]); - } - } + /* Host interrupt enable */ + sscape_write(devc, 1, 0xf0); /* All interrupts enabled */ + /* DMA A status/trigger register */ + sscape_write(devc, 2, 0x20); /* DMA channel disabled */ + /* DMA B status/trigger register */ + sscape_write(devc, 3, 0x20); /* DMA channel disabled */ + /* Host interrupt config reg */ + sscape_write(devc, 4, 0xf0 | (irq_bits << 2) | irq_bits); + /* Don't destroy CD-ROM DMA config bits (0xc0) */ + sscape_write(devc, 5, (regs[5] & 0x3f) | (sscape_read(devc, 5) & 0xc0)); + /* CD-ROM config (WSS codec actually) */ + sscape_write(devc, 6, regs[6]); + sscape_write(devc, 7, regs[7]); + sscape_write(devc, 8, regs[8]); + /* Master control reg. Don't modify CR-ROM bits. Disable SB emul */ + sscape_write(devc, 9, (sscape_read(devc, 9) & 0xf0) | 0x08); spin_unlock_irqrestore(&devc->lock,flags); } #ifdef SSCAPE_DEBUG2 @@ -715,7 +699,7 @@ void __init attach_sscape(struct address_info *hw_config) } #endif - if (probe_mpu401(hw_config)) + if (probe_mpu401(hw_config, sscape_ports)) hw_config->always_detect = 1; hw_config->name = "SoundScape"; @@ -739,9 +723,6 @@ static int detect_ga(sscape_info * devc) DDB(printk("Entered Soundscape detect_ga(%x)\n", devc->base)); - if (check_region(devc->base, 8)) - return 0; - /* * First check that the address register of "ODIE" is * there and that it has exactly 4 writable bits. @@ -1011,7 +992,6 @@ static void __init sscape_pnp_init_hw(sscape_info* devc) unsigned i; static char code_file_name[23] = "/sndscape/sndscape.cox"; - int sscape_sb_enable = 0; int sscape_joystic_enable = 0x7f; int sscape_mic_enable = 0; int sscape_ext_midi = 0; @@ -1035,14 +1015,9 @@ static void __init sscape_pnp_init_hw(sscape_info* devc) sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40); sscape_write( devc, 3, ( devc -> dma << 4) | 0x80); - if ( sscape_sb_enable ) - sscape_write (devc, 4, 0xF0 | (sb_irq << 2) | midi_irq); - else - sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq); + sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq); i = 0x10; //sscape_read(devc, 9) & (devc->ic_type == IC_ODIE ? 0xf0 : 0xc0); - if ( sscape_sb_enable ) - i |= devc->ic_type == IC_ODIE ? 0x05 : 0x07; if (sscape_joystic_enable) i |= 8; sscape_write (devc, 9, i); @@ -1115,9 +1090,9 @@ static void __init sscape_pnp_init_hw(sscape_info* devc) sscape_write( devc, 9, i | 3 ); sscape_write( devc, 3, 0x40); - if (check_region(0x228, 1)) { - outb(0, 0x228); - release_region(0x228,1); + if (request_region(0x228, 1, "sscape setup junk")) { + outb(0, 0x228); + release_region(0x228,1); } sscape_write( devc, 3, (devc -> dma << 4) | 0x80); sscape_write( devc, 9, i ); @@ -1134,50 +1109,46 @@ static int __init detect_sscape_pnp(sscape_info* devc) DDB(printk("Entered detect_sscape_pnp(%x)\n", devc->base)); - if (check_region(devc->base, 8)) { - printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->base); - return 0; - } - - if (check_region(devc->codec, 2)) { + if (!request_region(devc->codec, 2, "sscape codec")) { printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->codec); return 0; } - if ( (inb( devc -> base + 2) & 0x78) != 0) return 0; + if ((inb(devc->base + 2) & 0x78) != 0) + goto fail; d = inb ( devc -> base + 4) & 0xF0; - if ( (d & 0x80) != 0) return 0; + if (d & 0x80) + goto fail; if (d == 0) { - devc->codec_type = 1; - devc->ic_type = IC_ODIE; - } - else if ( (d & 0x60) != 0) { - devc->codec_type = 2; - devc->ic_type = IC_OPUS; - } - else if ( (d & 0x40) != 0) { - devc->codec_type = 2; - devc->ic_type = IC_ODIE; - } - else return 0; + devc->codec_type = 1; + devc->ic_type = IC_ODIE; + } else if ( (d & 0x60) != 0) { + devc->codec_type = 2; + devc->ic_type = IC_OPUS; + } else if ( (d & 0x40) != 0) { /* WTF? */ + devc->codec_type = 2; + devc->ic_type = IC_ODIE; + } else + goto fail; sscape_is_pnp = 1; outb(0xFA, devc -> base+4); if ((inb( devc -> base+4) & 0x9F) != 0x0A) - return 0; + goto fail; outb(0xFE, devc -> base+4); if ( (inb(devc -> base+4) & 0x9F) != 0x0E) - return 0; + goto fail; if ( (inb(devc -> base+5) & 0x9F) != 0x0E) - return 0; + goto fail; if (devc->codec_type == 2) { - if (devc -> codec != devc -> base + 8) + if (devc->codec != devc->base + 8) { printk("soundscape warning: incorrect codec port specified\n"); - devc -> codec = devc -> base + 8; + goto fail; + } d = 0x10 | (sscape_read(devc, 9) & 0xCF); sscape_write(devc, 9, d); sscape_write(devc, 6, 0x80); @@ -1193,9 +1164,9 @@ static int __init detect_sscape_pnp(sscape_info* devc) d = inb(devc -> codec); if (d & 0x80) - return 0; + goto fail; if ( inb(devc -> codec + 2) == 0xFF) - return 0; + goto fail; sscape_write(devc, 9, sscape_read(devc, 9) & 0x3F ); @@ -1217,7 +1188,7 @@ static int __init detect_sscape_pnp(sscape_info* devc) sscape_pnp_init_hw(devc); - for (i = 0; i < sizeof(valid_interrupts); i++) + for (i = 0; i < 4; i++) { if (devc->codec_irq == valid_interrupts[i]) { irq_bits = i; @@ -1234,15 +1205,14 @@ static int __init detect_sscape_pnp(sscape_info* devc) sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 0) | 0x20); sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 1) | 0x20); - return 1; + return 1; +fail: + release_region(devc->codec, 2); + return 0; } static int __init probe_sscape(struct address_info *hw_config) { - - if (sscape_detected != 0 && sscape_detected != hw_config->io_base) - return 0; - devc->base = hw_config->io_base; devc->irq = hw_config->irq; devc->dma = hw_config->dma; @@ -1262,12 +1232,21 @@ static int __init probe_sscape(struct address_info *hw_config) #endif devc->failed = 1; + sscape_ports = request_region(devc->base, 2, "mpu401"); + if (!sscape_ports) + return 0; + + if (!request_region(devc->base + 2, 6, "SoundScape")) { + release_region(devc->base, 2); + return 0; + } + if (!detect_ga(devc)) { - if (detect_sscape_pnp(devc)) { - sscape_detected = hw_config->io_base; + if (detect_sscape_pnp(devc)) return 1; - } - else return 0; + release_region(devc->base, 2); + release_region(devc->base + 2, 6); + return 0; } if (old_hardware) /* Check that it's really an old Spea/Reveal card. */ @@ -1282,14 +1261,14 @@ static int __init probe_sscape(struct address_info *hw_config) inb(devc->base + ODIE_ADDR); } } - sscape_detected = hw_config->io_base; return 1; } -static int __init probe_ss_ms_sound(struct address_info *hw_config) +static int __init init_ss_ms_sound(struct address_info *hw_config) { int i, irq_bits = 0xff; int ad_flags = 0; + struct resource *ports; if (devc->failed) { @@ -1301,7 +1280,7 @@ static int __init probe_ss_ms_sound(struct address_info *hw_config) printk(KERN_ERR "soundscape: Invalid initialization order.\n"); return 0; } - for (i = 0; i < sizeof(valid_interrupts); i++) + for (i = 0; i < 4; i++) { if (hw_config->irq == valid_interrupts[i]) { @@ -1309,37 +1288,27 @@ static int __init probe_ss_ms_sound(struct address_info *hw_config) break; } } - if (hw_config->irq > 15 || irq_bits == 0xff) - { + if (irq_bits == 0xff) { printk(KERN_ERR "soundscape: Invalid MSS IRQ%d\n", hw_config->irq); return 0; } - if (!sscape_is_pnp) { - if (old_hardware) - ad_flags = 0x12345677; /* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */ - return ad1848_detect(hw_config->io_base, &ad_flags, hw_config->osp); - } - else { - if (old_hardware) - ad_flags = 0x12345677; /* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */ - else - ad_flags = 0x87654321; /* Tell that we have a soundscape pnp with 1845 chip */ - return ad1848_detect(hw_config->io_base, &ad_flags, hw_config->osp); - } -} + if (old_hardware) + ad_flags = 0x12345677; /* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */ + else if (sscape_is_pnp) + ad_flags = 0x87654321; /* Tell that we have a soundscape pnp with 1845 chip */ -static void __init attach_ss_ms_sound(struct address_info *hw_config) -{ - /* - * This routine configures the SoundScape card for use with the - * Win Sound System driver. The AD1848 codec interface uses the CD-ROM - * config registers of the "ODIE". - */ + ports = request_region(hw_config->io_base, 4, "ad1848"); + if (!ports) { + printk(KERN_ERR "soundscape: ports busy\n"); + return 0; + } - int i, irq_bits = 0xff; + if (!ad1848_detect(ports, &ad_flags, hw_config->osp)) { + release_region(hw_config->io_base, 4); + return 0; + } - if (!sscape_is_pnp) /*pnp is already setup*/ { /* @@ -1355,14 +1324,6 @@ static void __init attach_ss_ms_sound(struct address_info *hw_config) /* * Init the AD1848 (CD-ROM) config reg. */ - for (i = 0; i < sizeof(valid_interrupts); i++) - { - if (hw_config->irq == valid_interrupts[i]) - { - irq_bits = i; - break; - } - } sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | (irq_bits << 1)); } @@ -1371,7 +1332,7 @@ static void __init attach_ss_ms_sound(struct address_info *hw_config) hw_config->slots[0] = ad1848_init( sscape_is_pnp ? "SoundScape" : "SoundScape PNP", - hw_config->io_base, + ports, hw_config->irq, hw_config->dma, hw_config->dma, @@ -1402,13 +1363,15 @@ static void __init attach_ss_ms_sound(struct address_info *hw_config) printk("I%d = %02x\n", i, sscape_read(devc, i)); } #endif - + return 1; } static void __exit unload_sscape(struct address_info *hw_config) { release_region(devc->base + 2, 6); unload_mpu401(hw_config); + if (sscape_is_pnp) + release_region(devc->codec, 2); } static void __exit unload_ss_ms_sound(struct address_info *hw_config) @@ -1425,20 +1388,20 @@ static struct address_info cfg; static struct address_info cfg_mpu; static int __initdata spea = -1; -static int __initdata mss = 0; +static int mss = 0; static int __initdata dma = -1; static int __initdata irq = -1; static int __initdata io = -1; static int __initdata mpu_irq = -1; static int __initdata mpu_io = -1; -MODULE_PARM(dma, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(io, "i"); -MODULE_PARM(spea, "i"); /* spea=0/1 set the old_hardware */ -MODULE_PARM(mpu_irq, "i"); -MODULE_PARM(mpu_io, "i"); -MODULE_PARM(mss, "i"); +module_param(dma, int, 0); +module_param(irq, int, 0); +module_param(io, int, 0); +module_param(spea, int, 0); /* spea=0/1 set the old_hardware */ +module_param(mpu_irq, int, 0); +module_param(mpu_io, int, 0); +module_param(mss, int, 0); static int __init init_sscape(void) { @@ -1480,10 +1443,7 @@ static int __init init_sscape(void) attach_sscape(&cfg_mpu); - mss = probe_ss_ms_sound(&cfg); - - if (mss) - attach_ss_ms_sound(&cfg); + mss = init_ss_ms_sound(&cfg); return 0; }