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