1/* $NetBSD: haltwo.c,v 1.26 2019/05/25 04:41:53 isaki 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.26 2019/05/25 04:41:53 isaki 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 <sys/bus.h> 41#include <machine/sysconf.h> 42 43#include <dev/audio/audio_if.h> 44 45#include <sgimips/hpc/hpcvar.h> 46#include <sgimips/hpc/hpcreg.h> 47 48#include <sgimips/hpc/haltworeg.h> 49#include <sgimips/hpc/haltwovar.h> 50 51#ifdef AUDIO_DEBUG 52#define DPRINTF(x) printf x 53#else 54#define DPRINTF(x) 55#endif 56 57static int haltwo_query_format(void *, audio_format_query_t *); 58static int haltwo_set_format(void *, int, 59 const audio_params_t *, const audio_params_t *, 60 audio_filter_reg_t *, audio_filter_reg_t *); 61static int haltwo_round_blocksize(void *, int, int, const audio_params_t *); 62static int haltwo_halt_output(void *); 63static int haltwo_halt_input(void *); 64static int haltwo_getdev(void *, struct audio_device *); 65static int haltwo_set_port(void *, mixer_ctrl_t *); 66static int haltwo_get_port(void *, mixer_ctrl_t *); 67static int haltwo_query_devinfo(void *, mixer_devinfo_t *); 68static void *haltwo_malloc(void *, int, size_t); 69static void haltwo_free(void *, void *, size_t); 70static int haltwo_get_props(void *); 71static int haltwo_trigger_output(void *, void *, void *, int, void (*)(void *), 72 void *, const audio_params_t *); 73static int haltwo_trigger_input(void *, void *, void *, int, void (*)(void *), 74 void *, const audio_params_t *); 75static void haltwo_get_locks(void *, kmutex_t **, kmutex_t **); 76static bool haltwo_shutdown(device_t, int); 77 78static const struct audio_hw_if haltwo_hw_if = { 79 .query_format = haltwo_query_format, 80 .set_format = haltwo_set_format, 81 .round_blocksize = haltwo_round_blocksize, 82 .halt_output = haltwo_halt_output, 83 .halt_input = haltwo_halt_input, 84 .getdev = haltwo_getdev, 85 .set_port = haltwo_set_port, 86 .get_port = haltwo_get_port, 87 .query_devinfo = haltwo_query_devinfo, 88 .allocm = haltwo_malloc, 89 .freem = haltwo_free, 90 .get_props = haltwo_get_props, 91 .trigger_output = haltwo_trigger_output, 92 .trigger_input = haltwo_trigger_input, 93 .get_locks = haltwo_get_locks, 94}; 95 96static const struct audio_device haltwo_device = { 97 "HAL2", 98 "", 99 "haltwo" 100}; 101 102static const struct audio_format haltwo_formats = { 103 .mode = AUMODE_PLAY, 104 .encoding = AUDIO_ENCODING_SLINEAR_NE, 105 .validbits = 16, 106 .precision = 16, 107 .channels = 2, 108 .channel_mask = AUFMT_STEREO, 109 .frequency_type = 2, 110 .frequency = { 44100, 48000 }, 111}; 112#define HALTWO_NFORMATS __arraycount(haltwo_formats) 113 114static int haltwo_match(device_t, cfdata_t, void *); 115static void haltwo_attach(device_t, device_t, void *); 116static int haltwo_intr(void *); 117 118CFATTACH_DECL_NEW(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 127static void 128haltwo_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 142static void 143haltwo_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 160static int 161haltwo_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 (void **)&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 197out_destroy: 198 bus_dmamap_destroy(sc->sc_dma_tag, codec->dma_map); 199out_free: 200 bus_dmamem_free(sc->sc_dma_tag, &codec->dma_seg, rseg); 201out: 202 DPRINTF(("haltwo_init_codec failed: %d\n",err)); 203 204 return err; 205} 206 207static void 208haltwo_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 259static int 260haltwo_match(device_t parent, cfdata_t 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 ( platform.badaddr((void *)(vaddr_t)(haa->ha_sh + haa->ha_devoff), 270 sizeof(uint32_t)) ) 271 return 0; 272 273 if ( platform.badaddr( 274 (void *)(vaddr_t)(haa->ha_sh + haa->ha_devoff + HAL2_REG_CTL_REV), 275 sizeof(uint32_t)) ) 276 return 0; 277 278 rev = *(uint32_t *)MIPS_PHYS_TO_KSEG1(haa->ha_sh + haa->ha_devoff + 279 HAL2_REG_CTL_REV); 280 281 /* This bit is inverted, the test is correct */ 282 if (rev & HAL2_REV_AUDIO_PRESENT_N) 283 return 0; 284 285 return 1; 286} 287 288static void 289haltwo_attach(device_t parent, device_t self, void *aux) 290{ 291 struct haltwo_softc *sc; 292 struct hpc_attach_args *haa; 293 uint32_t rev; 294 295 sc = device_private(self); 296 haa = aux; 297 sc->sc_dev = self; 298 sc->sc_st = haa->ha_st; 299 sc->sc_dma_tag = haa->ha_dmat; 300 301 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 302 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); 303 304 if (bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_devoff, 305 HPC3_PBUS_CH0_DEVREGS_SIZE, &sc->sc_ctl_sh)) { 306 aprint_error(": unable to map control registers\n"); 307 return; 308 } 309 310 if (bus_space_subregion(haa->ha_st, haa->ha_sh, HPC3_PBUS_CH2_DEVREGS, 311 HPC3_PBUS_CH2_DEVREGS_SIZE, &sc->sc_vol_sh)) { 312 aprint_error(": unable to map volume registers\n"); 313 return; 314 } 315 316 if (bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_dmaoff, 317 HPC3_PBUS_DMAREGS_SIZE, &sc->sc_dma_sh)) { 318 aprint_error(": unable to map DMA registers\n"); 319 return; 320 } 321 322 haltwo_write(sc, ctl, HAL2_REG_CTL_ISR, 0); 323 haltwo_write(sc, ctl, HAL2_REG_CTL_ISR, 324 HAL2_ISR_GLOBAL_RESET_N | HAL2_ISR_CODEC_RESET_N); 325 haltwo_write_indirect(sc, HAL2_IREG_RELAY_C, HAL2_RELAY_C_STATE, 0); 326 327 rev = haltwo_read(sc, ctl, HAL2_REG_CTL_REV); 328 329 if (cpu_intr_establish(haa->ha_irq, IPL_AUDIO, haltwo_intr, sc) 330 == NULL) { 331 aprint_error(": unable to establish interrupt\n"); 332 return; 333 } 334 335 aprint_naive(": Audio controller\n"); 336 337 aprint_normal(": HAL2 revision %d.%d.%d\n", (rev & 0x7000) >> 12, 338 (rev & 0x00F0) >> 4, rev & 0x000F); 339 340 if (haltwo_init_codec(sc, &sc->sc_dac)) { 341 aprint_error( 342 "haltwo_attach: unable to create DMA descriptor list\n"); 343 return; 344 } 345 346 /* XXX Magic PBUS CFGDMA values from Linux HAL2 driver XXX */ 347 bus_space_write_4(haa->ha_st, haa->ha_sh, HPC3_PBUS_CH0_CFGDMA, 348 0x8208844); 349 bus_space_write_4(haa->ha_st, haa->ha_sh, HPC3_PBUS_CH1_CFGDMA, 350 0x8208844); 351 352 /* Unmute output */ 353 /* XXX Add mute/unmute support to mixer ops? XXX */ 354 haltwo_write_indirect(sc, HAL2_IREG_DAC_C2, 0, 0); 355 356 /* Set master volume to zero */ 357 sc->sc_vol_left = sc->sc_vol_right = 0; 358 haltwo_write(sc, vol, HAL2_REG_VOL_LEFT, sc->sc_vol_left); 359 haltwo_write(sc, vol, HAL2_REG_VOL_RIGHT, sc->sc_vol_right); 360 361 audio_attach_mi(&haltwo_hw_if, sc, self); 362 363 if (!pmf_device_register1(self, NULL, NULL, haltwo_shutdown)) 364 aprint_error_dev(self, 365 "couldn't establish power handler\n"); 366} 367 368static int 369haltwo_intr(void *v) 370{ 371 struct haltwo_softc *sc; 372 int ret; 373 374 sc = v; 375 ret = 0; 376 377 mutex_spin_enter(&sc->sc_intr_lock); 378 379 if (bus_space_read_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_CTL) 380 & HPC3_PBUS_DMACTL_IRQ) { 381 sc->sc_dac.intr(sc->sc_dac.intr_arg); 382 383 ret = 1; 384 } else 385 DPRINTF(("haltwo_intr: Huh?\n")); 386 387 mutex_spin_exit(&sc->sc_intr_lock); 388 389 return ret; 390} 391 392static int 393haltwo_query_format(void *v, audio_format_query_t *afp) 394{ 395 396 return audio_query_format(&haltwo_formats, 1, afp); 397} 398 399static int 400haltwo_set_format(void *v, int setmode, 401 const audio_params_t *play, const audio_params_t *rec, 402 audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 403{ 404 struct haltwo_softc *sc; 405 int inc; 406 uint16_t tmp; 407 408 sc = v; 409 inc = 4; 410 411 /* Setup samplerate to HW */ 412 haltwo_write_indirect(sc, HAL2_IREG_BRES1_C1, 413 play->sample_rate == 44100 ? 1 : 0, 0); 414 /* XXX Documentation disagrees but this seems to work XXX */ 415 haltwo_write_indirect(sc, HAL2_IREG_BRES1_C2, inc, 0xFFFF); 416 417 /* Setup endianness to HW */ 418 haltwo_read_indirect(sc, HAL2_IREG_DMA_END, &tmp, NULL); 419 if (play->encoding == AUDIO_ENCODING_SLINEAR_LE) 420 tmp |= HAL2_DMA_END_CODECTX; 421 else 422 tmp &= ~HAL2_DMA_END_CODECTX; 423 haltwo_write_indirect(sc, HAL2_IREG_DMA_END, tmp, 0); 424 425 /* Set PBUS channel, Bresenham clock source, number of channels to HW */ 426 haltwo_write_indirect(sc, HAL2_IREG_DAC_C1, 427 (0 << HAL2_C1_DMA_SHIFT) | 428 (1 << HAL2_C1_CLKID_SHIFT) | 429 (play->channels << HAL2_C1_DATAT_SHIFT), 0); 430 431 DPRINTF(("%s: hw_encoding = %d hw_channels = %d\n", __func__, 432 play->encoding, play->channels)); 433 434 return 0; 435} 436 437static int 438haltwo_round_blocksize(void *v, int blocksize, 439 int mode, const audio_params_t *param) 440{ 441 442 /* XXX Make this smarter and support DMA descriptor chaining XXX */ 443 /* XXX Rounding to nearest PAGE_SIZE might work? XXX */ 444 return PAGE_SIZE; 445} 446 447static int 448haltwo_halt_output(void *v) 449{ 450 struct haltwo_softc *sc; 451 452 sc = v; 453 /* Disable PBUS DMA */ 454 bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_CTL, 455 HPC3_PBUS_DMACTL_ACT_LD); 456 457 return 0; 458} 459 460static int 461haltwo_halt_input(void *v) 462{ 463 464 return ENXIO; 465} 466 467static int 468haltwo_getdev(void *v, struct audio_device *dev) 469{ 470 471 *dev = haltwo_device; 472 return 0; 473} 474 475static int 476haltwo_set_port(void *v, mixer_ctrl_t *mc) 477{ 478 struct haltwo_softc *sc; 479 int lval, rval; 480 481 if (mc->type != AUDIO_MIXER_VALUE) 482 return EINVAL; 483 484 if (mc->un.value.num_channels == 1) 485 lval = rval = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 486 else if (mc->un.value.num_channels == 2) { 487 lval = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 488 rval = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 489 } else 490 return EINVAL; 491 492 sc = v; 493 switch (mc->dev) { 494 case HALTWO_MASTER_VOL: 495 sc->sc_vol_left = lval; 496 sc->sc_vol_right = rval; 497 498 haltwo_write(sc, vol, HAL2_REG_VOL_LEFT, 499 sc->sc_vol_left); 500 haltwo_write(sc, vol, HAL2_REG_VOL_RIGHT, 501 sc->sc_vol_right); 502 break; 503 504 default: 505 return EINVAL; 506 } 507 508 return 0; 509} 510 511static int 512haltwo_get_port(void *v, mixer_ctrl_t *mc) 513{ 514 struct haltwo_softc *sc; 515 int l, r; 516 517 switch (mc->dev) { 518 case HALTWO_MASTER_VOL: 519 sc = v; 520 l = sc->sc_vol_left; 521 r = sc->sc_vol_right; 522 break; 523 524 default: 525 return EINVAL; 526 } 527 528 if (mc->un.value.num_channels == 1) 529 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = (l+r) / 2; 530 else if (mc->un.value.num_channels == 2) { 531 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l; 532 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r; 533 } else 534 return EINVAL; 535 536 return 0; 537} 538 539static int 540haltwo_query_devinfo(void *v, mixer_devinfo_t *dev) 541{ 542 543 switch (dev->index) { 544 /* Mixer values */ 545 case HALTWO_MASTER_VOL: 546 dev->type = AUDIO_MIXER_VALUE; 547 dev->mixer_class = HALTWO_OUTPUT_CLASS; 548 dev->prev = dev->next = AUDIO_MIXER_LAST; 549 strcpy(dev->label.name, AudioNmaster); 550 dev->un.v.num_channels = 2; 551 dev->un.v.delta = 16; 552 strcpy(dev->un.v.units.name, AudioNvolume); 553 break; 554 555 /* Mixer classes */ 556 case HALTWO_OUTPUT_CLASS: 557 dev->type = AUDIO_MIXER_CLASS; 558 dev->mixer_class = HALTWO_OUTPUT_CLASS; 559 dev->next = dev->prev = AUDIO_MIXER_LAST; 560 strcpy(dev->label.name, AudioCoutputs); 561 break; 562 563 default: 564 return EINVAL; 565 } 566 567 return 0; 568} 569 570static int 571haltwo_alloc_dmamem(struct haltwo_softc *sc, size_t size, 572 struct haltwo_dmabuf *p) 573{ 574 int err; 575 576 p->size = size; 577 578 /* XXX Check align/boundary XXX */ 579 err = bus_dmamem_alloc(sc->sc_dma_tag, p->size, 0, 0, p->dma_segs, 580 HALTWO_MAX_DMASEGS, &p->dma_segcount, BUS_DMA_WAITOK); 581 if (err) 582 goto out; 583 584 /* XXX BUS_DMA_COHERENT? XXX */ 585 err = bus_dmamem_map(sc->sc_dma_tag, p->dma_segs, p->dma_segcount, 586 p->size, &p->kern_addr, BUS_DMA_WAITOK | BUS_DMA_COHERENT); 587 if (err) 588 goto out_free; 589 590 /* XXX Just guessing ... XXX */ 591 err = bus_dmamap_create(sc->sc_dma_tag, p->size, HALTWO_MAX_DMASEGS, 592 PAGE_SIZE, 0, BUS_DMA_WAITOK, &p->dma_map); 593 if (err) 594 goto out_free; 595 596 err = bus_dmamap_load(sc->sc_dma_tag, p->dma_map, p->kern_addr, 597 p->size, NULL, BUS_DMA_WAITOK); 598 if (err) 599 goto out_destroy; 600 601 return 0; 602 603out_destroy: 604 bus_dmamap_destroy(sc->sc_dma_tag, p->dma_map); 605out_free: 606 bus_dmamem_free(sc->sc_dma_tag, p->dma_segs, p->dma_segcount); 607out: 608 DPRINTF(("haltwo_alloc_dmamem failed: %d\n",err)); 609 610 return err; 611} 612 613static void * 614haltwo_malloc(void *v, int direction, size_t size) 615{ 616 struct haltwo_softc *sc; 617 struct haltwo_dmabuf *p; 618 619 DPRINTF(("haltwo_malloc size = %d\n", size)); 620 sc = v; 621 p = kmem_alloc(sizeof(*p), KM_SLEEP); 622 if (haltwo_alloc_dmamem(sc, size, p)) { 623 kmem_free(p, sizeof(*p)); 624 return NULL; 625 } 626 627 p->next = sc->sc_dma_bufs; 628 sc->sc_dma_bufs = p; 629 630 return p->kern_addr; 631} 632 633static void 634haltwo_free(void *v, void *addr, size_t size) 635{ 636 struct haltwo_softc *sc; 637 struct haltwo_dmabuf *p, **pp; 638 639 sc = v; 640 for (pp = &sc->sc_dma_bufs; (p = *pp) != NULL; pp = &p->next) { 641 if (p->kern_addr == addr) { 642 *pp = p->next; 643 kmem_free(p, sizeof(*p)); 644 return; 645 } 646 } 647 648 panic("haltwo_free: buffer not in list"); 649} 650 651static int 652haltwo_get_props(void *v) 653{ 654 655 return AUDIO_PROP_PLAYBACK; 656} 657 658static int 659haltwo_trigger_output(void *v, void *start, void *end, int blksize, 660 void (*intr)(void *), void *intrarg, const audio_params_t *param) 661{ 662 struct haltwo_softc *sc; 663 struct haltwo_dmabuf *p; 664 uint16_t tmp; 665 uint32_t ctrl; 666 unsigned int fifobeg, fifoend, highwater; 667 668 DPRINTF(("haltwo_trigger_output start = %p end = %p blksize = %d" 669 " param = %p\n", start, end, blksize, param)); 670 sc = v; 671 for (p = sc->sc_dma_bufs; p != NULL; p = p->next) 672 if (p->kern_addr == start) 673 break; 674 675 if (p == NULL) { 676 printf("haltwo_trigger_output: buffer not in list\n"); 677 678 return EINVAL; 679 } 680 681 /* Disable PBUS DMA */ 682 bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_CTL, 683 HPC3_PBUS_DMACTL_ACT_LD); 684 685 /* Disable HAL2 codec DMA */ 686 haltwo_read_indirect(sc, HAL2_IREG_DMA_PORT_EN, &tmp, NULL); 687 haltwo_write_indirect(sc, HAL2_IREG_DMA_PORT_EN, 688 tmp & ~HAL2_DMA_PORT_EN_CODECTX, 0); 689 690 haltwo_setup_dma(sc, &sc->sc_dac, p, (char *)end - (char *)start, 691 blksize, intr, intrarg); 692 693 highwater = (param->channels * 4) >> 1; 694 fifobeg = 0; 695 fifoend = (param->channels * 8) >> 3; 696 697 DPRINTF(("haltwo_trigger_output: hw_channels = %d highwater = %d" 698 " fifobeg = %d fifoend = %d\n", param->channels, highwater, 699 fifobeg, fifoend)); 700 701 ctrl = HPC3_PBUS_DMACTL_RT 702 | HPC3_PBUS_DMACTL_ACT_LD 703 | (highwater << HPC3_PBUS_DMACTL_HIGHWATER_SHIFT) 704 | (fifobeg << HPC3_PBUS_DMACTL_FIFOBEG_SHIFT) 705 | (fifoend << HPC3_PBUS_DMACTL_FIFOEND_SHIFT); 706 707 /* Using PBUS CH0 for DAC DMA */ 708 haltwo_write_indirect(sc, HAL2_IREG_DMA_DRV, 1, 0); 709 710 /* HAL2 is ready for action, now setup PBUS for DMA transfer */ 711 bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_DP, 712 sc->sc_dac.dma_seg.ds_addr); 713 bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_CTL, 714 ctrl | HPC3_PBUS_DMACTL_ACT); 715 716 /* Both HAL2 and PBUS have been setup, now start it up */ 717 haltwo_read_indirect(sc, HAL2_IREG_DMA_PORT_EN, &tmp, NULL); 718 haltwo_write_indirect(sc, HAL2_IREG_DMA_PORT_EN, 719 tmp | HAL2_DMA_PORT_EN_CODECTX, 0); 720 721 return 0; 722} 723 724static int 725haltwo_trigger_input(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 731 DPRINTF(("haltwo_trigger_input start = %p end = %p blksize = %d\n", 732 start, end, blksize)); 733 sc = v; 734 for (p = sc->sc_dma_bufs; p != NULL; p = p->next) 735 if (p->kern_addr == start) 736 break; 737 738 if (p == NULL) { 739 printf("haltwo_trigger_input: buffer not in list\n"); 740 741 return EINVAL; 742 } 743 744#if 0 745 haltwo_setup_dma(sc, &sc->sc_adc, p, (char *)end - (char *)start, 746 blksize, intr, intrarg); 747#endif 748 749 return ENXIO; 750} 751 752static void 753haltwo_get_locks(void *v, kmutex_t **intr, kmutex_t **thread) 754{ 755 struct haltwo_softc *sc; 756 757 DPRINTF(("haltwo_get_locks\n")); 758 sc = v; 759 760 *intr = &sc->sc_intr_lock; 761 *thread = &sc->sc_lock; 762} 763 764bool 765haltwo_shutdown(device_t self, int howto) 766{ 767 struct haltwo_softc *sc; 768 769 sc = device_private(self); 770 haltwo_write(sc, ctl, HAL2_REG_CTL_ISR, 0); 771 haltwo_write(sc, ctl, HAL2_REG_CTL_ISR, 772 HAL2_ISR_GLOBAL_RESET_N | HAL2_ISR_CODEC_RESET_N); 773 774 return true; 775} 776