1 /* $NetBSD: haltwo.c,v 1.10 2006/09/04 22:06:06 rumble 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.10 2006/09/04 22:06:06 rumble 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_query_encoding(void *, struct audio_encoding *); 61 static int haltwo_set_params(void *, int, int, audio_params_t *, 62 audio_params_t *, stream_filter_list_t *, stream_filter_list_t *); 63 static int haltwo_round_blocksize(void *, int, int, const audio_params_t *); 64 static int haltwo_halt_output(void *); 65 static int haltwo_halt_input(void *); 66 static int haltwo_getdev(void *, struct audio_device *); 67 static int haltwo_set_port(void *, mixer_ctrl_t *); 68 static int haltwo_get_port(void *, mixer_ctrl_t *); 69 static int haltwo_query_devinfo(void *, mixer_devinfo_t *); 70 static void *haltwo_malloc(void *, int, size_t, struct malloc_type *, int); 71 static void haltwo_free(void *, void *, struct malloc_type *); 72 static int haltwo_get_props(void *); 73 static int haltwo_trigger_output(void *, void *, void *, int, void (*)(void *), 74 void *, const audio_params_t *); 75 static int haltwo_trigger_input(void *, void *, void *, int, void (*)(void *), 76 void *, const audio_params_t *); 77 78 static const struct audio_hw_if haltwo_hw_if = { 79 NULL, /* open */ 80 NULL, /* close */ 81 NULL, /* drain */ 82 haltwo_query_encoding, 83 haltwo_set_params, 84 haltwo_round_blocksize, 85 NULL, /* commit_settings */ 86 NULL, /* init_output */ 87 NULL, /* init_input */ 88 NULL, /* start_output */ 89 NULL, /* start_input */ 90 haltwo_halt_output, 91 haltwo_halt_input, 92 NULL, /* speaker_ctl */ 93 haltwo_getdev, 94 NULL, /* setfd */ 95 haltwo_set_port, 96 haltwo_get_port, 97 haltwo_query_devinfo, 98 haltwo_malloc, 99 haltwo_free, 100 NULL, /* round_buffersize */ 101 NULL, /* mappage */ 102 haltwo_get_props, 103 haltwo_trigger_output, 104 haltwo_trigger_input, 105 NULL /* dev_ioctl */ 106 }; 107 108 static const struct audio_device haltwo_device = { 109 "HAL2", 110 "", 111 "haltwo" 112 }; 113 114 static int haltwo_match(struct device *, struct cfdata *, void *); 115 static void haltwo_attach(struct device *, struct device *, void *); 116 static int haltwo_intr(void *); 117 118 CFATTACH_DECL(haltwo, sizeof(struct haltwo_softc), 119 haltwo_match, haltwo_attach, NULL, NULL); 120 121 #define haltwo_write(sc,type,off,val) \ 122 bus_space_write_4(sc->sc_st, sc->sc_##type##_sh, off, val) 123 124 #define haltwo_read(sc,type,off) \ 125 bus_space_read_4(sc->sc_st, sc->sc_##type##_sh, off) 126 127 static void 128 haltwo_write_indirect(struct haltwo_softc *sc, uint32_t ireg, uint16_t low, 129 uint16_t high) 130 { 131 132 haltwo_write(sc, ctl, HAL2_REG_CTL_IDR0, low); 133 haltwo_write(sc, ctl, HAL2_REG_CTL_IDR1, high); 134 haltwo_write(sc, ctl, HAL2_REG_CTL_IDR2, 0); 135 haltwo_write(sc, ctl, HAL2_REG_CTL_IDR3, 0); 136 haltwo_write(sc, ctl, HAL2_REG_CTL_IAR, ireg); 137 138 while (haltwo_read(sc, ctl, HAL2_REG_CTL_ISR) & HAL2_ISR_TSTATUS) 139 continue; 140 } 141 142 static void 143 haltwo_read_indirect(struct haltwo_softc *sc, uint32_t ireg, uint16_t *low, 144 uint16_t *high) 145 { 146 147 haltwo_write(sc, ctl, HAL2_REG_CTL_IAR, 148 ireg | HAL2_IAR_READ); 149 150 while (haltwo_read(sc, ctl, HAL2_REG_CTL_ISR) & HAL2_ISR_TSTATUS) 151 continue; 152 153 if (low) 154 *low = haltwo_read(sc, ctl, HAL2_REG_CTL_IDR0); 155 156 if (high) 157 *high = haltwo_read(sc, ctl, HAL2_REG_CTL_IDR1); 158 } 159 160 static int 161 haltwo_init_codec(struct haltwo_softc *sc, struct haltwo_codec *codec) 162 { 163 int err; 164 int rseg; 165 size_t allocsz; 166 167 allocsz = sizeof(struct hpc_dma_desc) * HALTWO_MAX_DMASEGS; 168 KASSERT(allocsz <= PAGE_SIZE); 169 170 err = bus_dmamem_alloc(sc->sc_dma_tag, allocsz, 0, 0, &codec->dma_seg, 171 1, &rseg, BUS_DMA_NOWAIT); 172 if (err) 173 goto out; 174 175 err = bus_dmamem_map(sc->sc_dma_tag, &codec->dma_seg, rseg, allocsz, 176 (caddr_t *)&codec->dma_descs, BUS_DMA_NOWAIT); 177 if (err) 178 goto out_free; 179 180 err = bus_dmamap_create(sc->sc_dma_tag, allocsz, 1, PAGE_SIZE, 0, 181 BUS_DMA_NOWAIT, &codec->dma_map); 182 if (err) 183 goto out_free; 184 185 err = bus_dmamap_load(sc->sc_dma_tag, codec->dma_map, codec->dma_descs, 186 allocsz, NULL, BUS_DMA_NOWAIT); 187 if (err) 188 goto out_destroy; 189 190 DPRINTF(("haltwo_init_codec: allocated %d descriptors (%d bytes)" 191 " at %p\n", HALTWO_MAX_DMASEGS, allocsz, codec->dma_descs)); 192 193 memset(codec->dma_descs, 0, allocsz); 194 195 return 0; 196 197 out_destroy: 198 bus_dmamap_destroy(sc->sc_dma_tag, codec->dma_map); 199 out_free: 200 bus_dmamem_free(sc->sc_dma_tag, &codec->dma_seg, rseg); 201 out: 202 DPRINTF(("haltwo_init_codec failed: %d\n",err)); 203 204 return err; 205 } 206 207 static void 208 haltwo_setup_dma(struct haltwo_softc *sc, struct haltwo_codec *codec, 209 struct haltwo_dmabuf *dmabuf, size_t len, int blksize, 210 void (*intr)(void *), void *intrarg) 211 { 212 int i; 213 bus_dma_segment_t *segp; 214 struct hpc_dma_desc *descp; 215 int next_intr; 216 217 KASSERT(len % blksize == 0); 218 219 next_intr = blksize; 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 |= HPC3_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; 263 uint32_t rev; 264 265 haa = aux; 266 if (strcmp(haa->ha_name, cf->cf_name)) 267 return 0; 268 269 if ( badaddr((void *)(haa->ha_sh + haa->ha_devoff), sizeof(u_int32_t)) ) 270 return 0; 271 272 if ( badaddr((void *)(haa->ha_sh + haa->ha_devoff + HAL2_REG_CTL_REV), 273 sizeof(u_int32_t)) ) 274 return 0; 275 276 rev = *(uint32_t *)MIPS_PHYS_TO_KSEG1(haa->ha_sh + haa->ha_devoff + 277 HAL2_REG_CTL_REV); 278 279 /* This bit is inverted, the test is correct */ 280 if (rev & HAL2_REV_AUDIO_PRESENT_N) 281 return 0; 282 283 return 1; 284 } 285 286 static void 287 haltwo_attach(struct device *parent, struct device *self, void *aux) 288 { 289 struct haltwo_softc *sc; 290 struct hpc_attach_args *haa; 291 uint32_t rev; 292 293 sc = (void *)self; 294 haa = aux; 295 sc->sc_st = haa->ha_st; 296 sc->sc_dma_tag = haa->ha_dmat; 297 298 if (bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_devoff, 299 HPC3_PBUS_CH0_DEVREGS_SIZE, &sc->sc_ctl_sh)) { 300 aprint_error(": unable to map control registers\n"); 301 return; 302 } 303 304 if (bus_space_subregion(haa->ha_st, haa->ha_sh, HPC3_PBUS_CH2_DEVREGS, 305 HPC3_PBUS_CH2_DEVREGS_SIZE, &sc->sc_vol_sh)) { 306 aprint_error(": unable to map volume registers\n"); 307 return; 308 } 309 310 if (bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_dmaoff, 311 HPC3_PBUS_DMAREGS_SIZE, &sc->sc_dma_sh)) { 312 aprint_error(": unable to map DMA registers\n"); 313 return; 314 } 315 316 haltwo_write(sc, ctl, HAL2_REG_CTL_ISR, 0); 317 haltwo_write(sc, ctl, HAL2_REG_CTL_ISR, 318 HAL2_ISR_GLOBAL_RESET_N | HAL2_ISR_CODEC_RESET_N); 319 haltwo_write_indirect(sc, HAL2_IREG_RELAY_C, HAL2_RELAY_C_STATE, 0); 320 321 rev = haltwo_read(sc, ctl, HAL2_REG_CTL_REV); 322 323 if (cpu_intr_establish(haa->ha_irq, IPL_AUDIO, haltwo_intr, sc) 324 == NULL) { 325 aprint_error(": unable to establish interrupt\n"); 326 return; 327 } 328 329 aprint_naive(": Audio controller\n"); 330 331 aprint_normal(": HAL2 revision %d.%d.%d\n", (rev & 0x7000) >> 12, 332 (rev & 0x00F0) >> 4, rev & 0x000F); 333 334 if (haltwo_init_codec(sc, &sc->sc_dac)) { 335 aprint_error( 336 "haltwo_attach: unable to create DMA descriptor list\n"); 337 return; 338 } 339 340 /* XXX Magic PBUS CFGDMA values from Linux HAL2 driver XXX */ 341 bus_space_write_4(haa->ha_st, haa->ha_sh, HPC3_PBUS_CH0_CFGDMA, 342 0x8208844); 343 bus_space_write_4(haa->ha_st, haa->ha_sh, HPC3_PBUS_CH1_CFGDMA, 344 0x8208844); 345 346 /* Unmute output */ 347 /* XXX Add mute/unmute support to mixer ops? XXX */ 348 haltwo_write_indirect(sc, HAL2_IREG_DAC_C2, 0, 0); 349 350 /* Set master volume to zero */ 351 sc->sc_vol_left = sc->sc_vol_right = 0; 352 haltwo_write(sc, vol, HAL2_REG_VOL_LEFT, sc->sc_vol_left); 353 haltwo_write(sc, vol, HAL2_REG_VOL_RIGHT, sc->sc_vol_right); 354 355 audio_attach_mi(&haltwo_hw_if, sc, &sc->sc_dev); 356 } 357 358 static int 359 haltwo_intr(void *v) 360 { 361 struct haltwo_softc *sc; 362 int ret; 363 364 sc = v; 365 ret = 0; 366 if (bus_space_read_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_CTL) 367 & HPC3_PBUS_DMACTL_IRQ) { 368 sc->sc_dac.intr(sc->sc_dac.intr_arg); 369 370 ret = 1; 371 } else 372 DPRINTF(("haltwo_intr: Huh?\n")); 373 374 return ret; 375 } 376 377 static int 378 haltwo_query_encoding(void *v, struct audio_encoding *e) 379 { 380 381 switch (e->index) { 382 case 0: 383 strcpy(e->name, AudioEslinear_le); 384 e->encoding = AUDIO_ENCODING_SLINEAR_LE; 385 e->precision = 16; 386 e->flags = 0; 387 break; 388 389 case 1: 390 strcpy(e->name, AudioEslinear_be); 391 e->encoding = AUDIO_ENCODING_SLINEAR_BE; 392 e->precision = 16; 393 e->flags = 0; 394 break; 395 396 case 2: 397 strcpy(e->name, AudioEmulaw); 398 e->encoding = AUDIO_ENCODING_ULAW; 399 e->precision = 8; 400 e->flags = AUDIO_ENCODINGFLAG_EMULATED; 401 break; 402 403 default: 404 return EINVAL; 405 } 406 407 return 0; 408 } 409 410 static int 411 haltwo_set_params(void *v, int setmode, int usemode, 412 audio_params_t *play, audio_params_t *rec, 413 stream_filter_list_t *pfil, stream_filter_list_t *rfil) 414 { 415 audio_params_t hw; 416 struct haltwo_softc *sc; 417 int master, inc, mod; 418 uint16_t tmp; 419 420 sc = v; 421 if (play->sample_rate < 4000) 422 play->sample_rate = 4000; 423 if (play->sample_rate > 48000) 424 play->sample_rate = 48000; 425 426 if (44100 % play->sample_rate < 48000 % play->sample_rate) 427 master = 44100; 428 else 429 master = 48000; 430 431 /* HAL2 specification 3.1.2.21: Codecs should be driven with INC/MOD 432 * fractions equivalent to 4/N, where N is a positive integer. */ 433 inc = 4; 434 mod = master * inc / play->sample_rate; 435 436 /* Fixup upper layers idea of HW sample rate to the actual final rate */ 437 play->sample_rate = master * inc / mod; 438 439 DPRINTF(("haltwo_set_params: master = %d inc = %d mod = %d" 440 " sample_rate = %ld\n", master, inc, mod, 441 play->sample_rate)); 442 443 hw = *play; 444 switch (play->encoding) { 445 case AUDIO_ENCODING_ULAW: 446 if (play->precision != 8) 447 return EINVAL; 448 449 hw.encoding = AUDIO_ENCODING_SLINEAR_LE; 450 pfil->append(pfil, mulaw_to_linear16, &hw); 451 play = &hw; 452 break; 453 case AUDIO_ENCODING_SLINEAR_BE: 454 case AUDIO_ENCODING_SLINEAR_LE: 455 break; 456 457 default: 458 return EINVAL; 459 } 460 /* play points HW encoding */ 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->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->channels << HAL2_C1_DATAT_SHIFT), 0); 482 483 DPRINTF(("haltwo_set_params: hw_encoding = %d hw_channels = %d\n", 484 play->encoding, play->channels)); 485 486 return 0; 487 } 488 489 static int 490 haltwo_round_blocksize(void *v, int blocksize, 491 int mode, const audio_params_t *param) 492 { 493 494 /* XXX Make this smarter and support DMA descriptor chaining XXX */ 495 /* XXX Rounding to nearest PAGE_SIZE might work? XXX */ 496 return PAGE_SIZE; 497 } 498 499 static int 500 haltwo_halt_output(void *v) 501 { 502 struct haltwo_softc *sc; 503 504 sc = v; 505 /* Disable PBUS DMA */ 506 bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_CTL, 507 HPC3_PBUS_DMACTL_ACT_LD); 508 509 return 0; 510 } 511 512 static int 513 haltwo_halt_input(void *v) 514 { 515 516 return ENXIO; 517 } 518 519 static int 520 haltwo_getdev(void *v, struct audio_device *dev) 521 { 522 523 *dev = haltwo_device; 524 return 0; 525 } 526 527 static int 528 haltwo_set_port(void *v, mixer_ctrl_t *mc) 529 { 530 struct haltwo_softc *sc; 531 int lval, rval; 532 533 if (mc->type != AUDIO_MIXER_VALUE) 534 return EINVAL; 535 536 if (mc->un.value.num_channels == 1) 537 lval = rval = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 538 else if (mc->un.value.num_channels == 2) { 539 lval = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 540 rval = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 541 } else 542 return EINVAL; 543 544 sc = v; 545 switch (mc->dev) { 546 case HALTWO_MASTER_VOL: 547 sc->sc_vol_left = lval; 548 sc->sc_vol_right = rval; 549 550 haltwo_write(sc, vol, HAL2_REG_VOL_LEFT, 551 sc->sc_vol_left); 552 haltwo_write(sc, vol, HAL2_REG_VOL_RIGHT, 553 sc->sc_vol_right); 554 break; 555 556 default: 557 return EINVAL; 558 } 559 560 return 0; 561 } 562 563 static int 564 haltwo_get_port(void *v, mixer_ctrl_t *mc) 565 { 566 struct haltwo_softc *sc; 567 int l, r; 568 569 switch (mc->dev) { 570 case HALTWO_MASTER_VOL: 571 sc = v; 572 l = sc->sc_vol_left; 573 r = sc->sc_vol_right; 574 break; 575 576 default: 577 return EINVAL; 578 } 579 580 if (mc->un.value.num_channels == 1) 581 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = (l+r) / 2; 582 else if (mc->un.value.num_channels == 2) { 583 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l; 584 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r; 585 } else 586 return EINVAL; 587 588 return 0; 589 } 590 591 static int 592 haltwo_query_devinfo(void *v, mixer_devinfo_t *dev) 593 { 594 595 switch (dev->index) { 596 /* Mixer values */ 597 case HALTWO_MASTER_VOL: 598 dev->type = AUDIO_MIXER_VALUE; 599 dev->mixer_class = HALTWO_OUTPUT_CLASS; 600 dev->prev = dev->next = AUDIO_MIXER_LAST; 601 strcpy(dev->label.name, AudioNmaster); 602 dev->un.v.num_channels = 2; 603 strcpy(dev->un.v.units.name, AudioNvolume); 604 break; 605 606 /* Mixer classes */ 607 case HALTWO_OUTPUT_CLASS: 608 dev->type = AUDIO_MIXER_CLASS; 609 dev->mixer_class = HALTWO_OUTPUT_CLASS; 610 dev->next = dev->prev = AUDIO_MIXER_LAST; 611 strcpy(dev->label.name, AudioCoutputs); 612 break; 613 614 default: 615 return EINVAL; 616 } 617 618 return 0; 619 } 620 621 static int 622 haltwo_alloc_dmamem(struct haltwo_softc *sc, size_t size, 623 struct haltwo_dmabuf *p) 624 { 625 int err; 626 627 p->size = size; 628 629 /* XXX Check align/boundary XXX */ 630 /* XXX Pass flags and use them instead BUS_DMA_NOWAIT? XXX */ 631 err = bus_dmamem_alloc(sc->sc_dma_tag, p->size, 0, 0, p->dma_segs, 632 HALTWO_MAX_DMASEGS, &p->dma_segcount, BUS_DMA_NOWAIT); 633 if (err) 634 goto out; 635 636 /* XXX BUS_DMA_COHERENT? XXX */ 637 err = bus_dmamem_map(sc->sc_dma_tag, p->dma_segs, p->dma_segcount, 638 p->size, &p->kern_addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT); 639 if (err) 640 goto out_free; 641 642 /* XXX Just guessing ... XXX */ 643 err = bus_dmamap_create(sc->sc_dma_tag, p->size, HALTWO_MAX_DMASEGS, 644 PAGE_SIZE, 0, BUS_DMA_NOWAIT, &p->dma_map); 645 if (err) 646 goto out_free; 647 648 err = bus_dmamap_load(sc->sc_dma_tag, p->dma_map, p->kern_addr, 649 p->size, NULL, BUS_DMA_NOWAIT); 650 if (err) 651 goto out_destroy; 652 653 return 0; 654 655 out_destroy: 656 bus_dmamap_destroy(sc->sc_dma_tag, p->dma_map); 657 out_free: 658 bus_dmamem_free(sc->sc_dma_tag, p->dma_segs, p->dma_segcount); 659 out: 660 DPRINTF(("haltwo_alloc_dmamem failed: %d\n",err)); 661 662 return err; 663 } 664 665 static void * 666 haltwo_malloc(void *v, int direction, size_t size, struct malloc_type *type, 667 int flags) 668 { 669 struct haltwo_softc *sc; 670 struct haltwo_dmabuf *p; 671 672 DPRINTF(("haltwo_malloc size = %d\n", size)); 673 sc = v; 674 p = malloc(sizeof(struct haltwo_dmabuf), type, flags); 675 if (!p) 676 return 0; 677 678 if (haltwo_alloc_dmamem(sc, size, p)) { 679 free(p, type); 680 return 0; 681 } 682 683 p->next = sc->sc_dma_bufs; 684 sc->sc_dma_bufs = p; 685 686 return p->kern_addr; 687 } 688 689 static void 690 haltwo_free(void *v, void *addr, struct malloc_type *type) 691 { 692 struct haltwo_softc *sc; 693 struct haltwo_dmabuf *p, **pp; 694 695 sc = v; 696 for (pp = &sc->sc_dma_bufs; (p = *pp) != NULL; pp = &p->next) { 697 if (p->kern_addr == addr) { 698 *pp = p->next; 699 free(p, type); 700 return; 701 } 702 } 703 704 panic("haltwo_free: buffer not in list"); 705 } 706 707 static int 708 haltwo_get_props(void *v) 709 { 710 711 return 0; 712 } 713 714 static int 715 haltwo_trigger_output(void *v, void *start, void *end, int blksize, 716 void (*intr)(void *), void *intrarg, const audio_params_t *param) 717 { 718 struct haltwo_softc *sc; 719 struct haltwo_dmabuf *p; 720 uint16_t tmp; 721 uint32_t ctrl; 722 unsigned int fifobeg, fifoend, highwater; 723 724 DPRINTF(("haltwo_trigger_output start = %p end = %p blksize = %d" 725 " param = %p\n", start, end, blksize, param)); 726 sc = v; 727 for (p = sc->sc_dma_bufs; p != NULL; p = p->next) 728 if (p->kern_addr == start) 729 break; 730 731 if (p == NULL) { 732 printf("haltwo_trigger_output: buffer not in list\n"); 733 734 return EINVAL; 735 } 736 737 /* Disable PBUS DMA */ 738 bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_CTL, 739 HPC3_PBUS_DMACTL_ACT_LD); 740 741 /* Disable HAL2 codec DMA */ 742 haltwo_read_indirect(sc, HAL2_IREG_DMA_PORT_EN, &tmp, NULL); 743 haltwo_write_indirect(sc, HAL2_IREG_DMA_PORT_EN, 744 tmp & ~HAL2_DMA_PORT_EN_CODECTX, 0); 745 746 haltwo_setup_dma(sc, &sc->sc_dac, p, (char *)end - (char *)start, 747 blksize, intr, intrarg); 748 749 highwater = (param->channels * 4) >> 1; 750 fifobeg = 0; 751 fifoend = (param->channels * 8) >> 3; 752 753 DPRINTF(("haltwo_trigger_output: hw_channels = %d highwater = %d" 754 " fifobeg = %d fifoend = %d\n", param->hw_channels, highwater, 755 fifobeg, fifoend)); 756 757 ctrl = HPC3_PBUS_DMACTL_RT 758 | HPC3_PBUS_DMACTL_ACT_LD 759 | (highwater << HPC3_PBUS_DMACTL_HIGHWATER_SHIFT) 760 | (fifobeg << HPC3_PBUS_DMACTL_FIFOBEG_SHIFT) 761 | (fifoend << HPC3_PBUS_DMACTL_FIFOEND_SHIFT); 762 763 /* Using PBUS CH0 for DAC DMA */ 764 haltwo_write_indirect(sc, HAL2_IREG_DMA_DRV, 1, 0); 765 766 /* HAL2 is ready for action, now setup PBUS for DMA transfer */ 767 bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_DP, 768 sc->sc_dac.dma_seg.ds_addr); 769 bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_CTL, 770 ctrl | HPC3_PBUS_DMACTL_ACT); 771 772 /* Both HAL2 and PBUS have been setup, now start it up */ 773 haltwo_read_indirect(sc, HAL2_IREG_DMA_PORT_EN, &tmp, NULL); 774 haltwo_write_indirect(sc, HAL2_IREG_DMA_PORT_EN, 775 tmp | HAL2_DMA_PORT_EN_CODECTX, 0); 776 777 return 0; 778 } 779 780 static int 781 haltwo_trigger_input(void *v, void *start, void *end, int blksize, 782 void (*intr)(void *), void *intrarg, const audio_params_t *param) 783 { 784 struct haltwo_softc *sc; 785 struct haltwo_dmabuf *p; 786 787 DPRINTF(("haltwo_trigger_input start = %p end = %p blksize = %d\n", 788 start, end, blksize)); 789 sc = v; 790 for (p = sc->sc_dma_bufs; p != NULL; p = p->next) 791 if (p->kern_addr == start) 792 break; 793 794 if (p == NULL) { 795 printf("haltwo_trigger_input: buffer not in list\n"); 796 797 return EINVAL; 798 } 799 800 #if 0 801 haltwo_setup_dma(sc, &sc->sc_adc, p, (char *)end - (char *)start, 802 blksize, intr, intrarg); 803 #endif 804 805 return ENXIO; 806 } 807