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