diff options
Diffstat (limited to 'sound/oss/swarm_cs4297a.c')
| -rw-r--r-- | sound/oss/swarm_cs4297a.c | 153 |
1 files changed, 96 insertions, 57 deletions
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index df4d3771fa8..a33e8ce8085 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c @@ -69,13 +69,13 @@ #include <linux/sound.h> #include <linux/slab.h> #include <linux/soundcard.h> -#include <linux/ac97_codec.h> #include <linux/pci.h> #include <linux/bitops.h> #include <linux/interrupt.h> #include <linux/init.h> #include <linux/poll.h> -#include <linux/smp_lock.h> +#include <linux/mutex.h> +#include <linux/kernel.h> #include <asm/byteorder.h> #include <asm/dma.h> @@ -90,8 +90,11 @@ #include <asm/sibyte/sb1250_mac.h> #include <asm/sibyte/sb1250.h> +#include "sleep.h" + struct cs4297a_state; +static DEFINE_MUTEX(swarm_cs4297a_mutex); static void stop_dac(struct cs4297a_state *s); static void stop_adc(struct cs4297a_state *s); static void start_dac(struct cs4297a_state *s); @@ -109,9 +112,6 @@ static void start_adc(struct cs4297a_state *s); // rather than 64k as some of the games work more responsively. // log base 2( buff sz = 32k). -//static unsigned long defaultorder = 3; -//MODULE_PARM(defaultorder, "i"); - // // Turn on/off debugging compilation by commenting out "#define CSDEBUG" // @@ -153,8 +153,8 @@ static void start_adc(struct cs4297a_state *s); #if CSDEBUG static unsigned long cs_debuglevel = 4; // levels range from 1-9 static unsigned long cs_debugmask = CS_INIT /*| CS_IOCTL*/; -MODULE_PARM(cs_debuglevel, "i"); -MODULE_PARM(cs_debugmask, "i"); +module_param(cs_debuglevel, int, 0); +module_param(cs_debugmask, int, 0); #endif #define CS_TRUE 1 #define CS_FALSE 0 @@ -200,6 +200,22 @@ static const char invalid_magic[] = } \ }) +/* AC97 registers */ +#define AC97_MASTER_VOL_STEREO 0x0002 /* Line Out */ +#define AC97_PCBEEP_VOL 0x000a /* none */ +#define AC97_PHONE_VOL 0x000c /* TAD Input (mono) */ +#define AC97_MIC_VOL 0x000e /* MIC Input (mono) */ +#define AC97_LINEIN_VOL 0x0010 /* Line Input (stereo) */ +#define AC97_CD_VOL 0x0012 /* CD Input (stereo) */ +#define AC97_AUX_VOL 0x0016 /* Aux Input (stereo) */ +#define AC97_PCMOUT_VOL 0x0018 /* Wave Output (stereo) */ +#define AC97_RECORD_SELECT 0x001a /* */ +#define AC97_RECORD_GAIN 0x001c +#define AC97_GENERAL_PURPOSE 0x0020 +#define AC97_3D_CONTROL 0x0022 +#define AC97_POWER_CONTROL 0x0026 +#define AC97_VENDOR_ID1 0x007c + struct list_head cs4297a_devs = { &cs4297a_devs, &cs4297a_devs }; typedef struct serdma_descr_s { @@ -291,10 +307,10 @@ struct cs4297a_state { unsigned conversion:1; // conversion from 16 to 8 bit in progress unsigned ena; spinlock_t lock; - struct semaphore open_sem; - struct semaphore open_sem_adc; - struct semaphore open_sem_dac; - mode_t open_mode; + struct mutex open_mutex; + struct mutex open_sem_adc; + struct mutex open_sem_dac; + fmode_t open_mode; wait_queue_head_t open_wait; wait_queue_head_t open_wait_adc; wait_queue_head_t open_wait_dac; @@ -614,25 +630,23 @@ static int init_serdma(serdma_t *dma) /* Descriptors */ dma->ringsz = DMA_DESCR; - dma->descrtab = kmalloc(dma->ringsz * sizeof(serdma_descr_t), GFP_KERNEL); + dma->descrtab = kzalloc(dma->ringsz * sizeof(serdma_descr_t), GFP_KERNEL); if (!dma->descrtab) { - printk(KERN_ERR "cs4297a: kmalloc descrtab failed\n"); + printk(KERN_ERR "cs4297a: kzalloc descrtab failed\n"); return -1; } - memset(dma->descrtab, 0, dma->ringsz * sizeof(serdma_descr_t)); dma->descrtab_end = dma->descrtab + dma->ringsz; /* XXX bloddy mess, use proper DMA API here ... */ dma->descrtab_phys = CPHYSADDR((long)dma->descrtab); dma->descr_add = dma->descr_rem = dma->descrtab; /* Frame buffer area */ - dma->dma_buf = kmalloc(DMA_BUF_SIZE, GFP_KERNEL); + dma->dma_buf = kzalloc(DMA_BUF_SIZE, GFP_KERNEL); if (!dma->dma_buf) { - printk(KERN_ERR "cs4297a: kmalloc dma_buf failed\n"); + printk(KERN_ERR "cs4297a: kzalloc dma_buf failed\n"); kfree(dma->descrtab); return -1; } - memset(dma->dma_buf, 0, DMA_BUF_SIZE); dma->dma_buf_phys = CPHYSADDR((long)dma->dma_buf); /* Samples buffer area */ @@ -724,7 +738,7 @@ static int serdma_reg_access(struct cs4297a_state *s, u64 data) serdma_t *d = &s->dma_dac; u64 *data_p; unsigned swptr; - int flags; + unsigned long flags; serdma_descr_t *descr; if (s->reg_request) { @@ -736,7 +750,7 @@ static int serdma_reg_access(struct cs4297a_state *s, u64 data) /* Since a writer has the DSP open, we have to mux the request in */ s->reg_request = data; - interruptible_sleep_on(&s->dma_dac.reg_wait); + oss_broken_sleep_on(&s->dma_dac.reg_wait, MAX_SCHEDULE_TIMEOUT); /* XXXKW how can I deal with the starvation case where the opener isn't writing? */ } else { @@ -778,7 +792,7 @@ static int cs4297a_read_ac97(struct cs4297a_state *s, u32 offset, if (serdma_reg_access(s, (0xCLL << 60) | (1LL << 47) | ((u64)(offset & 0x7F) << 40))) return -1; - interruptible_sleep_on(&s->dma_adc.reg_wait); + oss_broken_sleep_on(&s->dma_adc.reg_wait, MAX_SCHEDULE_TIMEOUT); *value = s->read_value; CS_DBGOUT(CS_AC97, 2, printk(KERN_INFO "cs4297a: rdr reg %x -> %x\n", s->read_reg, s->read_value)); @@ -878,7 +892,7 @@ static void start_adc(struct cs4297a_state *s) if (s->prop_adc.fmt & AFMT_S8 || s->prop_adc.fmt & AFMT_U8) { // // now only use 16 bit capture, due to truncation issue - // in the chip, noticable distortion occurs. + // in the chip, noticeable distortion occurs. // allocate buffer and then convert from 16 bit to // 8 bit for the user buffer. // @@ -1538,6 +1552,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file) CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()+\n")); + mutex_lock(&swarm_cs4297a_mutex); list_for_each(entry, &cs4297a_devs) { s = list_entry(entry, struct cs4297a_state, list); @@ -1548,6 +1563,8 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file) { CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2, printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- -ENODEV\n")); + + mutex_unlock(&swarm_cs4297a_mutex); return -ENODEV; } VALIDATE_STATE(s); @@ -1555,6 +1572,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file) CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- 0\n")); + mutex_unlock(&swarm_cs4297a_mutex); return nonseekable_open(inode, file); } @@ -1570,21 +1588,25 @@ static int cs4297a_release_mixdev(struct inode *inode, struct file *file) } -static int cs4297a_ioctl_mixdev(struct inode *inode, struct file *file, +static int cs4297a_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg) { - return mixer_ioctl((struct cs4297a_state *) file->private_data, cmd, + int ret; + mutex_lock(&swarm_cs4297a_mutex); + ret = mixer_ioctl((struct cs4297a_state *) file->private_data, cmd, arg); + mutex_unlock(&swarm_cs4297a_mutex); + return ret; } // ****************************************************************************************** // Mixer file operations struct. // ****************************************************************************************** -static /*const */ struct file_operations cs4297a_mixer_fops = { +static const struct file_operations cs4297a_mixer_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .ioctl = cs4297a_ioctl_mixdev, + .unlocked_ioctl = cs4297a_ioctl_mixdev, .open = cs4297a_open_mixdev, .release = cs4297a_release_mixdev, }; @@ -1720,7 +1742,7 @@ static ssize_t cs4297a_read(struct file *file, char *buffer, size_t count, start_adc(s); if (file->f_flags & O_NONBLOCK) return ret ? ret : -EAGAIN; - interruptible_sleep_on(&s->dma_adc.wait); + oss_broken_sleep_on(&s->dma_adc.wait, MAX_SCHEDULE_TIMEOUT); if (signal_pending(current)) return ret ? ret : -ERESTARTSYS; continue; @@ -1816,7 +1838,7 @@ static ssize_t cs4297a_write(struct file *file, const char *buffer, start_dac(s); if (file->f_flags & O_NONBLOCK) return ret ? ret : -EAGAIN; - interruptible_sleep_on(&d->wait); + oss_broken_sleep_on(&d->wait, MAX_SCHEDULE_TIMEOUT); if (signal_pending(current)) return ret ? ret : -ERESTARTSYS; continue; @@ -1948,7 +1970,7 @@ static int cs4297a_mmap(struct file *file, struct vm_area_struct *vma) } -static int cs4297a_ioctl(struct inode *inode, struct file *file, +static int cs4297a_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cs4297a_state *s = @@ -2201,7 +2223,9 @@ static int cs4297a_ioctl(struct inode *inode, struct file *file, sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_NONBLOCK: + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; case SNDCTL_DSP_GETODELAY: @@ -2339,6 +2363,16 @@ static int cs4297a_ioctl(struct inode *inode, struct file *file, return mixer_ioctl(s, cmd, arg); } +static long cs4297a_unlocked_ioctl(struct file *file, u_int cmd, u_long arg) +{ + int ret; + + mutex_lock(&swarm_cs4297a_mutex); + ret = cs4297a_ioctl(file, cmd, arg); + mutex_unlock(&swarm_cs4297a_mutex); + + return ret; +} static int cs4297a_release(struct inode *inode, struct file *file) { @@ -2352,26 +2386,26 @@ static int cs4297a_release(struct inode *inode, struct file *file) if (file->f_mode & FMODE_WRITE) { drain_dac(s, file->f_flags & O_NONBLOCK); - down(&s->open_sem_dac); + mutex_lock(&s->open_sem_dac); stop_dac(s); dealloc_dmabuf(s, &s->dma_dac); s->open_mode &= ~FMODE_WRITE; - up(&s->open_sem_dac); + mutex_unlock(&s->open_sem_dac); wake_up(&s->open_wait_dac); } if (file->f_mode & FMODE_READ) { drain_adc(s, file->f_flags & O_NONBLOCK); - down(&s->open_sem_adc); + mutex_lock(&s->open_sem_adc); stop_adc(s); dealloc_dmabuf(s, &s->dma_adc); s->open_mode &= ~FMODE_READ; - up(&s->open_sem_adc); + mutex_unlock(&s->open_sem_adc); wake_up(&s->open_wait_adc); } return 0; } -static int cs4297a_open(struct inode *inode, struct file *file) +static int cs4297a_locked_open(struct inode *inode, struct file *file) { int minor = iminor(inode); struct cs4297a_state *s=NULL; @@ -2413,37 +2447,37 @@ static int cs4297a_open(struct inode *inode, struct file *file) ; } - down(&s->open_sem_dac); + mutex_lock(&s->open_sem_dac); while (s->open_mode & FMODE_WRITE) { if (file->f_flags & O_NONBLOCK) { - up(&s->open_sem_dac); + mutex_unlock(&s->open_sem_dac); return -EBUSY; } - up(&s->open_sem_dac); - interruptible_sleep_on(&s->open_wait_dac); + mutex_unlock(&s->open_sem_dac); + oss_broken_sleep_on(&s->open_wait_dac, MAX_SCHEDULE_TIMEOUT); if (signal_pending(current)) { printk("open - sig pending\n"); return -ERESTARTSYS; } - down(&s->open_sem_dac); + mutex_lock(&s->open_sem_dac); } } if (file->f_mode & FMODE_READ) { - down(&s->open_sem_adc); + mutex_lock(&s->open_sem_adc); while (s->open_mode & FMODE_READ) { if (file->f_flags & O_NONBLOCK) { - up(&s->open_sem_adc); + mutex_unlock(&s->open_sem_adc); return -EBUSY; } - up(&s->open_sem_adc); - interruptible_sleep_on(&s->open_wait_adc); + mutex_unlock(&s->open_sem_adc); + oss_broken_sleep_on(&s->open_wait_adc, MAX_SCHEDULE_TIMEOUT); if (signal_pending(current)) { printk("open - sig pending\n"); return -ERESTARTSYS; } - down(&s->open_sem_adc); + mutex_lock(&s->open_sem_adc); } } s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); @@ -2456,7 +2490,7 @@ static int cs4297a_open(struct inode *inode, struct file *file) s->ena &= ~FMODE_READ; s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0; - up(&s->open_sem_adc); + mutex_unlock(&s->open_sem_adc); if (prog_dmabuf_adc(s)) { CS_DBGOUT(CS_OPEN | CS_ERROR, 2, printk(KERN_ERR @@ -2474,7 +2508,7 @@ static int cs4297a_open(struct inode *inode, struct file *file) s->ena &= ~FMODE_WRITE; s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0; - up(&s->open_sem_dac); + mutex_unlock(&s->open_sem_dac); if (prog_dmabuf_dac(s)) { CS_DBGOUT(CS_OPEN | CS_ERROR, 2, printk(KERN_ERR @@ -2488,23 +2522,33 @@ static int cs4297a_open(struct inode *inode, struct file *file) return nonseekable_open(inode, file); } +static int cs4297a_open(struct inode *inode, struct file *file) +{ + int ret; + + mutex_lock(&swarm_cs4297a_mutex); + ret = cs4297a_open(inode, file); + mutex_unlock(&swarm_cs4297a_mutex); + + return ret; +} // ****************************************************************************************** // Wave (audio) file operations struct. // ****************************************************************************************** -static /*const */ struct file_operations cs4297a_audio_fops = { +static const struct file_operations cs4297a_audio_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .read = cs4297a_read, .write = cs4297a_write, .poll = cs4297a_poll, - .ioctl = cs4297a_ioctl, + .unlocked_ioctl = cs4297a_unlocked_ioctl, .mmap = cs4297a_mmap, .open = cs4297a_open, .release = cs4297a_release, }; -static void cs4297a_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static void cs4297a_interrupt(int irq, void *dev_id) { struct cs4297a_state *s = (struct cs4297a_state *) dev_id; u32 status; @@ -2581,15 +2625,12 @@ static int __init cs4297a_init(void) u32 pwr, id; mm_segment_t fs; int rval; -#ifndef CONFIG_BCM_CS4297A_CSWARM u64 cfg; int mdio_val; -#endif CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO "cs4297a: cs4297a_init_module()+ \n")); -#ifndef CONFIG_BCM_CS4297A_CSWARM mdio_val = __raw_readq(KSEG1 + A_MAC_REGISTER(2, R_MAC_MDIO)) & (M_MAC_MDIO_DIR|M_MAC_MDIO_OUT); @@ -2615,14 +2656,12 @@ static int __init cs4297a_init(void) __raw_writeq(mdio_val | M_MAC_GENC, KSEG1+A_MAC_REGISTER(2, R_MAC_MDIO)); /* Give the codec some time to finish resetting (start the bit clock) */ udelay(100); -#endif - if (!(s = kmalloc(sizeof(struct cs4297a_state), GFP_KERNEL))) { + if (!(s = kzalloc(sizeof(struct cs4297a_state), GFP_KERNEL))) { CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR "cs4297a: probe() no memory for state struct.\n")); return -1; } - memset(s, 0, sizeof(struct cs4297a_state)); s->magic = CS4297a_MAGIC; init_waitqueue_head(&s->dma_adc.wait); init_waitqueue_head(&s->dma_dac.wait); @@ -2631,8 +2670,8 @@ static int __init cs4297a_init(void) init_waitqueue_head(&s->open_wait); init_waitqueue_head(&s->open_wait_adc); init_waitqueue_head(&s->open_wait_dac); - init_MUTEX(&s->open_sem_adc); - init_MUTEX(&s->open_sem_dac); + mutex_init(&s->open_sem_adc); + mutex_init(&s->open_sem_dac); spin_lock_init(&s->lock); s->irq = K_INT_SER_1; @@ -2675,7 +2714,7 @@ static int __init cs4297a_init(void) #if 0 val = SOUND_MASK_LINE; mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long) &val); - for (i = 0; i < sizeof(initvol) / sizeof(initvol[0]); i++) { + for (i = 0; i < ARRAY_SIZE(initvol); i++) { val = initvol[i].vol; mixer_ioctl(s, initvol[i].mixch, (unsigned long) &val); } |
