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