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