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