X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Foss%2Fmad16.c;h=aa3c50db66c49d589102e6b68bd4f4c5b9075c47;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=b7ef7def6076a1c644493a57a70ecd327ff9a3c3;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/sound/oss/mad16.c b/sound/oss/mad16.c index b7ef7def6..aa3c50db6 100644 --- a/sound/oss/mad16.c +++ b/sound/oss/mad16.c @@ -50,11 +50,13 @@ #include "sb.h" #include "mpu401.h" +#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#define SUPPORT_JOYSTICK 1 +#endif + static int mad16_conf; static int mad16_cdsel; -static struct gameport gameport; -static spinlock_t lock=SPIN_LOCK_UNLOCKED; -static int already_initialized; +static DEFINE_SPINLOCK(lock); #define C928 1 #define MOZART 2 @@ -313,19 +315,6 @@ static int __init detect_mad16(void) static int __init wss_init(struct address_info *hw_config) { - int ad_flags = 0; - - /* - * Verify the WSS parameters - */ - - if (check_region(hw_config->io_base, 8)) - { - printk(KERN_ERR "MSS: I/O port conflict\n"); - return 0; - } - if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp)) - return 0; /* * Check if the IO port returns valid signature. The original MS Sound * system returns 0x04 while some cards (AudioTrix Pro for example) @@ -338,31 +327,20 @@ static int __init wss_init(struct address_info *hw_config) DDB(printk("No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, inb(hw_config->io_base + 3))); return 0; } - if (hw_config->irq > 11) - { - printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq); - return 0; - } - if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3) - { - printk(KERN_ERR "MSS: Bad DMA %d\n", hw_config->dma); - return 0; - } /* * Check that DMA0 is not in use with a 8 bit board. */ - if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80) { printk("MSS: Can't use DMA0 with a 8 bit card/slot\n"); return 0; } - if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80) + if (hw_config->irq > 9 && inb(hw_config->io_base + 3) & 0x80) printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq); return 1; } -static int __init init_c930(struct address_info *hw_config) +static void __init init_c930(struct address_info *hw_config, int base) { unsigned char cfg = 0; @@ -376,25 +354,7 @@ static int __init init_c930(struct address_info *hw_config) somewhere else. */ cfg = (cfg & 0x09) ^ 0x07; } - - switch (hw_config->io_base) - { - case 0x530: - cfg |= 0x00; - break; - case 0xe80: - cfg |= 0x10; - break; - case 0xf40: - cfg |= 0x20; - break; - case 0x604: - cfg |= 0x30; - break; - default: - printk(KERN_ERR "MAD16: Invalid codec port %x\n", hw_config->io_base); - return 0; - } + cfg |= base << 4; mad_write(MC1_PORT, cfg); /* MC2 is CD configuration. Don't touch it. */ @@ -414,8 +374,6 @@ static int __init init_c930(struct address_info *hw_config) mad_write(MC6_PORT, 0x02); /* Enable WSS, Disable MPU and SB */ mad_write(MC7_PORT, 0xCB); mad_write(MC10_PORT, 0x11); - - return wss_init(hw_config); } static int __init chip_detect(void) @@ -508,20 +466,48 @@ static int __init chip_detect(void) static int __init probe_mad16(struct address_info *hw_config) { int i; - static int valid_ports[] = - { - 0x530, 0xe80, 0xf40, 0x604 - }; unsigned char tmp; unsigned char cs4231_mode = 0; int ad_flags = 0; - if (already_initialized) - return 0; + signed char bits; + + static char dma_bits[4] = { + 1, 2, 0, 3 + }; + + int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3; + int dma = hw_config->dma, dma2 = hw_config->dma2; + unsigned char dma2_bit = 0; + int base; + struct resource *ports; mad16_osp = hw_config->osp; + switch (hw_config->io_base) { + case 0x530: + base = 0; + break; + case 0xe80: + base = 1; + break; + case 0xf40: + base = 2; + break; + case 0x604: + base = 3; + break; + default: + printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base); + return 0; + } + + if (dma != 0 && dma != 1 && dma != 3) { + printk(KERN_ERR "MSS: Bad DMA %d\n", dma); + return 0; + } + /* * Check that all ports return 0xff (bus float) when no password * is written to the password register. @@ -531,9 +517,44 @@ static int __init probe_mad16(struct address_info *hw_config) if (!chip_detect()) return 0; - if (board_type == C930) - return init_c930(hw_config); + switch (hw_config->irq) { + case 7: + bits = 8; + break; + case 9: + bits = 0x10; + break; + case 10: + bits = 0x18; + break; + case 12: + bits = 0x20; + break; + case 5: /* Also IRQ5 is possible on C930 */ + if (board_type == C930 || c924pnp) { + bits = 0x28; + break; + } + default: + printk(KERN_ERR "MAD16/Mozart: Bad IRQ %d\n", hw_config->irq); + return 0; + } + + ports = request_region(hw_config->io_base + 4, 4, "ad1848"); + if (!ports) { + printk(KERN_ERR "MSS: I/O port conflict\n"); + return 0; + } + if (!request_region(hw_config->io_base, 4, "mad16 WSS config")) { + release_region(hw_config->io_base + 4, 4); + printk(KERN_ERR "MSS: I/O port conflict\n"); + return 0; + } + if (board_type == C930) { + init_c930(hw_config, base); + goto got_it; + } for (i = 0xf8d; i <= 0xf93; i++) { if (!c924pnp) @@ -547,20 +568,7 @@ static int __init probe_mad16(struct address_info *hw_config) */ tmp = (mad_read(MC1_PORT) & 0x0f) | 0x80; /* Enable WSS, Disable SB */ - - for (i = 0; i < 5; i++) - { - if (i > 3) /* Not a valid port */ - { - printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base); - return 0; - } - if (valid_ports[i] == hw_config->io_base) - { - tmp |= i << 4; /* WSS port select bits */ - break; - } - } + tmp |= base << 4; /* WSS port select bits */ /* * Set optional CD-ROM and joystick settings. @@ -580,8 +588,8 @@ static int __init probe_mad16(struct address_info *hw_config) mad_write(MC5_PORT, 0x05); mad_write(MC6_PORT, 0x03); } - if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp)) - return 0; + if (!ad1848_detect(ports, &ad_flags, mad16_osp)) + goto fail; if (ad_flags & (AD_F_CS4231 | AD_F_CS4248)) cs4231_mode = 0x02; /* CS4248/CS4231 sync delay switch */ @@ -604,43 +612,19 @@ static int __init probe_mad16(struct address_info *hw_config) else DDB(printk("port %03x after init = %02x\n", i-0x80, mad_read(i))); } - wss_init(hw_config); - return 1; -} +got_it: + ad_flags = 0; + if (!ad1848_detect(ports, &ad_flags, mad16_osp)) + goto fail; -static void __init attach_mad16(struct address_info *hw_config) -{ - - static signed char interrupt_bits[12] = { - -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20 - }; - signed char bits; - - static char dma_bits[4] = { - 1, 2, 0, 3 - }; - - int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3; - int ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2; - unsigned char dma2_bit = 0; - - already_initialized = 1; - - if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp)) - return; + if (!wss_init(hw_config)) + goto fail; /* * Set the IRQ and DMA addresses. */ - if (board_type == C930 || c924pnp) - interrupt_bits[5] = 0x28; /* Also IRQ5 is possible on C930 */ - - bits = interrupt_bits[hw_config->irq]; - if (bits == -1) - return; - outb((bits | 0x40), config_port); if ((inb(version_port) & 0x40) == 0) printk(KERN_ERR "[IRQ Conflict?]\n"); @@ -675,27 +659,24 @@ static void __init attach_mad16(struct address_info *hw_config) outb((bits | dma_bits[dma] | dma2_bit), config_port); /* Write IRQ+DMA setup */ - hw_config->slots[0] = ad1848_init("mad16 WSS", hw_config->io_base + 4, + hw_config->slots[0] = ad1848_init("mad16 WSS", ports, hw_config->irq, dma, dma2, 0, hw_config->osp, THIS_MODULE); - request_region(hw_config->io_base, 4, "mad16 WSS config"); + return 1; + +fail: + release_region(hw_config->io_base + 4, 4); + release_region(hw_config->io_base, 4); + return 0; } static int __init probe_mad16_mpu(struct address_info *hw_config) { - static int mpu_attached; unsigned char tmp; - if (!already_initialized) /* The MSS port must be initialized first */ - return 0; - - if (mpu_attached) /* Don't let them call this twice */ - return 0; - mpu_attached = 1; - if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */ { @@ -732,8 +713,12 @@ static int __init probe_mad16_mpu(struct address_info *hw_config) mad_write(MC3_PORT, tmp | 0x04); hw_config->driver_use_1 = SB_MIDI_ONLY; - if (!sb_dsp_detect(hw_config, 0, 0, NULL)) + if (!request_region(hw_config->io_base, 16, "soundblaster")) + return 0; + if (!sb_dsp_detect(hw_config, 0, 0, NULL)) { + release_region(hw_config->io_base, 16); return 0; + } if (mad_read(MC1_PORT) & 0x20) hw_config->io_base = 0x240; @@ -892,19 +877,19 @@ static int __initdata cddma = -1; static int __initdata opl4 = 0; static int __initdata joystick = 0; -MODULE_PARM(mpu_io, "i"); -MODULE_PARM(mpu_irq, "i"); -MODULE_PARM(io,"i"); -MODULE_PARM(dma,"i"); -MODULE_PARM(dma16,"i"); -MODULE_PARM(irq,"i"); -MODULE_PARM(cdtype,"i"); -MODULE_PARM(cdirq,"i"); -MODULE_PARM(cdport,"i"); -MODULE_PARM(cddma,"i"); -MODULE_PARM(opl4,"i"); -MODULE_PARM(joystick,"i"); -MODULE_PARM(debug,"i"); +module_param(mpu_io, int, 0); +module_param(mpu_irq, int, 0); +module_param(io, int, 0); +module_param(dma, int, 0); +module_param(dma16, int, 0); +module_param(irq, int, 0); +module_param(cdtype, int, 0); +module_param(cdirq, int, 0); +module_param(cdport, int, 0); +module_param(cddma, int, 0); +module_param(opl4, int, 0); +module_param(joystick, bool, 0); +module_param(debug, bool, 0644); static int __initdata dma_map[2][8] = { @@ -920,7 +905,48 @@ static int __initdata irq_map[16] = -1, -1, -1, -1 }; -static int __init init_mad16(void) +#ifdef SUPPORT_JOYSTICK + +static struct gameport *gameport; + +static int __devinit mad16_register_gameport(int io_port) +{ + if (!request_region(io_port, 1, "mad16 gameport")) { + printk(KERN_ERR "mad16: gameport address 0x%#x already in use\n", io_port); + return -EBUSY; + } + + gameport = gameport_allocate_port(); + if (!gameport) { + printk(KERN_ERR "mad16: can not allocate memory for gameport\n"); + release_region(io_port, 1); + return -ENOMEM; + } + + gameport_set_name(gameport, "MAD16 Gameport"); + gameport_set_phys(gameport, "isa%04x/gameport0", io_port); + gameport->io = io_port; + + gameport_register_port(gameport); + + return 0; +} + +static inline void mad16_unregister_gameport(void) +{ + if (gameport) { + /* the gameport was initialized so we must free it up */ + gameport_unregister_port(gameport); + gameport = NULL; + release_region(0x201, 1); + } +} +#else +static inline int mad16_register_gameport(int io_port) { return -ENOSYS; } +static inline void mad16_unregister_gameport(void) { } +#endif + +static int __devinit init_mad16(void) { int dmatype = 0; @@ -1031,28 +1057,23 @@ static int __init init_mad16(void) printk(KERN_ERR "I/O, DMA and irq are mandatory\n"); return -EINVAL; } - - if (!probe_mad16(&cfg)) + + if (!request_region(MC0_PORT, 12, "mad16")) + return -EBUSY; + + if (!probe_mad16(&cfg)) { + release_region(MC0_PORT, 12); return -ENODEV; + } cfg_mpu.io_base = mpu_io; cfg_mpu.irq = mpu_irq; - attach_mad16(&cfg); - found_mpu = probe_mad16_mpu(&cfg_mpu); - if (joystick == 1) { - /* register gameport */ - if (!request_region(0x201, 1, "mad16 gameport")) - printk(KERN_ERR "mad16: gameport address 0x201 already in use\n"); - else { - printk(KERN_ERR "mad16: gameport enabled at 0x201\n"); - gameport.io = 0x201; - gameport_register_port(&gameport); - } - } - else printk(KERN_ERR "mad16: gameport disabled.\n"); + if (joystick) + mad16_register_gameport(0x201); + return 0; } @@ -1060,13 +1081,9 @@ static void __exit cleanup_mad16(void) { if (found_mpu) unload_mad16_mpu(&cfg_mpu); - if (gameport.io) { - /* the gameport was initialized so we must free it up */ - gameport_unregister_port(&gameport); - gameport.io = 0; - release_region(0x201, 1); - } + mad16_unregister_gameport(); unload_mad16(&cfg); + release_region(MC0_PORT, 12); } module_init(init_mad16);