Annotation of sys/dev/pci/yds.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: yds.c,v 1.28 2007/01/06 02:48:40 deraadt Exp $ */
2: /* $NetBSD: yds.c,v 1.5 2001/05/21 23:55:04 minoura Exp $ */
3:
4: /*
5: * Copyright (c) 2000, 2001 Kazuki Sakamoto and Minoura Makoto.
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. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29: /*
30: * Yamaha YMF724[B-F]/740[B-C]/744/754
31: *
32: * Documentation links:
33: * - ftp://ftp.alsa-project.org/pub/manuals/yamaha/
34: * - ftp://ftp.alsa-project.org/pub/manuals/yamaha/pci/
35: *
36: * TODO:
37: * - FM synth volume (difficult: mixed before ac97)
38: * - Digital in/out (SPDIF) support
39: * - Effect??
40: */
41:
42: #include <sys/param.h>
43: #include <sys/systm.h>
44: #include <sys/kernel.h>
45: #include <sys/fcntl.h>
46: #include <sys/malloc.h>
47: #include <sys/device.h>
48: #include <sys/proc.h>
49: #include <sys/queue.h>
50: #include <sys/fcntl.h>
51:
52: #include <dev/pci/pcidevs.h>
53: #include <dev/pci/pcireg.h>
54: #include <dev/pci/pcivar.h>
55:
56: #include <sys/audioio.h>
57: #include <dev/audio_if.h>
58: #include <dev/midi_if.h>
59: #include <dev/mulaw.h>
60: #include <dev/auconv.h>
61: #include <dev/ic/ac97.h>
62: #include <dev/ic/mpuvar.h>
63:
64: #include <machine/bus.h>
65: #include <machine/intr.h>
66:
67: #include <dev/pci/ydsreg.h>
68: #include <dev/pci/ydsvar.h>
69:
70: /* Debug */
71: #undef YDS_USE_REC_SLOT
72: #define YDS_USE_P44
73:
74: #ifdef AUDIO_DEBUG
75: # define DPRINTF(x) if (ydsdebug) printf x
76: # define DPRINTFN(n,x) if (ydsdebug>(n)) printf x
77: int ydsdebug = 0;
78: #else
79: # define DPRINTF(x)
80: # define DPRINTFN(n,x)
81: #endif
82: #ifdef YDS_USE_REC_SLOT
83: # define YDS_INPUT_SLOT 0 /* REC slot = ADC + loopbacks */
84: #else
85: # define YDS_INPUT_SLOT 1 /* ADC slot */
86: #endif
87:
88: static int ac97_id2;
89:
90: int yds_match(struct device *, void *, void *);
91: void yds_attach(struct device *, struct device *, void *);
92: int yds_intr(void *);
93:
94: static void nswaph(u_int32_t *p, int wcount);
95:
96: #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
97: #define KERNADDR(p) ((void *)((p)->addr))
98:
99: int yds_allocmem(struct yds_softc *, size_t, size_t,
100: struct yds_dma *);
101: int yds_freemem(struct yds_softc *, struct yds_dma *);
102:
103: #ifndef AUDIO_DEBUG
104: #define YWRITE1(sc, r, x) bus_space_write_1((sc)->memt, (sc)->memh, (r), (x))
105: #define YWRITE2(sc, r, x) bus_space_write_2((sc)->memt, (sc)->memh, (r), (x))
106: #define YWRITE4(sc, r, x) bus_space_write_4((sc)->memt, (sc)->memh, (r), (x))
107: #define YREAD1(sc, r) bus_space_read_1((sc)->memt, (sc)->memh, (r))
108: #define YREAD2(sc, r) bus_space_read_2((sc)->memt, (sc)->memh, (r))
109: #define YREAD4(sc, r) bus_space_read_4((sc)->memt, (sc)->memh, (r))
110: #else
111:
112: u_int16_t YREAD2(struct yds_softc *sc,bus_size_t r);
113: u_int32_t YREAD4(struct yds_softc *sc,bus_size_t r);
114: void YWRITE1(struct yds_softc *sc,bus_size_t r,u_int8_t x);
115: void YWRITE2(struct yds_softc *sc,bus_size_t r,u_int16_t x);
116: void YWRITE4(struct yds_softc *sc,bus_size_t r,u_int32_t x);
117:
118: u_int16_t YREAD2(struct yds_softc *sc,bus_size_t r)
119: {
120: DPRINTFN(5, (" YREAD2(0x%lX)\n",(unsigned long)r));
121: return bus_space_read_2(sc->memt,sc->memh,r);
122: }
123: u_int32_t YREAD4(struct yds_softc *sc,bus_size_t r)
124: {
125: DPRINTFN(5, (" YREAD4(0x%lX)\n",(unsigned long)r));
126: return bus_space_read_4(sc->memt,sc->memh,r);
127: }
128: void YWRITE1(struct yds_softc *sc,bus_size_t r,u_int8_t x)
129: {
130: DPRINTFN(5, (" YWRITE1(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x));
131: bus_space_write_1(sc->memt,sc->memh,r,x);
132: }
133: void YWRITE2(struct yds_softc *sc,bus_size_t r,u_int16_t x)
134: {
135: DPRINTFN(5, (" YWRITE2(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x));
136: bus_space_write_2(sc->memt,sc->memh,r,x);
137: }
138: void YWRITE4(struct yds_softc *sc,bus_size_t r,u_int32_t x)
139: {
140: DPRINTFN(5, (" YWRITE4(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x));
141: bus_space_write_4(sc->memt,sc->memh,r,x);
142: }
143: #endif
144:
145: #define YWRITEREGION4(sc, r, x, c) \
146: bus_space_write_region_4((sc)->memt, (sc)->memh, (r), (x), (c) / 4)
147:
148: struct cfattach yds_ca = {
149: sizeof(struct yds_softc), yds_match, yds_attach
150: };
151:
152: struct cfdriver yds_cd = {
153: NULL, "yds", DV_DULL
154: };
155:
156: int yds_open(void *, int);
157: void yds_close(void *);
158: int yds_query_encoding(void *, struct audio_encoding *);
159: int yds_set_params(void *, int, int,
160: struct audio_params *, struct audio_params *);
161: int yds_round_blocksize(void *, int);
162: int yds_trigger_output(void *, void *, void *, int, void (*)(void *),
163: void *, struct audio_params *);
164: int yds_trigger_input(void *, void *, void *, int, void (*)(void *),
165: void *, struct audio_params *);
166: int yds_halt_output(void *);
167: int yds_halt_input(void *);
168: int yds_getdev(void *, struct audio_device *);
169: int yds_mixer_set_port(void *, mixer_ctrl_t *);
170: int yds_mixer_get_port(void *, mixer_ctrl_t *);
171: void *yds_malloc(void *, int, size_t, int, int);
172: void yds_free(void *, void *, int);
173: size_t yds_round_buffersize(void *, int, size_t);
174: paddr_t yds_mappage(void *, void *, off_t, int);
175: int yds_get_props(void *);
176: int yds_query_devinfo(void *addr, mixer_devinfo_t *dip);
177:
178: int yds_attach_codec(void *sc, struct ac97_codec_if *);
179: int yds_read_codec(void *sc, u_int8_t a, u_int16_t *d);
180: int yds_write_codec(void *sc, u_int8_t a, u_int16_t d);
181: void yds_reset_codec(void *sc);
182: int yds_get_portnum_by_name(struct yds_softc *, char *, char *,
183: char *);
184:
185: static u_int yds_get_dstype(int);
186: static int yds_download_mcode(struct yds_softc *);
187: static int yds_allocate_slots(struct yds_softc *);
188: static void yds_configure_legacy(struct yds_softc *arg);
189: static void yds_enable_dsp(struct yds_softc *);
190: static int yds_disable_dsp(struct yds_softc *);
191: static int yds_ready_codec(struct yds_codec_softc *);
192: static int yds_halt(struct yds_softc *);
193: static u_int32_t yds_get_lpfq(u_int);
194: static u_int32_t yds_get_lpfk(u_int);
195: static struct yds_dma *yds_find_dma(struct yds_softc *, void *);
196:
197: void yds_powerhook(int, void *);
198: int yds_init(void *sc);
199: void yds_attachhook(void *);
200:
201: #ifdef AUDIO_DEBUG
202: static void yds_dump_play_slot(struct yds_softc *, int);
203: #define YDS_DUMP_PLAY_SLOT(n,sc,bank) \
204: if (ydsdebug > (n)) yds_dump_play_slot(sc, bank)
205: #else
206: #define YDS_DUMP_PLAY_SLOT(n,sc,bank)
207: #endif /* AUDIO_DEBUG */
208:
209: static struct audio_hw_if yds_hw_if = {
210: yds_open,
211: yds_close,
212: NULL,
213: yds_query_encoding,
214: yds_set_params,
215: yds_round_blocksize,
216: NULL,
217: NULL,
218: NULL,
219: NULL,
220: NULL,
221: yds_halt_output,
222: yds_halt_input,
223: NULL,
224: yds_getdev,
225: NULL,
226: yds_mixer_set_port,
227: yds_mixer_get_port,
228: yds_query_devinfo,
229: yds_malloc,
230: yds_free,
231: yds_round_buffersize,
232: yds_mappage,
233: yds_get_props,
234: yds_trigger_output,
235: yds_trigger_input
236: };
237:
238: struct audio_device yds_device = {
239: "Yamaha DS-1",
240: "",
241: "yds"
242: };
243:
244: const static struct {
245: u_int id;
246: u_int flags;
247: #define YDS_CAP_MCODE_1 0x0001
248: #define YDS_CAP_MCODE_1E 0x0002
249: #define YDS_CAP_LEGACY_SELECTABLE 0x0004
250: #define YDS_CAP_LEGACY_FLEXIBLE 0x0008
251: #define YDS_CAP_HAS_P44 0x0010
252: #define YDS_CAP_LEGACY_SMOD_DISABLE 0x1000
253: } yds_chip_capability_list[] = {
254: { PCI_PRODUCT_YAMAHA_YMF724,
255: YDS_CAP_MCODE_1|YDS_CAP_LEGACY_SELECTABLE },
256: /* 740[C] has only 32 slots. But anyway we use only 2 */
257: { PCI_PRODUCT_YAMAHA_YMF740,
258: YDS_CAP_MCODE_1|YDS_CAP_LEGACY_SELECTABLE }, /* XXX NOT TESTED */
259: { PCI_PRODUCT_YAMAHA_YMF740C,
260: YDS_CAP_MCODE_1E|YDS_CAP_LEGACY_SELECTABLE },
261: { PCI_PRODUCT_YAMAHA_YMF724F,
262: YDS_CAP_MCODE_1E|YDS_CAP_LEGACY_SELECTABLE },
263: { PCI_PRODUCT_YAMAHA_YMF744,
264: YDS_CAP_MCODE_1E|YDS_CAP_LEGACY_FLEXIBLE },
265: { PCI_PRODUCT_YAMAHA_YMF754,
266: YDS_CAP_MCODE_1E|YDS_CAP_LEGACY_FLEXIBLE|YDS_CAP_HAS_P44 },
267: /* How about 734/737/738?? */
268: { 0, 0 }
269: };
270: #ifdef AUDIO_DEBUG
271: #define YDS_CAP_BITS "\020\005P44\004LEGFLEX\003LEGSEL\002MCODE1E\001MCODE1"
272: #endif
273:
274: #ifdef AUDIO_DEBUG
275: static void
276: yds_dump_play_slot(sc, bank)
277: struct yds_softc *sc;
278: int bank;
279: {
280: int i, j;
281: u_int32_t *p;
282: u_int32_t num;
283: struct yds_dma *dma;
284:
285: for (i = 0; i < N_PLAY_SLOTS; i++) {
286: printf("pbankp[%d] = %p,", i*2, sc->pbankp[i*2]);
287: printf("pbankp[%d] = %p\n", i*2+1, sc->pbankp[i*2+1]);
288: }
289:
290: p = (u_int32_t*)sc->ptbl;
291: for (i = 0; i < N_PLAY_SLOTS+1; i++) {
292: printf("ptbl + %d:0x%x\n", i, *p);
293: p++;
294: }
295:
296: num = *(u_int32_t*)sc->ptbl;
297: printf("num = %d\n", num);
298:
299: for (i = 0; i < num; i++) {
300:
301: p = (u_int32_t *)sc->pbankp[i];
302:
303: dma = yds_find_dma(sc,(void *)p);
304:
305: for (j = 0; j < sizeof(struct play_slot_ctrl_bank) /
306: sizeof(u_int32_t); j++) {
307: printf(" 0x%02x: 0x%08x\n",
308: (unsigned) (j * sizeof(u_int32_t)),
309: (unsigned) *p++);
310: }
311: /*
312: p = (u_int32_t *)sc->pbankp[i*2 + 1];
313: printf(" pbankp[%d] : %p\n", i*2 + 1, p);
314: for (j = 0; j < sizeof(struct play_slot_ctrl_bank) /
315: sizeof(u_int32_t); j++) {
316: printf(" 0x%02x: 0x%08x\n",
317: j * sizeof(u_int32_t), *p++);
318: delay(1);
319: }
320: */
321: }
322: }
323: #endif /* AUDIO_DEBUG */
324:
325: static u_int
326: yds_get_dstype(id)
327: int id;
328: {
329: int i;
330:
331: for (i = 0; yds_chip_capability_list[i].id; i++) {
332: if (PCI_PRODUCT(id) == yds_chip_capability_list[i].id)
333: return yds_chip_capability_list[i].flags;
334: }
335:
336: return -1;
337: }
338:
339: static void
340: nswaph(u_int32_t *p, int wcount)
341: {
342: for (; wcount; wcount -=4) {
343: *p = ntohl(*p);
344: p++;
345: }
346: }
347:
348: static int
349: yds_download_mcode(sc)
350: struct yds_softc *sc;
351: {
352: u_int ctrl;
353: const u_int32_t *p;
354: size_t size;
355: u_char *buf;
356: size_t buflen;
357: int error;
358: struct yds_firmware *yf;
359:
360: error = loadfirmware("yds", &buf, &buflen);
361: if (error)
362: return 1;
363: yf = (struct yds_firmware *)buf;
364:
365: if (sc->sc_flags & YDS_CAP_MCODE_1) {
366: p = (u_int32_t *)&yf->data[ntohl(yf->dsplen)];
367: size = ntohl(yf->ds1len);
368: } else if (sc->sc_flags & YDS_CAP_MCODE_1E) {
369: p = (u_int32_t *)&yf->data[ntohl(yf->dsplen) + ntohl(yf->ds1len)];
370: size = ntohl(yf->ds1elen);
371: } else {
372: free(buf, M_DEVBUF);
373: return 1; /* unknown */
374: }
375:
376: if (size > buflen) {
377: printf("%s: old firmware file, update please\n",
378: sc->sc_dev.dv_xname);
379: free(buf, M_DEVBUF);
380: return 1;
381: }
382:
383: if (yds_disable_dsp(sc)) {
384: free(buf, M_DEVBUF);
385: return 1;
386: }
387:
388: /* Software reset */
389: YWRITE4(sc, YDS_MODE, YDS_MODE_RESET);
390: YWRITE4(sc, YDS_MODE, 0);
391:
392: YWRITE4(sc, YDS_MAPOF_REC, 0);
393: YWRITE4(sc, YDS_MAPOF_EFFECT, 0);
394: YWRITE4(sc, YDS_PLAY_CTRLBASE, 0);
395: YWRITE4(sc, YDS_REC_CTRLBASE, 0);
396: YWRITE4(sc, YDS_EFFECT_CTRLBASE, 0);
397: YWRITE4(sc, YDS_WORK_BASE, 0);
398:
399: ctrl = YREAD2(sc, YDS_GLOBAL_CONTROL);
400: YWRITE2(sc, YDS_GLOBAL_CONTROL, ctrl & ~0x0007);
401:
402: /* Download DSP microcode. */
403: nswaph((u_int32_t *)&yf->data[0], ntohl(yf->dsplen));
404: YWRITEREGION4(sc, YDS_DSP_INSTRAM, (u_int32_t *)&yf->data[0],
405: ntohl(yf->dsplen));
406:
407: /* Download CONTROL microcode. */
408: nswaph((u_int32_t *)p, size);
409: YWRITEREGION4(sc, YDS_CTRL_INSTRAM, p, size);
410:
411: yds_enable_dsp(sc);
412: delay(10*1000); /* neccesary on my 724F (??) */
413:
414: free(buf, M_DEVBUF);
415: return 0;
416: }
417:
418: static int
419: yds_allocate_slots(sc)
420: struct yds_softc *sc;
421: {
422: size_t pcs, rcs, ecs, ws, memsize;
423: void *mp;
424: u_int32_t da; /* DMA address */
425: char *va; /* KVA */
426: off_t cb;
427: int i;
428: struct yds_dma *p;
429:
430: /* Alloc DSP Control Data */
431: pcs = YREAD4(sc, YDS_PLAY_CTRLSIZE) * sizeof(u_int32_t);
432: rcs = YREAD4(sc, YDS_REC_CTRLSIZE) * sizeof(u_int32_t);
433: ecs = YREAD4(sc, YDS_EFFECT_CTRLSIZE) * sizeof(u_int32_t);
434: ws = WORK_SIZE;
435: YWRITE4(sc, YDS_WORK_SIZE, ws / sizeof(u_int32_t));
436:
437: DPRINTF(("play control size : %d\n", (unsigned int)pcs));
438: DPRINTF(("rec control size : %d\n", (unsigned int)rcs));
439: DPRINTF(("eff control size : %d\n", (unsigned int)ecs));
440: DPRINTF(("work size : %d\n", (unsigned int)ws));
441: #ifdef DIAGNOSTIC
442: if (pcs != sizeof(struct play_slot_ctrl_bank)) {
443: printf("%s: invalid play slot ctrldata %d != %d\n",
444: sc->sc_dev.dv_xname, (unsigned int)pcs,
445: (unsigned int)sizeof(struct play_slot_ctrl_bank));
446: }
447: if (rcs != sizeof(struct rec_slot_ctrl_bank)) {
448: printf("%s: invalid rec slot ctrldata %d != %d\n",
449: sc->sc_dev.dv_xname, (unsigned int)rcs,
450: (unsigned int)sizeof(struct rec_slot_ctrl_bank));
451: }
452: #endif
453:
454: memsize = N_PLAY_SLOTS*N_PLAY_SLOT_CTRL_BANK*pcs +
455: N_REC_SLOT_CTRL*N_REC_SLOT_CTRL_BANK*rcs + ws;
456: memsize += (N_PLAY_SLOTS+1)*sizeof(u_int32_t);
457:
458: p = &sc->sc_ctrldata;
459: i = yds_allocmem(sc, memsize, 16, p);
460: if (i) {
461: printf("%s: couldn't alloc/map DSP DMA buffer, reason %d\n",
462: sc->sc_dev.dv_xname, i);
463: free(p, M_DEVBUF);
464: return 1;
465: }
466: mp = KERNADDR(p);
467: da = DMAADDR(p);
468:
469: DPRINTF(("mp:%p, DMA addr:%p\n",
470: mp, (void *) sc->sc_ctrldata.map->dm_segs[0].ds_addr));
471:
472: bzero(mp, memsize);
473:
474: /* Work space */
475: cb = 0;
476: va = (u_int8_t*)mp;
477: YWRITE4(sc, YDS_WORK_BASE, da + cb);
478: cb += ws;
479:
480: /* Play control data table */
481: sc->ptbl = (u_int32_t *)(va + cb);
482: sc->ptbloff = cb;
483: YWRITE4(sc, YDS_PLAY_CTRLBASE, da + cb);
484: cb += (N_PLAY_SLOT_CTRL + 1) * sizeof(u_int32_t);
485:
486: /* Record slot control data */
487: sc->rbank = (struct rec_slot_ctrl_bank *)(va + cb);
488: YWRITE4(sc, YDS_REC_CTRLBASE, da + cb);
489: sc->rbankoff = cb;
490: cb += N_REC_SLOT_CTRL * N_REC_SLOT_CTRL_BANK * rcs;
491:
492: #if 0
493: /* Effect slot control data -- unused */
494: YWRITE4(sc, YDS_EFFECT_CTRLBASE, da + cb);
495: cb += N_EFFECT_SLOT_CTRL * N_EFFECT_SLOT_CTRL_BANK * ecs;
496: #endif
497:
498: /* Play slot control data */
499: sc->pbankoff = da + cb;
500: for (i=0; i<N_PLAY_SLOT_CTRL; i++) {
501: sc->pbankp[i*2] = (struct play_slot_ctrl_bank *)(va + cb);
502: *(sc->ptbl + i+1) = da + cb;
503: cb += pcs;
504:
505: sc->pbankp[i*2+1] = (struct play_slot_ctrl_bank *)(va + cb);
506: cb += pcs;
507: }
508: /* Sync play control data table */
509: bus_dmamap_sync(sc->sc_dmatag, p->map,
510: sc->ptbloff, (N_PLAY_SLOT_CTRL+1) * sizeof(u_int32_t),
511: BUS_DMASYNC_PREWRITE);
512:
513: return 0;
514: }
515:
516: static void
517: yds_enable_dsp(sc)
518: struct yds_softc *sc;
519: {
520: YWRITE4(sc, YDS_CONFIG, YDS_DSP_SETUP);
521: }
522:
523: static int
524: yds_disable_dsp(sc)
525: struct yds_softc *sc;
526: {
527: int to;
528: u_int32_t data;
529:
530: data = YREAD4(sc, YDS_CONFIG);
531: if (data)
532: YWRITE4(sc, YDS_CONFIG, YDS_DSP_DISABLE);
533:
534: for (to = 0; to < YDS_WORK_TIMEOUT; to++) {
535: if ((YREAD4(sc, YDS_STATUS) & YDS_STAT_WORK) == 0)
536: return 0;
537: delay(1);
538: }
539:
540: return 1;
541: }
542:
543: int
544: yds_match(parent, match, aux)
545: struct device *parent;
546: void *match;
547: void *aux;
548: {
549: struct pci_attach_args *pa = (struct pci_attach_args *) aux;
550:
551: switch (PCI_VENDOR(pa->pa_id)) {
552: case PCI_VENDOR_YAMAHA:
553: switch (PCI_PRODUCT(pa->pa_id)) {
554: case PCI_PRODUCT_YAMAHA_YMF724:
555: case PCI_PRODUCT_YAMAHA_YMF740:
556: case PCI_PRODUCT_YAMAHA_YMF740C:
557: case PCI_PRODUCT_YAMAHA_YMF724F:
558: case PCI_PRODUCT_YAMAHA_YMF744:
559: case PCI_PRODUCT_YAMAHA_YMF754:
560: /* 734, 737, 738?? */
561: return (1);
562: }
563: break;
564: }
565:
566: return (0);
567: }
568:
569: /*
570: * This routine is called after all the ISA devices are configured,
571: * to avoid conflict.
572: */
573: static void
574: yds_configure_legacy (sc)
575: struct yds_softc *sc;
576: #define FLEXIBLE (sc->sc_flags & YDS_CAP_LEGACY_FLEXIBLE)
577: #define SELECTABLE (sc->sc_flags & YDS_CAP_LEGACY_SELECTABLE)
578: {
579: pcireg_t reg;
580: struct device *dev;
581: int i;
582: bus_addr_t opl_addrs[] = {0x388, 0x398, 0x3A0, 0x3A8};
583: bus_addr_t mpu_addrs[] = {0x330, 0x300, 0x332, 0x334};
584:
585: if (!FLEXIBLE && !SELECTABLE)
586: return;
587:
588: reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, YDS_PCI_LEGACY);
589: reg &= ~0x8133c03f; /* these bits are out of interest */
590: reg |= (YDS_PCI_EX_LEGACY_IMOD | YDS_PCI_LEGACY_FMEN |
591: YDS_PCI_LEGACY_MEN /*| YDS_PCI_LEGACY_MIEN*/);
592: if (sc->sc_flags & YDS_CAP_LEGACY_SMOD_DISABLE)
593: reg |= YDS_PCI_EX_LEGACY_SMOD_DISABLE;
594: if (FLEXIBLE) {
595: pci_conf_write(sc->sc_pc, sc->sc_pcitag, YDS_PCI_LEGACY, reg);
596: delay(100*1000);
597: }
598:
599: /* Look for OPL */
600: dev = 0;
601: for (i = 0; i < sizeof(opl_addrs) / sizeof (bus_addr_t); i++) {
602: if (SELECTABLE) {
603: pci_conf_write(sc->sc_pc, sc->sc_pcitag,
604: YDS_PCI_LEGACY, reg | (i << (0+16)));
605: delay(100*1000); /* wait 100ms */
606: } else
607: pci_conf_write(sc->sc_pc, sc->sc_pcitag,
608: YDS_PCI_FM_BA, opl_addrs[i]);
609: if (bus_space_map(sc->sc_opl_iot,
610: opl_addrs[i], 4, 0, &sc->sc_opl_ioh) == 0) {
611: struct audio_attach_args aa;
612:
613: aa.type = AUDIODEV_TYPE_OPL;
614: aa.hwif = aa.hdl = NULL;
615: dev = config_found(&sc->sc_dev, &aa, audioprint);
616: if (dev == 0)
617: bus_space_unmap(sc->sc_opl_iot,
618: sc->sc_opl_ioh, 4);
619: else {
620: if (SELECTABLE)
621: reg |= (i << (0+16));
622: break;
623: }
624: }
625: }
626: if (dev == 0) {
627: reg &= ~YDS_PCI_LEGACY_FMEN;
628: pci_conf_write(sc->sc_pc, sc->sc_pcitag,
629: YDS_PCI_LEGACY, reg);
630: } else {
631: /* Max. volume */
632: YWRITE4(sc, YDS_LEGACY_OUT_VOLUME, 0x3fff3fff);
633: YWRITE4(sc, YDS_LEGACY_REC_VOLUME, 0x3fff3fff);
634: }
635:
636: /* Look for MPU */
637: dev = 0;
638: for (i = 0; i < sizeof(mpu_addrs) / sizeof (bus_addr_t); i++) {
639: if (SELECTABLE)
640: pci_conf_write(sc->sc_pc, sc->sc_pcitag,
641: YDS_PCI_LEGACY, reg | (i << (4+16)));
642: else
643: pci_conf_write(sc->sc_pc, sc->sc_pcitag,
644: YDS_PCI_MPU_BA, mpu_addrs[i]);
645: if (bus_space_map(sc->sc_mpu_iot,
646: mpu_addrs[i], 2, 0, &sc->sc_mpu_ioh) == 0) {
647: struct audio_attach_args aa;
648:
649: aa.type = AUDIODEV_TYPE_MPU;
650: aa.hwif = aa.hdl = NULL;
651: dev = config_found(&sc->sc_dev, &aa, audioprint);
652: if (dev == 0)
653: bus_space_unmap(sc->sc_mpu_iot,
654: sc->sc_mpu_ioh, 2);
655: else {
656: if (SELECTABLE)
657: reg |= (i << (4+16));
658: break;
659: }
660: }
661: }
662: if (dev == 0) {
663: reg &= ~(YDS_PCI_LEGACY_MEN | YDS_PCI_LEGACY_MIEN);
664: pci_conf_write(sc->sc_pc, sc->sc_pcitag,
665: YDS_PCI_LEGACY, reg);
666: }
667: sc->sc_mpu = dev;
668: }
669: #undef FLEXIBLE
670: #undef SELECTABLE
671:
672: void
673: yds_attach(parent, self, aux)
674: struct device *parent;
675: struct device *self;
676: void *aux;
677: {
678: struct yds_softc *sc = (struct yds_softc *)self;
679: struct pci_attach_args *pa = (struct pci_attach_args *)aux;
680: pci_chipset_tag_t pc = pa->pa_pc;
681: char const *intrstr;
682: pci_intr_handle_t ih;
683: bus_size_t size;
684: pcireg_t reg;
685: int i;
686:
687: /* Map register to memory */
688: if (pci_mapreg_map(pa, YDS_PCI_MBA, PCI_MAPREG_TYPE_MEM, 0,
689: &sc->memt, &sc->memh, NULL, &size, 0)) {
690: printf("%s: can't map memory space\n", sc->sc_dev.dv_xname);
691: return;
692: }
693:
694: /* Map and establish the interrupt. */
695: if (pci_intr_map(pa, &ih)) {
696: printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
697: bus_space_unmap(sc->memt, sc->memh, size);
698: return;
699: }
700: intrstr = pci_intr_string(pc, ih);
701: sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, yds_intr, sc,
702: self->dv_xname);
703: if (sc->sc_ih == NULL) {
704: printf("%s: couldn't establish interrupt",
705: sc->sc_dev.dv_xname);
706: if (intrstr != NULL)
707: printf(" at %s", intrstr);
708: printf("\n");
709: bus_space_unmap(sc->memt, sc->memh, size);
710: return;
711: }
712: printf(": %s\n", intrstr);
713:
714: sc->sc_dmatag = pa->pa_dmat;
715: sc->sc_pc = pc;
716: sc->sc_pcitag = pa->pa_tag;
717: sc->sc_id = pa->pa_id;
718: sc->sc_revision = PCI_REVISION(pa->pa_class);
719: sc->sc_flags = yds_get_dstype(sc->sc_id);
720: if (sc->sc_dev.dv_cfdata->cf_flags & YDS_CAP_LEGACY_SMOD_DISABLE)
721: sc->sc_flags |= YDS_CAP_LEGACY_SMOD_DISABLE;
722: #ifdef AUDIO_DEBUG
723: if (ydsdebug)
724: printf("%s: chip has %b\n", sc->sc_dev.dv_xname,
725: YDS_CAP_BITS, sc->sc_flags);
726: #endif
727:
728: /* Disable legacy mode */
729: reg = pci_conf_read(pc, pa->pa_tag, YDS_PCI_LEGACY);
730: pci_conf_write(pc, pa->pa_tag, YDS_PCI_LEGACY,
731: reg & YDS_PCI_LEGACY_LAD);
732:
733: /* Mute all volumes */
734: for (i = 0x80; i < 0xc0; i += 2)
735: YWRITE2(sc, i, 0);
736:
737: sc->sc_legacy_iot = pa->pa_iot;
738: mountroothook_establish(yds_attachhook, sc);
739: }
740:
741: void
742: yds_attachhook(void *xsc)
743: {
744: struct yds_softc *sc = xsc;
745: struct yds_codec_softc *codec;
746: mixer_ctrl_t ctl;
747: int r, i;
748:
749: /* Initialize the device */
750: if (yds_init(sc) == -1)
751: return;
752:
753: /*
754: * Attach ac97 codec
755: */
756: for (i = 0; i < 2; i++) {
757: static struct {
758: int data;
759: int addr;
760: } statregs[] = {
761: {AC97_STAT_DATA1, AC97_STAT_ADDR1},
762: {AC97_STAT_DATA2, AC97_STAT_ADDR2},
763: };
764:
765: if (i == 1 && ac97_id2 == -1)
766: break; /* secondary ac97 not available */
767:
768: codec = &sc->sc_codec[i];
769: memcpy(&codec->sc_dev, &sc->sc_dev, sizeof(codec->sc_dev));
770: codec->sc = sc;
771: codec->id = i == 1 ? ac97_id2 : 0;
772: codec->status_data = statregs[i].data;
773: codec->status_addr = statregs[i].addr;
774: codec->host_if.arg = codec;
775: codec->host_if.attach = yds_attach_codec;
776: codec->host_if.read = yds_read_codec;
777: codec->host_if.write = yds_write_codec;
778: codec->host_if.reset = yds_reset_codec;
779:
780: if ((r = ac97_attach(&codec->host_if)) != 0) {
781: printf("%s: can't attach codec (error 0x%X)\n",
782: sc->sc_dev.dv_xname, r);
783: return;
784: }
785: }
786:
787: /* Just enable the DAC and master volumes by default */
788: ctl.type = AUDIO_MIXER_ENUM;
789: ctl.un.ord = 0; /* off */
790: ctl.dev = yds_get_portnum_by_name(sc, AudioCoutputs,
791: AudioNmaster, AudioNmute);
792: yds_mixer_set_port(sc, &ctl);
793: ctl.dev = yds_get_portnum_by_name(sc, AudioCinputs,
794: AudioNdac, AudioNmute);
795: yds_mixer_set_port(sc, &ctl);
796: ctl.dev = yds_get_portnum_by_name(sc, AudioCinputs,
797: AudioNcd, AudioNmute);
798: yds_mixer_set_port(sc, &ctl);
799: ctl.dev = yds_get_portnum_by_name(sc, AudioCrecord,
800: AudioNvolume, AudioNmute);
801: yds_mixer_set_port(sc, &ctl);
802:
803: ctl.dev = yds_get_portnum_by_name(sc, AudioCrecord,
804: AudioNsource, NULL);
805: ctl.type = AUDIO_MIXER_ENUM;
806: ctl.un.ord = 0;
807: yds_mixer_set_port(sc, &ctl);
808:
809: /* Set a reasonable default volume */
810: ctl.type = AUDIO_MIXER_VALUE;
811: ctl.un.value.num_channels = 2;
812: ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
813: ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
814:
815: ctl.dev = sc->sc_codec[0].codec_if->vtbl->get_portnum_by_name(
816: sc->sc_codec[0].codec_if, AudioCoutputs, AudioNmaster, NULL);
817: yds_mixer_set_port(sc, &ctl);
818:
819: audio_attach_mi(&yds_hw_if, sc, &sc->sc_dev);
820:
821: /* Watch for power changes */
822: sc->suspend = PWR_RESUME;
823: sc->powerhook = powerhook_establish(yds_powerhook, sc);
824:
825: yds_configure_legacy(sc);
826: }
827:
828: int
829: yds_attach_codec(sc_, codec_if)
830: void *sc_;
831: struct ac97_codec_if *codec_if;
832: {
833: struct yds_codec_softc *sc = sc_;
834:
835: sc->codec_if = codec_if;
836: return 0;
837: }
838:
839: static int
840: yds_ready_codec(sc)
841: struct yds_codec_softc *sc;
842: {
843: int to;
844:
845: for (to = 0; to < AC97_TIMEOUT; to++) {
846: if ((YREAD2(sc->sc, sc->status_addr) & AC97_BUSY) == 0)
847: return 0;
848: delay(1);
849: }
850:
851: return 1;
852: }
853:
854: int
855: yds_read_codec(sc_, reg, data)
856: void *sc_;
857: u_int8_t reg;
858: u_int16_t *data;
859: {
860: struct yds_codec_softc *sc = sc_;
861:
862: YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_READ | AC97_ID(sc->id) | reg);
863:
864: if (yds_ready_codec(sc)) {
865: printf("%s: yds_read_codec timeout\n",
866: sc->sc->sc_dev.dv_xname);
867: return EIO;
868: }
869:
870: if (PCI_PRODUCT(sc->sc->sc_id) == PCI_PRODUCT_YAMAHA_YMF744 &&
871: sc->sc->sc_revision < 2) {
872: int i;
873:
874: for (i = 0; i < 600; i++)
875: YREAD2(sc->sc, sc->status_data);
876: }
877: *data = YREAD2(sc->sc, sc->status_data);
878:
879: return 0;
880: }
881:
882: int
883: yds_write_codec(sc_, reg, data)
884: void *sc_;
885: u_int8_t reg;
886: u_int16_t data;
887: {
888: struct yds_codec_softc *sc = sc_;
889:
890: YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_WRITE | AC97_ID(sc->id) | reg);
891: YWRITE2(sc->sc, AC97_CMD_DATA, data);
892:
893: if (yds_ready_codec(sc)) {
894: printf("%s: yds_write_codec timeout\n",
895: sc->sc->sc_dev.dv_xname);
896: return EIO;
897: }
898:
899: return 0;
900: }
901:
902: /*
903: * XXX: Must handle the secondary differntly!!
904: */
905: void
906: yds_reset_codec(sc_)
907: void *sc_;
908: {
909: struct yds_codec_softc *codec = sc_;
910: struct yds_softc *sc = codec->sc;
911: pcireg_t reg;
912:
913: /* reset AC97 codec */
914: reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, YDS_PCI_DSCTRL);
915: if (reg & 0x03) {
916: pci_conf_write(sc->sc_pc, sc->sc_pcitag,
917: YDS_PCI_DSCTRL, reg & ~0x03);
918: pci_conf_write(sc->sc_pc, sc->sc_pcitag,
919: YDS_PCI_DSCTRL, reg | 0x03);
920: pci_conf_write(sc->sc_pc, sc->sc_pcitag,
921: YDS_PCI_DSCTRL, reg & ~0x03);
922: delay(50000);
923: }
924:
925: yds_ready_codec(sc_);
926: }
927:
928: int
929: yds_intr(p)
930: void *p;
931: {
932: struct yds_softc *sc = p;
933: u_int status;
934:
935: status = YREAD4(sc, YDS_STATUS);
936: DPRINTFN(1, ("yds_intr: status=%08x\n", status));
937: if ((status & (YDS_STAT_INT|YDS_STAT_TINT)) == 0) {
938: #if 0
939: if (sc->sc_mpu)
940: return mpu_intr(sc->sc_mpu);
941: #endif
942: return 0;
943: }
944:
945: if (status & YDS_STAT_TINT) {
946: YWRITE4(sc, YDS_STATUS, YDS_STAT_TINT);
947: printf ("yds_intr: timeout!\n");
948: }
949:
950: if (status & YDS_STAT_INT) {
951: int nbank = (YREAD4(sc, YDS_CONTROL_SELECT) == 0);
952:
953: /* Clear interrupt flag */
954: YWRITE4(sc, YDS_STATUS, YDS_STAT_INT);
955:
956: /* Buffer for the next frame is always ready. */
957: YWRITE4(sc, YDS_MODE, YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV2);
958:
959: if (sc->sc_play.intr) {
960: u_int dma, cpu, blk, len;
961:
962: /* Sync play slot control data */
963: bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
964: sc->pbankoff,
965: sizeof(struct play_slot_ctrl_bank)*
966: (*sc->ptbl)*
967: N_PLAY_SLOT_CTRL_BANK,
968: BUS_DMASYNC_POSTWRITE|
969: BUS_DMASYNC_POSTREAD);
970: dma = sc->pbankp[nbank]->pgstart * sc->sc_play.factor;
971: cpu = sc->sc_play.offset;
972: blk = sc->sc_play.blksize;
973: len = sc->sc_play.length;
974:
975: if (((dma > cpu) && (dma - cpu > blk * 2)) ||
976: ((cpu > dma) && (dma + len - cpu > blk * 2))) {
977: /* We can fill the next block */
978: /* Sync ring buffer for previous write */
979: bus_dmamap_sync(sc->sc_dmatag,
980: sc->sc_play.dma->map,
981: cpu, blk,
982: BUS_DMASYNC_POSTWRITE);
983: sc->sc_play.intr(sc->sc_play.intr_arg);
984: sc->sc_play.offset += blk;
985: if (sc->sc_play.offset >= len) {
986: sc->sc_play.offset -= len;
987: #ifdef DIAGNOSTIC
988: if (sc->sc_play.offset != 0)
989: printf ("Audio ringbuffer botch\n");
990: #endif
991: }
992: /* Sync ring buffer for next write */
993: bus_dmamap_sync(sc->sc_dmatag,
994: sc->sc_play.dma->map,
995: cpu, blk,
996: BUS_DMASYNC_PREWRITE);
997: }
998: }
999: if (sc->sc_rec.intr) {
1000: u_int dma, cpu, blk, len;
1001:
1002: /* Sync rec slot control data */
1003: bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
1004: sc->rbankoff,
1005: sizeof(struct rec_slot_ctrl_bank)*
1006: N_REC_SLOT_CTRL*
1007: N_REC_SLOT_CTRL_BANK,
1008: BUS_DMASYNC_POSTWRITE|
1009: BUS_DMASYNC_POSTREAD);
1010: dma = sc->rbank[YDS_INPUT_SLOT*2 + nbank].pgstartadr;
1011: cpu = sc->sc_rec.offset;
1012: blk = sc->sc_rec.blksize;
1013: len = sc->sc_rec.length;
1014:
1015: if (((dma > cpu) && (dma - cpu > blk * 2)) ||
1016: ((cpu > dma) && (dma + len - cpu > blk * 2))) {
1017: /* We can drain the current block */
1018: /* Sync ring buffer first */
1019: bus_dmamap_sync(sc->sc_dmatag,
1020: sc->sc_rec.dma->map,
1021: cpu, blk,
1022: BUS_DMASYNC_POSTREAD);
1023: sc->sc_rec.intr(sc->sc_rec.intr_arg);
1024: sc->sc_rec.offset += blk;
1025: if (sc->sc_rec.offset >= len) {
1026: sc->sc_rec.offset -= len;
1027: #ifdef DIAGNOSTIC
1028: if (sc->sc_rec.offset != 0)
1029: printf ("Audio ringbuffer botch\n");
1030: #endif
1031: }
1032: /* Sync ring buffer for next read */
1033: bus_dmamap_sync(sc->sc_dmatag,
1034: sc->sc_rec.dma->map,
1035: cpu, blk,
1036: BUS_DMASYNC_PREREAD);
1037: }
1038: }
1039: }
1040:
1041: return 1;
1042: }
1043:
1044: int
1045: yds_allocmem(sc, size, align, p)
1046: struct yds_softc *sc;
1047: size_t size;
1048: size_t align;
1049: struct yds_dma *p;
1050: {
1051: int error;
1052:
1053: p->size = size;
1054: error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
1055: p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
1056: &p->nsegs, BUS_DMA_NOWAIT);
1057: if (error)
1058: return (error);
1059:
1060: error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
1061: &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
1062: if (error)
1063: goto free;
1064:
1065: error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
1066: 0, BUS_DMA_NOWAIT, &p->map);
1067: if (error)
1068: goto unmap;
1069:
1070: error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
1071: BUS_DMA_NOWAIT);
1072: if (error)
1073: goto destroy;
1074: return (0);
1075:
1076: destroy:
1077: bus_dmamap_destroy(sc->sc_dmatag, p->map);
1078: unmap:
1079: bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
1080: free:
1081: bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
1082: return (error);
1083: }
1084:
1085: int
1086: yds_freemem(sc, p)
1087: struct yds_softc *sc;
1088: struct yds_dma *p;
1089: {
1090: bus_dmamap_unload(sc->sc_dmatag, p->map);
1091: bus_dmamap_destroy(sc->sc_dmatag, p->map);
1092: bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
1093: bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
1094: return 0;
1095: }
1096:
1097: int
1098: yds_open(addr, flags)
1099: void *addr;
1100: int flags;
1101: {
1102: struct yds_softc *sc = addr;
1103: int mode;
1104:
1105: /* Select bank 0. */
1106: YWRITE4(sc, YDS_CONTROL_SELECT, 0);
1107:
1108: /* Start the DSP operation. */
1109: mode = YREAD4(sc, YDS_MODE);
1110: mode |= YDS_MODE_ACTV;
1111: mode &= ~YDS_MODE_ACTV2;
1112: YWRITE4(sc, YDS_MODE, mode);
1113:
1114: return 0;
1115: }
1116:
1117: /*
1118: * Close function is called at splaudio().
1119: */
1120: void
1121: yds_close(addr)
1122: void *addr;
1123: {
1124: struct yds_softc *sc = addr;
1125:
1126: yds_halt_output(sc);
1127: yds_halt_input(sc);
1128: yds_halt(sc);
1129: }
1130:
1131: int
1132: yds_query_encoding(addr, fp)
1133: void *addr;
1134: struct audio_encoding *fp;
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 = AUDIO_ENCODINGFLAG_EMULATED;
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 = AUDIO_ENCODINGFLAG_EMULATED;
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: }
1189:
1190: int
1191: yds_set_params(addr, setmode, usemode, play, rec)
1192: void *addr;
1193: int setmode, usemode;
1194: struct audio_params *play, *rec;
1195: {
1196: struct audio_params *p;
1197: int mode;
1198:
1199: for (mode = AUMODE_RECORD; mode != -1;
1200: mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
1201: if ((setmode & mode) == 0)
1202: continue;
1203:
1204: p = mode == AUMODE_PLAY ? play : rec;
1205:
1206: if (p->sample_rate < 4000 || p->sample_rate > 48000 ||
1207: (p->precision != 8 && p->precision != 16) ||
1208: (p->channels != 1 && p->channels != 2))
1209: return (EINVAL);
1210:
1211: p->factor = 1;
1212: p->sw_code = 0;
1213: switch (p->encoding) {
1214: case AUDIO_ENCODING_SLINEAR_BE:
1215: if (p->precision == 16)
1216: p->sw_code = swap_bytes;
1217: else
1218: p->sw_code = change_sign8;
1219: break;
1220: case AUDIO_ENCODING_SLINEAR_LE:
1221: if (p->precision != 16)
1222: p->sw_code = change_sign8;
1223: break;
1224: case AUDIO_ENCODING_ULINEAR_BE:
1225: if (p->precision == 16) {
1226: if (mode == AUMODE_PLAY)
1227: p->sw_code = swap_bytes_change_sign16_le;
1228: else
1229: p->sw_code = change_sign16_swap_bytes_le;
1230: }
1231: break;
1232: case AUDIO_ENCODING_ULINEAR_LE:
1233: if (p->precision == 16)
1234: p->sw_code = change_sign16_le;
1235: break;
1236: case AUDIO_ENCODING_ULAW:
1237: if (mode == AUMODE_PLAY) {
1238: p->factor = 2;
1239: p->precision = 16;
1240: p->sw_code = mulaw_to_slinear16_le;
1241: } else
1242: p->sw_code = ulinear8_to_mulaw;
1243: break;
1244: case AUDIO_ENCODING_ALAW:
1245: if (mode == AUMODE_PLAY) {
1246: p->factor = 2;
1247: p->precision = 16;
1248: p->sw_code = alaw_to_slinear16_le;
1249: } else
1250: p->sw_code = ulinear8_to_alaw;
1251: break;
1252: default:
1253: return (EINVAL);
1254: }
1255: }
1256:
1257: return 0;
1258: }
1259:
1260: int
1261: yds_round_blocksize(addr, blk)
1262: void *addr;
1263: int blk;
1264: {
1265: /*
1266: * Block size must be bigger than a frame.
1267: * That is 1024bytes at most, i.e. for 48000Hz, 16bit, 2ch.
1268: */
1269: if (blk < 1024)
1270: blk = 1024;
1271:
1272: return blk & ~4;
1273: }
1274:
1275: static u_int32_t
1276: yds_get_lpfq(sample_rate)
1277: u_int sample_rate;
1278: {
1279: int i;
1280: static struct lpfqt {
1281: u_int rate;
1282: u_int32_t lpfq;
1283: } lpfqt[] = {
1284: {8000, 0x32020000},
1285: {11025, 0x31770000},
1286: {16000, 0x31390000},
1287: {22050, 0x31c90000},
1288: {32000, 0x33d00000},
1289: {48000, 0x40000000},
1290: {0, 0}
1291: };
1292:
1293: if (sample_rate == 44100) /* for P44 slot? */
1294: return 0x370A0000;
1295:
1296: for (i = 0; lpfqt[i].rate != 0; i++)
1297: if (sample_rate <= lpfqt[i].rate)
1298: break;
1299:
1300: return lpfqt[i].lpfq;
1301: }
1302:
1303: static u_int32_t
1304: yds_get_lpfk(sample_rate)
1305: u_int sample_rate;
1306: {
1307: int i;
1308: static struct lpfkt {
1309: u_int rate;
1310: u_int32_t lpfk;
1311: } lpfkt[] = {
1312: {8000, 0x18b20000},
1313: {11025, 0x20930000},
1314: {16000, 0x2b9a0000},
1315: {22050, 0x35a10000},
1316: {32000, 0x3eaa0000},
1317: {48000, 0x40000000},
1318: {0, 0}
1319: };
1320:
1321: if (sample_rate == 44100) /* for P44 slot? */
1322: return 0x46460000;
1323:
1324: for (i = 0; lpfkt[i].rate != 0; i++)
1325: if (sample_rate <= lpfkt[i].rate)
1326: break;
1327:
1328: return lpfkt[i].lpfk;
1329: }
1330:
1331: int
1332: yds_trigger_output(addr, start, end, blksize, intr, arg, param)
1333: void *addr;
1334: void *start, *end;
1335: int blksize;
1336: void (*intr)(void *);
1337: void *arg;
1338: struct audio_params *param;
1339: #define P44 (sc->sc_flags & YDS_CAP_HAS_P44)
1340: {
1341: struct yds_softc *sc = addr;
1342: struct yds_dma *p;
1343: struct play_slot_ctrl_bank *psb;
1344: const u_int gain = 0x40000000;
1345: bus_addr_t s;
1346: size_t l;
1347: int i;
1348: int p44, channels;
1349:
1350: #ifdef DIAGNOSTIC
1351: if (sc->sc_play.intr)
1352: panic("yds_trigger_output: already running");
1353: #endif
1354:
1355: sc->sc_play.intr = intr;
1356: sc->sc_play.intr_arg = arg;
1357: sc->sc_play.offset = 0;
1358: sc->sc_play.blksize = blksize;
1359:
1360: DPRINTFN(1, ("yds_trigger_output: sc=%p start=%p end=%p "
1361: "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1362:
1363: p = yds_find_dma(sc, start);
1364: if (!p) {
1365: printf("yds_trigger_output: bad addr %p\n", start);
1366: return (EINVAL);
1367: }
1368: sc->sc_play.dma = p;
1369:
1370: #ifdef DIAGNOSTIC
1371: {
1372: u_int32_t ctrlsize;
1373: if ((ctrlsize = YREAD4(sc, YDS_PLAY_CTRLSIZE)) !=
1374: sizeof(struct play_slot_ctrl_bank) / sizeof(u_int32_t))
1375: panic("%s: invalid play slot ctrldata %d %d",
1376: sc->sc_dev.dv_xname, ctrlsize,
1377: sizeof(struct play_slot_ctrl_bank));
1378: }
1379: #endif
1380:
1381: #ifdef YDS_USE_P44
1382: /* The document says the P44 SRC supports only stereo, 16bit PCM. */
1383: if (P44)
1384: p44 = ((param->sample_rate == 44100) &&
1385: (param->channels == 2) &&
1386: (param->precision == 16));
1387: else
1388: #endif
1389: p44 = 0;
1390: channels = p44 ? 1 : param->channels;
1391:
1392: s = DMAADDR(p);
1393: l = ((char *)end - (char *)start);
1394: sc->sc_play.length = l;
1395:
1396: *sc->ptbl = channels; /* Num of play */
1397:
1398: sc->sc_play.factor = 1;
1399: if (param->channels == 2)
1400: sc->sc_play.factor *= 2;
1401: if (param->precision != 8)
1402: sc->sc_play.factor *= 2;
1403: l /= sc->sc_play.factor;
1404:
1405: psb = sc->pbankp[0];
1406: memset(psb, 0, sizeof(*psb));
1407: psb->format = ((channels == 2 ? PSLT_FORMAT_STEREO : 0) |
1408: (param->precision == 8 ? PSLT_FORMAT_8BIT : 0) |
1409: (p44 ? PSLT_FORMAT_SRC441 : 0));
1410: psb->pgbase = s;
1411: psb->pgloopend = l;
1412: if (!p44) {
1413: psb->pgdeltaend = (param->sample_rate * 65536 / 48000) << 12;
1414: psb->lpfkend = yds_get_lpfk(param->sample_rate);
1415: psb->eggainend = gain;
1416: psb->lpfq = yds_get_lpfq(param->sample_rate);
1417: psb->pgdelta = psb->pgdeltaend;
1418: psb->lpfk = yds_get_lpfk(param->sample_rate);
1419: psb->eggain = gain;
1420: }
1421:
1422: for (i = 0; i < channels; i++) {
1423: /* i == 0: left or mono, i == 1: right */
1424: psb = sc->pbankp[i*2];
1425: if (i)
1426: /* copy from left */
1427: *psb = *(sc->pbankp[0]);
1428: if (channels == 2) {
1429: /* stereo */
1430: if (i == 0) {
1431: psb->lchgain = psb->lchgainend = gain;
1432: } else {
1433: psb->lchgain = psb->lchgainend = 0;
1434: psb->rchgain = psb->rchgainend = gain;
1435: psb->format |= PSLT_FORMAT_RCH;
1436: }
1437: } else if (!p44) {
1438: /* mono */
1439: psb->lchgain = psb->rchgain = gain;
1440: psb->lchgainend = psb->rchgainend = gain;
1441: }
1442: /* copy to the other bank */
1443: *(sc->pbankp[i*2+1]) = *psb;
1444: }
1445:
1446: YDS_DUMP_PLAY_SLOT(5, sc, 0);
1447: YDS_DUMP_PLAY_SLOT(5, sc, 1);
1448:
1449: if (p44)
1450: YWRITE4(sc, YDS_P44_OUT_VOLUME, 0x3fff3fff);
1451: else
1452: YWRITE4(sc, YDS_DAC_OUT_VOLUME, 0x3fff3fff);
1453:
1454: /* Now the play slot for the next frame is set up!! */
1455: /* Sync play slot control data for both directions */
1456: bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
1457: sc->ptbloff,
1458: sizeof(struct play_slot_ctrl_bank) *
1459: channels * N_PLAY_SLOT_CTRL_BANK,
1460: BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
1461: /* Sync ring buffer */
1462: bus_dmamap_sync(sc->sc_dmatag, p->map, 0, blksize,
1463: BUS_DMASYNC_PREWRITE);
1464: /* HERE WE GO!! */
1465: YWRITE4(sc, YDS_MODE,
1466: YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV | YDS_MODE_ACTV2);
1467:
1468: return 0;
1469: }
1470: #undef P44
1471:
1472: int
1473: yds_trigger_input(addr, start, end, blksize, intr, arg, param)
1474: void *addr;
1475: void *start, *end;
1476: int blksize;
1477: void (*intr)(void *);
1478: void *arg;
1479: struct audio_params *param;
1480: {
1481: struct yds_softc *sc = addr;
1482: struct yds_dma *p;
1483: u_int srate, format;
1484: struct rec_slot_ctrl_bank *rsb;
1485: bus_addr_t s;
1486: size_t l;
1487:
1488: #ifdef DIAGNOSTIC
1489: if (sc->sc_rec.intr)
1490: panic("yds_trigger_input: already running");
1491: #endif
1492: sc->sc_rec.intr = intr;
1493: sc->sc_rec.intr_arg = arg;
1494: sc->sc_rec.offset = 0;
1495: sc->sc_rec.blksize = blksize;
1496:
1497: DPRINTFN(1, ("yds_trigger_input: "
1498: "sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
1499: addr, start, end, blksize, intr, arg));
1500: DPRINTFN(1, (" parameters: rate=%lu, precision=%u, channels=%u\n",
1501: param->sample_rate, param->precision, param->channels));
1502:
1503: p = yds_find_dma(sc, start);
1504: if (!p) {
1505: printf("yds_trigger_input: bad addr %p\n", start);
1506: return (EINVAL);
1507: }
1508: sc->sc_rec.dma = p;
1509:
1510: s = DMAADDR(p);
1511: l = ((char *)end - (char *)start);
1512: sc->sc_rec.length = l;
1513:
1514: sc->sc_rec.factor = 1;
1515: if (param->channels == 2)
1516: sc->sc_rec.factor *= 2;
1517: if (param->precision != 8)
1518: sc->sc_rec.factor *= 2;
1519:
1520: rsb = &sc->rbank[0];
1521: memset(rsb, 0, sizeof(*rsb));
1522: rsb->pgbase = s;
1523: rsb->pgloopendadr = l;
1524: /* Seems all 4 banks must be set up... */
1525: sc->rbank[1] = *rsb;
1526: sc->rbank[2] = *rsb;
1527: sc->rbank[3] = *rsb;
1528:
1529: YWRITE4(sc, YDS_ADC_IN_VOLUME, 0x3fff3fff);
1530: YWRITE4(sc, YDS_REC_IN_VOLUME, 0x3fff3fff);
1531: srate = 48000 * 4096 / param->sample_rate - 1;
1532: format = ((param->precision == 8 ? YDS_FORMAT_8BIT : 0) |
1533: (param->channels == 2 ? YDS_FORMAT_STEREO : 0));
1534: DPRINTF(("srate=%d, format=%08x\n", srate, format));
1535: #ifdef YDS_USE_REC_SLOT
1536: YWRITE4(sc, YDS_DAC_REC_VOLUME, 0x3fff3fff);
1537: YWRITE4(sc, YDS_P44_REC_VOLUME, 0x3fff3fff);
1538: YWRITE4(sc, YDS_MAPOF_REC, YDS_RECSLOT_VALID);
1539: YWRITE4(sc, YDS_REC_SAMPLE_RATE, srate);
1540: YWRITE4(sc, YDS_REC_FORMAT, format);
1541: #else
1542: YWRITE4(sc, YDS_MAPOF_REC, YDS_ADCSLOT_VALID);
1543: YWRITE4(sc, YDS_ADC_SAMPLE_RATE, srate);
1544: YWRITE4(sc, YDS_ADC_FORMAT, format);
1545: #endif
1546: /* Now the rec slot for the next frame is set up!! */
1547: /* Sync record slot control data */
1548: bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
1549: sc->rbankoff,
1550: sizeof(struct rec_slot_ctrl_bank)*
1551: N_REC_SLOT_CTRL*
1552: N_REC_SLOT_CTRL_BANK,
1553: BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
1554: /* Sync ring buffer */
1555: bus_dmamap_sync(sc->sc_dmatag, p->map, 0, blksize,
1556: BUS_DMASYNC_PREREAD);
1557: /* HERE WE GO!! */
1558: YWRITE4(sc, YDS_MODE,
1559: YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV | YDS_MODE_ACTV2);
1560:
1561: return 0;
1562: }
1563:
1564: static int
1565: yds_halt(sc)
1566: struct yds_softc *sc;
1567: {
1568: u_int32_t mode;
1569:
1570: /* Stop the DSP operation. */
1571: mode = YREAD4(sc, YDS_MODE);
1572: YWRITE4(sc, YDS_MODE, mode & ~(YDS_MODE_ACTV|YDS_MODE_ACTV2));
1573:
1574: /* Paranoia... mute all */
1575: YWRITE4(sc, YDS_P44_OUT_VOLUME, 0);
1576: YWRITE4(sc, YDS_DAC_OUT_VOLUME, 0);
1577: YWRITE4(sc, YDS_ADC_IN_VOLUME, 0);
1578: YWRITE4(sc, YDS_REC_IN_VOLUME, 0);
1579: YWRITE4(sc, YDS_DAC_REC_VOLUME, 0);
1580: YWRITE4(sc, YDS_P44_REC_VOLUME, 0);
1581:
1582: return 0;
1583: }
1584:
1585: int
1586: yds_halt_output(addr)
1587: void *addr;
1588: {
1589: struct yds_softc *sc = addr;
1590:
1591: DPRINTF(("yds: yds_halt_output\n"));
1592: if (sc->sc_play.intr) {
1593: sc->sc_play.intr = 0;
1594: /* Sync play slot control data */
1595: bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
1596: sc->pbankoff,
1597: sizeof(struct play_slot_ctrl_bank)*
1598: (*sc->ptbl)*N_PLAY_SLOT_CTRL_BANK,
1599: BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD);
1600: /* Stop the play slot operation */
1601: sc->pbankp[0]->status =
1602: sc->pbankp[1]->status =
1603: sc->pbankp[2]->status =
1604: sc->pbankp[3]->status = 1;
1605: /* Sync ring buffer */
1606: bus_dmamap_sync(sc->sc_dmatag, sc->sc_play.dma->map,
1607: 0, sc->sc_play.length, BUS_DMASYNC_POSTWRITE);
1608: }
1609:
1610: return 0;
1611: }
1612:
1613: int
1614: yds_halt_input(addr)
1615: void *addr;
1616: {
1617: struct yds_softc *sc = addr;
1618:
1619: DPRINTF(("yds: yds_halt_input\n"));
1620: if (sc->sc_rec.intr) {
1621: /* Stop the rec slot operation */
1622: YWRITE4(sc, YDS_MAPOF_REC, 0);
1623: sc->sc_rec.intr = 0;
1624: /* Sync rec slot control data */
1625: bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
1626: sc->rbankoff,
1627: sizeof(struct rec_slot_ctrl_bank)*
1628: N_REC_SLOT_CTRL*N_REC_SLOT_CTRL_BANK,
1629: BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD);
1630: /* Sync ring buffer */
1631: bus_dmamap_sync(sc->sc_dmatag, sc->sc_rec.dma->map,
1632: 0, sc->sc_rec.length, BUS_DMASYNC_POSTREAD);
1633: }
1634: sc->sc_rec.intr = NULL;
1635:
1636: return 0;
1637: }
1638:
1639: int
1640: yds_getdev(addr, retp)
1641: void *addr;
1642: struct audio_device *retp;
1643: {
1644: *retp = yds_device;
1645:
1646: return 0;
1647: }
1648:
1649: int
1650: yds_mixer_set_port(addr, cp)
1651: void *addr;
1652: mixer_ctrl_t *cp;
1653: {
1654: struct yds_softc *sc = addr;
1655:
1656: return (sc->sc_codec[0].codec_if->vtbl->mixer_set_port(
1657: sc->sc_codec[0].codec_if, cp));
1658: }
1659:
1660: int
1661: yds_mixer_get_port(addr, cp)
1662: void *addr;
1663: mixer_ctrl_t *cp;
1664: {
1665: struct yds_softc *sc = addr;
1666:
1667: return (sc->sc_codec[0].codec_if->vtbl->mixer_get_port(
1668: sc->sc_codec[0].codec_if, cp));
1669: }
1670:
1671: int
1672: yds_query_devinfo(addr, dip)
1673: void *addr;
1674: mixer_devinfo_t *dip;
1675: {
1676: struct yds_softc *sc = addr;
1677:
1678: return (sc->sc_codec[0].codec_if->vtbl->query_devinfo(
1679: sc->sc_codec[0].codec_if, dip));
1680: }
1681:
1682: int
1683: yds_get_portnum_by_name(sc, class, device, qualifier)
1684: struct yds_softc *sc;
1685: char *class, *device, *qualifier;
1686: {
1687: return (sc->sc_codec[0].codec_if->vtbl->get_portnum_by_name(
1688: sc->sc_codec[0].codec_if, class, device, qualifier));
1689: }
1690:
1691: void *
1692: yds_malloc(addr, direction, size, pool, flags)
1693: void *addr;
1694: int direction;
1695: size_t size;
1696: int pool, flags;
1697: {
1698: struct yds_softc *sc = addr;
1699: struct yds_dma *p;
1700: int error;
1701:
1702: p = malloc(sizeof(*p), pool, flags);
1703: if (!p)
1704: return (0);
1705: error = yds_allocmem(sc, size, 16, p);
1706: if (error) {
1707: free(p, pool);
1708: return (0);
1709: }
1710: p->next = sc->sc_dmas;
1711: sc->sc_dmas = p;
1712: return (KERNADDR(p));
1713: }
1714:
1715: void
1716: yds_free(addr, ptr, pool)
1717: void *addr;
1718: void *ptr;
1719: int pool;
1720: {
1721: struct yds_softc *sc = addr;
1722: struct yds_dma **pp, *p;
1723:
1724: for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
1725: if (KERNADDR(p) == ptr) {
1726: yds_freemem(sc, p);
1727: *pp = p->next;
1728: free(p, pool);
1729: return;
1730: }
1731: }
1732: }
1733:
1734: static struct yds_dma *
1735: yds_find_dma(sc, addr)
1736: struct yds_softc *sc;
1737: void *addr;
1738: {
1739: struct yds_dma *p;
1740:
1741: for (p = sc->sc_dmas; p && KERNADDR(p) != addr; p = p->next)
1742: ;
1743:
1744: return p;
1745: }
1746:
1747: size_t
1748: yds_round_buffersize(addr, direction, size)
1749: void *addr;
1750: int direction;
1751: size_t size;
1752: {
1753: /*
1754: * Buffer size should be at least twice as bigger as a frame.
1755: */
1756: if (size < 1024 * 3)
1757: size = 1024 * 3;
1758: return (size);
1759: }
1760:
1761: paddr_t
1762: yds_mappage(addr, mem, off, prot)
1763: void *addr;
1764: void *mem;
1765: off_t off;
1766: int prot;
1767: {
1768: struct yds_softc *sc = addr;
1769: struct yds_dma *p;
1770:
1771: if (off < 0)
1772: return (-1);
1773: p = yds_find_dma(sc, mem);
1774: if (!p)
1775: return (-1);
1776: return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs,
1777: off, prot, BUS_DMA_WAITOK));
1778: }
1779:
1780: int
1781: yds_get_props(addr)
1782: void *addr;
1783: {
1784: return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
1785: AUDIO_PROP_FULLDUPLEX);
1786: }
1787:
1788: void
1789: yds_powerhook(why, self)
1790: int why;
1791: void *self;
1792: {
1793: struct yds_softc *sc = (struct yds_softc *)self;
1794:
1795: if (why != PWR_RESUME) {
1796: /* Power down */
1797: DPRINTF(("yds: power down\n"));
1798: sc->suspend = why;
1799:
1800: } else {
1801: /* Wake up */
1802: DPRINTF(("yds: power resume\n"));
1803: if (sc->suspend == PWR_RESUME) {
1804: printf("%s: resume without suspend?\n",
1805: sc->sc_dev.dv_xname);
1806: sc->suspend = why;
1807: return;
1808: }
1809: sc->suspend = why;
1810: yds_init(sc);
1811: (sc->sc_codec[0].codec_if->vtbl->restore_ports)(sc->sc_codec[0].codec_if);
1812: }
1813: }
1814:
1815: int
1816: yds_init(sc_)
1817: void *sc_;
1818: {
1819: struct yds_softc *sc = sc_;
1820: u_int32_t reg;
1821:
1822: pci_chipset_tag_t pc = sc->sc_pc;
1823:
1824: int to;
1825:
1826: DPRINTF(("in yds_init()\n"));
1827:
1828: /* Download microcode */
1829: if (yds_download_mcode(sc)) {
1830: printf("%s: download microcode failed\n", sc->sc_dev.dv_xname);
1831: return -1;
1832: }
1833: /* Allocate DMA buffers */
1834: if (yds_allocate_slots(sc)) {
1835: printf("%s: could not allocate slots\n", sc->sc_dev.dv_xname);
1836: return -1;
1837: }
1838:
1839: /* Warm reset */
1840: reg = pci_conf_read(pc, sc->sc_pcitag, YDS_PCI_DSCTRL);
1841: pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL, reg | YDS_DSCTRL_WRST);
1842: delay(50000);
1843:
1844: /*
1845: * Detect primary/secondary AC97
1846: * YMF754 Hardware Specification Rev 1.01 page 24
1847: */
1848: reg = pci_conf_read(pc, sc->sc_pcitag, YDS_PCI_DSCTRL);
1849: pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL,
1850: reg & ~YDS_DSCTRL_CRST);
1851: delay(400000); /* Needed for 740C. */
1852:
1853: /* Primary */
1854: for (to = 0; to < AC97_TIMEOUT; to++) {
1855: if ((YREAD2(sc, AC97_STAT_ADDR1) & AC97_BUSY) == 0)
1856: break;
1857: delay(1);
1858: }
1859: if (to == AC97_TIMEOUT) {
1860: printf("%s: no AC97 available\n", sc->sc_dev.dv_xname);
1861: return -1;
1862: }
1863:
1864: /* Secondary */
1865: /* Secondary AC97 is used for 4ch audio. Currently unused. */
1866: ac97_id2 = -1;
1867: if ((YREAD2(sc, YDS_ACTIVITY) & YDS_ACTIVITY_DOCKA) == 0)
1868: goto detected;
1869: #if 0 /* reset secondary... */
1870: YWRITE2(sc, YDS_GPIO_OCTRL,
1871: YREAD2(sc, YDS_GPIO_OCTRL) & ~YDS_GPIO_GPO2);
1872: YWRITE2(sc, YDS_GPIO_FUNCE,
1873: (YREAD2(sc, YDS_GPIO_FUNCE)&(~YDS_GPIO_GPC2))|YDS_GPIO_GPE2);
1874: #endif
1875: for (to = 0; to < AC97_TIMEOUT; to++) {
1876: if ((YREAD2(sc, AC97_STAT_ADDR2) & AC97_BUSY) == 0)
1877: break;
1878: delay(1);
1879: }
1880: if (to < AC97_TIMEOUT) {
1881: /* detect id */
1882: for (ac97_id2 = 1; ac97_id2 < 4; ac97_id2++) {
1883: YWRITE2(sc, AC97_CMD_ADDR,
1884: AC97_CMD_READ | AC97_ID(ac97_id2) | 0x28);
1885:
1886: for (to = 0; to < AC97_TIMEOUT; to++) {
1887: if ((YREAD2(sc, AC97_STAT_ADDR2) & AC97_BUSY)
1888: == 0)
1889: goto detected;
1890: delay(1);
1891: }
1892: }
1893: if (ac97_id2 == 4)
1894: ac97_id2 = -1;
1895: detected:
1896: ;
1897: }
1898:
1899: pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL,
1900: reg | YDS_DSCTRL_CRST);
1901: delay (20);
1902: pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL,
1903: reg & ~YDS_DSCTRL_CRST);
1904: delay (400000);
1905: for (to = 0; to < AC97_TIMEOUT; to++) {
1906: if ((YREAD2(sc, AC97_STAT_ADDR1) & AC97_BUSY) == 0)
1907: break;
1908: delay(1);
1909: }
1910:
1911: DPRINTF(("out of yds_init()\n"));
1912:
1913: return 0;
1914: }
CVSweb