autri.c revision 1.22.2.1 1 /* $NetBSD: autri.c,v 1.22.2.1 2005/01/02 20:03:11 kent 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 <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: autri.c,v 1.22.2.1 2005/01/02 20:03:11 kent Exp $");
39
40 #include "midi.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/fcntl.h>
46 #include <sys/malloc.h>
47 #include <sys/device.h>
48 #include <sys/proc.h>
49
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/mulaw.h>
58 #include <dev/auconv.h>
59 #include <dev/ic/ac97reg.h>
60 #include <dev/ic/ac97var.h>
61 #include <dev/ic/mpuvar.h>
62
63 #include <machine/bus.h>
64 #include <machine/intr.h>
65
66 #include <dev/pci/autrireg.h>
67 #include <dev/pci/autrivar.h>
68
69 #ifdef AUDIO_DEBUG
70 # define DPRINTF(x) if (autridebug) printf x
71 # define DPRINTFN(n,x) if (autridebug > (n)) printf x
72 int autridebug = 0;
73 #else
74 # define DPRINTF(x)
75 # define DPRINTFN(n,x)
76 #endif
77
78 int autri_match(struct device *, struct cfdata *, void *);
79 void autri_attach(struct device *, struct device *, void *);
80 int autri_intr(void *);
81
82 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
83 #define KERNADDR(p) ((void *)((p)->addr))
84
85 int autri_allocmem(struct autri_softc *, size_t,
86 size_t, struct autri_dma *);
87 int autri_freemem(struct autri_softc *, struct autri_dma *);
88
89 #define TWRITE1(sc, r, x) bus_space_write_1((sc)->memt, (sc)->memh, (r), (x))
90 #define TWRITE2(sc, r, x) bus_space_write_2((sc)->memt, (sc)->memh, (r), (x))
91 #define TWRITE4(sc, r, x) bus_space_write_4((sc)->memt, (sc)->memh, (r), (x))
92 #define TREAD1(sc, r) bus_space_read_1((sc)->memt, (sc)->memh, (r))
93 #define TREAD2(sc, r) bus_space_read_2((sc)->memt, (sc)->memh, (r))
94 #define TREAD4(sc, r) bus_space_read_4((sc)->memt, (sc)->memh, (r))
95
96 static __inline void autri_reg_set_1(struct autri_softc *, int, uint8_t);
97 static __inline void autri_reg_clear_1(struct autri_softc *, int, uint8_t);
98 static __inline void autri_reg_set_4(struct autri_softc *, int, uint32_t);
99 static __inline void autri_reg_clear_4(struct autri_softc *, int, uint32_t);
100
101 int autri_attach_codec(void *sc, struct ac97_codec_if *);
102 int autri_read_codec(void *sc, u_int8_t a, u_int16_t *d);
103 int autri_write_codec(void *sc, u_int8_t a, u_int16_t d);
104 int autri_reset_codec(void *sc);
105 enum ac97_host_flags autri_flags_codec(void *sc);
106
107 static void autri_powerhook(int why,void *addr);
108 static int autri_init(void *sc);
109 static struct autri_dma *autri_find_dma(struct autri_softc *, void *);
110 static void autri_setup_channel(struct autri_softc *sc,int mode,
111 const audio_params_t *param);
112 static void autri_enable_interrupt(struct autri_softc *sc, int ch);
113 static void autri_disable_interrupt(struct autri_softc *sc, int ch);
114 static void autri_startch(struct autri_softc *sc, int ch, int ch_intr);
115 static void autri_stopch(struct autri_softc *sc, int ch, int ch_intr);
116 static void autri_enable_loop_interrupt(void *sc);
117 #if 0
118 static void autri_disable_loop_interrupt(void *sc);
119 #endif
120
121 CFATTACH_DECL(autri, sizeof(struct autri_softc),
122 autri_match, autri_attach, NULL, NULL);
123
124 int autri_open(void *, int);
125 void autri_close(void *);
126 int autri_query_encoding(void *, struct audio_encoding *);
127 int autri_set_params(void *, int, int, audio_params_t *, audio_params_t *,
128 stream_filter_list_t *, stream_filter_list_t *);
129 int autri_round_blocksize(void *, int);
130 int autri_trigger_output(void *, void *, void *, int, void (*)(void *),
131 void *, const audio_params_t *);
132 int autri_trigger_input(void *, void *, void *, int, void (*)(void *),
133 void *, const audio_params_t *);
134 int autri_halt_output(void *);
135 int autri_halt_input(void *);
136 int autri_getdev(void *, struct audio_device *);
137 int autri_mixer_set_port(void *, mixer_ctrl_t *);
138 int autri_mixer_get_port(void *, mixer_ctrl_t *);
139 void* autri_malloc(void *, int, size_t, struct malloc_type *, int);
140 void autri_free(void *, void *, struct malloc_type *);
141 size_t autri_round_buffersize(void *, int, size_t);
142 paddr_t autri_mappage(void *, void *, off_t, int);
143 int autri_get_props(void *);
144 int autri_query_devinfo(void *addr, mixer_devinfo_t *dip);
145
146 int autri_get_portnum_by_name(struct autri_softc *, char *, char *, char *);
147
148 static const struct audio_hw_if autri_hw_if = {
149 autri_open,
150 autri_close,
151 NULL, /* drain */
152 autri_query_encoding,
153 autri_set_params,
154 autri_round_blocksize,
155 NULL, /* commit_settings */
156 NULL, /* init_output */
157 NULL, /* init_input */
158 NULL, /* start_output */
159 NULL, /* start_input */
160 autri_halt_output,
161 autri_halt_input,
162 NULL, /* speaker_ctl */
163 autri_getdev,
164 NULL, /* setfd */
165 autri_mixer_set_port,
166 autri_mixer_get_port,
167 autri_query_devinfo,
168 autri_malloc,
169 autri_free,
170 autri_round_buffersize,
171 autri_mappage,
172 autri_get_props,
173 autri_trigger_output,
174 autri_trigger_input,
175 NULL, /* dev_ioctl */
176 };
177
178 #if NMIDI > 0
179 void autri_midi_close(void *);
180 void autri_midi_getinfo(void *, struct midi_info *);
181 int autri_midi_open(void *, int, void (*)(void *, int),
182 void (*)(void *), void *);
183 int autri_midi_output(void *, int);
184
185 const struct midi_hw_if autri_midi_hw_if = {
186 autri_midi_open,
187 autri_midi_close,
188 autri_midi_output,
189 autri_midi_getinfo,
190 NULL, /* ioctl */
191 };
192 #endif
193
194 #define AUTRI_NFORMATS 8
195 static const struct audio_format autri_formats[AUTRI_NFORMATS] = {
196 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
197 2, AUFMT_STEREO, 0, {4000, 48000}},
198 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
199 1, AUFMT_MONAURAL, 0, {4000, 48000}},
200 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 16, 16,
201 2, AUFMT_STEREO, 0, {4000, 48000}},
202 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 16, 16,
203 1, AUFMT_MONAURAL, 0, {4000, 48000}},
204 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8,
205 2, AUFMT_STEREO, 0, {4000, 48000}},
206 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8,
207 1, AUFMT_MONAURAL, 0, {4000, 48000}},
208 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 8, 8,
209 2, AUFMT_STEREO, 0, {4000, 48000}},
210 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 8, 8,
211 1, AUFMT_MONAURAL, 0, {4000, 48000}},
212 };
213
214 /*
215 * register set/clear bit
216 */
217 static __inline void
218 autri_reg_set_1(struct autri_softc *sc, int no, uint8_t mask)
219 {
220 bus_space_write_1(sc->memt, sc->memh, no,
221 (bus_space_read_1(sc->memt, sc->memh, no) | mask));
222 }
223
224 static __inline void
225 autri_reg_clear_1(struct autri_softc *sc, int no, uint8_t mask)
226 {
227 bus_space_write_1(sc->memt, sc->memh, no,
228 (bus_space_read_1(sc->memt, sc->memh, no) & ~mask));
229 }
230
231 static __inline void
232 autri_reg_set_4(struct autri_softc *sc, int no, uint32_t mask)
233 {
234 bus_space_write_4(sc->memt, sc->memh, no,
235 (bus_space_read_4(sc->memt, sc->memh, no) | mask));
236 }
237
238 static __inline void
239 autri_reg_clear_4(struct autri_softc *sc, int no, uint32_t mask)
240 {
241 bus_space_write_4(sc->memt, sc->memh, no,
242 (bus_space_read_4(sc->memt, sc->memh, no) & ~mask));
243 }
244
245 /*
246 * AC'97 codec
247 */
248 int
249 autri_attach_codec(void *sc_, struct ac97_codec_if *codec_if)
250 {
251 struct autri_codec_softc *sc = sc_;
252
253 DPRINTF(("autri_attach_codec()\n"));
254
255 sc->codec_if = codec_if;
256 return 0;
257 }
258
259 int
260 autri_read_codec(void *sc_, u_int8_t index, u_int16_t *data)
261 {
262 struct autri_codec_softc *codec = sc_;
263 struct autri_softc *sc = codec->sc;
264 u_int32_t status, addr, cmd, busy;
265 u_int16_t count;
266
267 /*DPRINTF(("sc->sc->type : 0x%X",sc->sc->type));*/
268
269 switch (sc->sc_devid) {
270 case AUTRI_DEVICE_ID_4DWAVE_DX:
271 addr = AUTRI_DX_ACR1;
272 cmd = AUTRI_DX_ACR1_CMD_READ;
273 busy = AUTRI_DX_ACR1_BUSY_READ;
274 break;
275 case AUTRI_DEVICE_ID_4DWAVE_NX:
276 addr = AUTRI_NX_ACR2;
277 cmd = AUTRI_NX_ACR2_CMD_READ;
278 busy = AUTRI_NX_ACR2_BUSY_READ | AUTRI_NX_ACR2_RECV_WAIT;
279 break;
280 case AUTRI_DEVICE_ID_SIS_7018:
281 addr = AUTRI_SIS_ACRD;
282 cmd = AUTRI_SIS_ACRD_CMD_READ;
283 busy = AUTRI_SIS_ACRD_BUSY_READ | AUTRI_SIS_ACRD_AUDIO_BUSY;
284 break;
285 case AUTRI_DEVICE_ID_ALI_M5451:
286 if (sc->sc_revision > 0x01)
287 addr = AUTRI_ALI_ACWR;
288 else
289 addr = AUTRI_ALI_ACRD;
290 cmd = AUTRI_ALI_ACRD_CMD_READ;
291 busy = AUTRI_ALI_ACRD_BUSY_READ;
292 break;
293 default:
294 printf("%s: autri_read_codec : unknown device\n",
295 sc->sc_dev.dv_xname);
296 return -1;
297 }
298
299 /* wait for 'Ready to Read' */
300 for (count=0; count<0xffff; count++) {
301 if ((TREAD4(sc, addr) & busy) == 0)
302 break;
303 }
304
305 if (count == 0xffff) {
306 printf("%s: Codec timeout. Busy reading AC'97 codec.\n",
307 sc->sc_dev.dv_xname);
308 return -1;
309 }
310
311 /* send Read Command to AC'97 */
312 TWRITE4(sc, addr, (index & 0x7f) | cmd);
313
314 /* wait for 'Returned data is avalable' */
315 for (count=0; count<0xffff; count++) {
316 status = TREAD4(sc, addr);
317 if ((status & busy) == 0)
318 break;
319 }
320
321 if (count == 0xffff) {
322 printf("%s: Codec timeout. Busy reading AC'97 codec.\n",
323 sc->sc_dev.dv_xname);
324 return -1;
325 }
326
327 *data = (status >> 16) & 0x0000ffff;
328 /*DPRINTF(("autri_read_codec(0x%X) return 0x%X\n",reg,*data));*/
329 return 0;
330 }
331
332 int
333 autri_write_codec(void *sc_, u_int8_t index, u_int16_t data)
334 {
335 struct autri_codec_softc *codec = sc_;
336 struct autri_softc *sc = codec->sc;
337 u_int32_t addr, cmd, busy;
338 u_int16_t count;
339
340 /*DPRINTF(("autri_write_codec(0x%X,0x%X)\n",index,data));*/
341
342 switch (sc->sc_devid) {
343 case AUTRI_DEVICE_ID_4DWAVE_DX:
344 addr = AUTRI_DX_ACR0;
345 cmd = AUTRI_DX_ACR0_CMD_WRITE;
346 busy = AUTRI_DX_ACR0_BUSY_WRITE;
347 break;
348 case AUTRI_DEVICE_ID_4DWAVE_NX:
349 addr = AUTRI_NX_ACR1;
350 cmd = AUTRI_NX_ACR1_CMD_WRITE;
351 busy = AUTRI_NX_ACR1_BUSY_WRITE;
352 break;
353 case AUTRI_DEVICE_ID_SIS_7018:
354 addr = AUTRI_SIS_ACWR;
355 cmd = AUTRI_SIS_ACWR_CMD_WRITE;
356 busy = AUTRI_SIS_ACWR_BUSY_WRITE | AUTRI_SIS_ACWR_AUDIO_BUSY;
357 break;
358 case AUTRI_DEVICE_ID_ALI_M5451:
359 addr = AUTRI_ALI_ACWR;
360 cmd = AUTRI_ALI_ACWR_CMD_WRITE;
361 if (sc->sc_revision > 0x01)
362 cmd |= 0x0100;
363 busy = AUTRI_ALI_ACWR_BUSY_WRITE;
364 break;
365 default:
366 printf("%s: autri_write_codec : unknown device.\n",
367 sc->sc_dev.dv_xname);
368 return -1;
369 }
370
371 /* wait for 'Ready to Write' */
372 for (count=0; count<0xffff; count++) {
373 if ((TREAD4(sc, addr) & busy) == 0)
374 break;
375 }
376
377 if (count == 0xffff) {
378 printf("%s: Codec timeout. Busy writing AC'97 codec\n",
379 sc->sc_dev.dv_xname);
380 return -1;
381 }
382
383 /* send Write Command to AC'97 */
384 TWRITE4(sc, addr, (data << 16) | (index & 0x7f) | cmd);
385
386 return 0;
387 }
388
389 int
390 autri_reset_codec(void *sc_)
391 {
392 struct autri_codec_softc *codec = sc_;
393 struct autri_softc *sc = codec->sc;
394 u_int32_t reg, ready;
395 int addr, count = 200;
396
397 DPRINTF(("autri_reset_codec(codec=%p,sc=%p)\n",codec,sc));
398 DPRINTF(("sc->sc_devid=%X\n",sc->sc_devid));
399
400 switch (sc->sc_devid) {
401 case AUTRI_DEVICE_ID_4DWAVE_DX:
402 /* warm reset AC'97 codec */
403 autri_reg_set_4(sc, AUTRI_DX_ACR2, 1);
404 delay(100);
405 /* release reset */
406 autri_reg_clear_4(sc, AUTRI_DX_ACR2, 1);
407 delay(100);
408
409 addr = AUTRI_DX_ACR2;
410 ready = AUTRI_DX_ACR2_CODEC_READY;
411 break;
412 case AUTRI_DEVICE_ID_4DWAVE_NX:
413 /* warm reset AC'97 codec */
414 autri_reg_set_4(sc, AUTRI_NX_ACR0, 1);
415 delay(100);
416 /* release reset */
417 autri_reg_clear_4(sc, AUTRI_NX_ACR0, 1);
418 delay(100);
419
420 addr = AUTRI_NX_ACR0;
421 ready = AUTRI_NX_ACR0_CODEC_READY;
422 break;
423 case AUTRI_DEVICE_ID_SIS_7018:
424 /* cold reset AC'97 codec */
425 autri_reg_set_4(sc, AUTRI_SIS_SCTRL, 2);
426 delay(1000);
427 /* release reset (warm & cold) */
428 autri_reg_clear_4(sc, AUTRI_SIS_SCTRL, 3);
429 delay(2000);
430
431 addr = AUTRI_SIS_SCTRL;
432 ready = AUTRI_SIS_SCTRL_CODEC_READY;
433 break;
434 case AUTRI_DEVICE_ID_ALI_M5451:
435 /* warm reset AC'97 codec */
436 autri_reg_set_4(sc, AUTRI_ALI_SCTRL, 1);
437 delay(100);
438 /* release reset (warm & cold) */
439 autri_reg_clear_4(sc, AUTRI_ALI_SCTRL, 3);
440 delay(100);
441
442 addr = AUTRI_ALI_SCTRL;
443 ready = AUTRI_ALI_SCTRL_CODEC_READY;
444 break;
445 default:
446 printf("%s: autri_reset_codec : unknown device\n",
447 sc->sc_dev.dv_xname);
448 return EOPNOTSUPP;
449 }
450
451 /* wait for 'Codec Ready' */
452 while (count--) {
453 reg = TREAD4(sc, addr);
454 if (reg & ready)
455 break;
456 delay(1000);
457 }
458
459 if (count == 0) {
460 printf("%s: Codec timeout. AC'97 is not ready for operation.\n",
461 sc->sc_dev.dv_xname);
462 return ETIMEDOUT;
463 }
464 return 0;
465 }
466
467 enum ac97_host_flags
468 autri_flags_codec(void *sc_)
469 {
470 return AC97_HOST_DONT_READ;
471 }
472
473 /*
474 *
475 */
476
477 int
478 autri_match(struct device *parent, struct cfdata *match, void *aux)
479 {
480 struct pci_attach_args *pa = (struct pci_attach_args *) aux;
481
482 switch (PCI_VENDOR(pa->pa_id)) {
483 case PCI_VENDOR_TRIDENT:
484 switch (PCI_PRODUCT(pa->pa_id)) {
485 case PCI_PRODUCT_TRIDENT_4DWAVE_DX:
486 case PCI_PRODUCT_TRIDENT_4DWAVE_NX:
487 return 1;
488 }
489 break;
490 case PCI_VENDOR_SIS:
491 switch (PCI_PRODUCT(pa->pa_id)) {
492 case PCI_PRODUCT_SIS_7018:
493 return 1;
494 }
495 break;
496 case PCI_VENDOR_ALI:
497 switch (PCI_PRODUCT(pa->pa_id)) {
498 case PCI_PRODUCT_ALI_M5451:
499 return 1;
500 }
501 break;
502 }
503
504 return 0;
505 }
506
507 void
508 autri_attach(struct device *parent, struct device *self, void *aux)
509 {
510 struct autri_softc *sc = (struct autri_softc *)self;
511 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
512 pci_chipset_tag_t pc = pa->pa_pc;
513 struct autri_codec_softc *codec;
514 pci_intr_handle_t ih;
515 char const *intrstr;
516 char devinfo[256];
517 int r;
518 u_int32_t reg;
519
520 aprint_naive(": Audio controller\n");
521
522 sc->sc_devid = pa->pa_id;
523 sc->sc_class = pa->pa_class;
524
525 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
526 sc->sc_revision = PCI_REVISION(pa->pa_class);
527 aprint_normal(": %s (rev. 0x%02x)\n", devinfo, sc->sc_revision);
528
529 /* map register to memory */
530 if (pci_mapreg_map(pa, AUTRI_PCI_MEMORY_BASE,
531 PCI_MAPREG_TYPE_MEM, 0, &sc->memt, &sc->memh, NULL, NULL)) {
532 aprint_error("%s: can't map memory space\n",
533 sc->sc_dev.dv_xname);
534 return;
535 }
536
537 /* map and establish the interrupt */
538 if (pci_intr_map(pa, &ih)) {
539 aprint_error("%s: couldn't map interrupt\n",
540 sc->sc_dev.dv_xname);
541 return;
542 }
543 intrstr = pci_intr_string(pc, ih);
544 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, autri_intr, sc);
545 if (sc->sc_ih == NULL) {
546 aprint_error("%s: couldn't establish interrupt",
547 sc->sc_dev.dv_xname);
548 if (intrstr != NULL)
549 aprint_normal(" at %s", intrstr);
550 aprint_normal("\n");
551 return;
552 }
553 aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
554
555 sc->sc_dmatag = pa->pa_dmat;
556 sc->sc_pc = pc;
557 sc->sc_pt = pa->pa_tag;
558
559 /* enable the device */
560 reg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
561 reg |= (PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE);
562 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg);
563
564 /* initialize the device */
565 autri_init(sc);
566
567 /* attach AC'97 codec */
568 codec = &sc->sc_codec;
569 memcpy(&codec->sc_dev, &sc->sc_dev, sizeof(codec->sc_dev));
570 codec->sc = sc;
571
572 codec->host_if.arg = codec;
573 codec->host_if.attach = autri_attach_codec;
574 codec->host_if.reset = autri_reset_codec;
575 codec->host_if.read = autri_read_codec;
576 codec->host_if.write = autri_write_codec;
577 codec->host_if.flags = autri_flags_codec;
578
579 if ((r = ac97_attach(&codec->host_if, self)) != 0) {
580 aprint_error("%s: can't attach codec (error 0x%X)\n",
581 sc->sc_dev.dv_xname, r);
582 return;
583 }
584
585 audio_attach_mi(&autri_hw_if, sc, &sc->sc_dev);
586
587 #if NMIDI > 0
588 midi_attach_mi(&autri_midi_hw_if, sc, &sc->sc_dev);
589 #endif
590
591 sc->sc_old_power = PWR_RESUME;
592 powerhook_establish(autri_powerhook, sc);
593 }
594
595 static void
596 autri_powerhook(int why, void *addr)
597 {
598 struct autri_softc *sc = addr;
599
600 if (why == PWR_RESUME && sc->sc_old_power == PWR_SUSPEND) {
601 DPRINTF(("PWR_RESUME\n"));
602 autri_init(sc);
603 /*autri_reset_codec(&sc->sc_codec);*/
604 (sc->sc_codec.codec_if->vtbl->restore_ports)(sc->sc_codec.codec_if);
605 }
606 sc->sc_old_power = why;
607 }
608
609 int
610 autri_init(void *sc_)
611 {
612 struct autri_softc *sc = sc_;
613 u_int32_t reg;
614
615 pci_chipset_tag_t pc = sc->sc_pc;
616 pcitag_t pt = sc->sc_pt;
617
618 DPRINTF(("in autri_init()\n"));
619 DPRINTFN(5,("pci_conf_read(0x40) : 0x%X\n",pci_conf_read(pc,pt,0x40)));
620 DPRINTFN(5,("pci_conf_read(0x44) : 0x%X\n",pci_conf_read(pc,pt,0x44)));
621
622 switch (sc->sc_devid) {
623 case AUTRI_DEVICE_ID_4DWAVE_DX:
624 /* disable Legacy Control */
625 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
626 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
627 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
628 delay(100);
629 /* audio engine reset */
630 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
631 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00040000);
632 delay(100);
633 /* release reset */
634 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
635 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
636 delay(100);
637 /* DAC on */
638 autri_reg_set_4(sc,AUTRI_DX_ACR2,0x02);
639 break;
640 case AUTRI_DEVICE_ID_4DWAVE_NX:
641 /* disable Legacy Control */
642 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
643 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
644 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
645 delay(100);
646 /* audio engine reset */
647 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
648 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00010000);
649 delay(100);
650 /* release reset */
651 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
652 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00010000);
653 delay(100);
654 /* DAC on */
655 autri_reg_set_4(sc,AUTRI_NX_ACR0,0x02);
656 break;
657 case AUTRI_DEVICE_ID_SIS_7018:
658 /* disable Legacy Control */
659 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
660 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
661 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
662 delay(100);
663 /* reset Digital Controller */
664 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
665 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000);
666 delay(100);
667 /* release reset */
668 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
669 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
670 delay(100);
671 /* disable AC97 GPIO interrupt */
672 TWRITE1(sc, AUTRI_SIS_ACGPIO, 0);
673 /* enable 64 channel mode */
674 autri_reg_set_4(sc, AUTRI_LFO_GC_CIR, BANK_B_EN);
675 break;
676 case AUTRI_DEVICE_ID_ALI_M5451:
677 /* disable Legacy Control */
678 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
679 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
680 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
681 delay(100);
682 /* reset Digital Controller */
683 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
684 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000);
685 delay(100);
686 /* release reset */
687 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
688 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
689 delay(100);
690 /* enable PCM input */
691 autri_reg_set_4(sc, AUTRI_ALI_GCONTROL, AUTRI_ALI_GCONTROL_PCM_IN);
692 break;
693 }
694
695 if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) {
696 sc->sc_play.ch = 0;
697 sc->sc_play.ch_intr = 1;
698 sc->sc_rec.ch = 31;
699 sc->sc_rec.ch_intr = 2;
700 } else {
701 sc->sc_play.ch = 0x20;
702 sc->sc_play.ch_intr = 0x21;
703 sc->sc_rec.ch = 0x22;
704 sc->sc_rec.ch_intr = 0x23;
705 }
706
707 /* clear channel status */
708 TWRITE4(sc, AUTRI_STOP_A, 0xffffffff);
709 TWRITE4(sc, AUTRI_STOP_B, 0xffffffff);
710
711 /* disable channel interrupt */
712 TWRITE4(sc, AUTRI_AINTEN_A, 0);
713 TWRITE4(sc, AUTRI_AINTEN_B, 0);
714
715 #if 0
716 /* TLB */
717 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
718 TWRITE4(sc,AUTRI_NX_TLBC,0);
719 }
720 #endif
721
722 autri_enable_loop_interrupt(sc);
723
724 DPRINTF(("out autri_init()\n"));
725 return 0;
726 }
727
728 static void
729 autri_enable_loop_interrupt(void *sc_)
730 {
731 struct autri_softc *sc = sc_;
732 u_int32_t reg;
733
734 /*reg = (ENDLP_IE | MIDLP_IE);*/
735 reg = ENDLP_IE;
736
737 if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018)
738 reg |= BANK_B_EN;
739
740 autri_reg_set_4(sc,AUTRI_LFO_GC_CIR,reg);
741 }
742
743 #if 0
744 static void
745 autri_disable_loop_interrupt(void *sc_)
746 {
747 struct autri_softc *sc = sc_;
748 u_int32_t reg;
749
750 reg = (ENDLP_IE | MIDLP_IE);
751 autri_reg_clear_4(sc,AUTRI_LFO_GC_CIR,reg);
752 }
753 #endif
754
755 int
756 autri_intr(void *p)
757 {
758 struct autri_softc *sc = p;
759 u_int32_t intsrc;
760 u_int32_t mask, active[2];
761 int ch, endch;
762 /*
763 u_int32_t reg;
764 u_int32_t cso,eso;
765 */
766
767 intsrc = TREAD4(sc,AUTRI_MISCINT);
768 if ((intsrc & (ADDRESS_IRQ|MPU401_IRQ)) == 0)
769 return 0;
770
771 if (intsrc & ADDRESS_IRQ) {
772
773 active[0] = TREAD4(sc,AUTRI_AIN_A);
774 active[1] = TREAD4(sc,AUTRI_AIN_B);
775
776 if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) {
777 endch = 32;
778 } else {
779 endch = 64;
780 }
781
782 for (ch=0; ch<endch; ch++) {
783 mask = 1 << (ch & 0x1f);
784 if (active[(ch & 0x20) ? 1 : 0] & mask) {
785
786 /* clear interrupt */
787 TWRITE4(sc, (ch & 0x20) ? AUTRI_AIN_B : AUTRI_AIN_A, mask);
788 /* disable interrupt */
789 autri_reg_clear_4(sc,(ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask);
790 #if 0
791 reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f;
792 TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | ch);
793
794 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
795 cso = TREAD4(sc, 0xe0) & 0x00ffffff;
796 eso = TREAD4(sc, 0xe8) & 0x00ffffff;
797 } else {
798 cso = (TREAD4(sc, 0xe0) >> 16) & 0x0000ffff;
799 eso = (TREAD4(sc, 0xe8) >> 16) & 0x0000ffff;
800 }
801 /*printf("cso=%d, eso=%d\n",cso,eso);*/
802 #endif
803 if (ch == sc->sc_play.ch_intr) {
804 if (sc->sc_play.intr)
805 sc->sc_play.intr(sc->sc_play.intr_arg);
806 }
807
808 if (ch == sc->sc_rec.ch_intr) {
809 if (sc->sc_rec.intr)
810 sc->sc_rec.intr(sc->sc_rec.intr_arg);
811 }
812
813 /* enable interrupt */
814 autri_reg_set_4(sc, (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask);
815 }
816 }
817 }
818
819 if (intsrc & MPU401_IRQ) {
820 /* XXX */
821 }
822
823 autri_reg_set_4(sc,AUTRI_MISCINT,
824 ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW);
825
826 return 1;
827 }
828
829 /*
830 *
831 */
832
833 int
834 autri_allocmem(struct autri_softc *sc, size_t size, size_t align,
835 struct autri_dma *p)
836 {
837 int error;
838
839 p->size = size;
840 error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
841 p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
842 &p->nsegs, BUS_DMA_NOWAIT);
843 if (error)
844 return (error);
845
846 error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
847 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
848 if (error)
849 goto free;
850
851 error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
852 0, BUS_DMA_NOWAIT, &p->map);
853 if (error)
854 goto unmap;
855
856 error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
857 BUS_DMA_NOWAIT);
858 if (error)
859 goto destroy;
860 return (0);
861
862 destroy:
863 bus_dmamap_destroy(sc->sc_dmatag, p->map);
864 unmap:
865 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
866 free:
867 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
868 return (error);
869 }
870
871 int
872 autri_freemem(struct autri_softc *sc, struct autri_dma *p)
873 {
874 bus_dmamap_unload(sc->sc_dmatag, p->map);
875 bus_dmamap_destroy(sc->sc_dmatag, p->map);
876 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
877 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
878 return 0;
879 }
880
881 int
882 autri_open(void *addr, int flags)
883 {
884 DPRINTF(("autri_open()\n"));
885 DPRINTFN(5,("MISCINT : 0x%08X\n",
886 TREAD4((struct autri_softc *)addr, AUTRI_MISCINT)));
887 DPRINTFN(5,("LFO_GC_CIR : 0x%08X\n",
888 TREAD4((struct autri_softc *)addr, AUTRI_LFO_GC_CIR)));
889 return 0;
890 }
891
892 void
893 autri_close(void *addr)
894 {
895 DPRINTF(("autri_close()\n"));
896 }
897
898 int
899 autri_query_encoding(void *addr, struct audio_encoding *fp)
900 {
901 switch (fp->index) {
902 case 0:
903 strcpy(fp->name, AudioEulinear);
904 fp->encoding = AUDIO_ENCODING_ULINEAR;
905 fp->precision = 8;
906 fp->flags = 0;
907 break;
908 case 1:
909 strcpy(fp->name, AudioEmulaw);
910 fp->encoding = AUDIO_ENCODING_ULAW;
911 fp->precision = 8;
912 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
913 break;
914 case 2:
915 strcpy(fp->name, AudioEalaw);
916 fp->encoding = AUDIO_ENCODING_ALAW;
917 fp->precision = 8;
918 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
919 break;
920 case 3:
921 strcpy(fp->name, AudioEslinear);
922 fp->encoding = AUDIO_ENCODING_SLINEAR;
923 fp->precision = 8;
924 fp->flags = 0;
925 break;
926 case 4:
927 strcpy(fp->name, AudioEslinear_le);
928 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
929 fp->precision = 16;
930 fp->flags = 0;
931 break;
932 case 5:
933 strcpy(fp->name, AudioEulinear_le);
934 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
935 fp->precision = 16;
936 fp->flags = 0;
937 break;
938 case 6:
939 strcpy(fp->name, AudioEslinear_be);
940 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
941 fp->precision = 16;
942 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
943 break;
944 case 7:
945 strcpy(fp->name, AudioEulinear_be);
946 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
947 fp->precision = 16;
948 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
949 break;
950 default:
951 return (EINVAL);
952 }
953
954 return 0;
955 }
956
957 int
958 autri_set_params(void *addr, int setmode, int usemode,
959 audio_params_t *play, audio_params_t *rec,
960 stream_filter_list_t *pfil, stream_filter_list_t *rfil)
961 {
962 if (setmode & AUMODE_RECORD) {
963 if (auconv_set_converter(autri_formats, AUTRI_NFORMATS,
964 AUMODE_RECORD, rec, FALSE, rfil) < 0)
965 return EINVAL;
966 }
967 if (setmode & AUMODE_PLAY) {
968 if (auconv_set_converter(autri_formats, AUTRI_NFORMATS,
969 AUMODE_PLAY, play, FALSE, pfil) < 0)
970 return EINVAL;
971 }
972 return 0;
973 }
974
975 int
976 autri_round_blocksize(void *addr, int block)
977 {
978 return (block & -4);
979 }
980
981 int
982 autri_halt_output(void *addr)
983 {
984 struct autri_softc *sc = addr;
985
986 DPRINTF(("autri_halt_output()\n"));
987
988 sc->sc_play.intr = NULL;
989 autri_stopch(sc, sc->sc_play.ch, sc->sc_play.ch_intr);
990 autri_disable_interrupt(sc, sc->sc_play.ch_intr);
991
992 return 0;
993 }
994
995 int
996 autri_halt_input(void *addr)
997 {
998 struct autri_softc *sc = addr;
999
1000 DPRINTF(("autri_halt_input()\n"));
1001
1002 sc->sc_rec.intr = NULL;
1003 autri_stopch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr);
1004 autri_disable_interrupt(sc, sc->sc_rec.ch_intr);
1005
1006 return 0;
1007 }
1008
1009 int
1010 autri_getdev(void *addr, struct audio_device *retp)
1011 {
1012 struct autri_softc *sc = addr;
1013
1014 DPRINTF(("autri_getdev().\n"));
1015
1016 strncpy(retp->name, "Trident 4DWAVE", sizeof(retp->name));
1017 snprintf(retp->version, sizeof(retp->version), "0x%02x",
1018 PCI_REVISION(sc->sc_class));
1019
1020 switch (sc->sc_devid) {
1021 case AUTRI_DEVICE_ID_4DWAVE_DX:
1022 strncpy(retp->config, "4DWAVE-DX", sizeof(retp->config));
1023 break;
1024 case AUTRI_DEVICE_ID_4DWAVE_NX:
1025 strncpy(retp->config, "4DWAVE-NX", sizeof(retp->config));
1026 break;
1027 case AUTRI_DEVICE_ID_SIS_7018:
1028 strncpy(retp->config, "SiS 7018", sizeof(retp->config));
1029 break;
1030 case AUTRI_DEVICE_ID_ALI_M5451:
1031 strncpy(retp->config, "ALi M5451", sizeof(retp->config));
1032 break;
1033 default:
1034 strncpy(retp->config, "unknown", sizeof(retp->config));
1035 }
1036
1037 return 0;
1038 }
1039
1040 int
1041 autri_mixer_set_port(void *addr, mixer_ctrl_t *cp)
1042 {
1043 struct autri_softc *sc = addr;
1044
1045 return (sc->sc_codec.codec_if->vtbl->mixer_set_port(
1046 sc->sc_codec.codec_if, cp));
1047 }
1048
1049 int
1050 autri_mixer_get_port(void *addr, mixer_ctrl_t *cp)
1051 {
1052 struct autri_softc *sc = addr;
1053
1054 return (sc->sc_codec.codec_if->vtbl->mixer_get_port(
1055 sc->sc_codec.codec_if, cp));
1056 }
1057
1058 int
1059 autri_query_devinfo(void *addr, mixer_devinfo_t *dip)
1060 {
1061 struct autri_softc *sc = addr;
1062
1063 return (sc->sc_codec.codec_if->vtbl->query_devinfo(
1064 sc->sc_codec.codec_if, dip));
1065 }
1066
1067 int
1068 autri_get_portnum_by_name(struct autri_softc *sc, char *class,
1069 char *device, char *qualifier)
1070 {
1071 return (sc->sc_codec.codec_if->vtbl->get_portnum_by_name(
1072 sc->sc_codec.codec_if, class, device, qualifier));
1073 }
1074
1075 void *
1076 autri_malloc(void *addr, int direction, size_t size,
1077 struct malloc_type *pool, int flags)
1078 {
1079 struct autri_softc *sc = addr;
1080 struct autri_dma *p;
1081 int error;
1082
1083 p = malloc(sizeof(*p), pool, flags);
1084 if (!p)
1085 return NULL;
1086
1087 #if 0
1088 error = autri_allocmem(sc, size, 16, p);
1089 #endif
1090 error = autri_allocmem(sc, size, 0x10000, p);
1091 if (error) {
1092 free(p, pool);
1093 return NULL;
1094 }
1095
1096 p->next = sc->sc_dmas;
1097 sc->sc_dmas = p;
1098 return KERNADDR(p);
1099 }
1100
1101 void
1102 autri_free(void *addr, void *ptr, struct malloc_type *pool)
1103 {
1104 struct autri_softc *sc = addr;
1105 struct autri_dma **pp, *p;
1106
1107 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
1108 if (KERNADDR(p) == ptr) {
1109 autri_freemem(sc, p);
1110 *pp = p->next;
1111 free(p, pool);
1112 return;
1113 }
1114 }
1115 }
1116
1117 static struct autri_dma *
1118 autri_find_dma(struct autri_softc *sc, void *addr)
1119 {
1120 struct autri_dma *p;
1121
1122 for (p = sc->sc_dmas; p && KERNADDR(p) != addr; p = p->next)
1123 ;
1124
1125 return p;
1126 }
1127
1128 size_t
1129 autri_round_buffersize(void *addr, int direction, size_t size)
1130 {
1131 return size;
1132 }
1133
1134 paddr_t
1135 autri_mappage(void *addr, void *mem, off_t off, int prot)
1136 {
1137 struct autri_softc *sc = addr;
1138 struct autri_dma *p;
1139
1140 if (off < 0)
1141 return (-1);
1142
1143 p = autri_find_dma(sc, mem);
1144 if (!p)
1145 return (-1);
1146
1147 return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs,
1148 off, prot, BUS_DMA_WAITOK));
1149 }
1150
1151 int
1152 autri_get_props(void *addr)
1153 {
1154 return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
1155 AUDIO_PROP_FULLDUPLEX);
1156 }
1157
1158 static void
1159 autri_setup_channel(struct autri_softc *sc, int mode,
1160 const audio_params_t *param)
1161 {
1162 int i, ch, channel;
1163 u_int32_t reg, cr[5];
1164 u_int32_t cso, eso;
1165 u_int32_t delta, dch[2], ctrl;
1166 u_int32_t alpha_fms, fm_vol, attribute;
1167
1168 u_int32_t dmaaddr, dmalen;
1169 int factor, rvol, cvol;
1170 struct autri_chstatus *chst;
1171
1172 ctrl = AUTRI_CTRL_LOOPMODE;
1173 switch (param->encoding) {
1174 case AUDIO_ENCODING_SLINEAR_BE:
1175 case AUDIO_ENCODING_SLINEAR_LE:
1176 ctrl |= AUTRI_CTRL_SIGNED;
1177 break;
1178 }
1179
1180 factor = 0;
1181 if (param->precision == 16) {
1182 ctrl |= AUTRI_CTRL_16BIT;
1183 factor++;
1184 }
1185
1186 if (param->channels == 2) {
1187 ctrl |= AUTRI_CTRL_STEREO;
1188 factor++;
1189 }
1190
1191 delta = param->sample_rate;
1192 if (delta < 4000)
1193 delta = 4000;
1194 if (delta > 48000)
1195 delta = 48000;
1196
1197 attribute = 0;
1198
1199 dch[1] = ((delta << 12) / 48000) & 0x0000ffff;
1200 if (mode == AUMODE_PLAY) {
1201 chst = &sc->sc_play;
1202 dch[0] = ((delta << 12) / 48000) & 0x0000ffff;
1203 ctrl |= AUTRI_CTRL_WAVEVOL;
1204 } else {
1205 chst = &sc->sc_rec;
1206 dch[0] = ((48000 << 12) / delta) & 0x0000ffff;
1207 if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) {
1208 ctrl |= AUTRI_CTRL_MUTEVOL_SIS;
1209 attribute = AUTRI_ATTR_PCMREC_SIS;
1210 if (delta != 48000)
1211 attribute |= AUTRI_ATTR_ENASRC_SIS;
1212 } else
1213 ctrl |= AUTRI_CTRL_MUTEVOL;
1214 }
1215
1216 dmaaddr = DMAADDR(chst->dma);
1217 cso = alpha_fms = 0;
1218 rvol = cvol = 0x7f;
1219 fm_vol = 0x0 | ((rvol & 0x7f) << 7) | (cvol & 0x7f);
1220
1221 for (ch=0; ch<2; ch++) {
1222
1223 if (ch == 0)
1224 dmalen = (chst->length >> factor);
1225 else {
1226 /* channel for interrupt */
1227 dmalen = (chst->blksize >> factor);
1228 if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018)
1229 ctrl |= AUTRI_CTRL_MUTEVOL_SIS;
1230 else
1231 ctrl |= AUTRI_CTRL_MUTEVOL;
1232 attribute = 0;
1233 }
1234
1235 eso = dmalen - 1;
1236
1237 switch (sc->sc_devid) {
1238 case AUTRI_DEVICE_ID_4DWAVE_DX:
1239 cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
1240 cr[1] = dmaaddr;
1241 cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
1242 cr[3] = fm_vol;
1243 cr[4] = ctrl;
1244 break;
1245 case AUTRI_DEVICE_ID_4DWAVE_NX:
1246 cr[0] = (dch[ch] << 24) | (cso & 0x00ffffff);
1247 cr[1] = dmaaddr;
1248 cr[2] = ((dch[ch] << 16) & 0xff000000) | (eso & 0x00ffffff);
1249 cr[3] = (alpha_fms << 16) | (fm_vol & 0x0000ffff);
1250 cr[4] = ctrl;
1251 break;
1252 case AUTRI_DEVICE_ID_SIS_7018:
1253 cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
1254 cr[1] = dmaaddr;
1255 cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
1256 cr[3] = attribute;
1257 cr[4] = ctrl;
1258 break;
1259 case AUTRI_DEVICE_ID_ALI_M5451:
1260 cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
1261 cr[1] = dmaaddr;
1262 cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
1263 cr[3] = 0;
1264 cr[4] = ctrl;
1265 break;
1266 }
1267
1268 /* write channel data */
1269 channel = (ch == 0) ? chst->ch : chst->ch_intr;
1270
1271 reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f;
1272 TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | channel);
1273
1274 for (i=0; i<5; i++) {
1275 TWRITE4(sc, AUTRI_ARAM_CR + i*sizeof(cr[0]), cr[i]);
1276 DPRINTFN(5,("cr[%d] : 0x%08X\n", i, cr[i]));
1277 }
1278
1279 /* Bank A only */
1280 if (channel < 0x20) {
1281 TWRITE4(sc, AUTRI_EBUF1, AUTRI_EMOD_STILL);
1282 TWRITE4(sc, AUTRI_EBUF2, AUTRI_EMOD_STILL);
1283 }
1284 }
1285
1286 }
1287
1288 int
1289 autri_trigger_output(void *addr, void *start, void *end, int blksize,
1290 void (*intr)(void *), void *arg,
1291 const audio_params_t *param)
1292 {
1293 struct autri_softc *sc = addr;
1294 struct autri_dma *p;
1295
1296 DPRINTFN(5,("autri_trigger_output: sc=%p start=%p end=%p "
1297 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1298
1299 sc->sc_play.intr = intr;
1300 sc->sc_play.intr_arg = arg;
1301 sc->sc_play.offset = 0;
1302 sc->sc_play.blksize = blksize;
1303 sc->sc_play.length = (char *)end - (char *)start;
1304
1305 p = autri_find_dma(sc, start);
1306 if (!p) {
1307 printf("autri_trigger_output: bad addr %p\n", start);
1308 return (EINVAL);
1309 }
1310
1311 sc->sc_play.dma = p;
1312
1313 /* */
1314 autri_setup_channel(sc, AUMODE_PLAY, param);
1315
1316 /* volume set to no attenuation */
1317 TWRITE4(sc, AUTRI_MUSICVOL_WAVEVOL, 0);
1318
1319 /* enable interrupt */
1320 autri_enable_interrupt(sc, sc->sc_play.ch_intr);
1321
1322 /* start channel */
1323 autri_startch(sc, sc->sc_play.ch, sc->sc_play.ch_intr);
1324
1325 return 0;
1326 }
1327
1328 int
1329 autri_trigger_input(void *addr, void *start, void *end, int blksize,
1330 void (*intr)(void *), void *arg,
1331 const audio_params_t *param)
1332 {
1333 struct autri_softc *sc = addr;
1334 struct autri_dma *p;
1335
1336 DPRINTFN(5,("autri_trigger_input: sc=%p start=%p end=%p "
1337 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1338
1339 sc->sc_rec.intr = intr;
1340 sc->sc_rec.intr_arg = arg;
1341 sc->sc_rec.offset = 0;
1342 sc->sc_rec.blksize = blksize;
1343 sc->sc_rec.length = (char *)end - (char *)start;
1344
1345 /* */
1346 p = autri_find_dma(sc, start);
1347 if (!p) {
1348 printf("autri_trigger_input: bad addr %p\n", start);
1349 return (EINVAL);
1350 }
1351
1352 sc->sc_rec.dma = p;
1353
1354 /* */
1355 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
1356 autri_reg_set_4(sc, AUTRI_NX_ACR0, AUTRI_NX_ACR0_PSB_CAPTURE);
1357 TWRITE1(sc, AUTRI_NX_RCI3, AUTRI_NX_RCI3_ENABLE | sc->sc_rec.ch);
1358 }
1359
1360 #if 0
1361 /* 4DWAVE only allows capturing at a 48KHz rate */
1362 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_DX ||
1363 sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX)
1364 param->sample_rate = 48000;
1365 #endif
1366
1367 autri_setup_channel(sc, AUMODE_RECORD, param);
1368
1369 /* enable interrupt */
1370 autri_enable_interrupt(sc, sc->sc_rec.ch_intr);
1371
1372 /* start channel */
1373 autri_startch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr);
1374
1375 return 0;
1376 }
1377
1378 #if 0
1379 static int
1380 autri_halt(struct autri_softc *sc)
1381 {
1382 DPRINTF(("autri_halt().\n"));
1383 /*autri_stopch(sc);*/
1384 autri_disable_interrupt(sc, sc->sc_play.channel);
1385 autri_disable_interrupt(sc, sc->sc_rec.channel);
1386 return 0;
1387 }
1388 #endif
1389
1390 static void
1391 autri_enable_interrupt(struct autri_softc *sc, int ch)
1392 {
1393 int reg;
1394
1395 reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A;
1396 ch &= 0x1f;
1397
1398 autri_reg_set_4(sc, reg, 1 << ch);
1399 }
1400
1401 static void
1402 autri_disable_interrupt(struct autri_softc *sc, int ch)
1403 {
1404 int reg;
1405
1406 reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A;
1407 ch &= 0x1f;
1408
1409 autri_reg_clear_4(sc, reg, 1 << ch);
1410 }
1411
1412 static void
1413 autri_startch(struct autri_softc *sc, int ch, int ch_intr)
1414 {
1415 int reg;
1416 u_int32_t chmask;
1417
1418 reg = (ch & 0x20) ? AUTRI_START_B : AUTRI_START_A;
1419 ch &= 0x1f;
1420 ch_intr &= 0x1f;
1421 chmask = (1 << ch) | (1 << ch_intr);
1422
1423 autri_reg_set_4(sc, reg, chmask);
1424 }
1425
1426 static void
1427 autri_stopch(struct autri_softc *sc, int ch, int ch_intr)
1428 {
1429 int reg;
1430 u_int32_t chmask;
1431
1432 reg = (ch & 0x20) ? AUTRI_STOP_B : AUTRI_STOP_A;
1433 ch &= 0x1f;
1434 ch_intr &= 0x1f;
1435 chmask = (1 << ch) | (1 << ch_intr);
1436
1437 autri_reg_set_4(sc, reg, chmask);
1438 }
1439
1440 #if NMIDI > 0
1441 int
1442 autri_midi_open(void *addr, int flags, void (*iintr)(void *, int),
1443 void (*ointr)(void *), void *arg)
1444 {
1445 struct autri_softc *sc = addr;
1446
1447 DPRINTF(("autri_midi_open()\n"));
1448
1449 DPRINTFN(5,("MPUR1 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR1)));
1450 DPRINTFN(5,("MPUR2 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR2)));
1451
1452 sc->sc_iintr = iintr;
1453 sc->sc_ointr = ointr;
1454 sc->sc_arg = arg;
1455
1456 if (flags & FREAD)
1457 autri_reg_clear_1(sc, AUTRI_MPUR2, AUTRI_MIDIIN_ENABLE_INTR);
1458
1459 if (flags & FWRITE)
1460 autri_reg_set_1(sc, AUTRI_MPUR2, AUTRI_MIDIOUT_CONNECT);
1461
1462 return (0);
1463 }
1464
1465 void
1466 autri_midi_close(void *addr)
1467 {
1468 struct autri_softc *sc = addr;
1469
1470 DPRINTF(("autri_midi_close()\n"));
1471
1472 tsleep(sc, PWAIT, "autri", hz/10); /* give uart a chance to drain */
1473
1474 sc->sc_iintr = NULL;
1475 sc->sc_ointr = NULL;
1476 }
1477
1478 int
1479 autri_midi_output(void *addr, int d)
1480 {
1481 struct autri_softc *sc = addr;
1482 int x;
1483
1484 for (x = 0; x != MIDI_BUSY_WAIT; x++) {
1485 if ((TREAD1(sc, AUTRI_MPUR1) & AUTRI_MIDIOUT_READY) == 0) {
1486 TWRITE1(sc, AUTRI_MPUR0, d);
1487 return (0);
1488 }
1489 delay(MIDI_BUSY_DELAY);
1490 }
1491 return (EIO);
1492 }
1493
1494 void
1495 autri_midi_getinfo(void *addr, struct midi_info *mi)
1496 {
1497 mi->name = "4DWAVE MIDI UART";
1498 mi->props = MIDI_PROP_CAN_INPUT;
1499 }
1500
1501 #endif
1502