X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Foss%2Fad1848.c;h=7cf9913a47b26ca4e3adb02a25e2538542913463;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=af1225d9fd4e1d9cd7b59ea2fb6aed1259384fc4;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c index af1225d9f..7cf9913a4 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c @@ -1,5 +1,5 @@ /* - * sound/ad1848.c + * sound/oss/ad1848.c * * The low level driver for the AD1848/CS4248 codec chip which * is used for example in the MS Sound System. @@ -41,12 +41,10 @@ * Tested. Believed fully functional. */ -#include #include #include #include #include -#include #include #include #include @@ -104,9 +102,6 @@ typedef struct int irq_ok; mixer_ents *mix_devices; int mixer_output_port; - - /* Power management */ - struct pm_dev *pmdev; } ad1848_info; typedef struct ad1848_port_info @@ -123,9 +118,9 @@ ad1848_port_info; static struct address_info cfg; static int nr_ad1848_devs; -int deskpro_xl; -int deskpro_m; -int soundpro; +static int deskpro_xl; +static int deskpro_m; +static int soundpro; static volatile signed char irq2dev[17] = { -1, -1, -1, -1, -1, -1, -1, -1, @@ -200,7 +195,7 @@ static void ad1848_halt(int dev); static void ad1848_halt_input(int dev); static void ad1848_halt_output(int dev); static void ad1848_trigger(int dev, int bits); -static int ad1848_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data); +static irqreturn_t adintr(int irq, void *dev_id); #ifndef EXCLUDE_TIMERS static int ad1848_tmr_install(int dev); @@ -1538,7 +1533,7 @@ static void ad1848_init_hw(ad1848_info * devc) ad1848_mixer_reset(devc); } -int ad1848_detect(int io_base, int *ad_flags, int *osp) +int ad1848_detect(struct resource *ports, int *ad_flags, int *osp) { unsigned char tmp; ad1848_info *devc = &adev_info[nr_ad1848_devs]; @@ -1548,6 +1543,7 @@ int ad1848_detect(int io_base, int *ad_flags, int *osp) int ad1847_flag = 0; int cs4248_flag = 0; int sscape_flag = 0; + int io_base = ports->start; int i; @@ -1578,11 +1574,6 @@ int ad1848_detect(int io_base, int *ad_flags, int *osp) printk(KERN_ERR "ad1848 - Too many audio devices\n"); return 0; } - if (check_region(io_base, 4)) - { - printk(KERN_ERR "ad1848.c: Port %x not free.\n", io_base); - return 0; - } spin_lock_init(&devc->lock); devc->base = io_base; devc->irq_ok = 0; @@ -1951,7 +1942,7 @@ int ad1848_detect(int io_base, int *ad_flags, int *osp) return 1; } -int ad1848_init (char *name, int io_base, int irq, int dma_playback, +int ad1848_init (char *name, struct resource *ports, int irq, int dma_playback, int dma_capture, int share_dma, int *osp, struct module *owner) { /* @@ -1986,8 +1977,7 @@ int ad1848_init (char *name, int io_base, int irq, int dma_playback, sprintf(dev_name, "Generic audio codec (%s)", devc->chip_name); - if (!request_region(devc->base, 4, devc->name)) - return -1; + rename_region(ports, devc->name); conf_printf2(dev_name, devc->base, devc->irq, dma_playback, dma_capture); @@ -2002,7 +1992,7 @@ int ad1848_init (char *name, int io_base, int irq, int dma_playback, devc->audio_flags |= DMA_DUPLEX; } - portc = (ad1848_port_info *) kmalloc(sizeof(ad1848_port_info), GFP_KERNEL); + portc = kmalloc(sizeof(ad1848_port_info), GFP_KERNEL); if(portc==NULL) { release_region(devc->base, 4); return -1; @@ -2031,16 +2021,13 @@ int ad1848_init (char *name, int io_base, int irq, int dma_playback, nr_ad1848_devs++; - devc->pmdev = pm_register(PM_ISA_DEV, my_dev, ad1848_pm_callback); - if (devc->pmdev) - devc->pmdev->data = devc; - ad1848_init_hw(devc); if (irq > 0) { devc->dev_no = my_dev; - if (request_irq(devc->irq, adintr, 0, devc->name, (void *)my_dev) < 0) + if (request_irq(devc->irq, adintr, 0, devc->name, + (void *)(long)my_dev) < 0) { printk(KERN_WARNING "ad1848: Unable to allocate IRQ\n"); /* Don't free it either then.. */ @@ -2183,14 +2170,13 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int if (devc != NULL) { - if(audio_devs[dev]->portc!=NULL) - kfree(audio_devs[dev]->portc); + kfree(audio_devs[dev]->portc); release_region(devc->base, 4); if (!share_dma) { if (devc->irq > 0) /* There is no point in freeing irq, if it wasn't allocated */ - free_irq(devc->irq, (void *)devc->dev_no); + free_irq(devc->irq, (void *)(long)devc->dev_no); sound_free_dma(dma_playback); @@ -2202,9 +2188,6 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int if(mixer>=0) sound_unload_mixerdev(mixer); - if (devc->pmdev) - pm_unregister(devc->pmdev); - nr_ad1848_devs--; for ( ; i < nr_ad1848_devs ; i++) adev_info[i] = adev_info[i+1]; @@ -2213,7 +2196,7 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int printk(KERN_ERR "ad1848: Can't find device to be unloaded. Base=%x\n", io_base); } -irqreturn_t adintr(int irq, void *dev_id, struct pt_regs *dummy) +static irqreturn_t adintr(int irq, void *dev_id) { unsigned char status; ad1848_info *devc; @@ -2222,7 +2205,7 @@ irqreturn_t adintr(int irq, void *dev_id, struct pt_regs *dummy) unsigned char c930_stat = 0; int cnt = 0; - dev = (int)dev_id; + dev = (long)dev_id; devc = (ad1848_info *) audio_devs[dev]->devc; interrupt_again: /* Jump back here if int status doesn't reset */ @@ -2522,21 +2505,16 @@ static int init_deskpro(struct address_info *hw_config) return 1; } -int probe_ms_sound(struct address_info *hw_config) +int probe_ms_sound(struct address_info *hw_config, struct resource *ports) { unsigned char tmp; DDB(printk("Entered probe_ms_sound(%x, %d)\n", hw_config->io_base, hw_config->card_subtype)); - if (check_region(hw_config->io_base, 8)) - { - printk(KERN_ERR "MSS: I/O port conflict\n"); - return 0; - } if (hw_config->card_subtype == 1) /* Has no IRQ/DMA registers */ { /* check_opl3(0x388, hw_config); */ - return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp); + return ad1848_detect(ports, NULL, hw_config->osp); } if (deskpro_xl && hw_config->card_subtype == 2) /* Compaq Deskpro XL */ @@ -2562,7 +2540,7 @@ int probe_ms_sound(struct address_info *hw_config) int ret; DDB(printk("I/O address is inactive (%x)\n", tmp)); - if (!(ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp))) + if (!(ret = ad1848_detect(ports, NULL, hw_config->osp))) return 0; return 1; } @@ -2575,7 +2553,7 @@ int probe_ms_sound(struct address_info *hw_config) MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, (int) inb(hw_config->io_base + 3))); DDB(printk("Trying to detect codec anyway but IRQ/DMA may not work\n")); - if (!(ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp))) + if (!(ret = ad1848_detect(ports, NULL, hw_config->osp))) return 0; hw_config->card_subtype = 1; @@ -2610,10 +2588,10 @@ int probe_ms_sound(struct address_info *hw_config) printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq); return 0; } - return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp); + return ad1848_detect(ports, NULL, hw_config->osp); } -void attach_ms_sound(struct address_info *hw_config, struct module *owner) +void attach_ms_sound(struct address_info *hw_config, struct resource *ports, struct module *owner) { static signed char interrupt_bits[12] = { @@ -2634,13 +2612,12 @@ void attach_ms_sound(struct address_info *hw_config, struct module *owner) if (hw_config->card_subtype == 1) /* Has no IRQ/DMA registers */ { - hw_config->slots[0] = ad1848_init("MS Sound System", hw_config->io_base + 4, + hw_config->slots[0] = ad1848_init("MS Sound System", ports, hw_config->irq, hw_config->dma, hw_config->dma2, 0, hw_config->osp, owner); - request_region(hw_config->io_base, 4, "WSS config"); return; } /* @@ -2651,6 +2628,8 @@ void attach_ms_sound(struct address_info *hw_config, struct module *owner) if (bits == -1) { printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq); + release_region(ports->start, 4); + release_region(ports->start - 4, 4); return; } outb((bits | 0x40), config_port); @@ -2694,12 +2673,11 @@ void attach_ms_sound(struct address_info *hw_config, struct module *owner) outb((bits | dma_bits[dma] | dma2_bit), config_port); /* Write IRQ+DMA setup */ - hw_config->slots[0] = ad1848_init("MS Sound System", hw_config->io_base + 4, + hw_config->slots[0] = ad1848_init("MS Sound System", ports, hw_config->irq, dma, dma2, 0, hw_config->osp, THIS_MODULE); - request_region(hw_config->io_base, 4, "WSS config"); } void unload_ms_sound(struct address_info *hw_config) @@ -2821,90 +2799,10 @@ static int ad1848_tmr_install(int dev) } #endif /* EXCLUDE_TIMERS */ -static int ad1848_suspend(ad1848_info *devc) -{ - unsigned long flags; - - spin_lock_irqsave(&devc->lock,flags); - - ad_mute(devc); - - spin_unlock_irqrestore(&devc->lock,flags); - return 0; -} - -static int ad1848_resume(ad1848_info *devc) -{ - int mixer_levels[32], i; - - /* Thinkpad is a bit more of PITA than normal. The BIOS tends to - restore it in a different config to the one we use. Need to - fix this somehow */ - - /* store old mixer levels */ - memcpy(mixer_levels, devc->levels, sizeof (mixer_levels)); - ad1848_init_hw(devc); - - /* restore mixer levels */ - for (i = 0; i < 32; i++) - ad1848_mixer_set(devc, devc->dev_no, mixer_levels[i]); - - if (!devc->subtype) { - static signed char interrupt_bits[12] = { -1, -1, -1, -1, -1, 0x00, -1, 0x08, -1, 0x10, 0x18, 0x20 }; - static char dma_bits[4] = { 1, 2, 0, 3 }; - unsigned long flags; - signed char bits; - char dma2_bit = 0; - - int config_port = devc->base + 0; - - bits = interrupt_bits[devc->irq]; - if (bits == -1) { - printk(KERN_ERR "MSS: Bad IRQ %d\n", devc->irq); - return -1; - } - - spin_lock_irqsave(&devc->lock,flags); - - outb((bits | 0x40), config_port); - - if (devc->dma2 != -1 && devc->dma2 != devc->dma1) - if ( (devc->dma1 == 0 && devc->dma2 == 1) || - (devc->dma1 == 1 && devc->dma2 == 0) || - (devc->dma1 == 3 && devc->dma2 == 0)) - dma2_bit = 0x04; - - outb((bits | dma_bits[devc->dma1] | dma2_bit), config_port); - spin_unlock_irqrestore(&devc->lock,flags); - } - - return 0; -} - -static int ad1848_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) -{ - ad1848_info *devc = dev->data; - if (devc) { - DEB(printk("ad1848: pm event received: 0x%x\n", rqst)); - - switch (rqst) { - case PM_SUSPEND: - ad1848_suspend(devc); - break; - case PM_RESUME: - ad1848_resume(devc); - break; - } - } - return 0; -} - - EXPORT_SYMBOL(ad1848_detect); EXPORT_SYMBOL(ad1848_init); EXPORT_SYMBOL(ad1848_unload); EXPORT_SYMBOL(ad1848_control); -EXPORT_SYMBOL(adintr); EXPORT_SYMBOL(probe_ms_sound); EXPORT_SYMBOL(attach_ms_sound); EXPORT_SYMBOL(unload_ms_sound); @@ -2915,24 +2813,24 @@ static int __initdata dma = -1; static int __initdata dma2 = -1; static int __initdata type = 0; -MODULE_PARM(io, "i"); /* I/O for a raw AD1848 card */ -MODULE_PARM(irq, "i"); /* IRQ to use */ -MODULE_PARM(dma, "i"); /* First DMA channel */ -MODULE_PARM(dma2, "i"); /* Second DMA channel */ -MODULE_PARM(type, "i"); /* Card type */ -MODULE_PARM(deskpro_xl, "i"); /* Special magic for Deskpro XL boxen */ -MODULE_PARM(deskpro_m, "i"); /* Special magic for Deskpro M box */ -MODULE_PARM(soundpro, "i"); /* More special magic for SoundPro chips */ +module_param(io, int, 0); /* I/O for a raw AD1848 card */ +module_param(irq, int, 0); /* IRQ to use */ +module_param(dma, int, 0); /* First DMA channel */ +module_param(dma2, int, 0); /* Second DMA channel */ +module_param(type, int, 0); /* Card type */ +module_param(deskpro_xl, bool, 0); /* Special magic for Deskpro XL boxen */ +module_param(deskpro_m, bool, 0); /* Special magic for Deskpro M box */ +module_param(soundpro, bool, 0); /* More special magic for SoundPro chips */ #ifdef CONFIG_PNP -MODULE_PARM(isapnp, "i"); -MODULE_PARM(isapnpjump, "i"); -MODULE_PARM(reverse, "i"); +module_param(isapnp, int, 0); +module_param(isapnpjump, int, 0); +module_param(reverse, bool, 0); MODULE_PARM_DESC(isapnp, "When set to 0, Plug & Play support will be disabled"); MODULE_PARM_DESC(isapnpjump, "Jumps to a specific slot in the driver's PnP table. Use the source, Luke."); MODULE_PARM_DESC(reverse, "When set to 1, will reverse ISAPnP search order"); -struct pnp_dev *ad1848_dev = NULL; +static struct pnp_dev *ad1848_dev = NULL; /* Please add new entries at the end of the table */ static struct { @@ -3002,7 +2900,8 @@ static struct pnp_dev *activate_dev(char *devname, char *resname, struct pnp_dev return(dev); } -static struct pnp_dev *ad1848_init_generic(struct pnp_card *bus, struct address_info *hw_config, int slot) +static struct pnp_dev __init *ad1848_init_generic(struct pnp_card *bus, + struct address_info *hw_config, int slot) { /* Configure Audio device */ @@ -3095,6 +2994,7 @@ static int __init init_ad1848(void) #endif if(io != -1) { + struct resource *ports; if( isapnp == 0 ) { if(irq == -1 || dma == -1) { @@ -3109,9 +3009,22 @@ static int __init init_ad1848(void) cfg.card_subtype = type; } - if(!probe_ms_sound(&cfg)) + ports = request_region(io + 4, 4, "ad1848"); + + if (!ports) + return -EBUSY; + + if (!request_region(io, 4, "WSS config")) { + release_region(io + 4, 4); + return -EBUSY; + } + + if (!probe_ms_sound(&cfg, ports)) { + release_region(io + 4, 4); + release_region(io, 4); return -ENODEV; - attach_ms_sound(&cfg, THIS_MODULE); + } + attach_ms_sound(&cfg, ports, THIS_MODULE); loaded = 1; } return 0;