X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Foss%2Fsscape.c;h=9ed5211c3168156f05f8d0f9e89d4191c9f48c2e;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=d4c1922649f59d1b1e656de7953708c402c2cb27;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/sound/oss/sscape.c b/sound/oss/sscape.c index d4c192264..9ed5211c3 100644 --- a/sound/oss/sscape.c +++ b/sound/oss/sscape.c @@ -171,13 +171,18 @@ static unsigned char sscape_read(struct sscape_info *devc, int reg) return val; } +static void __sscape_write(int reg, int data) +{ + outb(reg, PORT(ODIE_ADDR)); + outb(data, PORT(ODIE_DATA)); +} + static void sscape_write(struct sscape_info *devc, int reg, int data) { unsigned long flags; spin_lock_irqsave(&devc->lock,flags); - outb(reg, PORT(ODIE_ADDR)); - outb(data, PORT(ODIE_DATA)); + __sscape_write(reg, data); spin_unlock_irqrestore(&devc->lock,flags); } @@ -386,7 +391,7 @@ static void sscape_coproc_close(void *dev_info, int sub_device) spin_lock_irqsave(&devc->lock,flags); if (devc->dma_allocated) { - sscape_write(devc, GA_DMAA_REG, 0x20); /* DMA channel disabled */ + __sscape_write(GA_DMAA_REG, 0x20); /* DMA channel disabled */ devc->dma_allocated = 0; } spin_unlock_irqrestore(&devc->lock,flags); @@ -555,7 +560,7 @@ static int download_boot_block(void *dev_info, copr_buffer * buf) return 0; } -static int sscape_coproc_ioctl(void *dev_info, unsigned int cmd, caddr_t arg, int local) +static int sscape_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg, int local) { copr_buffer *buf; int err; @@ -595,10 +600,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 /* @@ -633,10 +638,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; @@ -645,7 +646,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]) { @@ -656,45 +657,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 @@ -710,7 +698,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"; @@ -734,9 +722,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. @@ -1006,7 +991,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; @@ -1030,14 +1014,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); @@ -1110,9 +1089,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 ); @@ -1129,50 +1108,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); @@ -1188,9 +1163,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 ); @@ -1212,7 +1187,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; @@ -1229,15 +1204,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; @@ -1257,12 +1231,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. */ @@ -1277,14 +1260,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) { @@ -1296,7 +1279,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]) { @@ -1304,37 +1287,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*/ { /* @@ -1350,14 +1323,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)); } @@ -1366,7 +1331,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, @@ -1397,13 +1362,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) @@ -1420,20 +1387,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) { @@ -1475,10 +1442,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; }