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