Annotation of sys/arch/sgi/dev/mavb.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: mavb.c,v 1.7 2007/05/20 14:17:05 miod Exp $ */
2:
3: /*
4: * Copyright (c) 2005 Mark Kettenis
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/param.h>
20: #include <sys/systm.h>
21: #include <sys/device.h>
22: #include <sys/kernel.h>
23: #include <sys/timeout.h>
24:
25: #include <machine/bus.h>
26: #include <machine/intr.h>
27: #include <machine/autoconf.h>
28:
29: #include <sys/audioio.h>
30: #include <dev/audio_if.h>
31:
32: #include <mips64/archtype.h>
33:
34: #include <sgi/localbus/macebus.h>
35: #include <sgi/dev/mavbreg.h>
36:
37: #include <dev/ic/ad1843reg.h>
38:
39: #undef MAVB_DEBUG
40:
41: #ifdef MAVB_DEBUG
42: #define DPRINTF(l,x) do { if (mavb_debug & (l)) printf x; } while (0)
43: #define MAVB_DEBUG_INTR 0x0100
44: int mavb_debug = ~MAVB_DEBUG_INTR;
45: #else
46: #define DPRINTF(l,x) /* nothing */
47: #endif
48:
49: /* Repeat delays for volume buttons. */
50: #define MAVB_VOLUME_BUTTON_REPEAT_DEL1 400 /* 400ms to start repeating */
51: #define MAVB_VOLUME_BUTTON_REPEAT_DELN 100 /* 100ms between repeats */
52:
53: /* XXX We need access to some of the MACE ISA registers. */
54: #define MAVB_ISA_NREGS 0x20
55:
56: /*
57: * AD1843 Mixer.
58: */
59:
60: enum {
61: AD1843_RECORD_CLASS,
62: AD1843_ADC_SOURCE, /* ADC Source Select */
63: AD1843_ADC_GAIN, /* ADC Input Gain */
64:
65: AD1843_INPUT_CLASS,
66: AD1843_DAC1_GAIN, /* DAC1 Analog/Digital Gain/Attenuation */
67: AD1843_DAC1_MUTE, /* DAC1 Analog Mute */
68: AD1843_DAC2_GAIN, /* DAC2 Mix Gain */
69: AD1843_AUX1_GAIN, /* Auxilliary 1 Mix Gain */
70: AD1843_AUX2_GAIN, /* Auxilliary 2 Mix Gain */
71: AD1843_AUX3_GAIN, /* Auxilliary 3 Mix Gain */
72: AD1843_MIC_GAIN, /* Microphone Mix Gain */
73: AD1843_MONO_GAIN, /* Mono Mix Gain */
74: AD1843_DAC2_MUTE, /* DAC2 Mix Mute */
75: AD1843_AUX1_MUTE, /* Auxilliary 1 Mix Mute */
76: AD1843_AUX2_MUTE, /* Auxilliary 2 Mix Mute */
77: AD1843_AUX3_MUTE, /* Auxilliary 3 Mix Mute */
78: AD1843_MIC_MUTE, /* Microphone Mix Mute */
79: AD1843_MONO_MUTE, /* Mono Mix Mute */
80: AD1843_SUM_MUTE, /* Sum Mute */
81:
82: AD1843_OUTPUT_CLASS,
83: AD1843_MNO_MUTE, /* Mono Output Mute */
84: AD1843_HPO_MUTE /* Headphone Output Mute */
85: };
86:
87: /* ADC Source Select. The order matches the hardware bits. */
88: const char *ad1843_source[] = {
89: AudioNline,
90: AudioNmicrophone,
91: AudioNaux "1",
92: AudioNaux "2",
93: AudioNaux "3",
94: AudioNmono,
95: AudioNdac "1",
96: AudioNdac "2"
97: };
98:
99: /* Mix Control. The order matches the hardware register numbering. */
100: const char *ad1843_input[] = {
101: AudioNdac "2", /* AD1843_DAC2__TO_MIXER */
102: AudioNaux "1",
103: AudioNaux "2",
104: AudioNaux "3",
105: AudioNmicrophone,
106: AudioNmono /* AD1843_MISC_SETTINGS */
107: };
108:
109: struct mavb_softc {
110: struct device sc_dev;
111: bus_space_tag_t sc_st;
112: bus_space_handle_t sc_sh;
113: bus_dma_tag_t sc_dmat;
114: bus_dmamap_t sc_dmamap;
115:
116: /* XXX We need access to some of the MACE ISA registers. */
117: bus_space_handle_t sc_isash;
118:
119: #define MAVB_ISA_RING_SIZE 0x1000
120: caddr_t sc_ring;
121:
122: caddr_t sc_start, sc_end;
123: int sc_blksize;
124: void (*sc_intr)(void *);
125: void *sc_intrarg;
126:
127: caddr_t sc_get;
128: int sc_count;
129:
130: u_long sc_play_rate;
131: u_int sc_play_format;
132:
133: struct timeout sc_volume_button_to;
134: };
135:
136: typedef u_long ad1843_addr_t;
137:
138: u_int16_t ad1843_reg_read(struct mavb_softc *, ad1843_addr_t);
139: u_int16_t ad1843_reg_write(struct mavb_softc *, ad1843_addr_t, u_int16_t);
140: void ad1843_dump_regs(struct mavb_softc *);
141:
142: int mavb_match(struct device *, void *, void *);
143: void mavb_attach(struct device *, struct device *, void *);
144:
145: struct cfattach mavb_ca = {
146: sizeof(struct mavb_softc), mavb_match, mavb_attach
147: };
148:
149: struct cfdriver mavb_cd = {
150: NULL, "mavb", DV_DULL
151: };
152:
153: int mavb_open(void *, int);
154: void mavb_close(void *);
155: int mavb_query_encoding(void *, struct audio_encoding *);
156: int mavb_set_params(void *, int, int, struct audio_params *,
157: struct audio_params *);
158: int mavb_round_blocksize(void *hdl, int bs);
159: int mavb_halt_output(void *);
160: int mavb_halt_input(void *);
161: int mavb_getdev(void *, struct audio_device *);
162: int mavb_set_port(void *, struct mixer_ctrl *);
163: int mavb_get_port(void *, struct mixer_ctrl *);
164: int mavb_query_devinfo(void *, struct mixer_devinfo *);
165: int mavb_get_props(void *);
166: int mavb_trigger_output(void *, void *, void *, int, void (*)(void *),
167: void *, struct audio_params *);
168: int mavb_trigger_input(void *, void *, void *, int, void (*)(void *),
169: void *, struct audio_params *);
170:
171: struct audio_hw_if mavb_sa_hw_if = {
172: mavb_open,
173: mavb_close,
174: 0,
175: mavb_query_encoding,
176: mavb_set_params,
177: mavb_round_blocksize,
178: 0,
179: 0,
180: 0,
181: 0,
182: 0,
183: mavb_halt_output,
184: mavb_halt_input,
185: 0,
186: mavb_getdev,
187: 0,
188: mavb_set_port,
189: mavb_get_port,
190: mavb_query_devinfo,
191: 0,
192: 0,
193: 0,
194: 0,
195: mavb_get_props,
196: mavb_trigger_output,
197: mavb_trigger_input
198: };
199:
200: struct audio_device mavb_device = {
201: "A3",
202: "",
203: "mavb"
204: };
205:
206: int
207: mavb_open(void *hdl, int flags)
208: {
209: return (0);
210: }
211:
212: void
213: mavb_close(void *hdl)
214: {
215: }
216:
217: int
218: mavb_query_encoding(void *hdl, struct audio_encoding *ae)
219: {
220: switch (ae->index) {
221: case 0:
222: /* 8-bit Unsigned Linear PCM. */
223: strlcpy(ae->name, AudioEulinear, sizeof ae->name);
224: ae->encoding = AUDIO_ENCODING_ULINEAR;
225: ae->precision = 8;
226: ae->flags = 0;
227: break;
228: case 1:
229: /* 16-bit Signed Linear PCM. */
230: strlcpy(ae->name, AudioEslinear_be, sizeof ae->name);
231: ae->encoding = AUDIO_ENCODING_SLINEAR_BE;
232: ae->precision = 16;
233: ae->flags = 0;
234: break;
235: case 2:
236: /* 8-bit mu-Law Companded. */
237: strlcpy(ae->name, AudioEmulaw, sizeof ae->name);
238: ae->encoding = AUDIO_ENCODING_ULAW;
239: ae->precision = 8;
240: ae->flags = 0;
241: break;
242: case 3:
243: /* 8-bit A-Law Companded. */
244: strlcpy(ae->name, AudioEalaw, sizeof ae->name);
245: ae->encoding = AUDIO_ENCODING_ALAW;
246: ae->precision = 8;
247: ae->flags = 0;
248: break;
249: default:
250: return (EINVAL);
251: }
252:
253: return (0);
254: }
255:
256: /*
257: * For some reason SGI has decided to standardize their sound hardware
258: * interfaces on 24-bit PCM even though the AD1843 codec used in the
259: * Moosehead A/V Board only supports 16-bit and 8-bit formats.
260: * Therefore we must convert everything to 24-bit samples only to have
261: * the MACE hardware convert them back into 16-bit samples again. To
262: * complicate matters further, the 24-bit samples are embedded 32-bit
263: * integers. The 8-bit and 16-bit samples are first converted into
264: * 24-bit samples by padding them to the right with zeroes. Then they
265: * are sign-extended into 32-bit integers. This conversion is
266: * conveniently done through the software encoding layer of the high
267: * level audio driver by using the functions below. Conversion of
268: * mu-law and A-law formats is done by the hardware.
269: */
270:
271: static void
272: linear16_to_linear24_be(void *hdl, u_char *p, int cc)
273: {
274: u_char *q = p;
275:
276: p += cc;
277: q += cc * 2;
278: while ((cc -= 2) >= 0) {
279: q -= 4;
280: q[3] = 0;
281: q[2] = *--p;
282: q[1] = *--p;
283: q[0] = (*p & 0x80) ? 0xff : 0;
284: }
285: }
286:
287: static void
288: linear24_to_linear16_be(void *hdl, u_char *p, int cc)
289: {
290: u_char *q = p;
291:
292: while ((cc -= 4) >= 0) {
293: *q++ = p[1];
294: *q++ = p[2];
295: p += 4;
296: }
297: }
298:
299: static void
300: ulinear8_to_ulinear24_be(void *hdl, u_char *p, int cc)
301: {
302: u_char *q = p;
303:
304: p += cc;
305: q += cc * 4;
306: while (--cc >= 0) {
307: q -= 4;
308: q[3] = 0;
309: q[2] = 0;
310: q[1] = *--p;
311: q[0] = (*p & 0x80) ? 0xff : 0;
312: }
313: }
314:
315: static void
316: ulinear24_to_ulinear8_be(void *hdl, u_char *p, int cc)
317: {
318: u_char *q = p;
319:
320: while ((cc -= 4) >= 0) {
321: *q++ = p[1];
322: p += 4;
323: }
324: }
325:
326: static void
327: linear16_to_linear24_be_mts(void *hdl, u_char *p, int cc)
328: {
329: u_char *q = p;
330:
331: p += cc;
332: q += cc * 4;
333: while ((cc -= 2) >= 0) {
334: q -= 8;
335: q[3] = q[7] = 0;
336: q[2] = q[6] = *--p;
337: q[1] = q[5] = *--p;
338: q[0] = q[4] = (*p & 0x80) ? 0xff : 0;
339: }
340: }
341:
342: static void
343: ulinear8_to_ulinear24_be_mts(void *hdl, u_char *p, int cc)
344: {
345: u_char *q = p;
346:
347: p += cc;
348: q += cc * 8;
349: while (--cc >= 0) {
350: q -= 8;
351: q[3] = q[7] = 0;
352: q[2] = q[6] = 0;
353: q[1] = q[5] = *--p;
354: q[0] = q[4] = (*p & 0x80) ? 0xff : 0;
355: }
356: }
357:
358: static int
359: mavb_set_play_rate(struct mavb_softc *sc, u_long sample_rate)
360: {
361: if (sample_rate < 4000 || sample_rate > 48000)
362: return (EINVAL);
363:
364: if (sc->sc_play_rate != sample_rate) {
365: ad1843_reg_write(sc, AD1843_CLOCK2_SAMPLE_RATE, sample_rate);
366: sc->sc_play_rate = sample_rate;
367: }
368: return (0);
369: }
370:
371: static int
372: mavb_set_play_format(struct mavb_softc *sc, u_int encoding)
373: {
374: u_int16_t value;
375: u_int format;
376:
377: switch(encoding) {
378: case AUDIO_ENCODING_ULINEAR_BE:
379: format = AD1843_PCM8;
380: break;
381: case AUDIO_ENCODING_SLINEAR_BE:
382: format = AD1843_PCM16;
383: break;
384: case AUDIO_ENCODING_ULAW:
385: format = AD1843_ULAW;
386: break;
387: case AUDIO_ENCODING_ALAW:
388: format = AD1843_ALAW;
389: break;
390: default:
391: return (EINVAL);
392: }
393:
394: if (sc->sc_play_format != format) {
395: value = ad1843_reg_read(sc, AD1843_SERIAL_INTERFACE);
396: value &= ~AD1843_DA1F_MASK;
397: value |= (format << AD1843_DA1F_SHIFT);
398: ad1843_reg_write(sc, AD1843_SERIAL_INTERFACE, value);
399: sc->sc_play_format = format;
400: }
401: return (0);
402: }
403:
404: int
405: mavb_set_params(void *hdl, int setmode, int usemode,
406: struct audio_params *play, struct audio_params *rec)
407: {
408: struct mavb_softc *sc = (struct mavb_softc *)hdl;
409: int error;
410:
411: DPRINTF(1, ("%s: mavb_set_params: sample=%ld precision=%d "
412: "channels=%d\n", sc->sc_dev.dv_xname, play->sample_rate,
413: play->precision, play->channels));
414:
415: if (setmode & AUMODE_PLAY) {
416: switch (play->encoding) {
417: case AUDIO_ENCODING_ULAW:
418: case AUDIO_ENCODING_ALAW:
419: case AUDIO_ENCODING_ULINEAR_BE:
420: if (play->precision != 8)
421: return (EINVAL);
422: switch (play->channels) {
423: case 1:
424: play->factor = 8;
425: play->sw_code = ulinear8_to_ulinear24_be_mts;
426: break;
427: case 2:
428: play->factor = 4;
429: play->sw_code = ulinear8_to_ulinear24_be;
430: break;
431: default:
432: return (EINVAL);
433: }
434: break;
435: case AUDIO_ENCODING_SLINEAR_BE:
436: if (play->precision == 16) {
437: switch (play->channels) {
438: case 1:
439: play->factor = 4;
440: play->sw_code =
441: linear16_to_linear24_be_mts;
442: break;
443: case 2:
444: play->factor = 2;
445: play->sw_code =
446: linear16_to_linear24_be;
447: break;
448: default:
449: return (EINVAL);
450: }
451: } else {
452: return (EINVAL);
453: }
454: break;
455: default:
456: return (EINVAL);
457: }
458:
459: error = mavb_set_play_rate(sc, play->sample_rate);
460: if (error)
461: return (error);
462:
463: error = mavb_set_play_format(sc, play->encoding);
464: if (error)
465: return (error);
466: }
467:
468: if (setmode & AUMODE_RECORD) {
469: switch (rec->encoding) {
470: case AUDIO_ENCODING_ULAW:
471: case AUDIO_ENCODING_ALAW:
472: case AUDIO_ENCODING_ULINEAR_BE:
473: if (rec->precision != 8)
474: return (EINVAL);
475: rec->factor = 4;
476: rec->sw_code = ulinear24_to_ulinear8_be;
477: break;
478: case AUDIO_ENCODING_SLINEAR_BE:
479: if (rec->precision == 16) {
480: rec->factor = 2;
481: rec->sw_code = linear24_to_linear16_be;
482: } else {
483: return (EINVAL);
484: }
485: break;
486: default:
487: return (EINVAL);
488: }
489: }
490:
491: return (0);
492: }
493:
494: int
495: mavb_round_blocksize(void *hdl, int bs)
496: {
497: /* Block size should be a multiple of 32. */
498: return (bs + 0x1f) & ~0x1f;
499: }
500:
501: int
502: mavb_halt_output(void *hdl)
503: {
504: struct mavb_softc *sc = (struct mavb_softc *)hdl;
505:
506: DPRINTF(1, ("%s: mavb_halt_output called\n", sc->sc_dev.dv_xname));
507:
508: bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0);
509: return (0);
510: }
511:
512: int
513: mavb_halt_input(void *hdl)
514: {
515: return (0);
516: }
517:
518: int
519: mavb_getdev(void *hdl, struct audio_device *ret)
520: {
521: *ret = mavb_device;
522: return (0);
523: }
524:
525: int
526: mavb_set_port(void *hdl, struct mixer_ctrl *mc)
527: {
528: struct mavb_softc *sc = (struct mavb_softc *)hdl;
529: u_char left, right;
530: ad1843_addr_t reg;
531: u_int16_t value;
532:
533: DPRINTF(1, ("%s: mavb_set_port: dev=%d\n", sc->sc_dev.dv_xname,
534: mc->dev));
535:
536: switch (mc->dev) {
537: case AD1843_ADC_SOURCE:
538: value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
539: value &= ~(AD1843_LSS_MASK | AD1843_RSS_MASK);
540: value |= ((mc->un.ord << AD1843_LSS_SHIFT) & AD1843_LSS_MASK);
541: value |= ((mc->un.ord << AD1843_RSS_SHIFT) & AD1843_RSS_MASK);
542: ad1843_reg_write(sc, AD1843_ADC_SOURCE_GAIN, value);
543: break;
544: case AD1843_ADC_GAIN:
545: left = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
546: right = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
547: value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
548: value &= ~(AD1843_LIG_MASK | AD1843_RIG_MASK);
549: value |= ((left >> 4) << AD1843_LIG_SHIFT);
550: value |= ((right >> 4) << AD1843_RIG_SHIFT);
551: ad1843_reg_write(sc, AD1843_ADC_SOURCE_GAIN, value);
552: break;
553:
554: case AD1843_DAC1_GAIN:
555: left = AUDIO_MAX_GAIN -
556: mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
557: right = AUDIO_MAX_GAIN -
558: mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
559: value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
560: value &= ~(AD1843_LDA1G_MASK | AD1843_RDA1G_MASK);
561: value |= ((left >> 2) << AD1843_LDA1G_SHIFT);
562: value |= ((right >> 2) << AD1843_RDA1G_SHIFT);
563: ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value);
564: break;
565: case AD1843_DAC1_MUTE:
566: value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
567: if (mc->un.ord == 0)
568: value &= ~(AD1843_LDA1GM | AD1843_RDA1GM);
569: else
570: value |= (AD1843_LDA1GM | AD1843_RDA1GM);
571: ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value);
572: break;
573:
574: case AD1843_DAC2_GAIN:
575: case AD1843_AUX1_GAIN:
576: case AD1843_AUX2_GAIN:
577: case AD1843_AUX3_GAIN:
578: case AD1843_MIC_GAIN:
579: left = AUDIO_MAX_GAIN -
580: mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
581: right = AUDIO_MAX_GAIN -
582: mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
583: reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_GAIN;
584: value = ad1843_reg_read(sc, reg);
585: value &= ~(AD1843_LD2M_MASK | AD1843_RD2M_MASK);
586: value |= ((left >> 3) << AD1843_LD2M_SHIFT);
587: value |= ((right >> 3) << AD1843_RD2M_SHIFT);
588: ad1843_reg_write(sc, reg, value);
589: break;
590: case AD1843_MONO_GAIN:
591: left = AUDIO_MAX_GAIN -
592: mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
593: value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
594: value &= ~AD1843_MNM_MASK;
595: value |= ((left >> 3) << AD1843_MNM_SHIFT);
596: ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
597: break;
598: case AD1843_DAC2_MUTE:
599: case AD1843_AUX1_MUTE:
600: case AD1843_AUX2_MUTE:
601: case AD1843_AUX3_MUTE:
602: case AD1843_MIC_MUTE:
603: case AD1843_MONO_MUTE: /* matches left channel */
604: reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_MUTE;
605: value = ad1843_reg_read(sc, reg);
606: if (mc->un.ord == 0)
607: value &= ~(AD1843_LD2MM | AD1843_RD2MM);
608: else
609: value |= (AD1843_LD2MM | AD1843_RD2MM);
610: ad1843_reg_write(sc, reg, value);
611: break;
612:
613: case AD1843_SUM_MUTE:
614: value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
615: if (mc->un.ord == 0)
616: value &= ~AD1843_SUMM;
617: else
618: value |= AD1843_SUMM;
619: ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
620: break;
621:
622: case AD1843_MNO_MUTE:
623: value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
624: if (mc->un.ord == 0)
625: value &= ~AD1843_MNOM;
626: else
627: value |= AD1843_MNOM;
628: ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
629: break;
630:
631: case AD1843_HPO_MUTE:
632: value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
633: if (mc->un.ord == 0)
634: value &= ~AD1843_HPOM;
635: else
636: value |= AD1843_HPOM;
637: ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
638: value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
639: break;
640:
641: default:
642: return (EINVAL);
643: }
644:
645: return (0);
646: }
647:
648: int
649: mavb_get_port(void *hdl, struct mixer_ctrl *mc)
650: {
651: struct mavb_softc *sc = (struct mavb_softc *)hdl;
652: u_char left, right;
653: ad1843_addr_t reg;
654: u_int16_t value;
655:
656: DPRINTF(1, ("%s: mavb_get_port: dev=%d\n", sc->sc_dev.dv_xname,
657: mc->dev));
658:
659: switch (mc->dev) {
660: case AD1843_ADC_SOURCE:
661: value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
662: mc->un.ord = (value & AD1843_LSS_MASK) >> AD1843_LSS_SHIFT;
663: break;
664: case AD1843_ADC_GAIN:
665: value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
666: left = (value & AD1843_LIG_MASK) >> AD1843_LIG_SHIFT;
667: right = (value & AD1843_RIG_MASK) >> AD1843_RIG_SHIFT;
668: mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
669: (left << 4) | left;
670: mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
671: (right << 2) | right;
672: break;
673:
674: case AD1843_DAC1_GAIN:
675: value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
676: left = (value & AD1843_LDA1G_MASK) >> AD1843_LDA1G_SHIFT;
677: right = (value & AD1843_RDA1G_MASK) >> AD1843_RDA1G_SHIFT;
678: mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
679: AUDIO_MAX_GAIN - (left << 2);
680: mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
681: AUDIO_MAX_GAIN - (right << 2);
682: break;
683: case AD1843_DAC1_MUTE:
684: value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
685: mc->un.ord = (value & AD1843_LDA1GM) ? 1 : 0;
686: break;
687:
688: case AD1843_DAC2_GAIN:
689: case AD1843_AUX1_GAIN:
690: case AD1843_AUX2_GAIN:
691: case AD1843_AUX3_GAIN:
692: case AD1843_MIC_GAIN:
693: reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_GAIN;
694: value = ad1843_reg_read(sc, reg);
695: left = (value & AD1843_LD2M_MASK) >> AD1843_LD2M_SHIFT;
696: right = (value & AD1843_RD2M_MASK) >> AD1843_RD2M_SHIFT;
697: mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
698: AUDIO_MAX_GAIN - (left << 3);
699: mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
700: AUDIO_MAX_GAIN - (right << 3);
701: break;
702: case AD1843_MONO_GAIN:
703: if (mc->un.value.num_channels != 1)
704: return (EINVAL);
705:
706: value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
707: left = (value & AD1843_MNM_MASK) >> AD1843_MNM_SHIFT;
708: mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
709: AUDIO_MAX_GAIN - (left << 3);
710: break;
711: case AD1843_DAC2_MUTE:
712: case AD1843_AUX1_MUTE:
713: case AD1843_AUX2_MUTE:
714: case AD1843_AUX3_MUTE:
715: case AD1843_MIC_MUTE:
716: case AD1843_MONO_MUTE: /* matches left channel */
717: reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_MUTE;
718: value = ad1843_reg_read(sc, reg);
719: mc->un.ord = (value & AD1843_LD2MM) ? 1 : 0;
720: break;
721:
722: case AD1843_SUM_MUTE:
723: value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
724: mc->un.ord = (value & AD1843_SUMM) ? 1 : 0;
725: break;
726:
727: case AD1843_MNO_MUTE:
728: value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
729: mc->un.ord = (value & AD1843_MNOM) ? 1 : 0;
730: break;
731:
732: case AD1843_HPO_MUTE:
733: value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
734: mc->un.ord = (value & AD1843_HPOM) ? 1 : 0;
735: break;
736:
737: default:
738: return (EINVAL);
739: }
740:
741: return (0);
742: }
743:
744: int
745: mavb_query_devinfo(void *hdl, struct mixer_devinfo *di)
746: {
747: int i;
748:
749: di->prev = di->next = AUDIO_MIXER_LAST;
750:
751: switch (di->index) {
752: case AD1843_RECORD_CLASS:
753: di->type = AUDIO_MIXER_CLASS;
754: di->mixer_class = AD1843_RECORD_CLASS;
755: strlcpy(di->label.name, AudioCrecord, sizeof di->label.name);
756: break;
757:
758: case AD1843_ADC_SOURCE:
759: di->type = AUDIO_MIXER_ENUM;
760: di->mixer_class = AD1843_RECORD_CLASS;
761: di->next = AD1843_ADC_GAIN;
762: strlcpy(di->label.name, AudioNsource, sizeof di->label.name);
763: di->un.e.num_mem =
764: sizeof ad1843_source / sizeof ad1843_source[1];
765: for (i = 0; i < di->un.e.num_mem; i++) {
766: strlcpy(di->un.e.member[i].label.name,
767: ad1843_source[i],
768: sizeof di->un.e.member[0].label.name);
769: di->un.e.member[i].ord = i;
770: }
771: break;
772: case AD1843_ADC_GAIN:
773: di->type = AUDIO_MIXER_VALUE;
774: di->mixer_class = AD1843_RECORD_CLASS;
775: di->prev = AD1843_ADC_SOURCE;
776: strlcpy(di->label.name, AudioNvolume, sizeof di->label.name);
777: di->un.v.num_channels = 2;
778: strlcpy(di->un.v.units.name, AudioNvolume,
779: sizeof di->un.v.units.name);
780: break;
781:
782: case AD1843_INPUT_CLASS:
783: di->type = AUDIO_MIXER_CLASS;
784: di->mixer_class = AD1843_INPUT_CLASS;
785: strlcpy(di->label.name, AudioCinputs, sizeof di->label.name);
786: break;
787:
788: case AD1843_DAC1_GAIN:
789: di->type = AUDIO_MIXER_VALUE;
790: di->mixer_class = AD1843_INPUT_CLASS;
791: di->next = AD1843_DAC1_MUTE;
792: strlcpy(di->label.name, AudioNdac "1", sizeof di->label.name);
793: di->un.v.num_channels = 2;
794: strlcpy(di->un.v.units.name, AudioNvolume,
795: sizeof di->un.v.units.name);
796: break;
797: case AD1843_DAC1_MUTE:
798: di->type = AUDIO_MIXER_ENUM;
799: di->mixer_class = AD1843_INPUT_CLASS;
800: di->prev = AD1843_DAC1_GAIN;
801: strlcpy(di->label.name, AudioNmute, sizeof di->label.name);
802: di->un.e.num_mem = 2;
803: strlcpy(di->un.e.member[0].label.name, AudioNoff,
804: sizeof di->un.e.member[0].label.name);
805: di->un.e.member[0].ord = 0;
806: strlcpy(di->un.e.member[1].label.name, AudioNon,
807: sizeof di->un.e.member[1].label.name);
808: di->un.e.member[1].ord = 1;
809: break;
810:
811: case AD1843_DAC2_GAIN:
812: case AD1843_AUX1_GAIN:
813: case AD1843_AUX2_GAIN:
814: case AD1843_AUX3_GAIN:
815: case AD1843_MIC_GAIN:
816: case AD1843_MONO_GAIN:
817: di->type = AUDIO_MIXER_VALUE;
818: di->mixer_class = AD1843_INPUT_CLASS;
819: di->next = di->index + AD1843_DAC2_MUTE - AD1843_DAC2_GAIN;
820: strlcpy(di->label.name,
821: ad1843_input[di->index - AD1843_DAC2_GAIN],
822: sizeof di->label.name);
823: if (di->index == AD1843_MONO_GAIN)
824: di->un.v.num_channels = 1;
825: else
826: di->un.v.num_channels = 2;
827: strlcpy(di->un.v.units.name, AudioNvolume,
828: sizeof di->un.v.units.name);
829: break;
830: case AD1843_DAC2_MUTE:
831: case AD1843_AUX1_MUTE:
832: case AD1843_AUX2_MUTE:
833: case AD1843_AUX3_MUTE:
834: case AD1843_MIC_MUTE:
835: case AD1843_MONO_MUTE:
836: di->type = AUDIO_MIXER_ENUM;
837: di->mixer_class = AD1843_INPUT_CLASS;
838: di->prev = di->index + AD1843_DAC2_GAIN - AD1843_DAC2_MUTE;
839: strlcpy(di->label.name, AudioNmute, sizeof di->label.name);
840: di->un.e.num_mem = 2;
841: strlcpy(di->un.e.member[0].label.name, AudioNoff,
842: sizeof di->un.e.member[0].label.name);
843: di->un.e.member[0].ord = 0;
844: strlcpy(di->un.e.member[1].label.name, AudioNon,
845: sizeof di->un.e.member[1].label.name);
846: di->un.e.member[1].ord = 1;
847: break;
848:
849: case AD1843_SUM_MUTE:
850: di->type = AUDIO_MIXER_ENUM;
851: di->mixer_class = AD1843_INPUT_CLASS;
852: strlcpy(di->label.name, "sum." AudioNmute,
853: sizeof di->label.name);
854: di->un.e.num_mem = 2;
855: strlcpy(di->un.e.member[0].label.name, AudioNoff,
856: sizeof di->un.e.member[0].label.name);
857: di->un.e.member[0].ord = 0;
858: strlcpy(di->un.e.member[1].label.name, AudioNon,
859: sizeof di->un.e.member[1].label.name);
860: di->un.e.member[1].ord = 1;
861: break;
862:
863: case AD1843_OUTPUT_CLASS:
864: di->type = AUDIO_MIXER_CLASS;
865: di->mixer_class = AD1843_OUTPUT_CLASS;
866: strlcpy(di->label.name, AudioCoutputs, sizeof di->label.name);
867: break;
868:
869: case AD1843_MNO_MUTE:
870: di->type = AUDIO_MIXER_ENUM;
871: di->mixer_class = AD1843_OUTPUT_CLASS;
872: strlcpy(di->label.name, AudioNmono "." AudioNmute,
873: sizeof di->label.name);
874: di->un.e.num_mem = 2;
875: strlcpy(di->un.e.member[0].label.name, AudioNoff,
876: sizeof di->un.e.member[0].label.name);
877: di->un.e.member[0].ord = 0;
878: strlcpy(di->un.e.member[1].label.name, AudioNon,
879: sizeof di->un.e.member[1].label.name);
880: di->un.e.member[1].ord = 1;
881: break;
882:
883: case AD1843_HPO_MUTE:
884: di->type = AUDIO_MIXER_ENUM;
885: di->mixer_class = AD1843_OUTPUT_CLASS;
886: strlcpy(di->label.name, AudioNheadphone "." AudioNmute,
887: sizeof di->label.name);
888: di->un.e.num_mem = 2;
889: strlcpy(di->un.e.member[0].label.name, AudioNoff,
890: sizeof di->un.e.member[0].label.name);
891: di->un.e.member[0].ord = 0;
892: strlcpy(di->un.e.member[1].label.name, AudioNon,
893: sizeof di->un.e.member[1].label.name);
894: di->un.e.member[1].ord = 1;
895: break;
896:
897: default:
898: return (EINVAL);
899: }
900:
901: return (0);
902: }
903:
904: int
905: mavb_get_props(void *hdl)
906: {
907: return (AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT);
908: }
909:
910: static void
911: mavb_dma_output(struct mavb_softc *sc)
912: {
913: bus_space_tag_t st = sc->sc_st;
914: bus_space_handle_t sh = sc->sc_sh;
915: u_int64_t write_ptr;
916: u_int64_t depth;
917: caddr_t src, dst;
918: int count;
919:
920: write_ptr = bus_space_read_8(st, sh, MAVB_CHANNEL2_WRITE_PTR);
921: depth = bus_space_read_8(st, sh, MAVB_CHANNEL2_DEPTH);
922:
923: dst = sc->sc_ring + write_ptr;
924: src = sc->sc_get;
925:
926: count = (MAVB_ISA_RING_SIZE - depth - 32);
927: while (--count >= 0) {
928: *dst++ = *src++;
929: if (dst >= sc->sc_ring + MAVB_ISA_RING_SIZE)
930: dst = sc->sc_ring;
931: if (src >= sc->sc_end)
932: src = sc->sc_start;
933: if (++sc->sc_count >= sc->sc_blksize) {
934: if (sc->sc_intr)
935: sc->sc_intr(sc->sc_intrarg);
936: sc->sc_count = 0;
937: }
938: }
939:
940: write_ptr = dst - sc->sc_ring;
941: bus_space_write_8(st, sh, MAVB_CHANNEL2_WRITE_PTR, write_ptr);
942: sc->sc_get = src;
943: }
944:
945: int
946: mavb_trigger_output(void *hdl, void *start, void *end, int blksize,
947: void (*intr)(void *), void *intrarg,
948: struct audio_params *param)
949: {
950: struct mavb_softc *sc = (struct mavb_softc *)hdl;
951:
952: DPRINTF(1, ("%s: mavb_trigger_output: start=%p end=%p "
953: "blksize=%d intr=%p(%p)\n", sc->sc_dev.dv_xname,
954: start, end, blksize, intr, intrarg));
955:
956: sc->sc_blksize = blksize;
957: sc->sc_intr = intr;
958: sc->sc_intrarg = intrarg;
959:
960: sc->sc_start = sc->sc_get = start;
961: sc->sc_end = end;
962:
963: sc->sc_count = 0;
964:
965: bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL,
966: MAVB_CHANNEL_RESET);
967: delay(1000);
968: bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0);
969:
970: mavb_dma_output(sc);
971:
972: bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL,
973: MAVB_CHANNEL_DMA_ENABLE | MAVB_CHANNEL_INT_50);
974: return (0);
975: }
976:
977: int
978: mavb_trigger_input(void *hdl, void *start, void *end, int blksize,
979: void (*intr)(void *), void *intrarg,
980: struct audio_params *param)
981: {
982: return (0);
983: }
984:
985: static void
986: mavb_button_repeat(void *hdl)
987: {
988: struct mavb_softc *sc = (struct mavb_softc *)hdl;
989: u_int64_t intmask, control;
990: u_int16_t value, left, right;
991:
992: DPRINTF(1, ("%s: mavb_repeat called\n", sc->sc_dev.dv_xname));
993:
994: #define MAVB_CONTROL_VOLUME_BUTTONS \
995: (MAVB_CONTROL_VOLUME_BUTTON_UP | MAVB_CONTROL_VOLUME_BUTTON_DOWN)
996:
997: control = bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL);
998: if (control & MAVB_CONTROL_VOLUME_BUTTONS) {
999: value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
1000: left = (value & AD1843_LDA1G_MASK) >> AD1843_LDA1G_SHIFT;
1001: right = (value & AD1843_RDA1G_MASK) >> AD1843_RDA1G_SHIFT;
1002: if (control & MAVB_CONTROL_VOLUME_BUTTON_UP) {
1003: control &= ~MAVB_CONTROL_VOLUME_BUTTON_UP;
1004: if (left > 0)
1005: left--; /* attenuation! */
1006: if (right > 0)
1007: right--;
1008: }
1009: if (control & MAVB_CONTROL_VOLUME_BUTTON_DOWN) {
1010: control &= ~MAVB_CONTROL_VOLUME_BUTTON_DOWN;
1011: if (left < 63)
1012: left++;
1013: if (right < 63)
1014: right++;
1015: }
1016: bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, control);
1017:
1018: value &= ~(AD1843_LDA1G_MASK | AD1843_RDA1G_MASK);
1019: value |= (left << AD1843_LDA1G_SHIFT);
1020: value |= (right << AD1843_RDA1G_SHIFT);
1021: ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value);
1022:
1023: timeout_add(&sc->sc_volume_button_to,
1024: (hz * MAVB_VOLUME_BUTTON_REPEAT_DELN) / 1000);
1025: } else {
1026: /* Enable volume button interrupts again. */
1027: intmask = bus_space_read_8(sc->sc_st, sc->sc_isash,
1028: MACE_ISA_INT_MASK);
1029: bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK,
1030: intmask | MACE_ISA_INT_AUDIO_SC);
1031: }
1032: }
1033:
1034: static int
1035: mavb_intr(void *arg)
1036: {
1037: struct mavb_softc *sc = arg;
1038: u_int64_t intstat, intmask;
1039:
1040: intstat = bus_space_read_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_STAT);
1041: DPRINTF(MAVB_DEBUG_INTR, ("%s: mavb_intr: intstat = 0x%lx\n",
1042: sc->sc_dev.dv_xname, intstat));
1043:
1044: if (intstat & MACE_ISA_INT_AUDIO_SC) {
1045: /* Disable volume button interrupts. */
1046: intmask = bus_space_read_8(sc->sc_st, sc->sc_isash,
1047: MACE_ISA_INT_MASK);
1048: bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK,
1049: intmask & ~MACE_ISA_INT_AUDIO_SC);
1050:
1051: timeout_add(&sc->sc_volume_button_to,
1052: (hz * MAVB_VOLUME_BUTTON_REPEAT_DEL1) / 1000);
1053: }
1054:
1055: if (intstat & MACE_ISA_INT_AUDIO_DMA2)
1056: mavb_dma_output(sc);
1057:
1058: return 1;
1059: }
1060:
1061: int
1062: mavb_match(struct device *parent, void *match, void *aux)
1063: {
1064: struct confargs *ca = aux;
1065: bus_space_handle_t ioh;
1066: u_int64_t control;
1067:
1068: if (ca->ca_sys != SGI_O2 || strcmp(ca->ca_name, mavb_cd.cd_name))
1069: return (0);
1070:
1071: if (bus_space_map(ca->ca_iot, ca->ca_baseaddr, MAVB_NREGS, 0,
1072: &ioh) != 0)
1073: return (0);
1074: control = bus_space_read_8(ca->ca_iot, ioh, MAVB_CONTROL);
1075: bus_space_unmap(ca->ca_iot, ioh, MAVB_NREGS);
1076:
1077: return ((control & MAVB_CONTROL_CODEC_PRESENT) != 0);
1078: }
1079:
1080: void
1081: mavb_attach(struct device *parent, struct device *self, void *aux)
1082: {
1083: struct mavb_softc *sc = (void *)self;
1084: struct confargs *ca = aux;
1085: bus_dma_segment_t seg;
1086: u_int16_t value;
1087: int rseg;
1088:
1089: sc->sc_st = ca->ca_iot;
1090: if (bus_space_map(sc->sc_st, ca->ca_baseaddr, MAVB_NREGS, 0,
1091: &sc->sc_sh) != 0) {
1092: printf(": can't map i/o space\n");
1093: return;
1094: }
1095:
1096: /* XXX We need access to some of the MACE ISA registers. */
1097: extern bus_space_handle_t mace_h;
1098: bus_space_subregion(sc->sc_st, mace_h, 0, MAVB_ISA_NREGS,
1099: &sc->sc_isash);
1100:
1101: /* Set up DMA structures. */
1102: sc->sc_dmat = ca->ca_dmat;
1103: if (bus_dmamap_create(sc->sc_dmat, 4 * MAVB_ISA_RING_SIZE, 1,
1104: 4 * MAVB_ISA_RING_SIZE, 0, 0, &sc->sc_dmamap)) {
1105: printf(": can't create MACE ISA DMA map\n");
1106: return;
1107: }
1108:
1109: if (bus_dmamem_alloc(sc->sc_dmat, 4 * MAVB_ISA_RING_SIZE,
1110: MACE_ISA_RING_ALIGN, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
1111: printf(": can't allocate ring buffer\n");
1112: return;
1113: }
1114:
1115: if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, 4 * MAVB_ISA_RING_SIZE,
1116: &sc->sc_ring, BUS_DMA_COHERENT)) {
1117: printf(": can't map ring buffer\n");
1118: return;
1119: }
1120:
1121: if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_ring,
1122: 4 * MAVB_ISA_RING_SIZE, NULL, BUS_DMA_NOWAIT)) {
1123: printf(": can't load MACE ISA DMA map\n");
1124: return;
1125: }
1126:
1127: sc->sc_ring += MAVB_ISA_RING_SIZE; /* XXX */
1128:
1129: bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_RING_BASE,
1130: sc->sc_dmamap->dm_segs[0].ds_addr);
1131:
1132: /* Establish interrupt. */
1133: BUS_INTR_ESTABLISH(ca, NULL, ca->ca_intr, IST_EDGE, IPL_AUDIO,
1134: mavb_intr, sc, sc->sc_dev.dv_xname);
1135:
1136: /* 2. Assert the RESET signal. */
1137: bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL,
1138: MAVB_CONTROL_RESET);
1139: delay(1); /* at least 100 ns */
1140:
1141: /* 3. Deassert the RESET signal and enter a wait period to
1142: allow the AD1843 internal clocks and the external
1143: crystal oscillator to stabilize. */
1144: bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, 0);
1145: delay(800); /* typically 400 us to 800 us */
1146: if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_INIT) {
1147: printf(": codec not ready\n");
1148: return;
1149: }
1150:
1151: /* 4. Put the conversion sources into standby. */
1152: value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS);
1153: ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS,
1154: value & ~AD1843_PDNI);
1155: delay (500000); /* approximately 474 ms */
1156: if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_PDNO) {
1157: printf(": can't power up conversion resources\n");
1158: return;
1159: }
1160:
1161: /* 5. Power up the clock generators and enable clock output pins. */
1162: value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS);
1163: ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS, value | AD1843_C2EN);
1164:
1165: /* 6. Configure conversion resources while they are in standby. */
1166: value = ad1843_reg_read(sc, AD1843_CHANNEL_SAMPLE_RATE);
1167: ad1843_reg_write(sc, AD1843_CHANNEL_SAMPLE_RATE,
1168: value | (2 << AD1843_DA1C_SHIFT));
1169:
1170: /* 7. Enable conversion resources. */
1171: value = ad1843_reg_read(sc, AD1843_CHANNEL_POWER_DOWN);
1172: ad1843_reg_write(sc, AD1843_CHANNEL_POWER_DOWN,
1173: value | (AD1843_DA1EN | AD1843_AAMEN));
1174:
1175: /* 8. Configure conversion resources while they are enabled. */
1176: value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
1177: ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN,
1178: value & ~(AD1843_LDA1GM | AD1843_RDA1GM));
1179: value = ad1843_reg_read(sc, AD1843_DAC1_DIGITAL_GAIN);
1180: ad1843_reg_write(sc, AD1843_DAC1_DIGITAL_GAIN,
1181: value & ~(AD1843_LDA1AM | AD1843_RDA1AM));
1182: value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
1183: ad1843_reg_write(sc, AD1843_MISC_SETTINGS,
1184: value & ~(AD1843_HPOM | AD1843_MNOM));
1185:
1186: value = ad1843_reg_read(sc, AD1843_CODEC_STATUS);
1187: printf(": AD1843 rev %d\n", (u_int)value & AD1843_REVISION_MASK);
1188:
1189: sc->sc_play_rate = 48000;
1190: sc->sc_play_format = AD1843_PCM8;
1191:
1192: timeout_set(&sc->sc_volume_button_to, mavb_button_repeat, sc);
1193:
1194: audio_attach_mi(&mavb_sa_hw_if, sc, &sc->sc_dev);
1195:
1196: return;
1197: }
1198:
1199: u_int16_t
1200: ad1843_reg_read(struct mavb_softc *sc, ad1843_addr_t addr)
1201: {
1202: bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL,
1203: (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT |
1204: MAVB_CODEC_READ);
1205: delay(200);
1206: return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS);
1207: }
1208:
1209: u_int16_t
1210: ad1843_reg_write(struct mavb_softc *sc, ad1843_addr_t addr, u_int16_t value)
1211: {
1212: bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL,
1213: (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT |
1214: (value & MAVB_CODEC_WORD_MASK) << MAVB_CODEC_WORD_SHIFT);
1215: delay(200);
1216: return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS);
1217: }
1218:
1219: void
1220: ad1843_dump_regs(struct mavb_softc *sc)
1221: {
1222: u_int16_t addr;
1223:
1224: for (addr = 0; addr < AD1843_NREGS; addr++)
1225: printf("%d: 0x%04x\n", addr, ad1843_reg_read(sc, addr));
1226: }
CVSweb