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