1 /* $NetBSD: haltwo.c,v 1.3 2003/12/29 06:33:57 sekiya Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Ilpo Ruotsalainen 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 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * <<Id: LICENSE_GC,v 1.1 2001/10/01 23:24:05 cgd Exp>> 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: haltwo.c,v 1.3 2003/12/29 06:33:57 sekiya Exp $"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/device.h> 38 #include <sys/audioio.h> 39 #include <sys/malloc.h> 40 #include <dev/audio_if.h> 41 #include <dev/auconv.h> 42 #include <dev/mulaw.h> 43 44 #include <uvm/uvm_extern.h> 45 46 #include <machine/bus.h> 47 48 #include <sgimips/hpc/hpcvar.h> 49 #include <sgimips/hpc/hpcreg.h> 50 51 #include <sgimips/hpc/haltworeg.h> 52 #include <sgimips/hpc/haltwovar.h> 53 54 #ifdef AUDIO_DEBUG 55 #define DPRINTF(x) printf x 56 #else 57 #define DPRINTF(x) 58 #endif 59 60 static int haltwo_open(void *, int); 61 static void haltwo_close(void *); 62 static int haltwo_query_encoding(void *, struct audio_encoding *); 63 static int haltwo_set_params(void *, int, int, struct audio_params *, 64 struct audio_params *); 65 static int haltwo_round_blocksize(void *, int); 66 static int haltwo_halt_output(void *); 67 static int haltwo_halt_input(void *); 68 static int haltwo_getdev(void *, struct audio_device *); 69 static int haltwo_set_port(void *, mixer_ctrl_t *); 70 static int haltwo_get_port(void *, mixer_ctrl_t *); 71 static int haltwo_query_devinfo(void *, mixer_devinfo_t *); 72 static void *haltwo_malloc(void *, int, size_t, struct malloc_type *, int); 73 static void haltwo_free(void *, void *, struct malloc_type *); 74 static int haltwo_get_props(void *); 75 static int haltwo_trigger_output(void *, void *, void *, int, void (*)(void *), 76 void *, struct audio_params *); 77 static int haltwo_trigger_input(void *, void *, void *, int, void (*)(void *), 78 void *, struct audio_params *); 79 80 static struct audio_hw_if haltwo_hw_if = { 81 haltwo_open, 82 haltwo_close, 83 NULL, /* drain */ 84 haltwo_query_encoding, 85 haltwo_set_params, 86 haltwo_round_blocksize, 87 NULL, /* commit_settings */ 88 NULL, /* init_output */ 89 NULL, /* init_input */ 90 NULL, /* start_output */ 91 NULL, /* start_input */ 92 haltwo_halt_output, 93 haltwo_halt_input, 94 NULL, /* speaker_ctl */ 95 haltwo_getdev, 96 NULL, /* setfd */ 97 haltwo_set_port, 98 haltwo_get_port, 99 haltwo_query_devinfo, 100 haltwo_malloc, 101 haltwo_free, 102 NULL, /* round_buffersize */ 103 NULL, /* mappage */ 104 haltwo_get_props, 105 haltwo_trigger_output, 106 haltwo_trigger_input, 107 NULL /* dev_ioctl */ 108 }; 109 110 static const struct audio_device haltwo_device = { 111 "HAL2", 112 "", 113 "haltwo" 114 }; 115 116 static int haltwo_match(struct device *, struct cfdata *, void *); 117 static void haltwo_attach(struct device *, struct device *, void *); 118 static int haltwo_intr(void *); 119 120 CFATTACH_DECL(haltwo, sizeof(struct haltwo_softc), 121 haltwo_match, haltwo_attach, NULL, NULL); 122 123 #define haltwo_write(sc,type,off,val) \ 124 bus_space_write_4(sc->sc_st, sc->sc_##type##_sh, off, val) 125 126 #define haltwo_read(sc,type,off) \ 127 bus_space_read_4(sc->sc_st, sc->sc_##type##_sh, off) 128 129 static void 130 haltwo_write_indirect(struct haltwo_softc *sc, uint32_t ireg, uint16_t low, 131 uint16_t high) 132 { 133 134 haltwo_write(sc, ctl, HAL2_REG_CTL_IDR0, low); 135 haltwo_write(sc, ctl, HAL2_REG_CTL_IDR1, high); 136 haltwo_write(sc, ctl, HAL2_REG_CTL_IDR2, 0); 137 haltwo_write(sc, ctl, HAL2_REG_CTL_IDR3, 0); 138 haltwo_write(sc, ctl, HAL2_REG_CTL_IAR, ireg); 139 140 while (haltwo_read(sc, ctl, HAL2_REG_CTL_ISR) & HAL2_ISR_TSTATUS) 141 ; 142 } 143 144 static void 145 haltwo_read_indirect(struct haltwo_softc *sc, uint32_t ireg, uint16_t *low, 146 uint16_t *high) 147 { 148 149 haltwo_write(sc, ctl, HAL2_REG_CTL_IAR, 150 ireg | HAL2_IAR_READ); 151 152 while (haltwo_read(sc, ctl, HAL2_REG_CTL_ISR) & HAL2_ISR_TSTATUS) 153 ; 154 155 if (low) 156 *low = haltwo_read(sc, ctl, HAL2_REG_CTL_IDR0); 157 158 if (high) 159 *high = haltwo_read(sc, ctl, HAL2_REG_CTL_IDR1); 160 } 161 162 static int 163 haltwo_init_codec(struct haltwo_softc *sc, struct haltwo_codec *codec) 164 { 165 int err; 166 int rseg; 167 size_t allocsz = sizeof(struct hpc_dma_desc) * HALTWO_MAX_DMASEGS; 168 169 KASSERT(allocsz <= PAGE_SIZE); 170 171 err = bus_dmamem_alloc(sc->sc_dma_tag, allocsz, 0, 0, &codec->dma_seg, 172 1, &rseg, BUS_DMA_NOWAIT); 173 if (err) 174 goto out; 175 176 err = bus_dmamem_map(sc->sc_dma_tag, &codec->dma_seg, rseg, allocsz, 177 (caddr_t *)&codec->dma_descs, BUS_DMA_NOWAIT); 178 if (err) 179 goto out_free; 180 181 err = bus_dmamap_create(sc->sc_dma_tag, allocsz, 1, PAGE_SIZE, 0, 182 BUS_DMA_NOWAIT, &codec->dma_map); 183 if (err) 184 goto out_free; 185 186 err = bus_dmamap_load(sc->sc_dma_tag, codec->dma_map, codec->dma_descs, 187 allocsz, NULL, BUS_DMA_NOWAIT); 188 if (err) 189 goto out_destroy; 190 191 DPRINTF(("haltwo_init_codec: allocated %d descriptors (%d bytes)" 192 " at %p\n", HALTWO_MAX_DMASEGS, allocsz, codec->dma_descs)); 193 194 memset(codec->dma_descs, 0, allocsz); 195 196 return (0); 197 198 out_destroy: 199 bus_dmamap_destroy(sc->sc_dma_tag, codec->dma_map); 200 out_free: 201 bus_dmamem_free(sc->sc_dma_tag, &codec->dma_seg, rseg); 202 out: 203 DPRINTF(("haltwo_init_codec failed: %d\n",err)); 204 205 return (err); 206 } 207 208 static void 209 haltwo_setup_dma(struct haltwo_softc *sc, struct haltwo_codec *codec, 210 struct haltwo_dmabuf *dmabuf, size_t len, int blksize, 211 void (*intr)(void *), void *intrarg) 212 { 213 int i; 214 bus_dma_segment_t *segp; 215 struct hpc_dma_desc *descp; 216 int next_intr = blksize; 217 218 KASSERT(len % blksize == 0); 219 220 codec->intr = intr; 221 codec->intr_arg = intrarg; 222 223 segp = dmabuf->dma_map->dm_segs; 224 descp = codec->dma_descs; 225 226 /* Build descriptor chain for looping DMA, triggering interrupt every 227 * blksize bytes */ 228 for (i = 0; i < dmabuf->dma_map->dm_nsegs; i++) { 229 descp->hpc3_hdd_bufptr = segp->ds_addr; 230 descp->hpc3_hdd_ctl = segp->ds_len; 231 232 KASSERT(next_intr >= segp->ds_len); 233 234 if (next_intr == segp->ds_len) { 235 /* Generate intr after this DMA buffer */ 236 descp->hpc3_hdd_ctl |= HDD_CTL_INTR; 237 next_intr = blksize; 238 } else 239 next_intr -= segp->ds_len; 240 241 if (i < dmabuf->dma_map->dm_nsegs - 1) 242 descp->hdd_descptr = codec->dma_seg.ds_addr + 243 sizeof(struct hpc_dma_desc) * (i + 1); 244 else 245 descp->hdd_descptr = codec->dma_seg.ds_addr; 246 247 DPRINTF(("haltwo_setup_dma: hdd_bufptr = %x hdd_ctl = %x" 248 " hdd_descptr = %x\n", descp->hpc3_hdd_bufptr, 249 descp->hpc3_hdd_ctl, descp->hdd_descptr)); 250 251 segp++; 252 descp++; 253 } 254 255 bus_dmamap_sync(sc->sc_dma_tag, codec->dma_map, 0, 256 codec->dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); 257 } 258 259 static int 260 haltwo_match(struct device *parent, struct cfdata *cf, void *aux) 261 { 262 struct hpc_attach_args *haa = aux; 263 264 if (strcmp(haa->ha_name, cf->cf_name) == 0) 265 return (1); 266 267 return (0); 268 } 269 270 static void 271 haltwo_attach(struct device *parent, struct device *self, void *aux) 272 { 273 struct haltwo_softc *sc = (void *)self; 274 struct hpc_attach_args *haa = aux; 275 uint32_t rev; 276 277 sc->sc_st = haa->ha_st; 278 sc->sc_dma_tag = haa->ha_dmat; 279 280 if (bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_devoff, 281 HPC_PBUS_CH0_DEVREGS_SIZE, &sc->sc_ctl_sh)) { 282 aprint_error(": unable to map control registers\n"); 283 return; 284 } 285 286 if (bus_space_subregion(haa->ha_st, haa->ha_sh, HPC_PBUS_CH2_DEVREGS, 287 HPC_PBUS_CH2_DEVREGS_SIZE, &sc->sc_vol_sh)) { 288 aprint_error(": unable to map volume registers\n"); 289 return; 290 } 291 292 if (bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_dmaoff, 293 HPC_PBUS_DMAREGS_SIZE, &sc->sc_dma_sh)) { 294 aprint_error(": unable to map DMA registers\n"); 295 return; 296 } 297 298 haltwo_write(sc, ctl, HAL2_REG_CTL_ISR, 0); 299 haltwo_write(sc, ctl, HAL2_REG_CTL_ISR, 300 HAL2_ISR_GLOBAL_RESET_N | HAL2_ISR_CODEC_RESET_N); 301 haltwo_write_indirect(sc, HAL2_IREG_RELAY_C, HAL2_RELAY_C_STATE, 0); 302 303 rev = haltwo_read(sc, ctl, HAL2_REG_CTL_REV); 304 305 /* This bit is inverted, the test is correct */ 306 if (rev & HAL2_REV_AUDIO_PRESENT_N) { 307 aprint_error(": Audio hardware not present (revision %x)\n", 308 rev); 309 return; 310 } 311 312 if (cpu_intr_establish(haa->ha_irq, IPL_AUDIO, haltwo_intr, sc) 313 == NULL) { 314 aprint_error(": unable to establish interrupt\n"); 315 return; 316 } 317 318 aprint_naive(": Audio controller\n"); 319 320 aprint_normal(": HAL2 revision %d.%d.%d\n", (rev & 0x7000) >> 12, 321 (rev & 0x00F0) >> 4, rev & 0x000F); 322 323 if (haltwo_init_codec(sc, &sc->sc_dac)) { 324 aprint_error( 325 "haltwo_attach: unable to create DMA descriptor list\n"); 326 return; 327 } 328 329 /* XXX Magic PBUS CFGDMA values from Linux HAL2 driver XXX */ 330 bus_space_write_4(haa->ha_st, haa->ha_sh, HPC_PBUS_CH0_CFGDMA, 331 0x8208844); 332 bus_space_write_4(haa->ha_st, haa->ha_sh, HPC_PBUS_CH1_CFGDMA, 333 0x8208844); 334 335 /* Unmute output */ 336 /* XXX Add mute/unmute support to mixer ops? XXX */ 337 haltwo_write_indirect(sc, HAL2_IREG_DAC_C2, 0, 0); 338 339 /* Set master volume to zero */ 340 sc->sc_vol_left = sc->sc_vol_right = 0; 341 haltwo_write(sc, vol, HAL2_REG_VOL_LEFT, sc->sc_vol_left); 342 haltwo_write(sc, vol, HAL2_REG_VOL_RIGHT, sc->sc_vol_right); 343 344 audio_attach_mi(&haltwo_hw_if, sc, &sc->sc_dev); 345 } 346 347 static int 348 haltwo_intr(void *v) 349 { 350 struct haltwo_softc *sc = v; 351 int ret = 0; 352 353 if (bus_space_read_4(sc->sc_st, sc->sc_dma_sh, HPC_PBUS_CH0_CTL) 354 & HPC_PBUS_DMACTL_IRQ) { 355 sc->sc_dac.intr(sc->sc_dac.intr_arg); 356 357 ret = 1; 358 } else 359 DPRINTF(("haltwo_intr: Huh?\n")); 360 361 return (ret); 362 } 363 364 static int 365 haltwo_open(void *v, int flags) 366 { 367 368 DPRINTF(("haltwo_open flags = %x\n", flags)); 369 370 return (0); 371 } 372 373 static void 374 haltwo_close(void *v) 375 { 376 } 377 378 static int 379 haltwo_query_encoding(void *v, struct audio_encoding *e) 380 { 381 382 switch (e->index) { 383 case 0: 384 strcpy(e->name, AudioEslinear_le); 385 e->encoding = AUDIO_ENCODING_SLINEAR_LE; 386 e->precision = 16; 387 e->flags = 0; 388 break; 389 390 case 1: 391 strcpy(e->name, AudioEslinear_be); 392 e->encoding = AUDIO_ENCODING_SLINEAR_BE; 393 e->precision = 16; 394 e->flags = 0; 395 break; 396 397 case 2: 398 strcpy(e->name, AudioEmulaw); 399 e->encoding = AUDIO_ENCODING_ULAW; 400 e->precision = 8; 401 e->flags = AUDIO_ENCODINGFLAG_EMULATED; 402 break; 403 404 default: 405 return (EINVAL); 406 } 407 408 return (0); 409 } 410 411 static int 412 haltwo_set_params(void *v, int setmode, int usemode, struct audio_params *play, 413 struct audio_params *rec) 414 { 415 struct haltwo_softc *sc = v; 416 int master, inc, mod; 417 uint16_t tmp; 418 419 if (play->hw_sample_rate < 4000) 420 play->hw_sample_rate = 4000; 421 if (play->hw_sample_rate > 48000) 422 play->hw_sample_rate = 48000; 423 424 play->sw_code = NULL; 425 play->factor = 1; 426 play->factor_denom = 1; 427 428 switch (play->encoding) { 429 case AUDIO_ENCODING_ULAW: 430 if (play->precision != 8) 431 return (EINVAL); 432 433 play->sw_code = mulaw_to_slinear16_le; 434 play->factor = 2; 435 play->hw_encoding = AUDIO_ENCODING_SLINEAR_LE; 436 break; 437 case AUDIO_ENCODING_SLINEAR_BE: 438 case AUDIO_ENCODING_SLINEAR_LE: 439 break; 440 441 default: 442 return (EINVAL); 443 } 444 445 if (44100 % play->hw_sample_rate < 48000 % play->hw_sample_rate) 446 master = 44100; 447 else 448 master = 48000; 449 450 /* HAL2 specification 3.1.2.21: Codecs should be driven with INC/MOD 451 * fractions equivalent to 4/N, where N is a positive integer. */ 452 inc = 4; 453 mod = master * inc / play->hw_sample_rate; 454 455 /* Fixup upper layers idea of HW sample rate to the actual final rate */ 456 play->hw_sample_rate = master * inc / mod; 457 458 DPRINTF(("haltwo_set_params: master = %d inc = %d mod = %d" 459 " hw_sample_rate = %ld\n", master, inc, mod, 460 play->hw_sample_rate)); 461 462 /* Setup samplerate to HW */ 463 haltwo_write_indirect(sc, HAL2_IREG_BRES1_C1, 464 master == 44100 ? 1 : 0, 0); 465 /* XXX Documentation disagrees but this seems to work XXX */ 466 haltwo_write_indirect(sc, HAL2_IREG_BRES1_C2, 467 inc, 0xFFFF & (inc - mod - 1)); 468 469 /* Setup endianness to HW */ 470 haltwo_read_indirect(sc, HAL2_IREG_DMA_END, &tmp, NULL); 471 if (play->hw_encoding == AUDIO_ENCODING_SLINEAR_LE) 472 tmp |= HAL2_DMA_END_CODECTX; 473 else 474 tmp &= ~HAL2_DMA_END_CODECTX; 475 haltwo_write_indirect(sc, HAL2_IREG_DMA_END, tmp, 0); 476 477 /* Set PBUS channel, Bresenham clock source, number of channels to HW */ 478 haltwo_write_indirect(sc, HAL2_IREG_DAC_C1, 479 (0 << HAL2_C1_DMA_SHIFT) | 480 (1 << HAL2_C1_CLKID_SHIFT) | 481 (play->hw_channels << HAL2_C1_DATAT_SHIFT), 0); 482 483 DPRINTF(("haltwo_set_params: hw_encoding = %d hw_channels = %d\n", 484 play->hw_encoding, play->hw_channels)); 485 486 return (0); 487 } 488 489 static int 490 haltwo_round_blocksize(void *v,int blocksize) 491 { 492 493 /* XXX Make this smarter and support DMA descriptor chaining XXX */ 494 /* XXX Rounding to nearest PAGE_SIZE might work? XXX */ 495 return PAGE_SIZE; 496 } 497 498 static int 499 haltwo_halt_output(void *v) 500 { 501 struct haltwo_softc *sc = v; 502 503 /* Disable PBUS DMA */ 504 bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC_PBUS_CH0_CTL, 505 HPC_PBUS_DMACTL_ACT_LD); 506 507 return (0); 508 } 509 510 static int 511 haltwo_halt_input(void *v) 512 { 513 514 return (ENXIO); 515 } 516 517 static int 518 haltwo_getdev(void *v, struct audio_device *dev) 519 { 520 521 *dev = haltwo_device; 522 523 return (0); 524 } 525 526 static int 527 haltwo_set_port(void *v, mixer_ctrl_t *mc) 528 { 529 struct haltwo_softc *sc = v; 530 int lval, rval; 531 532 if (mc->type != AUDIO_MIXER_VALUE) 533 return (EINVAL); 534 535 if (mc->un.value.num_channels == 1) 536 lval = rval = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 537 else if (mc->un.value.num_channels == 2) { 538 lval = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 539 rval = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 540 } else 541 return (EINVAL); 542 543 switch (mc->dev) { 544 case HALTWO_MASTER_VOL: 545 sc->sc_vol_left = lval; 546 sc->sc_vol_right = rval; 547 548 haltwo_write(sc, vol, HAL2_REG_VOL_LEFT, 549 sc->sc_vol_left); 550 haltwo_write(sc, vol, HAL2_REG_VOL_RIGHT, 551 sc->sc_vol_right); 552 break; 553 554 default: 555 return (EINVAL); 556 } 557 558 return (0); 559 } 560 561 static int 562 haltwo_get_port(void *v, mixer_ctrl_t *mc) 563 { 564 struct haltwo_softc *sc = v; 565 int l, r; 566 567 switch (mc->dev) { 568 case HALTWO_MASTER_VOL: 569 l = sc->sc_vol_left; 570 r = sc->sc_vol_right; 571 break; 572 573 default: 574 return (EINVAL); 575 } 576 577 if (mc->un.value.num_channels == 1) 578 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = (l+r) / 2; 579 else if (mc->un.value.num_channels == 2) { 580 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l; 581 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r; 582 } else 583 return (EINVAL); 584 585 return (0); 586 } 587 588 static int 589 haltwo_query_devinfo(void *v, mixer_devinfo_t *dev) 590 { 591 592 switch (dev->index) { 593 /* Mixer values */ 594 case HALTWO_MASTER_VOL: 595 dev->type = AUDIO_MIXER_VALUE; 596 dev->mixer_class = HALTWO_OUTPUT_CLASS; 597 dev->prev = dev->next = AUDIO_MIXER_LAST; 598 strcpy(dev->label.name, AudioNmaster); 599 dev->un.v.num_channels = 2; 600 strcpy(dev->un.v.units.name, AudioNvolume); 601 break; 602 603 /* Mixer classes */ 604 case HALTWO_OUTPUT_CLASS: 605 dev->type = AUDIO_MIXER_CLASS; 606 dev->mixer_class = HALTWO_OUTPUT_CLASS; 607 dev->next = dev->prev = AUDIO_MIXER_LAST; 608 strcpy(dev->label.name, AudioCoutputs); 609 break; 610 611 default: 612 return (EINVAL); 613 } 614 615 return (0); 616 } 617 618 static int 619 haltwo_alloc_dmamem(struct haltwo_softc *sc, size_t size, 620 struct haltwo_dmabuf *p) 621 { 622 int err; 623 624 p->size = size; 625 626 /* XXX Check align/boundary XXX */ 627 /* XXX Pass flags and use them instead BUS_DMA_NOWAIT? XXX */ 628 err = bus_dmamem_alloc(sc->sc_dma_tag, p->size, 0, 0, p->dma_segs, 629 HALTWO_MAX_DMASEGS, &p->dma_segcount, BUS_DMA_NOWAIT); 630 if (err) 631 goto out; 632 633 /* XXX BUS_DMA_COHERENT? XXX */ 634 err = bus_dmamem_map(sc->sc_dma_tag, p->dma_segs, p->dma_segcount, 635 p->size, &p->kern_addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT); 636 if (err) 637 goto out_free; 638 639 /* XXX Just guessing ... XXX */ 640 err = bus_dmamap_create(sc->sc_dma_tag, p->size, HALTWO_MAX_DMASEGS, 641 PAGE_SIZE, 0, BUS_DMA_NOWAIT, &p->dma_map); 642 if (err) 643 goto out_free; 644 645 err = bus_dmamap_load(sc->sc_dma_tag, p->dma_map, p->kern_addr, 646 p->size, NULL, BUS_DMA_NOWAIT); 647 if (err) 648 goto out_destroy; 649 650 return 0; 651 652 out_destroy: 653 bus_dmamap_destroy(sc->sc_dma_tag, p->dma_map); 654 out_free: 655 bus_dmamem_free(sc->sc_dma_tag, p->dma_segs, p->dma_segcount); 656 out: 657 DPRINTF(("haltwo_alloc_dmamem failed: %d\n",err)); 658 659 return err; 660 } 661 662 static void * 663 haltwo_malloc(void *v, int direction, size_t size, struct malloc_type *type, 664 int flags) 665 { 666 struct haltwo_softc *sc = v; 667 struct haltwo_dmabuf *p; 668 669 DPRINTF(("haltwo_malloc size = %d\n", size)); 670 671 p = malloc(sizeof(struct haltwo_dmabuf), type, flags); 672 if (!p) 673 return 0; 674 675 if (haltwo_alloc_dmamem(sc, size, p)) { 676 free(p, type); 677 return 0; 678 } 679 680 p->next = sc->sc_dma_bufs; 681 sc->sc_dma_bufs = p; 682 683 return p->kern_addr; 684 } 685 686 static void 687 haltwo_free(void *v, void *addr, struct malloc_type *type) 688 { 689 struct haltwo_softc *sc = v; 690 struct haltwo_dmabuf *p,**pp; 691 692 for (pp = &sc->sc_dma_bufs; (p = *pp) != NULL; pp = &p->next) { 693 if (p->kern_addr == addr) { 694 *pp = p->next; 695 free(p, type); 696 return; 697 } 698 } 699 700 panic("haltwo_free: buffer not in list"); 701 } 702 703 static int 704 haltwo_get_props(void *v) 705 { 706 707 return (0); 708 } 709 710 static int 711 haltwo_trigger_output(void *v, void *start, void *end, int blksize, 712 void (*intr)(void *), void *intrarg, struct audio_params *param) 713 { 714 struct haltwo_softc *sc = v; 715 struct haltwo_dmabuf *p; 716 uint16_t tmp; 717 uint32_t ctrl; 718 unsigned int fifobeg, fifoend, highwater; 719 720 DPRINTF(("haltwo_trigger_output start = %p end = %p blksize = %d" 721 " param = %p\n", start, end, blksize, param)); 722 723 for (p = sc->sc_dma_bufs; p != NULL; p = p->next) 724 if (p->kern_addr == start) 725 break; 726 727 if (p == NULL) { 728 printf("haltwo_trigger_output: buffer not in list\n"); 729 730 return (EINVAL); 731 } 732 733 /* Disable PBUS DMA */ 734 bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC_PBUS_CH0_CTL, 735 HPC_PBUS_DMACTL_ACT_LD); 736 737 /* Disable HAL2 codec DMA */ 738 haltwo_read_indirect(sc, HAL2_IREG_DMA_PORT_EN, &tmp, NULL); 739 haltwo_write_indirect(sc, HAL2_IREG_DMA_PORT_EN, 740 tmp & ~HAL2_DMA_PORT_EN_CODECTX, 0); 741 742 haltwo_setup_dma(sc, &sc->sc_dac, p, (char *)end - (char *)start, 743 blksize, intr, intrarg); 744 745 highwater = (param->hw_channels * 4) >> 1; 746 fifobeg = 0; 747 fifoend = (param->hw_channels * 8) >> 3; 748 749 DPRINTF(("haltwo_trigger_output: hw_channels = %d highwater = %d" 750 " fifobeg = %d fifoend = %d\n", param->hw_channels, highwater, 751 fifobeg, fifoend)); 752 753 ctrl = HPC_PBUS_DMACTL_RT 754 | HPC_PBUS_DMACTL_ACT_LD 755 | (highwater << HPC_PBUS_DMACTL_HIGHWATER_SHIFT) 756 | (fifobeg << HPC_PBUS_DMACTL_FIFOBEG_SHIFT) 757 | (fifoend << HPC_PBUS_DMACTL_FIFOEND_SHIFT); 758 759 /* Using PBUS CH0 for DAC DMA */ 760 haltwo_write_indirect(sc, HAL2_IREG_DMA_DRV, 1, 0); 761 762 /* HAL2 is ready for action, now setup PBUS for DMA transfer */ 763 bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC_PBUS_CH0_DP, 764 sc->sc_dac.dma_seg.ds_addr); 765 bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC_PBUS_CH0_CTL, 766 ctrl | HPC_PBUS_DMACTL_ACT); 767 768 /* Both HAL2 and PBUS have been setup, now start it up */ 769 haltwo_read_indirect(sc, HAL2_IREG_DMA_PORT_EN, &tmp, NULL); 770 haltwo_write_indirect(sc, HAL2_IREG_DMA_PORT_EN, 771 tmp | HAL2_DMA_PORT_EN_CODECTX, 0); 772 773 return (0); 774 } 775 776 static int 777 haltwo_trigger_input(void *v, void *start, void *end, int blksize, 778 void (*intr)(void *), void *intrarg, struct audio_params *param) 779 { 780 struct haltwo_softc *sc = v; 781 struct haltwo_dmabuf *p; 782 783 DPRINTF(("haltwo_trigger_input start = %p end = %p blksize = %d\n", 784 start, end, blksize)); 785 786 for (p = sc->sc_dma_bufs; p != NULL; p = p->next) 787 if (p->kern_addr == start) 788 break; 789 790 if (p == NULL) { 791 printf("haltwo_trigger_input: buffer not in list\n"); 792 793 return (EINVAL); 794 } 795 796 #if 0 797 haltwo_setup_dma(sc, &sc->sc_adc, p, (char *)end - (char *)start, 798 blksize, intr, intrarg); 799 #endif 800 801 return (ENXIO); 802 } 803