Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Add recording support for emuxki(4). The patch ...
details: https://anonhg.NetBSD.org/src/rev/5e7d418b383c
branches: trunk
changeset: 543438:5e7d418b383c
user: toshii <toshii%NetBSD.org@localhost>
date: Tue Feb 25 08:48:24 2003 +0000
description:
Add recording support for emuxki(4). The patch is basically the same
as I submitted in PR kern/18093. Some of the patch needs refinement.
Also, only the ADC recording source is supported, because the other
sources are probably much less useful and the implementation isn't
trivial.
diffstat:
sys/dev/pci/emuxki.c | 311 +++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 241 insertions(+), 70 deletions(-)
diffs (truncated from 529 to 300 lines):
diff -r 07843d43a5eb -r 5e7d418b383c sys/dev/pci/emuxki.c
--- a/sys/dev/pci/emuxki.c Tue Feb 25 08:09:30 2003 +0000
+++ b/sys/dev/pci/emuxki.c Tue Feb 25 08:48:24 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: emuxki.c,v 1.18 2003/02/22 04:57:48 tsutsui Exp $ */
+/* $NetBSD: emuxki.c,v 1.19 2003/02/25 08:48:24 toshii Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -57,7 +57,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.18 2003/02/22 04:57:48 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.19 2003/02/25 08:48:24 toshii Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -142,6 +142,7 @@
struct audio_params *,
struct audio_params *);
+static int emuxki_round_blocksize(void *, int);
static size_t emuxki_round_buffersize(void *, int, size_t);
static int emuxki_trigger_output(void *, void *, void *, int,
@@ -186,7 +187,7 @@
NULL, /* drain */
emuxki_query_encoding,
emuxki_set_params,
- NULL, /* round blocksize */
+ emuxki_round_blocksize,
NULL, /* commit settings */
NULL, /* init_output */
NULL, /* init_input */
@@ -210,6 +211,23 @@
NULL, /* dev_ioctl */
};
+static const int emuxki_recsrc_adcrates[] =
+ { 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000, -1 };
+static const int emuxki_recsrc_intrmasks[EMU_NUMRECSRCS] =
+ { EMU_INTE_MICBUFENABLE, EMU_INTE_ADCBUFENABLE, EMU_INTE_EFXBUFENABLE };
+static const u_int32_t emuxki_recsrc_bufaddrreg[EMU_NUMRECSRCS] =
+ { EMU_MICBA, EMU_ADCBA, EMU_FXBA };
+static const u_int32_t emuxki_recsrc_idxreg[EMU_NUMRECSRCS] =
+ { EMU_RECIDX(EMU_MICIDX), EMU_RECIDX(EMU_ADCIDX), EMU_RECIDX(EMU_FXIDX) };
+static const u_int32_t emuxki_recsrc_szreg[EMU_NUMRECSRCS] =
+ { EMU_MICBS, EMU_ADCBS, EMU_FXBS };
+static const int emuxki_recbuf_sz[] = {
+ 0, 384, 448, 512, 640, 768, 896, 1024, 1280, 1536, 1792,
+ 2048, 2560, 3072, 3584, 4096, 5120, 6144, 7168, 8192, 10240,
+ 12288, 14366, 16384, 20480, 24576, 28672, 32768, 40960, 49152,
+ 57344, 65536
+};
+
/*
* Dma memory mgmt
*/
@@ -402,8 +420,16 @@
aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
if (emuxki_scinit(sc) || emuxki_ac97_init(sc) ||
- (sc->sc_audev = audio_attach_mi(&emuxki_hw_if, sc, self)) == NULL)
+ (sc->sc_audev = audio_attach_mi(&emuxki_hw_if, sc, self)) == NULL) {
emuxki_pci_shutdown(sc);
+ return;
+ }
+#if 0
+ sc->rsourcectl.dev =
+ sc->codecif->vtbl->get_portnum_by_name(sc->codec_if, AudioCrecord,
+ AudioNsource, NULL);
+ sc->rsourcectl.cp = AUDIO_MIXER_ENUM;
+#endif
}
static int
@@ -600,6 +626,15 @@
EMU_DSP_OUTR(EMU_DSP_OUT_AC97),
EMU_DSP_FX(1), EMU_DSP_CST(4));
#endif
+ /* ADC recording (l/r) = AC97 In (l/r) */
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
+ EMU_DSP_OUTL(EMU_DSP_OUT_ADC),
+ EMU_DSP_INL(EMU_DSP_IN_AC97),
+ EMU_DSP_CST(0), EMU_DSP_CST(0));
+ emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
+ EMU_DSP_OUTR(EMU_DSP_OUT_ADC),
+ EMU_DSP_INR(EMU_DSP_IN_AC97),
+ EMU_DSP_CST(0), EMU_DSP_CST(0));
/* zero out the rest of the microcode */
while (pc < 512)
emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
@@ -1181,16 +1216,36 @@
/*
* Will come back when used in voice_dataloc_create
*/
-#if 0
static int
emuxki_recsrc_reserve(struct emuxki_voice *voice, emuxki_recsrc_t source)
{
- if (voice->emu->recsrc[source] != NULL)
+ if (source < 0 || source >= EMU_NUMRECSRCS) {
+#ifdef EMUXKI_DEBUG
+ printf("Tryed to reserve invalid source: %d\n", source);
+#endif
+ return (EINVAL);
+ }
+ if (voice->sc->recsrc[source] == voice)
+ return (0); /* XXX */
+ if (voice->sc->recsrc[source] != NULL)
return (EBUSY);
- voice->emu->recsrc[source] = voice;
+ voice->sc->recsrc[source] = voice;
return (0);
}
-#endif
+
+static int
+emuxki_recsrc_rate_to_index(int srate)
+{
+ int index;
+
+ for(index = 0; ; index++) {
+ if (emuxki_recsrc_adcrates[index] == srate)
+ return (index);
+
+ if (emuxki_recsrc_adcrates[index] < 0)
+ return (-1);
+ }
+}
/* When calling this function we assume the voice is stopped */
static void
@@ -1208,16 +1263,9 @@
if ((error = emuxki_voice_channel_create(voice)))
return (error);
} else {
- /*
- * Commented out because i don't know how to get the selected
- * recording source
- */
-#if 0
- if (emuxki_recsrc_reserve(voice, recsrc))
- return (EBUSY);
- printf("Which rec src do i have to create!!!\n");
-#endif
- return (EBUSY); /* just return an error, no real meaning */
+ if ((error =
+ emuxki_recsrc_reserve(voice, voice->dataloc.source)))
+ return (error);
}
return (0);
}
@@ -1248,25 +1296,25 @@
sc->lvoice = NULL;
splx(s);
- if (!voice) {
+ if (!voice)
if (!(voice = malloc(sizeof(*voice), M_DEVBUF, M_WAITOK)))
return (NULL);
- voice->sc = sc;
- voice->state = !EMU_VOICE_STATE_STARTED;
- voice->stereo = EMU_VOICE_STEREO_NOTSET;
- voice->b16 = 0;
- voice->sample_rate = 0;
- if (use & EMU_VOICE_USE_PLAY)
- voice->dataloc.chan[0] = voice->dataloc.chan[0] = NULL;
- else
- voice->dataloc.source = EMU_RECSRC_NOTSET;
- voice->buffer = NULL;
- voice->blksize = 0;
- voice->trigblk = 0;
- voice->blkmod = 0;
- voice->inth = NULL;
- voice->inthparam = NULL;
- }
+
+ voice->sc = sc;
+ voice->state = !EMU_VOICE_STATE_STARTED;
+ voice->stereo = EMU_VOICE_STEREO_NOTSET;
+ voice->b16 = 0;
+ voice->sample_rate = 0;
+ if (use & EMU_VOICE_USE_PLAY)
+ voice->dataloc.chan[0] = voice->dataloc.chan[1] = NULL;
+ else
+ voice->dataloc.source = EMU_RECSRC_NOTSET;
+ voice->buffer = NULL;
+ voice->blksize = 0;
+ voice->trigblk = 0;
+ voice->blkmod = 0;
+ voice->inth = NULL;
+ voice->inthparam = NULL;
voice->use = use;
s = splaudio();
@@ -1302,9 +1350,14 @@
emuxki_voice_set_stereo(struct emuxki_voice *voice, u_int8_t stereo)
{
int error;
+ emuxki_recsrc_t source;
struct emuxki_chanparms_fxsend fxsend;
+ if (! (voice->use & EMU_VOICE_USE_PLAY))
+ source = voice->dataloc.source;
emuxki_voice_dataloc_destroy(voice);
+ if (! (voice->use & EMU_VOICE_USE_PLAY))
+ voice->dataloc.source = source;
voice->stereo = stereo;
if ((error = emuxki_voice_dataloc_create(voice)))
return (error);
@@ -1339,10 +1392,9 @@
emuxki_channel_set_srate(voice->dataloc.chan[1],
srate);
} else {
-#ifdef EMUXKI_DEBUG
- printf("Recording voice set_srate not implemented\n");
-#endif
- return (EINVAL);
+ if (emuxki_recsrc_rate_to_index(srate) < 0)
+ return (EINVAL);
+ voice->sample_rate = srate;
}
return (0);
}
@@ -1382,6 +1434,7 @@
struct emuxki_channel **chan;
u_int32_t start, end;
u_int8_t sample_size;
+ int idx;
int error = EFAULT;
LIST_FOREACH(mem, &voice->sc->mem, next) {
@@ -1390,7 +1443,6 @@
voice->buffer = mem;
sample_size = (voice->b16 + 1) * (voice->stereo + 1);
- voice->blksize = blksize / sample_size;
voice->trigblk = 0; /* This shouldn't be needed */
voice->blkmod = bufsize / blksize;
if (bufsize % blksize) /* This should not happen */
@@ -1398,6 +1450,7 @@
error = 0;
if (voice->use & EMU_VOICE_USE_PLAY) {
+ voice->blksize = blksize / sample_size;
chan = voice->dataloc.chan;
start = mem->ptbidx << 12;
end = start + bufsize / sample_size;
@@ -1411,10 +1464,33 @@
if (voice->timerate < 5)
error = EINVAL;
} else {
+ voice->blksize = blksize;
+ for(idx = sizeof(emuxki_recbuf_sz) /
+ sizeof(emuxki_recbuf_sz[0]); --idx >= 0;)
+ if (emuxki_recbuf_sz[idx] == bufsize)
+ break;
+ if (idx < 0) {
#ifdef EMUXKI_DEBUG
- printf("Rec voice set bufparms not implemented\n");
+ printf("Invalid bufsize: %d\n", bufsize);
#endif
- error = ENODEV;
+ return (EINVAL);
+ }
+ emuxki_write(voice->sc, 0,
+ emuxki_recsrc_szreg[voice->dataloc.source], idx);
+ emuxki_write(voice->sc, 0,
+ emuxki_recsrc_bufaddrreg[voice->dataloc.source],
+ DMAADDR(mem->dmamem));
+
+ /* Use timer to emulate DMA completion interrupt */
+ voice->timerate = (u_int32_t) 48000 * blksize /
+ (voice->sample_rate * sample_size);
+ if (voice->timerate < 5) {
+#ifdef EMUXKI_DEBUG
+ printf("Invalid timerate: %d, blksize %d\n",
+ voice->timerate, blksize);
+#endif
+ error = EINVAL;
+ }
}
break;
@@ -1436,11 +1512,24 @@
static u_int32_t
emuxki_voice_curaddr(struct emuxki_voice *voice)
{
+
+ /* XXX different semantics in these cases */
if (voice->use & EMU_VOICE_USE_PLAY)
+ /* returns number of samples (an l/r pair counts 1) */
return (emuxki_read(voice->sc,
voice->dataloc.chan[0]->num,
EMU_CHAN_CCCA_CURRADDR) -
voice->dataloc.chan[0]->loop.start);
+ else
+ /* returns number of bytes */
Home |
Main Index |
Thread Index |
Old Index