X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=sound%2Foss%2Fcmpci.c;h=de60a059ff5f783c60d10127c701335d363637dc;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=386107f47bd432166552daa721f127ee3f6377c1;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/sound/oss/cmpci.c b/sound/oss/cmpci.c index 386107f47..de60a059f 100644 --- a/sound/oss/cmpci.c +++ b/sound/oss/cmpci.c @@ -123,6 +123,7 @@ #include #include #include +#include #include #include @@ -137,6 +138,8 @@ #endif #ifdef CONFIG_SOUND_CMPCI_JOYSTICK #include +#include + #endif /* --------------------------------------------------------------------- */ @@ -391,7 +394,7 @@ struct cm_state { unsigned char fmt, enable; spinlock_t lock; - struct semaphore open_sem; + struct mutex open_mutex; mode_t open_mode; wait_queue_head_t open_wait; @@ -426,7 +429,7 @@ struct cm_state { struct address_info mpu_data; #endif #ifdef CONFIG_SOUND_CMPCI_JOYSTICK - struct gameport gameport; + struct gameport *gameport; #endif int chip_version; @@ -468,28 +471,28 @@ struct cm_state { static LIST_HEAD(devs); -static int mpuio = 0; -static int fmio = 0; -static int joystick = 0; -static int spdif_inverse = 0; -static int spdif_loop = 0; -static int spdif_out = 0; -static int use_line_as_rear = 0; -static int use_line_as_bass = 0; -static int use_mic_as_bass = 0; -static int mic_boost = 0; -static int hw_copy = 0; -MODULE_PARM(mpuio, "i"); -MODULE_PARM(fmio, "i"); -MODULE_PARM(joystick, "i"); -MODULE_PARM(spdif_inverse, "i"); -MODULE_PARM(spdif_loop, "i"); -MODULE_PARM(spdif_out, "i"); -MODULE_PARM(use_line_as_rear, "i"); -MODULE_PARM(use_line_as_bass, "i"); -MODULE_PARM(use_mic_as_bass, "i"); -MODULE_PARM(mic_boost, "i"); -MODULE_PARM(hw_copy, "i"); +static int mpuio; +static int fmio; +static int joystick; +static int spdif_inverse; +static int spdif_loop; +static int spdif_out; +static int use_line_as_rear; +static int use_line_as_bass; +static int use_mic_as_bass; +static int mic_boost; +static int hw_copy; +module_param(mpuio, int, 0); +module_param(fmio, int, 0); +module_param(joystick, bool, 0); +module_param(spdif_inverse, bool, 0); +module_param(spdif_loop, bool, 0); +module_param(spdif_out, bool, 0); +module_param(use_line_as_rear, bool, 0); +module_param(use_line_as_bass, bool, 0); +module_param(use_mic_as_bass, bool, 0); +module_param(mic_boost, bool, 0); +module_param(hw_copy, bool, 0); MODULE_PARM_DESC(mpuio, "(0x330, 0x320, 0x310, 0x300) Base of MPU-401, 0 to disable"); MODULE_PARM_DESC(fmio, "(0x388, 0x3C8, 0x3E0) Base of OPL3, 0 to disable"); MODULE_PARM_DESC(joystick, "(1/0) Enable joystick interface, still need joystick driver"); @@ -1162,15 +1165,6 @@ static inline void enable_dac_unlocked(struct cm_state *s) enable_adc(s); } -static inline void enable_dac(struct cm_state *s) -{ - unsigned long flags; - - spin_lock_irqsave(&s->lock, flags); - enable_dac_unlocked(s); - spin_unlock_irqrestore(&s->lock, flags); -} - static inline void stop_adc_unlocked(struct cm_state *s) { if (s->enable & ENADC) { @@ -1393,7 +1387,7 @@ static int prog_dmabuf(struct cm_state *s, unsigned rec) if (!db->rawbuf || !db->dmaaddr) return -ENOMEM; db->buforder = order; - /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ + /* now mark the pages as reserved; otherwise remap_pfn_range doesn't do what we want */ pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); for (pstart = virt_to_page(db->rawbuf); pstart <= pend; pstart++) SetPageReserved(pstart); @@ -1719,7 +1713,7 @@ static int mixer_ioctl(struct cm_state *s, unsigned int cmd, unsigned long arg) case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ if (get_user(val, p)) return -EFAULT; - i = generic_hweight32(val); + i = hweight32(val); for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) { if (!(val & (1 << i))) continue; @@ -2301,7 +2295,9 @@ static int cm_mmap(struct file *file, struct vm_area_struct *vma) if (size > (PAGE_SIZE << db->buforder)) goto out; ret = -EINVAL; - if (remap_page_range(vma, vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) + if (remap_pfn_range(vma, vma->vm_start, + virt_to_phys(db->rawbuf) >> PAGE_SHIFT, + size, vma->vm_page_prot)) goto out; db->mapped = 1; ret = 0; @@ -2831,21 +2827,21 @@ static int cm_open(struct inode *inode, struct file *file) VALIDATE_STATE(s); file->private_data = s; /* wait for device to become free */ - down(&s->open_sem); + mutex_lock(&s->open_mutex); while (s->open_mode & file->f_mode) { if (file->f_flags & O_NONBLOCK) { - up(&s->open_sem); + mutex_unlock(&s->open_mutex); return -EBUSY; } add_wait_queue(&s->open_wait, &wait); __set_current_state(TASK_INTERRUPTIBLE); - up(&s->open_sem); + mutex_unlock(&s->open_mutex); schedule(); remove_wait_queue(&s->open_wait, &wait); set_current_state(TASK_RUNNING); if (signal_pending(current)) return -ERESTARTSYS; - down(&s->open_sem); + mutex_lock(&s->open_mutex); } if (file->f_mode & FMODE_READ) { s->status &= ~DO_BIGENDIAN_R; @@ -2873,7 +2869,7 @@ static int cm_open(struct inode *inode, struct file *file) } set_fmt(s, fmtm, fmts); s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); - up(&s->open_sem); + mutex_unlock(&s->open_mutex); return nonseekable_open(inode, file); } @@ -2885,7 +2881,7 @@ static int cm_release(struct inode *inode, struct file *file) lock_kernel(); if (file->f_mode & FMODE_WRITE) drain_dac(s, file->f_flags & O_NONBLOCK); - down(&s->open_sem); + mutex_lock(&s->open_mutex); if (file->f_mode & FMODE_WRITE) { stop_dac(s); @@ -2909,7 +2905,7 @@ static int cm_release(struct inode *inode, struct file *file) s->status &= ~DO_BIGENDIAN_R; } s->open_mode &= ~(file->f_mode & (FMODE_READ|FMODE_WRITE)); - up(&s->open_sem); + mutex_unlock(&s->open_mutex); wake_up(&s->open_wait); unlock_kernel(); return 0; @@ -2932,7 +2928,7 @@ static /*const*/ struct file_operations cm_audio_fops = { static struct initvol { int mixch; int vol; -} initvol[] __initdata = { +} initvol[] __devinitdata = { { SOUND_MIXER_WRITE_CD, 0x4f4f }, { SOUND_MIXER_WRITE_LINE, 0x4f4f }, { SOUND_MIXER_WRITE_MIC, 0x4f4f }, @@ -2991,6 +2987,51 @@ static int query_chip(struct cm_state *s) return ChipVersion; } +#ifdef CONFIG_SOUND_CMPCI_JOYSTICK +static int __devinit cm_create_gameport(struct cm_state *s, int io_port) +{ + struct gameport *gp; + + if (!request_region(io_port, CM_EXTENT_GAME, "cmpci GAME")) { + printk(KERN_ERR "cmpci: gameport io ports 0x%#x in use\n", io_port); + return -EBUSY; + } + + if (!(s->gameport = gp = gameport_allocate_port())) { + printk(KERN_ERR "cmpci: can not allocate memory for gameport\n"); + release_region(io_port, CM_EXTENT_GAME); + return -ENOMEM; + } + + gameport_set_name(gp, "C-Media GP"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev)); + gp->dev.parent = &s->dev->dev; + gp->io = io_port; + + /* enable joystick */ + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x02); + + gameport_register_port(gp); + + return 0; +} + +static void __devexit cm_free_gameport(struct cm_state *s) +{ + if (s->gameport) { + int gpio = s->gameport->io; + + gameport_unregister_port(s->gameport); + s->gameport = NULL; + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0); + release_region(gpio, CM_EXTENT_GAME); + } +} +#else +static inline int cm_create_gameport(struct cm_state *s, int io_port) { return -ENOSYS; } +static inline void cm_free_gameport(struct cm_state *s) { } +#endif + #define echo_option(x)\ if (x) strcat(options, "" #x " ") @@ -3000,6 +3041,8 @@ static int __devinit cm_probe(struct pci_dev *pcidev, const struct pci_device_id mm_segment_t fs; int i, val, ret; unsigned char reg_mask; + int timeout; + struct resource *ports; struct { unsigned short deviceid; char *devicename; @@ -3018,7 +3061,7 @@ static int __devinit cm_probe(struct pci_dev *pcidev, const struct pci_device_id return -ENODEV; if (pcidev->irq == 0) return -ENODEV; - i = pci_set_dma_mask(pcidev, 0xffffffff); + i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK); if (i) { printk(KERN_WARNING "cmpci: architecture does not support 32bit PCI busmaster DMA\n"); return i; @@ -3039,7 +3082,7 @@ static int __devinit cm_probe(struct pci_dev *pcidev, const struct pci_device_id init_waitqueue_head(&s->dma_adc.wait); init_waitqueue_head(&s->dma_dac.wait); init_waitqueue_head(&s->open_wait); - init_MUTEX(&s->open_sem); + mutex_init(&s->open_mutex); spin_lock_init(&s->lock); s->magic = CM_MAGIC; s->dev = pcidev; @@ -3184,71 +3227,61 @@ static int __devinit cm_probe(struct pci_dev *pcidev, const struct pci_device_id } #endif #ifdef CONFIG_SOUND_CMPCI_MIDI + switch (s->iomidi) { + case 0x330: + reg_mask = 0; + break; + case 0x320: + reg_mask = 0x20; + break; + case 0x310: + reg_mask = 0x40; + break; + case 0x300: + reg_mask = 0x60; + break; + default: + s->iomidi = 0; + goto skip_mpu; + } + ports = request_region(s->iomidi, 2, "mpu401"); + if (!ports) + goto skip_mpu; /* disable MPU-401 */ maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x04, 0); s->mpu_data.name = "cmpci mpu"; s->mpu_data.io_base = s->iomidi; s->mpu_data.irq = -s->irq; // tell mpu401 to share irq - if (probe_mpu401(&s->mpu_data)) + if (probe_mpu401(&s->mpu_data, ports)) { + release_region(s->iomidi, 2); s->iomidi = 0; - if (s->iomidi) { - /* set IO based at 0x330 */ - switch (s->iomidi) { - case 0x330: - reg_mask = 0; - break; - case 0x320: - reg_mask = 0x20; - break; - case 0x310: - reg_mask = 0x40; - break; - case 0x300: - reg_mask = 0x60; - break; - default: - s->iomidi = 0; + goto skip_mpu; + } + maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0x60, reg_mask); + /* enable MPU-401 */ + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04); + /* clear all previously received interrupt */ + for (timeout = 900000; timeout > 0; timeout--) { + if ((inb(s->iomidi + 1) && 0x80) == 0) + inb(s->iomidi); + else break; - } - maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0x60, reg_mask); - /* enable MPU-401 */ - if (s->iomidi) { - int timeout; - - maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04); - /* clear all previously received interrupt */ - for (timeout = 900000; timeout > 0; timeout--) { - if ((inb(s->iomidi + 1) && 0x80) == 0) - inb(s->iomidi); - else - break; - } - if (!probe_mpu401(&s->mpu_data)) { - s->iomidi = 0; - maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04); - } else { - attach_mpu401(&s->mpu_data, THIS_MODULE); - s->midi_devc = s->mpu_data.slots[1]; - } - } } -#endif -#ifdef CONFIG_SOUND_CMPCI_JOYSTICK - /* enable joystick */ - if (joystick) { - s->gameport.io = 0x200; - if (!request_region(s->gameport.io, CM_EXTENT_GAME, "cmpci GAME")) { - printk(KERN_ERR "cmpci: gameport io ports in use\n"); - s->gameport.io = 0; - } else { - maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x02); - gameport_register_port(&s->gameport); - } + if (!probe_mpu401(&s->mpu_data, ports)) { + release_region(s->iomidi, 2); + s->iomidi = 0; + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04); } else { - maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0); - s->gameport.io = 0; + attach_mpu401(&s->mpu_data, THIS_MODULE); + s->midi_devc = s->mpu_data.slots[1]; } +skip_mpu: #endif + /* disable joystick port */ + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0); + if (joystick) + cm_create_gameport(s, 0x200); + /* store it in the driver field */ pci_set_drvdata(pcidev, s); /* put it into driver list */ @@ -3282,13 +3315,9 @@ static void __devexit cm_remove(struct pci_dev *dev) if (!s) return; -#ifdef CONFIG_SOUND_CMPCI_JOYSTICK - if (s->gameport.io) { - gameport_unregister_port(&s->gameport); - release_region(s->gameport.io, CM_EXTENT_GAME); - maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0); - } -#endif + + cm_free_gameport(s); + #ifdef CONFIG_SOUND_CMPCI_FM if (s->iosynth) { /* disable FM */ @@ -3339,7 +3368,7 @@ static struct pci_driver cm_driver = { static int __init init_cmpci(void) { printk(KERN_INFO "cmpci: version $Revision: 6.82 $ time " __TIME__ " " __DATE__ "\n"); - return pci_module_init(&cm_driver); + return pci_register_driver(&cm_driver); } static void __exit cleanup_cmpci(void)