patch-1.3.69 linux/drivers/sound/dmabuf.c
Next file: linux/drivers/sound/gus_card.c
Previous file: linux/drivers/sound/dev_table.h
Back to the patch index
Back to the overall index
- Lines: 368
- Date:
Fri Feb 23 14:54:55 1996
- Orig file:
v1.3.68/linux/drivers/sound/dmabuf.c
- Orig date:
Wed Feb 14 14:37:14 1996
diff -u --recursive --new-file v1.3.68/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c
@@ -44,25 +44,24 @@
{
{0}};
+#define NEUTRAL8 0x80
+#define NEUTRAL16 0x00
+
static int ndmaps = 0;
#define MAX_DMAP (MAX_AUDIO_DEV*2)
static struct dma_buffparms dmaps[MAX_DMAP] =
{
- {0}}; /*
+ {0}};
- * Primitive way to allocate
- * such a large array.
- * Needs dynamic run-time alloction.
- */
static int space_in_queue (int dev);
static void dma_reset_output (int dev);
static void dma_reset_input (int dev);
static void
-reorganize_buffers (int dev, struct dma_buffparms *dmap)
+reorganize_buffers (int dev, struct dma_buffparms *dmap, int recording)
{
/*
* This routine breaks the physical device buffers to logical ones.
@@ -81,9 +80,9 @@
sz = dsp_dev->ioctl (dev, SOUND_PCM_READ_BITS, 0, 1);
if (sz == 8)
- dmap->neutral_byte = 0x80;
+ dmap->neutral_byte = NEUTRAL8;
else
- dmap->neutral_byte = 0x00;
+ dmap->neutral_byte = NEUTRAL16;
if (sr < 1 || nc < 1 || sz < 1)
{
@@ -118,11 +117,13 @@
*/
if (dmap->subdivision == 0) /* Not already set */
-#ifdef V35A9_COMPATIBLE
- dmap->subdivision = 1; /* Init to the default value */
-#else
- dmap->subdivision = 4; /* Init to the default value */
+ {
+ dmap->subdivision = 1; /* Init to the default value */
+#ifndef V35A9_COMPATIBLE
+ if (recording)
+ dmap->subdivision = 4; /* Use shorter fragments when recording */
#endif
+ }
bsz /= dmap->subdivision;
@@ -155,12 +156,16 @@
dmap->nbufs = n;
dmap->bytes_in_use = n * bsz;
+ memset (dmap->raw_buf,
+ dmap->neutral_byte,
+ dmap->bytes_in_use);
+
for (i = 0; i < dmap->nbufs; i++)
{
dmap->counts[i] = 0;
}
- dmap->flags |= DMA_ALLOC_DONE;
+ dmap->flags |= DMA_ALLOC_DONE | DMA_EMPTY;
}
static void
@@ -182,7 +187,7 @@
dmap->dma_mode = DMODE_NONE;
dmap->mapping_flags = 0;
- dmap->neutral_byte = 0x80;
+ dmap->neutral_byte = NEUTRAL8;
dmap->cfrag = -1;
dmap->closing = 0;
}
@@ -320,7 +325,7 @@
restore_flags (flags);
dma_init_buffers (dev, audio_devs[dev]->dmap_out);
- reorganize_buffers (dev, audio_devs[dev]->dmap_out);
+ reorganize_buffers (dev, audio_devs[dev]->dmap_out, 0);
}
static void
@@ -338,7 +343,7 @@
restore_flags (flags);
dma_init_buffers (dev, audio_devs[dev]->dmap_in);
- reorganize_buffers (dev, audio_devs[dev]->dmap_in);
+ reorganize_buffers (dev, audio_devs[dev]->dmap_in, 1);
}
static int
@@ -354,8 +359,10 @@
save_flags (flags);
cli ();
+ audio_devs[dev]->dmap_out->underrun_count = 0;
while (!current_got_fatal_signal ()
- && audio_devs[dev]->dmap_out->qlen)
+ && audio_devs[dev]->dmap_out->qlen
+ && audio_devs[dev]->dmap_out->underrun_count == 0)
{
{
@@ -472,7 +479,7 @@
}
if (!(dmap->flags & DMA_ALLOC_DONE))
- reorganize_buffers (dev, dmap);
+ reorganize_buffers (dev, dmap, 1);
if (!dmap->dma_mode)
{
@@ -517,7 +524,7 @@
}
else if (!dmap->qlen)
{
- int timeout;
+ int tmout;
if ((err = activate_recording (dev, dmap)) < 0)
{
@@ -541,16 +548,16 @@
}
if (!audio_devs[dev]->go)
- timeout = 0;
+ tmout = 0;
else
- timeout = 2 * HZ;
+ tmout = 2 * HZ;
{
unsigned long tl;
- if (timeout)
- current_set_timeout (tl = jiffies + (timeout));
+ if (tmout)
+ current_set_timeout (tl = jiffies + (tmout));
else
tl = (unsigned long) -1;
in_sleep_flag[dev].mode = WK_SLEEP;
@@ -709,6 +716,7 @@
}
}
+
int
DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
{
@@ -730,7 +738,7 @@
case SNDCTL_DSP_GETBLKSIZE:
if (!(dmap_out->flags & DMA_ALLOC_DONE))
- reorganize_buffers (dev, dmap_out);
+ reorganize_buffers (dev, dmap_out, 0);
return snd_ioctl_return ((int *) arg, dmap_out->fragment_size);
break;
@@ -784,7 +792,7 @@
return -EINVAL;
if (!(dmap->flags & DMA_ALLOC_DONE))
- reorganize_buffers (dev, dmap);
+ reorganize_buffers (dev, dmap, (cmd == SNDCTL_DSP_GETISPACE));
info->fragstotal = dmap->nbufs;
@@ -846,8 +854,16 @@
if ((changed & bits) & PCM_ENABLE_INPUT && audio_devs[dev]->go)
{
+ int err;
+
if (!(dmap_in->flags & DMA_ALLOC_DONE))
- reorganize_buffers (dev, dmap_in);
+ {
+ reorganize_buffers (dev, dmap_in, 1);
+ }
+
+ if ((err = audio_devs[dev]->prepare_for_input (dev,
+ dmap_in->fragment_size, dmap_in->nbufs)) < 0)
+ return -err;
activate_recording (dev, dmap_in);
}
@@ -856,8 +872,16 @@
dmap_out->mapping_flags & DMA_MAP_MAPPED &&
audio_devs[dev]->go)
{
+ int err;
+
if (!(dmap_out->flags & DMA_ALLOC_DONE))
- reorganize_buffers (dev, dmap_out);
+ {
+ reorganize_buffers (dev, dmap_out, 0);
+ }
+
+ if ((err = audio_devs[dev]->prepare_for_output (dev,
+ dmap_out->fragment_size, dmap_out->nbufs)) < 0)
+ return -err;
dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size;
DMAbuf_start_output (dev, 0, dmap_out->fragment_size);
@@ -1009,10 +1033,10 @@
dma_reset_output (dev);
}
- dmap->flags &= ~DMA_RESTART;
+ dmap->flags &= ~(DMA_RESTART | DMA_EMPTY);
if (!(dmap->flags & DMA_ALLOC_DONE))
- reorganize_buffers (dev, dmap);
+ reorganize_buffers (dev, dmap, 0);
if (!dmap->dma_mode)
{
@@ -1031,7 +1055,7 @@
while (!space_in_queue (dev) &&
!abort)
{
- int timeout;
+ int tmout;
if (dontblock)
{
@@ -1050,16 +1074,16 @@
* Wait for free space
*/
if (!audio_devs[dev]->go)
- timeout = 0;
+ tmout = 0;
else
- timeout = 2 * HZ;
+ tmout = 2 * HZ;
{
unsigned long tl;
- if (timeout)
- current_set_timeout (tl = jiffies + (timeout));
+ if (tmout)
+ current_set_timeout (tl = jiffies + (tmout));
else
tl = (unsigned long) -1;
out_sleep_flag[dev].mode = WK_SLEEP;
@@ -1094,11 +1118,6 @@
*buf = dmap->raw_buf + dmap->qtail * dmap->fragment_size;
*size = dmap->fragment_size;
-#if 1
- memset (*buf,
- dmap->neutral_byte,
- *size);
-#endif
dmap->counts[dmap->qtail] = 0;
return dmap->qtail;
@@ -1160,6 +1179,14 @@
dev, dmap->qlen, dmap->nbufs);
dmap->counts[dmap->qtail] = l;
+ if (l < dmap->fragment_size)
+ {
+ int p = dmap->fragment_size * dmap->qtail;
+
+ memset (dmap->raw_buf + p + l,
+ dmap->neutral_byte,
+ dmap->fragment_size - l);
+ }
if ((l != dmap->fragment_size) &&
((audio_devs[dev]->flags & DMA_AUTOMODE) &&
@@ -1266,6 +1293,41 @@
return mem_start;
}
+static void
+polish_buffers (struct dma_buffparms *dmap)
+{
+ int i;
+
+ if (dmap->cfrag < 0)
+ {
+ memset (dmap->raw_buf,
+ dmap->neutral_byte,
+ dmap->bytes_in_use);
+ return;
+ }
+
+ for (i = 0; i < dmap->nbufs; i++)
+ {
+ int p, l;
+
+ p = dmap->fragment_size * i;
+
+ if (i == dmap->cfrag)
+ {
+ l = dmap->fragment_size - dmap->counts[i];
+ }
+ else
+ l = dmap->fragment_size;
+
+ if (l)
+ {
+ memset (dmap->raw_buf + p,
+ dmap->neutral_byte,
+ l);
+ }
+ }
+}
+
void
DMAbuf_outputintr (int dev, int event_type)
{
@@ -1291,12 +1353,6 @@
if (dmap->mapping_flags & DMA_MAP_MAPPED)
{
/* mmapped access */
- int p;
-
- p = dmap->fragment_size * dmap->qhead;
- memset (dmap->raw_buf + p,
- dmap->neutral_byte,
- dmap->fragment_size);
dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
dmap->qlen++; /* Yes increment it (don't decrement) */
@@ -1334,17 +1390,19 @@
/* Ignore underrun. Just move the tail pointer forward and go */
if (dmap->closing)
{
+ polish_buffers (dmap);
audio_devs[dev]->halt_xfer (dev);
}
else
{
dmap->qlen++;
- dmap->cfrag = -1;
dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
- memset (audio_devs[dev]->dmap_out->raw_buf,
- audio_devs[dev]->dmap_out->neutral_byte,
- audio_devs[dev]->dmap_out->bytes_in_use);
+ if (!(dmap->flags & DMA_EMPTY))
+ polish_buffers (dmap);
+
+ dmap->cfrag = -1;
+ dmap->flags |= DMA_EMPTY;
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this