X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Foss%2Ftrident.c;h=2813e4c8e365aafb6bc6b364b671c8d2e4720b10;hb=7172c64a7cee4dfa95864f49c914f7ea8cf497c8;hp=8395501af2ae140988e76f666f38bff192a3fd2d;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/sound/oss/trident.c b/sound/oss/trident.c index 8395501af..2813e4c8e 100644 --- a/sound/oss/trident.c +++ b/sound/oss/trident.c @@ -190,11 +190,10 @@ * * Lock order (high->low) * lock - hardware lock - * open_sem - guard opens + * open_mutex - guard opens * sem - guard dmabuf, write re-entry etc */ -#include #include #include #include @@ -216,6 +215,8 @@ #include #include #include +#include + #include #include #include @@ -228,6 +229,10 @@ #define DRIVER_VERSION "0.14.10j-2.6" +#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#define SUPPORT_JOYSTICK 1 +#endif + /* magic numbers to protect our data structures */ #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ @@ -274,16 +279,14 @@ static char *card_names[] = { }; static struct pci_device_id trident_pci_tbl[] = { - {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_DX}, - {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_NX}, - {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018}, - {PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, ALI_5451}, - {PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, CYBER5050}, + {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX), + PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TRIDENT_4D_DX}, + {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX), + 0, 0, TRIDENT_4D_NX}, + {PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, SIS_7018}, + {PCI_DEVICE(PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451), 0, 0, ALI_5451}, + {PCI_DEVICE(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050), + 0, 0, CYBER5050}, {0,} }; @@ -347,7 +350,7 @@ struct trident_state { unsigned chans_num; unsigned long fmt_flag; /* Guard against mmap/write/read races */ - struct semaphore sem; + struct mutex sem; }; @@ -400,7 +403,7 @@ struct trident_card { struct trident_card *next; /* single open lock mechanism, only used for recording */ - struct semaphore open_sem; + struct mutex open_mutex; /* The trident has a certain amount of cross channel interaction so we use a single per card lock */ @@ -441,7 +444,7 @@ struct trident_card { struct timer_list timer; /* Game port support */ - struct gameport gameport; + struct gameport *gameport; }; enum dmabuf_mode { @@ -487,7 +490,7 @@ static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *ca static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card); static void ali_restore_regs(struct trident_card *card); static void ali_save_regs(struct trident_card *card); -static int trident_suspend(struct pci_dev *dev, u32 unused); +static int trident_suspend(struct pci_dev *dev, pm_message_t unused); static int trident_resume(struct pci_dev *dev); static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel); static int ali_setup_multi_channels(struct trident_card *card, int chan_nums); @@ -1879,7 +1882,7 @@ trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; - down(&state->sem); + mutex_lock(&state->sem); if (!dmabuf->ready && (ret = prog_dmabuf_record(state))) goto out; @@ -1911,7 +1914,7 @@ trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos goto out; } - up(&state->sem); + mutex_unlock(&state->sem); /* No matter how much space left in the buffer, */ /* we have to wait until CSO == ESO/2 or CSO == ESO */ /* when address engine interrupts */ @@ -1938,7 +1941,7 @@ trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos ret = -ERESTARTSYS; goto out; } - down(&state->sem); + mutex_lock(&state->sem); if (dmabuf->mapped) { if (!ret) ret = -ENXIO; @@ -1966,7 +1969,7 @@ trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos start_adc(state); } out: - up(&state->sem); + mutex_unlock(&state->sem); return ret; } @@ -1994,7 +1997,7 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t * Guard against an mmap or ioctl while writing */ - down(&state->sem); + mutex_lock(&state->sem); if (dmabuf->mapped) { ret = -ENXIO; @@ -2043,7 +2046,7 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); tmo >>= sample_shift[dmabuf->fmt]; unlock_set_fmt(state); - up(&state->sem); + mutex_unlock(&state->sem); /* There are two situations when sleep_on_timeout */ /* returns, one is when the interrupt is serviced */ @@ -2071,7 +2074,7 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t ret = -ERESTARTSYS; goto out_nolock; } - down(&state->sem); + mutex_lock(&state->sem); if (dmabuf->mapped) { if (!ret) ret = -ENXIO; @@ -2129,7 +2132,7 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t start_dac(state); } out: - up(&state->sem); + mutex_unlock(&state->sem); out_nolock: return ret; } @@ -2150,24 +2153,24 @@ trident_poll(struct file *file, struct poll_table_struct *wait) * prog_dmabuf events */ - down(&state->sem); + mutex_lock(&state->sem); if (file->f_mode & FMODE_WRITE) { if (!dmabuf->ready && prog_dmabuf_playback(state)) { - up(&state->sem); + mutex_unlock(&state->sem); return 0; } poll_wait(file, &dmabuf->wait, wait); } if (file->f_mode & FMODE_READ) { if (!dmabuf->ready && prog_dmabuf_record(state)) { - up(&state->sem); + mutex_unlock(&state->sem); return 0; } poll_wait(file, &dmabuf->wait, wait); } - up(&state->sem); + mutex_unlock(&state->sem); spin_lock_irqsave(&state->card->lock, flags); trident_update_ptr(state); @@ -2205,7 +2208,7 @@ trident_mmap(struct file *file, struct vm_area_struct *vma) * a read or write against an mmap. */ - down(&state->sem); + mutex_lock(&state->sem); if (vma->vm_flags & VM_WRITE) { if ((ret = prog_dmabuf_playback(state)) != 0) @@ -2230,7 +2233,7 @@ trident_mmap(struct file *file, struct vm_area_struct *vma) dmabuf->mapped = 1; ret = 0; out: - up(&state->sem); + mutex_unlock(&state->sem); return ret; } @@ -2427,15 +2430,15 @@ trident_ioctl(struct inode *inode, struct file *file, unlock_set_fmt(state); break; } - down(&state->card->open_sem); + mutex_lock(&state->card->open_mutex); ret = ali_allocate_other_states_resources(state, 6); if (ret < 0) { - up(&state->card->open_sem); + mutex_unlock(&state->card->open_mutex); unlock_set_fmt(state); break; } state->card->multi_channel_use_count++; - up(&state->card->open_sem); + mutex_unlock(&state->card->open_mutex); } else val = 2; /*yield to 2-channels */ } else @@ -2725,11 +2728,11 @@ trident_open(struct inode *inode, struct file *file) /* find an available virtual channel (instance of /dev/dsp) */ while (card != NULL) { - down(&card->open_sem); + mutex_lock(&card->open_mutex); if (file->f_mode & FMODE_READ) { /* Skip opens on cards that are in 6 channel mode */ if (card->multi_channel_use_count > 0) { - up(&card->open_sem); + mutex_unlock(&card->open_mutex); card = card->next; continue; } @@ -2738,16 +2741,16 @@ trident_open(struct inode *inode, struct file *file) if (card->states[i] == NULL) { state = card->states[i] = kmalloc(sizeof(*state), GFP_KERNEL); if (state == NULL) { - up(&card->open_sem); + mutex_unlock(&card->open_mutex); return -ENOMEM; } memset(state, 0, sizeof(*state)); - init_MUTEX(&state->sem); + mutex_init(&state->sem); dmabuf = &state->dmabuf; goto found_virt; } } - up(&card->open_sem); + mutex_unlock(&card->open_mutex); card = card->next; } /* no more virtual channel avaiable */ @@ -2814,7 +2817,7 @@ trident_open(struct inode *inode, struct file *file) } state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); - up(&card->open_sem); + mutex_unlock(&card->open_mutex); pr_debug("trident: open virtual channel %d, hard channel %d\n", state->virt, dmabuf->channel->num); @@ -2843,7 +2846,7 @@ trident_release(struct inode *inode, struct file *file) state->virt, dmabuf->channel->num); /* stop DMA state machine and free DMA buffers/channels */ - down(&card->open_sem); + mutex_lock(&card->open_mutex); if (file->f_mode & FMODE_WRITE) { stop_dac(state); @@ -2876,8 +2879,8 @@ trident_release(struct inode *inode, struct file *file) card->states[state->virt] = NULL; kfree(state); - /* we're covered by the open_sem */ - up(&card->open_sem); + /* we're covered by the open_mutex */ + mutex_unlock(&card->open_mutex); return 0; } @@ -3723,7 +3726,7 @@ ali_restore_regs(struct trident_card *card) } static int -trident_suspend(struct pci_dev *dev, u32 unused) +trident_suspend(struct pci_dev *dev, pm_message_t unused) { struct trident_card *card = pci_get_drvdata(dev); @@ -4252,26 +4255,27 @@ trident_ac97_init(struct trident_card *card) return num_ac97 + 1; } +#ifdef SUPPORT_JOYSTICK /* Gameport functions for the cards ADC gameport */ -static unsigned char -trident_game_read(struct gameport *gameport) +static unsigned char trident_game_read(struct gameport *gameport) { - struct trident_card *card = gameport->driver; + struct trident_card *card = gameport->port_data; + return inb(TRID_REG(card, T4D_GAME_LEG)); } -static void -trident_game_trigger(struct gameport *gameport) +static void trident_game_trigger(struct gameport *gameport) { - struct trident_card *card = gameport->driver; + struct trident_card *card = gameport->port_data; + outb(0xff, TRID_REG(card, T4D_GAME_LEG)); } -static int -trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) +static int trident_game_cooked_read(struct gameport *gameport, + int *axes, int *buttons) { - struct trident_card *card = gameport->driver; + struct trident_card *card = gameport->port_data; int i; *buttons = (~inb(TRID_REG(card, T4D_GAME_LEG)) >> 4) & 0xf; @@ -4285,10 +4289,9 @@ trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) return 0; } -static int -trident_game_open(struct gameport *gameport, int mode) +static int trident_game_open(struct gameport *gameport, int mode) { - struct trident_card *card = gameport->driver; + struct trident_card *card = gameport->port_data; switch (mode) { case GAMEPORT_MODE_COOKED: @@ -4305,6 +4308,41 @@ trident_game_open(struct gameport *gameport, int mode) return 0; } +static int __devinit trident_register_gameport(struct trident_card *card) +{ + struct gameport *gp; + + card->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "trident: can not allocate memory for gameport\n"); + return -ENOMEM; + } + + gameport_set_name(gp, "Trident 4DWave"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(card->pci_dev)); + gp->read = trident_game_read; + gp->trigger = trident_game_trigger; + gp->cooked_read = trident_game_cooked_read; + gp->open = trident_game_open; + gp->fuzz = 64; + gp->port_data = card; + + gameport_register_port(gp); + + return 0; +} + +static inline void trident_unregister_gameport(struct trident_card *card) +{ + if (card->gameport) + gameport_unregister_port(card->gameport); +} + +#else +static inline int trident_register_gameport(struct trident_card *card) { return -ENOSYS; } +static inline void trident_unregister_gameport(struct trident_card *card) { } +#endif /* SUPPORT_JOYSTICK */ + /* install the driver, we do not allocate hardware channel nor DMA buffer */ /* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ /* open/read/write/ioctl/mmap) */ @@ -4368,14 +4406,7 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) card->banks[BANK_B].addresses = &bank_b_addrs; card->banks[BANK_B].bitmap = 0UL; - card->gameport.driver = card; - card->gameport.fuzz = 64; - card->gameport.read = trident_game_read; - card->gameport.trigger = trident_game_trigger; - card->gameport.cooked_read = trident_game_cooked_read; - card->gameport.open = trident_game_open; - - init_MUTEX(&card->open_sem); + mutex_init(&card->open_mutex); spin_lock_init(&card->lock); init_timer(&card->timer); @@ -4441,7 +4472,7 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) /* claim our irq */ rc = -ENODEV; - if (request_irq(card->irq, &trident_interrupt, SA_SHIRQ, + if (request_irq(card->irq, &trident_interrupt, IRQF_SHARED, card_names[pci_id->driver_data], card)) { printk(KERN_ERR "trident: unable to allocate irq %d\n", card->irq); @@ -4508,7 +4539,7 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) trident_enable_loop_interrupts(card); /* Register gameport */ - gameport_register_port(&card->gameport); + trident_register_gameport(card); out: return rc; @@ -4551,7 +4582,7 @@ trident_remove(struct pci_dev *pci_dev) } /* Unregister gameport */ - gameport_unregister_port(&card->gameport); + trident_unregister_gameport(card); /* Kill interrupts, and SP/DIF */ trident_disable_loop_interrupts(card);