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/isa/ess.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 /*      $OpenBSD: ess.c,v 1.33 2022/11/02 10:41:34 kn Exp $     */
    2 /*      $NetBSD: ess.c,v 1.44.4.1 1999/06/21 01:18:00 thorpej Exp $     */
    3 
    4 /*
    5  * Copyright 1997
    6  * Digital Equipment Corporation. All rights reserved.
    7  *
    8  * This software is furnished under license and may be used and
    9  * copied only in accordance with the following terms and conditions.
   10  * Subject to these conditions, you may download, copy, install,
   11  * use, modify and distribute this software in source and/or binary
   12  * form. No title or ownership is transferred hereby.
   13  *
   14  * 1) Any source code used, modified or distributed must reproduce
   15  *    and retain this copyright notice and list of conditions as
   16  *    they appear in the source file.
   17  *
   18  * 2) No right is granted to use any trade name, trademark, or logo of
   19  *    Digital Equipment Corporation. Neither the "Digital Equipment
   20  *    Corporation" name nor any trademark or logo of Digital Equipment
   21  *    Corporation may be used to endorse or promote products derived
   22  *    from this software without the prior written permission of
   23  *    Digital Equipment Corporation.
   24  *
   25  * 3) This software is provided "AS-IS" and any express or implied
   26  *    warranties, including but not limited to, any implied warranties
   27  *    of merchantability, fitness for a particular purpose, or
   28  *    non-infringement are disclaimed. In no event shall DIGITAL be
   29  *    liable for any damages whatsoever, and in particular, DIGITAL
   30  *    shall not be liable for special, indirect, consequential, or
   31  *    incidental damages or damages for lost profits, loss of
   32  *    revenue or loss of use, whether such damages arise in contract,
   33  *    negligence, tort, under statute, in equity, at law or otherwise,
   34  *    even if advised of the possibility of such damage.
   35  */
   36 
   37 /*
   38 **++
   39 **
   40 **  ess.c
   41 **
   42 **  FACILITY:
   43 **
   44 **      DIGITAL Network Appliance Reference Design (DNARD)
   45 **
   46 **  MODULE DESCRIPTION:
   47 **
   48 **      This module contains the device driver for the ESS
   49 **      Technologies 1888/1887/888 sound chip. The code in sbdsp.c was
   50 **      used as a reference point when implementing this driver.
   51 **
   52 **  AUTHORS:
   53 **
   54 **      Blair Fidler    Software Engineering Australia
   55 **                      Gold Coast, Australia.
   56 **
   57 **  CREATION DATE:
   58 **
   59 **      March 10, 1997.
   60 **
   61 **  MODIFICATION HISTORY:
   62 **
   63 **      Heavily modified by Lennart Augustsson and Charles M. Hannum for
   64 **      bus_dma, changes to audio interface, and many bug fixes.
   65 **      ESS1788 support by Nathan J. Williams and Charles M. Hannum.
   66 **--
   67 */
   68 
   69 #include <sys/param.h>
   70 #include <sys/systm.h>
   71 #include <sys/errno.h>
   72 #include <sys/ioctl.h>
   73 #include <sys/syslog.h>
   74 #include <sys/device.h>
   75 #include <sys/kernel.h>
   76 #include <sys/timeout.h>
   77 #include <sys/fcntl.h>
   78 
   79 #include <machine/cpu.h>
   80 #include <machine/intr.h>
   81 #include <machine/bus.h>
   82 
   83 #include <sys/audioio.h>
   84 #include <dev/audio_if.h>
   85 
   86 #include <dev/isa/isavar.h>
   87 #include <dev/isa/isadmavar.h>
   88 
   89 #include <dev/isa/essvar.h>
   90 #include <dev/isa/essreg.h>
   91 
   92 #ifdef AUDIO_DEBUG
   93 #define DPRINTF(x)      if (essdebug) printf x
   94 #define DPRINTFN(n,x)   if (essdebug>(n)) printf x
   95 int     essdebug = 0;
   96 #else
   97 #define DPRINTF(x)
   98 #define DPRINTFN(n,x)
   99 #endif
  100 
  101 #if 0
  102 unsigned uuu;
  103 #define EREAD1(t, h, a) (uuu=bus_space_read_1(t, h, a),printf("EREAD  %02x=%02x\n", ((int)h&0xfff)+a, uuu),uuu)
  104 #define EWRITE1(t, h, a, d) (printf("EWRITE %02x=%02x\n", ((int)h & 0xfff)+a, d), bus_space_write_1(t, h, a, d))
  105 #else
  106 #define EREAD1(t, h, a) bus_space_read_1(t, h, a)
  107 #define EWRITE1(t, h, a, d) bus_space_write_1(t, h, a, d)
  108 #endif
  109 
  110 struct cfdriver ess_cd = {
  111         NULL, "ess", DV_DULL
  112 };
  113 
  114 struct audio_params ess_audio_default =
  115         {44100, AUDIO_ENCODING_SLINEAR_LE, 16, 2, 1, 2};
  116 
  117 int     ess_setup_sc(struct ess_softc *, int);
  118 
  119 int     ess_1788_open(void *, int);
  120 int     ess_open(void *, int);
  121 void    ess_1788_close(void *);
  122 void    ess_1888_close(void *);
  123 
  124 int     ess_set_params(void *, int, int, struct audio_params *,
  125             struct audio_params *);
  126 
  127 int     ess_round_blocksize(void *, int);
  128 
  129 int     ess_audio1_trigger_output(void *, void *, void *, int,
  130             void (*)(void *), void *, struct audio_params *);
  131 int     ess_audio2_trigger_output(void *, void *, void *, int,
  132             void (*)(void *), void *, struct audio_params *);
  133 int     ess_audio1_trigger_input(void *, void *, void *, int,
  134             void (*)(void *), void *, struct audio_params *);
  135 int     ess_audio1_halt(void *);
  136 int     ess_audio2_halt(void *);
  137 int     ess_audio1_intr(void *);
  138 int     ess_audio2_intr(void *);
  139 void    ess_audio1_poll(void *);
  140 void    ess_audio2_poll(void *);
  141 
  142 int     ess_speaker_ctl(void *, int);
  143 
  144 int     ess_set_port(void *, mixer_ctrl_t *);
  145 int     ess_get_port(void *, mixer_ctrl_t *);
  146 
  147 void   *ess_malloc(void *, int, size_t, int, int);
  148 void    ess_free(void *, void *, int);
  149 size_t  ess_round_buffersize(void *, int, size_t);
  150 
  151 
  152 int     ess_query_devinfo(void *, mixer_devinfo_t *);
  153 
  154 void    ess_speaker_on(struct ess_softc *);
  155 void    ess_speaker_off(struct ess_softc *);
  156 
  157 int     ess_config_addr(struct ess_softc *);
  158 void    ess_config_irq(struct ess_softc *);
  159 void    ess_config_drq(struct ess_softc *);
  160 void    ess_setup(struct ess_softc *);
  161 int     ess_identify(struct ess_softc *);
  162 
  163 int     ess_reset(struct ess_softc *);
  164 void    ess_set_gain(struct ess_softc *, int, int);
  165 int     ess_set_in_port(struct ess_softc *, int);
  166 int     ess_set_in_ports(struct ess_softc *, int);
  167 u_int   ess_srtotc(u_int);
  168 u_int   ess_srtofc(u_int);
  169 u_char  ess_get_dsp_status(struct ess_softc *);
  170 u_char  ess_dsp_read_ready(struct ess_softc *);
  171 u_char  ess_dsp_write_ready(struct ess_softc *);
  172 int     ess_rdsp(struct ess_softc *);
  173 int     ess_wdsp(struct ess_softc *, u_char);
  174 u_char  ess_read_x_reg(struct ess_softc *, u_char);
  175 int     ess_write_x_reg(struct ess_softc *, u_char, u_char);
  176 void    ess_clear_xreg_bits(struct ess_softc *, u_char, u_char);
  177 void    ess_set_xreg_bits(struct ess_softc *, u_char, u_char);
  178 u_char  ess_read_mix_reg(struct ess_softc *, u_char);
  179 void    ess_write_mix_reg(struct ess_softc *, u_char, u_char);
  180 void    ess_clear_mreg_bits(struct ess_softc *, u_char, u_char);
  181 void    ess_set_mreg_bits(struct ess_softc *, u_char, u_char);
  182 void    ess_read_multi_mix_reg(struct ess_softc *, u_char, u_int8_t *, bus_size_t);
  183 
  184 static const char *essmodel[] = {
  185         "unsupported",
  186         "1888",
  187         "1887",
  188         "888",
  189         "1788",
  190         "1869",
  191         "1879",
  192         "1868",
  193         "1878",
  194 };
  195 
  196 /*
  197  * Define our interface to the higher level audio driver.
  198  */
  199 
  200 const struct audio_hw_if ess_1788_hw_if = {
  201         .open = ess_1788_open,
  202         .close = ess_1788_close,
  203         .set_params = ess_set_params,
  204         .round_blocksize = ess_round_blocksize,
  205         .halt_output = ess_audio1_halt,
  206         .halt_input = ess_audio1_halt,
  207         .set_port = ess_set_port,
  208         .get_port = ess_get_port,
  209         .query_devinfo = ess_query_devinfo,
  210         .allocm = ess_malloc,
  211         .freem = ess_free,
  212         .round_buffersize = ess_round_buffersize,
  213         .trigger_output = ess_audio1_trigger_output,
  214         .trigger_input = ess_audio1_trigger_input,
  215 };
  216 
  217 const struct audio_hw_if ess_1888_hw_if = {
  218         .open = ess_open,
  219         .close = ess_1888_close,
  220         .set_params = ess_set_params,
  221         .round_blocksize = ess_round_blocksize,
  222         .halt_output = ess_audio2_halt,
  223         .halt_input = ess_audio1_halt,
  224         .set_port = ess_set_port,
  225         .get_port = ess_get_port,
  226         .query_devinfo = ess_query_devinfo,
  227         .allocm = ess_malloc,
  228         .freem = ess_free,
  229         .round_buffersize = ess_round_buffersize,
  230         .trigger_output = ess_audio2_trigger_output,
  231         .trigger_input = ess_audio1_trigger_input,
  232 };
  233 
  234 #ifdef AUDIO_DEBUG
  235 void ess_printsc(struct ess_softc *);
  236 void ess_dump_mixer(struct ess_softc *);
  237 
  238 void
  239 ess_printsc(struct ess_softc *sc)
  240 {
  241         int i;
  242 
  243         printf("open %d iobase 0x%x outport %u inport %u speaker %s\n",
  244                (int)sc->sc_open, sc->sc_iobase, sc->out_port,
  245                sc->in_port, sc->spkr_state ? "on" : "off");
  246 
  247         printf("audio1: dmachan %d irq %d nintr %lu intr %p arg %p\n",
  248                sc->sc_audio1.drq, sc->sc_audio1.irq, sc->sc_audio1.nintr,
  249                sc->sc_audio1.intr, sc->sc_audio1.arg);
  250 
  251         if (!ESS_USE_AUDIO1(sc->sc_model)) {
  252                 printf("audio2: dmachan %d irq %d nintr %lu intr %p arg %p\n",
  253                        sc->sc_audio2.drq, sc->sc_audio2.irq, sc->sc_audio2.nintr,
  254                        sc->sc_audio2.intr, sc->sc_audio2.arg);
  255         }
  256 
  257         printf("gain:");
  258         for (i = 0; i < sc->ndevs; i++)
  259                 printf(" %u,%u", sc->gain[i][ESS_LEFT], sc->gain[i][ESS_RIGHT]);
  260         printf("\n");
  261 }
  262 
  263 void
  264 ess_dump_mixer(struct ess_softc *sc)
  265 {
  266         printf("ESS_DAC_PLAY_VOL: mix reg 0x%02x=0x%02x\n",
  267                0x7C, ess_read_mix_reg(sc, 0x7C));
  268         printf("ESS_MIC_PLAY_VOL: mix reg 0x%02x=0x%02x\n",
  269                0x1A, ess_read_mix_reg(sc, 0x1A));
  270         printf("ESS_LINE_PLAY_VOL: mix reg 0x%02x=0x%02x\n",
  271                0x3E, ess_read_mix_reg(sc, 0x3E));
  272         printf("ESS_SYNTH_PLAY_VOL: mix reg 0x%02x=0x%02x\n",
  273                0x36, ess_read_mix_reg(sc, 0x36));
  274         printf("ESS_CD_PLAY_VOL: mix reg 0x%02x=0x%02x\n",
  275                0x38, ess_read_mix_reg(sc, 0x38));
  276         printf("ESS_AUXB_PLAY_VOL: mix reg 0x%02x=0x%02x\n",
  277                0x3A, ess_read_mix_reg(sc, 0x3A));
  278         printf("ESS_MASTER_VOL: mix reg 0x%02x=0x%02x\n",
  279                0x32, ess_read_mix_reg(sc, 0x32));
  280         printf("ESS_PCSPEAKER_VOL: mix reg 0x%02x=0x%02x\n",
  281                0x3C, ess_read_mix_reg(sc, 0x3C));
  282         printf("ESS_DAC_REC_VOL: mix reg 0x%02x=0x%02x\n",
  283                0x69, ess_read_mix_reg(sc, 0x69));
  284         printf("ESS_MIC_REC_VOL: mix reg 0x%02x=0x%02x\n",
  285                0x68, ess_read_mix_reg(sc, 0x68));
  286         printf("ESS_LINE_REC_VOL: mix reg 0x%02x=0x%02x\n",
  287                0x6E, ess_read_mix_reg(sc, 0x6E));
  288         printf("ESS_SYNTH_REC_VOL: mix reg 0x%02x=0x%02x\n",
  289                0x6B, ess_read_mix_reg(sc, 0x6B));
  290         printf("ESS_CD_REC_VOL: mix reg 0x%02x=0x%02x\n",
  291                0x6A, ess_read_mix_reg(sc, 0x6A));
  292         printf("ESS_AUXB_REC_VOL: mix reg 0x%02x=0x%02x\n",
  293                0x6C, ess_read_mix_reg(sc, 0x6C));
  294         printf("ESS_RECORD_VOL: x reg 0x%02x=0x%02x\n",
  295                0xB4, ess_read_x_reg(sc, 0xB4));
  296         printf("Audio 1 play vol (unused): mix reg 0x%02x=0x%02x\n",
  297                0x14, ess_read_mix_reg(sc, 0x14));
  298 
  299         printf("ESS_MIC_PREAMP: x reg 0x%02x=0x%02x\n",
  300                ESS_XCMD_PREAMP_CTRL, ess_read_x_reg(sc, ESS_XCMD_PREAMP_CTRL));
  301         printf("ESS_RECORD_MONITOR: x reg 0x%02x=0x%02x\n",
  302                ESS_XCMD_AUDIO_CTRL, ess_read_x_reg(sc, ESS_XCMD_AUDIO_CTRL));
  303         printf("Record source: mix reg 0x%02x=0x%02x, 0x%02x=0x%02x\n",
  304                ESS_MREG_ADC_SOURCE, ess_read_mix_reg(sc, ESS_MREG_ADC_SOURCE),
  305                ESS_MREG_AUDIO2_CTRL2, ess_read_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2));
  306 }
  307 
  308 #endif
  309 
  310 /*
  311  * Configure the ESS chip for the desired audio base address.
  312  */
  313 int
  314 ess_config_addr(struct ess_softc *sc)
  315 {
  316         int iobase = sc->sc_iobase;
  317         bus_space_tag_t iot = sc->sc_iot;
  318 
  319         /*
  320          * Configure using the System Control Register method.  This
  321          * method is used when the AMODE line is tied high, which is
  322          * the case for the Shark, but not for the evaluation board.
  323          */
  324 
  325         bus_space_handle_t scr_access_ioh;
  326         bus_space_handle_t scr_ioh;
  327         u_short scr_value;
  328 
  329         /*
  330          * Set the SCR bit to enable audio.
  331          */
  332         scr_value = ESS_SCR_AUDIO_ENABLE;
  333 
  334         /*
  335          * Set the SCR bits necessary to select the specified audio
  336          * base address.
  337          */
  338         switch(iobase) {
  339         case 0x220:
  340                 scr_value |= ESS_SCR_AUDIO_220;
  341                 break;
  342         case 0x230:
  343                 scr_value |= ESS_SCR_AUDIO_230;
  344                 break;
  345         case 0x240:
  346                 scr_value |= ESS_SCR_AUDIO_240;
  347                 break;
  348         case 0x250:
  349                 scr_value |= ESS_SCR_AUDIO_250;
  350                 break;
  351         default:
  352                 printf("ess: configured iobase 0x%x invalid\n", iobase);
  353                 return (1);
  354                 break;
  355         }
  356 
  357         /*
  358          * Get a mapping for the System Control Register (SCR) access
  359          * registers and the SCR data registers.
  360          */
  361         if (bus_space_map(iot, ESS_SCR_ACCESS_BASE, ESS_SCR_ACCESS_PORTS,
  362                           0, &scr_access_ioh)) {
  363                 printf("ess: can't map SCR access registers\n");
  364                 return (1);
  365         }
  366         if (bus_space_map(iot, ESS_SCR_BASE, ESS_SCR_PORTS,
  367                           0, &scr_ioh)) {
  368                 printf("ess: can't map SCR registers\n");
  369                 bus_space_unmap(iot, scr_access_ioh, ESS_SCR_ACCESS_PORTS);
  370                 return (1);
  371         }
  372 
  373         /* Unlock the SCR. */
  374         EWRITE1(iot, scr_access_ioh, ESS_SCR_UNLOCK, 0);
  375 
  376         /* Write the base address information into SCR[0]. */
  377         EWRITE1(iot, scr_ioh, ESS_SCR_INDEX, 0);
  378         EWRITE1(iot, scr_ioh, ESS_SCR_DATA, scr_value);
  379 
  380         /* Lock the SCR. */
  381         EWRITE1(iot, scr_access_ioh, ESS_SCR_LOCK, 0);
  382 
  383         /* Unmap the SCR access ports and the SCR data ports. */
  384         bus_space_unmap(iot, scr_access_ioh, ESS_SCR_ACCESS_PORTS);
  385         bus_space_unmap(iot, scr_ioh, ESS_SCR_PORTS);
  386 
  387         return 0;
  388 }
  389 
  390 
  391 /*
  392  * Configure the ESS chip for the desired IRQ and DMA channels.
  393  * ESS  ISA
  394  * --------
  395  * IRQA irq9
  396  * IRQB irq5
  397  * IRQC irq7
  398  * IRQD irq10
  399  * IRQE irq15
  400  *
  401  * DRQA drq0
  402  * DRQB drq1
  403  * DRQC drq3
  404  * DRQD drq5
  405  */
  406 void
  407 ess_config_irq(struct ess_softc *sc)
  408 {
  409         int v;
  410 
  411         DPRINTFN(2,("ess_config_irq\n"));
  412 
  413         if (sc->sc_model == ESS_1887 &&
  414             sc->sc_audio1.irq == sc->sc_audio2.irq &&
  415             sc->sc_audio1.irq != -1) {
  416                 /* Use new method, both interrupts are the same. */
  417                 v = ESS_IS_SELECT_IRQ;  /* enable intrs */
  418                 switch (sc->sc_audio1.irq) {
  419                 case 5:
  420                         v |= ESS_IS_INTRB;
  421                         break;
  422                 case 7:
  423                         v |= ESS_IS_INTRC;
  424                         break;
  425                 case 9:
  426                         v |= ESS_IS_INTRA;
  427                         break;
  428                 case 10:
  429                         v |= ESS_IS_INTRD;
  430                         break;
  431                 case 15:
  432                         v |= ESS_IS_INTRE;
  433                         break;
  434 #ifdef DIAGNOSTIC
  435                 default:
  436                         printf("ess_config_irq: configured irq %d not supported for Audio 1\n",
  437                                sc->sc_audio1.irq);
  438                         return;
  439 #endif
  440                 }
  441                 /* Set the IRQ */
  442                 ess_write_mix_reg(sc, ESS_MREG_INTR_ST, v);
  443                 return;
  444         }
  445 
  446         if (sc->sc_model == ESS_1887) {
  447                 /* Tell the 1887 to use the old interrupt method. */
  448                 ess_write_mix_reg(sc, ESS_MREG_INTR_ST, ESS_IS_ES1888);
  449         }
  450 
  451         if (sc->sc_audio1.polled) {
  452                 /* Turn off Audio1 interrupts. */
  453                 v = 0;
  454         } else {
  455                 /* Configure Audio 1 for the appropriate IRQ line. */
  456                 v = ESS_IRQ_CTRL_MASK | ESS_IRQ_CTRL_EXT; /* All intrs on */
  457                 switch (sc->sc_audio1.irq) {
  458                 case 5:
  459                         v |= ESS_IRQ_CTRL_INTRB;
  460                         break;
  461                 case 7:
  462                         v |= ESS_IRQ_CTRL_INTRC;
  463                         break;
  464                 case 9:
  465                         v |= ESS_IRQ_CTRL_INTRA;
  466                         break;
  467                 case 10:
  468                         v |= ESS_IRQ_CTRL_INTRD;
  469                         break;
  470 #ifdef DIAGNOSTIC
  471                 default:
  472                         printf("ess: configured irq %d not supported for Audio 1\n",
  473                                sc->sc_audio1.irq);
  474                         return;
  475 #endif
  476                 }
  477         }
  478         ess_write_x_reg(sc, ESS_XCMD_IRQ_CTRL, v);
  479 
  480         if (ESS_USE_AUDIO1(sc->sc_model))
  481                 return;
  482 
  483         if (sc->sc_audio2.polled) {
  484                 /* Turn off Audio2 interrupts. */
  485                 ess_clear_mreg_bits(sc, ESS_MREG_AUDIO2_CTRL2,
  486                                     ESS_AUDIO2_CTRL2_IRQ2_ENABLE);
  487         } else {
  488                 /* Audio2 is hardwired to INTRE in this mode. */
  489                 ess_set_mreg_bits(sc, ESS_MREG_AUDIO2_CTRL2,
  490                                   ESS_AUDIO2_CTRL2_IRQ2_ENABLE);
  491         }
  492 }
  493 
  494 
  495 void
  496 ess_config_drq(struct ess_softc *sc)
  497 {
  498         int v;
  499 
  500         DPRINTFN(2,("ess_config_drq\n"));
  501 
  502         /* Configure Audio 1 (record) for DMA on the appropriate channel. */
  503         v = ESS_DRQ_CTRL_PU | ESS_DRQ_CTRL_EXT;
  504         switch (sc->sc_audio1.drq) {
  505         case 0:
  506                 v |= ESS_DRQ_CTRL_DRQA;
  507                 break;
  508         case 1:
  509                 v |= ESS_DRQ_CTRL_DRQB;
  510                 break;
  511         case 3:
  512                 v |= ESS_DRQ_CTRL_DRQC;
  513                 break;
  514 #ifdef DIAGNOSTIC
  515         default:
  516                 printf("ess_config_drq: configured dma chan %d not supported for Audio 1\n",
  517                        sc->sc_audio1.drq);
  518                 return;
  519 #endif
  520         }
  521         /* Set DRQ1 */
  522         ess_write_x_reg(sc, ESS_XCMD_DRQ_CTRL, v);
  523 
  524         if (ESS_USE_AUDIO1(sc->sc_model))
  525                 return;
  526 
  527         /* Configure DRQ2 */
  528         v = ESS_AUDIO2_CTRL3_DRQ_PD;
  529         switch (sc->sc_audio2.drq) {
  530         case 0:
  531                 v |= ESS_AUDIO2_CTRL3_DRQA;
  532                 break;
  533         case 1:
  534                 v |= ESS_AUDIO2_CTRL3_DRQB;
  535                 break;
  536         case 3:
  537                 v |= ESS_AUDIO2_CTRL3_DRQC;
  538                 break;
  539         case 5:
  540                 v |= ESS_AUDIO2_CTRL3_DRQD;
  541                 break;
  542 #ifdef DIAGNOSTIC
  543         default:
  544                 printf("ess_config_drq: configured dma chan %d not supported for Audio 2\n",
  545                        sc->sc_audio2.drq);
  546                 return;
  547 #endif
  548         }
  549         ess_write_mix_reg(sc, ESS_MREG_AUDIO2_CTRL3, v);
  550         /* Enable DMA 2 */
  551         ess_set_mreg_bits(sc, ESS_MREG_AUDIO2_CTRL2,
  552                           ESS_AUDIO2_CTRL2_DMA_ENABLE);
  553 }
  554 
  555 /*
  556  * Set up registers after a reset.
  557  */
  558 void
  559 ess_setup(struct ess_softc *sc)
  560 {
  561         ess_config_irq(sc);
  562         ess_config_drq(sc);
  563 
  564         DPRINTFN(2,("ess_setup: done\n"));
  565 }
  566 
  567 /*
  568  * Determine the model of ESS chip we are talking to.  Currently we
  569  * only support ES1888, ES1887 and ES888.  The method of determining
  570  * the chip is based on the information on page 27 of the ES1887 data
  571  * sheet.
  572  *
  573  * This routine sets the values of sc->sc_model and sc->sc_version.
  574  */
  575 int
  576 ess_identify(struct ess_softc *sc)
  577 {
  578         u_char reg1;
  579         u_char reg2;
  580         u_char reg3;
  581         u_int8_t ident[4];
  582 
  583         sc->sc_model = ESS_UNSUPPORTED;
  584         sc->sc_version = 0;
  585 
  586         memset(ident, 0, sizeof(ident));
  587 
  588         /*
  589          * 1. Check legacy ID bytes.  These should be 0x68 0x8n, where
  590          *    n >= 8 for an ES1887 or an ES888.  Other values indicate
  591          *    earlier (unsupported) chips.
  592          */
  593         ess_wdsp(sc, ESS_ACMD_LEGACY_ID);
  594 
  595         if ((reg1 = ess_rdsp(sc)) != 0x68) {
  596                 printf("ess: First ID byte wrong (0x%02x)\n", reg1);
  597                 return 1;
  598         }
  599 
  600         reg2 = ess_rdsp(sc);
  601         if (((reg2 & 0xf0) != 0x80) ||
  602             ((reg2 & 0x0f) < 8)) {
  603                 printf("ess: Second ID byte wrong (0x%02x)\n", reg2);
  604                 return 1;
  605         }
  606 
  607         /*
  608          * Store the ID bytes as the version.
  609          */
  610         sc->sc_version = (reg1 << 8) + reg2;
  611 
  612 
  613         /*
  614          * 2. Verify we can change bit 2 in mixer register 0x64.  This
  615          *    should be possible on all supported chips.
  616          */
  617         reg1 = ess_read_mix_reg(sc, ESS_MREG_VOLUME_CTRL);
  618         reg2 = reg1 ^ 0x04;  /* toggle bit 2 */
  619 
  620         ess_write_mix_reg(sc, ESS_MREG_VOLUME_CTRL, reg2);
  621 
  622         if (ess_read_mix_reg(sc, ESS_MREG_VOLUME_CTRL) != reg2) {
  623                 printf("ess: Hardware error (unable to toggle bit 2 of mixer register 0x64)\n");
  624                 return 1;
  625         }
  626 
  627         /*
  628          * Restore the original value of mixer register 0x64.
  629          */
  630         ess_write_mix_reg(sc, ESS_MREG_VOLUME_CTRL, reg1);
  631 
  632 
  633         /*
  634          * 3. Verify we can change the value of mixer register
  635          *    ESS_MREG_SAMPLE_RATE.
  636          *    This is possible on the 1888/1887/888, but not on the 1788.
  637          *    It is not necessary to restore the value of this mixer register.
  638          */
  639         reg1 = ess_read_mix_reg(sc, ESS_MREG_SAMPLE_RATE);
  640         reg2 = reg1 ^ 0xff;  /* toggle all bits */
  641 
  642         ess_write_mix_reg(sc, ESS_MREG_SAMPLE_RATE, reg2);
  643 
  644         if (ess_read_mix_reg(sc, ESS_MREG_SAMPLE_RATE) != reg2) {
  645                 /* If we got this far before failing, it's a 1788. */
  646                 sc->sc_model = ESS_1788;
  647 
  648                 /*
  649                  * Identify ESS model for ES18[67]8.
  650                  */
  651                 ess_read_multi_mix_reg(sc, 0x40, ident, sizeof(ident));
  652                 if(ident[0] == 0x18) {
  653                         switch(ident[1]) {
  654                         case 0x68:
  655                                 sc->sc_model = ESS_1868;
  656                                 break;
  657                         case 0x78:
  658                                 sc->sc_model = ESS_1878;
  659                                 break;
  660                         }
  661                 }
  662         } else {
  663                 /*
  664                  * 4. Determine if we can change bit 5 in mixer register 0x64.
  665                  *    This determines whether we have an ES1887:
  666                  *
  667                  *    - can change indicates ES1887
  668                  *    - can't change indicates ES1888 or ES888
  669                  */
  670                 reg1 = ess_read_mix_reg(sc, ESS_MREG_VOLUME_CTRL);
  671                 reg2 = reg1 ^ 0x20;  /* toggle bit 5 */
  672 
  673                 ess_write_mix_reg(sc, ESS_MREG_VOLUME_CTRL, reg2);
  674 
  675                 if (ess_read_mix_reg(sc, ESS_MREG_VOLUME_CTRL) == reg2) {
  676                         sc->sc_model = ESS_1887;
  677 
  678                         /*
  679                          * Restore the original value of mixer register 0x64.
  680                          */
  681                         ess_write_mix_reg(sc, ESS_MREG_VOLUME_CTRL, reg1);
  682 
  683                         /*
  684                          * Identify ESS model for ES18[67]9.
  685                          */
  686                         ess_read_multi_mix_reg(sc, 0x40, ident, sizeof(ident));
  687                         if(ident[0] == 0x18) {
  688                                 switch(ident[1]) {
  689                                 case 0x69:
  690                                         sc->sc_model = ESS_1869;
  691                                         break;
  692                                 case 0x79:
  693                                         sc->sc_model = ESS_1879;
  694                                         break;
  695                                 }
  696                         }
  697                 } else {
  698                         /*
  699                          * 5. Determine if we can change the value of mixer
  700                          *    register 0x69 independently of mixer register
  701                          *    0x68. This determines which chip we have:
  702                          *
  703                          *    - can modify independently indicates ES888
  704                          *    - register 0x69 is an alias of 0x68 indicates ES1888
  705                          */
  706                         reg1 = ess_read_mix_reg(sc, 0x68);
  707                         reg2 = ess_read_mix_reg(sc, 0x69);
  708                         reg3 = reg2 ^ 0xff;  /* toggle all bits */
  709 
  710                         /*
  711                          * Write different values to each register.
  712                          */
  713                         ess_write_mix_reg(sc, 0x68, reg2);
  714                         ess_write_mix_reg(sc, 0x69, reg3);
  715 
  716                         if (ess_read_mix_reg(sc, 0x68) == reg2 &&
  717                             ess_read_mix_reg(sc, 0x69) == reg3)
  718                                 sc->sc_model = ESS_888;
  719                         else
  720                                 sc->sc_model = ESS_1888;
  721 
  722                         /*
  723                          * Restore the original value of the registers.
  724                          */
  725                         ess_write_mix_reg(sc, 0x68, reg1);
  726                         ess_write_mix_reg(sc, 0x69, reg2);
  727                 }
  728         }
  729 
  730         return 0;
  731 }
  732 
  733 
  734 int
  735 ess_setup_sc(struct ess_softc *sc, int doinit)
  736 {
  737         /* Reset the chip. */
  738         if (ess_reset(sc) != 0) {
  739                 DPRINTF(("ess_setup_sc: couldn't reset chip\n"));
  740                 return (1);
  741         }
  742 
  743         /* Identify the ESS chip, and check that it is supported. */
  744         if (ess_identify(sc)) {
  745                 DPRINTF(("ess_setup_sc: couldn't identify\n"));
  746                 return (1);
  747         }
  748 
  749         return (0);
  750 }
  751 
  752 /*
  753  * Probe for the ESS hardware.
  754  */
  755 int
  756 essmatch(struct ess_softc *sc)
  757 {
  758         if (!ESS_BASE_VALID(sc->sc_iobase)) {
  759                 printf("ess: configured iobase 0x%x invalid\n", sc->sc_iobase);
  760                 return (0);
  761         }
  762 
  763         /* Configure the ESS chip for the desired audio base address. */
  764         if (ess_config_addr(sc))
  765                 return (0);
  766 
  767         if (ess_setup_sc(sc, 1))
  768                 return (0);
  769 
  770         if (sc->sc_model == ESS_UNSUPPORTED) {
  771                 DPRINTF(("ess: Unsupported model\n"));
  772                 return (0);
  773         }
  774 
  775         /* Check that requested DMA channels are valid and different. */
  776         if (!ESS_DRQ1_VALID(sc->sc_audio1.drq)) {
  777                 printf("ess: record drq %d invalid\n", sc->sc_audio1.drq);
  778                 return (0);
  779         }
  780         if (!isa_drq_isfree(sc->sc_isa, sc->sc_audio1.drq))
  781                 return (0);
  782         if (!ESS_USE_AUDIO1(sc->sc_model)) {
  783                 if (!ESS_DRQ2_VALID(sc->sc_audio2.drq)) {
  784                         printf("ess: play drq %d invalid\n", sc->sc_audio2.drq);
  785                         return (0);
  786                 }
  787                 if (sc->sc_audio1.drq == sc->sc_audio2.drq) {
  788                         printf("ess: play and record drq both %d\n",
  789                                sc->sc_audio1.drq);
  790                         return (0);
  791                 }
  792                 if (!isa_drq_isfree(sc->sc_isa, sc->sc_audio2.drq))
  793                         return (0);
  794         }
  795 
  796         /*
  797          * The 1887 has an additional IRQ mode where both channels are mapped
  798          * to the same IRQ.
  799          */
  800         if (sc->sc_model == ESS_1887 &&
  801             sc->sc_audio1.irq == sc->sc_audio2.irq &&
  802             sc->sc_audio1.irq != -1 &&
  803             ESS_IRQ12_VALID(sc->sc_audio1.irq))
  804                 goto irq_not1888;
  805 
  806         /* Check that requested IRQ lines are valid and different. */
  807         if (sc->sc_audio1.irq != -1 &&
  808             !ESS_IRQ1_VALID(sc->sc_audio1.irq)) {
  809                 printf("ess: record irq %d invalid\n", sc->sc_audio1.irq);
  810                 return (0);
  811         }
  812         if (!ESS_USE_AUDIO1(sc->sc_model)) {
  813                 if (sc->sc_audio2.irq != -1 &&
  814                     !ESS_IRQ2_VALID(sc->sc_audio2.irq)) {
  815                         printf("ess: play irq %d invalid\n", sc->sc_audio2.irq);
  816                         return (0);
  817                 }
  818                 if (sc->sc_audio1.irq == sc->sc_audio2.irq &&
  819                     sc->sc_audio1.irq != -1) {
  820                         printf("ess: play and record irq both %d\n",
  821                                sc->sc_audio1.irq);
  822                         return (0);
  823                 }
  824         }
  825 
  826 irq_not1888:
  827         /* XXX should we check IRQs as well? */
  828 
  829         return (1);
  830 }
  831 
  832 
  833 /*
  834  * Attach hardware to driver, attach hardware driver to audio
  835  * pseudo-device driver.
  836  */
  837 void
  838 essattach(struct ess_softc *sc)
  839 {
  840         struct audio_attach_args arg;
  841         struct audio_params pparams, rparams;
  842         int i;
  843         u_int v;
  844 
  845         if (ess_setup_sc(sc, 0)) {
  846                 printf(": setup failed\n");
  847                 return;
  848         }
  849 
  850         printf(": ESS Technology ES%s [version 0x%04x]\n",
  851                essmodel[sc->sc_model], sc->sc_version);
  852 
  853         sc->sc_audio1.polled = sc->sc_audio1.irq == -1;
  854         if (!sc->sc_audio1.polled) {
  855                 sc->sc_audio1.ih = isa_intr_establish(sc->sc_ic,
  856                     sc->sc_audio1.irq, sc->sc_audio1.ist,
  857                     IPL_AUDIO | IPL_MPSAFE,
  858                     ess_audio1_intr, sc, sc->sc_dev.dv_xname);
  859                 printf("%s: audio1 interrupting at irq %d\n",
  860                     sc->sc_dev.dv_xname, sc->sc_audio1.irq);
  861         } else
  862                 printf("%s: audio1 polled\n", sc->sc_dev.dv_xname);
  863         if (isa_dmamap_create(sc->sc_isa, sc->sc_audio1.drq,
  864             MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
  865                 printf("%s: can't create map for drq %d\n",
  866                        sc->sc_dev.dv_xname, sc->sc_audio1.drq);
  867                 return;
  868         }
  869 
  870         if (!ESS_USE_AUDIO1(sc->sc_model)) {
  871                 sc->sc_audio2.polled = sc->sc_audio2.irq == -1;
  872                 if (!sc->sc_audio2.polled) {
  873                         sc->sc_audio2.ih = isa_intr_establish(sc->sc_ic,
  874                             sc->sc_audio2.irq, sc->sc_audio2.ist,
  875                             IPL_AUDIO | IPL_MPSAFE,
  876                             ess_audio2_intr, sc, sc->sc_dev.dv_xname);
  877                         printf("%s: audio2 interrupting at irq %d\n",
  878                             sc->sc_dev.dv_xname, sc->sc_audio2.irq);
  879                 } else
  880                         printf("%s: audio2 polled\n", sc->sc_dev.dv_xname);
  881                 if (isa_dmamap_create(sc->sc_isa, sc->sc_audio2.drq,
  882                     MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
  883                         printf("%s: can't create map for drq %d\n",
  884                                sc->sc_dev.dv_xname, sc->sc_audio2.drq);
  885                         return;
  886                 }
  887         }
  888 
  889         timeout_set(&sc->sc_tmo1, ess_audio1_poll, sc);
  890         timeout_set(&sc->sc_tmo2, ess_audio2_poll, sc);
  891 
  892         /*
  893          * Set record and play parameters to default values defined in
  894          * generic audio driver.
  895          */
  896         pparams = ess_audio_default;
  897         rparams = ess_audio_default;
  898         ess_set_params(sc, AUMODE_RECORD|AUMODE_PLAY, 0, &pparams, &rparams);
  899 
  900         /* Do a hardware reset on the mixer. */
  901         ess_write_mix_reg(sc, ESS_MIX_RESET, ESS_MIX_RESET);
  902 
  903         /*
  904          * Set volume of Audio 1 to zero and disable Audio 1 DAC input
  905          * to playback mixer, since playback is always through Audio 2.
  906          */
  907         if (!ESS_USE_AUDIO1(sc->sc_model))
  908                 ess_write_mix_reg(sc, ESS_MREG_VOLUME_VOICE, 0);
  909         ess_wdsp(sc, ESS_ACMD_DISABLE_SPKR);
  910 
  911         if (ESS_USE_AUDIO1(sc->sc_model)) {
  912                 ess_write_mix_reg(sc, ESS_MREG_ADC_SOURCE, ESS_SOURCE_MIC);
  913                 sc->in_port = ESS_SOURCE_MIC;
  914                 sc->ndevs = ESS_1788_NDEVS;
  915         } else {
  916                 /*
  917                  * Set hardware record source to use output of the record
  918                  * mixer. We do the selection of record source in software by
  919                  * setting the gain of the unused sources to zero. (See
  920                  * ess_set_in_ports.)
  921                  */
  922                 ess_write_mix_reg(sc, ESS_MREG_ADC_SOURCE, ESS_SOURCE_MIXER);
  923                 sc->in_mask = 1 << ESS_MIC_REC_VOL;
  924                 sc->ndevs = ESS_1888_NDEVS;
  925                 ess_clear_mreg_bits(sc, ESS_MREG_AUDIO2_CTRL2, 0x10);
  926                 ess_set_mreg_bits(sc, ESS_MREG_AUDIO2_CTRL2, 0x08);
  927         }
  928 
  929         /*
  930          * Set gain on each mixer device to a sensible value.
  931          * Devices not normally used are turned off, and other devices
  932          * are set to 50% volume.
  933          */
  934         for (i = 0; i < sc->ndevs; i++) {
  935                 switch (i) {
  936                 case ESS_MIC_PLAY_VOL:
  937                 case ESS_LINE_PLAY_VOL:
  938                 case ESS_CD_PLAY_VOL:
  939                 case ESS_AUXB_PLAY_VOL:
  940                 case ESS_DAC_REC_VOL:
  941                 case ESS_LINE_REC_VOL:
  942                 case ESS_SYNTH_REC_VOL:
  943                 case ESS_CD_REC_VOL:
  944                 case ESS_AUXB_REC_VOL:
  945                         v = 0;
  946                         break;
  947                 default:
  948                         v = ESS_4BIT_GAIN(AUDIO_MAX_GAIN / 2);
  949                         break;
  950                 }
  951                 sc->gain[i][ESS_LEFT] = sc->gain[i][ESS_RIGHT] = v;
  952                 ess_set_gain(sc, i, 1);
  953         }
  954 
  955         ess_setup(sc);
  956 
  957         /* Disable the speaker until the device is opened.  */
  958         ess_speaker_off(sc);
  959         sc->spkr_state = SPKR_OFF;
  960 
  961         if (ESS_USE_AUDIO1(sc->sc_model))
  962                 audio_attach_mi(&ess_1788_hw_if, sc, NULL, &sc->sc_dev);
  963         else
  964                 audio_attach_mi(&ess_1888_hw_if, sc, NULL, &sc->sc_dev);
  965 
  966         arg.type = AUDIODEV_TYPE_OPL;
  967         arg.hwif = 0;
  968         arg.hdl = 0;
  969         (void)config_found(&sc->sc_dev, &arg, audioprint);
  970 
  971 #ifdef AUDIO_DEBUG
  972         if (essdebug > 0)
  973                 ess_printsc(sc);
  974 #endif
  975 }
  976 
  977 /*
  978  * Various routines to interface to higher level audio driver
  979  */
  980 
  981 int
  982 ess_1788_open(void *addr, int flags)
  983 {
  984         if ((flags & (FWRITE | FREAD)) == (FWRITE | FREAD))
  985                 return ENXIO;
  986 
  987         return ess_open(addr, flags);
  988 }
  989 
  990 int
  991 ess_open(void *addr, int flags)
  992 {
  993         struct ess_softc *sc = addr;
  994 
  995         DPRINTF(("ess_open: sc=%p\n", sc));
  996 
  997         if (sc->sc_open != 0 || ess_reset(sc) != 0)
  998                 return ENXIO;
  999 
 1000         ess_setup(sc);          /* because we did a reset */
 1001 
 1002         ess_speaker_ctl(sc, (flags & FWRITE) ? SPKR_ON : SPKR_OFF);
 1003 
 1004         sc->sc_open = 1;
 1005 
 1006         DPRINTF(("ess_open: opened\n"));
 1007 
 1008         return (0);
 1009 }
 1010 
 1011 void
 1012 ess_1788_close(void *addr)
 1013 {
 1014         struct ess_softc *sc = addr;
 1015 
 1016         DPRINTF(("ess_1788_close: sc=%p\n", sc));
 1017 
 1018         ess_speaker_off(sc);
 1019         sc->spkr_state = SPKR_OFF;
 1020 
 1021         ess_audio1_halt(sc);
 1022 
 1023         sc->sc_open = 0;
 1024         DPRINTF(("ess_1788_close: closed\n"));
 1025 }
 1026 
 1027 void
 1028 ess_1888_close(void *addr)
 1029 {
 1030         struct ess_softc *sc = addr;
 1031 
 1032         DPRINTF(("ess_1888_close: sc=%p\n", sc));
 1033 
 1034         ess_speaker_off(sc);
 1035         sc->spkr_state = SPKR_OFF;
 1036 
 1037         ess_audio1_halt(sc);
 1038         ess_audio2_halt(sc);
 1039 
 1040         sc->sc_open = 0;
 1041         DPRINTF(("ess_1888_close: closed\n"));
 1042 }
 1043 
 1044 /* XXX should use reference count */
 1045 int
 1046 ess_speaker_ctl(void *addr, int newstate)
 1047 {
 1048         struct ess_softc *sc = addr;
 1049 
 1050         if ((newstate == SPKR_ON) && (sc->spkr_state == SPKR_OFF)) {
 1051                 ess_speaker_on(sc);
 1052                 sc->spkr_state = SPKR_ON;
 1053         }
 1054         if ((newstate == SPKR_OFF) && (sc->spkr_state == SPKR_ON)) {
 1055                 ess_speaker_off(sc);
 1056                 sc->spkr_state = SPKR_OFF;
 1057         }
 1058         return (0);
 1059 }
 1060 
 1061 int
 1062 ess_set_params(void *addr, int setmode, int usemode,
 1063     struct audio_params *play, struct audio_params *rec)
 1064 {
 1065         struct ess_softc *sc = addr;
 1066         struct audio_params *p;
 1067         int mode;
 1068         int rate;
 1069 
 1070         DPRINTF(("ess_set_params: set=%d use=%d\n", setmode, usemode));
 1071 
 1072         /*
 1073          * The ES1887 manual (page 39, `Full-Duplex DMA Mode') claims that in
 1074          * full-duplex operation the sample rates must be the same for both
 1075          * channels.  This appears to be false; the only bit in common is the
 1076          * clock source selection.  However, we'll be conservative here.
 1077          * - mycroft
 1078          */
 1079         if (play->sample_rate != rec->sample_rate &&
 1080             usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
 1081                 if (setmode == AUMODE_PLAY) {
 1082                         rec->sample_rate = play->sample_rate;
 1083                         setmode |= AUMODE_RECORD;
 1084                 } else if (setmode == AUMODE_RECORD) {
 1085                         play->sample_rate = rec->sample_rate;
 1086                         setmode |= AUMODE_PLAY;
 1087                 } else
 1088                         return (EINVAL);
 1089         }
 1090 
 1091         for (mode = AUMODE_RECORD; mode != -1;
 1092              mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
 1093                 if ((setmode & mode) == 0)
 1094                         continue;
 1095 
 1096                 p = mode == AUMODE_PLAY ? play : rec;
 1097 
 1098                 if (p->sample_rate < ESS_MINRATE)
 1099                         p->sample_rate = ESS_MINRATE;
 1100                 if (p->sample_rate > ESS_MAXRATE)
 1101                         p->sample_rate = ESS_MAXRATE;
 1102                 if (p->precision > 16)
 1103                         p->precision = 16;
 1104                 if (p->channels > 2)
 1105                         p->channels = 2;
 1106 
 1107                 switch (p->encoding) {
 1108                 case AUDIO_ENCODING_SLINEAR_BE:
 1109                 case AUDIO_ENCODING_ULINEAR_BE:
 1110                         if (p->precision != 8)
 1111                                 return EINVAL;
 1112                         break;
 1113                 case AUDIO_ENCODING_SLINEAR_LE:
 1114                 case AUDIO_ENCODING_ULINEAR_LE:
 1115                         break;
 1116                 default:
 1117                         return (EINVAL);
 1118                 }
 1119                 p->bps = AUDIO_BPS(p->precision);
 1120                 p->msb = 1;
 1121         }
 1122 
 1123         if (usemode == AUMODE_RECORD)
 1124                 rate = rec->sample_rate;
 1125         else
 1126                 rate = play->sample_rate;
 1127 
 1128         ess_write_x_reg(sc, ESS_XCMD_SAMPLE_RATE, ess_srtotc(rate));
 1129         ess_write_x_reg(sc, ESS_XCMD_FILTER_CLOCK, ess_srtofc(rate));
 1130 
 1131         if (!ESS_USE_AUDIO1(sc->sc_model)) {
 1132                 ess_write_mix_reg(sc, ESS_MREG_SAMPLE_RATE, ess_srtotc(rate));
 1133                 ess_write_mix_reg(sc, ESS_MREG_FILTER_CLOCK, ess_srtofc(rate));
 1134         }
 1135 
 1136         return (0);
 1137 }
 1138 
 1139 int
 1140 ess_audio1_trigger_output(void *addr, void *start, void *end, int blksize,
 1141     void (*intr)(void *), void *arg, struct audio_params *param)
 1142 {
 1143         struct ess_softc *sc = addr;
 1144         u_int8_t reg;
 1145 
 1146         mtx_enter(&audio_lock);
 1147         DPRINTFN(1, ("ess_audio1_trigger_output: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
 1148             addr, start, end, blksize, intr, arg));
 1149 
 1150         if (sc->sc_audio1.active)
 1151                 panic("ess_audio1_trigger_output: already running");
 1152 
 1153         sc->sc_audio1.active = 1;
 1154         sc->sc_audio1.intr = intr;
 1155         sc->sc_audio1.arg = arg;
 1156         if (sc->sc_audio1.polled) {
 1157                 sc->sc_audio1.dmapos = 0;
 1158                 sc->sc_audio1.buffersize = (char *)end - (char *)start;
 1159                 sc->sc_audio1.dmacount = 0;
 1160                 sc->sc_audio1.blksize = blksize;
 1161                 timeout_add_msec(&sc->sc_tmo1, 1000/30);
 1162         }
 1163 
 1164         reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO_CTRL);
 1165         if (param->channels == 2) {
 1166                 reg &= ~ESS_AUDIO_CTRL_MONO;
 1167                 reg |= ESS_AUDIO_CTRL_STEREO;
 1168         } else {
 1169                 reg |= ESS_AUDIO_CTRL_MONO;
 1170                 reg &= ~ESS_AUDIO_CTRL_STEREO;
 1171         }
 1172         ess_write_x_reg(sc, ESS_XCMD_AUDIO_CTRL, reg);
 1173 
 1174         reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO1_CTRL1);
 1175         if (param->precision == 16)
 1176                 reg |= ESS_AUDIO1_CTRL1_FIFO_SIZE;
 1177         else
 1178                 reg &= ~ESS_AUDIO1_CTRL1_FIFO_SIZE;
 1179         if (param->channels == 2)
 1180                 reg |= ESS_AUDIO1_CTRL1_FIFO_STEREO;
 1181         else
 1182                 reg &= ~ESS_AUDIO1_CTRL1_FIFO_STEREO;
 1183         if (param->encoding == AUDIO_ENCODING_SLINEAR_BE ||
 1184             param->encoding == AUDIO_ENCODING_SLINEAR_LE)
 1185                 reg |= ESS_AUDIO1_CTRL1_FIFO_SIGNED;
 1186         else
 1187                 reg &= ~ESS_AUDIO1_CTRL1_FIFO_SIGNED;
 1188         reg |= ESS_AUDIO1_CTRL1_FIFO_CONNECT;
 1189         ess_write_x_reg(sc, ESS_XCMD_AUDIO1_CTRL1, reg);
 1190 
 1191         isa_dmastart(sc->sc_isa, sc->sc_audio1.drq, start,
 1192                      (char *)end - (char *)start, NULL,
 1193             DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
 1194 
 1195         /* Program transfer count registers with 2's complement of count. */
 1196         blksize = -blksize;
 1197         ess_write_x_reg(sc, ESS_XCMD_XFER_COUNTLO, blksize);
 1198         ess_write_x_reg(sc, ESS_XCMD_XFER_COUNTHI, blksize >> 8);
 1199 
 1200         /* Use 4 bytes per output DMA. */
 1201         ess_set_xreg_bits(sc, ESS_XCMD_DEMAND_CTRL, ESS_DEMAND_CTRL_DEMAND_4);
 1202 
 1203         /* Start auto-init DMA */
 1204         ess_wdsp(sc, ESS_ACMD_ENABLE_SPKR);
 1205         reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO1_CTRL2);
 1206         reg &= ~(ESS_AUDIO1_CTRL2_DMA_READ | ESS_AUDIO1_CTRL2_ADC_ENABLE);
 1207         reg |= ESS_AUDIO1_CTRL2_FIFO_ENABLE | ESS_AUDIO1_CTRL2_AUTO_INIT;
 1208         ess_write_x_reg(sc, ESS_XCMD_AUDIO1_CTRL2, reg);
 1209         mtx_leave(&audio_lock);
 1210         return (0);
 1211 }
 1212 
 1213 int
 1214 ess_audio2_trigger_output(void *addr, void *start, void *end, int blksize,
 1215     void (*intr)(void *), void *arg, struct audio_params *param)
 1216 {
 1217         struct ess_softc *sc = addr;
 1218         u_int8_t reg;
 1219 
 1220         mtx_enter(&audio_lock);
 1221         DPRINTFN(1, ("ess_audio2_trigger_output: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
 1222             addr, start, end, blksize, intr, arg));
 1223 
 1224         if (sc->sc_audio2.active)
 1225                 panic("ess_audio2_trigger_output: already running");
 1226 
 1227         sc->sc_audio2.active = 1;
 1228         sc->sc_audio2.intr = intr;
 1229         sc->sc_audio2.arg = arg;
 1230         if (sc->sc_audio2.polled) {
 1231                 sc->sc_audio2.dmapos = 0;
 1232                 sc->sc_audio2.buffersize = (char *)end - (char *)start;
 1233                 sc->sc_audio2.dmacount = 0;
 1234                 sc->sc_audio2.blksize = blksize;
 1235                 timeout_add_msec(&sc->sc_tmo2, 1000/30);
 1236         }
 1237 
 1238         reg = ess_read_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2);
 1239         if (param->precision == 16)
 1240                 reg |= ESS_AUDIO2_CTRL2_FIFO_SIZE;
 1241         else
 1242                 reg &= ~ESS_AUDIO2_CTRL2_FIFO_SIZE;
 1243         if (param->channels == 2)
 1244                 reg |= ESS_AUDIO2_CTRL2_CHANNELS;
 1245         else
 1246                 reg &= ~ESS_AUDIO2_CTRL2_CHANNELS;
 1247         if (param->encoding == AUDIO_ENCODING_SLINEAR_BE ||
 1248             param->encoding == AUDIO_ENCODING_SLINEAR_LE)
 1249                 reg |= ESS_AUDIO2_CTRL2_FIFO_SIGNED;
 1250         else
 1251                 reg &= ~ESS_AUDIO2_CTRL2_FIFO_SIGNED;
 1252         ess_write_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2, reg);
 1253 
 1254         isa_dmastart(sc->sc_isa, sc->sc_audio2.drq, start,
 1255                      (char *)end - (char *)start, NULL,
 1256             DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
 1257 
 1258         if (IS16BITDRQ(sc->sc_audio2.drq))
 1259                 blksize >>= 1;  /* use word count for 16 bit DMA */
 1260         /* Program transfer count registers with 2's complement of count. */
 1261         blksize = -blksize;
 1262         ess_write_mix_reg(sc, ESS_MREG_XFER_COUNTLO, blksize);
 1263         ess_write_mix_reg(sc, ESS_MREG_XFER_COUNTHI, blksize >> 8);
 1264 
 1265         reg = ess_read_mix_reg(sc, ESS_MREG_AUDIO2_CTRL1);
 1266         if (IS16BITDRQ(sc->sc_audio2.drq))
 1267                 reg |= ESS_AUDIO2_CTRL1_XFER_SIZE;
 1268         else
 1269                 reg &= ~ESS_AUDIO2_CTRL1_XFER_SIZE;
 1270         reg |= ESS_AUDIO2_CTRL1_DEMAND_8;
 1271         reg |= ESS_AUDIO2_CTRL1_DAC_ENABLE | ESS_AUDIO2_CTRL1_FIFO_ENABLE |
 1272                ESS_AUDIO2_CTRL1_AUTO_INIT;
 1273         ess_write_mix_reg(sc, ESS_MREG_AUDIO2_CTRL1, reg);
 1274         mtx_leave(&audio_lock);
 1275         return (0);
 1276 }
 1277 
 1278 int
 1279 ess_audio1_trigger_input(void *addr, void *start, void *end, int blksize,
 1280     void (*intr)(void *), void *arg, struct audio_params *param)
 1281 {
 1282         struct ess_softc *sc = addr;
 1283         u_int8_t reg;
 1284 
 1285         mtx_enter(&audio_lock);
 1286         DPRINTFN(1, ("ess_audio1_trigger_input: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
 1287             addr, start, end, blksize, intr, arg));
 1288 
 1289         if (sc->sc_audio1.active)
 1290                 panic("ess_audio1_trigger_input: already running");
 1291 
 1292         sc->sc_audio1.active = 1;
 1293         sc->sc_audio1.intr = intr;
 1294         sc->sc_audio1.arg = arg;
 1295         if (sc->sc_audio1.polled) {
 1296                 sc->sc_audio1.dmapos = 0;
 1297                 sc->sc_audio1.buffersize = (char *)end - (char *)start;
 1298                 sc->sc_audio1.dmacount = 0;
 1299                 sc->sc_audio1.blksize = blksize;
 1300                 timeout_add_msec(&sc->sc_tmo1, 1000/30);
 1301         }
 1302 
 1303         reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO_CTRL);
 1304         if (param->channels == 2) {
 1305                 reg &= ~ESS_AUDIO_CTRL_MONO;
 1306                 reg |= ESS_AUDIO_CTRL_STEREO;
 1307         } else {
 1308                 reg |= ESS_AUDIO_CTRL_MONO;
 1309                 reg &= ~ESS_AUDIO_CTRL_STEREO;
 1310         }
 1311         ess_write_x_reg(sc, ESS_XCMD_AUDIO_CTRL, reg);
 1312 
 1313         reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO1_CTRL1);
 1314         if (param->precision == 16)
 1315                 reg |= ESS_AUDIO1_CTRL1_FIFO_SIZE;
 1316         else
 1317                 reg &= ~ESS_AUDIO1_CTRL1_FIFO_SIZE;
 1318         if (param->channels == 2)
 1319                 reg |= ESS_AUDIO1_CTRL1_FIFO_STEREO;
 1320         else
 1321                 reg &= ~ESS_AUDIO1_CTRL1_FIFO_STEREO;
 1322         if (param->encoding == AUDIO_ENCODING_SLINEAR_BE ||
 1323             param->encoding == AUDIO_ENCODING_SLINEAR_LE)
 1324                 reg |= ESS_AUDIO1_CTRL1_FIFO_SIGNED;
 1325         else
 1326                 reg &= ~ESS_AUDIO1_CTRL1_FIFO_SIGNED;
 1327         reg |= ESS_AUDIO1_CTRL1_FIFO_CONNECT;
 1328         ess_write_x_reg(sc, ESS_XCMD_AUDIO1_CTRL1, reg);
 1329 
 1330         isa_dmastart(sc->sc_isa, sc->sc_audio1.drq, start,
 1331                      (char *)end - (char *)start, NULL,
 1332             DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT);
 1333 
 1334         /* Program transfer count registers with 2's complement of count. */
 1335         blksize = -blksize;
 1336         ess_write_x_reg(sc, ESS_XCMD_XFER_COUNTLO, blksize);
 1337         ess_write_x_reg(sc, ESS_XCMD_XFER_COUNTHI, blksize >> 8);
 1338 
 1339         /* Use 4 bytes per input DMA. */
 1340         ess_set_xreg_bits(sc, ESS_XCMD_DEMAND_CTRL, ESS_DEMAND_CTRL_DEMAND_4);
 1341 
 1342         /* Start auto-init DMA */
 1343         ess_wdsp(sc, ESS_ACMD_DISABLE_SPKR);
 1344         reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO1_CTRL2);
 1345         reg |= ESS_AUDIO1_CTRL2_DMA_READ | ESS_AUDIO1_CTRL2_ADC_ENABLE;
 1346         reg |= ESS_AUDIO1_CTRL2_FIFO_ENABLE | ESS_AUDIO1_CTRL2_AUTO_INIT;
 1347         ess_write_x_reg(sc, ESS_XCMD_AUDIO1_CTRL2, reg);
 1348         mtx_leave(&audio_lock);
 1349         return (0);
 1350 }
 1351 
 1352 int
 1353 ess_audio1_halt(void *addr)
 1354 {
 1355         struct ess_softc *sc = addr;
 1356 
 1357         DPRINTF(("ess_audio1_halt: sc=%p\n", sc));
 1358         mtx_enter(&audio_lock);
 1359         if (sc->sc_audio1.active) {
 1360                 ess_clear_xreg_bits(sc, ESS_XCMD_AUDIO1_CTRL2,
 1361                     ESS_AUDIO1_CTRL2_FIFO_ENABLE);
 1362                 isa_dmaabort(sc->sc_isa, sc->sc_audio1.drq);
 1363                 if (sc->sc_audio1.polled)
 1364                         timeout_del(&sc->sc_tmo1);
 1365                 sc->sc_audio1.active = 0;
 1366         }
 1367         mtx_leave(&audio_lock);
 1368         return (0);
 1369 }
 1370 
 1371 int
 1372 ess_audio2_halt(void *addr)
 1373 {
 1374         struct ess_softc *sc = addr;
 1375 
 1376         DPRINTF(("ess_audio2_halt: sc=%p\n", sc));
 1377         mtx_enter(&audio_lock);
 1378         if (sc->sc_audio2.active) {
 1379                 ess_clear_mreg_bits(sc, ESS_MREG_AUDIO2_CTRL1,
 1380                     ESS_AUDIO2_CTRL1_DAC_ENABLE |
 1381                     ESS_AUDIO2_CTRL1_FIFO_ENABLE);
 1382                 isa_dmaabort(sc->sc_isa, sc->sc_audio2.drq);
 1383                 if (sc->sc_audio2.polled)
 1384                         timeout_del(&sc->sc_tmo2);
 1385                 sc->sc_audio2.active = 0;
 1386         }
 1387         mtx_leave(&audio_lock);
 1388         return (0);
 1389 }
 1390 
 1391 int
 1392 ess_audio1_intr(void *arg)
 1393 {
 1394         struct ess_softc *sc = arg;
 1395         u_int8_t reg;
 1396 
 1397         DPRINTFN(1,("ess_audio1_intr: intr=%p\n", sc->sc_audio1.intr));
 1398 
 1399         mtx_enter(&audio_lock);
 1400         /* Check and clear interrupt on Audio1. */
 1401         reg = EREAD1(sc->sc_iot, sc->sc_ioh, ESS_DSP_RW_STATUS);
 1402         if ((reg & ESS_DSP_READ_OFLOW) == 0) {
 1403                 mtx_leave(&audio_lock);
 1404                 return (0);
 1405         }
 1406         reg = EREAD1(sc->sc_iot, sc->sc_ioh, ESS_CLEAR_INTR);
 1407 
 1408         sc->sc_audio1.nintr++;
 1409 
 1410         if (sc->sc_audio1.active) {
 1411                 (*sc->sc_audio1.intr)(sc->sc_audio1.arg);
 1412                 mtx_leave(&audio_lock);
 1413                 return (1);
 1414         } else {
 1415                 mtx_leave(&audio_lock);
 1416                 return (0);
 1417         }
 1418 }
 1419 
 1420 int
 1421 ess_audio2_intr(void *arg)
 1422 {
 1423         struct ess_softc *sc = arg;
 1424         u_int8_t reg;
 1425 
 1426         DPRINTFN(1,("ess_audio2_intr: intr=%p\n", sc->sc_audio2.intr));
 1427 
 1428         mtx_enter(&audio_lock);
 1429         /* Check and clear interrupt on Audio2. */
 1430         reg = ess_read_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2);
 1431         if ((reg & ESS_AUDIO2_CTRL2_IRQ_LATCH) == 0) {
 1432                 mtx_leave(&audio_lock);
 1433                 return (0);
 1434         }
 1435         reg &= ~ESS_AUDIO2_CTRL2_IRQ_LATCH;
 1436         ess_write_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2, reg);
 1437 
 1438         sc->sc_audio2.nintr++;
 1439 
 1440         if (sc->sc_audio2.active) {
 1441                 (*sc->sc_audio2.intr)(sc->sc_audio2.arg);
 1442                 mtx_leave(&audio_lock);
 1443                 return (1);
 1444         } else {
 1445                 mtx_leave(&audio_lock);
 1446                 return (0);
 1447         }
 1448 }
 1449 
 1450 void
 1451 ess_audio1_poll(void *addr)
 1452 {
 1453         struct ess_softc *sc = addr;
 1454         int dmapos, dmacount;
 1455 
 1456         if (!sc->sc_audio1.active)
 1457                 return;
 1458 
 1459         mtx_enter(&audio_lock);
 1460         sc->sc_audio1.nintr++;
 1461 
 1462         dmapos = isa_dmacount(sc->sc_isa, sc->sc_audio1.drq);
 1463         dmacount = sc->sc_audio1.dmapos - dmapos;
 1464         if (dmacount < 0)
 1465                 dmacount += sc->sc_audio1.buffersize;
 1466         sc->sc_audio1.dmapos = dmapos;
 1467 #if 1
 1468         dmacount += sc->sc_audio1.dmacount;
 1469         while (dmacount > sc->sc_audio1.blksize) {
 1470                 dmacount -= sc->sc_audio1.blksize;
 1471                 (*sc->sc_audio1.intr)(sc->sc_audio1.arg);
 1472         }
 1473         sc->sc_audio1.dmacount = dmacount;
 1474 #else
 1475         (*sc->sc_audio1.intr)(sc->sc_audio1.arg, dmacount);
 1476 #endif
 1477         timeout_add_msec(&sc->sc_tmo1, 1000/30);
 1478         mtx_leave(&audio_lock);
 1479 }
 1480 
 1481 void
 1482 ess_audio2_poll(void *addr)
 1483 {
 1484         struct ess_softc *sc = addr;
 1485         int dmapos, dmacount;
 1486 
 1487         if (!sc->sc_audio2.active)
 1488                 return;
 1489 
 1490         mtx_enter(&audio_lock);
 1491         sc->sc_audio2.nintr++;
 1492 
 1493         dmapos = isa_dmacount(sc->sc_isa, sc->sc_audio2.drq);
 1494         dmacount = sc->sc_audio2.dmapos - dmapos;
 1495         if (dmacount < 0)
 1496                 dmacount += sc->sc_audio2.buffersize;
 1497         sc->sc_audio2.dmapos = dmapos;
 1498 #if 1
 1499         dmacount += sc->sc_audio2.dmacount;
 1500         while (dmacount > sc->sc_audio2.blksize) {
 1501                 dmacount -= sc->sc_audio2.blksize;
 1502                 (*sc->sc_audio2.intr)(sc->sc_audio2.arg);
 1503         }
 1504         sc->sc_audio2.dmacount = dmacount;
 1505 #else
 1506         (*sc->sc_audio2.intr)(sc->sc_audio2.arg, dmacount);
 1507 #endif
 1508         timeout_add_msec(&sc->sc_tmo2, 1000/30);
 1509         mtx_leave(&audio_lock);
 1510 }
 1511 
 1512 int
 1513 ess_round_blocksize(void *addr, int blk)
 1514 {
 1515         return ((blk + 7) & -8);        /* round for max DMA size */
 1516 }
 1517 
 1518 int
 1519 ess_set_port(void *addr, mixer_ctrl_t *cp)
 1520 {
 1521         struct ess_softc *sc = addr;
 1522         int lgain, rgain;
 1523 
 1524         DPRINTFN(5,("ess_set_port: port=%d num_channels=%d\n",
 1525                     cp->dev, cp->un.value.num_channels));
 1526 
 1527         switch (cp->dev) {
 1528         /*
 1529          * The following mixer ports are all stereo. If we get a
 1530          * single-channel gain value passed in, then we duplicate it
 1531          * to both left and right channels.
 1532          */
 1533         case ESS_MASTER_VOL:
 1534         case ESS_DAC_PLAY_VOL:
 1535         case ESS_MIC_PLAY_VOL:
 1536         case ESS_LINE_PLAY_VOL:
 1537         case ESS_SYNTH_PLAY_VOL:
 1538         case ESS_CD_PLAY_VOL:
 1539         case ESS_AUXB_PLAY_VOL:
 1540         case ESS_RECORD_VOL:
 1541                 if (cp->type != AUDIO_MIXER_VALUE)
 1542                         return EINVAL;
 1543 
 1544                 switch (cp->un.value.num_channels) {
 1545                 case 1:
 1546                         lgain = rgain = ESS_4BIT_GAIN(
 1547                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
 1548                         break;
 1549                 case 2:
 1550                         lgain = ESS_4BIT_GAIN(
 1551                           cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
 1552                         rgain = ESS_4BIT_GAIN(
 1553                           cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
 1554                         break;
 1555                 default:
 1556                         return EINVAL;
 1557                 }
 1558 
 1559                 sc->gain[cp->dev][ESS_LEFT]  = lgain;
 1560                 sc->gain[cp->dev][ESS_RIGHT] = rgain;
 1561                 ess_set_gain(sc, cp->dev, 1);
 1562                 return (0);
 1563 
 1564         /*
 1565          * The PC speaker port is mono. If we get a stereo gain value
 1566          * passed in, then we return EINVAL.
 1567          */
 1568         case ESS_PCSPEAKER_VOL:
 1569                 if (cp->un.value.num_channels != 1)
 1570                         return EINVAL;
 1571 
 1572                 sc->gain[cp->dev][ESS_LEFT] = sc->gain[cp->dev][ESS_RIGHT] =
 1573                   ESS_3BIT_GAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
 1574                 ess_set_gain(sc, cp->dev, 1);
 1575                 return (0);
 1576 
 1577         case ESS_RECORD_SOURCE:
 1578                 if (ESS_USE_AUDIO1(sc->sc_model)) {
 1579                         if (cp->type == AUDIO_MIXER_ENUM)
 1580                                 return (ess_set_in_port(sc, cp->un.ord));
 1581                         else
 1582                                 return (EINVAL);
 1583                 } else {
 1584                         if (cp->type == AUDIO_MIXER_SET)
 1585                                 return (ess_set_in_ports(sc, cp->un.mask));
 1586                         else
 1587                                 return (EINVAL);
 1588                 }
 1589                 return (0);
 1590 
 1591         case ESS_RECORD_MONITOR:
 1592                 if (cp->type != AUDIO_MIXER_ENUM)
 1593                         return EINVAL;
 1594 
 1595                 if (cp->un.ord)
 1596                         /* Enable monitor */
 1597                         ess_set_xreg_bits(sc, ESS_XCMD_AUDIO_CTRL,
 1598                                           ESS_AUDIO_CTRL_MONITOR);
 1599                 else
 1600                         /* Disable monitor */
 1601                         ess_clear_xreg_bits(sc, ESS_XCMD_AUDIO_CTRL,
 1602                                             ESS_AUDIO_CTRL_MONITOR);
 1603                 return (0);
 1604         }
 1605 
 1606         if (ESS_USE_AUDIO1(sc->sc_model))
 1607                 return (EINVAL);
 1608 
 1609         switch (cp->dev) {
 1610         case ESS_DAC_REC_VOL:
 1611         case ESS_MIC_REC_VOL:
 1612         case ESS_LINE_REC_VOL:
 1613         case ESS_SYNTH_REC_VOL:
 1614         case ESS_CD_REC_VOL:
 1615         case ESS_AUXB_REC_VOL:
 1616                 if (cp->type != AUDIO_MIXER_VALUE)
 1617                         return EINVAL;
 1618 
 1619                 switch (cp->un.value.num_channels) {
 1620                 case 1:
 1621                         lgain = rgain = ESS_4BIT_GAIN(
 1622                           cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
 1623                         break;
 1624                 case 2:
 1625                         lgain = ESS_4BIT_GAIN(
 1626                           cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
 1627                         rgain = ESS_4BIT_GAIN(
 1628                           cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
 1629                         break;
 1630                 default:
 1631                         return EINVAL;
 1632                 }
 1633 
 1634                 sc->gain[cp->dev][ESS_LEFT]  = lgain;
 1635                 sc->gain[cp->dev][ESS_RIGHT] = rgain;
 1636                 ess_set_gain(sc, cp->dev, 1);
 1637                 return (0);
 1638 
 1639         case ESS_MIC_PREAMP:
 1640                 if (cp->type != AUDIO_MIXER_ENUM)
 1641                         return EINVAL;
 1642 
 1643                 if (cp->un.ord)
 1644                         /* Enable microphone preamp */
 1645                         ess_set_xreg_bits(sc, ESS_XCMD_PREAMP_CTRL,
 1646                                           ESS_PREAMP_CTRL_ENABLE);
 1647                 else
 1648                         /* Disable microphone preamp */
 1649                         ess_clear_xreg_bits(sc, ESS_XCMD_PREAMP_CTRL,
 1650                                           ESS_PREAMP_CTRL_ENABLE);
 1651                 return (0);
 1652         }
 1653 
 1654         return (EINVAL);
 1655 }
 1656 
 1657 int
 1658 ess_get_port(void *addr, mixer_ctrl_t *cp)
 1659 {
 1660         struct ess_softc *sc = addr;
 1661 
 1662         DPRINTFN(5,("ess_get_port: port=%d\n", cp->dev));
 1663 
 1664         switch (cp->dev) {
 1665         case ESS_MASTER_VOL:
 1666         case ESS_DAC_PLAY_VOL:
 1667         case ESS_MIC_PLAY_VOL:
 1668         case ESS_LINE_PLAY_VOL:
 1669         case ESS_SYNTH_PLAY_VOL:
 1670         case ESS_CD_PLAY_VOL:
 1671         case ESS_AUXB_PLAY_VOL:
 1672         case ESS_RECORD_VOL:
 1673                 switch (cp->un.value.num_channels) {
 1674                 case 1:
 1675                         cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
 1676                                 sc->gain[cp->dev][ESS_LEFT];
 1677                         break;
 1678                 case 2:
 1679                         cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
 1680                                 sc->gain[cp->dev][ESS_LEFT];
 1681                         cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
 1682                                 sc->gain[cp->dev][ESS_RIGHT];
 1683                         break;
 1684                 default:
 1685                         return EINVAL;
 1686                 }
 1687                 return (0);
 1688 
 1689         case ESS_PCSPEAKER_VOL:
 1690                 if (cp->un.value.num_channels != 1)
 1691                         return EINVAL;
 1692 
 1693                 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
 1694                         sc->gain[cp->dev][ESS_LEFT];
 1695                 return (0);
 1696 
 1697         case ESS_RECORD_SOURCE:
 1698                 if (ESS_USE_AUDIO1(sc->sc_model))
 1699                         cp->un.ord = sc->in_port;
 1700                 else
 1701                         cp->un.mask = sc->in_mask;
 1702                 return (0);
 1703 
 1704         case ESS_RECORD_MONITOR:
 1705                 cp->un.ord = (ess_read_x_reg(sc, ESS_XCMD_AUDIO_CTRL) &
 1706                               ESS_AUDIO_CTRL_MONITOR) ? 1 : 0;
 1707                 return (0);
 1708         }
 1709 
 1710         if (ESS_USE_AUDIO1(sc->sc_model))
 1711                 return (EINVAL);
 1712 
 1713         switch (cp->dev) {
 1714         case ESS_DAC_REC_VOL:
 1715         case ESS_MIC_REC_VOL:
 1716         case ESS_LINE_REC_VOL:
 1717         case ESS_SYNTH_REC_VOL:
 1718         case ESS_CD_REC_VOL:
 1719         case ESS_AUXB_REC_VOL:
 1720                 switch (cp->un.value.num_channels) {
 1721                 case 1:
 1722                         cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
 1723                                 sc->gain[cp->dev][ESS_LEFT];
 1724                         break;
 1725                 case 2:
 1726                         cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
 1727                                 sc->gain[cp->dev][ESS_LEFT];
 1728                         cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
 1729                                 sc->gain[cp->dev][ESS_RIGHT];
 1730                         break;
 1731                 default:
 1732                         return EINVAL;
 1733                 }
 1734                 return (0);
 1735 
 1736         case ESS_MIC_PREAMP:
 1737                 cp->un.ord = (ess_read_x_reg(sc, ESS_XCMD_PREAMP_CTRL) &
 1738                               ESS_PREAMP_CTRL_ENABLE) ? 1 : 0;
 1739                 return (0);
 1740         }
 1741 
 1742         return (EINVAL);
 1743 }
 1744 
 1745 int
 1746 ess_query_devinfo(void *addr, mixer_devinfo_t *dip)
 1747 {
 1748         struct ess_softc *sc = addr;
 1749 
 1750         DPRINTFN(5,("ess_query_devinfo: model=%d index=%d\n",
 1751                     sc->sc_model, dip->index));
 1752 
 1753         /*
 1754          * REVISIT: There are some slight differences between the
 1755          *          mixers on the different ESS chips, which can
 1756          *          be sorted out using the chip model rather than a
 1757          *          separate mixer model.
 1758          *          This is currently coded assuming an ES1887; we
 1759          *          need to work out which bits are not applicable to
 1760          *          the other models (1888 and 888).
 1761          */
 1762         switch (dip->index) {
 1763         case ESS_DAC_PLAY_VOL:
 1764                 dip->mixer_class = ESS_INPUT_CLASS;
 1765                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1766                 strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
 1767                 dip->type = AUDIO_MIXER_VALUE;
 1768                 dip->un.v.num_channels = 2;
 1769                 strlcpy(dip->un.v.units.name, AudioNvolume,
 1770                     sizeof dip->un.v.units.name);
 1771                 return (0);
 1772 
 1773         case ESS_MIC_PLAY_VOL:
 1774                 dip->mixer_class = ESS_INPUT_CLASS;
 1775                 dip->prev = AUDIO_MIXER_LAST;
 1776                 if (ESS_USE_AUDIO1(sc->sc_model))
 1777                         dip->next = AUDIO_MIXER_LAST;
 1778                 else
 1779                         dip->next = ESS_MIC_PREAMP;
 1780                 strlcpy(dip->label.name, AudioNmicrophone,
 1781                     sizeof dip->label.name);
 1782                 dip->type = AUDIO_MIXER_VALUE;
 1783                 dip->un.v.num_channels = 2;
 1784                 strlcpy(dip->un.v.units.name, AudioNvolume,
 1785                     sizeof dip->un.v.units.name);
 1786                 return (0);
 1787 
 1788         case ESS_LINE_PLAY_VOL:
 1789                 dip->mixer_class = ESS_INPUT_CLASS;
 1790                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1791                 strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
 1792                 dip->type = AUDIO_MIXER_VALUE;
 1793                 dip->un.v.num_channels = 2;
 1794                 strlcpy(dip->un.v.units.name, AudioNvolume,
 1795                     sizeof dip->un.v.units.name);
 1796                 return (0);
 1797 
 1798         case ESS_SYNTH_PLAY_VOL:
 1799                 dip->mixer_class = ESS_INPUT_CLASS;
 1800                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1801                 strlcpy(dip->label.name, AudioNfmsynth,
 1802                     sizeof dip->label.name);
 1803                 dip->type = AUDIO_MIXER_VALUE;
 1804                 dip->un.v.num_channels = 2;
 1805                 strlcpy(dip->un.v.units.name, AudioNvolume,
 1806                     sizeof dip->un.v.units.name);
 1807                 return (0);
 1808 
 1809         case ESS_CD_PLAY_VOL:
 1810                 dip->mixer_class = ESS_INPUT_CLASS;
 1811                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1812                 strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
 1813                 dip->type = AUDIO_MIXER_VALUE;
 1814                 dip->un.v.num_channels = 2;
 1815                 strlcpy(dip->un.v.units.name, AudioNvolume,
 1816                     sizeof dip->un.v.units.name);
 1817                 return (0);
 1818 
 1819         case ESS_AUXB_PLAY_VOL:
 1820                 dip->mixer_class = ESS_INPUT_CLASS;
 1821                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1822                 strlcpy(dip->label.name, "auxb", sizeof dip->label.name);
 1823                 dip->type = AUDIO_MIXER_VALUE;
 1824                 dip->un.v.num_channels = 2;
 1825                 strlcpy(dip->un.v.units.name, AudioNvolume,
 1826                     sizeof dip->un.v.units.name);
 1827                 return (0);
 1828 
 1829         case ESS_INPUT_CLASS:
 1830                 dip->mixer_class = ESS_INPUT_CLASS;
 1831                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1832                 strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
 1833                 dip->type = AUDIO_MIXER_CLASS;
 1834                 return (0);
 1835 
 1836         case ESS_MASTER_VOL:
 1837                 dip->mixer_class = ESS_OUTPUT_CLASS;
 1838                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1839                 strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
 1840                 dip->type = AUDIO_MIXER_VALUE;
 1841                 dip->un.v.num_channels = 2;
 1842                 strlcpy(dip->un.v.units.name, AudioNvolume,
 1843                     sizeof dip->un.v.units.name);
 1844                 return (0);
 1845 
 1846         case ESS_PCSPEAKER_VOL:
 1847                 dip->mixer_class = ESS_OUTPUT_CLASS;
 1848                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1849                 strlcpy(dip->label.name, "pc_speaker", sizeof dip->label.name);
 1850                 dip->type = AUDIO_MIXER_VALUE;
 1851                 dip->un.v.num_channels = 1;
 1852                 strlcpy(dip->un.v.units.name, AudioNvolume,
 1853                     sizeof dip->un.v.units.name);
 1854                 return (0);
 1855 
 1856         case ESS_OUTPUT_CLASS:
 1857                 dip->mixer_class = ESS_OUTPUT_CLASS;
 1858                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1859                 strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
 1860                 dip->type = AUDIO_MIXER_CLASS;
 1861                 return (0);
 1862 
 1863         case ESS_RECORD_VOL:
 1864                 dip->mixer_class = ESS_RECORD_CLASS;
 1865                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1866                 strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name);
 1867                 dip->type = AUDIO_MIXER_VALUE;
 1868                 dip->un.v.num_channels = 2;
 1869                 strlcpy(dip->un.v.units.name, AudioNvolume,
 1870                     sizeof dip->un.v.units.name);
 1871                 return (0);
 1872 
 1873         case ESS_RECORD_SOURCE:
 1874                 dip->mixer_class = ESS_RECORD_CLASS;
 1875                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1876                 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
 1877                 if (ESS_USE_AUDIO1(sc->sc_model)) {
 1878                         /*
 1879                          * The 1788 doesn't use the input mixer control that
 1880                          * the 1888 uses, because it's a pain when you only
 1881                          * have one mixer.
 1882                          * Perhaps it could be emulated by keeping both sets of
 1883                          * gain values, and doing a `context switch' of the
 1884                          * mixer registers when shifting from playing to
 1885                          * recording.
 1886                          */
 1887                         dip->type = AUDIO_MIXER_ENUM;
 1888                         dip->un.e.num_mem = 4;
 1889                         strlcpy(dip->un.e.member[0].label.name,
 1890                             AudioNmicrophone,
 1891                             sizeof dip->un.e.member[0].label.name);
 1892                         dip->un.e.member[0].ord = ESS_SOURCE_MIC;
 1893                         strlcpy(dip->un.e.member[1].label.name, AudioNline,
 1894                             sizeof dip->un.e.member[1].label.name);
 1895                         dip->un.e.member[1].ord = ESS_SOURCE_LINE;
 1896                         strlcpy(dip->un.e.member[2].label.name, AudioNcd,
 1897                             sizeof dip->un.e.member[2].label.name);
 1898                         dip->un.e.member[2].ord = ESS_SOURCE_CD;
 1899                         strlcpy(dip->un.e.member[3].label.name, AudioNmixerout,
 1900                             sizeof dip->un.e.member[3].label.name);
 1901                         dip->un.e.member[3].ord = ESS_SOURCE_MIXER;
 1902                 } else {
 1903                         dip->type = AUDIO_MIXER_SET;
 1904                         dip->un.s.num_mem = 6;
 1905                         strlcpy(dip->un.s.member[0].label.name, AudioNdac,
 1906                             sizeof dip->un.e.member[0].label.name);
 1907                         dip->un.s.member[0].mask = 1 << ESS_DAC_REC_VOL;
 1908                         strlcpy(dip->un.s.member[1].label.name,
 1909                             AudioNmicrophone,
 1910                             sizeof dip->un.e.member[1].label.name);
 1911                         dip->un.s.member[1].mask = 1 << ESS_MIC_REC_VOL;
 1912                         strlcpy(dip->un.s.member[2].label.name, AudioNline,
 1913                             sizeof dip->un.e.member[2].label.name);
 1914                         dip->un.s.member[2].mask = 1 << ESS_LINE_REC_VOL;
 1915                         strlcpy(dip->un.s.member[3].label.name, AudioNfmsynth,
 1916                             sizeof dip->un.e.member[3].label.name);
 1917                         dip->un.s.member[3].mask = 1 << ESS_SYNTH_REC_VOL;
 1918                         strlcpy(dip->un.s.member[4].label.name, AudioNcd,
 1919                             sizeof dip->un.e.member[4].label.name);
 1920                         dip->un.s.member[4].mask = 1 << ESS_CD_REC_VOL;
 1921                         strlcpy(dip->un.s.member[5].label.name, "auxb",
 1922                             sizeof dip->un.e.member[5].label.name);
 1923                         dip->un.s.member[5].mask = 1 << ESS_AUXB_REC_VOL;
 1924                 }
 1925                 return (0);
 1926 
 1927         case ESS_RECORD_CLASS:
 1928                 dip->mixer_class = ESS_RECORD_CLASS;
 1929                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1930                 strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
 1931                 dip->type = AUDIO_MIXER_CLASS;
 1932                 return (0);
 1933 
 1934         case ESS_RECORD_MONITOR:
 1935                 dip->prev = dip->next = AUDIO_MIXER_LAST;
 1936                 strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
 1937                 dip->type = AUDIO_MIXER_ENUM;
 1938                 dip->mixer_class = ESS_MONITOR_CLASS;
 1939                 dip->un.e.num_mem = 2;
 1940                 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
 1941                     sizeof dip->un.e.member[0].label.name);
 1942                 dip->un.e.member[0].ord = 0;
 1943                 strlcpy(dip->un.e.member[1].label.name, AudioNon,
 1944                     sizeof dip->un.e.member[1].label.name);
 1945                 dip->un.e.member[1].ord = 1;
 1946                 return (0);
 1947 
 1948         case ESS_MONITOR_CLASS:
 1949                 dip->mixer_class = ESS_MONITOR_CLASS;
 1950                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1951                 strlcpy(dip->label.name, AudioCmonitor,
 1952                     sizeof dip->label.name);
 1953                 dip->type = AUDIO_MIXER_CLASS;
 1954                 return (0);
 1955         }
 1956 
 1957         if (ESS_USE_AUDIO1(sc->sc_model))
 1958                 return (ENXIO);
 1959 
 1960         switch (dip->index) {
 1961         case ESS_DAC_REC_VOL:
 1962                 dip->mixer_class = ESS_RECORD_CLASS;
 1963                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1964                 strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
 1965                 dip->type = AUDIO_MIXER_VALUE;
 1966                 dip->un.v.num_channels = 2;
 1967                 strlcpy(dip->un.v.units.name, AudioNvolume,
 1968                     sizeof dip->un.v.units.name);
 1969                 return (0);
 1970 
 1971         case ESS_MIC_REC_VOL:
 1972                 dip->mixer_class = ESS_RECORD_CLASS;
 1973                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1974                 strlcpy(dip->label.name, AudioNmicrophone,
 1975                     sizeof dip->label.name);
 1976                 dip->type = AUDIO_MIXER_VALUE;
 1977                 dip->un.v.num_channels = 2;
 1978                 strlcpy(dip->un.v.units.name, AudioNvolume,
 1979                     sizeof dip->un.v.units.name);
 1980                 return (0);
 1981 
 1982         case ESS_LINE_REC_VOL:
 1983                 dip->mixer_class = ESS_RECORD_CLASS;
 1984                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1985                 strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
 1986                 dip->type = AUDIO_MIXER_VALUE;
 1987                 dip->un.v.num_channels = 2;
 1988                 strlcpy(dip->un.v.units.name, AudioNvolume,
 1989                     sizeof dip->un.v.units.name);
 1990                 return (0);
 1991 
 1992         case ESS_SYNTH_REC_VOL:
 1993                 dip->mixer_class = ESS_RECORD_CLASS;
 1994                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 1995                 strlcpy(dip->label.name, AudioNfmsynth,
 1996                     sizeof dip->label.name);
 1997                 dip->type = AUDIO_MIXER_VALUE;
 1998                 dip->un.v.num_channels = 2;
 1999                 strlcpy(dip->un.v.units.name, AudioNvolume,
 2000                     sizeof dip->un.v.units.name);
 2001                 return (0);
 2002 
 2003         case ESS_CD_REC_VOL:
 2004                 dip->mixer_class = ESS_RECORD_CLASS;
 2005                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 2006                 strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
 2007                 dip->type = AUDIO_MIXER_VALUE;
 2008                 dip->un.v.num_channels = 2;
 2009                 strlcpy(dip->un.v.units.name, AudioNvolume,
 2010                     sizeof dip->un.v.units.name);
 2011                 return (0);
 2012 
 2013         case ESS_AUXB_REC_VOL:
 2014                 dip->mixer_class = ESS_RECORD_CLASS;
 2015                 dip->next = dip->prev = AUDIO_MIXER_LAST;
 2016                 strlcpy(dip->label.name, "auxb", sizeof dip->label.name);
 2017                 dip->type = AUDIO_MIXER_VALUE;
 2018                 dip->un.v.num_channels = 2;
 2019                 strlcpy(dip->un.v.units.name, AudioNvolume,
 2020                     sizeof dip->un.v.units.name);
 2021                 return (0);
 2022 
 2023         case ESS_MIC_PREAMP:
 2024                 dip->mixer_class = ESS_INPUT_CLASS;
 2025                 dip->prev = ESS_MIC_PLAY_VOL;
 2026                 dip->next = AUDIO_MIXER_LAST;
 2027                 strlcpy(dip->label.name, AudioNpreamp, sizeof dip->label.name);
 2028                 dip->type = AUDIO_MIXER_ENUM;
 2029                 dip->un.e.num_mem = 2;
 2030                 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
 2031                     sizeof dip->un.e.member[0].label.name);
 2032                 dip->un.e.member[0].ord = 0;
 2033                 strlcpy(dip->un.e.member[1].label.name, AudioNon,
 2034                     sizeof dip->un.e.member[1].label.name);
 2035                 dip->un.e.member[1].ord = 1;
 2036                 return (0);
 2037         }
 2038 
 2039         return (ENXIO);
 2040 }
 2041 
 2042 void *
 2043 ess_malloc(void *addr, int direction, size_t size, int pool, int flags)
 2044 {
 2045         struct ess_softc *sc = addr;
 2046         int drq;
 2047 
 2048         if (!ESS_USE_AUDIO1(sc->sc_model))
 2049                 drq = sc->sc_audio2.drq;
 2050         else
 2051                 drq = sc->sc_audio1.drq;
 2052         return (isa_malloc(sc->sc_isa, drq, size, pool, flags));
 2053 }
 2054 
 2055 void
 2056 ess_free(void *addr, void *ptr, int pool)
 2057 {
 2058         isa_free(ptr, pool);
 2059 }
 2060 
 2061 size_t
 2062 ess_round_buffersize(void *addr, int direction, size_t size)
 2063 {
 2064         if (size > MAX_ISADMA)
 2065                 size = MAX_ISADMA;
 2066         return (size);
 2067 }
 2068 
 2069 /* ============================================
 2070  * Generic functions for ess, not used by audio h/w i/f
 2071  * =============================================
 2072  */
 2073 
 2074 /*
 2075  * Reset the chip.
 2076  * Return non-zero if the chip isn't detected.
 2077  */
 2078 int
 2079 ess_reset(struct ess_softc *sc)
 2080 {
 2081         bus_space_tag_t iot = sc->sc_iot;
 2082         bus_space_handle_t ioh = sc->sc_ioh;
 2083 
 2084         sc->sc_audio1.active = 0;
 2085         sc->sc_audio2.active = 0;
 2086 
 2087         EWRITE1(iot, ioh, ESS_DSP_RESET, ESS_RESET_EXT);
 2088         delay(10000);
 2089         EWRITE1(iot, ioh, ESS_DSP_RESET, 0);
 2090         if (ess_rdsp(sc) != ESS_MAGIC)
 2091                 return (1);
 2092 
 2093         /* Enable access to the ESS extension commands. */
 2094         ess_wdsp(sc, ESS_ACMD_ENABLE_EXT);
 2095 
 2096         return (0);
 2097 }
 2098 
 2099 void
 2100 ess_set_gain(struct ess_softc *sc, int port, int on)
 2101 {
 2102         int gain, left, right;
 2103         int mix;
 2104         int src;
 2105         int stereo;
 2106 
 2107         /*
 2108          * Most gain controls are found in the mixer registers and
 2109          * are stereo. Any that are not, must set mix and stereo as
 2110          * required.
 2111          */
 2112         mix = 1;
 2113         stereo = 1;
 2114 
 2115         switch (port) {
 2116         case ESS_MASTER_VOL:
 2117                 src = ESS_MREG_VOLUME_MASTER;
 2118                 break;
 2119         case ESS_DAC_PLAY_VOL:
 2120                 if (ESS_USE_AUDIO1(sc->sc_model))
 2121                         src = ESS_MREG_VOLUME_VOICE;
 2122                 else
 2123                         src = 0x7C;
 2124                 break;
 2125         case ESS_MIC_PLAY_VOL:
 2126                 src = ESS_MREG_VOLUME_MIC;
 2127                 break;
 2128         case ESS_LINE_PLAY_VOL:
 2129                 src = ESS_MREG_VOLUME_LINE;
 2130                 break;
 2131         case ESS_SYNTH_PLAY_VOL:
 2132                 src = ESS_MREG_VOLUME_SYNTH;
 2133                 break;
 2134         case ESS_CD_PLAY_VOL:
 2135                 src = ESS_MREG_VOLUME_CD;
 2136                 break;
 2137         case ESS_AUXB_PLAY_VOL:
 2138                 src = ESS_MREG_VOLUME_AUXB;
 2139                 break;
 2140         case ESS_PCSPEAKER_VOL:
 2141                 src = ESS_MREG_VOLUME_PCSPKR;
 2142                 stereo = 0;
 2143                 break;
 2144         case ESS_DAC_REC_VOL:
 2145                 src = 0x69;
 2146                 break;
 2147         case ESS_MIC_REC_VOL:
 2148                 src = 0x68;
 2149                 break;
 2150         case ESS_LINE_REC_VOL:
 2151                 src = 0x6E;
 2152                 break;
 2153         case ESS_SYNTH_REC_VOL:
 2154                 src = 0x6B;
 2155                 break;
 2156         case ESS_CD_REC_VOL:
 2157                 src = 0x6A;
 2158                 break;
 2159         case ESS_AUXB_REC_VOL:
 2160                 src = 0x6C;
 2161                 break;
 2162         case ESS_RECORD_VOL:
 2163                 src = ESS_XCMD_VOLIN_CTRL;
 2164                 mix = 0;
 2165                 break;
 2166         default:
 2167                 return;
 2168         }
 2169 
 2170         /* 1788 doesn't have a separate recording mixer */
 2171         if (ESS_USE_AUDIO1(sc->sc_model) && mix && src > 0x62)
 2172                 return;
 2173 
 2174         if (on) {
 2175                 left = sc->gain[port][ESS_LEFT];
 2176                 right = sc->gain[port][ESS_RIGHT];
 2177         } else {
 2178                 left = right = 0;
 2179         }
 2180 
 2181         if (stereo)
 2182                 gain = ESS_STEREO_GAIN(left, right);
 2183         else
 2184                 gain = ESS_MONO_GAIN(left);
 2185 
 2186         if (mix)
 2187                 ess_write_mix_reg(sc, src, gain);
 2188         else
 2189                 ess_write_x_reg(sc, src, gain);
 2190 }
 2191 
 2192 /* Set the input device on devices without an input mixer. */
 2193 int
 2194 ess_set_in_port(struct ess_softc *sc, int ord)
 2195 {
 2196         mixer_devinfo_t di;
 2197         int i;
 2198 
 2199         DPRINTF(("ess_set_in_port: ord=0x%x\n", ord));
 2200 
 2201         /*
 2202          * Get the device info for the record source control,
 2203          * including the list of available sources.
 2204          */
 2205         di.index = ESS_RECORD_SOURCE;
 2206         if (ess_query_devinfo(sc, &di))
 2207                 return EINVAL;
 2208 
 2209         /* See if the given ord value was anywhere in the list. */
 2210         for (i = 0; i < di.un.e.num_mem; i++) {
 2211                 if (ord == di.un.e.member[i].ord)
 2212                         break;
 2213         }
 2214         if (i == di.un.e.num_mem)
 2215                 return EINVAL;
 2216 
 2217         ess_write_mix_reg(sc, ESS_MREG_ADC_SOURCE, ord);
 2218 
 2219         sc->in_port = ord;
 2220         return (0);
 2221 }
 2222 
 2223 /* Set the input device levels on input-mixer-enabled devices. */
 2224 int
 2225 ess_set_in_ports(struct ess_softc *sc, int mask)
 2226 {
 2227         mixer_devinfo_t di;
 2228         int i, port;
 2229 
 2230         DPRINTF(("ess_set_in_ports: mask=0x%x\n", mask));
 2231 
 2232         /*
 2233          * Get the device info for the record source control,
 2234          * including the list of available sources.
 2235          */
 2236         di.index = ESS_RECORD_SOURCE;
 2237         if (ess_query_devinfo(sc, &di))
 2238                 return EINVAL;
 2239 
 2240         /*
 2241          * Set or disable the record volume control for each of the
 2242          * possible sources.
 2243          */
 2244         for (i = 0; i < di.un.s.num_mem; i++) {
 2245                 /*
 2246                  * Calculate the source port number from its mask.
 2247                  */
 2248                 port = ffs(di.un.s.member[i].mask);
 2249 
 2250                 /*
 2251                  * Set the source gain:
 2252                  *      to the current value if source is enabled
 2253                  *      to zero if source is disabled
 2254                  */
 2255                 ess_set_gain(sc, port, mask & di.un.s.member[i].mask);
 2256         }
 2257 
 2258         sc->in_mask = mask;
 2259         return (0);
 2260 }
 2261 
 2262 void
 2263 ess_speaker_on(struct ess_softc *sc)
 2264 {
 2265         /* Unmute the DAC. */
 2266         ess_set_gain(sc, ESS_DAC_PLAY_VOL, 1);
 2267 }
 2268 
 2269 void
 2270 ess_speaker_off(struct ess_softc *sc)
 2271 {
 2272         /* Mute the DAC. */
 2273         ess_set_gain(sc, ESS_DAC_PLAY_VOL, 0);
 2274 }
 2275 
 2276 /*
 2277  * Calculate the time constant for the requested sampling rate.
 2278  */
 2279 u_int
 2280 ess_srtotc(u_int rate)
 2281 {
 2282         u_int tc;
 2283 
 2284         /* The following formulae are from the ESS data sheet. */
 2285         if (rate <= 22050)
 2286                 tc = 128 - 397700L / rate;
 2287         else
 2288                 tc = 256 - 795500L / rate;
 2289 
 2290         return (tc);
 2291 }
 2292 
 2293 
 2294 /*
 2295  * Calculate the filter constant for the requested sampling rate.
 2296  */
 2297 u_int
 2298 ess_srtofc(u_int rate)
 2299 {
 2300         /*
 2301          * The following formula is derived from the information in
 2302          * the ES1887 data sheet, based on a roll-off frequency of
 2303          * 87%.
 2304          */
 2305         return (256 - 200279L / rate);
 2306 }
 2307 
 2308 
 2309 /*
 2310  * Return the status of the DSP.
 2311  */
 2312 u_char
 2313 ess_get_dsp_status(struct ess_softc *sc)
 2314 {
 2315         return (EREAD1(sc->sc_iot, sc->sc_ioh, ESS_DSP_RW_STATUS));
 2316 }
 2317 
 2318 
 2319 /*
 2320  * Return the read status of the DSP:   1 -> DSP ready for reading
 2321  *                                      0 -> DSP not ready for reading
 2322  */
 2323 u_char
 2324 ess_dsp_read_ready(struct ess_softc *sc)
 2325 {
 2326         return ((ess_get_dsp_status(sc) & ESS_DSP_READ_READY) ? 1 : 0);
 2327 }
 2328 
 2329 
 2330 /*
 2331  * Return the write status of the DSP:  1 -> DSP ready for writing
 2332  *                                      0 -> DSP not ready for writing
 2333  */
 2334 u_char
 2335 ess_dsp_write_ready(struct ess_softc *sc)
 2336 {
 2337         return ((ess_get_dsp_status(sc) & ESS_DSP_WRITE_BUSY) ? 0 : 1);
 2338 }
 2339 
 2340 
 2341 /*
 2342  * Read a byte from the DSP.
 2343  */
 2344 int
 2345 ess_rdsp(struct ess_softc *sc)
 2346 {
 2347         bus_space_tag_t iot = sc->sc_iot;
 2348         bus_space_handle_t ioh = sc->sc_ioh;
 2349         int i;
 2350 
 2351         for (i = ESS_READ_TIMEOUT; i > 0; --i) {
 2352                 if (ess_dsp_read_ready(sc)) {
 2353                         i = EREAD1(iot, ioh, ESS_DSP_READ);
 2354                         DPRINTFN(8,("ess_rdsp() = 0x%02x\n", i));
 2355                         return i;
 2356                 } else
 2357                         delay(10);
 2358         }
 2359 
 2360         DPRINTF(("ess_rdsp: timed out\n"));
 2361         return (-1);
 2362 }
 2363 
 2364 /*
 2365  * Write a byte to the DSP.
 2366  */
 2367 int
 2368 ess_wdsp(struct ess_softc *sc, u_char v)
 2369 {
 2370         bus_space_tag_t iot = sc->sc_iot;
 2371         bus_space_handle_t ioh = sc->sc_ioh;
 2372         int i;
 2373 
 2374         DPRINTFN(8,("ess_wdsp(0x%02x)\n", v));
 2375 
 2376         for (i = ESS_WRITE_TIMEOUT; i > 0; --i) {
 2377                 if (ess_dsp_write_ready(sc)) {
 2378                         EWRITE1(iot, ioh, ESS_DSP_WRITE, v);
 2379                         return (0);
 2380                 } else
 2381                         delay(10);
 2382         }
 2383 
 2384         DPRINTF(("ess_wdsp(0x%02x): timed out\n", v));
 2385         return (-1);
 2386 }
 2387 
 2388 /*
 2389  * Write a value to one of the ESS extended registers.
 2390  */
 2391 int
 2392 ess_write_x_reg(struct ess_softc *sc, u_char reg, u_char val)
 2393 {
 2394         int error;
 2395 
 2396         DPRINTFN(2,("ess_write_x_reg: %02x=%02x\n", reg, val));
 2397         if ((error = ess_wdsp(sc, reg)) == 0)
 2398                 error = ess_wdsp(sc, val);
 2399 
 2400         return error;
 2401 }
 2402 
 2403 /*
 2404  * Read the value of one of the ESS extended registers.
 2405  */
 2406 u_char
 2407 ess_read_x_reg(struct ess_softc *sc, u_char reg)
 2408 {
 2409         int error;
 2410         int val;
 2411 
 2412         if ((error = ess_wdsp(sc, 0xC0)) == 0)
 2413                 error = ess_wdsp(sc, reg);
 2414         if (error)
 2415                 DPRINTF(("Error reading extended register 0x%02x\n", reg));
 2416 /* REVISIT: what if an error is returned above? */
 2417         val = ess_rdsp(sc);
 2418         DPRINTFN(2,("ess_read_x_reg: %02x=%02x\n", reg, val));
 2419         return val;
 2420 }
 2421 
 2422 void
 2423 ess_clear_xreg_bits(struct ess_softc *sc, u_char reg, u_char mask)
 2424 {
 2425         if (ess_write_x_reg(sc, reg, ess_read_x_reg(sc, reg) & ~mask) == -1)
 2426                 DPRINTF(("Error clearing bits in extended register 0x%02x\n",
 2427                          reg));
 2428 }
 2429 
 2430 void
 2431 ess_set_xreg_bits(struct ess_softc *sc, u_char reg, u_char mask)
 2432 {
 2433         if (ess_write_x_reg(sc, reg, ess_read_x_reg(sc, reg) | mask) == -1)
 2434                 DPRINTF(("Error setting bits in extended register 0x%02x\n",
 2435                          reg));
 2436 }
 2437 
 2438 
 2439 /*
 2440  * Write a value to one of the ESS mixer registers.
 2441  */
 2442 void
 2443 ess_write_mix_reg(struct ess_softc *sc, u_char reg, u_char val)
 2444 {
 2445         bus_space_tag_t iot = sc->sc_iot;
 2446         bus_space_handle_t ioh = sc->sc_ioh;
 2447 
 2448         DPRINTFN(2,("ess_write_mix_reg: %x=%x\n", reg, val));
 2449 
 2450         mtx_enter(&audio_lock);
 2451         EWRITE1(iot, ioh, ESS_MIX_REG_SELECT, reg);
 2452         EWRITE1(iot, ioh, ESS_MIX_REG_DATA, val);
 2453         mtx_leave(&audio_lock);
 2454 }
 2455 
 2456 /*
 2457  * Read the value of one of the ESS mixer registers.
 2458  */
 2459 u_char
 2460 ess_read_mix_reg(struct ess_softc *sc, u_char reg)
 2461 {
 2462         bus_space_tag_t iot = sc->sc_iot;
 2463         bus_space_handle_t ioh = sc->sc_ioh;
 2464         u_char val;
 2465 
 2466         mtx_enter(&audio_lock);
 2467         EWRITE1(iot, ioh, ESS_MIX_REG_SELECT, reg);
 2468         val = EREAD1(iot, ioh, ESS_MIX_REG_DATA);
 2469         mtx_leave(&audio_lock);
 2470 
 2471         DPRINTFN(2,("ess_read_mix_reg: %x=%x\n", reg, val));
 2472         return val;
 2473 }
 2474 
 2475 void
 2476 ess_clear_mreg_bits(struct ess_softc *sc, u_char reg, u_char mask)
 2477 {
 2478         ess_write_mix_reg(sc, reg, ess_read_mix_reg(sc, reg) & ~mask);
 2479 }
 2480 
 2481 void
 2482 ess_set_mreg_bits(struct ess_softc *sc, u_char reg, u_char mask)
 2483 {
 2484         ess_write_mix_reg(sc, reg, ess_read_mix_reg(sc, reg) | mask);
 2485 }
 2486 
 2487 void
 2488 ess_read_multi_mix_reg(struct ess_softc *sc, u_char reg, u_int8_t *datap,
 2489     bus_size_t count)
 2490 {
 2491         bus_space_tag_t iot = sc->sc_iot;
 2492         bus_space_handle_t ioh = sc->sc_ioh;
 2493 
 2494         mtx_enter(&audio_lock);
 2495         EWRITE1(iot, ioh, ESS_MIX_REG_SELECT, reg);
 2496         bus_space_read_multi_1(iot, ioh, ESS_MIX_REG_DATA, datap, count);
 2497         mtx_leave(&audio_lock);
 2498 }

Cache object: 471f9707bf6ff0a53fb113c59fc79a3a


[ 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.