patch-2.1.6 linux/drivers/sound/audio.c
Next file: linux/drivers/sound/configure.c
Previous file: linux/drivers/sound/aedsp16.c
Back to the patch index
Back to the overall index
- Lines: 344
- Date:
Tue Oct 29 09:43:46 1996
- Orig file:
v2.1.5/linux/drivers/sound/audio.c
- Orig date:
Wed Oct 16 10:48:23 1996
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/audio.c linux/drivers/sound/audio.c
@@ -7,7 +7,7 @@
/*
* Copyright (C) by Hannu Savolainen 1993-1996
*
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
*/
@@ -31,11 +31,13 @@
#define AM_WRITE 1
#define AM_READ 2
+
static int audio_format[MAX_AUDIO_DEV];
static int local_conversion[MAX_AUDIO_DEV];
+#define CNV_MU_LAW 0x00000001
static int
-set_format (int dev, long fmt)
+set_format (int dev, int fmt)
{
if (fmt != AFMT_QUERY)
{
@@ -46,12 +48,12 @@
if (fmt == AFMT_MU_LAW)
{
fmt = AFMT_U8;
- local_conversion[dev] = AFMT_MU_LAW;
+ local_conversion[dev] = CNV_MU_LAW;
}
else
fmt = AFMT_U8; /* This is always supported */
- audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) fmt, 1);
+ audio_format[dev] = audio_devs[dev]->d->set_bits (dev, fmt);
}
if (local_conversion[dev]) /* This shadows the HW format */
@@ -64,7 +66,7 @@
audio_open (int dev, struct fileinfo *file)
{
int ret;
- long bits;
+ int bits;
int dev_type = dev & 0x0f;
int mode = file->mode & O_ACCMODE;
@@ -75,6 +77,9 @@
else
bits = 8;
+ if (dev < 0 || dev >= num_audiodevs)
+ return -ENXIO;
+
if ((ret = DMAbuf_open (dev, mode)) < 0)
return ret;
@@ -90,11 +95,8 @@
local_conversion[dev] = 0;
- if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) bits, 1) != bits)
+ if (audio_devs[dev]->d->set_bits (dev, bits) != bits)
{
- printk ("audio: Can't set number of bits on device %d\n", dev);
- audio_release (dev, file);
- return -(ENXIO);
}
if (dev_type == SND_DEV_AUDIO)
@@ -107,6 +109,7 @@
audio_mode[dev] = AM_NONE;
dev_nblock[dev] = 0;
+
return ret;
}
@@ -119,6 +122,13 @@
if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
{
+ int i, n = buf_size & 3;
+
+ if (n) /* Not 4 byte aligned */
+ {
+ for (i = 0; i < n; i++)
+ dma_buf[buf_ptr++] = dmap->neutral_byte;
+ }
DMAbuf_start_output (dev, buf_no, buf_ptr);
}
@@ -130,11 +140,10 @@
for (i = dmap->qlen + 1; i < dmap->nbufs; i++)
{
+ p = (p + 1) % dmap->nbufs;
memset (dmap->raw_buf + p * dmap->fragment_size,
dmap->neutral_byte,
dmap->fragment_size);
-
- p = (p + 1) % dmap->nbufs;
}
dmap->flags |= DMA_CLEAN;
@@ -225,7 +234,7 @@
dev_nblock[dev])) < 0)
{
/* Handle nonblocking mode */
- if (dev_nblock[dev] && buf_no == -(EAGAIN))
+ if (dev_nblock[dev] && buf_no == -EAGAIN)
return p; /* No more space. Return # of accepted bytes */
return buf_no;
}
@@ -236,17 +245,18 @@
if (l > (buf_size - buf_ptr))
l = (buf_size - buf_ptr);
- if (!audio_devs[dev]->d->copy_from_user)
+
+ if (!audio_devs[dev]->d->copy_user)
{ /*
* No device specific copy routine
*/
copy_from_user (&dma_buf[buf_ptr], &(buf)[p], l);
}
else
- audio_devs[dev]->d->copy_from_user (dev,
- dma_buf, buf_ptr, buf, p, l);
+ audio_devs[dev]->d->copy_user (dev,
+ dma_buf, buf_ptr, buf, p, l);
- if (local_conversion[dev] == AFMT_MU_LAW)
+ if (local_conversion[dev] & CNV_MU_LAW)
{
/*
* This just allows interrupts while the conversion is running
@@ -303,7 +313,7 @@
{
/* Nonblocking mode handling. Return current # of bytes */
- if (dev_nblock[dev] && buf_no == -(EAGAIN))
+ if (dev_nblock[dev] && buf_no == -EAGAIN)
return p;
return buf_no;
@@ -316,7 +326,7 @@
* Insert any local processing here.
*/
- if (local_conversion[dev] == AFMT_MU_LAW)
+ if (local_conversion[dev] & CNV_MU_LAW)
{
/*
* This just allows interrupts while the conversion is running
@@ -326,7 +336,11 @@
translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
}
- copy_to_user (&(buf)[p], dmabuf, l);
+ {
+ char *fixit = dmabuf;
+
+ copy_to_user (&(buf)[p], fixit, l);
+ };
DMAbuf_rmchars (dev, buf_no, l);
@@ -341,6 +355,9 @@
audio_ioctl (int dev, struct fileinfo *file,
unsigned int cmd, caddr_t arg)
{
+ int val;
+
+/* printk("audio_ioctl(%x, %x)\n", cmd, arg); */
dev = dev >> 4;
@@ -351,7 +368,7 @@
else
printk ("/dev/dsp%d: No coprocessor for this device\n", dev);
- return -(ENXIO);
+ return -ENXIO;
}
else
switch (cmd)
@@ -361,33 +378,39 @@
return 0;
sync_output (dev);
- return DMAbuf_ioctl (dev, cmd, arg, 0);
+ DMAbuf_sync (dev);
+ DMAbuf_reset (dev);
+ return 0;
break;
case SNDCTL_DSP_POST:
if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
return 0;
+ audio_devs[dev]->dmap_out->flags |= DMA_POST;
sync_output (dev);
+ DMAbuf_ioctl (dev, SNDCTL_DSP_POST, 0, 1);
return 0;
break;
case SNDCTL_DSP_RESET:
audio_mode[dev] = AM_NONE;
- return DMAbuf_ioctl (dev, cmd, arg, 0);
+ DMAbuf_reset (dev);
+ return 0;
break;
case SNDCTL_DSP_GETFMTS:
- return snd_ioctl_return ((int *) arg, audio_devs[dev]->format_mask | AFMT_MU_LAW);
+ return ioctl_out (arg, audio_devs[dev]->format_mask);
break;
case SNDCTL_DSP_SETFMT:
- return snd_ioctl_return ((int *) arg, set_format (dev, get_user ((int *) arg)));
+ get_user (val, (int *) arg);
+ return ioctl_out (arg, set_format (dev, val));
case SNDCTL_DSP_GETISPACE:
if (!(audio_devs[dev]->open_mode & OPEN_READ))
return 0;
if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
- return -(EBUSY);
+ return -EBUSY;
{
audio_buf_info info;
@@ -397,7 +420,11 @@
if (err < 0)
return err;
- copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+ {
+ char *fixit = (char *) &info;
+
+ copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+ };
return 0;
}
@@ -405,7 +432,7 @@
if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
return -EPERM;
if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
- return -(EBUSY);
+ return -EBUSY;
{
audio_buf_info info;
@@ -420,7 +447,11 @@
if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
info.bytes -= buf_ptr;
- copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+ {
+ char *fixit = (char *) &info;
+
+ copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+ };
return 0;
}
@@ -447,18 +478,64 @@
info |= DSP_CAP_MMAP;
- copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+ {
+ char *fixit = (char *) &info;
+
+ copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+ };
return 0;
}
break;
+ case SOUND_PCM_WRITE_RATE:
+ get_user (val, (int *) arg);
+ return ioctl_out (arg, audio_devs[dev]->d->set_speed (dev, val));
+
+ case SOUND_PCM_READ_RATE:
+ return ioctl_out (arg, audio_devs[dev]->d->set_speed (dev, 0));
+
+ case SNDCTL_DSP_STEREO:
+ {
+ int n;
+
+ get_user (n, (int *) arg);
+ if (n > 1)
+ {
+ printk ("sound: SNDCTL_DSP_STEREO called with invalid argument %d\n",
+ n);
+ return ioctl_out (arg, audio_devs[dev]->d->set_channels (dev, n));
+ }
+
+ if (n < 0)
+ return -EINVAL;
+
+ return ioctl_out (arg, audio_devs[dev]->d->set_channels (dev, n + 1) - 1);
+ }
+
+ case SOUND_PCM_WRITE_CHANNELS:
+ get_user (val, (int *) arg);
+ return ioctl_out (arg, audio_devs[dev]->d->set_channels (dev, val));
+
+ case SOUND_PCM_READ_CHANNELS:
+ return ioctl_out (arg, audio_devs[dev]->d->set_channels (dev, 0));
+
+ case SOUND_PCM_READ_BITS:
+ return ioctl_out (arg, audio_devs[dev]->d->set_bits (dev, 0));
+
+ case SNDCTL_DSP_SETDUPLEX:
+ if (audio_devs[dev]->flags & DMA_DUPLEX)
+ return 0;
+ else
+ return -EIO;
+ break;
+
default:
return DMAbuf_ioctl (dev, cmd, arg, 0);
}
}
void
-audio_init (void)
+audio_init_devices (void)
{
/*
* NOTE! This routine could be called several times during boot.
@@ -466,7 +543,7 @@
}
int
-audio_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
+audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
{
char *dma_buf;
int buf_no, buf_ptr, buf_size;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov