1 /* $OpenBSD: autri.c,v 1.51 2024/05/24 06:02:53 jsg Exp $ */
2
3 /*
4 * Copyright (c) 2001 SOMEYA Yoshihiko and KUROSAWA Takahiro.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /*
29 * Trident 4DWAVE-DX/NX, SiS 7018, ALi M5451 Sound Driver
30 *
31 * The register information is taken from the ALSA driver.
32 *
33 * Documentation links:
34 * - ftp://ftp.alsa-project.org/pub/manuals/trident/
35 */
36
37 #include "midi.h"
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/fcntl.h>
42 #include <sys/malloc.h>
43 #include <sys/device.h>
44
45 #include <dev/pci/pcidevs.h>
46 #include <dev/pci/pcireg.h>
47 #include <dev/pci/pcivar.h>
48
49 #include <sys/audioio.h>
50 #include <dev/audio_if.h>
51 #include <dev/midi_if.h>
52 #include <dev/ic/ac97.h>
53
54 #include <machine/bus.h>
55 #include <machine/intr.h>
56
57 #include <dev/pci/autrireg.h>
58 #include <dev/pci/autrivar.h>
59
60 #ifdef AUDIO_DEBUG
61 # define DPRINTF(x) if (autridebug) printf x
62 # define DPRINTFN(n,x) if (autridebug > (n)) printf x
63 int autridebug = 0;
64 #else
65 # define DPRINTF(x)
66 # define DPRINTFN(n,x)
67 #endif
68
69 int autri_match(struct device *, void *, void *);
70 void autri_attach(struct device *, struct device *, void *);
71 int autri_activate(struct device *, int);
72 int autri_intr(void *);
73
74 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
75 #define KERNADDR(p) ((void *)((p)->addr))
76
77 int autri_allocmem(struct autri_softc *, size_t, size_t, struct autri_dma *);
78 int autri_freemem(struct autri_softc *, struct autri_dma *);
79
80 #define TWRITE1(sc, r, x) bus_space_write_1((sc)->memt, (sc)->memh, (r), (x))
81 #define TWRITE2(sc, r, x) bus_space_write_2((sc)->memt, (sc)->memh, (r), (x))
82 #define TWRITE4(sc, r, x) bus_space_write_4((sc)->memt, (sc)->memh, (r), (x))
83 #define TREAD1(sc, r) bus_space_read_1((sc)->memt, (sc)->memh, (r))
84 #define TREAD2(sc, r) bus_space_read_2((sc)->memt, (sc)->memh, (r))
85 #define TREAD4(sc, r) bus_space_read_4((sc)->memt, (sc)->memh, (r))
86
87 static __inline void autri_reg_set_1(struct autri_softc *, int, uint8_t);
88 static __inline void autri_reg_clear_1(struct autri_softc *, int, uint8_t);
89 static __inline void autri_reg_set_4(struct autri_softc *, int, uint32_t);
90 static __inline void autri_reg_clear_4(struct autri_softc *, int, uint32_t);
91
92 int autri_attach_codec(void *sc, struct ac97_codec_if *);
93 int autri_read_codec(void *sc, u_int8_t a, u_int16_t *d);
94 int autri_write_codec(void *sc, u_int8_t a, u_int16_t d);
95 void autri_reset_codec(void *sc);
96 enum ac97_host_flags autri_flags_codec(void *);
97
98 int autri_init(void *sc);
99 struct autri_dma *autri_find_dma(struct autri_softc *, void *);
100 void autri_setup_channel(struct autri_softc *sc,int mode,
101 struct audio_params *param);
102 void autri_enable_interrupt(struct autri_softc *sc, int ch);
103 void autri_disable_interrupt(struct autri_softc *sc, int ch);
104 void autri_startch(struct autri_softc *sc, int ch, int ch_intr);
105 void autri_stopch(struct autri_softc *sc, int ch, int ch_intr);
106 void autri_enable_loop_interrupt(void *sc);
107 #if 0
108 void autri_disable_loop_interrupt(void *sc);
109 #endif
110
111 struct cfdriver autri_cd = {
112 NULL, "autri", DV_DULL
113 };
114
115 const struct cfattach autri_ca = {
116 sizeof(struct autri_softc), autri_match, autri_attach, NULL,
117 autri_activate
118 };
119
120 int autri_open(void *, int);
121 void autri_close(void *);
122 int autri_set_params(void *, int, int, struct audio_params *,
123 struct audio_params *);
124 int autri_round_blocksize(void *, int);
125 int autri_trigger_output(void *, void *, void *, int, void (*)(void *),
126 void *, struct audio_params *);
127 int autri_trigger_input(void *, void *, void *, int, void (*)(void *),
128 void *, struct audio_params *);
129 int autri_halt_output(void *);
130 int autri_halt_input(void *);
131 int autri_mixer_set_port(void *, mixer_ctrl_t *);
132 int autri_mixer_get_port(void *, mixer_ctrl_t *);
133 void *autri_malloc(void *, int, size_t, int, int);
134 void autri_free(void *, void *, int);
135 int autri_query_devinfo(void *addr, mixer_devinfo_t *dip);
136
137 int autri_get_portnum_by_name(struct autri_softc *, char *, char *, char *);
138
139 const struct audio_hw_if autri_hw_if = {
140 .open = autri_open,
141 .close = autri_close,
142 .set_params = autri_set_params,
143 .round_blocksize = autri_round_blocksize,
144 .halt_output = autri_halt_output,
145 .halt_input = autri_halt_input,
146 .set_port = autri_mixer_set_port,
147 .get_port = autri_mixer_get_port,
148 .query_devinfo = autri_query_devinfo,
149 .allocm = autri_malloc,
150 .freem = autri_free,
151 .trigger_output = autri_trigger_output,
152 .trigger_input = autri_trigger_input,
153 };
154
155 #if NMIDI > 0
156 void autri_midi_close(void *);
157 void autri_midi_getinfo(void *, struct midi_info *);
158 int autri_midi_open(void *, int, void (*)(void *, int),
159 void (*)(void *), void *);
160 int autri_midi_output(void *, int);
161
162 const struct midi_hw_if autri_midi_hw_if = {
163 autri_midi_open,
164 autri_midi_close,
165 autri_midi_output,
166 NULL, /* flush */
167 autri_midi_getinfo,
168 NULL, /* ioctl */
169 };
170 #endif
171
172 /*
173 * register set/clear bit
174 */
175 static __inline void
autri_reg_set_1(struct autri_softc * sc,int no,uint8_t mask)176 autri_reg_set_1(struct autri_softc *sc, int no, uint8_t mask)
177 {
178 bus_space_write_1(sc->memt, sc->memh, no,
179 (bus_space_read_1(sc->memt, sc->memh, no) | mask));
180 }
181
182 static __inline void
autri_reg_clear_1(struct autri_softc * sc,int no,uint8_t mask)183 autri_reg_clear_1(struct autri_softc *sc, int no, uint8_t mask)
184 {
185 bus_space_write_1(sc->memt, sc->memh, no,
186 (bus_space_read_1(sc->memt, sc->memh, no) & ~mask));
187 }
188
189 static __inline void
autri_reg_set_4(struct autri_softc * sc,int no,uint32_t mask)190 autri_reg_set_4(struct autri_softc *sc, int no, uint32_t mask)
191 {
192 bus_space_write_4(sc->memt, sc->memh, no,
193 (bus_space_read_4(sc->memt, sc->memh, no) | mask));
194 }
195
196 static __inline void
autri_reg_clear_4(struct autri_softc * sc,int no,uint32_t mask)197 autri_reg_clear_4(struct autri_softc *sc, int no, uint32_t mask)
198 {
199 bus_space_write_4(sc->memt, sc->memh, no,
200 (bus_space_read_4(sc->memt, sc->memh, no) & ~mask));
201 }
202
203 /*
204 * AC97 codec
205 */
206 int
autri_attach_codec(void * sc_,struct ac97_codec_if * codec_if)207 autri_attach_codec(void *sc_, struct ac97_codec_if *codec_if)
208 {
209 struct autri_codec_softc *sc = sc_;
210
211 DPRINTF(("autri_attach_codec()\n"));
212
213 sc->codec_if = codec_if;
214 return 0;
215 }
216
217 int
autri_read_codec(void * sc_,u_int8_t index,u_int16_t * data)218 autri_read_codec(void *sc_, u_int8_t index, u_int16_t *data)
219 {
220 struct autri_codec_softc *codec = sc_;
221 struct autri_softc *sc = codec->sc;
222 u_int32_t status, addr, cmd, busy;
223 u_int16_t count;
224
225 /*DPRINTF(("sc->sc->type : 0x%X",sc->sc->type));*/
226
227 switch (sc->sc_devid) {
228 case AUTRI_DEVICE_ID_4DWAVE_DX:
229 addr = AUTRI_DX_ACR1;
230 cmd = AUTRI_DX_ACR1_CMD_READ;
231 busy = AUTRI_DX_ACR1_BUSY_READ;
232 break;
233 case AUTRI_DEVICE_ID_4DWAVE_NX:
234 addr = AUTRI_NX_ACR2;
235 cmd = AUTRI_NX_ACR2_CMD_READ;
236 busy = AUTRI_NX_ACR2_BUSY_READ | AUTRI_NX_ACR2_RECV_WAIT;
237 break;
238 case AUTRI_DEVICE_ID_SIS_7018:
239 addr = AUTRI_SIS_ACRD;
240 cmd = AUTRI_SIS_ACRD_CMD_READ;
241 busy = AUTRI_SIS_ACRD_BUSY_READ | AUTRI_SIS_ACRD_AUDIO_BUSY;
242 break;
243 case AUTRI_DEVICE_ID_ALI_M5451:
244 if (sc->sc_revision > 0x01)
245 addr = AUTRI_ALI_ACWR;
246 else
247 addr = AUTRI_ALI_ACRD;
248 cmd = AUTRI_ALI_ACRD_CMD_READ;
249 busy = AUTRI_ALI_ACRD_BUSY_READ;
250 break;
251 default:
252 printf("%s: autri_read_codec : unknown device\n",
253 sc->sc_dev.dv_xname);
254 return -1;
255 }
256
257 /* wait for 'Ready to Read' */
258 for (count=0; count < 0xffff; count++) {
259 if ((TREAD4(sc, addr) & busy) == 0)
260 break;
261 DELAY(1);
262 }
263
264 if (count == 0xffff) {
265 printf("%s: Codec timeout. Busy reading AC97 codec.\n",
266 sc->sc_dev.dv_xname);
267 return -1;
268 }
269
270 /* send Read Command to AC97 */
271 TWRITE4(sc, addr, (index & 0x7f) | cmd);
272
273 /* wait for 'Returned data is available' */
274 for (count=0; count < 0xffff; count++) {
275 status = TREAD4(sc, addr);
276 if ((status & busy) == 0)
277 break;
278 DELAY(1);
279 }
280
281 if (count == 0xffff) {
282 printf("%s: Codec timeout. Busy reading AC97 codec.\n",
283 sc->sc_dev.dv_xname);
284 return -1;
285 }
286
287 *data = (status >> 16) & 0x0000ffff;
288 /*DPRINTF(("autri_read_codec(0x%X) return 0x%X\n",reg,*data));*/
289 return 0;
290 }
291
292 int
autri_write_codec(void * sc_,u_int8_t index,u_int16_t data)293 autri_write_codec(void *sc_, u_int8_t index, u_int16_t data)
294 {
295 struct autri_codec_softc *codec = sc_;
296 struct autri_softc *sc = codec->sc;
297 u_int32_t addr, cmd, busy;
298 u_int16_t count;
299
300 /*DPRINTF(("autri_write_codec(0x%X,0x%X)\n",index,data));*/
301
302 switch (sc->sc_devid) {
303 case AUTRI_DEVICE_ID_4DWAVE_DX:
304 addr = AUTRI_DX_ACR0;
305 cmd = AUTRI_DX_ACR0_CMD_WRITE;
306 busy = AUTRI_DX_ACR0_BUSY_WRITE;
307 break;
308 case AUTRI_DEVICE_ID_4DWAVE_NX:
309 addr = AUTRI_NX_ACR1;
310 cmd = AUTRI_NX_ACR1_CMD_WRITE;
311 busy = AUTRI_NX_ACR1_BUSY_WRITE;
312 break;
313 case AUTRI_DEVICE_ID_SIS_7018:
314 addr = AUTRI_SIS_ACWR;
315 cmd = AUTRI_SIS_ACWR_CMD_WRITE;
316 busy = AUTRI_SIS_ACWR_BUSY_WRITE | AUTRI_SIS_ACWR_AUDIO_BUSY;
317 break;
318 case AUTRI_DEVICE_ID_ALI_M5451:
319 addr = AUTRI_ALI_ACWR;
320 cmd = AUTRI_ALI_ACWR_CMD_WRITE;
321 if (sc->sc_revision > 0x01)
322 cmd |= 0x0100;
323 busy = AUTRI_ALI_ACWR_BUSY_WRITE;
324 break;
325 default:
326 printf("%s: autri_write_codec : unknown device.\n",
327 sc->sc_dev.dv_xname);
328 return -1;
329 }
330
331 /* wait for 'Ready to Write' */
332 for (count=0; count < 0xffff; count++) {
333 if ((TREAD4(sc, addr) & busy) == 0)
334 break;
335 DELAY(1);
336 }
337
338 if (count == 0xffff) {
339 printf("%s: Codec timeout. Busy writing AC97 codec\n",
340 sc->sc_dev.dv_xname);
341 return -1;
342 }
343
344 /* send Write Command to AC97 */
345 TWRITE4(sc, addr, (data << 16) | (index & 0x7f) | cmd);
346
347 return 0;
348 }
349
350 void
autri_reset_codec(void * sc_)351 autri_reset_codec(void *sc_)
352 {
353 struct autri_codec_softc *codec = sc_;
354 struct autri_softc *sc = codec->sc;
355 u_int32_t reg, ready;
356 int addr, count = 200;
357
358 DPRINTF(("autri_reset_codec(codec=%p,sc=%p)\n",codec,sc));
359 DPRINTF(("sc->sc_devid=%X\n",sc->sc_devid));
360
361 switch (sc->sc_devid) {
362 case AUTRI_DEVICE_ID_4DWAVE_DX:
363 /* warm reset AC97 codec */
364 autri_reg_set_4(sc, AUTRI_DX_ACR2, 1);
365 delay(100);
366 /* release reset */
367 autri_reg_clear_4(sc, AUTRI_DX_ACR2, 1);
368 delay(100);
369
370 addr = AUTRI_DX_ACR2;
371 ready = AUTRI_DX_ACR2_CODEC_READY;
372 break;
373 case AUTRI_DEVICE_ID_4DWAVE_NX:
374 /* warm reset AC97 codec */
375 autri_reg_set_4(sc, AUTRI_NX_ACR0, 1);
376 delay(100);
377 /* release reset */
378 autri_reg_clear_4(sc, AUTRI_NX_ACR0, 1);
379 delay(100);
380
381 addr = AUTRI_NX_ACR0;
382 ready = AUTRI_NX_ACR0_CODEC_READY;
383 break;
384 case AUTRI_DEVICE_ID_SIS_7018:
385 /* warm reset AC97 codec */
386 autri_reg_set_4(sc, AUTRI_SIS_SCTRL, 2);
387 delay(1000);
388 /* release reset (warm & cold) */
389 autri_reg_clear_4(sc, AUTRI_SIS_SCTRL, 3);
390 delay(2000);
391
392 addr = AUTRI_SIS_SCTRL;
393 ready = AUTRI_SIS_SCTRL_CODEC_READY;
394 break;
395 case AUTRI_DEVICE_ID_ALI_M5451:
396 /* warm reset AC97 codec */
397 autri_reg_set_4(sc, AUTRI_ALI_SCTRL, 1);
398 delay(100);
399 /* release reset (warm & cold) */
400 autri_reg_clear_4(sc, AUTRI_ALI_SCTRL, 3);
401 delay(100);
402
403 addr = AUTRI_ALI_SCTRL;
404 ready = AUTRI_ALI_SCTRL_CODEC_READY;
405 break;
406 }
407
408 /* wait for 'Codec Ready' */
409 while (count--) {
410 reg = TREAD4(sc, addr);
411 if (reg & ready)
412 break;
413 delay(1000);
414 }
415
416 if (count == 0)
417 printf("%s: Codec timeout. AC97 is not ready for operation.\n",
418 sc->sc_dev.dv_xname);
419 }
420
421 enum ac97_host_flags
autri_flags_codec(void * v)422 autri_flags_codec(void *v)
423 {
424 struct autri_codec_softc *sc = v;
425
426 return (sc->flags);
427 }
428
429 /*
430 *
431 */
432 const struct pci_matchid autri_devices[] = {
433 { PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_4DWAVE_NX },
434 { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7018 },
435 { PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5451 }
436 };
437
438 int
autri_match(struct device * parent,void * match,void * aux)439 autri_match(struct device *parent, void *match, void *aux)
440 {
441 struct pci_attach_args *pa = aux;
442
443 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TRIDENT &&
444 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TRIDENT_4DWAVE_DX) {
445 /*
446 * IBM makes a pcn network card and improperly
447 * sets the vendor and product ID's. Avoid matching.
448 */
449 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_NETWORK)
450 return (0);
451 else
452 return (1);
453 }
454
455 return (pci_matchbyid((struct pci_attach_args *)aux, autri_devices,
456 nitems(autri_devices)));
457 }
458
459 void
autri_attach(struct device * parent,struct device * self,void * aux)460 autri_attach(struct device *parent, struct device *self, void *aux)
461 {
462 struct autri_softc *sc = (struct autri_softc *)self;
463 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
464 pci_chipset_tag_t pc = pa->pa_pc;
465 struct autri_codec_softc *codec;
466 bus_size_t iosize;
467 pci_intr_handle_t ih;
468 char const *intrstr;
469 mixer_ctrl_t ctl;
470 int i, r;
471
472 sc->sc_devid = pa->pa_id;
473 sc->sc_class = pa->pa_class;
474 sc->sc_revision = PCI_REVISION(pa->pa_class);
475
476 /* map register to memory */
477 if (pci_mapreg_map(pa, AUTRI_PCI_MEMORY_BASE,
478 PCI_MAPREG_TYPE_MEM, 0, &sc->memt, &sc->memh, NULL, &iosize, 0)) {
479 printf("%s: can't map mem space\n", sc->sc_dev.dv_xname);
480 return;
481 }
482
483 /* map and establish the interrupt */
484 if (pci_intr_map(pa, &ih)) {
485 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
486 bus_space_unmap(sc->memt, sc->memh, iosize);
487 return;
488 }
489 intrstr = pci_intr_string(pc, ih);
490 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
491 autri_intr, sc, sc->sc_dev.dv_xname);
492 if (sc->sc_ih == NULL) {
493 printf("%s: couldn't establish interrupt",
494 sc->sc_dev.dv_xname);
495 if (intrstr != NULL)
496 printf(" at %s", intrstr);
497 printf("\n");
498 bus_space_unmap(sc->memt, sc->memh, iosize);
499 return;
500 }
501 printf(": %s\n", intrstr);
502
503 sc->sc_dmatag = pa->pa_dmat;
504 sc->sc_pc = pc;
505 sc->sc_pt = pa->pa_tag;
506
507 /* initialize the device */
508 autri_init(sc);
509
510 /* attach AC97 codec */
511 codec = &sc->sc_codec;
512 memcpy(&codec->sc_dev, &sc->sc_dev, sizeof(codec->sc_dev));
513 codec->sc = sc;
514
515 codec->host_if.arg = codec;
516 codec->host_if.attach = autri_attach_codec;
517 codec->host_if.reset = autri_reset_codec;
518 codec->host_if.read = autri_read_codec;
519 codec->host_if.write = autri_write_codec;
520 codec->host_if.flags = autri_flags_codec;
521 codec->flags = AC97_HOST_DONT_READ | AC97_HOST_SWAPPED_CHANNELS;
522 if (sc->sc_dev.dv_cfdata->cf_flags & 0x0001)
523 codec->flags &= ~AC97_HOST_SWAPPED_CHANNELS;
524
525 if ((r = ac97_attach(&codec->host_if)) != 0) {
526 printf("%s: can't attach codec (error 0x%X)\n",
527 sc->sc_dev.dv_xname, r);
528 pci_intr_disestablish(pc, sc->sc_ih);
529 bus_space_unmap(sc->memt, sc->memh, iosize);
530 return;
531 }
532
533 /* disable mutes */
534 for (i = 0; i < 4; i++) {
535 static struct {
536 char *class, *device;
537 } d[] = {
538 { AudioCoutputs, AudioNmaster},
539 { AudioCinputs, AudioNdac},
540 { AudioCinputs, AudioNcd},
541 { AudioCrecord, AudioNvolume},
542 };
543
544 ctl.type = AUDIO_MIXER_ENUM;
545 ctl.un.ord = 0;
546
547 #if 0
548 ctl.dev = sc->sc_codec.codec_if->vtbl->get_portnum_by_name(sc->sc_codec.codec_if,
549 d[i].class, d[i].device, AudioNmute);
550 #endif
551 ctl.dev = autri_get_portnum_by_name(sc,d[i].class,
552 d[i].device, AudioNmute);
553 autri_mixer_set_port(sc, &ctl);
554 }
555
556 /* set a reasonable default volume */
557 ctl.type = AUDIO_MIXER_VALUE;
558 ctl.un.value.num_channels = 2;
559 ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
560 ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
561
562 ctl.dev = autri_get_portnum_by_name(sc,AudioCoutputs,AudioNmaster,NULL);
563 autri_mixer_set_port(sc, &ctl);
564
565 audio_attach_mi(&autri_hw_if, sc, NULL, &sc->sc_dev);
566
567 #if NMIDI > 0
568 midi_attach_mi(&autri_midi_hw_if, sc, &sc->sc_dev);
569 #endif
570 }
571
572 int
autri_activate(struct device * self,int act)573 autri_activate(struct device *self, int act)
574 {
575 struct autri_softc *sc = (struct autri_softc *)self;
576
577 if (act == DVACT_RESUME) {
578 autri_init(sc);
579 ac97_resume(&sc->sc_codec.host_if, sc->sc_codec.codec_if);
580 }
581 return (config_activate_children(self, act));
582 }
583
584 int
autri_init(void * sc_)585 autri_init(void *sc_)
586 {
587 struct autri_softc *sc = sc_;
588 pcireg_t reg;
589
590 pci_chipset_tag_t pc = sc->sc_pc;
591 pcitag_t pt = sc->sc_pt;
592
593 DPRINTF(("in autri_init()\n"));
594 DPRINTFN(5,("pci_conf_read(0x40) : 0x%X\n",pci_conf_read(pc,pt,0x40)));
595 DPRINTFN(5,("pci_conf_read(0x44) : 0x%X\n",pci_conf_read(pc,pt,0x44)));
596
597 switch (sc->sc_devid) {
598 case AUTRI_DEVICE_ID_4DWAVE_DX:
599 /* disable Legacy Control */
600 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
601 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
602 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
603 delay(100);
604 /* audio engine reset */
605 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
606 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00040000);
607 delay(100);
608 /* release reset */
609 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
610 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
611 delay(100);
612 /* DAC on */
613 autri_reg_set_4(sc,AUTRI_DX_ACR2,0x02);
614 break;
615 case AUTRI_DEVICE_ID_4DWAVE_NX:
616 /* disable Legacy Control */
617 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
618 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
619 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
620 delay(100);
621 /* audio engine reset */
622 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
623 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00010000);
624 delay(100);
625 /* release reset */
626 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
627 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00010000);
628 delay(100);
629 /* DAC on */
630 autri_reg_set_4(sc,AUTRI_NX_ACR0,0x02);
631 break;
632 case AUTRI_DEVICE_ID_SIS_7018:
633 /* disable Legacy Control */
634 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
635 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
636 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
637 delay(100);
638 /* reset Digital Controller */
639 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
640 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000);
641 delay(100);
642 /* release reset */
643 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
644 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
645 delay(100);
646 /* disable AC97 GPIO interrupt */
647 TWRITE1(sc, AUTRI_SIS_ACGPIO, 0);
648 /* enable 64 channel mode */
649 autri_reg_set_4(sc, AUTRI_LFO_GC_CIR, BANK_B_EN);
650 break;
651 case AUTRI_DEVICE_ID_ALI_M5451:
652 /* disable Legacy Control */
653 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
654 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
655 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
656 delay(100);
657 /* reset Digital Controller */
658 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
659 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000);
660 delay(100);
661 /* release reset */
662 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
663 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
664 delay(100);
665 /* enable PCM input */
666 autri_reg_set_4(sc, AUTRI_ALI_GCONTROL, AUTRI_ALI_GCONTROL_PCM_IN);
667 break;
668 }
669
670 if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) {
671 sc->sc_play.ch = 0;
672 sc->sc_play.ch_intr = 1;
673 sc->sc_rec.ch = 2;
674 sc->sc_rec.ch_intr = 3;
675 } else {
676 sc->sc_play.ch = 0x20;
677 sc->sc_play.ch_intr = 0x21;
678 sc->sc_rec.ch = 0x22;
679 sc->sc_rec.ch_intr = 0x23;
680 }
681
682 /* clear channel status */
683 TWRITE4(sc, AUTRI_STOP_A, 0xffffffff);
684 TWRITE4(sc, AUTRI_STOP_B, 0xffffffff);
685
686 /* disable channel interrupt */
687 TWRITE4(sc, AUTRI_AINTEN_A, 0);
688 TWRITE4(sc, AUTRI_AINTEN_B, 0);
689
690 #if 0
691 /* TLB */
692 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
693 TWRITE4(sc,AUTRI_NX_TLBC,0);
694 }
695 #endif
696
697 autri_enable_loop_interrupt(sc);
698
699 DPRINTF(("out autri_init()\n"));
700 return 0;
701 }
702
703 void
autri_enable_loop_interrupt(void * sc_)704 autri_enable_loop_interrupt(void *sc_)
705 {
706 struct autri_softc *sc = sc_;
707 u_int32_t reg;
708
709 /*reg = (ENDLP_IE | MIDLP_IE);*/
710 reg = ENDLP_IE;
711 #if 0
712 if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018)
713 reg |= BANK_B_EN;
714 #endif
715 autri_reg_set_4(sc,AUTRI_LFO_GC_CIR,reg);
716 }
717
718 #if 0
719 void
720 autri_disable_loop_interrupt(void *sc_)
721 {
722 struct autri_softc *sc = sc_;
723 u_int32_t reg;
724
725 reg = (ENDLP_IE | MIDLP_IE);
726 autri_reg_clear_4(sc,AUTRI_LFO_GC_CIR,reg);
727 }
728 #endif
729
730 int
autri_intr(void * p)731 autri_intr(void *p)
732 {
733 struct autri_softc *sc = p;
734 u_int32_t intsrc;
735 u_int32_t mask, active[2];
736 int ch, endch;
737 /*
738 u_int32_t reg;
739 u_int32_t cso,eso;
740 */
741
742 mtx_enter(&audio_lock);
743 intsrc = TREAD4(sc,AUTRI_MISCINT);
744 if ((intsrc & (ADDRESS_IRQ|MPU401_IRQ)) == 0) {
745 mtx_leave(&audio_lock);
746 return 0;
747 }
748
749 if (intsrc & ADDRESS_IRQ) {
750
751 active[0] = TREAD4(sc,AUTRI_AIN_A);
752 active[1] = TREAD4(sc,AUTRI_AIN_B);
753
754 if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) {
755 endch = 32;
756 } else {
757 endch = 64;
758 }
759
760 for (ch=0; ch<endch; ch++) {
761 mask = 1 << (ch & 0x1f);
762 if (active[(ch & 0x20) ? 1 : 0] & mask) {
763
764 /* clear interrupt */
765 TWRITE4(sc, (ch & 0x20) ? AUTRI_AIN_B : AUTRI_AIN_A, mask);
766 /* disable interrupt */
767 autri_reg_clear_4(sc,(ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask);
768 #if 0
769 reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f;
770 TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | ch);
771
772 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
773 cso = TREAD4(sc, 0xe0) & 0x00ffffff;
774 eso = TREAD4(sc, 0xe8) & 0x00ffffff;
775 } else {
776 cso = (TREAD4(sc, 0xe0) >> 16) & 0x0000ffff;
777 eso = (TREAD4(sc, 0xe8) >> 16) & 0x0000ffff;
778 }
779 /*printf("cso=%d, eso=%d\n",cso,eso);*/
780 #endif
781 if (ch == sc->sc_play.ch_intr) {
782 if (sc->sc_play.intr)
783 sc->sc_play.intr(sc->sc_play.intr_arg);
784 }
785
786 if (ch == sc->sc_rec.ch_intr) {
787 if (sc->sc_rec.intr)
788 sc->sc_rec.intr(sc->sc_rec.intr_arg);
789 }
790
791 /* enable interrupt */
792 autri_reg_set_4(sc, (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask);
793 }
794 }
795 }
796
797 if (intsrc & MPU401_IRQ) {
798 /* XXX */
799 }
800
801 autri_reg_set_4(sc,AUTRI_MISCINT,
802 ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW);
803 mtx_leave(&audio_lock);
804 return 1;
805 }
806
807 /*
808 *
809 */
810
811 int
autri_allocmem(struct autri_softc * sc,size_t size,size_t align,struct autri_dma * p)812 autri_allocmem(struct autri_softc *sc, size_t size, size_t align,
813 struct autri_dma *p)
814 {
815 int error;
816
817 p->size = size;
818 error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
819 p->segs, nitems(p->segs), &p->nsegs, BUS_DMA_NOWAIT);
820 if (error)
821 return (error);
822
823 error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
824 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
825 if (error)
826 goto free;
827
828 error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
829 0, BUS_DMA_NOWAIT, &p->map);
830 if (error)
831 goto unmap;
832
833 error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
834 BUS_DMA_NOWAIT);
835 if (error)
836 goto destroy;
837 return (0);
838
839 destroy:
840 bus_dmamap_destroy(sc->sc_dmatag, p->map);
841 unmap:
842 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
843 free:
844 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
845 return (error);
846 }
847
848 int
autri_freemem(struct autri_softc * sc,struct autri_dma * p)849 autri_freemem(struct autri_softc *sc, struct autri_dma *p)
850 {
851 bus_dmamap_unload(sc->sc_dmatag, p->map);
852 bus_dmamap_destroy(sc->sc_dmatag, p->map);
853 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
854 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
855 return 0;
856 }
857
858 int
autri_open(void * addr,int flags)859 autri_open(void *addr, int flags)
860 {
861 DPRINTF(("autri_open()\n"));
862 DPRINTFN(5,("MISCINT : 0x%08X\n",
863 TREAD4((struct autri_softc *)addr, AUTRI_MISCINT)));
864 DPRINTFN(5,("LFO_GC_CIR : 0x%08X\n",
865 TREAD4((struct autri_softc *)addr, AUTRI_LFO_GC_CIR)));
866 return 0;
867 }
868
869 void
autri_close(void * addr)870 autri_close(void *addr)
871 {
872 DPRINTF(("autri_close()\n"));
873 }
874
875 int
autri_set_params(void * addr,int setmode,int usemode,struct audio_params * play,struct audio_params * rec)876 autri_set_params(void *addr, int setmode, int usemode, struct audio_params *play,
877 struct audio_params *rec)
878 {
879 struct audio_params *p;
880 int mode;
881
882 for (mode = AUMODE_RECORD; mode != -1;
883 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
884 if ((setmode & mode) == 0)
885 continue;
886 p = mode == AUMODE_PLAY ? play : rec;
887 p->sample_rate = 48000;
888 if (p->precision != 8)
889 p->precision = 16;
890 if (p->channels != 1)
891 p->channels = 2;
892 p->encoding = p->precision == 16 ?
893 AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_ULINEAR_LE;
894 p->bps = AUDIO_BPS(p->precision);
895 p->msb = 1;
896 }
897
898 return 0;
899 }
900
901 int
autri_round_blocksize(void * addr,int block)902 autri_round_blocksize(void *addr, int block)
903 {
904 return ((block + 3) & -4);
905 }
906
907 int
autri_halt_output(void * addr)908 autri_halt_output(void *addr)
909 {
910 struct autri_softc *sc = addr;
911
912 DPRINTF(("autri_halt_output()\n"));
913 mtx_enter(&audio_lock);
914 sc->sc_play.intr = NULL;
915 autri_stopch(sc, sc->sc_play.ch, sc->sc_play.ch_intr);
916 autri_disable_interrupt(sc, sc->sc_play.ch_intr);
917 mtx_leave(&audio_lock);
918 return 0;
919 }
920
921 int
autri_halt_input(void * addr)922 autri_halt_input(void *addr)
923 {
924 struct autri_softc *sc = addr;
925
926 DPRINTF(("autri_halt_input()\n"));
927 mtx_enter(&audio_lock);
928 sc->sc_rec.intr = NULL;
929 autri_stopch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr);
930 autri_disable_interrupt(sc, sc->sc_rec.ch_intr);
931 mtx_leave(&audio_lock);
932 return 0;
933 }
934
935 int
autri_mixer_set_port(void * addr,mixer_ctrl_t * cp)936 autri_mixer_set_port(void *addr, mixer_ctrl_t *cp)
937 {
938 struct autri_softc *sc = addr;
939
940 return (sc->sc_codec.codec_if->vtbl->mixer_set_port(
941 sc->sc_codec.codec_if, cp));
942 }
943
944 int
autri_mixer_get_port(void * addr,mixer_ctrl_t * cp)945 autri_mixer_get_port(void *addr, mixer_ctrl_t *cp)
946 {
947 struct autri_softc *sc = addr;
948
949 return (sc->sc_codec.codec_if->vtbl->mixer_get_port(
950 sc->sc_codec.codec_if, cp));
951 }
952
953 int
autri_query_devinfo(void * addr,mixer_devinfo_t * dip)954 autri_query_devinfo(void *addr, mixer_devinfo_t *dip)
955 {
956 struct autri_softc *sc = addr;
957
958 return (sc->sc_codec.codec_if->vtbl->query_devinfo(
959 sc->sc_codec.codec_if, dip));
960 }
961
962 int
autri_get_portnum_by_name(struct autri_softc * sc,char * class,char * device,char * qualifier)963 autri_get_portnum_by_name(struct autri_softc *sc, char *class, char *device,
964 char *qualifier)
965 {
966 return (sc->sc_codec.codec_if->vtbl->get_portnum_by_name(
967 sc->sc_codec.codec_if, class, device, qualifier));
968 }
969
970 void *
autri_malloc(void * addr,int direction,size_t size,int pool,int flags)971 autri_malloc(void *addr, int direction, size_t size, int pool, int flags)
972 {
973 struct autri_softc *sc = addr;
974 struct autri_dma *p;
975 int error;
976
977 p = malloc(sizeof(*p), pool, flags);
978 if (!p)
979 return NULL;
980
981 #if 0
982 error = autri_allocmem(sc, size, 16, p);
983 #endif
984 error = autri_allocmem(sc, size, 0x10000, p);
985 if (error) {
986 free(p, pool, sizeof(*p));
987 return NULL;
988 }
989
990 p->next = sc->sc_dmas;
991 sc->sc_dmas = p;
992 return KERNADDR(p);
993 }
994
995 void
autri_free(void * addr,void * ptr,int pool)996 autri_free(void *addr, void *ptr, int pool)
997 {
998 struct autri_softc *sc = addr;
999 struct autri_dma **pp, *p;
1000
1001 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
1002 if (KERNADDR(p) == ptr) {
1003 autri_freemem(sc, p);
1004 *pp = p->next;
1005 free(p, pool, sizeof(*p));
1006 return;
1007 }
1008 }
1009 }
1010
1011 struct autri_dma *
autri_find_dma(struct autri_softc * sc,void * addr)1012 autri_find_dma(struct autri_softc *sc, void *addr)
1013 {
1014 struct autri_dma *p;
1015
1016 for (p = sc->sc_dmas; p && KERNADDR(p) != addr; p = p->next)
1017 ;
1018
1019 return p;
1020 }
1021
1022 void
autri_setup_channel(struct autri_softc * sc,int mode,struct audio_params * param)1023 autri_setup_channel(struct autri_softc *sc, int mode, struct audio_params *param)
1024 {
1025 int i, ch, channel;
1026 u_int32_t reg, cr[5];
1027 u_int32_t cso, eso;
1028 u_int32_t delta, dch[2], ctrl;
1029 u_int32_t alpha_fms, fm_vol, attribute;
1030
1031 u_int32_t dmaaddr, dmalen;
1032 int factor, rvol, cvol;
1033 struct autri_chstatus *chst;
1034
1035 ctrl = AUTRI_CTRL_LOOPMODE;
1036 switch (param->encoding) {
1037 case AUDIO_ENCODING_SLINEAR_BE:
1038 case AUDIO_ENCODING_SLINEAR_LE:
1039 ctrl |= AUTRI_CTRL_SIGNED;
1040 break;
1041 }
1042
1043 factor = 0;
1044 if (param->precision == 16) {
1045 ctrl |= AUTRI_CTRL_16BIT;
1046 factor++;
1047 }
1048
1049 if (param->channels == 2) {
1050 ctrl |= AUTRI_CTRL_STEREO;
1051 factor++;
1052 }
1053
1054 delta = (u_int32_t)param->sample_rate;
1055 if (delta < 4000)
1056 delta = 4000;
1057 if (delta > 48000)
1058 delta = 48000;
1059
1060 attribute = 0;
1061
1062 dch[1] = ((delta << 12) / 48000) & 0x0000ffff;
1063 if (mode == AUMODE_PLAY) {
1064 chst = &sc->sc_play;
1065 dch[0] = ((delta << 12) / 48000) & 0x0000ffff;
1066 ctrl |= AUTRI_CTRL_WAVEVOL;
1067 /*
1068 if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451)
1069 ctrl |= 0x80000000;
1070 */
1071 } else {
1072 chst = &sc->sc_rec;
1073 dch[0] = ((48000 << 12) / delta) & 0x0000ffff;
1074 if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) {
1075 ctrl |= AUTRI_CTRL_MUTE_SIS;
1076 attribute = AUTRI_ATTR_PCMREC_SIS;
1077 if (delta != 48000)
1078 attribute |= AUTRI_ATTR_ENASRC_SIS;
1079 }
1080 ctrl |= AUTRI_CTRL_MUTE;
1081 }
1082
1083 dmaaddr = DMAADDR(chst->dma);
1084 cso = alpha_fms = 0;
1085 rvol = cvol = 0x7f;
1086 fm_vol = 0x0 | ((rvol & 0x7f) << 7) | (cvol & 0x7f);
1087
1088 for (ch=0; ch<2; ch++) {
1089
1090 if (ch == 0)
1091 dmalen = (chst->length >> factor);
1092 else {
1093 /* channel for interrupt */
1094 dmalen = (chst->blksize >> factor);
1095 if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018)
1096 ctrl |= AUTRI_CTRL_MUTE_SIS;
1097 else
1098 ctrl |= AUTRI_CTRL_MUTE;
1099 attribute = 0;
1100 }
1101
1102 eso = dmalen - 1;
1103
1104 switch (sc->sc_devid) {
1105 case AUTRI_DEVICE_ID_4DWAVE_DX:
1106 cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
1107 cr[1] = dmaaddr;
1108 cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
1109 cr[3] = fm_vol;
1110 cr[4] = ctrl;
1111 break;
1112 case AUTRI_DEVICE_ID_4DWAVE_NX:
1113 cr[0] = (dch[ch] << 24) | (cso & 0x00ffffff);
1114 cr[1] = dmaaddr;
1115 cr[2] = ((dch[ch] << 16) & 0xff000000) | (eso & 0x00ffffff);
1116 cr[3] = (alpha_fms << 16) | (fm_vol & 0x0000ffff);
1117 cr[4] = ctrl;
1118 break;
1119 case AUTRI_DEVICE_ID_SIS_7018:
1120 cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
1121 cr[1] = dmaaddr;
1122 cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
1123 cr[3] = attribute;
1124 cr[4] = ctrl;
1125 break;
1126 case AUTRI_DEVICE_ID_ALI_M5451:
1127 cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
1128 cr[1] = dmaaddr;
1129 cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
1130 cr[3] = 0;
1131 cr[4] = ctrl;
1132 break;
1133 }
1134
1135 /* write channel data */
1136 channel = (ch == 0) ? chst->ch : chst->ch_intr;
1137
1138 reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f;
1139 TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | channel);
1140
1141 for (i=0; i<5; i++) {
1142 TWRITE4(sc, AUTRI_ARAM_CR + i*sizeof(cr[0]), cr[i]);
1143 DPRINTFN(5,("cr[%d] : 0x%08X\n", i, cr[i]));
1144 }
1145
1146 /* Bank A only */
1147 if (channel < 0x20) {
1148 TWRITE4(sc, AUTRI_EBUF1, AUTRI_EMOD_STILL);
1149 TWRITE4(sc, AUTRI_EBUF2, AUTRI_EMOD_STILL);
1150 }
1151 }
1152
1153 }
1154
1155 int
autri_trigger_output(void * addr,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)1156 autri_trigger_output(void *addr, void *start, void *end, int blksize,
1157 void (*intr)(void *), void *arg, struct audio_params *param)
1158 {
1159 struct autri_softc *sc = addr;
1160 struct autri_dma *p;
1161
1162 DPRINTFN(5,("autri_trigger_output: sc=%p start=%p end=%p "
1163 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1164
1165 sc->sc_play.intr = intr;
1166 sc->sc_play.intr_arg = arg;
1167 sc->sc_play.offset = 0;
1168 sc->sc_play.blksize = blksize;
1169 sc->sc_play.length = (char *)end - (char *)start;
1170
1171 p = autri_find_dma(sc, start);
1172 if (!p) {
1173 printf("autri_trigger_output: bad addr %p\n", start);
1174 return (EINVAL);
1175 }
1176
1177 sc->sc_play.dma = p;
1178
1179 /* */
1180 mtx_enter(&audio_lock);
1181 autri_setup_channel(sc, AUMODE_PLAY, param);
1182
1183 /* volume set to no attenuation */
1184 TWRITE4(sc, AUTRI_MUSICVOL_WAVEVOL, 0);
1185
1186 /* enable interrupt */
1187 autri_enable_interrupt(sc, sc->sc_play.ch_intr);
1188
1189 /* start channel */
1190 autri_startch(sc, sc->sc_play.ch, sc->sc_play.ch_intr);
1191 mtx_leave(&audio_lock);
1192 return 0;
1193 }
1194
1195 int
autri_trigger_input(void * addr,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)1196 autri_trigger_input(void *addr, void *start, void *end, int blksize, void (*intr)(void *), void *arg, struct audio_params *param)
1197 {
1198 struct autri_softc *sc = addr;
1199 struct autri_dma *p;
1200
1201 DPRINTFN(5,("autri_trigger_input: sc=%p start=%p end=%p "
1202 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1203
1204 sc->sc_rec.intr = intr;
1205 sc->sc_rec.intr_arg = arg;
1206 sc->sc_rec.offset = 0;
1207 sc->sc_rec.blksize = blksize;
1208 sc->sc_rec.length = (char *)end - (char *)start;
1209
1210 /* */
1211 p = autri_find_dma(sc, start);
1212 if (!p) {
1213 printf("autri_trigger_input: bad addr %p\n", start);
1214 return (EINVAL);
1215 }
1216
1217 sc->sc_rec.dma = p;
1218 mtx_enter(&audio_lock);
1219
1220 /* */
1221 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
1222 autri_reg_set_4(sc, AUTRI_NX_ACR0, AUTRI_NX_ACR0_PSB_CAPTURE);
1223 TWRITE1(sc, AUTRI_NX_RCI3, AUTRI_NX_RCI3_ENABLE | sc->sc_rec.ch);
1224 }
1225
1226 #if 0
1227 /* 4DWAVE only allows capturing at a 48KHz rate */
1228 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_DX ||
1229 sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX)
1230 param->sample_rate = 48000;
1231 #endif
1232
1233 autri_setup_channel(sc, AUMODE_RECORD, param);
1234
1235 /* enable interrupt */
1236 autri_enable_interrupt(sc, sc->sc_rec.ch_intr);
1237
1238 /* start channel */
1239 autri_startch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr);
1240 mtx_leave(&audio_lock);
1241 return 0;
1242 }
1243
1244 #if 0
1245 int
1246 autri_halt(struct autri_softc *sc)
1247 {
1248 DPRINTF(("autri_halt().\n"));
1249 /*autri_stopch(sc);*/
1250 autri_disable_interrupt(sc, sc->sc_play.channel);
1251 autri_disable_interrupt(sc, sc->sc_rec.channel);
1252 return 0;
1253 }
1254 #endif
1255
1256 void
autri_enable_interrupt(struct autri_softc * sc,int ch)1257 autri_enable_interrupt(struct autri_softc *sc, int ch)
1258 {
1259 int reg;
1260
1261 reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A;
1262 ch &= 0x1f;
1263
1264 autri_reg_set_4(sc, reg, 1 << ch);
1265 }
1266
1267 void
autri_disable_interrupt(struct autri_softc * sc,int ch)1268 autri_disable_interrupt(struct autri_softc *sc, int ch)
1269 {
1270 int reg;
1271
1272 reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A;
1273 ch &= 0x1f;
1274
1275 autri_reg_clear_4(sc, reg, 1 << ch);
1276 }
1277
1278 void
autri_startch(struct autri_softc * sc,int ch,int ch_intr)1279 autri_startch(struct autri_softc *sc, int ch, int ch_intr)
1280 {
1281 int reg;
1282 u_int32_t chmask;
1283
1284 reg = (ch & 0x20) ? AUTRI_START_B : AUTRI_START_A;
1285 ch &= 0x1f;
1286 chmask = (1 << ch) | (1 << ch_intr);
1287
1288 autri_reg_set_4(sc, reg, chmask);
1289 }
1290
1291 void
autri_stopch(struct autri_softc * sc,int ch,int ch_intr)1292 autri_stopch(struct autri_softc *sc, int ch, int ch_intr)
1293 {
1294 int reg;
1295 u_int32_t chmask;
1296
1297 reg = (ch & 0x20) ? AUTRI_STOP_B : AUTRI_STOP_A;
1298 ch &= 0x1f;
1299 chmask = (1 << ch) | (1 << ch_intr);
1300
1301 autri_reg_set_4(sc, reg, chmask);
1302 }
1303
1304 #if NMIDI > 0
1305 int
autri_midi_open(void * addr,int flags,void (* iintr)(void *,int),void (* ointr)(void *),void * arg)1306 autri_midi_open(void *addr, int flags, void (*iintr)(void *, int),
1307 void (*ointr)(void *), void *arg)
1308 {
1309 struct autri_softc *sc = addr;
1310
1311 DPRINTF(("autri_midi_open()\n"));
1312
1313 DPRINTFN(5,("MPUR1 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR1)));
1314 DPRINTFN(5,("MPUR2 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR2)));
1315
1316 sc->sc_iintr = iintr;
1317 sc->sc_ointr = ointr;
1318 sc->sc_arg = arg;
1319
1320 if (flags & FREAD)
1321 autri_reg_clear_1(sc, AUTRI_MPUR2, AUTRI_MIDIIN_ENABLE_INTR);
1322
1323 if (flags & FWRITE)
1324 autri_reg_set_1(sc, AUTRI_MPUR2, AUTRI_MIDIOUT_CONNECT);
1325
1326 return (0);
1327 }
1328
1329 void
autri_midi_close(void * addr)1330 autri_midi_close(void *addr)
1331 {
1332 struct autri_softc *sc = addr;
1333
1334 DPRINTF(("autri_midi_close()\n"));
1335
1336 /* give uart a chance to drain */
1337 tsleep_nsec(sc, PWAIT, "autri", MSEC_TO_NSEC(100));
1338
1339 sc->sc_iintr = NULL;
1340 sc->sc_ointr = NULL;
1341 }
1342
1343 int
autri_midi_output(void * addr,int d)1344 autri_midi_output(void *addr, int d)
1345 {
1346 struct autri_softc *sc = addr;
1347
1348 if ((TREAD1(sc, AUTRI_MPUR1) & AUTRI_MIDIOUT_READY) != 0) {
1349 TWRITE1(sc, AUTRI_MPUR0, d);
1350 return 0;
1351 }
1352 return 1;
1353 }
1354
1355 void
autri_midi_getinfo(void * addr,struct midi_info * mi)1356 autri_midi_getinfo(void *addr, struct midi_info *mi)
1357 {
1358 mi->name = "4DWAVE MIDI UART";
1359 mi->props = MIDI_PROP_CAN_INPUT;
1360 }
1361
1362 #endif
1363