ess.c revision 1.88 1 1.88 thorpej /* $NetBSD: ess.c,v 1.88 2021/04/26 19:10:38 thorpej 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.88 thorpej __KERNEL_RCSID(0, "$NetBSD: ess.c,v 1.88 2021/04/26 19:10:38 thorpej 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.62 mycroft * - can modify idependently 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.88 thorpej CFARG_IATTR, "ess",
1050 1.88 thorpej CFARG_EOL);
1051 1.2 augustss
1052 1.61 drochner #if NJOY_ESS > 0
1053 1.61 drochner if (sc->sc_model == ESS_1888 && enablejoy) {
1054 1.61 drochner unsigned char m40;
1055 1.61 drochner
1056 1.61 drochner m40 = ess_read_mix_reg(sc, 0x40);
1057 1.61 drochner m40 |= 2;
1058 1.61 drochner ess_write_mix_reg(sc, 0x40, m40);
1059 1.61 drochner
1060 1.61 drochner arg.type = AUDIODEV_TYPE_AUX;
1061 1.88 thorpej (void)config_found(sc->sc_dev, &arg, audioprint,
1062 1.88 thorpej CFARG_IATTR, "ess",
1063 1.88 thorpej CFARG_EOL);
1064 1.61 drochner }
1065 1.61 drochner #endif
1066 1.61 drochner
1067 1.2 augustss #ifdef AUDIO_DEBUG
1068 1.26 augustss if (essdebug > 0)
1069 1.26 augustss ess_printsc(sc);
1070 1.2 augustss #endif
1071 1.79 jmcneill
1072 1.79 jmcneill return;
1073 1.79 jmcneill
1074 1.79 jmcneill fail:
1075 1.79 jmcneill callout_destroy(&sc->sc_poll1_ch);
1076 1.79 jmcneill callout_destroy(&sc->sc_poll2_ch);
1077 1.79 jmcneill mutex_destroy(&sc->sc_lock);
1078 1.79 jmcneill mutex_destroy(&sc->sc_intr_lock);
1079 1.1 augustss }
1080 1.1 augustss
1081 1.1 augustss /*
1082 1.1 augustss * Various routines to interface to higher level audio driver
1083 1.1 augustss */
1084 1.1 augustss
1085 1.1 augustss void
1086 1.66 kent ess_close(void *addr)
1087 1.1 augustss {
1088 1.66 kent struct ess_softc *sc;
1089 1.1 augustss
1090 1.66 kent sc = addr;
1091 1.60 mycroft DPRINTF(("ess_close: sc=%p\n", sc));
1092 1.1 augustss
1093 1.1 augustss ess_speaker_off(sc);
1094 1.1 augustss sc->spkr_state = SPKR_OFF;
1095 1.34 mycroft
1096 1.60 mycroft DPRINTF(("ess_close: closed\n"));
1097 1.1 augustss }
1098 1.1 augustss
1099 1.25 augustss /* XXX should use reference count */
1100 1.1 augustss int
1101 1.66 kent ess_speaker_ctl(void *addr, int newstate)
1102 1.4 augustss {
1103 1.66 kent struct ess_softc *sc;
1104 1.4 augustss
1105 1.66 kent sc = addr;
1106 1.4 augustss if ((newstate == SPKR_ON) && (sc->spkr_state == SPKR_OFF)) {
1107 1.4 augustss ess_speaker_on(sc);
1108 1.4 augustss sc->spkr_state = SPKR_ON;
1109 1.4 augustss }
1110 1.4 augustss if ((newstate == SPKR_OFF) && (sc->spkr_state == SPKR_ON)) {
1111 1.4 augustss ess_speaker_off(sc);
1112 1.4 augustss sc->spkr_state = SPKR_OFF;
1113 1.4 augustss }
1114 1.66 kent return 0;
1115 1.4 augustss }
1116 1.4 augustss
1117 1.4 augustss int
1118 1.73 christos ess_getdev(void *addr, struct audio_device *retp)
1119 1.1 augustss {
1120 1.66 kent
1121 1.1 augustss *retp = ess_device;
1122 1.66 kent return 0;
1123 1.1 augustss }
1124 1.1 augustss
1125 1.1 augustss int
1126 1.85 isaki ess_query_format(void *addr, audio_format_query_t *afp)
1127 1.1 augustss {
1128 1.1 augustss
1129 1.85 isaki return audio_query_format(ess_formats, ESS_NFORMATS, afp);
1130 1.1 augustss }
1131 1.1 augustss
1132 1.1 augustss int
1133 1.85 isaki ess_set_format(void *addr, int setmode,
1134 1.85 isaki const audio_params_t *play, const audio_params_t *rec,
1135 1.85 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
1136 1.1 augustss {
1137 1.66 kent struct ess_softc *sc;
1138 1.19 mycroft int rate;
1139 1.1 augustss
1140 1.85 isaki DPRINTF(("%s: set=%d\n", __func__, setmode));
1141 1.66 kent sc = addr;
1142 1.13 mycroft
1143 1.85 isaki /* *play and *rec are the identical because !AUDIO_PROP_INDEPENDENT. */
1144 1.19 mycroft
1145 1.85 isaki rate = play->sample_rate;
1146 1.82 nakayama ess_write_x_reg(sc, ESS_XCMD_SAMPLE_RATE, ess_srtotc(sc, rate));
1147 1.34 mycroft ess_write_x_reg(sc, ESS_XCMD_FILTER_CLOCK, ess_srtofc(rate));
1148 1.34 mycroft
1149 1.46 augustss if (!ESS_USE_AUDIO1(sc->sc_model)) {
1150 1.82 nakayama ess_write_mix_reg(sc, ESS_MREG_SAMPLE_RATE,
1151 1.82 nakayama ess_srtotc(sc, rate));
1152 1.33 nathanw ess_write_mix_reg(sc, ESS_MREG_FILTER_CLOCK, ess_srtofc(rate));
1153 1.33 nathanw }
1154 1.1 augustss
1155 1.66 kent return 0;
1156 1.1 augustss }
1157 1.1 augustss
1158 1.1 augustss int
1159 1.66 kent ess_audio1_trigger_output(
1160 1.66 kent void *addr,
1161 1.66 kent void *start, void *end,
1162 1.66 kent int blksize,
1163 1.66 kent void (*intr)(void *),
1164 1.66 kent void *arg,
1165 1.66 kent const audio_params_t *param)
1166 1.33 nathanw {
1167 1.66 kent struct ess_softc *sc;
1168 1.39 mycroft u_int8_t reg;
1169 1.33 nathanw
1170 1.66 kent sc = addr;
1171 1.66 kent DPRINTFN(1, ("ess_audio1_trigger_output: sc=%p start=%p end=%p "
1172 1.66 kent "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1173 1.33 nathanw
1174 1.34 mycroft if (sc->sc_audio1.active)
1175 1.36 mycroft panic("ess_audio1_trigger_output: already running");
1176 1.39 mycroft
1177 1.34 mycroft sc->sc_audio1.active = 1;
1178 1.34 mycroft sc->sc_audio1.intr = intr;
1179 1.34 mycroft sc->sc_audio1.arg = arg;
1180 1.42 mycroft if (sc->sc_audio1.polled) {
1181 1.43 mycroft sc->sc_audio1.dmapos = 0;
1182 1.43 mycroft sc->sc_audio1.buffersize = (char *)end - (char *)start;
1183 1.42 mycroft sc->sc_audio1.dmacount = 0;
1184 1.42 mycroft sc->sc_audio1.blksize = blksize;
1185 1.51 thorpej callout_reset(&sc->sc_poll1_ch, hz / 30,
1186 1.51 thorpej ess_audio1_poll, sc);
1187 1.42 mycroft }
1188 1.33 nathanw
1189 1.39 mycroft reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO_CTRL);
1190 1.34 mycroft if (param->channels == 2) {
1191 1.39 mycroft reg &= ~ESS_AUDIO_CTRL_MONO;
1192 1.39 mycroft reg |= ESS_AUDIO_CTRL_STEREO;
1193 1.33 nathanw } else {
1194 1.39 mycroft reg |= ESS_AUDIO_CTRL_MONO;
1195 1.39 mycroft reg &= ~ESS_AUDIO_CTRL_STEREO;
1196 1.33 nathanw }
1197 1.39 mycroft ess_write_x_reg(sc, ESS_XCMD_AUDIO_CTRL, reg);
1198 1.33 nathanw
1199 1.39 mycroft reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO1_CTRL1);
1200 1.65 kent if (param->precision == 16)
1201 1.39 mycroft reg |= ESS_AUDIO1_CTRL1_FIFO_SIZE;
1202 1.39 mycroft else
1203 1.39 mycroft reg &= ~ESS_AUDIO1_CTRL1_FIFO_SIZE;
1204 1.39 mycroft if (param->channels == 2)
1205 1.39 mycroft reg |= ESS_AUDIO1_CTRL1_FIFO_STEREO;
1206 1.39 mycroft else
1207 1.39 mycroft reg &= ~ESS_AUDIO1_CTRL1_FIFO_STEREO;
1208 1.34 mycroft if (param->encoding == AUDIO_ENCODING_SLINEAR_BE ||
1209 1.34 mycroft param->encoding == AUDIO_ENCODING_SLINEAR_LE)
1210 1.39 mycroft reg |= ESS_AUDIO1_CTRL1_FIFO_SIGNED;
1211 1.34 mycroft else
1212 1.39 mycroft reg &= ~ESS_AUDIO1_CTRL1_FIFO_SIGNED;
1213 1.39 mycroft reg |= ESS_AUDIO1_CTRL1_FIFO_CONNECT;
1214 1.39 mycroft ess_write_x_reg(sc, ESS_XCMD_AUDIO1_CTRL1, reg);
1215 1.33 nathanw
1216 1.66 kent isa_dmastart(sc->sc_ic, sc->sc_audio1.drq, start,
1217 1.34 mycroft (char *)end - (char *)start, NULL,
1218 1.34 mycroft DMAMODE_WRITE | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT);
1219 1.33 nathanw
1220 1.33 nathanw /* Program transfer count registers with 2's complement of count. */
1221 1.33 nathanw blksize = -blksize;
1222 1.33 nathanw ess_write_x_reg(sc, ESS_XCMD_XFER_COUNTLO, blksize);
1223 1.33 nathanw ess_write_x_reg(sc, ESS_XCMD_XFER_COUNTHI, blksize >> 8);
1224 1.33 nathanw
1225 1.38 mycroft /* Use 4 bytes per output DMA. */
1226 1.39 mycroft ess_set_xreg_bits(sc, ESS_XCMD_DEMAND_CTRL, ESS_DEMAND_CTRL_DEMAND_4);
1227 1.33 nathanw
1228 1.33 nathanw /* Start auto-init DMA */
1229 1.65 kent ess_wdsp(sc, ESS_ACMD_ENABLE_SPKR);
1230 1.39 mycroft reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO1_CTRL2);
1231 1.39 mycroft reg &= ~(ESS_AUDIO1_CTRL2_DMA_READ | ESS_AUDIO1_CTRL2_ADC_ENABLE);
1232 1.39 mycroft reg |= ESS_AUDIO1_CTRL2_FIFO_ENABLE | ESS_AUDIO1_CTRL2_AUTO_INIT;
1233 1.39 mycroft ess_write_x_reg(sc, ESS_XCMD_AUDIO1_CTRL2, reg);
1234 1.33 nathanw
1235 1.66 kent return 0;
1236 1.33 nathanw }
1237 1.33 nathanw
1238 1.33 nathanw int
1239 1.66 kent ess_audio2_trigger_output(
1240 1.66 kent void *addr,
1241 1.66 kent void *start, void *end,
1242 1.66 kent int blksize,
1243 1.66 kent void (*intr)(void *),
1244 1.66 kent void *arg,
1245 1.66 kent const audio_params_t *param)
1246 1.1 augustss {
1247 1.66 kent struct ess_softc *sc;
1248 1.39 mycroft u_int8_t reg;
1249 1.1 augustss
1250 1.66 kent sc = addr;
1251 1.66 kent DPRINTFN(1, ("ess_audio2_trigger_output: sc=%p start=%p end=%p "
1252 1.66 kent "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1253 1.19 mycroft
1254 1.34 mycroft if (sc->sc_audio2.active)
1255 1.36 mycroft panic("ess_audio2_trigger_output: already running");
1256 1.39 mycroft
1257 1.34 mycroft sc->sc_audio2.active = 1;
1258 1.34 mycroft sc->sc_audio2.intr = intr;
1259 1.34 mycroft sc->sc_audio2.arg = arg;
1260 1.42 mycroft if (sc->sc_audio2.polled) {
1261 1.43 mycroft sc->sc_audio2.dmapos = 0;
1262 1.43 mycroft sc->sc_audio2.buffersize = (char *)end - (char *)start;
1263 1.42 mycroft sc->sc_audio2.dmacount = 0;
1264 1.42 mycroft sc->sc_audio2.blksize = blksize;
1265 1.51 thorpej callout_reset(&sc->sc_poll2_ch, hz / 30,
1266 1.51 thorpej ess_audio2_poll, sc);
1267 1.42 mycroft }
1268 1.1 augustss
1269 1.39 mycroft reg = ess_read_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2);
1270 1.65 kent if (param->precision == 16)
1271 1.39 mycroft reg |= ESS_AUDIO2_CTRL2_FIFO_SIZE;
1272 1.17 mycroft else
1273 1.39 mycroft reg &= ~ESS_AUDIO2_CTRL2_FIFO_SIZE;
1274 1.19 mycroft if (param->channels == 2)
1275 1.39 mycroft reg |= ESS_AUDIO2_CTRL2_CHANNELS;
1276 1.17 mycroft else
1277 1.39 mycroft reg &= ~ESS_AUDIO2_CTRL2_CHANNELS;
1278 1.19 mycroft if (param->encoding == AUDIO_ENCODING_SLINEAR_BE ||
1279 1.34 mycroft param->encoding == AUDIO_ENCODING_SLINEAR_LE)
1280 1.39 mycroft reg |= ESS_AUDIO2_CTRL2_FIFO_SIGNED;
1281 1.17 mycroft else
1282 1.39 mycroft reg &= ~ESS_AUDIO2_CTRL2_FIFO_SIGNED;
1283 1.39 mycroft ess_write_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2, reg);
1284 1.6 augustss
1285 1.65 kent isa_dmastart(sc->sc_ic, sc->sc_audio2.drq, start,
1286 1.34 mycroft (char *)end - (char *)start, NULL,
1287 1.34 mycroft DMAMODE_WRITE | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT);
1288 1.1 augustss
1289 1.34 mycroft if (IS16BITDRQ(sc->sc_audio2.drq))
1290 1.19 mycroft blksize >>= 1; /* use word count for 16 bit DMA */
1291 1.6 augustss /* Program transfer count registers with 2's complement of count. */
1292 1.19 mycroft blksize = -blksize;
1293 1.19 mycroft ess_write_mix_reg(sc, ESS_MREG_XFER_COUNTLO, blksize);
1294 1.19 mycroft ess_write_mix_reg(sc, ESS_MREG_XFER_COUNTHI, blksize >> 8);
1295 1.1 augustss
1296 1.39 mycroft reg = ess_read_mix_reg(sc, ESS_MREG_AUDIO2_CTRL1);
1297 1.34 mycroft if (IS16BITDRQ(sc->sc_audio2.drq))
1298 1.39 mycroft reg |= ESS_AUDIO2_CTRL1_XFER_SIZE;
1299 1.18 mycroft else
1300 1.39 mycroft reg &= ~ESS_AUDIO2_CTRL1_XFER_SIZE;
1301 1.39 mycroft reg |= ESS_AUDIO2_CTRL1_DEMAND_8;
1302 1.39 mycroft reg |= ESS_AUDIO2_CTRL1_DAC_ENABLE | ESS_AUDIO2_CTRL1_FIFO_ENABLE |
1303 1.39 mycroft ESS_AUDIO2_CTRL1_AUTO_INIT;
1304 1.39 mycroft ess_write_mix_reg(sc, ESS_MREG_AUDIO2_CTRL1, reg);
1305 1.34 mycroft
1306 1.33 nathanw return (0);
1307 1.33 nathanw }
1308 1.33 nathanw
1309 1.33 nathanw int
1310 1.66 kent ess_audio1_trigger_input(
1311 1.66 kent void *addr,
1312 1.66 kent void *start, void *end,
1313 1.66 kent int blksize,
1314 1.66 kent void (*intr)(void *),
1315 1.66 kent void *arg,
1316 1.66 kent const audio_params_t *param)
1317 1.33 nathanw {
1318 1.66 kent struct ess_softc *sc;
1319 1.39 mycroft u_int8_t reg;
1320 1.33 nathanw
1321 1.66 kent sc = addr;
1322 1.65 kent DPRINTFN(1, ("ess_audio1_trigger_input: sc=%p start=%p end=%p "
1323 1.65 kent "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1324 1.33 nathanw
1325 1.34 mycroft if (sc->sc_audio1.active)
1326 1.36 mycroft panic("ess_audio1_trigger_input: already running");
1327 1.39 mycroft
1328 1.34 mycroft sc->sc_audio1.active = 1;
1329 1.34 mycroft sc->sc_audio1.intr = intr;
1330 1.34 mycroft sc->sc_audio1.arg = arg;
1331 1.42 mycroft if (sc->sc_audio1.polled) {
1332 1.43 mycroft sc->sc_audio1.dmapos = 0;
1333 1.43 mycroft sc->sc_audio1.buffersize = (char *)end - (char *)start;
1334 1.42 mycroft sc->sc_audio1.dmacount = 0;
1335 1.42 mycroft sc->sc_audio1.blksize = blksize;
1336 1.51 thorpej callout_reset(&sc->sc_poll1_ch, hz / 30,
1337 1.51 thorpej ess_audio1_poll, sc);
1338 1.42 mycroft }
1339 1.19 mycroft
1340 1.39 mycroft reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO_CTRL);
1341 1.19 mycroft if (param->channels == 2) {
1342 1.39 mycroft reg &= ~ESS_AUDIO_CTRL_MONO;
1343 1.39 mycroft reg |= ESS_AUDIO_CTRL_STEREO;
1344 1.17 mycroft } else {
1345 1.39 mycroft reg |= ESS_AUDIO_CTRL_MONO;
1346 1.39 mycroft reg &= ~ESS_AUDIO_CTRL_STEREO;
1347 1.17 mycroft }
1348 1.39 mycroft ess_write_x_reg(sc, ESS_XCMD_AUDIO_CTRL, reg);
1349 1.17 mycroft
1350 1.39 mycroft reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO1_CTRL1);
1351 1.65 kent if (param->precision == 16)
1352 1.39 mycroft reg |= ESS_AUDIO1_CTRL1_FIFO_SIZE;
1353 1.39 mycroft else
1354 1.39 mycroft reg &= ~ESS_AUDIO1_CTRL1_FIFO_SIZE;
1355 1.39 mycroft if (param->channels == 2)
1356 1.39 mycroft reg |= ESS_AUDIO1_CTRL1_FIFO_STEREO;
1357 1.39 mycroft else
1358 1.39 mycroft reg &= ~ESS_AUDIO1_CTRL1_FIFO_STEREO;
1359 1.19 mycroft if (param->encoding == AUDIO_ENCODING_SLINEAR_BE ||
1360 1.34 mycroft param->encoding == AUDIO_ENCODING_SLINEAR_LE)
1361 1.39 mycroft reg |= ESS_AUDIO1_CTRL1_FIFO_SIGNED;
1362 1.17 mycroft else
1363 1.39 mycroft reg &= ~ESS_AUDIO1_CTRL1_FIFO_SIGNED;
1364 1.39 mycroft reg |= ESS_AUDIO1_CTRL1_FIFO_CONNECT;
1365 1.39 mycroft ess_write_x_reg(sc, ESS_XCMD_AUDIO1_CTRL1, reg);
1366 1.17 mycroft
1367 1.65 kent isa_dmastart(sc->sc_ic, sc->sc_audio1.drq, start,
1368 1.34 mycroft (char *)end - (char *)start, NULL,
1369 1.34 mycroft DMAMODE_READ | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT);
1370 1.11 mycroft
1371 1.10 mycroft /* Program transfer count registers with 2's complement of count. */
1372 1.19 mycroft blksize = -blksize;
1373 1.19 mycroft ess_write_x_reg(sc, ESS_XCMD_XFER_COUNTLO, blksize);
1374 1.19 mycroft ess_write_x_reg(sc, ESS_XCMD_XFER_COUNTHI, blksize >> 8);
1375 1.1 augustss
1376 1.18 mycroft /* Use 4 bytes per input DMA. */
1377 1.39 mycroft ess_set_xreg_bits(sc, ESS_XCMD_DEMAND_CTRL, ESS_DEMAND_CTRL_DEMAND_4);
1378 1.18 mycroft
1379 1.10 mycroft /* Start auto-init DMA */
1380 1.65 kent ess_wdsp(sc, ESS_ACMD_DISABLE_SPKR);
1381 1.39 mycroft reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO1_CTRL2);
1382 1.39 mycroft reg |= ESS_AUDIO1_CTRL2_DMA_READ | ESS_AUDIO1_CTRL2_ADC_ENABLE;
1383 1.39 mycroft reg |= ESS_AUDIO1_CTRL2_FIFO_ENABLE | ESS_AUDIO1_CTRL2_AUTO_INIT;
1384 1.39 mycroft ess_write_x_reg(sc, ESS_XCMD_AUDIO1_CTRL2, reg);
1385 1.1 augustss
1386 1.66 kent return 0;
1387 1.1 augustss }
1388 1.1 augustss
1389 1.34 mycroft int
1390 1.66 kent ess_audio1_halt(void *addr)
1391 1.33 nathanw {
1392 1.66 kent struct ess_softc *sc;
1393 1.33 nathanw
1394 1.66 kent sc = addr;
1395 1.39 mycroft DPRINTF(("ess_audio1_halt: sc=%p\n", sc));
1396 1.34 mycroft
1397 1.34 mycroft if (sc->sc_audio1.active) {
1398 1.34 mycroft ess_clear_xreg_bits(sc, ESS_XCMD_AUDIO1_CTRL2,
1399 1.34 mycroft ESS_AUDIO1_CTRL2_FIFO_ENABLE);
1400 1.34 mycroft isa_dmaabort(sc->sc_ic, sc->sc_audio1.drq);
1401 1.42 mycroft if (sc->sc_audio1.polled)
1402 1.51 thorpej callout_stop(&sc->sc_poll1_ch);
1403 1.34 mycroft sc->sc_audio1.active = 0;
1404 1.33 nathanw }
1405 1.33 nathanw
1406 1.66 kent return 0;
1407 1.33 nathanw }
1408 1.33 nathanw
1409 1.1 augustss int
1410 1.66 kent ess_audio2_halt(void *addr)
1411 1.1 augustss {
1412 1.66 kent struct ess_softc *sc;
1413 1.1 augustss
1414 1.66 kent sc = addr;
1415 1.39 mycroft DPRINTF(("ess_audio2_halt: sc=%p\n", sc));
1416 1.34 mycroft
1417 1.34 mycroft if (sc->sc_audio2.active) {
1418 1.31 mycroft ess_clear_mreg_bits(sc, ESS_MREG_AUDIO2_CTRL1,
1419 1.31 mycroft ESS_AUDIO2_CTRL1_DAC_ENABLE |
1420 1.31 mycroft ESS_AUDIO2_CTRL1_FIFO_ENABLE);
1421 1.34 mycroft isa_dmaabort(sc->sc_ic, sc->sc_audio2.drq);
1422 1.42 mycroft if (sc->sc_audio2.polled)
1423 1.51 thorpej callout_stop(&sc->sc_poll2_ch);
1424 1.34 mycroft sc->sc_audio2.active = 0;
1425 1.33 nathanw }
1426 1.33 nathanw
1427 1.66 kent return 0;
1428 1.33 nathanw }
1429 1.33 nathanw
1430 1.33 nathanw int
1431 1.66 kent ess_audio1_intr(void *arg)
1432 1.1 augustss {
1433 1.66 kent struct ess_softc *sc;
1434 1.66 kent uint8_t reg;
1435 1.79 jmcneill int rv;
1436 1.1 augustss
1437 1.66 kent sc = arg;
1438 1.36 mycroft DPRINTFN(1,("ess_audio1_intr: intr=%p\n", sc->sc_audio1.intr));
1439 1.1 augustss
1440 1.79 jmcneill mutex_spin_enter(&sc->sc_intr_lock);
1441 1.79 jmcneill
1442 1.41 mycroft /* Check and clear interrupt on Audio1. */
1443 1.41 mycroft reg = EREAD1(sc->sc_iot, sc->sc_ioh, ESS_DSP_RW_STATUS);
1444 1.79 jmcneill if ((reg & ESS_DSP_READ_OFLOW) == 0) {
1445 1.79 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
1446 1.66 kent return 0;
1447 1.79 jmcneill }
1448 1.41 mycroft reg = EREAD1(sc->sc_iot, sc->sc_ioh, ESS_CLEAR_INTR);
1449 1.10 mycroft
1450 1.36 mycroft sc->sc_audio1.nintr++;
1451 1.1 augustss
1452 1.39 mycroft if (sc->sc_audio1.active) {
1453 1.36 mycroft (*sc->sc_audio1.intr)(sc->sc_audio1.arg);
1454 1.79 jmcneill rv = 1;
1455 1.39 mycroft } else
1456 1.79 jmcneill rv = 0;
1457 1.79 jmcneill
1458 1.79 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
1459 1.79 jmcneill
1460 1.79 jmcneill return rv;
1461 1.1 augustss }
1462 1.1 augustss
1463 1.1 augustss int
1464 1.66 kent ess_audio2_intr(void *arg)
1465 1.1 augustss {
1466 1.66 kent struct ess_softc *sc;
1467 1.66 kent uint8_t reg;
1468 1.79 jmcneill int rv;
1469 1.34 mycroft
1470 1.66 kent sc = arg;
1471 1.36 mycroft DPRINTFN(1,("ess_audio2_intr: intr=%p\n", sc->sc_audio2.intr));
1472 1.34 mycroft
1473 1.79 jmcneill mutex_spin_enter(&sc->sc_intr_lock);
1474 1.79 jmcneill
1475 1.41 mycroft /* Check and clear interrupt on Audio2. */
1476 1.41 mycroft reg = ess_read_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2);
1477 1.79 jmcneill if ((reg & ESS_AUDIO2_CTRL2_IRQ_LATCH) == 0) {
1478 1.79 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
1479 1.66 kent return 0;
1480 1.79 jmcneill }
1481 1.41 mycroft reg &= ~ESS_AUDIO2_CTRL2_IRQ_LATCH;
1482 1.41 mycroft ess_write_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2, reg);
1483 1.1 augustss
1484 1.36 mycroft sc->sc_audio2.nintr++;
1485 1.1 augustss
1486 1.39 mycroft if (sc->sc_audio2.active) {
1487 1.36 mycroft (*sc->sc_audio2.intr)(sc->sc_audio2.arg);
1488 1.79 jmcneill rv = 1;
1489 1.39 mycroft } else
1490 1.79 jmcneill rv = 0;
1491 1.79 jmcneill
1492 1.79 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
1493 1.79 jmcneill
1494 1.79 jmcneill return rv;
1495 1.42 mycroft }
1496 1.42 mycroft
1497 1.42 mycroft void
1498 1.66 kent ess_audio1_poll(void *addr)
1499 1.42 mycroft {
1500 1.66 kent struct ess_softc *sc;
1501 1.42 mycroft int dmapos, dmacount;
1502 1.42 mycroft
1503 1.66 kent sc = addr;
1504 1.79 jmcneill mutex_spin_enter(&sc->sc_intr_lock);
1505 1.79 jmcneill
1506 1.79 jmcneill if (!sc->sc_audio1.active) {
1507 1.79 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
1508 1.42 mycroft return;
1509 1.79 jmcneill }
1510 1.42 mycroft
1511 1.42 mycroft sc->sc_audio1.nintr++;
1512 1.42 mycroft
1513 1.42 mycroft dmapos = isa_dmacount(sc->sc_ic, sc->sc_audio1.drq);
1514 1.43 mycroft dmacount = sc->sc_audio1.dmapos - dmapos;
1515 1.43 mycroft if (dmacount < 0)
1516 1.42 mycroft dmacount += sc->sc_audio1.buffersize;
1517 1.43 mycroft sc->sc_audio1.dmapos = dmapos;
1518 1.43 mycroft #if 1
1519 1.43 mycroft dmacount += sc->sc_audio1.dmacount;
1520 1.42 mycroft while (dmacount > sc->sc_audio1.blksize) {
1521 1.42 mycroft dmacount -= sc->sc_audio1.blksize;
1522 1.42 mycroft (*sc->sc_audio1.intr)(sc->sc_audio1.arg);
1523 1.42 mycroft }
1524 1.42 mycroft sc->sc_audio1.dmacount = dmacount;
1525 1.43 mycroft #else
1526 1.43 mycroft (*sc->sc_audio1.intr)(sc->sc_audio1.arg, dmacount);
1527 1.43 mycroft #endif
1528 1.42 mycroft
1529 1.79 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
1530 1.51 thorpej callout_reset(&sc->sc_poll1_ch, hz / 30, ess_audio1_poll, sc);
1531 1.42 mycroft }
1532 1.42 mycroft
1533 1.42 mycroft void
1534 1.66 kent ess_audio2_poll(void *addr)
1535 1.42 mycroft {
1536 1.66 kent struct ess_softc *sc;
1537 1.42 mycroft int dmapos, dmacount;
1538 1.42 mycroft
1539 1.66 kent sc = addr;
1540 1.79 jmcneill mutex_spin_enter(&sc->sc_intr_lock);
1541 1.79 jmcneill
1542 1.79 jmcneill if (!sc->sc_audio2.active) {
1543 1.79 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
1544 1.42 mycroft return;
1545 1.79 jmcneill }
1546 1.42 mycroft
1547 1.42 mycroft sc->sc_audio2.nintr++;
1548 1.42 mycroft
1549 1.42 mycroft dmapos = isa_dmacount(sc->sc_ic, sc->sc_audio2.drq);
1550 1.43 mycroft dmacount = sc->sc_audio2.dmapos - dmapos;
1551 1.43 mycroft if (dmacount < 0)
1552 1.42 mycroft dmacount += sc->sc_audio2.buffersize;
1553 1.43 mycroft sc->sc_audio2.dmapos = dmapos;
1554 1.43 mycroft #if 1
1555 1.43 mycroft dmacount += sc->sc_audio2.dmacount;
1556 1.42 mycroft while (dmacount > sc->sc_audio2.blksize) {
1557 1.42 mycroft dmacount -= sc->sc_audio2.blksize;
1558 1.42 mycroft (*sc->sc_audio2.intr)(sc->sc_audio2.arg);
1559 1.42 mycroft }
1560 1.42 mycroft sc->sc_audio2.dmacount = dmacount;
1561 1.43 mycroft #else
1562 1.43 mycroft (*sc->sc_audio2.intr)(sc->sc_audio2.arg, dmacount);
1563 1.43 mycroft #endif
1564 1.42 mycroft
1565 1.79 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
1566 1.51 thorpej callout_reset(&sc->sc_poll2_ch, hz / 30, ess_audio2_poll, sc);
1567 1.1 augustss }
1568 1.1 augustss
1569 1.1 augustss int
1570 1.73 christos ess_round_blocksize(void *addr, int blk, int mode,
1571 1.73 christos const audio_params_t *param)
1572 1.1 augustss {
1573 1.66 kent
1574 1.66 kent return blk & -8; /* round for max DMA size */
1575 1.1 augustss }
1576 1.1 augustss
1577 1.1 augustss int
1578 1.66 kent ess_set_port(void *addr, mixer_ctrl_t *cp)
1579 1.1 augustss {
1580 1.66 kent struct ess_softc *sc;
1581 1.1 augustss int lgain, rgain;
1582 1.66 kent
1583 1.66 kent sc = addr;
1584 1.4 augustss DPRINTFN(5,("ess_set_port: port=%d num_channels=%d\n",
1585 1.4 augustss cp->dev, cp->un.value.num_channels));
1586 1.1 augustss
1587 1.1 augustss switch (cp->dev) {
1588 1.1 augustss /*
1589 1.1 augustss * The following mixer ports are all stereo. If we get a
1590 1.1 augustss * single-channel gain value passed in, then we duplicate it
1591 1.1 augustss * to both left and right channels.
1592 1.1 augustss */
1593 1.1 augustss case ESS_MASTER_VOL:
1594 1.1 augustss case ESS_DAC_PLAY_VOL:
1595 1.1 augustss case ESS_MIC_PLAY_VOL:
1596 1.1 augustss case ESS_LINE_PLAY_VOL:
1597 1.1 augustss case ESS_SYNTH_PLAY_VOL:
1598 1.1 augustss case ESS_CD_PLAY_VOL:
1599 1.1 augustss case ESS_AUXB_PLAY_VOL:
1600 1.1 augustss case ESS_RECORD_VOL:
1601 1.1 augustss if (cp->type != AUDIO_MIXER_VALUE)
1602 1.1 augustss return EINVAL;
1603 1.1 augustss
1604 1.1 augustss switch (cp->un.value.num_channels) {
1605 1.1 augustss case 1:
1606 1.1 augustss lgain = rgain = ESS_4BIT_GAIN(
1607 1.1 augustss cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1608 1.1 augustss break;
1609 1.1 augustss case 2:
1610 1.1 augustss lgain = ESS_4BIT_GAIN(
1611 1.1 augustss cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
1612 1.1 augustss rgain = ESS_4BIT_GAIN(
1613 1.1 augustss cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
1614 1.1 augustss break;
1615 1.1 augustss default:
1616 1.1 augustss return EINVAL;
1617 1.1 augustss }
1618 1.1 augustss
1619 1.1 augustss sc->gain[cp->dev][ESS_LEFT] = lgain;
1620 1.1 augustss sc->gain[cp->dev][ESS_RIGHT] = rgain;
1621 1.1 augustss ess_set_gain(sc, cp->dev, 1);
1622 1.66 kent return 0;
1623 1.1 augustss
1624 1.1 augustss /*
1625 1.1 augustss * The PC speaker port is mono. If we get a stereo gain value
1626 1.1 augustss * passed in, then we return EINVAL.
1627 1.1 augustss */
1628 1.1 augustss case ESS_PCSPEAKER_VOL:
1629 1.1 augustss if (cp->un.value.num_channels != 1)
1630 1.1 augustss return EINVAL;
1631 1.1 augustss
1632 1.34 mycroft sc->gain[cp->dev][ESS_LEFT] = sc->gain[cp->dev][ESS_RIGHT] =
1633 1.1 augustss ESS_3BIT_GAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1634 1.1 augustss ess_set_gain(sc, cp->dev, 1);
1635 1.66 kent return 0;
1636 1.1 augustss
1637 1.1 augustss case ESS_RECORD_SOURCE:
1638 1.46 augustss if (ESS_USE_AUDIO1(sc->sc_model)) {
1639 1.34 mycroft if (cp->type == AUDIO_MIXER_ENUM)
1640 1.66 kent return ess_set_in_port(sc, cp->un.ord);
1641 1.34 mycroft else
1642 1.66 kent return EINVAL;
1643 1.34 mycroft } else {
1644 1.34 mycroft if (cp->type == AUDIO_MIXER_SET)
1645 1.66 kent return ess_set_in_ports(sc, cp->un.mask);
1646 1.34 mycroft else
1647 1.66 kent return EINVAL;
1648 1.34 mycroft }
1649 1.66 kent return 0;
1650 1.1 augustss
1651 1.1 augustss case ESS_RECORD_MONITOR:
1652 1.1 augustss if (cp->type != AUDIO_MIXER_ENUM)
1653 1.1 augustss return EINVAL;
1654 1.1 augustss
1655 1.1 augustss if (cp->un.ord)
1656 1.1 augustss /* Enable monitor */
1657 1.1 augustss ess_set_xreg_bits(sc, ESS_XCMD_AUDIO_CTRL,
1658 1.1 augustss ESS_AUDIO_CTRL_MONITOR);
1659 1.1 augustss else
1660 1.1 augustss /* Disable monitor */
1661 1.1 augustss ess_clear_xreg_bits(sc, ESS_XCMD_AUDIO_CTRL,
1662 1.1 augustss ESS_AUDIO_CTRL_MONITOR);
1663 1.66 kent return 0;
1664 1.1 augustss }
1665 1.1 augustss
1666 1.82 nakayama if (ESS_IS_ES18X9(sc->sc_model)) {
1667 1.82 nakayama
1668 1.82 nakayama switch (cp->dev) {
1669 1.82 nakayama case ESS_SPATIALIZER:
1670 1.82 nakayama if (cp->type != AUDIO_MIXER_VALUE ||
1671 1.82 nakayama cp->un.value.num_channels != 1)
1672 1.82 nakayama return EINVAL;
1673 1.82 nakayama
1674 1.82 nakayama sc->gain[cp->dev][ESS_LEFT] =
1675 1.82 nakayama sc->gain[cp->dev][ESS_RIGHT] = ESS_6BIT_GAIN(
1676 1.82 nakayama cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1677 1.82 nakayama ess_set_gain(sc, cp->dev, 1);
1678 1.82 nakayama return 0;
1679 1.82 nakayama
1680 1.82 nakayama case ESS_SPATIALIZER_ENABLE:
1681 1.82 nakayama if (cp->type != AUDIO_MIXER_ENUM)
1682 1.82 nakayama return EINVAL;
1683 1.82 nakayama
1684 1.82 nakayama sc->sc_spatializer = (cp->un.ord != 0);
1685 1.82 nakayama if (sc->sc_spatializer)
1686 1.82 nakayama ess_set_mreg_bits(sc, ESS_MREG_SPATIAL_CTRL,
1687 1.82 nakayama ESS_SPATIAL_CTRL_ENABLE);
1688 1.82 nakayama else
1689 1.82 nakayama ess_clear_mreg_bits(sc, ESS_MREG_SPATIAL_CTRL,
1690 1.82 nakayama ESS_SPATIAL_CTRL_ENABLE);
1691 1.82 nakayama return 0;
1692 1.82 nakayama }
1693 1.82 nakayama }
1694 1.82 nakayama
1695 1.46 augustss if (ESS_USE_AUDIO1(sc->sc_model))
1696 1.66 kent return EINVAL;
1697 1.1 augustss
1698 1.1 augustss switch (cp->dev) {
1699 1.33 nathanw case ESS_DAC_REC_VOL:
1700 1.33 nathanw case ESS_MIC_REC_VOL:
1701 1.33 nathanw case ESS_LINE_REC_VOL:
1702 1.33 nathanw case ESS_SYNTH_REC_VOL:
1703 1.33 nathanw case ESS_CD_REC_VOL:
1704 1.33 nathanw case ESS_AUXB_REC_VOL:
1705 1.34 mycroft if (cp->type != AUDIO_MIXER_VALUE)
1706 1.33 nathanw return EINVAL;
1707 1.34 mycroft
1708 1.34 mycroft switch (cp->un.value.num_channels) {
1709 1.34 mycroft case 1:
1710 1.34 mycroft lgain = rgain = ESS_4BIT_GAIN(
1711 1.34 mycroft cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1712 1.34 mycroft break;
1713 1.34 mycroft case 2:
1714 1.34 mycroft lgain = ESS_4BIT_GAIN(
1715 1.34 mycroft cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
1716 1.34 mycroft rgain = ESS_4BIT_GAIN(
1717 1.34 mycroft cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
1718 1.34 mycroft break;
1719 1.34 mycroft default:
1720 1.34 mycroft return EINVAL;
1721 1.34 mycroft }
1722 1.34 mycroft
1723 1.34 mycroft sc->gain[cp->dev][ESS_LEFT] = lgain;
1724 1.34 mycroft sc->gain[cp->dev][ESS_RIGHT] = rgain;
1725 1.34 mycroft ess_set_gain(sc, cp->dev, 1);
1726 1.66 kent return 0;
1727 1.34 mycroft
1728 1.34 mycroft case ESS_MIC_PREAMP:
1729 1.34 mycroft if (cp->type != AUDIO_MIXER_ENUM)
1730 1.34 mycroft return EINVAL;
1731 1.34 mycroft
1732 1.34 mycroft if (cp->un.ord)
1733 1.34 mycroft /* Enable microphone preamp */
1734 1.34 mycroft ess_set_xreg_bits(sc, ESS_XCMD_PREAMP_CTRL,
1735 1.34 mycroft ESS_PREAMP_CTRL_ENABLE);
1736 1.34 mycroft else
1737 1.34 mycroft /* Disable microphone preamp */
1738 1.34 mycroft ess_clear_xreg_bits(sc, ESS_XCMD_PREAMP_CTRL,
1739 1.34 mycroft ESS_PREAMP_CTRL_ENABLE);
1740 1.66 kent return 0;
1741 1.34 mycroft }
1742 1.34 mycroft
1743 1.66 kent return EINVAL;
1744 1.34 mycroft }
1745 1.34 mycroft
1746 1.34 mycroft int
1747 1.66 kent ess_get_port(void *addr, mixer_ctrl_t *cp)
1748 1.34 mycroft {
1749 1.66 kent struct ess_softc *sc;
1750 1.66 kent
1751 1.66 kent sc = addr;
1752 1.34 mycroft DPRINTFN(5,("ess_get_port: port=%d\n", cp->dev));
1753 1.34 mycroft
1754 1.34 mycroft switch (cp->dev) {
1755 1.34 mycroft case ESS_MASTER_VOL:
1756 1.1 augustss case ESS_DAC_PLAY_VOL:
1757 1.1 augustss case ESS_MIC_PLAY_VOL:
1758 1.1 augustss case ESS_LINE_PLAY_VOL:
1759 1.1 augustss case ESS_SYNTH_PLAY_VOL:
1760 1.1 augustss case ESS_CD_PLAY_VOL:
1761 1.1 augustss case ESS_AUXB_PLAY_VOL:
1762 1.1 augustss case ESS_RECORD_VOL:
1763 1.1 augustss switch (cp->un.value.num_channels) {
1764 1.1 augustss case 1:
1765 1.66 kent cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1766 1.1 augustss sc->gain[cp->dev][ESS_LEFT];
1767 1.1 augustss break;
1768 1.1 augustss case 2:
1769 1.66 kent cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1770 1.1 augustss sc->gain[cp->dev][ESS_LEFT];
1771 1.66 kent cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1772 1.1 augustss sc->gain[cp->dev][ESS_RIGHT];
1773 1.1 augustss break;
1774 1.1 augustss default:
1775 1.1 augustss return EINVAL;
1776 1.1 augustss }
1777 1.66 kent return 0;
1778 1.1 augustss
1779 1.34 mycroft case ESS_PCSPEAKER_VOL:
1780 1.34 mycroft if (cp->un.value.num_channels != 1)
1781 1.33 nathanw return EINVAL;
1782 1.34 mycroft
1783 1.66 kent cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1784 1.34 mycroft sc->gain[cp->dev][ESS_LEFT];
1785 1.66 kent return 0;
1786 1.1 augustss
1787 1.1 augustss case ESS_RECORD_SOURCE:
1788 1.46 augustss if (ESS_USE_AUDIO1(sc->sc_model))
1789 1.33 nathanw cp->un.ord = sc->in_port;
1790 1.33 nathanw else
1791 1.33 nathanw cp->un.mask = sc->in_mask;
1792 1.66 kent return 0;
1793 1.1 augustss
1794 1.1 augustss case ESS_RECORD_MONITOR:
1795 1.1 augustss cp->un.ord = (ess_read_x_reg(sc, ESS_XCMD_AUDIO_CTRL) &
1796 1.1 augustss ESS_AUDIO_CTRL_MONITOR) ? 1 : 0;
1797 1.66 kent return 0;
1798 1.34 mycroft }
1799 1.34 mycroft
1800 1.82 nakayama if (ESS_IS_ES18X9(sc->sc_model)) {
1801 1.82 nakayama
1802 1.82 nakayama switch (cp->dev) {
1803 1.82 nakayama case ESS_SPATIALIZER:
1804 1.82 nakayama if (cp->un.value.num_channels != 1)
1805 1.82 nakayama return EINVAL;
1806 1.82 nakayama
1807 1.82 nakayama cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1808 1.82 nakayama sc->gain[cp->dev][ESS_LEFT];
1809 1.82 nakayama return 0;
1810 1.82 nakayama
1811 1.82 nakayama case ESS_SPATIALIZER_ENABLE:
1812 1.82 nakayama cp->un.ord = sc->sc_spatializer;
1813 1.82 nakayama return 0;
1814 1.82 nakayama }
1815 1.82 nakayama }
1816 1.82 nakayama
1817 1.46 augustss if (ESS_USE_AUDIO1(sc->sc_model))
1818 1.66 kent return EINVAL;
1819 1.34 mycroft
1820 1.34 mycroft switch (cp->dev) {
1821 1.34 mycroft case ESS_DAC_REC_VOL:
1822 1.34 mycroft case ESS_MIC_REC_VOL:
1823 1.34 mycroft case ESS_LINE_REC_VOL:
1824 1.34 mycroft case ESS_SYNTH_REC_VOL:
1825 1.34 mycroft case ESS_CD_REC_VOL:
1826 1.34 mycroft case ESS_AUXB_REC_VOL:
1827 1.34 mycroft switch (cp->un.value.num_channels) {
1828 1.34 mycroft case 1:
1829 1.66 kent cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1830 1.34 mycroft sc->gain[cp->dev][ESS_LEFT];
1831 1.34 mycroft break;
1832 1.34 mycroft case 2:
1833 1.66 kent cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1834 1.34 mycroft sc->gain[cp->dev][ESS_LEFT];
1835 1.66 kent cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1836 1.34 mycroft sc->gain[cp->dev][ESS_RIGHT];
1837 1.34 mycroft break;
1838 1.34 mycroft default:
1839 1.34 mycroft return EINVAL;
1840 1.34 mycroft }
1841 1.66 kent return 0;
1842 1.1 augustss
1843 1.34 mycroft case ESS_MIC_PREAMP:
1844 1.34 mycroft cp->un.ord = (ess_read_x_reg(sc, ESS_XCMD_PREAMP_CTRL) &
1845 1.34 mycroft ESS_PREAMP_CTRL_ENABLE) ? 1 : 0;
1846 1.66 kent return 0;
1847 1.1 augustss }
1848 1.1 augustss
1849 1.66 kent return EINVAL;
1850 1.1 augustss }
1851 1.1 augustss
1852 1.1 augustss int
1853 1.66 kent ess_query_devinfo(void *addr, mixer_devinfo_t *dip)
1854 1.1 augustss {
1855 1.66 kent struct ess_softc *sc;
1856 1.1 augustss
1857 1.66 kent sc = addr;
1858 1.66 kent DPRINTFN(5,("ess_query_devinfo: model=%d index=%d\n",
1859 1.4 augustss sc->sc_model, dip->index));
1860 1.1 augustss
1861 1.1 augustss /*
1862 1.1 augustss * REVISIT: There are some slight differences between the
1863 1.1 augustss * mixers on the different ESS chips, which can
1864 1.1 augustss * be sorted out using the chip model rather than a
1865 1.1 augustss * separate mixer model.
1866 1.1 augustss * This is currently coded assuming an ES1887; we
1867 1.1 augustss * need to work out which bits are not applicable to
1868 1.1 augustss * the other models (1888 and 888).
1869 1.1 augustss */
1870 1.1 augustss switch (dip->index) {
1871 1.1 augustss case ESS_DAC_PLAY_VOL:
1872 1.1 augustss dip->mixer_class = ESS_INPUT_CLASS;
1873 1.27 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
1874 1.1 augustss strcpy(dip->label.name, AudioNdac);
1875 1.27 mycroft dip->type = AUDIO_MIXER_VALUE;
1876 1.1 augustss dip->un.v.num_channels = 2;
1877 1.1 augustss strcpy(dip->un.v.units.name, AudioNvolume);
1878 1.66 kent return 0;
1879 1.1 augustss
1880 1.1 augustss case ESS_MIC_PLAY_VOL:
1881 1.1 augustss dip->mixer_class = ESS_INPUT_CLASS;
1882 1.1 augustss dip->prev = AUDIO_MIXER_LAST;
1883 1.46 augustss if (ESS_USE_AUDIO1(sc->sc_model))
1884 1.33 nathanw dip->next = AUDIO_MIXER_LAST;
1885 1.33 nathanw else
1886 1.33 nathanw dip->next = ESS_MIC_PREAMP;
1887 1.1 augustss strcpy(dip->label.name, AudioNmicrophone);
1888 1.27 mycroft dip->type = AUDIO_MIXER_VALUE;
1889 1.1 augustss dip->un.v.num_channels = 2;
1890 1.1 augustss strcpy(dip->un.v.units.name, AudioNvolume);
1891 1.66 kent return 0;
1892 1.1 augustss
1893 1.1 augustss case ESS_LINE_PLAY_VOL:
1894 1.1 augustss dip->mixer_class = ESS_INPUT_CLASS;
1895 1.27 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
1896 1.1 augustss strcpy(dip->label.name, AudioNline);
1897 1.27 mycroft dip->type = AUDIO_MIXER_VALUE;
1898 1.1 augustss dip->un.v.num_channels = 2;
1899 1.1 augustss strcpy(dip->un.v.units.name, AudioNvolume);
1900 1.66 kent return 0;
1901 1.1 augustss
1902 1.1 augustss case ESS_SYNTH_PLAY_VOL:
1903 1.1 augustss dip->mixer_class = ESS_INPUT_CLASS;
1904 1.27 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
1905 1.1 augustss strcpy(dip->label.name, AudioNfmsynth);
1906 1.27 mycroft dip->type = AUDIO_MIXER_VALUE;
1907 1.1 augustss dip->un.v.num_channels = 2;
1908 1.1 augustss strcpy(dip->un.v.units.name, AudioNvolume);
1909 1.66 kent return 0;
1910 1.1 augustss
1911 1.1 augustss case ESS_CD_PLAY_VOL:
1912 1.1 augustss dip->mixer_class = ESS_INPUT_CLASS;
1913 1.27 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
1914 1.1 augustss strcpy(dip->label.name, AudioNcd);
1915 1.27 mycroft dip->type = AUDIO_MIXER_VALUE;
1916 1.1 augustss dip->un.v.num_channels = 2;
1917 1.1 augustss strcpy(dip->un.v.units.name, AudioNvolume);
1918 1.66 kent return 0;
1919 1.1 augustss
1920 1.1 augustss case ESS_AUXB_PLAY_VOL:
1921 1.1 augustss dip->mixer_class = ESS_INPUT_CLASS;
1922 1.27 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
1923 1.1 augustss strcpy(dip->label.name, "auxb");
1924 1.27 mycroft dip->type = AUDIO_MIXER_VALUE;
1925 1.1 augustss dip->un.v.num_channels = 2;
1926 1.1 augustss strcpy(dip->un.v.units.name, AudioNvolume);
1927 1.66 kent return 0;
1928 1.1 augustss
1929 1.1 augustss case ESS_INPUT_CLASS:
1930 1.1 augustss dip->mixer_class = ESS_INPUT_CLASS;
1931 1.1 augustss dip->next = dip->prev = AUDIO_MIXER_LAST;
1932 1.1 augustss strcpy(dip->label.name, AudioCinputs);
1933 1.27 mycroft dip->type = AUDIO_MIXER_CLASS;
1934 1.66 kent return 0;
1935 1.1 augustss
1936 1.1 augustss case ESS_MASTER_VOL:
1937 1.1 augustss dip->mixer_class = ESS_OUTPUT_CLASS;
1938 1.27 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
1939 1.1 augustss strcpy(dip->label.name, AudioNmaster);
1940 1.27 mycroft dip->type = AUDIO_MIXER_VALUE;
1941 1.1 augustss dip->un.v.num_channels = 2;
1942 1.1 augustss strcpy(dip->un.v.units.name, AudioNvolume);
1943 1.66 kent return 0;
1944 1.1 augustss
1945 1.1 augustss case ESS_PCSPEAKER_VOL:
1946 1.1 augustss dip->mixer_class = ESS_OUTPUT_CLASS;
1947 1.27 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
1948 1.1 augustss strcpy(dip->label.name, "pc_speaker");
1949 1.27 mycroft dip->type = AUDIO_MIXER_VALUE;
1950 1.1 augustss dip->un.v.num_channels = 1;
1951 1.1 augustss strcpy(dip->un.v.units.name, AudioNvolume);
1952 1.66 kent return 0;
1953 1.1 augustss
1954 1.1 augustss case ESS_OUTPUT_CLASS:
1955 1.1 augustss dip->mixer_class = ESS_OUTPUT_CLASS;
1956 1.1 augustss dip->next = dip->prev = AUDIO_MIXER_LAST;
1957 1.1 augustss strcpy(dip->label.name, AudioCoutputs);
1958 1.27 mycroft dip->type = AUDIO_MIXER_CLASS;
1959 1.66 kent return 0;
1960 1.1 augustss
1961 1.1 augustss case ESS_RECORD_VOL:
1962 1.1 augustss dip->mixer_class = ESS_RECORD_CLASS;
1963 1.27 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
1964 1.1 augustss strcpy(dip->label.name, AudioNrecord);
1965 1.27 mycroft dip->type = AUDIO_MIXER_VALUE;
1966 1.1 augustss dip->un.v.num_channels = 2;
1967 1.1 augustss strcpy(dip->un.v.units.name, AudioNvolume);
1968 1.66 kent return 0;
1969 1.1 augustss
1970 1.1 augustss case ESS_RECORD_SOURCE:
1971 1.34 mycroft dip->mixer_class = ESS_RECORD_CLASS;
1972 1.27 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
1973 1.1 augustss strcpy(dip->label.name, AudioNsource);
1974 1.46 augustss if (ESS_USE_AUDIO1(sc->sc_model)) {
1975 1.34 mycroft /*
1976 1.34 mycroft * The 1788 doesn't use the input mixer control that
1977 1.34 mycroft * the 1888 uses, because it's a pain when you only
1978 1.66 kent * have one mixer.
1979 1.34 mycroft * Perhaps it could be emulated by keeping both sets of
1980 1.34 mycroft * gain values, and doing a `context switch' of the
1981 1.34 mycroft * mixer registers when shifting from playing to
1982 1.34 mycroft * recording.
1983 1.33 nathanw */
1984 1.33 nathanw dip->type = AUDIO_MIXER_ENUM;
1985 1.33 nathanw dip->un.e.num_mem = 4;
1986 1.33 nathanw strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
1987 1.33 nathanw dip->un.e.member[0].ord = ESS_SOURCE_MIC;
1988 1.33 nathanw strcpy(dip->un.e.member[1].label.name, AudioNline);
1989 1.33 nathanw dip->un.e.member[1].ord = ESS_SOURCE_LINE;
1990 1.33 nathanw strcpy(dip->un.e.member[2].label.name, AudioNcd);
1991 1.33 nathanw dip->un.e.member[2].ord = ESS_SOURCE_CD;
1992 1.33 nathanw strcpy(dip->un.e.member[3].label.name, AudioNmixerout);
1993 1.33 nathanw dip->un.e.member[3].ord = ESS_SOURCE_MIXER;
1994 1.33 nathanw } else {
1995 1.33 nathanw dip->type = AUDIO_MIXER_SET;
1996 1.33 nathanw dip->un.s.num_mem = 6;
1997 1.33 nathanw strcpy(dip->un.s.member[0].label.name, AudioNdac);
1998 1.33 nathanw dip->un.s.member[0].mask = 1 << ESS_DAC_REC_VOL;
1999 1.33 nathanw strcpy(dip->un.s.member[1].label.name, AudioNmicrophone);
2000 1.33 nathanw dip->un.s.member[1].mask = 1 << ESS_MIC_REC_VOL;
2001 1.33 nathanw strcpy(dip->un.s.member[2].label.name, AudioNline);
2002 1.33 nathanw dip->un.s.member[2].mask = 1 << ESS_LINE_REC_VOL;
2003 1.33 nathanw strcpy(dip->un.s.member[3].label.name, AudioNfmsynth);
2004 1.33 nathanw dip->un.s.member[3].mask = 1 << ESS_SYNTH_REC_VOL;
2005 1.33 nathanw strcpy(dip->un.s.member[4].label.name, AudioNcd);
2006 1.33 nathanw dip->un.s.member[4].mask = 1 << ESS_CD_REC_VOL;
2007 1.33 nathanw strcpy(dip->un.s.member[5].label.name, "auxb");
2008 1.33 nathanw dip->un.s.member[5].mask = 1 << ESS_AUXB_REC_VOL;
2009 1.33 nathanw }
2010 1.66 kent return 0;
2011 1.1 augustss
2012 1.1 augustss case ESS_RECORD_CLASS:
2013 1.1 augustss dip->mixer_class = ESS_RECORD_CLASS;
2014 1.1 augustss dip->next = dip->prev = AUDIO_MIXER_LAST;
2015 1.1 augustss strcpy(dip->label.name, AudioCrecord);
2016 1.27 mycroft dip->type = AUDIO_MIXER_CLASS;
2017 1.66 kent return 0;
2018 1.1 augustss
2019 1.1 augustss case ESS_RECORD_MONITOR:
2020 1.1 augustss dip->prev = dip->next = AUDIO_MIXER_LAST;
2021 1.45 nathanw strcpy(dip->label.name, AudioNmute);
2022 1.1 augustss dip->type = AUDIO_MIXER_ENUM;
2023 1.27 mycroft dip->mixer_class = ESS_MONITOR_CLASS;
2024 1.1 augustss dip->un.e.num_mem = 2;
2025 1.1 augustss strcpy(dip->un.e.member[0].label.name, AudioNoff);
2026 1.1 augustss dip->un.e.member[0].ord = 0;
2027 1.1 augustss strcpy(dip->un.e.member[1].label.name, AudioNon);
2028 1.1 augustss dip->un.e.member[1].ord = 1;
2029 1.66 kent return 0;
2030 1.1 augustss
2031 1.1 augustss case ESS_MONITOR_CLASS:
2032 1.1 augustss dip->mixer_class = ESS_MONITOR_CLASS;
2033 1.1 augustss dip->next = dip->prev = AUDIO_MIXER_LAST;
2034 1.1 augustss strcpy(dip->label.name, AudioCmonitor);
2035 1.27 mycroft dip->type = AUDIO_MIXER_CLASS;
2036 1.66 kent return 0;
2037 1.1 augustss }
2038 1.1 augustss
2039 1.82 nakayama if (ESS_IS_ES18X9(sc->sc_model)) {
2040 1.82 nakayama
2041 1.82 nakayama switch (dip->index) {
2042 1.82 nakayama case ESS_SPATIALIZER:
2043 1.82 nakayama dip->mixer_class = ESS_OUTPUT_CLASS;
2044 1.82 nakayama dip->prev = AUDIO_MIXER_LAST;
2045 1.82 nakayama dip->next = ESS_SPATIALIZER_ENABLE;
2046 1.82 nakayama strcpy(dip->label.name, AudioNspatial);
2047 1.82 nakayama dip->type = AUDIO_MIXER_VALUE;
2048 1.82 nakayama dip->un.v.num_channels = 1;
2049 1.82 nakayama strcpy(dip->un.v.units.name, "level");
2050 1.82 nakayama return 0;
2051 1.82 nakayama
2052 1.82 nakayama case ESS_SPATIALIZER_ENABLE:
2053 1.82 nakayama dip->mixer_class = ESS_OUTPUT_CLASS;
2054 1.82 nakayama dip->prev = ESS_SPATIALIZER;
2055 1.82 nakayama dip->next = AUDIO_MIXER_LAST;
2056 1.82 nakayama strcpy(dip->label.name, "enable");
2057 1.82 nakayama dip->type = AUDIO_MIXER_ENUM;
2058 1.82 nakayama dip->un.e.num_mem = 2;
2059 1.82 nakayama strcpy(dip->un.e.member[0].label.name, AudioNoff);
2060 1.82 nakayama dip->un.e.member[0].ord = 0;
2061 1.82 nakayama strcpy(dip->un.e.member[1].label.name, AudioNon);
2062 1.82 nakayama dip->un.e.member[1].ord = 1;
2063 1.82 nakayama return 0;
2064 1.82 nakayama }
2065 1.82 nakayama }
2066 1.82 nakayama
2067 1.46 augustss if (ESS_USE_AUDIO1(sc->sc_model))
2068 1.66 kent return ENXIO;
2069 1.34 mycroft
2070 1.34 mycroft switch (dip->index) {
2071 1.34 mycroft case ESS_DAC_REC_VOL:
2072 1.34 mycroft dip->mixer_class = ESS_RECORD_CLASS;
2073 1.34 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
2074 1.34 mycroft strcpy(dip->label.name, AudioNdac);
2075 1.34 mycroft dip->type = AUDIO_MIXER_VALUE;
2076 1.34 mycroft dip->un.v.num_channels = 2;
2077 1.34 mycroft strcpy(dip->un.v.units.name, AudioNvolume);
2078 1.66 kent return 0;
2079 1.34 mycroft
2080 1.34 mycroft case ESS_MIC_REC_VOL:
2081 1.34 mycroft dip->mixer_class = ESS_RECORD_CLASS;
2082 1.34 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
2083 1.34 mycroft strcpy(dip->label.name, AudioNmicrophone);
2084 1.34 mycroft dip->type = AUDIO_MIXER_VALUE;
2085 1.34 mycroft dip->un.v.num_channels = 2;
2086 1.34 mycroft strcpy(dip->un.v.units.name, AudioNvolume);
2087 1.66 kent return 0;
2088 1.34 mycroft
2089 1.34 mycroft case ESS_LINE_REC_VOL:
2090 1.34 mycroft dip->mixer_class = ESS_RECORD_CLASS;
2091 1.34 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
2092 1.34 mycroft strcpy(dip->label.name, AudioNline);
2093 1.34 mycroft dip->type = AUDIO_MIXER_VALUE;
2094 1.34 mycroft dip->un.v.num_channels = 2;
2095 1.34 mycroft strcpy(dip->un.v.units.name, AudioNvolume);
2096 1.66 kent return 0;
2097 1.34 mycroft
2098 1.34 mycroft case ESS_SYNTH_REC_VOL:
2099 1.34 mycroft dip->mixer_class = ESS_RECORD_CLASS;
2100 1.34 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
2101 1.34 mycroft strcpy(dip->label.name, AudioNfmsynth);
2102 1.34 mycroft dip->type = AUDIO_MIXER_VALUE;
2103 1.34 mycroft dip->un.v.num_channels = 2;
2104 1.34 mycroft strcpy(dip->un.v.units.name, AudioNvolume);
2105 1.66 kent return 0;
2106 1.34 mycroft
2107 1.34 mycroft case ESS_CD_REC_VOL:
2108 1.34 mycroft dip->mixer_class = ESS_RECORD_CLASS;
2109 1.34 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
2110 1.34 mycroft strcpy(dip->label.name, AudioNcd);
2111 1.34 mycroft dip->type = AUDIO_MIXER_VALUE;
2112 1.34 mycroft dip->un.v.num_channels = 2;
2113 1.34 mycroft strcpy(dip->un.v.units.name, AudioNvolume);
2114 1.66 kent return 0;
2115 1.34 mycroft
2116 1.34 mycroft case ESS_AUXB_REC_VOL:
2117 1.34 mycroft dip->mixer_class = ESS_RECORD_CLASS;
2118 1.34 mycroft dip->next = dip->prev = AUDIO_MIXER_LAST;
2119 1.34 mycroft strcpy(dip->label.name, "auxb");
2120 1.34 mycroft dip->type = AUDIO_MIXER_VALUE;
2121 1.34 mycroft dip->un.v.num_channels = 2;
2122 1.34 mycroft strcpy(dip->un.v.units.name, AudioNvolume);
2123 1.66 kent return 0;
2124 1.34 mycroft
2125 1.34 mycroft case ESS_MIC_PREAMP:
2126 1.34 mycroft dip->mixer_class = ESS_INPUT_CLASS;
2127 1.34 mycroft dip->prev = ESS_MIC_PLAY_VOL;
2128 1.34 mycroft dip->next = AUDIO_MIXER_LAST;
2129 1.34 mycroft strcpy(dip->label.name, AudioNpreamp);
2130 1.34 mycroft dip->type = AUDIO_MIXER_ENUM;
2131 1.34 mycroft dip->un.e.num_mem = 2;
2132 1.34 mycroft strcpy(dip->un.e.member[0].label.name, AudioNoff);
2133 1.34 mycroft dip->un.e.member[0].ord = 0;
2134 1.34 mycroft strcpy(dip->un.e.member[1].label.name, AudioNon);
2135 1.34 mycroft dip->un.e.member[1].ord = 1;
2136 1.66 kent return 0;
2137 1.34 mycroft }
2138 1.34 mycroft
2139 1.66 kent return ENXIO;
2140 1.4 augustss }
2141 1.4 augustss
2142 1.4 augustss void *
2143 1.79 jmcneill ess_malloc(void *addr, int direction, size_t size)
2144 1.4 augustss {
2145 1.66 kent struct ess_softc *sc;
2146 1.30 mycroft int drq;
2147 1.4 augustss
2148 1.66 kent sc = addr;
2149 1.46 augustss if ((!ESS_USE_AUDIO1(sc->sc_model)) && direction == AUMODE_PLAY)
2150 1.34 mycroft drq = sc->sc_audio2.drq;
2151 1.30 mycroft else
2152 1.34 mycroft drq = sc->sc_audio1.drq;
2153 1.79 jmcneill return (isa_malloc(sc->sc_ic, drq, size, M_DEVBUF, M_WAITOK));
2154 1.4 augustss }
2155 1.4 augustss
2156 1.4 augustss void
2157 1.79 jmcneill ess_free(void *addr, void *ptr, size_t size)
2158 1.4 augustss {
2159 1.66 kent
2160 1.79 jmcneill isa_free(ptr, M_DEVBUF);
2161 1.4 augustss }
2162 1.4 augustss
2163 1.30 mycroft size_t
2164 1.66 kent ess_round_buffersize(void *addr, int direction, size_t size)
2165 1.4 augustss {
2166 1.66 kent struct ess_softc *sc;
2167 1.50 thorpej bus_size_t maxsize;
2168 1.50 thorpej
2169 1.66 kent sc = addr;
2170 1.50 thorpej if ((!ESS_USE_AUDIO1(sc->sc_model)) && direction == AUMODE_PLAY)
2171 1.50 thorpej maxsize = sc->sc_audio2.maxsize;
2172 1.50 thorpej else
2173 1.50 thorpej maxsize = sc->sc_audio1.maxsize;
2174 1.50 thorpej
2175 1.50 thorpej if (size > maxsize)
2176 1.50 thorpej size = maxsize;
2177 1.66 kent return size;
2178 1.4 augustss }
2179 1.4 augustss
2180 1.1 augustss int
2181 1.73 christos ess_1788_get_props(void *addr)
2182 1.36 mycroft {
2183 1.36 mycroft
2184 1.86 isaki return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE;
2185 1.36 mycroft }
2186 1.36 mycroft
2187 1.36 mycroft int
2188 1.73 christos ess_1888_get_props(void *addr)
2189 1.1 augustss {
2190 1.14 mycroft
2191 1.86 isaki return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE |
2192 1.86 isaki AUDIO_PROP_FULLDUPLEX;
2193 1.1 augustss }
2194 1.1 augustss
2195 1.79 jmcneill void
2196 1.79 jmcneill ess_get_locks(void *addr, kmutex_t **intr, kmutex_t **thread)
2197 1.79 jmcneill {
2198 1.79 jmcneill struct ess_softc *sc;
2199 1.79 jmcneill
2200 1.79 jmcneill sc = addr;
2201 1.79 jmcneill *intr = &sc->sc_intr_lock;
2202 1.79 jmcneill *thread = &sc->sc_lock;
2203 1.79 jmcneill }
2204 1.79 jmcneill
2205 1.79 jmcneill
2206 1.1 augustss /* ============================================
2207 1.1 augustss * Generic functions for ess, not used by audio h/w i/f
2208 1.1 augustss * =============================================
2209 1.1 augustss */
2210 1.1 augustss
2211 1.1 augustss /*
2212 1.1 augustss * Reset the chip.
2213 1.1 augustss * Return non-zero if the chip isn't detected.
2214 1.1 augustss */
2215 1.1 augustss int
2216 1.66 kent ess_reset(struct ess_softc *sc)
2217 1.1 augustss {
2218 1.66 kent bus_space_tag_t iot;
2219 1.66 kent bus_space_handle_t ioh;
2220 1.1 augustss
2221 1.66 kent iot = sc->sc_iot;
2222 1.66 kent ioh = sc->sc_ioh;
2223 1.40 mycroft sc->sc_audio1.active = 0;
2224 1.40 mycroft sc->sc_audio2.active = 0;
2225 1.1 augustss
2226 1.4 augustss EWRITE1(iot, ioh, ESS_DSP_RESET, ESS_RESET_EXT);
2227 1.48 augustss delay(10000); /* XXX shouldn't delay so long */
2228 1.2 augustss EWRITE1(iot, ioh, ESS_DSP_RESET, 0);
2229 1.1 augustss if (ess_rdsp(sc) != ESS_MAGIC)
2230 1.66 kent return 1;
2231 1.1 augustss
2232 1.4 augustss /* Enable access to the ESS extension commands. */
2233 1.1 augustss ess_wdsp(sc, ESS_ACMD_ENABLE_EXT);
2234 1.1 augustss
2235 1.66 kent return 0;
2236 1.1 augustss }
2237 1.1 augustss
2238 1.1 augustss void
2239 1.66 kent ess_set_gain(struct ess_softc *sc, int port, int on)
2240 1.1 augustss {
2241 1.1 augustss int gain, left, right;
2242 1.1 augustss int mix;
2243 1.1 augustss int src;
2244 1.1 augustss int stereo;
2245 1.1 augustss
2246 1.1 augustss /*
2247 1.1 augustss * Most gain controls are found in the mixer registers and
2248 1.1 augustss * are stereo. Any that are not, must set mix and stereo as
2249 1.1 augustss * required.
2250 1.1 augustss */
2251 1.1 augustss mix = 1;
2252 1.1 augustss stereo = 1;
2253 1.1 augustss
2254 1.82 nakayama if (ESS_IS_ES18X9(sc->sc_model)) {
2255 1.82 nakayama switch (port) {
2256 1.82 nakayama case ESS_SPATIALIZER:
2257 1.82 nakayama src = ESS_MREG_SPATIAL_LEVEL;
2258 1.82 nakayama stereo = -1;
2259 1.82 nakayama goto skip;
2260 1.82 nakayama case ESS_SPATIALIZER_ENABLE:
2261 1.82 nakayama return;
2262 1.82 nakayama }
2263 1.82 nakayama }
2264 1.1 augustss switch (port) {
2265 1.1 augustss case ESS_MASTER_VOL:
2266 1.33 nathanw src = ESS_MREG_VOLUME_MASTER;
2267 1.1 augustss break;
2268 1.1 augustss case ESS_DAC_PLAY_VOL:
2269 1.46 augustss if (ESS_USE_AUDIO1(sc->sc_model))
2270 1.33 nathanw src = ESS_MREG_VOLUME_VOICE;
2271 1.33 nathanw else
2272 1.33 nathanw src = 0x7C;
2273 1.1 augustss break;
2274 1.1 augustss case ESS_MIC_PLAY_VOL:
2275 1.33 nathanw src = ESS_MREG_VOLUME_MIC;
2276 1.1 augustss break;
2277 1.1 augustss case ESS_LINE_PLAY_VOL:
2278 1.33 nathanw src = ESS_MREG_VOLUME_LINE;
2279 1.1 augustss break;
2280 1.1 augustss case ESS_SYNTH_PLAY_VOL:
2281 1.33 nathanw src = ESS_MREG_VOLUME_SYNTH;
2282 1.1 augustss break;
2283 1.1 augustss case ESS_CD_PLAY_VOL:
2284 1.33 nathanw src = ESS_MREG_VOLUME_CD;
2285 1.1 augustss break;
2286 1.1 augustss case ESS_AUXB_PLAY_VOL:
2287 1.33 nathanw src = ESS_MREG_VOLUME_AUXB;
2288 1.1 augustss break;
2289 1.1 augustss case ESS_PCSPEAKER_VOL:
2290 1.33 nathanw src = ESS_MREG_VOLUME_PCSPKR;
2291 1.1 augustss stereo = 0;
2292 1.1 augustss break;
2293 1.1 augustss case ESS_DAC_REC_VOL:
2294 1.1 augustss src = 0x69;
2295 1.1 augustss break;
2296 1.1 augustss case ESS_MIC_REC_VOL:
2297 1.1 augustss src = 0x68;
2298 1.1 augustss break;
2299 1.1 augustss case ESS_LINE_REC_VOL:
2300 1.1 augustss src = 0x6E;
2301 1.1 augustss break;
2302 1.1 augustss case ESS_SYNTH_REC_VOL:
2303 1.1 augustss src = 0x6B;
2304 1.1 augustss break;
2305 1.1 augustss case ESS_CD_REC_VOL:
2306 1.1 augustss src = 0x6A;
2307 1.1 augustss break;
2308 1.1 augustss case ESS_AUXB_REC_VOL:
2309 1.1 augustss src = 0x6C;
2310 1.1 augustss break;
2311 1.1 augustss case ESS_RECORD_VOL:
2312 1.33 nathanw src = ESS_XCMD_VOLIN_CTRL;
2313 1.1 augustss mix = 0;
2314 1.1 augustss break;
2315 1.1 augustss default:
2316 1.1 augustss return;
2317 1.1 augustss }
2318 1.82 nakayama skip:
2319 1.1 augustss
2320 1.33 nathanw /* 1788 doesn't have a separate recording mixer */
2321 1.46 augustss if (ESS_USE_AUDIO1(sc->sc_model) && mix && src > 0x62)
2322 1.34 mycroft return;
2323 1.33 nathanw
2324 1.1 augustss if (on) {
2325 1.1 augustss left = sc->gain[port][ESS_LEFT];
2326 1.1 augustss right = sc->gain[port][ESS_RIGHT];
2327 1.1 augustss } else {
2328 1.1 augustss left = right = 0;
2329 1.1 augustss }
2330 1.1 augustss
2331 1.82 nakayama if (stereo == -1)
2332 1.82 nakayama gain = ESS_SPATIAL_GAIN(left);
2333 1.82 nakayama else if (stereo)
2334 1.1 augustss gain = ESS_STEREO_GAIN(left, right);
2335 1.1 augustss else
2336 1.1 augustss gain = ESS_MONO_GAIN(left);
2337 1.1 augustss
2338 1.1 augustss if (mix)
2339 1.1 augustss ess_write_mix_reg(sc, src, gain);
2340 1.1 augustss else
2341 1.1 augustss ess_write_x_reg(sc, src, gain);
2342 1.1 augustss }
2343 1.1 augustss
2344 1.33 nathanw /* Set the input device on devices without an input mixer. */
2345 1.33 nathanw int
2346 1.66 kent ess_set_in_port(struct ess_softc *sc, int ord)
2347 1.33 nathanw {
2348 1.33 nathanw mixer_devinfo_t di;
2349 1.34 mycroft int i;
2350 1.33 nathanw
2351 1.33 nathanw DPRINTF(("ess_set_in_port: ord=0x%x\n", ord));
2352 1.33 nathanw
2353 1.33 nathanw /*
2354 1.33 nathanw * Get the device info for the record source control,
2355 1.33 nathanw * including the list of available sources.
2356 1.33 nathanw */
2357 1.33 nathanw di.index = ESS_RECORD_SOURCE;
2358 1.33 nathanw if (ess_query_devinfo(sc, &di))
2359 1.33 nathanw return EINVAL;
2360 1.33 nathanw
2361 1.34 mycroft /* See if the given ord value was anywhere in the list. */
2362 1.33 nathanw for (i = 0; i < di.un.e.num_mem; i++) {
2363 1.34 mycroft if (ord == di.un.e.member[i].ord)
2364 1.33 nathanw break;
2365 1.33 nathanw }
2366 1.34 mycroft if (i == di.un.e.num_mem)
2367 1.34 mycroft return EINVAL;
2368 1.33 nathanw
2369 1.34 mycroft ess_write_mix_reg(sc, ESS_MREG_ADC_SOURCE, ord);
2370 1.33 nathanw
2371 1.34 mycroft sc->in_port = ord;
2372 1.66 kent return 0;
2373 1.33 nathanw }
2374 1.33 nathanw
2375 1.33 nathanw /* Set the input device levels on input-mixer-enabled devices. */
2376 1.1 augustss int
2377 1.66 kent ess_set_in_ports(struct ess_softc *sc, int mask)
2378 1.1 augustss {
2379 1.1 augustss mixer_devinfo_t di;
2380 1.34 mycroft int i, port;
2381 1.1 augustss
2382 1.1 augustss DPRINTF(("ess_set_in_ports: mask=0x%x\n", mask));
2383 1.1 augustss
2384 1.1 augustss /*
2385 1.1 augustss * Get the device info for the record source control,
2386 1.1 augustss * including the list of available sources.
2387 1.1 augustss */
2388 1.1 augustss di.index = ESS_RECORD_SOURCE;
2389 1.1 augustss if (ess_query_devinfo(sc, &di))
2390 1.1 augustss return EINVAL;
2391 1.1 augustss
2392 1.1 augustss /*
2393 1.1 augustss * Set or disable the record volume control for each of the
2394 1.1 augustss * possible sources.
2395 1.1 augustss */
2396 1.33 nathanw for (i = 0; i < di.un.s.num_mem; i++) {
2397 1.1 augustss /*
2398 1.1 augustss * Calculate the source port number from its mask.
2399 1.1 augustss */
2400 1.34 mycroft port = ffs(di.un.s.member[i].mask);
2401 1.1 augustss
2402 1.1 augustss /*
2403 1.1 augustss * Set the source gain:
2404 1.1 augustss * to the current value if source is enabled
2405 1.1 augustss * to zero if source is disabled
2406 1.1 augustss */
2407 1.1 augustss ess_set_gain(sc, port, mask & di.un.s.member[i].mask);
2408 1.1 augustss }
2409 1.1 augustss
2410 1.1 augustss sc->in_mask = mask;
2411 1.66 kent return 0;
2412 1.1 augustss }
2413 1.1 augustss
2414 1.1 augustss void
2415 1.66 kent ess_speaker_on(struct ess_softc *sc)
2416 1.1 augustss {
2417 1.66 kent
2418 1.49 mycroft /* Unmute the DAC. */
2419 1.49 mycroft ess_set_gain(sc, ESS_DAC_PLAY_VOL, 1);
2420 1.1 augustss }
2421 1.1 augustss
2422 1.1 augustss void
2423 1.66 kent ess_speaker_off(struct ess_softc *sc)
2424 1.1 augustss {
2425 1.66 kent
2426 1.49 mycroft /* Mute the DAC. */
2427 1.49 mycroft ess_set_gain(sc, ESS_DAC_PLAY_VOL, 0);
2428 1.1 augustss }
2429 1.1 augustss
2430 1.1 augustss /*
2431 1.1 augustss * Calculate the time constant for the requested sampling rate.
2432 1.1 augustss */
2433 1.1 augustss u_int
2434 1.82 nakayama ess_srtotc(struct ess_softc *sc, u_int rate)
2435 1.1 augustss {
2436 1.1 augustss u_int tc;
2437 1.1 augustss
2438 1.1 augustss /* The following formulae are from the ESS data sheet. */
2439 1.82 nakayama if (ESS_IS_ES18X9(sc->sc_model)) {
2440 1.82 nakayama if ((rate % 8000) != 0)
2441 1.82 nakayama tc = 128 - 793800L / rate;
2442 1.82 nakayama else
2443 1.82 nakayama tc = 256 - 768000L / rate;
2444 1.82 nakayama } else {
2445 1.82 nakayama if (rate <= 22050)
2446 1.82 nakayama tc = 128 - 397700L / rate;
2447 1.82 nakayama else
2448 1.82 nakayama tc = 256 - 795500L / rate;
2449 1.82 nakayama }
2450 1.1 augustss
2451 1.66 kent return tc;
2452 1.1 augustss }
2453 1.1 augustss
2454 1.1 augustss
2455 1.1 augustss /*
2456 1.1 augustss * Calculate the filter constant for the reuqested sampling rate.
2457 1.1 augustss */
2458 1.1 augustss u_int
2459 1.66 kent ess_srtofc(u_int rate)
2460 1.1 augustss {
2461 1.1 augustss /*
2462 1.1 augustss * The following formula is derived from the information in
2463 1.1 augustss * the ES1887 data sheet, based on a roll-off frequency of
2464 1.1 augustss * 87%.
2465 1.1 augustss */
2466 1.66 kent return 256 - 200279L / rate;
2467 1.1 augustss }
2468 1.1 augustss
2469 1.1 augustss
2470 1.1 augustss /*
2471 1.1 augustss * Return the status of the DSP.
2472 1.1 augustss */
2473 1.1 augustss u_char
2474 1.66 kent ess_get_dsp_status(struct ess_softc *sc)
2475 1.1 augustss {
2476 1.66 kent return EREAD1(sc->sc_iot, sc->sc_ioh, ESS_DSP_RW_STATUS);
2477 1.1 augustss }
2478 1.1 augustss
2479 1.1 augustss
2480 1.1 augustss /*
2481 1.1 augustss * Return the read status of the DSP: 1 -> DSP ready for reading
2482 1.1 augustss * 0 -> DSP not ready for reading
2483 1.1 augustss */
2484 1.1 augustss u_char
2485 1.66 kent ess_dsp_read_ready(struct ess_softc *sc)
2486 1.1 augustss {
2487 1.66 kent
2488 1.66 kent return (ess_get_dsp_status(sc) & ESS_DSP_READ_READY) ? 1 : 0;
2489 1.1 augustss }
2490 1.1 augustss
2491 1.1 augustss
2492 1.1 augustss /*
2493 1.1 augustss * Return the write status of the DSP: 1 -> DSP ready for writing
2494 1.1 augustss * 0 -> DSP not ready for writing
2495 1.1 augustss */
2496 1.1 augustss u_char
2497 1.66 kent ess_dsp_write_ready(struct ess_softc *sc)
2498 1.1 augustss {
2499 1.66 kent return (ess_get_dsp_status(sc) & ESS_DSP_WRITE_BUSY) ? 0 : 1;
2500 1.1 augustss }
2501 1.1 augustss
2502 1.1 augustss
2503 1.1 augustss /*
2504 1.1 augustss * Read a byte from the DSP.
2505 1.1 augustss */
2506 1.1 augustss int
2507 1.66 kent ess_rdsp(struct ess_softc *sc)
2508 1.1 augustss {
2509 1.66 kent bus_space_tag_t iot;
2510 1.66 kent bus_space_handle_t ioh;
2511 1.1 augustss int i;
2512 1.1 augustss
2513 1.66 kent iot = sc->sc_iot;
2514 1.66 kent ioh = sc->sc_ioh;
2515 1.1 augustss for (i = ESS_READ_TIMEOUT; i > 0; --i) {
2516 1.1 augustss if (ess_dsp_read_ready(sc)) {
2517 1.2 augustss i = EREAD1(iot, ioh, ESS_DSP_READ);
2518 1.2 augustss DPRINTFN(8,("ess_rdsp() = 0x%02x\n", i));
2519 1.1 augustss return i;
2520 1.1 augustss } else
2521 1.1 augustss delay(10);
2522 1.1 augustss }
2523 1.1 augustss
2524 1.1 augustss DPRINTF(("ess_rdsp: timed out\n"));
2525 1.66 kent return -1;
2526 1.1 augustss }
2527 1.1 augustss
2528 1.1 augustss /*
2529 1.1 augustss * Write a byte to the DSP.
2530 1.1 augustss */
2531 1.1 augustss int
2532 1.66 kent ess_wdsp(struct ess_softc *sc, u_char v)
2533 1.1 augustss {
2534 1.66 kent bus_space_tag_t iot;
2535 1.66 kent bus_space_handle_t ioh;
2536 1.1 augustss int i;
2537 1.2 augustss
2538 1.2 augustss DPRINTFN(8,("ess_wdsp(0x%02x)\n", v));
2539 1.2 augustss
2540 1.66 kent iot = sc->sc_iot;
2541 1.66 kent ioh = sc->sc_ioh;
2542 1.1 augustss for (i = ESS_WRITE_TIMEOUT; i > 0; --i) {
2543 1.1 augustss if (ess_dsp_write_ready(sc)) {
2544 1.2 augustss EWRITE1(iot, ioh, ESS_DSP_WRITE, v);
2545 1.66 kent return 0;
2546 1.1 augustss } else
2547 1.1 augustss delay(10);
2548 1.1 augustss }
2549 1.1 augustss
2550 1.1 augustss DPRINTF(("ess_wdsp(0x%02x): timed out\n", v));
2551 1.66 kent return -1;
2552 1.1 augustss }
2553 1.1 augustss
2554 1.1 augustss /*
2555 1.1 augustss * Write a value to one of the ESS extended registers.
2556 1.1 augustss */
2557 1.1 augustss int
2558 1.66 kent ess_write_x_reg(struct ess_softc *sc, u_char reg, u_char val)
2559 1.1 augustss {
2560 1.1 augustss int error;
2561 1.1 augustss
2562 1.2 augustss DPRINTFN(2,("ess_write_x_reg: %02x=%02x\n", reg, val));
2563 1.1 augustss if ((error = ess_wdsp(sc, reg)) == 0)
2564 1.1 augustss error = ess_wdsp(sc, val);
2565 1.1 augustss
2566 1.1 augustss return error;
2567 1.1 augustss }
2568 1.1 augustss
2569 1.1 augustss /*
2570 1.1 augustss * Read the value of one of the ESS extended registers.
2571 1.1 augustss */
2572 1.1 augustss u_char
2573 1.66 kent ess_read_x_reg(struct ess_softc *sc, u_char reg)
2574 1.1 augustss {
2575 1.1 augustss int error;
2576 1.2 augustss int val;
2577 1.1 augustss
2578 1.1 augustss if ((error = ess_wdsp(sc, 0xC0)) == 0)
2579 1.1 augustss error = ess_wdsp(sc, reg);
2580 1.71 christos if (error) {
2581 1.1 augustss DPRINTF(("Error reading extended register 0x%02x\n", reg));
2582 1.71 christos }
2583 1.1 augustss /* REVISIT: what if an error is returned above? */
2584 1.2 augustss val = ess_rdsp(sc);
2585 1.33 nathanw DPRINTFN(2,("ess_read_x_reg: %02x=%02x\n", reg, val));
2586 1.2 augustss return val;
2587 1.1 augustss }
2588 1.1 augustss
2589 1.1 augustss void
2590 1.66 kent ess_clear_xreg_bits(struct ess_softc *sc, u_char reg, u_char mask)
2591 1.1 augustss {
2592 1.71 christos if (ess_write_x_reg(sc, reg, ess_read_x_reg(sc, reg) & ~mask) == -1) {
2593 1.1 augustss DPRINTF(("Error clearing bits in extended register 0x%02x\n",
2594 1.1 augustss reg));
2595 1.71 christos }
2596 1.1 augustss }
2597 1.1 augustss
2598 1.1 augustss void
2599 1.66 kent ess_set_xreg_bits(struct ess_softc *sc, u_char reg, u_char mask)
2600 1.1 augustss {
2601 1.71 christos if (ess_write_x_reg(sc, reg, ess_read_x_reg(sc, reg) | mask) == -1) {
2602 1.1 augustss DPRINTF(("Error setting bits in extended register 0x%02x\n",
2603 1.1 augustss reg));
2604 1.71 christos }
2605 1.1 augustss }
2606 1.1 augustss
2607 1.1 augustss
2608 1.1 augustss /*
2609 1.1 augustss * Write a value to one of the ESS mixer registers.
2610 1.1 augustss */
2611 1.1 augustss void
2612 1.66 kent ess_write_mix_reg(struct ess_softc *sc, u_char reg, u_char val)
2613 1.1 augustss {
2614 1.66 kent bus_space_tag_t iot;
2615 1.66 kent bus_space_handle_t ioh;
2616 1.1 augustss
2617 1.2 augustss DPRINTFN(2,("ess_write_mix_reg: %x=%x\n", reg, val));
2618 1.4 augustss
2619 1.66 kent iot = sc->sc_iot;
2620 1.66 kent ioh = sc->sc_ioh;
2621 1.2 augustss EWRITE1(iot, ioh, ESS_MIX_REG_SELECT, reg);
2622 1.2 augustss EWRITE1(iot, ioh, ESS_MIX_REG_DATA, val);
2623 1.1 augustss }
2624 1.1 augustss
2625 1.1 augustss /*
2626 1.1 augustss * Read the value of one of the ESS mixer registers.
2627 1.1 augustss */
2628 1.1 augustss u_char
2629 1.66 kent ess_read_mix_reg(struct ess_softc *sc, u_char reg)
2630 1.1 augustss {
2631 1.66 kent bus_space_tag_t iot;
2632 1.66 kent bus_space_handle_t ioh;
2633 1.1 augustss u_char val;
2634 1.1 augustss
2635 1.66 kent iot = sc->sc_iot;
2636 1.66 kent ioh = sc->sc_ioh;
2637 1.2 augustss EWRITE1(iot, ioh, ESS_MIX_REG_SELECT, reg);
2638 1.2 augustss val = EREAD1(iot, ioh, ESS_MIX_REG_DATA);
2639 1.1 augustss
2640 1.2 augustss DPRINTFN(2,("ess_read_mix_reg: %x=%x\n", reg, val));
2641 1.1 augustss return val;
2642 1.1 augustss }
2643 1.1 augustss
2644 1.1 augustss void
2645 1.66 kent ess_clear_mreg_bits(struct ess_softc *sc, u_char reg, u_char mask)
2646 1.1 augustss {
2647 1.66 kent
2648 1.1 augustss ess_write_mix_reg(sc, reg, ess_read_mix_reg(sc, reg) & ~mask);
2649 1.1 augustss }
2650 1.1 augustss
2651 1.1 augustss void
2652 1.66 kent ess_set_mreg_bits(struct ess_softc *sc, u_char reg, u_char mask)
2653 1.1 augustss {
2654 1.66 kent
2655 1.1 augustss ess_write_mix_reg(sc, reg, ess_read_mix_reg(sc, reg) | mask);
2656 1.46 augustss }
2657 1.46 augustss
2658 1.46 augustss void
2659 1.66 kent ess_read_multi_mix_reg(struct ess_softc *sc, u_char reg,
2660 1.66 kent uint8_t *datap, bus_size_t count)
2661 1.46 augustss {
2662 1.66 kent bus_space_tag_t iot;
2663 1.66 kent bus_space_handle_t ioh;
2664 1.46 augustss
2665 1.66 kent iot = sc->sc_iot;
2666 1.66 kent ioh = sc->sc_ioh;
2667 1.46 augustss EWRITE1(iot, ioh, ESS_MIX_REG_SELECT, reg);
2668 1.46 augustss bus_space_read_multi_1(iot, ioh, ESS_MIX_REG_DATA, datap, count);
2669 1.1 augustss }
2670