1 /* $NetBSD: vraiu.c,v 1.3 2002/10/02 05:26:53 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 2001 HAMAJIMA Katsuomi. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/device.h> 31 #include <sys/malloc.h> 32 #include <sys/bswap.h> 33 34 #include <machine/cpu.h> 35 #include <machine/intr.h> 36 #include <machine/bus.h> 37 #include <machine/platid.h> 38 #include <machine/platid_mask.h> 39 #include <machine/config_hook.h> 40 41 #include <sys/audioio.h> 42 #include <dev/audio_if.h> 43 44 #include <hpcmips/vr/vr.h> 45 #include <hpcmips/vr/vripif.h> 46 #include <hpcmips/vr/icureg.h> 47 #include <hpcmips/vr/cmureg.h> 48 #include <hpcmips/vr/vraiureg.h> 49 50 #ifdef VRAIU_DEBUG 51 int vraiu_debug = VRAIU_DEBUG; 52 #define DPRINTFN(n,x) if (vraiu_debug>(n)) printf x; 53 #else 54 #define DPRINTFN(n,x) 55 #endif 56 57 #define AUDIO_BUF_SIZE 2048 58 59 struct vraiu_softc { 60 struct device sc_dev; 61 bus_space_tag_t sc_iot; 62 bus_space_handle_t sc_ioh; 63 bus_dma_tag_t sc_dmat; 64 bus_dmamap_t sc_dmap; 65 vrip_chipset_tag_t sc_vrip; 66 vrdcu_chipset_tag_t sc_dc; 67 vrdmaau_chipset_tag_t sc_ac; 68 vrcmu_chipset_tag_t sc_cc; 69 void *sc_handler; 70 u_short *sc_buf; /* dma buffer pointer */ 71 int sc_status; /* status */ 72 u_int sc_rate; /* sampling rate */ 73 u_int sc_channels; /* # of channels used */ 74 u_int sc_encoding; /* encoding type */ 75 int sc_precision; /* 8 or 16 bits */ 76 /* pointer to format conversion routine */ 77 void (*sc_decodefunc)(struct vraiu_softc *, u_short *, void *, int); 78 void (*sc_intr)(void *); /* interrupt routine */ 79 void *sc_intrdata; /* interrupt data */ 80 }; 81 82 int vraiu_match(struct device *, struct cfdata *, void *); 83 void vraiu_attach(struct device *, struct device *, void *); 84 int vraiu_intr(void *); 85 86 CFATTACH_DECL(vraiu, sizeof(struct vraiu_softc), 87 vraiu_match, vraiu_attach, NULL, NULL); 88 89 struct audio_device aiu_device = { 90 "VR4121 AIU", 91 "0.1", 92 "aiu" 93 }; 94 95 /* 96 * Define our interface to the higher level audio driver. 97 */ 98 int vraiu_open(void *, int); 99 void vraiu_close(void *); 100 int vraiu_query_encoding(void *, struct audio_encoding *); 101 int vraiu_round_blocksize(void *, int); 102 int vraiu_commit_settings(void *); 103 int vraiu_init_output(void *, void*, int); 104 int vraiu_start_output(void *, void *, int, void (*)(void *), void *); 105 int vraiu_start_input(void *, void *, int, void (*)(void *), void *); 106 int vraiu_halt_output(void *); 107 int vraiu_halt_input(void *); 108 int vraiu_getdev(void *, struct audio_device *); 109 int vraiu_set_port(void *, mixer_ctrl_t *); 110 int vraiu_get_port(void *, mixer_ctrl_t *); 111 int vraiu_query_devinfo(void *, mixer_devinfo_t *); 112 int vraiu_set_params(void *, int, int, struct audio_params *, 113 struct audio_params *); 114 int vraiu_get_props(void *); 115 116 struct audio_hw_if vraiu_hw_if = { 117 vraiu_open, 118 vraiu_close, 119 NULL, 120 vraiu_query_encoding, 121 vraiu_set_params, 122 vraiu_round_blocksize, 123 vraiu_commit_settings, 124 vraiu_init_output, 125 NULL, 126 vraiu_start_output, 127 vraiu_start_input, 128 vraiu_halt_output, 129 vraiu_halt_input, 130 NULL, 131 vraiu_getdev, 132 NULL, 133 vraiu_set_port, 134 vraiu_get_port, 135 vraiu_query_devinfo, 136 NULL, 137 NULL, 138 NULL, 139 NULL, 140 vraiu_get_props, 141 }; 142 143 /* 144 * convert to 1ch 10bit unsigned PCM data. 145 */ 146 static void vraiu_slinear8_1(struct vraiu_softc *, u_short *, void *, int); 147 static void vraiu_slinear8_2(struct vraiu_softc *, u_short *, void *, int); 148 static void vraiu_ulinear8_1(struct vraiu_softc *, u_short *, void *, int); 149 static void vraiu_ulinear8_2(struct vraiu_softc *, u_short *, void *, int); 150 static void vraiu_ulaw_1(struct vraiu_softc *, u_short *, void *, int); 151 static void vraiu_ulaw_2(struct vraiu_softc *, u_short *, void *, int); 152 static void vraiu_slinear16_1(struct vraiu_softc *, u_short *, void *, int); 153 static void vraiu_slinear16_2(struct vraiu_softc *, u_short *, void *, int); 154 static void vraiu_slinear16sw_1(struct vraiu_softc *, u_short *, void *, int); 155 static void vraiu_slinear16sw_2(struct vraiu_softc *, u_short *, void *, int); 156 157 int 158 vraiu_match(struct device *parent, struct cfdata *cf, void *aux) 159 { 160 return 1; 161 } 162 163 void 164 vraiu_attach(struct device *parent, struct device *self, void *aux) 165 { 166 struct vrip_attach_args *va = aux; 167 struct vraiu_softc *sc = (void*)self; 168 bus_dma_segment_t segs; 169 int rsegs; 170 171 sc->sc_status = ENXIO; 172 sc->sc_intr = NULL; 173 sc->sc_iot = va->va_iot; 174 sc->sc_vrip = va->va_vc; 175 sc->sc_cc = va->va_cc; 176 sc->sc_dc = va->va_dc; 177 sc->sc_ac = va->va_ac; 178 sc->sc_dmat = &vrdcu_bus_dma_tag; 179 180 if (!sc->sc_cc) { 181 printf(" not configured: cmu not found\n"); 182 return; 183 } 184 if (!sc->sc_dc) { 185 printf(" not configured: dcu not found\n"); 186 return; 187 } 188 if (!sc->sc_ac) { 189 printf(" not configured: dmaau not found\n"); 190 return; 191 } 192 if (bus_space_map(sc->sc_iot, va->va_addr, va->va_size, 193 0 /* no flags */, &sc->sc_ioh)) { 194 printf(": can't map i/o space\n"); 195 return; 196 } 197 198 /* install interrupt handler and enable interrupt */ 199 if (!(sc->sc_handler = vrip_intr_establish(va->va_vc, va->va_unit, 200 0, IPL_AUDIO, 201 vraiu_intr, sc))) { 202 printf(": can't map interrupt line.\n"); 203 return; 204 } 205 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, (AIUINT_INTMEND | \ 206 AIUINT_INTM | \ 207 AIUINT_INTMIDLE | \ 208 AIUINT_INTMST | \ 209 AIUINT_INTSEND | \ 210 AIUINT_INTS | \ 211 AIUINT_INTSIDLE), 0); 212 213 if (bus_dmamem_alloc(sc->sc_dmat, AUDIO_BUF_SIZE, 0, 0, &segs, 1, 214 &rsegs, BUS_DMA_NOWAIT)) { 215 printf(": can't allocate memory.\n"); 216 return; 217 } 218 if (bus_dmamem_map(sc->sc_dmat, &segs, rsegs, AUDIO_BUF_SIZE, 219 (caddr_t *)&sc->sc_buf, 220 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) { 221 printf(": can't map memory.\n"); 222 bus_dmamem_free(sc->sc_dmat, &segs, rsegs); 223 return; 224 } 225 if (bus_dmamap_create(sc->sc_dmat, AUDIO_BUF_SIZE, 1, AUDIO_BUF_SIZE, 226 0, BUS_DMA_NOWAIT, &sc->sc_dmap)) { 227 printf(": can't create DMA map.\n"); 228 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_buf, 229 AUDIO_BUF_SIZE); 230 bus_dmamem_free(sc->sc_dmat, &segs, rsegs); 231 return; 232 } 233 if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmap, sc->sc_buf, 234 AUDIO_BUF_SIZE, NULL, BUS_DMA_NOWAIT)) { 235 printf(": can't load DMA map.\n"); 236 bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmap); 237 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_buf, 238 AUDIO_BUF_SIZE); 239 bus_dmamem_free(sc->sc_dmat, &segs, rsegs); 240 return; 241 } 242 if (sc->sc_ac->ac_set_aiuout(sc->sc_ac, sc->sc_buf)) { 243 printf(": can't set DMA address.\n"); 244 bus_dmamap_unload(sc->sc_dmat, sc->sc_dmap); 245 bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmap); 246 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_buf, 247 AUDIO_BUF_SIZE); 248 bus_dmamem_free(sc->sc_dmat, &segs, rsegs); 249 return; 250 } 251 printf("\n"); 252 253 sc->sc_status = 0; 254 sc->sc_rate = SPS8000; 255 sc->sc_channels = 1; 256 sc->sc_precision = 8; 257 sc->sc_encoding = AUDIO_ENCODING_ULAW; 258 sc->sc_decodefunc = vraiu_ulaw_1; 259 DPRINTFN(1, ("vraiu_attach: reset AIU\n")) 260 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SEQ_REG_W, AIURST); 261 /* attach audio subsystem */ 262 audio_attach_mi(&vraiu_hw_if, sc, &sc->sc_dev); 263 } 264 265 int 266 vraiu_open(void *self, int flags) 267 { 268 struct vraiu_softc *sc = (void*)self; 269 270 DPRINTFN(1, ("vraiu_open\n")); 271 272 if (sc->sc_status) { 273 DPRINTFN(0, ("vraiu_open: device error\n")); 274 return sc->sc_status; 275 } 276 sc->sc_status = EBUSY; 277 return 0; 278 } 279 280 void 281 vraiu_close(void *self) 282 { 283 struct vraiu_softc *sc = (void*)self; 284 285 DPRINTFN(1, ("vraiu_close\n")); 286 287 vraiu_halt_output(self); 288 sc->sc_status = 0; 289 } 290 291 int 292 vraiu_query_encoding(void *self, struct audio_encoding *ae) 293 { 294 DPRINTFN(3, ("vraiu_query_encoding\n")); 295 296 switch (ae->index) { 297 case 0: 298 strcpy(ae->name, AudioEslinear); 299 ae->encoding = AUDIO_ENCODING_SLINEAR; 300 ae->precision = 8; 301 ae->flags = AUDIO_ENCODINGFLAG_EMULATED; 302 break; 303 case 1: 304 strcpy(ae->name, AudioEmulaw); 305 ae->encoding = AUDIO_ENCODING_ULAW; 306 ae->precision = 8; 307 ae->flags = AUDIO_ENCODINGFLAG_EMULATED; 308 break; 309 case 2: 310 strcpy(ae->name, AudioEulinear); 311 ae->encoding = AUDIO_ENCODING_ULINEAR; 312 ae->precision = 8; 313 ae->flags = AUDIO_ENCODINGFLAG_EMULATED; 314 break; 315 case 3: 316 strcpy(ae->name, AudioEslinear); 317 ae->encoding = AUDIO_ENCODING_SLINEAR; 318 ae->precision = 16; 319 ae->flags = AUDIO_ENCODINGFLAG_EMULATED; 320 break; 321 case 4: 322 strcpy(ae->name, AudioEslinear_be); 323 ae->encoding = AUDIO_ENCODING_SLINEAR_BE; 324 ae->precision = 16; 325 ae->flags = AUDIO_ENCODINGFLAG_EMULATED; 326 break; 327 case 5: 328 strcpy(ae->name, AudioEslinear_le); 329 ae->encoding = AUDIO_ENCODING_SLINEAR_LE; 330 ae->precision = 16; 331 ae->flags = AUDIO_ENCODINGFLAG_EMULATED; 332 break; 333 case 6: 334 strcpy(ae->name, AudioEslinear); 335 ae->encoding = AUDIO_ENCODING_ULINEAR; 336 ae->precision = 16; 337 ae->flags = AUDIO_ENCODINGFLAG_EMULATED; 338 break; 339 case 7: 340 strcpy(ae->name, AudioEslinear_be); 341 ae->encoding = AUDIO_ENCODING_ULINEAR_BE; 342 ae->precision = 16; 343 ae->flags = AUDIO_ENCODINGFLAG_EMULATED; 344 break; 345 case 8: 346 strcpy(ae->name, AudioEslinear_le); 347 ae->encoding = AUDIO_ENCODING_ULINEAR_LE; 348 ae->precision = 16; 349 ae->flags = AUDIO_ENCODINGFLAG_EMULATED; 350 break; 351 default: 352 DPRINTFN(0, ("vraiu_query_encoding: param error" 353 " (%d)\n", ae->index)); 354 return EINVAL; 355 } 356 return 0; 357 } 358 359 int 360 vraiu_set_params(void *self, int setmode, int usemode, 361 struct audio_params *play, struct audio_params *rec) 362 { 363 struct vraiu_softc *sc = (void*)self; 364 365 DPRINTFN(1, ("vraiu_set_params: %dbit, %dch, %ldHz, encoding %d\n", 366 play->precision, play->channels, play->sample_rate, 367 play->encoding)); 368 369 switch (play->sample_rate) { 370 case 8000: 371 sc->sc_rate = SPS8000; 372 break; 373 case 11025: 374 sc->sc_rate = SPS11025; 375 break; 376 case 22050: 377 sc->sc_rate = SPS22050; 378 break; 379 case 44100: 380 sc->sc_rate = SPS44100; 381 break; 382 default: 383 DPRINTFN(0, ("vraiu_set_params: rate error (%ld)\n", 384 play->sample_rate)); 385 return EINVAL; 386 } 387 388 switch (play->precision) { 389 case 8: 390 switch (play->encoding) { 391 case AUDIO_ENCODING_ULAW: 392 switch (play->channels) { 393 case 1: 394 sc->sc_decodefunc = vraiu_ulaw_1; 395 break; 396 case 2: 397 sc->sc_decodefunc = vraiu_ulaw_2; 398 break; 399 default: 400 DPRINTFN(0, ("vraiu_set_params: channel error" 401 " (%d)\n", play->channels)); 402 return EINVAL; 403 } 404 break; 405 case AUDIO_ENCODING_SLINEAR: 406 case AUDIO_ENCODING_SLINEAR_BE: 407 case AUDIO_ENCODING_SLINEAR_LE: 408 switch (play->channels) { 409 case 1: 410 sc->sc_decodefunc = vraiu_slinear8_1; 411 break; 412 case 2: 413 sc->sc_decodefunc = vraiu_slinear8_2; 414 break; 415 default: 416 DPRINTFN(0, ("vraiu_set_params: channel error" 417 " (%d)\n", play->channels)); 418 return EINVAL; 419 } 420 break; 421 case AUDIO_ENCODING_ULINEAR: 422 case AUDIO_ENCODING_ULINEAR_BE: 423 case AUDIO_ENCODING_ULINEAR_LE: 424 switch (play->channels) { 425 case 1: 426 sc->sc_decodefunc = vraiu_ulinear8_1; 427 break; 428 case 2: 429 sc->sc_decodefunc = vraiu_ulinear8_2; 430 break; 431 default: 432 DPRINTFN(0, ("vraiu_set_params: channel error" 433 " (%d)\n", play->channels)); 434 return EINVAL; 435 } 436 break; 437 default: 438 DPRINTFN(0, ("vraiu_set_params: encoding error" 439 " (%d)\n", play->encoding)); 440 return EINVAL; 441 } 442 break; 443 case 16: 444 switch (play->encoding) { 445 #if BYTE_ORDER == BIG_ENDIAN 446 case AUDIO_ENCODING_SLINEAR: 447 #endif 448 case AUDIO_ENCODING_SLINEAR_BE: 449 switch (play->channels) { 450 case 1: 451 #if BYTE_ORDER == BIG_ENDIAN 452 sc->sc_decodefunc = vraiu_slinear16_1; 453 #else 454 sc->sc_decodefunc = vraiu_slinear16sw_1; 455 #endif 456 break; 457 case 2: 458 #if BYTE_ORDER == BIG_ENDIAN 459 sc->sc_decodefunc = vraiu_slinear16_2; 460 #else 461 sc->sc_decodefunc = vraiu_slinear16sw_2; 462 #endif 463 break; 464 default: 465 DPRINTFN(0, ("vraiu_set_params: channel error" 466 " (%d)\n", play->channels)); 467 return EINVAL; 468 } 469 break; 470 #if BYTE_ORDER == LITTLE_ENDIAN 471 case AUDIO_ENCODING_SLINEAR: 472 #endif 473 case AUDIO_ENCODING_SLINEAR_LE: 474 switch (play->channels) { 475 case 1: 476 #if BYTE_ORDER == LITTLE_ENDIAN 477 sc->sc_decodefunc = vraiu_slinear16_1; 478 #else 479 sc->sc_decodefunc = vraiu_slinear16sw_1; 480 #endif 481 break; 482 case 2: 483 #if BYTE_ORDER == LITTLE_ENDIAN 484 sc->sc_decodefunc = vraiu_slinear16_2; 485 #else 486 sc->sc_decodefunc = vraiu_slinear16sw_2; 487 #endif 488 break; 489 default: 490 DPRINTFN(0, ("vraiu_set_params: channel error" 491 " (%d)\n", play->channels)); 492 return EINVAL; 493 } 494 break; 495 default: 496 DPRINTFN(0, ("vraiu_set_params: encoding error" 497 " (%d)\n", play->encoding)); 498 return EINVAL; 499 } 500 break; 501 default: 502 DPRINTFN(0, ("vraiu_set_params: precision error (%d)\n", 503 play->precision)); 504 return EINVAL; 505 } 506 507 sc->sc_encoding = play->encoding; 508 sc->sc_precision = play->precision; 509 sc->sc_channels = play->channels; 510 return 0; 511 } 512 513 int 514 vraiu_round_blocksize(void *self, int bs) 515 { 516 struct vraiu_softc *sc = (void*)self; 517 int n = AUDIO_BUF_SIZE; 518 519 if (sc->sc_precision == 8) 520 n /= 2; 521 n *= sc->sc_channels; 522 523 DPRINTFN(1, ("vraiu_round_blocksize: upper %d, lower %d\n", 524 bs, n)); 525 526 return n; 527 } 528 529 int 530 vraiu_commit_settings(void *self) 531 { 532 struct vraiu_softc *sc = (void*)self; 533 int err; 534 535 DPRINTFN(1, ("vraiu_commit_settings\n")); 536 537 if (sc->sc_status != EBUSY) 538 return sc->sc_status; 539 540 DPRINTFN(1, ("vraiu_commit_settings: set conversion rate %d\n", 541 sc->sc_rate)) 542 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCNVR_REG_W, sc->sc_rate); 543 DPRINTFN(1, ("vraiu_commit_settings: clock supply start\n")) 544 if ((err = sc->sc_cc->cc_clock(sc->sc_cc, VR4102_CMUMSKAIU, 1))) { 545 DPRINTFN(0, ("vraiu_commit_settings: clock supply error\n")); 546 return err; 547 } 548 DPRINTFN(1, ("vraiu_commit_settings: enable DMA\n")) 549 if ((err = sc->sc_dc->dc_enable_aiuout(sc->sc_dc))) { 550 sc->sc_cc->cc_clock(sc->sc_cc, VR4102_CMUMSKAIU, 0); 551 DPRINTFN(0, ("vraiu_commit_settings: enable dma error\n")); 552 return err; 553 } 554 DPRINTFN(1, ("vraiu_commit_settings: Vref on\n")) 555 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCNT_REG_W, DAENAIU); 556 return 0; 557 } 558 559 int 560 vraiu_init_output(void *self, void *buffer, int size) 561 { 562 struct vraiu_softc *sc = (void*)self; 563 564 DPRINTFN(1, ("vraiu_init_output: buffer %p, size %d\n", buffer, size)); 565 566 sc->sc_intr = NULL; 567 DPRINTFN(1, ("vraiu_init_output: speaker power on\n")) 568 config_hook_call(CONFIG_HOOK_POWERCONTROL, 569 CONFIG_HOOK_POWERCONTROL_SPEAKER, (void*)1); 570 DPRINTFN(1, ("vraiu_init_output: start output\n")) 571 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SEQ_REG_W, AIUSEN); 572 return 0; 573 } 574 575 int 576 vraiu_start_output(void *self, void *block, int bsize, 577 void (*intr)(void *), void *intrarg) 578 { 579 struct vraiu_softc *sc = (void*)self; 580 581 DPRINTFN(2, ("vraiu_start_output: block %p, bsize %d\n", 582 block, bsize)); 583 sc->sc_decodefunc(sc, sc->sc_buf, block, bsize); 584 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, AUDIO_BUF_SIZE, 585 BUS_DMASYNC_PREWRITE); 586 sc->sc_intr = intr; 587 sc->sc_intrdata = intrarg; 588 /* clear interrupt status */ 589 bus_space_write_2(sc->sc_iot, sc->sc_ioh, INT_REG_W, 590 SENDINTR | SINTR | SIDLEINTR); 591 /* enable interrupt */ 592 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AIUINT_INTSEND, 1); 593 return 0; 594 } 595 596 int 597 vraiu_start_input(void *self, void *block, int bsize, 598 void (*intr)(void *), void *intrarg) 599 { 600 DPRINTFN(3, ("vraiu_start_input\n")); 601 602 /* no input */ 603 return ENXIO; 604 } 605 606 int 607 vraiu_intr(void* self) 608 { 609 struct vraiu_softc *sc = (void*)self; 610 u_int32_t reg; 611 612 DPRINTFN(2, ("vraiu_intr")); 613 614 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AIUINT_INTSEND, 0); 615 vrip_intr_getstatus2(sc->sc_vrip, sc->sc_handler, ®); 616 if (reg & AIUINT_INTSEND) { 617 DPRINTFN(2, (": AIUINT_INTSEND")); 618 if (sc->sc_intr) { 619 void (*intr)(void *) = sc->sc_intr; 620 sc->sc_intr = NULL; 621 (*(intr))(sc->sc_intrdata); 622 } 623 bus_space_write_2(sc->sc_iot, sc->sc_ioh, INT_REG_W, SENDINTR); 624 } 625 DPRINTFN(2, ("\n")); 626 return 0; 627 } 628 629 int 630 vraiu_halt_output(void *self) 631 { 632 struct vraiu_softc *sc = (void*)self; 633 634 DPRINTFN(1, ("vraiu_halt_output\n")); 635 636 DPRINTFN(1, ("vraiu_halt_output: disable interrupt\n")) 637 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AIUINT_INTSEND, 0); 638 DPRINTFN(1, ("vraiu_halt_output: stop output\n")) 639 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SEQ_REG_W, 0); 640 DPRINTFN(1, ("vraiu_halt_output: speaker power off\n")) 641 config_hook_call(CONFIG_HOOK_POWERCONTROL, 642 CONFIG_HOOK_POWERCONTROL_SPEAKER, (void*)0); 643 DPRINTFN(1, ("vraiu_halt_output: Vref off\n")) 644 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCNT_REG_W, 0); 645 DPRINTFN(1, ("vraiu_halt_output: disable DMA\n")) 646 sc->sc_dc->dc_disable(sc->sc_dc); 647 DPRINTFN(1, ("vraiu_halt_output: clock supply stop\n")) 648 sc->sc_cc->cc_clock(sc->sc_cc, VR4102_CMUMSKAIU, 0); 649 sc->sc_intr = NULL; 650 return 0; 651 } 652 653 int 654 vraiu_halt_input(void *self) 655 { 656 DPRINTFN(3, ("vraiu_halt_input\n")); 657 658 /* no input */ 659 return ENXIO; 660 } 661 662 663 int 664 vraiu_getdev(void *self, struct audio_device *ret) 665 { 666 DPRINTFN(3, ("vraiu_getdev\n")); 667 668 *ret = aiu_device; 669 return 0; 670 } 671 672 int 673 vraiu_set_port(void *self, mixer_ctrl_t *mc) 674 { 675 DPRINTFN(3, ("vraiu_set_port\n")); 676 677 /* no mixer */ 678 return EINVAL; 679 } 680 681 int 682 vraiu_get_port(void *self, mixer_ctrl_t *mc) 683 { 684 DPRINTFN(3, ("vraiu_get_port\n")); 685 686 /* no mixer */ 687 return EINVAL; 688 } 689 690 int 691 vraiu_query_devinfo(void *self, mixer_devinfo_t *di) 692 { 693 DPRINTFN(3, ("vraiu_query_devinfo\n")); 694 695 /* no mixer */ 696 return ENXIO; 697 } 698 699 int 700 vraiu_get_props(void *self) 701 { 702 DPRINTFN(3, ("vraiu_get_props\n")); 703 704 return 0; 705 } 706 707 unsigned char ulaw_to_lin[] = { 708 0x02, 0x06, 0x0a, 0x0e, 0x12, 0x16, 0x1a, 0x1e, 709 0x22, 0x26, 0x2a, 0x2e, 0x32, 0x36, 0x3a, 0x3e, 710 0x41, 0x43, 0x45, 0x47, 0x49, 0x4b, 0x4d, 0x4f, 711 0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x5f, 712 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 713 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 714 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x74, 715 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 716 0x78, 0x78, 0x79, 0x79, 0x79, 0x79, 0x7a, 0x7a, 717 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 718 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 719 0x7d, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 720 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 721 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 722 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 723 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 724 0xfd, 0xf9, 0xf5, 0xf1, 0xed, 0xe9, 0xe5, 0xe1, 725 0xdd, 0xd9, 0xd5, 0xd1, 0xcd, 0xc9, 0xc5, 0xc1, 726 0xbe, 0xbc, 0xba, 0xb8, 0xb6, 0xb4, 0xb2, 0xb0, 727 0xae, 0xac, 0xaa, 0xa8, 0xa6, 0xa4, 0xa2, 0xa0, 728 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 729 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 730 0x8f, 0x8e, 0x8e, 0x8d, 0x8d, 0x8c, 0x8c, 0x8b, 731 0x8b, 0x8a, 0x8a, 0x89, 0x89, 0x88, 0x88, 0x87, 732 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x85, 0x85, 733 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, 0x83, 0x83, 734 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, 735 0x82, 0x82, 0x82, 0x82, 0x81, 0x81, 0x81, 0x81, 736 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 737 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 738 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 739 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 740 }; 741 742 static void 743 vraiu_slinear8_1(struct vraiu_softc *sc, u_short *dmap, void *p, int n) 744 { 745 char *q = (char*)p; 746 747 DPRINTFN(3, ("vraiu_slinear8_1\n")); 748 749 #ifdef DIAGNOSTIC 750 if (n > AUDIO_BUF_SIZE/2) { 751 printf("%s: output data too large (%d > %d)\n", 752 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE/2); 753 n = AUDIO_BUF_SIZE/2; 754 } 755 #endif 756 while (n--) { 757 short i = *q++; 758 *dmap++ = (i << 2) + 0x200; 759 } 760 } 761 762 static void 763 vraiu_slinear8_2(struct vraiu_softc *sc, u_short *dmap, void *p, int n) 764 { 765 char *q = (char*)p; 766 767 DPRINTFN(3, ("vraiu_slinear8_2\n")); 768 769 #ifdef DIAGNOSTIC 770 if (n > AUDIO_BUF_SIZE) { 771 printf("%s: output data too large (%d > %d)\n", 772 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE); 773 n = AUDIO_BUF_SIZE; 774 } 775 #endif 776 n /= 2; 777 while (n--) { 778 short i = *q++; 779 short j = *q++; 780 *dmap++ = ((i + j) << 1) + 0x200; 781 } 782 } 783 784 static void 785 vraiu_ulinear8_1(struct vraiu_softc *sc, u_short *dmap, void *p, int n) 786 { 787 u_char *q = (u_char*)p; 788 789 DPRINTFN(3, ("vraiu_ulinear8_1\n")); 790 791 #ifdef DIAGNOSTIC 792 if (n > AUDIO_BUF_SIZE/2) { 793 printf("%s: output data too large (%d > %d)\n", 794 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE/2); 795 n = AUDIO_BUF_SIZE/2; 796 } 797 #endif 798 while (n--) { 799 short i = *q++; 800 *dmap++ = i << 2; 801 } 802 } 803 804 static void 805 vraiu_ulinear8_2(struct vraiu_softc *sc, u_short *dmap, void *p, int n) 806 { 807 u_char *q = (u_char*)p; 808 809 DPRINTFN(3, ("vraiu_ulinear8_2\n")); 810 811 #ifdef DIAGNOSTIC 812 if (n > AUDIO_BUF_SIZE) { 813 printf("%s: output data too large (%d > %d)\n", 814 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE); 815 n = AUDIO_BUF_SIZE; 816 } 817 #endif 818 n /= 2; 819 while (n--) { 820 short i = *q++; 821 short j = *q++; 822 *dmap++ = (i + j) << 1; 823 } 824 } 825 826 static void 827 vraiu_ulaw_1(struct vraiu_softc *sc, u_short *dmap, void *p, int n) 828 { 829 u_char *q = (u_char*)p; 830 831 DPRINTFN(3, ("vraiu_ulaw_1\n")); 832 833 #ifdef DIAGNOSTIC 834 if (n > AUDIO_BUF_SIZE/2) { 835 printf("%s: output data too large (%d > %d)\n", 836 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE/2); 837 n = AUDIO_BUF_SIZE/2; 838 } 839 #endif 840 while (n--) { 841 short i = ulaw_to_lin[*q++]; 842 *dmap++ = i << 2; 843 } 844 } 845 846 static void 847 vraiu_ulaw_2(struct vraiu_softc *sc, u_short *dmap, void *p, int n) 848 { 849 u_char *q = (u_char*)p; 850 851 DPRINTFN(3, ("vraiu_ulaw_2\n")); 852 853 #ifdef DIAGNOSTIC 854 if (n > AUDIO_BUF_SIZE) { 855 printf("%s: output data too large (%d > %d)\n", 856 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE); 857 n = AUDIO_BUF_SIZE; 858 } 859 #endif 860 n /= 2; 861 while (n--) { 862 short i = ulaw_to_lin[*q++]; 863 short j = ulaw_to_lin[*q++]; 864 *dmap++ = (i + j) << 1; 865 } 866 } 867 868 static void 869 vraiu_slinear16_1(struct vraiu_softc *sc, u_short *dmap, void *p, int n) 870 { 871 short *q = (short*)p; 872 873 DPRINTFN(3, ("vraiu_slinear16_1\n")); 874 875 #ifdef DIAGNOSTIC 876 if (n > AUDIO_BUF_SIZE) { 877 printf("%s: output data too large (%d > %d)\n", 878 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE); 879 n = AUDIO_BUF_SIZE; 880 } 881 #endif 882 n /= 2; 883 while (n--) { 884 short i = *q++; 885 *dmap++ = (i >> 6) + 0x200; 886 } 887 } 888 889 static void 890 vraiu_slinear16_2(struct vraiu_softc *sc, u_short *dmap, void *p, int n) 891 { 892 short *q = (short*)p; 893 894 DPRINTFN(3, ("vraiu_slinear16_2\n")); 895 896 #ifdef DIAGNOSTIC 897 if (n > AUDIO_BUF_SIZE*2) { 898 printf("%s: output data too large (%d > %d)\n", 899 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE*2); 900 n = AUDIO_BUF_SIZE*2; 901 } 902 #endif 903 n /= 4; 904 while (n--) { 905 short i = *q++; 906 short j = *q++; 907 *dmap++ = (i >> 7) + (j >> 7) + 0x200; 908 } 909 } 910 911 static void 912 vraiu_slinear16sw_1(struct vraiu_softc *sc, u_short *dmap, void *p, int n) 913 { 914 short *q = (short*)p; 915 916 DPRINTFN(3, ("vraiu_slinear16sw_1\n")); 917 918 #ifdef DIAGNOSTIC 919 if (n > AUDIO_BUF_SIZE) { 920 printf("%s: output data too large (%d > %d)\n", 921 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE); 922 n = AUDIO_BUF_SIZE; 923 } 924 #endif 925 n /= 2; 926 while (n--) { 927 short i = bswap16(*q++); 928 *dmap++ = (i >> 6) + 0x200; 929 } 930 } 931 932 static void 933 vraiu_slinear16sw_2(struct vraiu_softc *sc, u_short *dmap, void *p, int n) 934 { 935 short *q = (short*)p; 936 937 DPRINTFN(3, ("vraiu_slinear16sw_2\n")); 938 939 #ifdef DIAGNOSTIC 940 if (n > AUDIO_BUF_SIZE*2) { 941 printf("%s: output data too large (%d > %d)\n", 942 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE*2); 943 n = AUDIO_BUF_SIZE*2; 944 } 945 #endif 946 n /= 4; 947 while (n--) { 948 short i = bswap16(*q++); 949 short j = bswap16(*q++); 950 *dmap++ = (i >> 7) + (j >> 7) + 0x200; 951 } 952 } 953