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