Annotation of sys/dev/pci/esa.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: esa.c,v 1.11 2006/01/25 23:54:21 brad Exp $ */
2: /* $NetBSD: esa.c,v 1.12 2002/03/24 14:17:35 jmcneill Exp $ */
3:
4: /*
5: * Copyright (c) 2001, 2002 Jared D. McNeill <jmcneill@invisible.ca>
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. The name of the author may not be used to endorse or promote products
14: * derived from this software without specific prior written permission.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: */
28:
29: /*
30: * Shamelessly stolen from NetBSD who based it on FreeBSD's who in turn
31: * based it on Linux's driver. What a wonderful world.
32: *
33: *
34: * ESS Allegro-1 / Maestro3 Audio Driver
35: *
36: * Based on the FreeBSD maestro3 driver and the NetBSD eap driver.
37: * Original driver by Don Kim.
38: *
39: * The list management code could possibly be written better, but what
40: * we have right now does the job nicely. Thanks to Zach Brown <zab@zabbo.net>
41: * and Andrew MacDonald <amac@epsilon.yi.org> for helping me debug the
42: * problems with the original list management code present in the Linux
43: * driver.
44: */
45:
46: #include <sys/types.h>
47: #include <sys/errno.h>
48: #include <sys/param.h>
49: #include <sys/systm.h>
50: #include <sys/malloc.h>
51: #include <sys/device.h>
52: #include <sys/conf.h>
53: #include <sys/exec.h>
54: #include <sys/selinfo.h>
55: #include <sys/audioio.h>
56:
57: #include <machine/bus.h>
58: #include <machine/intr.h>
59:
60: #include <dev/pci/pcidevs.h>
61: #include <dev/pci/pcivar.h>
62:
63: #include <dev/audio_if.h>
64: #include <dev/mulaw.h>
65: #include <dev/auconv.h>
66: #include <dev/ic/ac97.h>
67:
68: #include <dev/pci/esareg.h>
69: #include <dev/pci/esavar.h>
70: #include <dev/microcode/esa/esadsp.h>
71:
72: #define PCI_CBIO 0x10
73:
74: #define ESA_DAC_DATA 0x1100
75:
76: enum {
77: ESS_ALLEGRO1,
78: ESS_MAESTRO3
79: };
80:
81: static struct esa_card_type {
82: u_int16_t pci_vendor_id;
83: u_int16_t pci_product_id;
84: int type;
85: int delay1, delay2;
86: } esa_card_types[] = {
87: { PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_ES1989,
88: ESS_ALLEGRO1, 50, 800 },
89: { PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO3,
90: ESS_MAESTRO3, 20, 500 },
91: { PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO3_2,
92: ESS_MAESTRO3, 20, 500 },
93: { 0, 0, 0, 0, 0 }
94: };
95:
96: struct audio_device esa_device = {
97: "ESS Allegro",
98: "",
99: "esa"
100: };
101:
102: int esa_match(struct device *, void *, void *);
103: void esa_attach(struct device *, struct device *, void *);
104: int esa_detach(struct device *, int);
105:
106: /* audio(9) functions */
107: int esa_open(void *, int);
108: void esa_close(void *);
109: int esa_query_encoding(void *, struct audio_encoding *);
110: int esa_set_params(void *, int, int, struct audio_params *,
111: struct audio_params *);
112: int esa_round_blocksize(void *, int);
113: int esa_commit_settings(void *);
114: int esa_halt_output(void *);
115: int esa_halt_input(void *);
116: int esa_set_port(void *, mixer_ctrl_t *);
117: int esa_get_port(void *, mixer_ctrl_t *);
118: int esa_query_devinfo(void *, mixer_devinfo_t *);
119: void * esa_malloc(void *, int, size_t, int, int);
120: void esa_free(void *, void *, int);
121: int esa_getdev(void *, struct audio_device *);
122: size_t esa_round_buffersize(void *, int, size_t);
123: int esa_get_props(void *);
124: int esa_trigger_output(void *, void *, void *, int,
125: void (*)(void *), void *,
126: struct audio_params *);
127: int esa_trigger_input(void *, void *, void *, int,
128: void (*)(void *), void *,
129: struct audio_params *);
130:
131: int esa_intr(void *);
132: int esa_allocmem(struct esa_softc *, size_t, size_t,
133: struct esa_dma *);
134: int esa_freemem(struct esa_softc *, struct esa_dma *);
135: paddr_t esa_mappage(void *addr, void *mem, off_t off, int prot);
136:
137: /* Supporting subroutines */
138: u_int16_t esa_read_assp(struct esa_softc *, u_int16_t, u_int16_t);
139: void esa_write_assp(struct esa_softc *, u_int16_t, u_int16_t,
140: u_int16_t);
141: int esa_init_codec(struct esa_softc *);
142: int esa_attach_codec(void *, struct ac97_codec_if *);
143: int esa_read_codec(void *, u_int8_t, u_int16_t *);
144: int esa_write_codec(void *, u_int8_t, u_int16_t);
145: void esa_reset_codec(void *);
146: enum ac97_host_flags esa_flags_codec(void *);
147: int esa_wait(struct esa_softc *);
148: int esa_init(struct esa_softc *);
149: void esa_config(struct esa_softc *);
150: u_int8_t esa_assp_halt(struct esa_softc *);
151: void esa_codec_reset(struct esa_softc *);
152: int esa_amp_enable(struct esa_softc *);
153: void esa_enable_interrupts(struct esa_softc *);
154: u_int32_t esa_get_pointer(struct esa_softc *, struct esa_channel *);
155:
156: /* list management */
157: int esa_add_list(struct esa_voice *, struct esa_list *, u_int16_t,
158: int);
159: void esa_remove_list(struct esa_voice *, struct esa_list *, int);
160:
161: /* power management */
162: int esa_power(struct esa_softc *, int);
163: void esa_powerhook(int, void *);
164: int esa_suspend(struct esa_softc *);
165: int esa_resume(struct esa_softc *);
166:
167: static audio_encoding_t esa_encoding[] = {
168: { 0, AudioEulinear, AUDIO_ENCODING_ULINEAR, 8, 0 },
169: { 1, AudioEmulaw, AUDIO_ENCODING_ULAW, 8,
170: AUDIO_ENCODINGFLAG_EMULATED },
171: { 2, AudioEalaw, AUDIO_ENCODING_ALAW, 8, AUDIO_ENCODINGFLAG_EMULATED },
172: { 3, AudioEslinear, AUDIO_ENCODING_SLINEAR, 8,
173: AUDIO_ENCODINGFLAG_EMULATED }, /* XXX: Are you sure? */
174: { 4, AudioEslinear_le, AUDIO_ENCODING_SLINEAR_LE, 16, 0 },
175: { 5, AudioEulinear_le, AUDIO_ENCODING_ULINEAR_LE, 16,
176: AUDIO_ENCODINGFLAG_EMULATED },
177: { 6, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16,
178: AUDIO_ENCODINGFLAG_EMULATED },
179: { 7, AudioEulinear_be, AUDIO_ENCODING_ULINEAR_BE, 16,
180: AUDIO_ENCODINGFLAG_EMULATED }
181: };
182:
183: #define ESA_NENCODINGS 8
184:
185: struct audio_hw_if esa_hw_if = {
186: esa_open,
187: esa_close,
188: NULL, /* drain */
189: esa_query_encoding,
190: esa_set_params,
191: esa_round_blocksize,
192: esa_commit_settings,
193: NULL, /* init_output */
194: NULL, /* init_input */
195: NULL, /* start_output */
196: NULL, /* start_input */
197: esa_halt_output,
198: esa_halt_input,
199: NULL, /* speaker_ctl */
200: esa_getdev,
201: NULL, /* getfd */
202: esa_set_port,
203: esa_get_port,
204: esa_query_devinfo,
205: esa_malloc,
206: esa_free,
207: esa_round_buffersize,
208: esa_mappage,
209: esa_get_props,
210: esa_trigger_output,
211: esa_trigger_input
212: };
213:
214: struct cfdriver esa_cd = {
215: NULL, "esa", DV_DULL
216: };
217:
218: struct cfattach esa_ca = {
219: sizeof(struct esa_softc), esa_match, esa_attach,
220: esa_detach, /*esa_activate*/ NULL
221: };
222:
223: /*
224: * audio(9) functions
225: */
226:
227: int
228: esa_open(void *hdl, int flags)
229: {
230:
231: return (0);
232: }
233:
234: void
235: esa_close(void *hdl)
236: {
237:
238: return;
239: }
240:
241: int
242: esa_query_encoding(void *hdl, struct audio_encoding *ae)
243: {
244:
245: if (ae->index < 0 || ae->index >= ESA_NENCODINGS)
246: return (EINVAL);
247: *ae = esa_encoding[ae->index];
248:
249: return (0);
250: }
251:
252: int
253: esa_set_params(void *hdl, int setmode, int usemode, struct audio_params *play,
254: struct audio_params *rec)
255: {
256: struct esa_voice *vc = hdl;
257: //struct esa_softc *sc = (struct esa_softc *)vc->parent;
258: struct esa_channel *ch;
259: struct audio_params *p;
260: int mode;
261:
262: for (mode = AUMODE_RECORD; mode != -1;
263: mode = (mode == AUMODE_RECORD) ? AUMODE_PLAY : -1) {
264: if ((setmode & mode) == 0)
265: continue;
266:
267: switch (mode) {
268: case AUMODE_PLAY:
269: p = play;
270: ch = &vc->play;
271: break;
272: case AUMODE_RECORD:
273: p = rec;
274: ch = &vc->rec;
275: break;
276: }
277:
278: if (p->sample_rate < ESA_MINRATE ||
279: p->sample_rate > ESA_MAXRATE ||
280: (p->precision != 8 && p->precision != 16) ||
281: (p->channels < 1 || p->channels > 2))
282: return (EINVAL);
283:
284: p->factor = 1;
285: p->sw_code = 0;
286:
287: switch(p->encoding) {
288: case AUDIO_ENCODING_SLINEAR_BE:
289: if (p->precision == 16)
290: p->sw_code = swap_bytes;
291: else
292: p->sw_code = change_sign8;
293: break;
294: case AUDIO_ENCODING_SLINEAR_LE:
295: if (p->precision != 16)
296: p->sw_code = change_sign8;
297: break;
298: case AUDIO_ENCODING_ULINEAR_BE:
299: if (p->precision == 16) {
300: if (mode == AUMODE_PLAY)
301: p->sw_code =
302: swap_bytes_change_sign16_le;
303: else
304: p->sw_code =
305: change_sign16_swap_bytes_le;
306: }
307: break;
308: case AUDIO_ENCODING_ULINEAR_LE:
309: if (p->precision == 16)
310: p->sw_code = change_sign16_le;
311: break;
312: case AUDIO_ENCODING_ULAW:
313: if (mode == AUMODE_PLAY) {
314: p->factor = 2;
315: p->sw_code = mulaw_to_slinear16_le;
316: } else
317: p->sw_code = ulinear8_to_mulaw;
318: break;
319: case AUDIO_ENCODING_ALAW:
320: if (mode == AUMODE_PLAY) {
321: p->factor = 2;
322: p->sw_code = alaw_to_slinear16_le;
323: } else
324: p->sw_code = ulinear8_to_alaw;
325: break;
326: default:
327: return (EINVAL);
328: }
329:
330: ch->mode = *p;
331: }
332:
333: return (0);
334: }
335:
336: int
337: esa_commit_settings(void *hdl)
338: {
339: struct esa_voice *vc = hdl;
340: struct esa_softc *sc = (struct esa_softc *)vc->parent;
341: struct audio_params *p = &vc->play.mode;
342: struct audio_params *r = &vc->rec.mode;
343: u_int32_t data;
344: u_int32_t freq;
345: int data_bytes = (((ESA_MINISRC_TMP_BUFFER_SIZE & ~1) +
346: (ESA_MINISRC_IN_BUFFER_SIZE & ~1) +
347: (ESA_MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255)
348: &~ 255;
349:
350: /* playback */
351: vc->play.data_offset = ESA_DAC_DATA + (data_bytes * vc->index);
352: if (p->channels == 1)
353: data = 1;
354: else
355: data = 0;
356: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
357: vc->play.data_offset + ESA_SRC3_MODE_OFFSET,
358: data);
359: if (p->precision * p->factor == 8)
360: data = 1;
361: else
362: data = 0;
363: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
364: vc->play.data_offset + ESA_SRC3_WORD_LENGTH_OFFSET,
365: data);
366: if ((freq = ((p->sample_rate << 15) + 24000) / 48000) != 0) {
367: freq--;
368: }
369: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
370: vc->play.data_offset + ESA_CDATA_FREQUENCY, freq);
371:
372: /* recording */
373: vc->rec.data_offset = ESA_DAC_DATA + (data_bytes * vc->index) +
374: (data_bytes / 2);
375: if (r->channels == 1)
376: data = 1;
377: else
378: data = 0;
379: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
380: vc->rec.data_offset + ESA_SRC3_MODE_OFFSET,
381: data);
382: if (r->precision * r->factor == 8)
383: data = 1;
384: else
385: data = 0;
386: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
387: vc->rec.data_offset + ESA_SRC3_WORD_LENGTH_OFFSET,
388: data);
389: if ((freq = ((r->sample_rate << 15) + 24000) / 48000) != 0) {
390: freq--;
391: }
392: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
393: vc->rec.data_offset + ESA_CDATA_FREQUENCY, freq);
394:
395: return (0);
396: };
397:
398: int
399: esa_round_blocksize(void *hdl, int bs)
400: {
401: struct esa_voice *vc = hdl;
402:
403: /*
404: * Surely there has to be a better solution...
405: */
406: vc->play.blksize = vc->rec.blksize = 4096;
407:
408: return (vc->play.blksize);
409: }
410:
411: int
412: esa_halt_output(void *hdl)
413: {
414: struct esa_voice *vc = hdl;
415: struct esa_softc *sc = (struct esa_softc *)vc->parent;
416: bus_space_tag_t iot = sc->sc_iot;
417: bus_space_handle_t ioh = sc->sc_ioh;
418: u_int16_t data;
419:
420: if (vc->play.active == 0)
421: return (0);
422:
423: vc->play.active = 0;
424:
425: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
426: ESA_CDATA_INSTANCE_READY + vc->play.data_offset, 0);
427:
428: sc->sc_ntimers--;
429: if (sc->sc_ntimers == 0) {
430: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
431: ESA_KDATA_TIMER_COUNT_RELOAD, 0);
432: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
433: ESA_KDATA_TIMER_COUNT_CURRENT, 0);
434: data = bus_space_read_2(iot, ioh, ESA_HOST_INT_CTRL);
435: bus_space_write_2(iot, ioh, ESA_HOST_INT_CTRL,
436: data & ~ESA_CLKRUN_GEN_ENABLE);
437: }
438:
439: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
440: ESA_KDATA_MIXER_TASK_NUMBER,
441: sc->mixer_list.indexmap[vc->index]);
442: /* remove ourselves from the packed lists */
443: esa_remove_list(vc, &sc->mixer_list, vc->index);
444: esa_remove_list(vc, &sc->dma_list, vc->index);
445: esa_remove_list(vc, &sc->msrc_list, vc->index);
446:
447: return (0);
448: }
449:
450: int
451: esa_halt_input(void *hdl)
452: {
453: struct esa_voice *vc = hdl;
454: struct esa_softc *sc = (struct esa_softc *)vc->parent;
455: bus_space_tag_t iot = sc->sc_iot;
456: bus_space_handle_t ioh = sc->sc_ioh;
457: u_int32_t data;
458:
459: if (vc->rec.active == 0)
460: return (0);
461:
462: vc->rec.active = 0;
463:
464: sc->sc_ntimers--;
465: if (sc->sc_ntimers == 0) {
466: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
467: ESA_KDATA_TIMER_COUNT_RELOAD, 0);
468: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
469: ESA_KDATA_TIMER_COUNT_CURRENT, 0);
470: data = bus_space_read_2(iot, ioh, ESA_HOST_INT_CTRL);
471: bus_space_write_2(iot, ioh, ESA_HOST_INT_CTRL,
472: data & ~ESA_CLKRUN_GEN_ENABLE);
473: }
474:
475: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, vc->rec.data_offset +
476: ESA_CDATA_INSTANCE_READY, 0);
477: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, ESA_KDATA_ADC1_REQUEST,
478: 0);
479:
480: /* remove ourselves from the packed lists */
481: esa_remove_list(vc, &sc->adc1_list, vc->index + ESA_NUM_VOICES);
482: esa_remove_list(vc, &sc->dma_list, vc->index + ESA_NUM_VOICES);
483: esa_remove_list(vc, &sc->msrc_list, vc->index + ESA_NUM_VOICES);
484:
485: return (0);
486: }
487:
488: void *
489: esa_malloc(void *hdl, int direction, size_t size, int type, int flags)
490: {
491: struct esa_voice *vc = hdl;
492: struct esa_softc *sc = (struct esa_softc *)vc->parent;
493: struct esa_dma *p;
494: int error;
495:
496: p = malloc(sizeof(*p), type, flags);
497: if (!p)
498: return (0);
499: error = esa_allocmem(sc, size, 16, p);
500: if (error) {
501: free(p, type);
502: printf("%s: esa_malloc: not enough memory\n",
503: sc->sc_dev.dv_xname);
504: return (0);
505: }
506: p->next = vc->dma;
507: vc->dma = p;
508:
509: return (KERNADDR(p));
510: }
511:
512: void
513: esa_free(void *hdl, void *addr, int type)
514: {
515: struct esa_voice *vc = hdl;
516: struct esa_softc *sc = (struct esa_softc *)vc->parent;
517: struct esa_dma *p;
518: struct esa_dma **pp;
519:
520: for (pp = &vc->dma; (p = *pp) != NULL; pp = &p->next)
521: if (KERNADDR(p) == addr) {
522: esa_freemem(sc, p);
523: *pp = p->next;
524: free(p, type);
525: return;
526: }
527: }
528:
529: int
530: esa_getdev(void *hdl, struct audio_device *ret)
531: {
532:
533: *ret = esa_device;
534:
535: return (0);
536: }
537:
538: int
539: esa_set_port(void *hdl, mixer_ctrl_t *mc)
540: {
541: struct esa_voice *vc = hdl;
542: struct esa_softc *sc = (struct esa_softc *)vc->parent;
543:
544: return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, mc));
545: }
546:
547: int
548: esa_get_port(void *hdl, mixer_ctrl_t *mc)
549: {
550: struct esa_voice *vc = hdl;
551: struct esa_softc *sc = (struct esa_softc *)vc->parent;
552:
553: return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, mc));
554: }
555:
556: int
557: esa_query_devinfo(void *hdl, mixer_devinfo_t *di)
558: {
559: struct esa_voice *vc = hdl;
560: struct esa_softc *sc = (struct esa_softc *)vc->parent;
561:
562: return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, di));
563: }
564:
565: size_t
566: esa_round_buffersize(void *hdl, int direction, size_t bufsize)
567: {
568: struct esa_voice *vc = hdl;
569:
570: /*
571: * We must be able to do better than this...
572: */
573: vc->play.bufsize = vc->rec.bufsize = 65536;
574:
575: return (vc->play.bufsize);
576: }
577:
578: int
579: esa_get_props(void *hdl)
580: {
581:
582: return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX);
583: }
584:
585: int
586: esa_trigger_output(void *hdl, void *start, void *end, int blksize,
587: void (*intr)(void *), void *intrarg,
588: struct audio_params *param)
589: {
590: struct esa_voice *vc = hdl;
591: struct esa_softc *sc = (struct esa_softc *)vc->parent;
592: struct esa_dma *p;
593: bus_space_tag_t iot = sc->sc_iot;
594: bus_space_handle_t ioh = sc->sc_ioh;
595: u_int32_t data;
596: u_int32_t bufaddr;
597: u_int32_t i;
598: size_t size;
599:
600: int data_bytes = (((ESA_MINISRC_TMP_BUFFER_SIZE & ~1) +
601: (ESA_MINISRC_IN_BUFFER_SIZE & ~1) +
602: (ESA_MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255)
603: &~ 255;
604: int dac_data = ESA_DAC_DATA + (data_bytes * vc->index);
605: int dsp_in_size = ESA_MINISRC_IN_BUFFER_SIZE - (0x20 * 2);
606: int dsp_out_size = ESA_MINISRC_OUT_BUFFER_SIZE - (0x20 * 2);
607: int dsp_in_buf = dac_data + (ESA_MINISRC_TMP_BUFFER_SIZE / 2);
608: int dsp_out_buf = dsp_in_buf + (dsp_in_size / 2) + 1;
609:
610: if (vc->play.active)
611: return (EINVAL);
612:
613: for (p = vc->dma; p && KERNADDR(p) != start; p = p->next)
614: ;
615: if (!p) {
616: printf("%s: esa_trigger_output: bad addr %p\n",
617: sc->sc_dev.dv_xname, start);
618: return (EINVAL);
619: }
620:
621: vc->play.active = 1;
622: vc->play.intr = intr;
623: vc->play.arg = intrarg;
624: vc->play.pos = 0;
625: vc->play.count = 0;
626: vc->play.buf = start;
627: size = (size_t)(((caddr_t)end - (caddr_t)start));
628: bufaddr = DMAADDR(p);
629: vc->play.start = bufaddr;
630:
631: #define LO(x) ((x) & 0x0000ffff)
632: #define HI(x) ((x) >> 16)
633:
634: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
635: ESA_CDATA_HOST_SRC_ADDRL, LO(bufaddr));
636: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
637: ESA_CDATA_HOST_SRC_ADDRH, HI(bufaddr));
638: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
639: ESA_CDATA_HOST_SRC_END_PLUS_1L, LO(bufaddr + size));
640: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
641: ESA_CDATA_HOST_SRC_END_PLUS_1H, HI(bufaddr + size));
642: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
643: ESA_CDATA_HOST_SRC_CURRENTL, LO(bufaddr));
644: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
645: ESA_CDATA_HOST_SRC_CURRENTH, HI(bufaddr));
646:
647: /* DSP buffers */
648: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
649: ESA_CDATA_IN_BUF_BEGIN, dsp_in_buf);
650: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
651: ESA_CDATA_IN_BUF_END_PLUS_1, dsp_in_buf + (dsp_in_size / 2));
652: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
653: ESA_CDATA_IN_BUF_HEAD, dsp_in_buf);
654: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
655: ESA_CDATA_IN_BUF_TAIL, dsp_in_buf);
656: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
657: ESA_CDATA_OUT_BUF_BEGIN, dsp_out_buf);
658: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
659: ESA_CDATA_OUT_BUF_END_PLUS_1, dsp_out_buf + (dsp_out_size / 2));
660: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
661: ESA_CDATA_OUT_BUF_HEAD, dsp_out_buf);
662: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
663: ESA_CDATA_OUT_BUF_TAIL, dsp_out_buf);
664:
665: /* Some per-client initializers */
666: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
667: ESA_SRC3_DIRECTION_OFFSET + 12, dac_data + 40 + 8);
668: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
669: ESA_SRC3_DIRECTION_OFFSET + 19, 0x400 + ESA_MINISRC_COEF_LOC);
670: /* Enable or disable low-pass filter? (0xff if rate > 45000) */
671: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
672: ESA_SRC3_DIRECTION_OFFSET + 22,
673: vc->play.mode.sample_rate > 45000 ? 0xff : 0);
674: /* Tell it which way DMA is going */
675: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
676: ESA_CDATA_DMA_CONTROL,
677: ESA_DMACONTROL_AUTOREPEAT + ESA_DMAC_PAGE3_SELECTOR +
678: ESA_DMAC_BLOCKF_SELECTOR);
679:
680: /* Set an armload of static initializers */
681: for (i = 0; i < (sizeof(esa_playvals) / sizeof(esa_playvals[0])); i++)
682: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
683: esa_playvals[i].addr, esa_playvals[i].val);
684:
685: /* Put us in the packed task lists */
686: esa_add_list(vc, &sc->msrc_list, dac_data >> ESA_DP_SHIFT_COUNT,
687: vc->index);
688: esa_add_list(vc, &sc->dma_list, dac_data >> ESA_DP_SHIFT_COUNT,
689: vc->index);
690: esa_add_list(vc, &sc->mixer_list, dac_data >> ESA_DP_SHIFT_COUNT,
691: vc->index);
692: #undef LO
693: #undef HI
694:
695: /* XXX */
696: //esa_commit_settings(vc);
697:
698: sc->sc_ntimers++;
699:
700: if (sc->sc_ntimers == 1) {
701: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
702: ESA_KDATA_TIMER_COUNT_RELOAD, 240);
703: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
704: ESA_KDATA_TIMER_COUNT_CURRENT, 240);
705: data = bus_space_read_2(iot, ioh, ESA_HOST_INT_CTRL);
706: bus_space_write_2(iot, ioh, ESA_HOST_INT_CTRL,
707: data | ESA_CLKRUN_GEN_ENABLE);
708: }
709:
710: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, dac_data +
711: ESA_CDATA_INSTANCE_READY, 1);
712: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
713: ESA_KDATA_MIXER_TASK_NUMBER,
714: sc->mixer_list.indexmap[vc->index]);
715:
716: return (0);
717: }
718:
719: int
720: esa_trigger_input(void *hdl, void *start, void *end, int blksize,
721: void (*intr)(void *), void *intrarg,
722: struct audio_params *param)
723: {
724: struct esa_voice *vc = hdl;
725: struct esa_softc *sc = (struct esa_softc *)vc->parent;
726: struct esa_dma *p;
727: bus_space_tag_t iot = sc->sc_iot;
728: bus_space_handle_t ioh = sc->sc_ioh;
729: u_int32_t data;
730: u_int32_t bufaddr;
731: u_int32_t i;
732: size_t size;
733: int data_bytes = (((ESA_MINISRC_TMP_BUFFER_SIZE & ~1) +
734: (ESA_MINISRC_IN_BUFFER_SIZE & ~1) +
735: (ESA_MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255)
736: &~ 255;
737: int adc_data = ESA_DAC_DATA + (data_bytes * vc->index) +
738: (data_bytes / 2);
739: int dsp_in_size = ESA_MINISRC_IN_BUFFER_SIZE - (0x10 * 2);
740: int dsp_out_size = ESA_MINISRC_OUT_BUFFER_SIZE - (0x10 * 2);
741: int dsp_in_buf = adc_data + (ESA_MINISRC_TMP_BUFFER_SIZE / 2);
742: int dsp_out_buf = dsp_in_buf + (dsp_in_size / 2) + 1;
743: vc->rec.data_offset = adc_data;
744:
745: /* We only support 1 recording channel */
746: if (vc->index > 0)
747: return (ENODEV);
748:
749: if (vc->rec.active)
750: return (EINVAL);
751:
752: for (p = vc->dma; p && KERNADDR(p) != start; p = p->next)
753: ;
754: if (!p) {
755: printf("%s: esa_trigger_input: bad addr %p\n",
756: sc->sc_dev.dv_xname, start);
757: return (EINVAL);
758: }
759:
760: vc->rec.active = 1;
761: vc->rec.intr = intr;
762: vc->rec.arg = intrarg;
763: vc->rec.pos = 0;
764: vc->rec.count = 0;
765: vc->rec.buf = start;
766: size = (size_t)(((caddr_t)end - (caddr_t)start));
767: bufaddr = DMAADDR(p);
768: vc->rec.start = bufaddr;
769:
770: #define LO(x) ((x) & 0x0000ffff)
771: #define HI(x) ((x) >> 16)
772:
773: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
774: ESA_CDATA_HOST_SRC_ADDRL, LO(bufaddr));
775: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
776: ESA_CDATA_HOST_SRC_ADDRH, HI(bufaddr));
777: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
778: ESA_CDATA_HOST_SRC_END_PLUS_1L, LO(bufaddr + size));
779: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
780: ESA_CDATA_HOST_SRC_END_PLUS_1H, HI(bufaddr + size));
781: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
782: ESA_CDATA_HOST_SRC_CURRENTL, LO(bufaddr));
783: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
784: ESA_CDATA_HOST_SRC_CURRENTH, HI(bufaddr));
785:
786: /* DSP buffers */
787: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
788: ESA_CDATA_IN_BUF_BEGIN, dsp_in_buf);
789: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
790: ESA_CDATA_IN_BUF_END_PLUS_1, dsp_in_buf + (dsp_in_size / 2));
791: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
792: ESA_CDATA_IN_BUF_HEAD, dsp_in_buf);
793: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
794: ESA_CDATA_IN_BUF_TAIL, dsp_in_buf);
795: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
796: ESA_CDATA_OUT_BUF_BEGIN, dsp_out_buf);
797: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
798: ESA_CDATA_OUT_BUF_END_PLUS_1, dsp_out_buf + (dsp_out_size / 2));
799: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
800: ESA_CDATA_OUT_BUF_HEAD, dsp_out_buf);
801: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
802: ESA_CDATA_OUT_BUF_TAIL, dsp_out_buf);
803:
804: /* Some per-client initializers */
805: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
806: ESA_SRC3_DIRECTION_OFFSET + 12, adc_data + 40 + 8);
807: /* Tell it which way DMA is going */
808: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
809: ESA_CDATA_DMA_CONTROL,
810: ESA_DMACONTROL_DIRECTION + ESA_DMACONTROL_AUTOREPEAT +
811: ESA_DMAC_PAGE3_SELECTOR + ESA_DMAC_BLOCKF_SELECTOR);
812:
813: /* Set an armload of static initializers */
814: for (i = 0; i < (sizeof(esa_recvals) / sizeof(esa_recvals[0])); i++)
815: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
816: esa_recvals[i].addr, esa_recvals[i].val);
817:
818: /* Put us in the packed task lists */
819: esa_add_list(vc, &sc->adc1_list, adc_data >> ESA_DP_SHIFT_COUNT,
820: vc->index + ESA_NUM_VOICES);
821: esa_add_list(vc, &sc->msrc_list, adc_data >> ESA_DP_SHIFT_COUNT,
822: vc->index + ESA_NUM_VOICES);
823: esa_add_list(vc, &sc->dma_list, adc_data >> ESA_DP_SHIFT_COUNT,
824: vc->index + ESA_NUM_VOICES);
825: #undef LO
826: #undef HI
827:
828: /* XXX */
829: //esa_commit_settings(vc);
830:
831: sc->sc_ntimers++;
832: if (sc->sc_ntimers == 1) {
833: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
834: ESA_KDATA_TIMER_COUNT_RELOAD, 240);
835: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
836: ESA_KDATA_TIMER_COUNT_CURRENT, 240);
837: data = bus_space_read_2(iot, ioh, ESA_HOST_INT_CTRL);
838: bus_space_write_2(iot, ioh, ESA_HOST_INT_CTRL,
839: data | ESA_CLKRUN_GEN_ENABLE);
840: }
841:
842: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, adc_data +
843: ESA_CDATA_INSTANCE_READY, 1);
844: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, ESA_KDATA_ADC1_REQUEST,
845: 1);
846:
847: return (0);
848: }
849:
850: /* Interrupt handler */
851:
852: int
853: esa_intr(void *hdl)
854: {
855: struct esa_softc *sc = hdl;
856: struct esa_voice *vc;
857: bus_space_tag_t iot = sc->sc_iot;
858: bus_space_handle_t ioh = sc->sc_ioh;
859: u_int8_t status, ctl;
860: u_int32_t pos;
861: u_int32_t diff;
862: u_int32_t play_blksize, play_bufsize;
863: u_int32_t rec_blksize, rec_bufsize;
864: int i;
865:
866: status = bus_space_read_1(iot, ioh, ESA_HOST_INT_STATUS);
867: if (status == 0xff)
868: return (0);
869:
870: /* ack the interrupt */
871: bus_space_write_1(iot, ioh, ESA_HOST_INT_STATUS, status);
872:
873: if (status & ESA_HV_INT_PENDING) {
874: u_int8_t event;
875:
876: printf("%s: hardware volume interrupt\n", sc->sc_dev.dv_xname);
877: event = bus_space_read_1(iot, ioh, ESA_HW_VOL_COUNTER_MASTER);
878: switch(event) {
879: case 0x99:
880: case 0xaa:
881: case 0x66:
882: case 0x88:
883: printf("%s: esa_intr: FIXME\n", sc->sc_dev.dv_xname);
884: break;
885: default:
886: printf("%s: unknown hwvol event 0x%02x\n",
887: sc->sc_dev.dv_xname, event);
888: break;
889: }
890: bus_space_write_1(iot, ioh, ESA_HW_VOL_COUNTER_MASTER, 0x88);
891: }
892:
893: if (status & ESA_ASSP_INT_PENDING) {
894: ctl = bus_space_read_1(iot, ioh, ESA_ASSP_CONTROL_B);
895: if (!(ctl & ESA_STOP_ASSP_CLOCK)) {
896: ctl = bus_space_read_1(iot, ioh,
897: ESA_ASSP_HOST_INT_STATUS);
898: if (ctl & ESA_DSP2HOST_REQ_TIMER) {
899: bus_space_write_1(iot, ioh,
900: ESA_ASSP_HOST_INT_STATUS,
901: ESA_DSP2HOST_REQ_TIMER);
902: for (i = 0; i < ESA_NUM_VOICES; i++) {
903: vc = &sc->voice[i];
904: if (vc->play.active) {
905: play_blksize = vc->play.blksize;
906: play_bufsize = vc->play.bufsize;
907: pos = esa_get_pointer(sc, &vc->play)
908: % play_bufsize;
909: diff = (play_bufsize + pos - vc->play.pos)
910: % play_bufsize;
911: vc->play.pos = pos;
912: vc->play.count += diff;
913: while(vc->play.count >= play_blksize) {
914: vc->play.count -= play_blksize;
915: (*vc->play.intr)(vc->play.arg);
916: }
917: }
918: if (vc->rec.active) {
919: rec_blksize = vc->rec.blksize;
920: rec_bufsize = vc->rec.bufsize;
921: pos = esa_get_pointer(sc, &vc->rec)
922: % rec_bufsize;
923: diff = (rec_bufsize + pos - vc->rec.pos)
924: % rec_bufsize;
925: vc->rec.pos = pos;
926: vc->rec.count += diff;
927: while(vc->rec.count >= rec_blksize) {
928: vc->rec.count -= rec_blksize;
929: (*vc->rec.intr)(vc->rec.arg);
930: }
931: }
932: }
933: }
934: }
935: }
936:
937: return (1);
938: }
939:
940: int
941: esa_allocmem(struct esa_softc *sc, size_t size, size_t align,
942: struct esa_dma *p)
943: {
944: int error;
945:
946: p->size = size;
947: error = bus_dmamem_alloc(sc->sc_dmat, p->size, align, 0,
948: p->segs, sizeof(p->segs) / sizeof(p->segs[0]),
949: &p->nsegs, BUS_DMA_NOWAIT);
950: if (error)
951: return (error);
952:
953: error = bus_dmamem_map(sc->sc_dmat, p->segs, p->nsegs, p->size,
954: &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
955: if (error)
956: goto free;
957:
958: error = bus_dmamap_create(sc->sc_dmat, p->size, 1, p->size, 0,
959: BUS_DMA_NOWAIT, &p->map);
960: if (error)
961: goto unmap;
962:
963: error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, p->size, NULL,
964: BUS_DMA_NOWAIT);
965: if (error)
966: goto destroy;
967:
968: return (0);
969:
970: destroy:
971: bus_dmamap_destroy(sc->sc_dmat, p->map);
972: unmap:
973: bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
974: free:
975: bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs);
976:
977: return (error);
978: }
979:
980: int
981: esa_freemem(struct esa_softc *sc, struct esa_dma *p)
982: {
983:
984: bus_dmamap_unload(sc->sc_dmat, p->map);
985: bus_dmamap_destroy(sc->sc_dmat, p->map);
986: bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
987: bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs);
988:
989: return (0);
990: }
991:
992: /*
993: * Supporting Subroutines
994: */
995: const struct pci_matchid esa_devices[] = {
996: { PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_ES1989 },
997: { PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO3 },
998: { PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO3_2 },
999: };
1000:
1001: int
1002: esa_match(struct device *dev, void *match, void *aux)
1003: {
1004: return (pci_matchbyid((struct pci_attach_args *)aux, esa_devices,
1005: sizeof(esa_devices)/sizeof(esa_devices[0])));
1006: }
1007:
1008: void
1009: esa_attach(struct device *parent, struct device *self, void *aux)
1010: {
1011: struct esa_softc *sc = (struct esa_softc *)self;
1012: struct pci_attach_args *pa = (struct pci_attach_args *)aux;
1013: pcitag_t tag = pa->pa_tag;
1014: pci_chipset_tag_t pc = pa->pa_pc;
1015: pci_intr_handle_t ih;
1016: struct esa_card_type *card;
1017: const char *intrstr;
1018: int i, len;
1019:
1020: for (card = esa_card_types; card->pci_vendor_id; card++)
1021: if (PCI_VENDOR(pa->pa_id) == card->pci_vendor_id &&
1022: PCI_PRODUCT(pa->pa_id) == card->pci_product_id) {
1023: sc->type = card->type;
1024: sc->delay1 = card->delay1;
1025: sc->delay2 = card->delay2;
1026: break;
1027: }
1028:
1029: /* Map I/O register */
1030: if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
1031: &sc->sc_iot, &sc->sc_ioh, &sc->sc_iob, &sc->sc_ios, 0)) {
1032: printf(": can't map i/o space\n");
1033: return;
1034: }
1035:
1036: /* Initialize softc */
1037: sc->sc_tag = tag;
1038: sc->sc_pct = pc;
1039: sc->sc_dmat = pa->pa_dmat;
1040:
1041: /* Map and establish an interrupt */
1042: if (pci_intr_map(pa, &ih)) {
1043: printf(": can't map interrupt\n");
1044: bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
1045: return;
1046: }
1047: intrstr = pci_intr_string(pc, ih);
1048: sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, esa_intr, self,
1049: sc->sc_dev.dv_xname);
1050: if (sc->sc_ih == NULL) {
1051: printf(": can't establish interrupt");
1052: if (intrstr != NULL)
1053: printf(" at %s", intrstr);
1054: printf("\n");
1055: bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
1056: return;
1057: }
1058: printf(": %s\n", intrstr);
1059:
1060: /* Power up chip */
1061: esa_power(sc, PCI_PMCSR_STATE_D0);
1062:
1063: /* Init chip */
1064: if (esa_init(sc) == -1) {
1065: printf("%s: esa_attach: unable to initialize the card\n",
1066: sc->sc_dev.dv_xname);
1067: pci_intr_disestablish(pc, sc->sc_ih);
1068: bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
1069: return;
1070: }
1071:
1072: /* create suspend save area */
1073: len = sizeof(u_int16_t) * (ESA_REV_B_CODE_MEMORY_LENGTH
1074: + ESA_REV_B_DATA_MEMORY_LENGTH + 1);
1075: sc->savemem = (u_int16_t *)malloc(len, M_DEVBUF, M_NOWAIT);
1076: if (sc->savemem == NULL) {
1077: printf("%s: unable to allocate suspend buffer\n",
1078: sc->sc_dev.dv_xname);
1079: pci_intr_disestablish(pc, sc->sc_ih);
1080: bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
1081: return;
1082: }
1083: bzero(sc->savemem, len);
1084:
1085: /*
1086: * Every card I've seen has had their channels swapped with respect
1087: * to the mixer. Ie:
1088: * $ mixerctl -w outputs.master=0,191
1089: * Would result in the _right_ speaker being turned off.
1090: *
1091: * So, we will swap the left and right mixer channels to compensate
1092: * for this.
1093: */
1094: sc->codec_flags |= AC97_HOST_SWAPPED_CHANNELS;
1095: sc->codec_flags |= AC97_HOST_DONT_READ;
1096:
1097: /* Attach AC97 host interface */
1098: sc->host_if.arg = self;
1099: sc->host_if.attach = esa_attach_codec;
1100: sc->host_if.read = esa_read_codec;
1101: sc->host_if.write = esa_write_codec;
1102: sc->host_if.reset = esa_reset_codec;
1103: sc->host_if.flags = esa_flags_codec;
1104:
1105: if (ac97_attach(&sc->host_if) != 0) {
1106: pci_intr_disestablish(pc, sc->sc_ih);
1107: bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
1108: free(sc->savemem, M_DEVBUF);
1109: return;
1110: }
1111:
1112: /* initialize list management structures */
1113: sc->mixer_list.mem_addr = ESA_KDATA_MIXER_XFER0;
1114: sc->mixer_list.max = ESA_MAX_VIRTUAL_MIXER_CHANNELS;
1115: sc->adc1_list.mem_addr = ESA_KDATA_ADC1_XFER0;
1116: sc->adc1_list.max = ESA_MAX_VIRTUAL_ADC1_CHANNELS;
1117: sc->dma_list.mem_addr = ESA_KDATA_DMA_XFER0;
1118: sc->dma_list.max = ESA_MAX_VIRTUAL_DMA_CHANNELS;
1119: sc->msrc_list.mem_addr = ESA_KDATA_INSTANCE0_MINISRC;
1120: sc->msrc_list.max = ESA_MAX_INSTANCE_MINISRC;
1121:
1122: /* initialize index maps */
1123: for (i = 0; i < ESA_NUM_VOICES * 2; i++) {
1124: sc->mixer_list.indexmap[i] = -1;
1125: sc->msrc_list.indexmap[i] = -1;
1126: sc->dma_list.indexmap[i] = -1;
1127: sc->adc1_list.indexmap[i] = -1;
1128: }
1129: for (i = 0; i < ESA_NUM_VOICES; i++) {
1130: sc->voice[i].parent = (struct device *)sc;
1131: sc->voice[i].index = i;
1132: sc->sc_audiodev[i] =
1133: audio_attach_mi(&esa_hw_if, &sc->voice[i], &sc->sc_dev);
1134: }
1135:
1136: sc->powerhook = powerhook_establish(esa_powerhook, sc);
1137: if (sc->powerhook == NULL)
1138: printf("%s: WARNING: unable to establish powerhook\n",
1139: sc->sc_dev.dv_xname);
1140:
1141: return;
1142: }
1143:
1144: int
1145: esa_detach(struct device *self, int flags)
1146: {
1147: struct esa_softc *sc = (struct esa_softc *)self;
1148: int i;
1149:
1150: for (i = 0; i < ESA_NUM_VOICES; i++) {
1151: if (sc->sc_audiodev[i] != NULL)
1152: config_detach(sc->sc_audiodev[i], flags);
1153: }
1154:
1155: if (sc->sc_ih != NULL)
1156: pci_intr_disestablish(sc->sc_pct, sc->sc_ih);
1157: if (sc->sc_ios)
1158: bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
1159:
1160: free(sc->savemem, M_DEVBUF);
1161:
1162: return (0);
1163: }
1164:
1165: u_int16_t
1166: esa_read_assp(struct esa_softc *sc, u_int16_t region, u_int16_t index)
1167: {
1168: u_int16_t data;
1169: bus_space_tag_t iot = sc->sc_iot;
1170: bus_space_handle_t ioh = sc->sc_ioh;
1171:
1172: bus_space_write_2(iot, ioh, ESA_DSP_PORT_MEMORY_TYPE,
1173: region & ESA_MEMTYPE_MASK);
1174: bus_space_write_2(iot, ioh, ESA_DSP_PORT_MEMORY_INDEX, index);
1175: data = bus_space_read_2(iot, ioh, ESA_DSP_PORT_MEMORY_DATA);
1176:
1177: return (data);
1178: }
1179:
1180: void
1181: esa_write_assp(struct esa_softc *sc, u_int16_t region, u_int16_t index,
1182: u_int16_t data)
1183: {
1184: bus_space_tag_t iot = sc->sc_iot;
1185: bus_space_handle_t ioh = sc->sc_ioh;
1186:
1187: bus_space_write_2(iot, ioh, ESA_DSP_PORT_MEMORY_TYPE,
1188: region & ESA_MEMTYPE_MASK);
1189: bus_space_write_2(iot, ioh, ESA_DSP_PORT_MEMORY_INDEX, index);
1190: bus_space_write_2(iot, ioh, ESA_DSP_PORT_MEMORY_DATA, data);
1191:
1192: return;
1193: }
1194:
1195: int
1196: esa_init_codec(struct esa_softc *sc)
1197: {
1198: bus_space_tag_t iot = sc->sc_iot;
1199: bus_space_handle_t ioh = sc->sc_ioh;
1200: u_int32_t data;
1201:
1202: data = bus_space_read_1(iot, ioh, ESA_CODEC_COMMAND);
1203:
1204: return ((data & 0x1) ? 0 : 1);
1205: }
1206:
1207: int
1208: esa_attach_codec(void *aux, struct ac97_codec_if *codec_if)
1209: {
1210: struct esa_softc *sc = aux;
1211:
1212: sc->codec_if = codec_if;
1213:
1214: return (0);
1215: }
1216:
1217: int
1218: esa_read_codec(void *aux, u_int8_t reg, u_int16_t *result)
1219: {
1220: struct esa_softc *sc = aux;
1221: bus_space_tag_t iot = sc->sc_iot;
1222: bus_space_handle_t ioh = sc->sc_ioh;
1223:
1224: if (esa_wait(sc))
1225: printf("%s: esa_read_codec: timed out\n", sc->sc_dev.dv_xname);
1226: bus_space_write_1(iot, ioh, ESA_CODEC_COMMAND, (reg & 0x7f) | 0x80);
1227: delay(50);
1228: if (esa_wait(sc))
1229: printf("%s: esa_read_codec: timed out\n", sc->sc_dev.dv_xname);
1230: *result = bus_space_read_2(iot, ioh, ESA_CODEC_DATA);
1231:
1232: return (0);
1233: }
1234:
1235: int
1236: esa_write_codec(void *aux, u_int8_t reg, u_int16_t data)
1237: {
1238: struct esa_softc *sc = aux;
1239: bus_space_tag_t iot = sc->sc_iot;
1240: bus_space_handle_t ioh = sc->sc_ioh;
1241:
1242: if (esa_wait(sc)) {
1243: printf("%s: esa_write_codec: timed out\n", sc->sc_dev.dv_xname);
1244: return (-1);
1245: }
1246: bus_space_write_2(iot, ioh, ESA_CODEC_DATA, data);
1247: bus_space_write_1(iot, ioh, ESA_CODEC_COMMAND, reg & 0x7f);
1248: delay(50);
1249:
1250: return (0);
1251: }
1252:
1253: void
1254: esa_reset_codec(void *aux)
1255: {
1256:
1257: return;
1258: }
1259:
1260: enum ac97_host_flags
1261: esa_flags_codec(void *aux)
1262: {
1263: struct esa_softc *sc = aux;
1264:
1265: return (sc->codec_flags);
1266: }
1267:
1268: int
1269: esa_wait(struct esa_softc *sc)
1270: {
1271: int i, val;
1272: bus_space_tag_t iot = sc->sc_iot;
1273: bus_space_handle_t ioh = sc->sc_ioh;
1274:
1275: for (i = 0; i < 20; i++) {
1276: val = bus_space_read_1(iot, ioh, ESA_CODEC_STATUS);
1277: if ((val & 1) == 0)
1278: return (0);
1279: delay(2);
1280: }
1281:
1282: return (-1);
1283: }
1284:
1285: int
1286: esa_init(struct esa_softc *sc)
1287: {
1288: struct esa_voice *vc;
1289: bus_space_tag_t iot = sc->sc_iot;
1290: bus_space_handle_t ioh = sc->sc_ioh;
1291: pcitag_t tag = sc->sc_tag;
1292: pci_chipset_tag_t pc = sc->sc_pct;
1293: u_int32_t data, i, size;
1294: u_int8_t reset_state;
1295: int data_bytes = (((ESA_MINISRC_TMP_BUFFER_SIZE & ~1) +
1296: (ESA_MINISRC_IN_BUFFER_SIZE & ~1) +
1297: (ESA_MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255)
1298: &~ 255;
1299:
1300: /* Disable legacy emulation */
1301: data = pci_conf_read(pc, tag, PCI_LEGACY_AUDIO_CTRL);
1302: data |= DISABLE_LEGACY;
1303: pci_conf_write(pc, tag, PCI_LEGACY_AUDIO_CTRL, data);
1304:
1305: esa_config(sc);
1306:
1307: reset_state = esa_assp_halt(sc);
1308:
1309: esa_init_codec(sc);
1310: esa_codec_reset(sc);
1311:
1312: /* Zero kernel and mixer data */
1313: size = ESA_REV_B_DATA_MEMORY_UNIT_LENGTH * ESA_NUM_UNITS_KERNEL_DATA;
1314: for (i = 0; i < size / 2; i++) {
1315: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
1316: ESA_KDATA_BASE_ADDR + i, 0);
1317: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
1318: ESA_KDATA_BASE_ADDR2 + i, 0);
1319: }
1320:
1321: /* Init DMA pointer */
1322: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, ESA_KDATA_CURRENT_DMA,
1323: ESA_KDATA_DMA_XFER0);
1324:
1325: /* Write kernel code into memory */
1326: size = sizeof(esa_assp_kernel_image);
1327: for (i = 0; i < size / 2; i++)
1328: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_CODE,
1329: ESA_REV_B_CODE_MEMORY_BEGIN + i, esa_assp_kernel_image[i]);
1330:
1331: size = sizeof(esa_assp_minisrc_image);
1332: for (i = 0; i < size / 2; i++)
1333: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_CODE, 0x400 + i,
1334: esa_assp_minisrc_image[i]);
1335:
1336: /* Write the coefficients for the low pass filter */
1337: size = sizeof(esa_minisrc_lpf_image);
1338: for (i = 0; i < size / 2; i++)
1339: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_CODE,
1340: 0x400 + ESA_MINISRC_COEF_LOC + i, esa_minisrc_lpf_image[i]);
1341: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_CODE,
1342: 0x400 + ESA_MINISRC_COEF_LOC + size, 0x8000);
1343: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, ESA_KDATA_TASK0, 0x400);
1344: /* Init the mixer number */
1345: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
1346: ESA_KDATA_MIXER_TASK_NUMBER, 0);
1347: /* Extreme kernel master volume */
1348: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
1349: ESA_KDATA_DAC_LEFT_VOLUME, ESA_ARB_VOLUME);
1350: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
1351: ESA_KDATA_DAC_RIGHT_VOLUME, ESA_ARB_VOLUME);
1352:
1353: if (esa_amp_enable(sc))
1354: return (-1);
1355:
1356: /* Zero entire DAC/ADC area */
1357: for (i = 0x1100; i < 0x1c00; i++)
1358: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, i, 0);
1359:
1360: /* set some sane defaults */
1361: for (i = 0; i < ESA_NUM_VOICES; i++) {
1362: vc = &sc->voice[i];
1363: vc->play.data_offset = ESA_DAC_DATA + (data_bytes * i);
1364: vc->rec.data_offset = ESA_DAC_DATA + (data_bytes * i * 2);
1365: }
1366:
1367: esa_enable_interrupts(sc);
1368:
1369: bus_space_write_1(iot, ioh, ESA_DSP_PORT_CONTROL_REG_B,
1370: reset_state | ESA_REGB_ENABLE_RESET);
1371:
1372: return (0);
1373: }
1374:
1375: void
1376: esa_config(struct esa_softc *sc)
1377: {
1378: bus_space_tag_t iot = sc->sc_iot;
1379: bus_space_handle_t ioh = sc->sc_ioh;
1380: pcitag_t tag = sc->sc_tag;
1381: pci_chipset_tag_t pc = sc->sc_pct;
1382: u_int32_t data;
1383:
1384: data = pci_conf_read(pc, tag, ESA_PCI_ALLEGRO_CONFIG);
1385: data &= ESA_REDUCED_DEBOUNCE;
1386: data |= ESA_PM_CTRL_ENABLE | ESA_CLK_DIV_BY_49 | ESA_USE_PCI_TIMING;
1387: pci_conf_write(pc, tag, ESA_PCI_ALLEGRO_CONFIG, data);
1388:
1389: bus_space_write_1(iot, ioh, ESA_ASSP_CONTROL_B, ESA_RESET_ASSP);
1390: data = pci_conf_read(pc, tag, ESA_PCI_ALLEGRO_CONFIG);
1391: data &= ~ESA_INT_CLK_SELECT;
1392: if (sc->type == ESS_MAESTRO3) {
1393: data &= ~ESA_INT_CLK_MULT_ENABLE;
1394: data |= ESA_INT_CLK_SRC_NOT_PCI;
1395: }
1396: data &= ~(ESA_CLK_MULT_MODE_SELECT | ESA_CLK_MULT_MODE_SELECT_2);
1397: pci_conf_write(pc, tag, ESA_PCI_ALLEGRO_CONFIG, data);
1398:
1399: if (sc->type == ESS_ALLEGRO1) {
1400: data = pci_conf_read(pc, tag, ESA_PCI_USER_CONFIG);
1401: data |= ESA_IN_CLK_12MHZ_SELECT;
1402: pci_conf_write(pc, tag, ESA_PCI_USER_CONFIG, data);
1403: }
1404:
1405: data = bus_space_read_1(iot, ioh, ESA_ASSP_CONTROL_A);
1406: data &= ~(ESA_DSP_CLK_36MHZ_SELECT | ESA_ASSP_CLK_49MHZ_SELECT);
1407: data |= ESA_ASSP_CLK_49MHZ_SELECT; /* XXX: Assumes 49MHz DSP */
1408: data |= ESA_ASSP_0_WS_ENABLE;
1409: bus_space_write_1(iot, ioh, ESA_ASSP_CONTROL_A, data);
1410:
1411: bus_space_write_1(iot, ioh, ESA_ASSP_CONTROL_B, ESA_RUN_ASSP);
1412:
1413: return;
1414: }
1415:
1416: u_int8_t
1417: esa_assp_halt(struct esa_softc *sc)
1418: {
1419: bus_space_tag_t iot = sc->sc_iot;
1420: bus_space_handle_t ioh = sc->sc_ioh;
1421: u_int8_t data, reset_state;
1422:
1423: data = bus_space_read_1(iot, ioh, ESA_DSP_PORT_CONTROL_REG_B);
1424: reset_state = data & ~ESA_REGB_STOP_CLOCK;
1425: delay(10000); /* XXX use tsleep */
1426: bus_space_write_1(iot, ioh, ESA_DSP_PORT_CONTROL_REG_B,
1427: reset_state & ~ESA_REGB_ENABLE_RESET);
1428: delay(10000); /* XXX use tsleep */
1429:
1430: return (reset_state);
1431: }
1432:
1433: void
1434: esa_codec_reset(struct esa_softc *sc)
1435: {
1436: bus_space_tag_t iot = sc->sc_iot;
1437: bus_space_handle_t ioh = sc->sc_ioh;
1438: u_int16_t data, dir;
1439: int retry = 0;
1440:
1441: do {
1442: data = bus_space_read_2(iot, ioh, ESA_GPIO_DIRECTION);
1443: dir = data | 0x10; /* assuming pci bus master? */
1444:
1445: /* remote codec config */
1446: data = bus_space_read_2(iot, ioh, ESA_RING_BUS_CTRL_B);
1447: bus_space_write_2(iot, ioh, ESA_RING_BUS_CTRL_B,
1448: data & ~ESA_SECOND_CODEC_ID_MASK);
1449: data = bus_space_read_2(iot, ioh, ESA_SDO_OUT_DEST_CTRL);
1450: bus_space_write_2(iot, ioh, ESA_SDO_OUT_DEST_CTRL,
1451: data & ~ESA_COMMAND_ADDR_OUT);
1452: data = bus_space_read_2(iot, ioh, ESA_SDO_IN_DEST_CTRL);
1453: bus_space_write_2(iot, ioh, ESA_SDO_IN_DEST_CTRL,
1454: data & ~ESA_STATUS_ADDR_IN);
1455:
1456: bus_space_write_2(iot, ioh, ESA_RING_BUS_CTRL_A,
1457: ESA_IO_SRAM_ENABLE);
1458: delay(20);
1459:
1460: bus_space_write_2(iot, ioh, ESA_GPIO_DIRECTION,
1461: dir & ~ESA_GPO_PRIMARY_AC97);
1462: bus_space_write_2(iot, ioh, ESA_GPIO_MASK,
1463: ~ESA_GPO_PRIMARY_AC97);
1464: bus_space_write_2(iot, ioh, ESA_GPIO_DATA, 0);
1465: bus_space_write_2(iot, ioh, ESA_GPIO_DIRECTION,
1466: dir | ESA_GPO_PRIMARY_AC97);
1467: delay(sc->delay1 * 1000);
1468: bus_space_write_2(iot, ioh, ESA_GPIO_DATA,
1469: ESA_GPO_PRIMARY_AC97);
1470: delay(5);
1471: bus_space_write_2(iot, ioh, ESA_RING_BUS_CTRL_A,
1472: ESA_IO_SRAM_ENABLE | ESA_SERIAL_AC_LINK_ENABLE);
1473: bus_space_write_2(iot, ioh, ESA_GPIO_MASK, ~0);
1474: delay(sc->delay2 * 1000);
1475:
1476: esa_read_codec(sc, 0x7c, &data);
1477: if ((data == 0) || (data == 0xffff)) {
1478: retry++;
1479: if (retry > 3) {
1480: printf("%s: esa_codec_reset: failed\n",
1481: sc->sc_dev.dv_xname);
1482: break;
1483: }
1484: printf("%s: esa_codec_reset: retrying\n",
1485: sc->sc_dev.dv_xname);
1486: } else
1487: retry = 0;
1488: } while (retry);
1489:
1490: return;
1491: }
1492:
1493: int
1494: esa_amp_enable(struct esa_softc *sc)
1495: {
1496: bus_space_tag_t iot = sc->sc_iot;
1497: bus_space_handle_t ioh = sc->sc_ioh;
1498: u_int32_t gpo, polarity_port, polarity;
1499: u_int16_t data;
1500:
1501: switch (sc->type) {
1502: case ESS_ALLEGRO1:
1503: polarity_port = 0x1800;
1504: break;
1505: case ESS_MAESTRO3:
1506: polarity_port = 0x1100;
1507: break;
1508: default:
1509: printf("%s: esa_amp_enable: Unknown chip type!!!\n",
1510: sc->sc_dev.dv_xname);
1511: return (1);
1512: }
1513:
1514: gpo = (polarity_port >> 8) & 0x0f;
1515: polarity = polarity_port >> 12;
1516: polarity = !polarity; /* Enable */
1517: polarity = polarity << gpo;
1518: gpo = 1 << gpo;
1519: bus_space_write_2(iot, ioh, ESA_GPIO_MASK, ~gpo);
1520: data = bus_space_read_2(iot, ioh, ESA_GPIO_DIRECTION);
1521: bus_space_write_2(iot, ioh, ESA_GPIO_DIRECTION, data | gpo);
1522: data = ESA_GPO_SECONDARY_AC97 | ESA_GPO_PRIMARY_AC97 | polarity;
1523: bus_space_write_2(iot, ioh, ESA_GPIO_DATA, data);
1524: bus_space_write_2(iot, ioh, ESA_GPIO_MASK, ~0);
1525:
1526: return (0);
1527: }
1528:
1529: void
1530: esa_enable_interrupts(struct esa_softc *sc)
1531: {
1532: bus_space_tag_t iot = sc->sc_iot;
1533: bus_space_handle_t ioh = sc->sc_ioh;
1534: u_int8_t data;
1535:
1536: bus_space_write_2(iot, ioh, ESA_HOST_INT_CTRL,
1537: ESA_ASSP_INT_ENABLE | ESA_HV_INT_ENABLE);
1538: data = bus_space_read_1(iot, ioh, ESA_ASSP_CONTROL_C);
1539: bus_space_write_1(iot, ioh, ESA_ASSP_CONTROL_C,
1540: data | ESA_ASSP_HOST_INT_ENABLE);
1541: }
1542:
1543: /*
1544: * List management
1545: */
1546: int
1547: esa_add_list(struct esa_voice *vc, struct esa_list *el,
1548: u_int16_t val, int index)
1549: {
1550: struct esa_softc *sc = (struct esa_softc *)vc->parent;
1551:
1552: el->indexmap[index] = el->currlen;
1553: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
1554: el->mem_addr + el->currlen,
1555: val);
1556:
1557: return (el->currlen++);
1558: }
1559:
1560: void
1561: esa_remove_list(struct esa_voice *vc, struct esa_list *el, int index)
1562: {
1563: struct esa_softc *sc = (struct esa_softc *)vc->parent;
1564: u_int16_t val;
1565: int lastindex = el->currlen - 1;
1566: int vindex = el->indexmap[index];
1567: int i;
1568:
1569: /* reset our virtual index */
1570: el->indexmap[index] = -1;
1571:
1572: if (vindex != lastindex) {
1573: val = esa_read_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
1574: el->mem_addr + lastindex);
1575: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
1576: el->mem_addr + vindex,
1577: val);
1578: for (i = 0; i < ESA_NUM_VOICES * 2; i++)
1579: if (el->indexmap[i] == lastindex)
1580: break;
1581: if (i >= ESA_NUM_VOICES * 2)
1582: printf("%s: esa_remove_list: invalid task index\n",
1583: sc->sc_dev.dv_xname);
1584: else
1585: el->indexmap[i] = vindex;
1586: }
1587:
1588: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA,
1589: el->mem_addr + lastindex, 0);
1590: el->currlen--;
1591:
1592: return;
1593: }
1594:
1595: int
1596: esa_power(struct esa_softc *sc, int state)
1597: {
1598: pcitag_t tag = sc->sc_tag;
1599: pci_chipset_tag_t pc = sc->sc_pct;
1600: pcireg_t data;
1601: int pmcapreg;
1602:
1603: if (pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &pmcapreg, 0)) {
1604: data = pci_conf_read(pc, tag, pmcapreg + PCI_PMCSR);
1605: if ((data & PCI_PMCSR_STATE_MASK) != state)
1606: pci_conf_write(pc, tag, pmcapreg + PCI_PMCSR, state);
1607: }
1608:
1609: return (0);
1610: }
1611:
1612: void
1613: esa_powerhook(int why, void *hdl)
1614: {
1615: struct esa_softc *sc = (struct esa_softc *)hdl;
1616:
1617: switch (why) {
1618: case PWR_SUSPEND:
1619: case PWR_STANDBY:
1620: esa_suspend(sc);
1621: break;
1622: case PWR_RESUME:
1623: esa_resume(sc);
1624: (sc->codec_if->vtbl->restore_ports)(sc->codec_if);
1625: break;
1626: }
1627: }
1628:
1629: int
1630: esa_suspend(struct esa_softc *sc)
1631: {
1632: bus_space_tag_t iot = sc->sc_iot;
1633: bus_space_handle_t ioh = sc->sc_ioh;
1634: int i, index;
1635:
1636: index = 0;
1637:
1638: bus_space_write_2(iot, ioh, ESA_HOST_INT_CTRL, 0);
1639: bus_space_write_1(iot, ioh, ESA_ASSP_CONTROL_C, 0);
1640:
1641: esa_assp_halt(sc);
1642:
1643: /* Save ASSP state */
1644: for (i = ESA_REV_B_CODE_MEMORY_BEGIN; i <= ESA_REV_B_CODE_MEMORY_END;
1645: i++)
1646: sc->savemem[index++] = esa_read_assp(sc,
1647: ESA_MEMTYPE_INTERNAL_CODE, i);
1648: for (i = ESA_REV_B_DATA_MEMORY_BEGIN; i <= ESA_REV_B_DATA_MEMORY_END;
1649: i++)
1650: sc->savemem[index++] = esa_read_assp(sc,
1651: ESA_MEMTYPE_INTERNAL_DATA, i);
1652:
1653: esa_power(sc, PCI_PMCSR_STATE_D3);
1654:
1655: return (0);
1656: }
1657:
1658: int
1659: esa_resume(struct esa_softc *sc) {
1660: bus_space_tag_t iot = sc->sc_iot;
1661: bus_space_handle_t ioh = sc->sc_ioh;
1662: int i, index;
1663: u_int8_t reset_state;
1664:
1665: index = 0;
1666:
1667: esa_power(sc, PCI_PMCSR_STATE_D0);
1668: delay(10000);
1669:
1670: esa_config(sc);
1671:
1672: reset_state = esa_assp_halt(sc);
1673:
1674: esa_codec_reset(sc);
1675:
1676: /* restore ASSP */
1677: for (i = ESA_REV_B_CODE_MEMORY_BEGIN; i <= ESA_REV_B_CODE_MEMORY_END;
1678: i++)
1679: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_CODE, i,
1680: sc->savemem[index++]);
1681: for (i = ESA_REV_B_DATA_MEMORY_BEGIN; i <= ESA_REV_B_DATA_MEMORY_END;
1682: i++)
1683: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, i,
1684: sc->savemem[index++]);
1685:
1686: esa_write_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, ESA_KDATA_DMA_ACTIVE, 0);
1687: bus_space_write_1(iot, ioh, ESA_DSP_PORT_CONTROL_REG_B,
1688: reset_state | ESA_REGB_ENABLE_RESET);
1689:
1690: esa_enable_interrupts(sc);
1691: esa_amp_enable(sc);
1692:
1693: return (0);
1694: }
1695:
1696: u_int32_t
1697: esa_get_pointer(struct esa_softc *sc, struct esa_channel *ch)
1698: {
1699: u_int16_t hi = 0, lo = 0;
1700: u_int32_t addr;
1701: int data_offset = ch->data_offset;
1702:
1703: hi = esa_read_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, data_offset +
1704: ESA_CDATA_HOST_SRC_CURRENTH);
1705: lo = esa_read_assp(sc, ESA_MEMTYPE_INTERNAL_DATA, data_offset +
1706: ESA_CDATA_HOST_SRC_CURRENTL);
1707:
1708: addr = lo | ((u_int32_t)hi << 16);
1709: return (addr - ch->start);
1710: }
1711:
1712: paddr_t
1713: esa_mappage(void *addr, void *mem, off_t off, int prot)
1714: {
1715: struct esa_voice *vc = addr;
1716: struct esa_softc *sc = (struct esa_softc *)vc->parent;
1717: struct esa_dma *p;
1718:
1719: if (off < 0)
1720: return (-1);
1721: for (p = vc->dma; p && KERNADDR(p) != mem; p = p->next)
1722: ;
1723: if (!p)
1724: return (-1);
1725: return (bus_dmamem_mmap(sc->sc_dmat, p->segs, p->nsegs,
1726: off, prot, BUS_DMA_WAITOK));
1727: }
CVSweb