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