diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
commit | db7d4daea91e105e3859cf461d7e53b9b77454b2 (patch) | |
tree | 9bb65b95440af09e8aca63abe56970dd3360cc57 /drivers/sbus/audio/audio.c | |
parent | 9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff) |
Merge with Linux 2.2.8.
Diffstat (limited to 'drivers/sbus/audio/audio.c')
-rw-r--r-- | drivers/sbus/audio/audio.c | 64 |
1 files changed, 51 insertions, 13 deletions
diff --git a/drivers/sbus/audio/audio.c b/drivers/sbus/audio/audio.c index 36d925daf..b02101941 100644 --- a/drivers/sbus/audio/audio.c +++ b/drivers/sbus/audio/audio.c @@ -7,6 +7,7 @@ * * Mixer code adapted from code contributed by and * Copyright (C) 1998 Michael Mraka (michael@fi.muni.cz) + * and with fixes from Michael Shuey (shuey@ecn.purdue.edu) * The mixer code cheats; Sparc hardware doesn't generally allow independent * line control, and this fakes it badly. * @@ -136,7 +137,7 @@ int register_sparcaudio_driver(struct sparcaudio_driver *drv, int duplex) drv->output_buffer = kmalloc((drv->output_buffer_size * drv->num_output_buffers), - GFP_KERNEL); + (GFP_DMA | GFP_KERNEL)); if (!drv->output_buffer) goto kmalloc_failed2; /* Allocate the pages for each output buffer. */ @@ -167,7 +168,7 @@ int register_sparcaudio_driver(struct sparcaudio_driver *drv, int duplex) if (duplex == 1) { drv->input_buffer = kmalloc((drv->input_buffer_size * drv->num_input_buffers), - GFP_KERNEL); + (GFP_DMA | GFP_KERNEL)); if (!drv->input_buffer) goto kmalloc_failed4; for (i = 0; i < drv->num_input_buffers; i++) { @@ -628,19 +629,43 @@ static ssize_t sparcaudio_write(struct file * file, const char *buf, #define MONO_DEVICES (SOUND_MASK_SPEAKER | SOUND_MASK_MIC) static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned int *arg) { struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> SPARCAUDIO_DEVICE_SHIFT)]; - unsigned long i = 0, j = 0, k = 0; - - k = (unsigned long) &arg; + unsigned long i = 0, j = 0; + unsigned int k; + + if(cmd == SOUND_MIXER_INFO) { + audio_device_t tmp; + mixer_info info; + int retval = -EINVAL; + + if(drv->ops->sunaudio_getdev) { + drv->ops->sunaudio_getdev(drv, &tmp); + memset(&info, 0, sizeof(info)); + strncpy(info.id, tmp.name, sizeof(info.id)); + strncpy(info.name, "Sparc Audio", sizeof(info.name)); + + /* XXX do this right... */ + info.modify_counter = 0; + + if(copy_to_user((char *)arg, &info, sizeof(info))) + retval = -EFAULT; + else + retval = 0; + } + return retval; + } switch (cmd) { case SOUND_MIXER_WRITE_RECLEV: case SOUND_MIXER_WRITE_MIC: case SOUND_MIXER_WRITE_CD: case SOUND_MIXER_WRITE_LINE: + case SOUND_MIXER_WRITE_IMIX: + if(get_user(k, arg)) + return -EFAULT; tprintk(("setting input volume (0x%x)", k)); if (drv->ops->get_input_channels) j = drv->ops->get_input_channels(drv); @@ -670,6 +695,8 @@ static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, case SOUND_MIXER_WRITE_PCM: case SOUND_MIXER_WRITE_VOLUME: case SOUND_MIXER_WRITE_SPEAKER: + if(get_user(k, arg)) + return -EFAULT; tprintk(("setting output volume (0x%x)", k)); if (drv->ops->get_output_channels) j = drv->ops->get_output_channels(drv); @@ -709,10 +736,13 @@ static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, case SOUND_MIXER_WRITE_RECSRC: if (!drv->ops->set_input_port) return -EINVAL; - if (arg & SOUND_MASK_IMIX) j |= AUDIO_ANALOG_LOOPBACK; - if (arg & SOUND_MASK_CD) j |= AUDIO_CD; - if (arg & SOUND_MASK_LINE) j |= AUDIO_LINE_IN; - if (arg & SOUND_MASK_MIC) j |= AUDIO_MICROPHONE; + if(get_user(k, arg)) + return -EFAULT; + /* only one should ever be selected */ + if (k & SOUND_MASK_IMIX) j = AUDIO_ANALOG_LOOPBACK; + if (k & SOUND_MASK_CD) j = AUDIO_CD; + if (k & SOUND_MASK_LINE) j = AUDIO_LINE_IN; + if (k & SOUND_MASK_MIC) j = AUDIO_MICROPHONE; tprintk(("setting inport to %d\n", j)); i = drv->ops->set_input_port(drv, j); @@ -768,11 +798,12 @@ static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, j = drv->ops->get_output_balance(drv); i = b_to_s(i,j); } - return COPY_OUT((int *)arg, i); + return COPY_OUT(arg, i); case SOUND_MIXER_READ_RECLEV: case SOUND_MIXER_READ_MIC: case SOUND_MIXER_READ_CD: case SOUND_MIXER_READ_LINE: + case SOUND_MIXER_READ_IMIX: if (drv->ops->get_input_channels) j = drv->ops->get_input_channels(drv); if (j == 1) { @@ -786,7 +817,7 @@ static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, j = drv->ops->get_input_balance(drv); i = b_to_s(i,j); } - return COPY_OUT((int *)arg, i); + return COPY_OUT(arg, i); default: return -EINVAL; } @@ -840,7 +871,7 @@ static int sparcaudio_ioctl(struct inode * inode, struct file * file, switch (minor & 0xf) { case SPARCAUDIO_MIXER_MINOR: - return sparcaudio_mixer_ioctl(inode, file, cmd, arg); + return sparcaudio_mixer_ioctl(inode, file, cmd, (unsigned int *)arg); case SPARCAUDIO_DSP16_MINOR: case SPARCAUDIO_DSP_MINOR: case SPARCAUDIO_AUDIO_MINOR: @@ -1022,12 +1053,14 @@ static int sparcaudio_ioctl(struct inode * inode, struct file * file, break; } } else if (k == 16) { + switch (j) { case AUDIO_ENCODING_LINEAR: i = AFMT_S16_BE; break; case AUDIO_ENCODING_LINEARLE: i = AFMT_S16_LE; break; + } } COPY_OUT(arg, i); break; @@ -1873,6 +1906,11 @@ static int sparcaudio_open(struct inode * inode, struct file * file) if (!drv) return -ENODEV; +#ifdef S_ZERO_WR + /* This is how 2.0 ended up dealing with 0 len writes */ + inode->i_flags |= S_ZERO_WR; +#endif + switch (minor & 0xf) { case SPARCAUDIO_AUDIOCTL_MINOR: file->f_op = &sparcaudioctl_fops; |