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