The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/interwave.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: interwave.c,v 1.33 2008/04/28 20:23:50 martin Exp $    */
    2 
    3 /*
    4  * Copyright (c) 1997, 1999 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * Author: Kari Mettinen
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   28  * POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __KERNEL_RCSID(0, "$NetBSD: interwave.c,v 1.33 2008/04/28 20:23:50 martin Exp $");
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/errno.h>
   37 #include <sys/ioctl.h>
   38 #include <sys/syslog.h>
   39 #include <sys/device.h>
   40 #include <sys/proc.h>
   41 #include <sys/buf.h>
   42 #include <sys/fcntl.h>
   43 #include <sys/malloc.h>
   44 #include <sys/kernel.h>
   45 
   46 #include <sys/cpu.h>
   47 #include <sys/intr.h>
   48 #include <machine/pio.h>
   49 #include <sys/audioio.h>
   50 #include <dev/audio_if.h>
   51 #include <dev/mulaw.h>
   52 
   53 #include <dev/isa/isavar.h>
   54 #include <dev/isa/isadmavar.h>
   55 
   56 #include <dev/ic/interwavereg.h>
   57 #include <dev/ic/interwavevar.h>
   58 
   59 
   60 static void iwreset(struct iw_softc *, int);
   61 
   62 static int iw_set_speed(struct iw_softc *, u_long, char);
   63 static u_long iw_set_format(struct iw_softc *, u_long, int);
   64 static void iw_mixer_line_level(struct iw_softc *, int, int, int);
   65 static void iw_trigger_dma(struct iw_softc *, u_char);
   66 static void iw_stop_dma(struct iw_softc *, u_char, u_char);
   67 static void iw_dma_count(struct iw_softc *, u_short, int);
   68 static int iwintr(void *);
   69 static void iw_meminit(struct iw_softc *);
   70 static void iw_mempoke(struct iw_softc *, u_long, u_char);
   71 static u_char iw_mempeek(struct iw_softc *, u_long);
   72 
   73 #ifdef USE_WAVETABLE
   74 static void iw_set_voice_place(struct iw_softc *, u_char, u_long);
   75 static void iw_voice_pan(struct iw_softc *, u_char, u_short, u_short);
   76 static void iw_voice_freq(struct iw_softc *, u_char, u_long);
   77 static void iw_set_loopmode(struct iw_softc *, u_char, u_char, u_char);
   78 static void iw_set_voice_pos(struct iw_softc *, u_short, u_long, u_long);
   79 static void iw_start_voice(struct iw_softc *, u_char);
   80 static void iw_play_voice(struct iw_softc *, u_long, u_long, u_short);
   81 static void iw_stop_voice(struct iw_softc *, u_char);
   82 static void iw_move_voice_end(struct iw_softc *, u_short, u_long);
   83 static void iw_initvoices(struct iw_softc *);
   84 #endif
   85 
   86 struct audio_device iw_device = {
   87         "Am78C201",
   88         "0.1",
   89         "guspnp"
   90 };
   91 
   92 #ifdef AUDIO_DEBUG
   93 int iw_debug;
   94 #define DPRINTF(p)       if (iw_debug) printf p
   95 #else
   96 #define DPRINTF(p)
   97 #endif
   98 
   99 static int      iw_cc = 1;
  100 #ifdef DIAGNOSTIC
  101 static int      outputs = 0;
  102 static int      iw_ints = 0;
  103 static int      inputs = 0;
  104 static int      iw_inints = 0;
  105 #endif
  106 
  107 int
  108 iwintr(void *arg)
  109 {
  110         struct  iw_softc *sc;
  111         int     val;
  112         u_char  intrs;
  113 
  114         sc = arg;
  115         val = 0;
  116         intrs = 0;
  117         IW_READ_DIRECT_1(6, sc->p2xr_h, intrs); /* UISR */
  118 
  119         /* codec ints */
  120 
  121         /*
  122          * The proper order to do this seems to be to read CSR3 to get the
  123          * int cause and fifo over underrrun status, then deal with the ints
  124          * (new DMA set up), and to clear ints by writing the respective bit
  125          * to 0.
  126          */
  127 
  128         /* read what ints happened */
  129 
  130         IW_READ_CODEC_1(CSR3I, intrs);
  131 
  132         /* clear them */
  133 
  134         IW_WRITE_DIRECT_1(2, sc->codec_index_h, 0x00);
  135 
  136         /* and process them */
  137 
  138         if (intrs & 0x20) {
  139 #ifdef DIAGNOSTIC
  140                 iw_inints++;
  141 #endif
  142                 if (sc->sc_recintr != 0)
  143                         sc->sc_recintr(sc->sc_recarg);
  144                 val = 1;
  145         }
  146         if (intrs & 0x10) {
  147 #ifdef DIAGNOSTIC
  148                 iw_ints++;
  149 #endif
  150                 if (sc->sc_playintr != 0)
  151                         sc->sc_playintr(sc->sc_playarg);
  152                 val = 1;
  153         }
  154         return val;
  155 
  156 }
  157 
  158 void
  159 iwattach(struct iw_softc *sc)
  160 {
  161         int     got_irq;
  162 
  163         DPRINTF(("iwattach sc %p\n", sc));
  164         got_irq = 0;
  165 
  166         sc->cdatap = 1;         /* relative offsets in region */
  167         sc->csr1r = 2;
  168         sc->cxdr = 3;           /* CPDR or CRDR */
  169 
  170         sc->gmxr = 0;           /* sc->p3xr */
  171         sc->gmxdr = 1;          /* GMTDR or GMRDR */
  172         sc->svsr = 2;
  173         sc->igidxr = 3;
  174         sc->i16dp = 4;
  175         sc->i8dp = 5;
  176         sc->lmbdr = 7;
  177 
  178         sc->rec_precision = sc->play_precision = 8;
  179         sc->rec_channels = sc->play_channels = 1;
  180         sc->rec_encoding = sc->play_encoding = AUDIO_ENCODING_ULAW;
  181         sc->sc_irate = 8000;
  182         sc->sc_orate = 8000;
  183 
  184         sc->sc_fullduplex = 1;
  185 
  186         sc->sc_dma_flags = 0;
  187 
  188         /*
  189          * We can only use a few selected irqs, see if we got one from pnp
  190          * code that suits us.
  191          */
  192 
  193         if (sc->sc_irq > 0) {
  194                 sc->sc_ih = isa_intr_establish(sc->sc_p2xr_ic,
  195                     sc->sc_irq, IST_EDGE, IPL_AUDIO, iwintr, sc);
  196                 got_irq = 1;
  197         }
  198         if (!got_irq) {
  199                 printf("\niwattach: couldn't get a suitable irq\n");
  200                 return;
  201         }
  202         printf("\n");
  203         iwreset(sc, 0);
  204         iw_set_format(sc, AUDIO_ENCODING_ULAW, 0);
  205         iw_set_format(sc, AUDIO_ENCODING_ULAW, 1);
  206         printf("%s: interwave version %s\n",
  207             device_xname(&sc->sc_dev), iw_device.version);
  208         audio_attach_mi(sc->iw_hw_if, sc, &sc->sc_dev);
  209 }
  210 
  211 int
  212 iwopen(struct iw_softc *sc, int flags)
  213 {
  214 
  215         DPRINTF(("iwopen: sc %p\n", sc));
  216 
  217 #ifdef DIAGNOSTIC
  218         outputs = 0;
  219         iw_ints = 0;
  220         inputs = 0;
  221         iw_inints = 0;
  222 #endif
  223 
  224         iwreset(sc, 1);
  225 
  226         return 0;
  227 }
  228 
  229 void
  230 iwclose(void *addr)
  231 {
  232 
  233         DPRINTF(("iwclose sc %p\n", addr));
  234 #ifdef DIAGNOSTIC
  235         DPRINTF(("iwclose: outputs %d ints %d inputs %d in_ints %d\n",
  236                 outputs, iw_ints, inputs, iw_inints));
  237 #endif
  238 }
  239 
  240 #define RAM_STEP        64*1024
  241 
  242 static void
  243 iw_mempoke(struct iw_softc *sc, u_long addy, u_char val)
  244 {
  245 
  246         IW_WRITE_GENERAL_2(LMALI, (u_short) addy);
  247         IW_WRITE_GENERAL_1(LMAHI, (u_char) (addy >> 16));
  248 
  249         /* Write byte to LMBDR */
  250         IW_WRITE_DIRECT_1(sc->p3xr + 7, sc->p3xr_h, val);
  251 }
  252 
  253 static u_char
  254 iw_mempeek(struct iw_softc *sc, u_long addy)
  255 {
  256         u_char  ret;
  257 
  258         IW_WRITE_GENERAL_2(LMALI, (u_short) addy);
  259         IW_WRITE_GENERAL_1(LMAHI, (u_char) (addy >> 16));
  260 
  261         IW_READ_DIRECT_1(sc->p3xr + 7, sc->p3xr_h, ret);
  262         return ret;             /* return byte from LMBDR */
  263 }
  264 
  265 static void
  266 iw_meminit(struct iw_softc *sc)
  267 {
  268         u_long  bank[4] = {0L, 0L, 0L, 0L};
  269         u_long  addr, base, cnt;
  270         u_char  i, ram /* ,memval=0 */ ;
  271         u_short lmcfi;
  272         u_long  temppi;
  273         u_long  *lpbanks;
  274 
  275         addr = 0L;
  276         base = 0L;
  277         cnt = 0L;
  278         ram = 0;
  279         lpbanks = &temppi;
  280 
  281         IW_WRITE_GENERAL_1(LDMACI, 0x00);
  282 
  283         IW_READ_GENERAL_2(LMCFI, lmcfi);        /* 0x52 */
  284         lmcfi |= 0x0A0C;
  285         IW_WRITE_GENERAL_2(LMCFI, lmcfi);       /* max addr span */
  286         IW_WRITE_GENERAL_1(LMCI, 0x00);
  287 
  288         /* fifo addresses */
  289 
  290         IW_WRITE_GENERAL_2(LMRFAI, ((4 * 1024 * 1024) >> 8));
  291         IW_WRITE_GENERAL_2(LMPFAI, ((4 * 1024 * 1024 + 16 * 1024) >> 8));
  292 
  293         IW_WRITE_GENERAL_2(LMFSI, 0x000);
  294 
  295         IW_WRITE_GENERAL_2(LDICI, 0x0000);
  296 
  297         while (addr < (16 * 1024 * 1024)) {
  298                 iw_mempoke(sc, addr, 0x00);
  299                 addr += RAM_STEP;
  300         }
  301 
  302         printf("%s:", device_xname(&sc->sc_dev));
  303 
  304         for (i = 0; i < 4; i++) {
  305                 iw_mempoke(sc, base, 0xAA);     /* mark start of bank */
  306                 iw_mempoke(sc, base + 1L, 0x55);
  307                 if (iw_mempeek(sc, base) == 0xAA  &&
  308                     iw_mempeek(sc, base + 1L) == 0x55)
  309                         ram = 1;
  310                 if (ram) {
  311                         while (cnt < (4 * 1024 * 1024)) {
  312                                 bank[i] += RAM_STEP;
  313                                 cnt += RAM_STEP;
  314                                 addr = base + cnt;
  315                                 if (iw_mempeek(sc, addr) == 0xAA)
  316                                         break;
  317                         }
  318                 }
  319                 if (lpbanks != NULL) {
  320                         *lpbanks = bank[i];
  321                         lpbanks++;
  322                 }
  323                 bank[i] = bank[i] >> 10;
  324                 printf("%s bank[%d]: %ldK", i ? "," : "", i, bank[i]);
  325                 base += 4 * 1024 * 1024;
  326                 cnt = 0L;
  327                 ram = 0;
  328         }
  329 
  330         printf("\n");
  331 
  332         /*
  333          * this is not really useful since GUS PnP supports memory
  334          * configurations that aren't really supported by Interwave...beware
  335          * of holes! Also, we don't use the memory for anything in this
  336          * version of the driver.
  337          *
  338          * we've configured for 4M-4M-4M-4M
  339          */
  340 }
  341 
  342 static void
  343 iwreset(struct iw_softc *sc, int warm)
  344 {
  345         u_char  reg, cmode, val, mixer_image;
  346 
  347         val = 0;
  348         mixer_image = 0;
  349         reg = 0;                /* XXX gcc -Wall */
  350 
  351         cmode = 0x6c;           /* enhanced codec mode (full duplex) */
  352 
  353         /* reset */
  354 
  355         IW_WRITE_GENERAL_1(URSTI, 0x00);
  356         delay(10);
  357         IW_WRITE_GENERAL_1(URSTI, 0x07);
  358         IW_WRITE_GENERAL_1(ICMPTI, 0x1f);       /* disable DSP and uici and
  359                                                  * udci writes */
  360         IW_WRITE_GENERAL_1(IDECI, 0x7f);        /* enable ints to ISA and
  361                                                  * codec access */
  362         IW_READ_GENERAL_1(IVERI, reg);
  363         IW_WRITE_GENERAL_1(IVERI, reg | 0x01);  /* hidden reg lock disable */
  364         IW_WRITE_GENERAL_1(UASBCI, 0x00);
  365 
  366         /* synth enhanced mode (default), 0 active voices, disable ints */
  367 
  368         IW_WRITE_GENERAL_1(SGMI_WR, 0x01);      /* enhanced mode, LFOs
  369                                                  * disabled */
  370         for (val = 0; val < 32; val++) {
  371                 /* set each synth sound volume to 0 */
  372                 IW_WRITE_DIRECT_1(sc->p3xr + 2, sc->p3xr_h, val);
  373                 IW_WRITE_GENERAL_1(SVSI_WR, 0x00);
  374                 IW_WRITE_GENERAL_2(SASLI_WR, 0x0000);
  375                 IW_WRITE_GENERAL_2(SASHI_WR, 0x0000);
  376                 IW_WRITE_GENERAL_2(SAELI_WR, 0x0000);
  377                 IW_WRITE_GENERAL_2(SAEHI_WR, 0x0000);
  378                 IW_WRITE_GENERAL_2(SFCI_WR, 0x0000);
  379                 IW_WRITE_GENERAL_1(SACI_WR, 0x02);
  380                 IW_WRITE_GENERAL_1(SVSI_WR, 0x00);
  381                 IW_WRITE_GENERAL_1(SVEI_WR, 0x00);
  382                 IW_WRITE_GENERAL_2(SVLI_WR, 0x0000);
  383                 IW_WRITE_GENERAL_1(SVCI_WR, 0x02);
  384                 IW_WRITE_GENERAL_1(SMSI_WR, 0x02);
  385         }
  386 
  387         IW_WRITE_GENERAL_1(SAVI_WR, 0x00);
  388 
  389         /* codec mode/init */
  390 
  391         /* first change mode to 1 */
  392 
  393         IW_WRITE_CODEC_1(CMODEI, 0x00);
  394 
  395         /* and mode 3 */
  396 
  397         IW_WRITE_CODEC_1(CMODEI, cmode);
  398 
  399         IW_READ_CODEC_1(CMODEI, reg);
  400 
  401         DPRINTF(("cmode %x\n", reg));
  402 
  403         sc->revision = ((reg & 0x80) >> 3) | (reg & 0x0f);
  404 
  405         IW_WRITE_DIRECT_1(sc->codec_index + 2, sc->p2xr_h, 0x00);
  406 
  407         IW_WRITE_CODEC_1(CFIG1I | IW_MCE, 0x00);        /* DMA 2 chan access */
  408         IW_WRITE_CODEC_1(CEXTI, 0x00);  /* disable ints for now */
  409 
  410 
  411         IW_WRITE_CODEC_1(CLPCTI, 0x00); /* reset playback sample counters */
  412         IW_WRITE_CODEC_1(CUPCTI, 0x00); /* always upper byte last */
  413         IW_WRITE_CODEC_1(CFIG2I, 0x80); /* full voltage range, enable record
  414                                          * and playback sample counters, and
  415                                          * don't center output in case or
  416                                          * FIFO underrun */
  417         IW_WRITE_CODEC_1(CFIG3I, 0xc0); /* enable record/playback irq (still
  418                                          * turned off from CEXTI), max DMA
  419                                          * rate */
  420         IW_WRITE_CODEC_1(CSR3I, 0x00);  /* clear status 3 reg */
  421 
  422 
  423         IW_WRITE_CODEC_1(CLRCTI, 0x00); /* reset record sample counters */
  424         IW_WRITE_CODEC_1(CURCTI, 0x00); /* always upper byte last */
  425 
  426 
  427         IW_READ_GENERAL_1(IVERI, reg);
  428 
  429         sc->vers = reg >> 4;
  430         if (!warm)
  431                 snprintf(iw_device.version, sizeof(iw_device.version), "%d.%d",
  432                     sc->vers, sc->revision);
  433 
  434         IW_WRITE_GENERAL_1(IDECI, 0x7f);        /* irqs and codec decode
  435                                                  * enable */
  436 
  437 
  438         /* ports */
  439 
  440         if (!warm) {
  441                 iw_mixer_line_level(sc, IW_LINE_OUT, 255, 255);
  442                 iw_mixer_line_level(sc, IW_LINE_IN, 0, 0);
  443                 iw_mixer_line_level(sc, IW_AUX1, 0, 0);
  444                 iw_mixer_line_level(sc, IW_AUX2, 200, 200); /* CD */
  445                 sc->sc_dac.off = 0;
  446                 iw_mixer_line_level(sc, IW_DAC, 200, 200);
  447 
  448                 iw_mixer_line_level(sc, IW_MIC_IN, 0, 0);
  449                 iw_mixer_line_level(sc, IW_REC, 0, 0);
  450                 iw_mixer_line_level(sc, IW_LOOPBACK, 0, 0);
  451                 iw_mixer_line_level(sc, IW_MONO_IN, 0, 0);
  452 
  453                 /* mem stuff */
  454                 iw_meminit(sc);
  455 
  456         }
  457         IW_WRITE_CODEC_1(CEXTI, 0x02);  /* codec int enable */
  458 
  459         /* clear _LDMACI */
  460 
  461         IW_WRITE_GENERAL_1(LDMACI, 0x00);
  462 
  463         /* enable mixer paths */
  464         mixer_image = 0x0c;
  465         IW_WRITE_DIRECT_1(sc->p2xr, sc->p2xr_h, mixer_image);
  466         /*
  467          * enable output, line in. disable mic in bit 0 = 0 -> line in on
  468          * (from codec?) bit 1 = 0 -> output on bit 2 = 1 -> mic in on bit 3
  469          * = 1 -> irq&drq pin enable bit 4 = 1 -> channel interrupts to chan
  470          * 1 bit 5 = 1 -> enable midi loop back bit 6 = 0 -> irq latches
  471          * URCR[2:0] bit 6 = 1 -> DMA latches URCR[2:0]
  472          */
  473 
  474 
  475         IW_READ_DIRECT_1(sc->p2xr, sc->p2xr_h, mixer_image);
  476 #ifdef AUDIO_DEBUG
  477         if (!warm)
  478                 DPRINTF(("mix image %x \n", mixer_image));
  479 #endif
  480 }
  481 
  482 struct iw_codec_freq {
  483         u_long  freq;
  484         u_char  bits;
  485 };
  486 
  487 int
  488 iw_set_speed(struct iw_softc *sc, u_long freq, char in)
  489 {
  490         u_char  var, cfig3, reg;
  491 
  492         static struct iw_codec_freq iw_cf[17] = {
  493 #define FREQ_1 24576000
  494 #define FREQ_2 16934400
  495 #define XTAL1 0
  496 #define XTAL2 1
  497                 {5510, 0x00 | XTAL2}, {6620, 0x0E | XTAL2},
  498                 {8000, 0x00 | XTAL1}, {9600, 0x0E | XTAL1},
  499                 {11025, 0x02 | XTAL2}, {16000, 0x02 | XTAL1},
  500                 {18900, 0x04 | XTAL2}, {22050, 0x06 | XTAL2},
  501                 {27420, 0x04 | XTAL1}, {32000, 0x06 | XTAL1},
  502                 {33075, 0x0C | XTAL2}, {37800, 0x08 | XTAL2},
  503                 {38400, 0x0A | XTAL1}, {44100, 0x0A | XTAL2},
  504                 {44800, 0x08 | XTAL1}, {48000, 0x0C | XTAL1},
  505                 {48000, 0x0C | XTAL1}   /* really a dummy for indexing later */
  506 #undef XTAL1
  507 #undef XTAL2
  508         };
  509 
  510         cfig3 = 0;              /* XXX gcc -Wall */
  511 
  512         /*
  513          * if the frequency is between 3493 Hz and 32 kHz we can use a more
  514          * accurate frequency than the ones listed above base on the formula
  515          * FREQ/((16*(48+x))) where FREQ is either FREQ_1 (24576000Hz) or
  516          * FREQ_2 (16934400Hz) and x is the value to be written to either
  517          * CPVFI or CRVFI. To enable this option, bit 2 in CFIG3 needs to be
  518          * set high
  519          *
  520          * NOT IMPLEMENTED!
  521          *
  522          * Note that if you have a 'bad' XTAL_1 (higher than 18.5 MHz), 44.8 kHz
  523          * and 38.4 kHz modes will provide wrong frequencies to output.
  524          */
  525 
  526 
  527         if (freq > 48000)
  528                 freq = 48000;
  529         if (freq < 5510)
  530                 freq = 5510;
  531 
  532         /* reset CFIG3[2] */
  533 
  534         IW_READ_CODEC_1(CFIG3I, cfig3);
  535 
  536         cfig3 |= 0xc0;          /* not full fifo treshhold */
  537 
  538         DPRINTF(("cfig3i = %x -> ", cfig3));
  539 
  540         cfig3 &= ~0x04;
  541         IW_WRITE_CODEC_1(CFIG3I, cfig3);
  542         IW_READ_CODEC_1(CFIG3I, cfig3);
  543 
  544         DPRINTF(("%x\n", cfig3));
  545 
  546         for (var = 0; var < 16; var++)  /* select closest frequency */
  547                 if (freq <= iw_cf[var].freq)
  548                         break;
  549         if (var != 16)
  550                 if (abs(freq - iw_cf[var].freq) > abs(iw_cf[var + 1].freq - freq))
  551                         var++;
  552 
  553         if (in)
  554                 IW_WRITE_CODEC_1(CRDFI | IW_MCE, sc->recfmtbits | iw_cf[var].bits);
  555         else
  556                 IW_WRITE_CODEC_1(CPDFI | IW_MCE, sc->playfmtbits | iw_cf[var].bits);
  557         freq = iw_cf[var].freq;
  558         DPRINTF(("setting %s frequency to %d bits %x \n",
  559                in ? "in" : "out", (int) freq, iw_cf[var].bits));
  560 
  561         IW_READ_CODEC_1(CPDFI, reg);
  562 
  563         DPRINTF((" CPDFI %x ", reg));
  564 
  565         IW_READ_CODEC_1(CRDFI, reg);
  566 
  567         DPRINTF((" CRDFI %x ", reg));
  568 
  569         return freq;
  570 }
  571 
  572 /* Encoding. */
  573 int
  574 iw_query_encoding(void *addr, audio_encoding_t *fp)
  575 {
  576         /*
  577          * LINEAR, ALAW, ULAW, ADPCM in HW, we'll use linear unsigned
  578          * hardware mode for all 8-bit modes due to buggy (?) codec.
  579          */
  580 
  581         /*
  582          * except in wavetable synth. there we have only mu-law and 8 and 16
  583          * bit linear data
  584          */
  585 
  586         switch (fp->index) {
  587         case 0:
  588                 strcpy(fp->name, AudioEulinear);
  589                 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
  590                 fp->precision = 8;
  591                 fp->flags = 0;
  592                 break;
  593         case 1:
  594                 strcpy(fp->name, AudioEmulaw);
  595                 fp->encoding = AUDIO_ENCODING_ULAW;
  596                 fp->precision = 8;
  597                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  598                 break;
  599         case 2:
  600                 strcpy(fp->name, AudioEalaw);
  601                 fp->encoding = AUDIO_ENCODING_ALAW;
  602                 fp->precision = 8;
  603                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  604                 break;
  605         case 3:
  606                 strcpy(fp->name, AudioEadpcm);
  607                 fp->encoding = AUDIO_ENCODING_ADPCM;
  608                 fp->precision = 8;      /* really 4 bit */
  609                 fp->flags = 0;
  610                 break;
  611         case 4:
  612                 strcpy(fp->name, AudioEslinear_le);
  613                 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
  614                 fp->precision = 16;
  615                 fp->flags = 0;
  616                 break;
  617         case 5:
  618                 strcpy(fp->name, AudioEslinear_be);
  619                 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
  620                 fp->precision = 16;
  621                 fp->flags = 0;
  622                 break;
  623         default:
  624                 return EINVAL;
  625                 /* NOTREACHED */
  626         }
  627         return 0;
  628 }
  629 
  630 u_long
  631 iw_set_format(struct iw_softc *sc, u_long precision, int in)
  632 {
  633         u_char  data;
  634         int     encoding, channels;
  635 
  636         encoding = in ? sc->rec_encoding : sc->play_encoding;
  637         channels = in ? sc->rec_channels : sc->play_channels;
  638 
  639         DPRINTF(("iw_set_format\n"));
  640 
  641         switch (encoding) {
  642         case AUDIO_ENCODING_ULAW:
  643                 data = 0x00;
  644                 break;
  645 
  646         case AUDIO_ENCODING_ALAW:
  647                 data = 0x00;
  648                 break;
  649 
  650         case AUDIO_ENCODING_SLINEAR_LE:
  651                 if (precision == 16)
  652                         data = 0x40;    /* little endian. 0xc0 is big endian */
  653                 else
  654                         data = 0x00;
  655                 break;
  656 
  657         case AUDIO_ENCODING_SLINEAR_BE:
  658                 if (precision == 16)
  659                         data = 0xc0;
  660                 else
  661                         data = 0x00;
  662                 break;
  663 
  664         case AUDIO_ENCODING_ADPCM:
  665                 data = 0xa0;
  666                 break;
  667 
  668         default:
  669                 return -1;
  670         }
  671 
  672         if (channels == 2)
  673                 data |= 0x10;   /* stereo */
  674 
  675         if (in) {
  676                 /* in */
  677                 sc->recfmtbits = data;
  678                 /* This will zero the normal codec frequency,
  679                  * iw_set_speed should always be called afterwards.
  680                  */
  681                 IW_WRITE_CODEC_1(CRDFI | IW_MCE, data);
  682         } else {
  683                 /* out */
  684                 sc->playfmtbits = data;
  685                 IW_WRITE_CODEC_1(CPDFI | IW_MCE, data);
  686         }
  687 
  688         DPRINTF(("formatbits %s %x", in ? "in" : "out", data));
  689 
  690         return encoding;
  691 }
  692 
  693 int
  694 iw_set_params(void *addr, int setmode, int usemode, audio_params_t *p,
  695     audio_params_t *q, stream_filter_list_t *pfil, stream_filter_list_t *rfil)
  696 {
  697         audio_params_t phw, rhw;
  698         struct iw_softc *sc;
  699         stream_filter_factory_t *swcode;
  700 
  701         DPRINTF(("iw_setparams: code %u, prec %u, rate %u, chan %u\n",
  702             p->encoding, p->precision, p->sample_rate, p->channels));
  703         sc = addr;
  704         swcode = NULL;
  705         phw = *p;
  706         rhw = *q;
  707         switch (p->encoding) {
  708         case AUDIO_ENCODING_ULAW:
  709                 if (p->precision != 8)
  710                         return EINVAL;
  711                 phw.encoding = AUDIO_ENCODING_ULINEAR_LE;
  712                 rhw.encoding = AUDIO_ENCODING_ULINEAR_LE;
  713                 swcode = setmode & AUMODE_PLAY ? mulaw_to_linear8 : linear8_to_mulaw;
  714                 break;
  715         case AUDIO_ENCODING_ALAW:
  716                 if (p->precision != 8)
  717                         return EINVAL;
  718                 phw.encoding = AUDIO_ENCODING_ULINEAR_LE;
  719                 rhw.encoding = AUDIO_ENCODING_ULINEAR_LE;
  720                 swcode = setmode & AUMODE_PLAY ? alaw_to_linear8 : linear8_to_alaw;
  721                 break;
  722         case AUDIO_ENCODING_ADPCM:
  723                 if (p->precision != 8)
  724                         return EINVAL;
  725                 else
  726                         break;
  727 
  728         case AUDIO_ENCODING_SLINEAR_LE:
  729         case AUDIO_ENCODING_SLINEAR_BE:
  730                 if (p->precision != 8 && p->precision != 16)
  731                         return EINVAL;
  732                 else
  733                         break;
  734 
  735         default:
  736                 return EINVAL;
  737 
  738         }
  739 
  740         if (setmode & AUMODE_PLAY) {
  741                 sc->play_channels = p->channels;
  742                 sc->play_encoding = p->encoding;
  743                 sc->play_precision = p->precision;
  744                 iw_set_format(sc, p->precision, 0);
  745                 q->sample_rate = p->sample_rate = sc->sc_orate =
  746                         iw_set_speed(sc, p->sample_rate, 0);
  747                 if (swcode != NULL) {
  748                         phw.sample_rate = p->sample_rate;
  749                         pfil->append(pfil, swcode, &phw);
  750                 }
  751         } else {
  752 #if 0
  753                 q->channels = sc->rec_channels = p->channels;
  754                 q->encoding = sc->rec_encoding = p->encoding;
  755                 q->precision = sc->rec_precision = p->precision;
  756 #endif
  757                 sc->rec_channels = q->channels;
  758                 sc->rec_encoding = q->encoding;
  759                 sc->rec_precision = q->precision;
  760 
  761                 iw_set_format(sc, p->precision, 1);
  762                 q->sample_rate = sc->sc_irate =
  763                         iw_set_speed(sc, q->sample_rate, 1);
  764                 if (swcode != NULL) {
  765                         rhw.sample_rate = q->sample_rate;
  766                         rfil->append(rfil, swcode, &rhw);
  767                 }
  768         }
  769         return 0;
  770 }
  771 
  772 
  773 int
  774 iw_round_blocksize(void *addr, int blk, int mode,
  775     const audio_params_t *param)
  776 {
  777 
  778         /* Round to a multiple of the biggest sample size. */
  779         return blk &= -4;
  780 }
  781 
  782 void
  783 iw_mixer_line_level(struct iw_softc *sc, int line, int levl, int levr)
  784 {
  785         u_char  gainl, gainr, attenl, attenr;
  786 
  787         switch (line) {
  788         case IW_REC:
  789                 gainl = sc->sc_recsrcbits | (levl >> 4);
  790                 gainr = sc->sc_recsrcbits | (levr >> 4);
  791                 DPRINTF(("recording with %x", gainl));
  792                 IW_WRITE_CODEC_1(CLICI, gainl);
  793                 IW_WRITE_CODEC_1(CRICI, gainr);
  794                 sc->sc_rec.voll = levl & 0xf0;
  795                 sc->sc_rec.volr = levr & 0xf0;
  796                 break;
  797 
  798         case IW_AUX1:
  799 
  800                 gainl = (255 - levl) >> 3;
  801                 gainr = (255 - levr) >> 3;
  802 
  803                 /* mute if 0 level */
  804                 if (levl == 0)
  805                         gainl |= 0x80;
  806                 if (levr == 0)
  807                         gainr |= 0x80;
  808 
  809                 IW_WRITE_CODEC_1(IW_LEFT_AUX1_PORT, gainl);
  810                 IW_WRITE_CODEC_1(IW_RIGHT_AUX1_PORT, gainr);
  811                 sc->sc_aux1.voll = levl & 0xf8;
  812                 sc->sc_aux1.volr = levr & 0xf8;
  813 
  814                 break;
  815 
  816         case IW_AUX2:
  817 
  818                 gainl = (255 - levl) >> 3;
  819                 gainr = (255 - levr) >> 3;
  820 
  821                 /* mute if 0 level */
  822                 if (levl == 0)
  823                         gainl |= 0x80;
  824                 if (levr == 0)
  825                         gainr |= 0x80;
  826 
  827                 IW_WRITE_CODEC_1(IW_LEFT_AUX2_PORT, gainl);
  828                 IW_WRITE_CODEC_1(IW_RIGHT_AUX2_PORT, gainr);
  829                 sc->sc_aux2.voll = levl & 0xf8;
  830                 sc->sc_aux2.volr = levr & 0xf8;
  831                 break;
  832         case IW_DAC:
  833                 attenl = ((255 - levl) >> 2) | ((levl && !sc->sc_dac.off) ? 0 : 0x80);
  834                 attenr = ((255 - levr) >> 2) | ((levr && !sc->sc_dac.off) ? 0 : 0x80);
  835                 IW_WRITE_CODEC_1(CLDACI, attenl);
  836                 IW_WRITE_CODEC_1(CRDACI, attenr);
  837                 sc->sc_dac.voll = levl & 0xfc;
  838                 sc->sc_dac.volr = levr & 0xfc;
  839                 break;
  840         case IW_LOOPBACK:
  841                 attenl = ((255 - levl) & 0xfc) | (levl ? 0x01 : 0);
  842                 IW_WRITE_CODEC_1(CLCI, attenl);
  843                 sc->sc_loopback.voll = levl & 0xfc;
  844                 break;
  845         case IW_LINE_IN:
  846                 gainl = (levl >> 3) | (levl ? 0 : 0x80);
  847                 gainr = (levr >> 3) | (levr ? 0 : 0x80);
  848                 IW_WRITE_CODEC_1(CLLICI, gainl);
  849                 IW_WRITE_CODEC_1(CRLICI, gainr);
  850                 sc->sc_linein.voll = levl & 0xf8;
  851                 sc->sc_linein.volr = levr & 0xf8;
  852                 break;
  853         case IW_MIC_IN:
  854                 gainl = ((255 - levl) >> 3) | (levl ? 0 : 0x80);
  855                 gainr = ((255 - levr) >> 3) | (levr ? 0 : 0x80);
  856                 IW_WRITE_CODEC_1(CLMICI, gainl);
  857                 IW_WRITE_CODEC_1(CRMICI, gainr);
  858                 sc->sc_mic.voll = levl & 0xf8;
  859                 sc->sc_mic.volr = levr & 0xf8;
  860                 break;
  861         case IW_LINE_OUT:
  862                 attenl = ((255 - levl) >> 3) | (levl ? 0 : 0x80);
  863                 attenr = ((255 - levr) >> 3) | (levr ? 0 : 0x80);
  864                 IW_WRITE_CODEC_1(CLOAI, attenl);
  865                 IW_WRITE_CODEC_1(CROAI, attenr);
  866                 sc->sc_lineout.voll = levl & 0xf8;
  867                 sc->sc_lineout.volr = levr & 0xf8;
  868                 break;
  869         case IW_MONO_IN:
  870                 attenl = ((255 - levl) >> 4) | (levl ? 0 : 0xc0);       /* in/out mute */
  871                 IW_WRITE_CODEC_1(CMONOI, attenl);
  872                 sc->sc_monoin.voll = levl & 0xf0;
  873                 break;
  874         }
  875 }
  876 
  877 int
  878 iw_commit_settings(void *addr)
  879 {
  880 
  881         return 0;
  882 }
  883 
  884 void
  885 iw_trigger_dma(struct iw_softc *sc, u_char io)
  886 {
  887         u_char  reg;
  888         int     s;
  889 
  890         s = splaudio();
  891 
  892         IW_READ_CODEC_1(CSR3I, reg);
  893         IW_WRITE_CODEC_1(CSR3I, reg & ~(io == IW_DMA_PLAYBACK ? 0x10 : 0x20));
  894 
  895         IW_READ_CODEC_1(CFIG1I, reg);
  896 
  897         IW_WRITE_CODEC_1(CFIG1I, reg | io);
  898 
  899         /* let the counter run */
  900         IW_READ_CODEC_1(CFIG2I, reg);
  901         IW_WRITE_CODEC_1(CFIG2I, reg & ~(io << 4));
  902 
  903         splx(s);
  904 }
  905 
  906 void
  907 iw_stop_dma(struct iw_softc *sc, u_char io, u_char hard)
  908 {
  909         u_char  reg;
  910 
  911         /* just stop the counter, no need to flush the fifo */
  912         IW_READ_CODEC_1(CFIG2I, reg);
  913         IW_WRITE_CODEC_1(CFIG2I, (reg | (io << 4)));
  914 
  915         if (hard) {
  916                 /* unless we're closing the device */
  917                 IW_READ_CODEC_1(CFIG1I, reg);
  918                 IW_WRITE_CODEC_1(CFIG1I, reg & ~io);
  919         }
  920 }
  921 
  922 void
  923 iw_dma_count(struct iw_softc *sc, u_short count, int io)
  924 {
  925 
  926         if (io == IW_DMA_PLAYBACK) {
  927                 IW_WRITE_CODEC_1(CLPCTI, (u_char) (count & 0x00ff));
  928                 IW_WRITE_CODEC_1(CUPCTI, (u_char) ((count >> 8) & 0x00ff));
  929         } else {
  930                 IW_WRITE_CODEC_1(CLRCTI, (u_char) (count & 0x00ff));
  931                 IW_WRITE_CODEC_1(CURCTI, (u_char) ((count >> 8) & 0x00ff));
  932         }
  933 }
  934 
  935 int
  936 iw_init_output(addr, sbuf, cc)
  937         void    *addr;
  938         void    *sbuf;
  939         int     cc;
  940 {
  941         struct iw_softc *sc = (struct iw_softc *) addr;
  942 
  943         DPRINTF(("iw_init_output\n"));
  944 
  945         isa_dmastart(sc->sc_ic, sc->sc_playdrq, sbuf,
  946                      cc, NULL, DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
  947         return 0;
  948 }
  949 
  950 int
  951 iw_init_input(void *addr, void *sbuf, int cc)
  952 {
  953         struct  iw_softc *sc;
  954 
  955         DPRINTF(("iw_init_input\n"));
  956         sc = (struct iw_softc *) addr;
  957         isa_dmastart(sc->sc_ic, sc->sc_recdrq, sbuf,
  958                      cc, NULL, DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT);
  959         return 0;
  960 }
  961 
  962 
  963 int
  964 iw_start_output(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
  965 {
  966         struct  iw_softc *sc;
  967 
  968 #ifdef DIAGNOSTIC
  969         if (!intr) {
  970                 printf("iw_start_output: no callback!\n");
  971                 return 1;
  972         }
  973 #endif
  974         sc = addr;
  975         sc->sc_playintr = intr;
  976         sc->sc_playarg = arg;
  977         sc->sc_dma_flags |= DMAMODE_WRITE;
  978         sc->sc_playdma_bp = p;
  979 
  980         isa_dmastart(sc->sc_ic, sc->sc_playdrq, sc->sc_playdma_bp,
  981             cc, NULL, DMAMODE_WRITE, BUS_DMA_NOWAIT);
  982 
  983 
  984         if (sc->play_encoding == AUDIO_ENCODING_ADPCM)
  985                 cc >>= 2;
  986         if (sc->play_precision == 16)
  987                 cc >>= 1;
  988 
  989         if (sc->play_channels == 2 && sc->play_encoding != AUDIO_ENCODING_ADPCM)
  990                 cc >>= 1;
  991 
  992         cc -= iw_cc;
  993 
  994         /* iw_dma_access(sc,1); */
  995         if (cc != sc->sc_playdma_cnt) {
  996                 iw_dma_count(sc, (u_short) cc, IW_DMA_PLAYBACK);
  997                 sc->sc_playdma_cnt = cc;
  998 
  999                 iw_trigger_dma(sc, IW_DMA_PLAYBACK);
 1000         }
 1001 
 1002 #ifdef DIAGNOSTIC
 1003         if (outputs != iw_ints)
 1004                 printf("iw_start_output: out %d, int %d\n", outputs, iw_ints);
 1005         outputs++;
 1006 #endif
 1007 
 1008         return 0;
 1009 }
 1010 
 1011 
 1012 int
 1013 iw_start_input(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
 1014 {
 1015         struct  iw_softc *sc;
 1016 
 1017 #ifdef DIAGNOSTIC
 1018         if (!intr) {
 1019                 printf("iw_start_input: no callback!\n");
 1020                 return 1;
 1021         }
 1022 #endif
 1023         sc = addr;
 1024         sc->sc_recintr = intr;
 1025         sc->sc_recarg = arg;
 1026         sc->sc_dma_flags |= DMAMODE_READ;
 1027         sc->sc_recdma_bp = p;
 1028 
 1029         isa_dmastart(sc->sc_ic, sc->sc_recdrq, sc->sc_recdma_bp,
 1030             cc, NULL, DMAMODE_READ, BUS_DMA_NOWAIT);
 1031 
 1032 
 1033         if (sc->rec_encoding == AUDIO_ENCODING_ADPCM)
 1034                 cc >>= 2;
 1035         if (sc->rec_precision == 16)
 1036                 cc >>= 1;
 1037 
 1038         if (sc->rec_channels == 2 && sc->rec_encoding != AUDIO_ENCODING_ADPCM)
 1039                 cc >>= 1;
 1040 
 1041         cc -= iw_cc;
 1042 
 1043         /* iw_dma_access(sc,0); */
 1044         if (sc->sc_recdma_cnt != cc) {
 1045                 iw_dma_count(sc, (u_short) cc, IW_DMA_RECORD);
 1046                 sc->sc_recdma_cnt = cc;
 1047                 /* iw_dma_ctrl(sc, IW_DMA_RECORD); */
 1048                 iw_trigger_dma(sc, IW_DMA_RECORD);
 1049         }
 1050 
 1051 #ifdef DIAGNOSTIC
 1052         if ((inputs != iw_inints))
 1053                 printf("iw_start_input: in %d, inints %d\n", inputs, iw_inints);
 1054         inputs++;
 1055 #endif
 1056 
 1057         return 0;
 1058 }
 1059 
 1060 
 1061 int
 1062 iw_halt_output(void *addr)
 1063 {
 1064         struct  iw_softc *sc;
 1065 
 1066         sc = addr;
 1067         iw_stop_dma(sc, IW_DMA_PLAYBACK, 0);
 1068         return 0;
 1069 }
 1070 
 1071 
 1072 int
 1073 iw_halt_input(void *addr)
 1074 {
 1075         struct  iw_softc *sc;
 1076 
 1077         sc = addr;
 1078         iw_stop_dma(sc, IW_DMA_RECORD, 0);
 1079         return 0;
 1080 }
 1081 
 1082 int
 1083 iw_speaker_ctl(void *addr, int newstate)
 1084 {
 1085         struct iw_softc *sc;
 1086         u_char reg;
 1087 
 1088         sc = addr;
 1089         if (newstate == SPKR_ON) {
 1090                 sc->sc_dac.off = 0;
 1091                 IW_READ_CODEC_1(CLDACI, reg);
 1092                 IW_WRITE_CODEC_1(CLDACI, reg & 0x7f);
 1093                 IW_READ_CODEC_1(CRDACI, reg);
 1094                 IW_WRITE_CODEC_1(CRDACI, reg & 0x7f);
 1095         } else {
 1096                 /* SPKR_OFF */
 1097                 sc->sc_dac.off = 1;
 1098                 IW_READ_CODEC_1(CLDACI, reg);
 1099                 IW_WRITE_CODEC_1(CLDACI, reg | 0x80);
 1100                 IW_READ_CODEC_1(CRDACI, reg);
 1101                 IW_WRITE_CODEC_1(CRDACI, reg | 0x80);
 1102         }
 1103         return 0;
 1104 }
 1105 
 1106 int
 1107 iw_getdev(void *addr, struct audio_device *retp)
 1108 {
 1109 
 1110         *retp = iw_device;
 1111         return 0;
 1112 }
 1113 
 1114 int
 1115 iw_setfd(void *addr, int flag)
 1116 {
 1117 
 1118         return 0;
 1119 }
 1120 
 1121 /* Mixer (in/out ports) */
 1122 int
 1123 iw_set_port(void *addr, mixer_ctrl_t *cp)
 1124 {
 1125         struct iw_softc *sc;
 1126         u_char vall, valr;
 1127         int error;
 1128 
 1129         sc = addr;
 1130         vall = 0;
 1131         valr = 0;
 1132         error = EINVAL;
 1133         switch (cp->dev) {
 1134         case IW_MIC_IN_LVL:
 1135                 if (cp->type == AUDIO_MIXER_VALUE) {
 1136                         error = 0;
 1137                         if (cp->un.value.num_channels == 1) {
 1138                                 vall = valr = cp->un.value.level[0];
 1139                         } else {
 1140                                 vall = cp->un.value.level[0];
 1141                                 valr = cp->un.value.level[1];
 1142                         }
 1143                         sc->sc_mic.voll = vall;
 1144                         sc->sc_mic.volr = valr;
 1145                         iw_mixer_line_level(sc, IW_MIC_IN, vall, valr);
 1146                 }
 1147                 break;
 1148         case IW_AUX1_LVL:
 1149                 if (cp->type == AUDIO_MIXER_VALUE) {
 1150                         error = 0;
 1151                         if (cp->un.value.num_channels == 1) {
 1152                                 vall = valr = cp->un.value.level[0];
 1153                         } else {
 1154                                 vall = cp->un.value.level[0];
 1155                                 valr = cp->un.value.level[1];
 1156                         }
 1157                         sc->sc_aux1.voll = vall;
 1158                         sc->sc_aux1.volr = valr;
 1159                         iw_mixer_line_level(sc, IW_AUX1, vall, valr);
 1160                 }
 1161                 break;
 1162         case IW_AUX2_LVL:
 1163                 if (cp->type == AUDIO_MIXER_VALUE) {
 1164                         error = 0;
 1165                         if (cp->un.value.num_channels == 1) {
 1166                                 vall = valr = cp->un.value.level[0];
 1167                         } else {
 1168                                 vall = cp->un.value.level[0];
 1169                                 valr = cp->un.value.level[1];
 1170                         }
 1171                         sc->sc_aux2.voll = vall;
 1172                         sc->sc_aux2.volr = valr;
 1173                         iw_mixer_line_level(sc, IW_AUX2, vall, valr);
 1174                 }
 1175                 break;
 1176         case IW_LINE_IN_LVL:
 1177                 if (cp->type == AUDIO_MIXER_VALUE) {
 1178                         error = 0;
 1179                         if (cp->un.value.num_channels == 1) {
 1180                                 vall = valr = cp->un.value.level[0];
 1181                         } else {
 1182                                 vall = cp->un.value.level[0];
 1183                                 valr = cp->un.value.level[1];
 1184                         }
 1185                         sc->sc_linein.voll = vall;
 1186                         sc->sc_linein.volr = valr;
 1187                         iw_mixer_line_level(sc, IW_LINE_IN, vall, valr);
 1188                 }
 1189                 break;
 1190         case IW_LINE_OUT_LVL:
 1191                 if (cp->type == AUDIO_MIXER_VALUE) {
 1192                         error = 0;
 1193                         if (cp->un.value.num_channels == 1) {
 1194                                 vall = valr = cp->un.value.level[0];
 1195                         } else {
 1196                                 vall = cp->un.value.level[0];
 1197                                 valr = cp->un.value.level[1];
 1198                         }
 1199                         sc->sc_lineout.voll = vall;
 1200                         sc->sc_lineout.volr = valr;
 1201                         iw_mixer_line_level(sc, IW_LINE_OUT, vall, valr);
 1202                 }
 1203                 break;
 1204         case IW_REC_LVL:
 1205                 if (cp->type == AUDIO_MIXER_VALUE) {
 1206                         error = 0;
 1207                         if (cp->un.value.num_channels == 1) {
 1208                                 vall = valr = cp->un.value.level[0];
 1209                         } else {
 1210                                 vall = cp->un.value.level[0];
 1211                                 valr = cp->un.value.level[1];
 1212                         }
 1213                         sc->sc_rec.voll = vall;
 1214                         sc->sc_rec.volr = valr;
 1215                         iw_mixer_line_level(sc, IW_REC, vall, valr);
 1216                 }
 1217                 break;
 1218 
 1219         case IW_DAC_LVL:
 1220                 if (cp->type == AUDIO_MIXER_VALUE) {
 1221                         error = 0;
 1222                         if (cp->un.value.num_channels == 1) {
 1223                                 vall = valr = cp->un.value.level[0];
 1224                         } else {
 1225                                 vall = cp->un.value.level[0];
 1226                                 valr = cp->un.value.level[1];
 1227                         }
 1228                         sc->sc_dac.voll = vall;
 1229                         sc->sc_dac.volr = valr;
 1230                         iw_mixer_line_level(sc, IW_DAC, vall, valr);
 1231                 }
 1232                 break;
 1233 
 1234         case IW_LOOPBACK_LVL:
 1235                 if (cp->type == AUDIO_MIXER_VALUE) {
 1236                         error = 0;
 1237                         if (cp->un.value.num_channels != 1) {
 1238                                 return EINVAL;
 1239                         } else {
 1240                                 valr = vall = cp->un.value.level[0];
 1241                         }
 1242                         sc->sc_loopback.voll = vall;
 1243                         sc->sc_loopback.volr = valr;
 1244                         iw_mixer_line_level(sc, IW_LOOPBACK, vall, valr);
 1245                 }
 1246                 break;
 1247 
 1248         case IW_MONO_IN_LVL:
 1249                 if (cp->type == AUDIO_MIXER_VALUE) {
 1250                         error = 0;
 1251                         if (cp->un.value.num_channels != 1) {
 1252                                 return EINVAL;
 1253                         } else {
 1254                                 valr = vall = cp->un.value.level[0];
 1255                         }
 1256                         sc->sc_monoin.voll = vall;
 1257                         sc->sc_monoin.volr = valr;
 1258                         iw_mixer_line_level(sc, IW_MONO_IN, vall, valr);
 1259                 }
 1260                 break;
 1261         case IW_RECORD_SOURCE:
 1262                 error = 0;
 1263                 sc->sc_recsrcbits = cp->un.ord << 6;
 1264                 DPRINTF(("record source %d bits %x\n", cp->un.ord, sc->sc_recsrcbits));
 1265                 iw_mixer_line_level(sc, IW_REC, sc->sc_rec.voll, sc->sc_rec.volr);
 1266                 break;
 1267         }
 1268 
 1269         return error;
 1270 }
 1271 
 1272 
 1273 int
 1274 iw_get_port(void *addr, mixer_ctrl_t *cp)
 1275 {
 1276         struct iw_softc *sc;
 1277         int error;
 1278 
 1279         sc = addr;
 1280         error = EINVAL;
 1281         switch (cp->dev) {
 1282         case IW_MIC_IN_LVL:
 1283                 if (cp->type == AUDIO_MIXER_VALUE) {
 1284                         cp->un.value.num_channels = 2;
 1285                         cp->un.value.level[0] = sc->sc_mic.voll;
 1286                         cp->un.value.level[1] = sc->sc_mic.volr;
 1287                         error = 0;
 1288                 }
 1289                 break;
 1290         case IW_AUX1_LVL:
 1291                 if (cp->type == AUDIO_MIXER_VALUE) {
 1292                         cp->un.value.num_channels = 2;
 1293                         cp->un.value.level[0] = sc->sc_aux1.voll;
 1294                         cp->un.value.level[1] = sc->sc_aux1.volr;
 1295                         error = 0;
 1296                 }
 1297                 break;
 1298         case IW_AUX2_LVL:
 1299                 if (cp->type == AUDIO_MIXER_VALUE) {
 1300                         cp->un.value.num_channels = 2;
 1301                         cp->un.value.level[0] = sc->sc_aux2.voll;
 1302                         cp->un.value.level[1] = sc->sc_aux2.volr;
 1303                         error = 0;
 1304                 }
 1305                 break;
 1306         case IW_LINE_OUT_LVL:
 1307                 if (cp->type == AUDIO_MIXER_VALUE) {
 1308                         cp->un.value.num_channels = 2;
 1309                         cp->un.value.level[0] = sc->sc_lineout.voll;
 1310                         cp->un.value.level[1] = sc->sc_lineout.volr;
 1311                         error = 0;
 1312                 }
 1313                 break;
 1314         case IW_LINE_IN_LVL:
 1315                 if (cp->type == AUDIO_MIXER_VALUE) {
 1316                         cp->un.value.num_channels = 2;
 1317                         cp->un.value.level[0] = sc->sc_linein.voll;
 1318                         cp->un.value.level[1] = sc->sc_linein.volr;
 1319                         error = 0;
 1320                 }
 1321         case IW_REC_LVL:
 1322                 if (cp->type == AUDIO_MIXER_VALUE) {
 1323                         cp->un.value.num_channels = 2;
 1324                         cp->un.value.level[0] = sc->sc_rec.voll;
 1325                         cp->un.value.level[1] = sc->sc_rec.volr;
 1326                         error = 0;
 1327                 }
 1328                 break;
 1329 
 1330         case IW_DAC_LVL:
 1331                 if (cp->type == AUDIO_MIXER_VALUE) {
 1332                         cp->un.value.num_channels = 2;
 1333                         cp->un.value.level[0] = sc->sc_dac.voll;
 1334                         cp->un.value.level[1] = sc->sc_dac.volr;
 1335                         error = 0;
 1336                 }
 1337                 break;
 1338 
 1339         case IW_LOOPBACK_LVL:
 1340                 if (cp->type == AUDIO_MIXER_VALUE) {
 1341                         cp->un.value.num_channels = 1;
 1342                         cp->un.value.level[0] = sc->sc_loopback.voll;
 1343                         error = 0;
 1344                 }
 1345                 break;
 1346 
 1347         case IW_MONO_IN_LVL:
 1348                 if (cp->type == AUDIO_MIXER_VALUE) {
 1349                         cp->un.value.num_channels = 1;
 1350                         cp->un.value.level[0] = sc->sc_monoin.voll;
 1351                         error = 0;
 1352                 }
 1353                 break;
 1354         case IW_RECORD_SOURCE:
 1355                 cp->un.ord = sc->sc_recsrcbits >> 6;
 1356                 error = 0;
 1357                 break;
 1358         }
 1359 
 1360         return error;
 1361 }
 1362 
 1363 
 1364 
 1365 int
 1366 iw_query_devinfo(void *addr, mixer_devinfo_t *dip)
 1367 {
 1368 
 1369         switch (dip->index) {
 1370         case IW_MIC_IN_LVL:     /* Microphone */
 1371                 dip->type = AUDIO_MIXER_VALUE;
 1372                 dip->mixer_class = IW_INPUT_CLASS;
 1373                 dip->prev = AUDIO_MIXER_LAST;
 1374                 dip->next = AUDIO_MIXER_LAST;
 1375                 strcpy(dip->label.name, AudioNmicrophone);
 1376                 dip->un.v.num_channels = 2;
 1377                 strcpy(dip->un.v.units.name, AudioNvolume);
 1378                 break;
 1379         case IW_AUX1_LVL:
 1380                 dip->type = AUDIO_MIXER_VALUE;
 1381                 dip->mixer_class = IW_INPUT_CLASS;
 1382                 dip->prev = AUDIO_MIXER_LAST;
 1383                 dip->next = AUDIO_MIXER_LAST;
 1384                 strcpy(dip->label.name, AudioNline);
 1385                 dip->un.v.num_channels = 2;
 1386                 strcpy(dip->un.v.units.name, AudioNvolume);
 1387                 break;
 1388         case IW_AUX2_LVL:
 1389                 dip->type = AUDIO_MIXER_VALUE;
 1390                 dip->mixer_class = IW_INPUT_CLASS;
 1391                 dip->prev = AUDIO_MIXER_LAST;
 1392                 dip->next = AUDIO_MIXER_LAST;
 1393                 strcpy(dip->label.name, AudioNcd);
 1394                 dip->un.v.num_channels = 2;
 1395                 strcpy(dip->un.v.units.name, AudioNvolume);
 1396                 break;
 1397         case IW_LINE_OUT_LVL:
 1398                 dip->type = AUDIO_MIXER_VALUE;
 1399                 dip->mixer_class = IW_OUTPUT_CLASS;
 1400                 dip->prev = AUDIO_MIXER_LAST;
 1401                 dip->next = AUDIO_MIXER_LAST;
 1402                 strcpy(dip->label.name, AudioNline);
 1403                 dip->un.v.num_channels = 2;
 1404                 strcpy(dip->un.v.units.name, AudioNvolume);
 1405                 break;
 1406         case IW_DAC_LVL:
 1407                 dip->type = AUDIO_MIXER_VALUE;
 1408                 dip->mixer_class = IW_OUTPUT_CLASS;
 1409                 dip->prev = AUDIO_MIXER_LAST;
 1410                 dip->next = AUDIO_MIXER_LAST;
 1411                 strcpy(dip->label.name, AudioNdac);
 1412                 dip->un.v.num_channels = 2;
 1413                 strcpy(dip->un.v.units.name, AudioNvolume);
 1414                 break;
 1415         case IW_LINE_IN_LVL:
 1416                 dip->type = AUDIO_MIXER_VALUE;
 1417                 dip->mixer_class = IW_INPUT_CLASS;
 1418                 dip->prev = AUDIO_MIXER_LAST;
 1419                 dip->next = AUDIO_MIXER_LAST;
 1420                 strcpy(dip->label.name, AudioNinput);
 1421                 dip->un.v.num_channels = 2;
 1422                 strcpy(dip->un.v.units.name, AudioNvolume);
 1423                 break;
 1424         case IW_MONO_IN_LVL:
 1425                 dip->type = AUDIO_MIXER_VALUE;
 1426                 dip->mixer_class = IW_INPUT_CLASS;
 1427                 dip->prev = AUDIO_MIXER_LAST;
 1428                 dip->next = AUDIO_MIXER_LAST;
 1429                 strcpy(dip->label.name, AudioNmono);
 1430                 dip->un.v.num_channels = 1;
 1431                 strcpy(dip->un.v.units.name, AudioNvolume);
 1432                 break;
 1433 
 1434         case IW_REC_LVL:        /* record level */
 1435                 dip->type = AUDIO_MIXER_VALUE;
 1436                 dip->mixer_class = IW_RECORD_CLASS;
 1437                 dip->prev = AUDIO_MIXER_LAST;
 1438                 dip->next = AUDIO_MIXER_LAST;
 1439                 strcpy(dip->label.name, AudioNrecord);
 1440                 dip->un.v.num_channels = 2;
 1441                 strcpy(dip->un.v.units.name, AudioNvolume);
 1442                 break;
 1443 
 1444         case IW_LOOPBACK_LVL:
 1445                 dip->type = AUDIO_MIXER_VALUE;
 1446                 dip->mixer_class = IW_RECORD_CLASS;
 1447                 dip->prev = AUDIO_MIXER_LAST;
 1448                 dip->next = AUDIO_MIXER_LAST;
 1449                 strcpy(dip->label.name, "filter");
 1450                 dip->un.v.num_channels = 1;
 1451                 strcpy(dip->un.v.units.name, AudioNvolume);
 1452                 break;
 1453 
 1454         case IW_RECORD_SOURCE:
 1455                 dip->mixer_class = IW_RECORD_CLASS;
 1456                 dip->type = AUDIO_MIXER_ENUM;
 1457                 dip->prev = AUDIO_MIXER_LAST;
 1458                 dip->next = AUDIO_MIXER_LAST;
 1459                 strcpy(dip->label.name, AudioNsource);
 1460                 dip->un.e.num_mem = 4;
 1461                 strcpy(dip->un.e.member[0].label.name, AudioNline);
 1462                 dip->un.e.member[0].ord = IW_LINE_IN_SRC;
 1463                 strcpy(dip->un.e.member[1].label.name, "aux1");
 1464                 dip->un.e.member[1].ord = IW_AUX1_SRC;
 1465                 strcpy(dip->un.e.member[2].label.name, AudioNmicrophone);
 1466                 dip->un.e.member[2].ord = IW_MIC_IN_SRC;
 1467                 strcpy(dip->un.e.member[3].label.name, AudioNmixerout);
 1468                 dip->un.e.member[3].ord = IW_MIX_OUT_SRC;
 1469                 break;
 1470         case IW_INPUT_CLASS:
 1471                 dip->type = AUDIO_MIXER_CLASS;
 1472                 dip->mixer_class = IW_INPUT_CLASS;
 1473                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1474                 strcpy(dip->label.name, AudioCinputs);
 1475                 break;
 1476         case IW_OUTPUT_CLASS:
 1477                 dip->type = AUDIO_MIXER_CLASS;
 1478                 dip->mixer_class = IW_OUTPUT_CLASS;
 1479                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1480                 strcpy(dip->label.name, AudioCoutputs);
 1481                 break;
 1482         case IW_RECORD_CLASS:   /* record source class */
 1483                 dip->type = AUDIO_MIXER_CLASS;
 1484                 dip->mixer_class = IW_RECORD_CLASS;
 1485                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1486                 strcpy(dip->label.name, AudioCrecord);
 1487                 return 0;
 1488         default:
 1489                 return ENXIO;
 1490         }
 1491         return 0;
 1492 }
 1493 
 1494 
 1495 void *
 1496 iw_malloc(void *addr, int direction, size_t size,
 1497     struct malloc_type *pool, int flags)
 1498 {
 1499         struct iw_softc *sc;
 1500         int drq;
 1501 
 1502         sc = addr;
 1503         if (direction == AUMODE_PLAY)
 1504                 drq = sc->sc_playdrq;
 1505         else
 1506                 drq = sc->sc_recdrq;
 1507         return isa_malloc(sc->sc_ic, drq, size, pool, flags);
 1508 }
 1509 
 1510 void
 1511 iw_free(void *addr, void *ptr, struct malloc_type *pool)
 1512 {
 1513         isa_free(ptr, pool);
 1514 }
 1515 
 1516 size_t
 1517 iw_round_buffersize(void *addr, int direction, size_t size)
 1518 {
 1519         struct iw_softc *sc;
 1520         bus_size_t maxsize;
 1521 
 1522         sc = addr;
 1523         if (direction == AUMODE_PLAY)
 1524                 maxsize = sc->sc_play_maxsize;
 1525         else
 1526                 maxsize = sc->sc_rec_maxsize;
 1527 
 1528         if (size > maxsize)
 1529                 size = maxsize;
 1530         return size;
 1531 }
 1532 
 1533 paddr_t
 1534 iw_mappage(void *addr, void *mem, off_t off, int prot)
 1535 {
 1536 
 1537         return isa_mappage(mem, off, prot);
 1538 }
 1539 
 1540 int
 1541 iw_get_props(void *addr)
 1542 {
 1543         struct iw_softc *sc;
 1544 
 1545         sc = addr;
 1546         return AUDIO_PROP_MMAP |
 1547                 (sc->sc_fullduplex ? AUDIO_PROP_FULLDUPLEX : 0);
 1548 }

Cache object: 60e6f84d6f33febbe349abc263973ce9


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.