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