1 /* $Id: imx23_digfilt.c,v 1.2 2019/05/08 13:40:14 isaki Exp $ */ 2 3 /* 4 * Copyright (c) 2014 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Petri Laakso. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/cdefs.h> 34 #include <sys/types.h> 35 #include <sys/device.h> 36 #include <sys/errno.h> 37 #include <sys/systm.h> 38 #include <sys/bus.h> 39 #include <sys/mutex.h> 40 #include <sys/audioio.h> 41 #include <sys/mallocvar.h> 42 #include <dev/audio/audio_if.h> 43 #include <arm/imx/imx23_digfiltreg.h> 44 #include <arm/imx/imx23_rtcvar.h> 45 #include <arm/imx/imx23_clkctrlvar.h> 46 #include <arm/imx/imx23_apbdmavar.h> 47 #include <arm/imx/imx23_icollreg.h> 48 #include <arm/imx/imx23var.h> 49 50 #include <arm/pic/picvar.h> 51 52 /* Autoconf. */ 53 static int digfilt_match(device_t, cfdata_t, void *); 54 static void digfilt_attach(device_t, device_t, void *); 55 static int digfilt_activate(device_t, enum devact); 56 57 /* Audio driver interface. */ 58 static int digfilt_query_format(void *, audio_format_query_t *); 59 static int digfilt_set_format(void *, int, 60 const audio_params_t *, const audio_params_t *, 61 audio_filter_reg_t *, audio_filter_reg_t *); 62 static int digfilt_round_blocksize(void *, int, int, const audio_params_t *); 63 static int digfilt_init_output(void *, void *, int ); 64 static int digfilt_start_output(void *, void *, int, void (*)(void *), void *); 65 static int digfilt_halt_output(void *); 66 static int digfilt_getdev(void *, struct audio_device *); 67 static int digfilt_set_port(void *, mixer_ctrl_t *); 68 static int digfilt_get_port(void *, mixer_ctrl_t *); 69 static int digfilt_query_devinfo(void *, mixer_devinfo_t *); 70 static void *digfilt_allocm(void *, int, size_t); 71 static void digfilt_freem(void *, void *, size_t); 72 static size_t digfilt_round_buffersize(void *, int, size_t); 73 static int digfilt_get_props(void *); 74 static void digfilt_get_locks(void *, kmutex_t **, kmutex_t **); 75 76 /* IRQs */ 77 static int dac_error_intr(void *); 78 static int dac_dma_intr(void *); 79 80 struct digfilt_softc; 81 82 /* Audio out. */ 83 static void *digfilt_ao_alloc_dmachain(void *, size_t); 84 static void digfilt_ao_apply_mutes(struct digfilt_softc *); 85 static void digfilt_ao_init(struct digfilt_softc *); 86 static void digfilt_ao_reset(struct digfilt_softc *); 87 static void digfilt_ao_set_rate(struct digfilt_softc *, int); 88 89 /* Audio in. */ 90 #if 0 91 static void digfilt_ai_reset(struct digfilt_softc *); 92 #endif 93 94 #define DIGFILT_DMA_NSEGS 1 95 #define DIGFILT_BLOCKSIZE_MAX 4096 96 #define DIGFILT_BLOCKSIZE_ROUND 512 97 #define DIGFILT_DMA_CHAIN_LENGTH 3 98 #define DIGFILT_DMA_CHANNEL 1 99 #define DIGFILT_MUTE_DAC 1 100 #define DIGFILT_MUTE_HP 2 101 #define DIGFILT_MUTE_LINE 4 102 #define DIGFILT_SOFT_RST_LOOP 455 /* At least 1 us. */ 103 104 #define AO_RD(sc, reg) \ 105 bus_space_read_4(sc->sc_iot, sc->sc_aohdl, (reg)) 106 #define AO_WR(sc, reg, val) \ 107 bus_space_write_4(sc->sc_iot, sc->sc_aohdl, (reg), (val)) 108 #define AI_RD(sc, reg) \ 109 bus_space_read_4(sc->sc_iot, sc->sc_aihdl, (reg)) 110 #define AI_WR(sc, reg, val) \ 111 bus_space_write_4(sc->sc_iot, sc->sc_aihdl, (reg), (val)) 112 113 struct digfilt_softc { 114 device_t sc_dev; 115 device_t sc_audiodev; 116 struct audio_format sc_format; 117 bus_space_handle_t sc_aihdl; 118 bus_space_handle_t sc_aohdl; 119 apbdma_softc_t sc_dmac; 120 bus_dma_tag_t sc_dmat; 121 bus_dmamap_t sc_dmamp; 122 bus_dmamap_t sc_c_dmamp; 123 bus_dma_segment_t sc_ds[DIGFILT_DMA_NSEGS]; 124 bus_dma_segment_t sc_c_ds[DIGFILT_DMA_NSEGS]; 125 bus_space_handle_t sc_hdl; 126 kmutex_t sc_intr_lock; 127 bus_space_tag_t sc_iot; 128 kmutex_t sc_lock; 129 audio_params_t sc_pparam; 130 void *sc_buffer; 131 void *sc_dmachain; 132 void *sc_intarg; 133 void (*sc_intr)(void*); 134 uint8_t sc_mute; 135 uint8_t sc_cmd_index; 136 }; 137 138 CFATTACH_DECL3_NEW(digfilt, 139 sizeof(struct digfilt_softc), 140 digfilt_match, 141 digfilt_attach, 142 NULL, 143 digfilt_activate, 144 NULL, 145 NULL, 146 0); 147 148 static const struct audio_hw_if digfilt_hw_if = { 149 .open = NULL, 150 .close = NULL, 151 .query_format = digfilt_query_format, 152 .set_format = digfilt_set_format, 153 .round_blocksize = digfilt_round_blocksize, 154 .commit_settings = NULL, 155 .init_output = digfilt_init_output, 156 .init_input = NULL, 157 .start_output = digfilt_start_output, 158 .start_input = NULL, 159 .halt_output = digfilt_halt_output, 160 .speaker_ctl = NULL, 161 .getdev = digfilt_getdev, 162 .set_port = digfilt_set_port, 163 .get_port = digfilt_get_port, 164 .query_devinfo = digfilt_query_devinfo, 165 .allocm = digfilt_allocm, 166 .freem = digfilt_freem, 167 .round_buffersize = digfilt_round_buffersize, 168 .get_props = digfilt_get_props, 169 .trigger_output = NULL, 170 .trigger_input = NULL, 171 .dev_ioctl = NULL, 172 .get_locks = digfilt_get_locks 173 }; 174 175 enum { 176 DIGFILT_OUTPUT_CLASS, 177 DIGFILT_OUTPUT_DAC_VOLUME, 178 DIGFILT_OUTPUT_DAC_MUTE, 179 DIGFILT_OUTPUT_HP_VOLUME, 180 DIGFILT_OUTPUT_HP_MUTE, 181 DIGFILT_OUTPUT_LINE_VOLUME, 182 DIGFILT_OUTPUT_LINE_MUTE, 183 DIGFILT_ENUM_LAST 184 }; 185 186 static int 187 digfilt_match(device_t parent, cfdata_t match, void *aux) 188 { 189 struct apb_attach_args *aa = aux; 190 191 if (aa->aa_addr == HW_DIGFILT_BASE && aa->aa_size == HW_DIGFILT_SIZE) 192 return 1; 193 else 194 return 0; 195 } 196 197 static void 198 digfilt_attach(device_t parent, device_t self, void *aux) 199 { 200 struct apb_softc *sc_parent = device_private(parent); 201 struct digfilt_softc *sc = device_private(self); 202 struct apb_attach_args *aa = aux; 203 static int digfilt_attached = 0; 204 int error; 205 uint32_t v; 206 void *intr; 207 208 sc->sc_dev = self; 209 sc->sc_iot = aa->aa_iot; 210 sc->sc_dmat = aa->aa_dmat; 211 212 /* This driver requires DMA functionality from the bus. 213 * Parent bus passes handle to the DMA controller instance. */ 214 if (sc_parent->dmac == NULL) { 215 aprint_error_dev(sc->sc_dev, "DMA functionality missing\n"); 216 return; 217 } 218 sc->sc_dmac = device_private(sc_parent->dmac); 219 220 if (aa->aa_addr == HW_DIGFILT_BASE && digfilt_attached) { 221 aprint_error_dev(sc->sc_dev, "DIGFILT already attached\n"); 222 return; 223 } 224 225 /* Allocate DMA for audio buffer. */ 226 error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, DIGFILT_DMA_NSEGS, 227 MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_dmamp); 228 if (error) { 229 aprint_error_dev(sc->sc_dev, 230 "Unable to allocate DMA handle\n"); 231 return; 232 } 233 234 /* Allocate for DMA chain. */ 235 error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, DIGFILT_DMA_NSEGS, 236 MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_c_dmamp); 237 if (error) { 238 aprint_error_dev(sc->sc_dev, 239 "Unable to allocate DMA handle\n"); 240 return; 241 } 242 243 /* Map DIGFILT bus space. */ 244 if (bus_space_map(sc->sc_iot, HW_DIGFILT_BASE, HW_DIGFILT_SIZE, 0, 245 &sc->sc_hdl)) { 246 aprint_error_dev(sc->sc_dev, 247 "Unable to map DIGFILT bus space\n"); 248 return; 249 } 250 251 /* Map AUDIOOUT subregion from parent bus space. */ 252 if (bus_space_subregion(sc->sc_iot, sc->sc_hdl, 253 (HW_AUDIOOUT_BASE - HW_DIGFILT_BASE), HW_AUDIOOUT_SIZE, 254 &sc->sc_aohdl)) { 255 aprint_error_dev(sc->sc_dev, 256 "Unable to submap AUDIOOUT bus space\n"); 257 return; 258 } 259 260 /* Map AUDIOIN subregion from parent bus space. */ 261 if (bus_space_subregion(sc->sc_iot, sc->sc_hdl, 262 (HW_AUDIOIN_BASE - HW_DIGFILT_BASE), HW_AUDIOIN_SIZE, 263 &sc->sc_aihdl)) { 264 aprint_error_dev(sc->sc_dev, 265 "Unable to submap AUDIOIN bus space\n"); 266 return; 267 } 268 269 /* Enable clocks to the DIGFILT block. */ 270 clkctrl_en_filtclk(); 271 delay(10); 272 273 digfilt_ao_reset(sc); /* Reset AUDIOOUT. */ 274 /* Not yet: digfilt_ai_reset(sc); */ 275 276 v = AO_RD(sc, HW_AUDIOOUT_VERSION); 277 aprint_normal(": DIGFILT Block v%" __PRIuBIT ".%" __PRIuBIT 278 ".%" __PRIuBIT "\n", 279 __SHIFTOUT(v, HW_AUDIOOUT_VERSION_MAJOR), 280 __SHIFTOUT(v, HW_AUDIOOUT_VERSION_MINOR), 281 __SHIFTOUT(v, HW_AUDIOOUT_VERSION_STEP)); 282 283 digfilt_ao_init(sc); 284 digfilt_ao_set_rate(sc, 44100); /* Default sample rate 44.1 kHz. */ 285 286 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 287 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED); 288 289 /* HW supported formats. */ 290 sc->sc_format.mode = AUMODE_PLAY|AUMODE_RECORD; 291 sc->sc_format.encoding = AUDIO_ENCODING_SLINEAR_LE; 292 sc->sc_format.validbits = 16; 293 sc->sc_format.precision = 16; 294 sc->sc_format.channels = 2; 295 sc->sc_format.channel_mask = AUFMT_STEREO; 296 sc->sc_format.frequency_type = 8; 297 sc->sc_format.frequency[0] = 8000; 298 sc->sc_format.frequency[1] = 11025; 299 sc->sc_format.frequency[2] = 12000; 300 sc->sc_format.frequency[3] = 16000; 301 sc->sc_format.frequency[4] = 22050; 302 sc->sc_format.frequency[5] = 24000; 303 sc->sc_format.frequency[6] = 32000; 304 sc->sc_format.frequency[7] = 44100; 305 306 sc->sc_audiodev = audio_attach_mi(&digfilt_hw_if, sc, sc->sc_dev); 307 308 /* Default mutes. */ 309 sc->sc_mute = DIGFILT_MUTE_LINE; 310 digfilt_ao_apply_mutes(sc); 311 312 /* Allocate DMA safe memory for the DMA chain. */ 313 sc->sc_dmachain = digfilt_ao_alloc_dmachain(sc, 314 sizeof(struct apbdma_command) * DIGFILT_DMA_CHAIN_LENGTH); 315 if (sc->sc_dmachain == NULL) { 316 aprint_error_dev(self, "digfilt_ao_alloc_dmachain failed\n"); 317 return; 318 } 319 320 intr = intr_establish(IRQ_DAC_DMA, IPL_SCHED, IST_LEVEL, dac_dma_intr, 321 sc); 322 if (intr == NULL) { 323 aprint_error_dev(sc->sc_dev, 324 "Unable to establish IRQ for DAC_DMA\n"); 325 return; 326 } 327 328 intr = intr_establish(IRQ_DAC_ERROR, IPL_SCHED, IST_LEVEL, 329 dac_error_intr, sc); 330 if (intr == NULL) { 331 aprint_error_dev(sc->sc_dev, 332 "Unable to establish IRQ for DAC_ERROR\n"); 333 return; 334 } 335 336 /* Initialize DMA channel. */ 337 apbdma_chan_init(sc->sc_dmac, DIGFILT_DMA_CHANNEL); 338 339 digfilt_attached = 1; 340 341 return; 342 } 343 344 static int 345 digfilt_activate(device_t self, enum devact act) 346 { 347 return EOPNOTSUPP; 348 } 349 350 static int 351 digfilt_query_format(void *priv, audio_format_query_t *afp) 352 { 353 struct digfilt_softc *sc = priv; 354 355 return audio_query_format(&sc->sc_format, 1, afp); 356 } 357 358 static int 359 digfilt_set_format(void *priv, int setmode, 360 const audio_params_t *play, const audio_params_t *rec, 361 audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 362 { 363 struct digfilt_softc *sc = priv; 364 365 if ((setmode & AUMODE_PLAY)) { 366 /* At this point bitrate should be figured out. */ 367 digfilt_ao_set_rate(sc, sc->sc_pparam.sample_rate); 368 } 369 370 return 0; 371 } 372 373 static int 374 digfilt_round_blocksize(void *priv, int bs, int mode, 375 const audio_params_t *param) 376 { 377 int blocksize; 378 379 if (bs > DIGFILT_BLOCKSIZE_MAX) 380 blocksize = DIGFILT_BLOCKSIZE_MAX; 381 else 382 blocksize = bs & ~(DIGFILT_BLOCKSIZE_ROUND-1); 383 384 return blocksize; 385 } 386 387 static int 388 digfilt_init_output(void *priv, void *buffer, int size) 389 { 390 struct digfilt_softc *sc = priv; 391 apbdma_command_t dma_cmd; 392 int i; 393 dma_cmd = sc->sc_dmachain; 394 sc->sc_cmd_index = 0; 395 396 /* 397 * Build circular DMA command chain template for later use. 398 */ 399 for (i = 0; i < DIGFILT_DMA_CHAIN_LENGTH; i++) { 400 /* Last entry loops back to first. */ 401 if (i == DIGFILT_DMA_CHAIN_LENGTH - 1) 402 dma_cmd[i].next = (void *)(sc->sc_c_dmamp->dm_segs[0].ds_addr); 403 else 404 dma_cmd[i].next = (void *)(sc->sc_c_dmamp->dm_segs[0].ds_addr + (sizeof(struct apbdma_command) * (1 + i))); 405 406 dma_cmd[i].control = __SHIFTIN(DIGFILT_BLOCKSIZE_MAX, APBDMA_CMD_XFER_COUNT) | 407 __SHIFTIN(1, APBDMA_CMD_CMDPIOWORDS) | 408 APBDMA_CMD_SEMAPHORE | 409 APBDMA_CMD_IRQONCMPLT | 410 APBDMA_CMD_CHAIN | 411 __SHIFTIN(APBDMA_CMD_DMA_READ, APBDMA_CMD_COMMAND); 412 413 dma_cmd[i].buffer = (void *)(sc->sc_c_dmamp->dm_segs[0].ds_addr); 414 415 dma_cmd[i].pio_words[0] = HW_AUDIOOUT_CTRL_WORD_LENGTH | 416 HW_AUDIOOUT_CTRL_FIFO_ERROR_IRQ_EN | 417 HW_AUDIOOUT_CTRL_RUN; 418 419 } 420 421 apbdma_chan_set_chain(sc->sc_dmac, DIGFILT_DMA_CHANNEL, sc->sc_c_dmamp); 422 423 return 0; 424 } 425 426 static int 427 digfilt_start_output(void *priv, void *start, int bs, void (*intr)(void*), void *intarg) 428 { 429 struct digfilt_softc *sc = priv; 430 apbdma_command_t dma_cmd; 431 bus_addr_t offset; 432 433 sc->sc_intr = intr; 434 sc->sc_intarg = intarg; 435 dma_cmd = sc->sc_dmachain; 436 437 offset = (bus_addr_t)start - (bus_addr_t)sc->sc_buffer; 438 439 dma_cmd[sc->sc_cmd_index].buffer = 440 (void *)((bus_addr_t)sc->sc_dmamp->dm_segs[0].ds_addr + offset); 441 442 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamp, offset, bs, BUS_DMASYNC_PREWRITE); 443 bus_dmamap_sync(sc->sc_dmat, sc->sc_c_dmamp, 444 sizeof(struct apbdma_command) * sc->sc_cmd_index, sizeof(struct apbdma_command), BUS_DMASYNC_PREWRITE); 445 446 sc->sc_cmd_index++; 447 if (sc->sc_cmd_index > DIGFILT_DMA_CHAIN_LENGTH - 1) 448 sc->sc_cmd_index = 0; 449 450 apbdma_run(sc->sc_dmac, DIGFILT_DMA_CHANNEL); 451 452 return 0; 453 } 454 455 static int 456 digfilt_halt_output(void *priv) 457 { 458 struct digfilt_softc *sc = priv; 459 460 sc->sc_cmd_index = 0; 461 return 0; 462 } 463 464 static int 465 digfilt_getdev(void *priv, struct audio_device *ad) 466 { 467 struct digfilt_softc *sc = priv; 468 469 strncpy(ad->name, device_xname(sc->sc_dev), MAX_AUDIO_DEV_LEN); 470 strncpy(ad->version, "", MAX_AUDIO_DEV_LEN); 471 strncpy(ad->config, "", MAX_AUDIO_DEV_LEN); 472 473 return 0; 474 } 475 476 static int 477 digfilt_set_port(void *priv, mixer_ctrl_t *mc) 478 { 479 struct digfilt_softc *sc = priv; 480 uint32_t val; 481 uint8_t nvol; 482 483 switch (mc->dev) { 484 case DIGFILT_OUTPUT_DAC_VOLUME: 485 val = AO_RD(sc, HW_AUDIOOUT_DACVOLUME); 486 val &= ~(HW_AUDIOOUT_DACVOLUME_VOLUME_LEFT | 487 HW_AUDIOOUT_DACVOLUME_VOLUME_RIGHT); 488 489 /* DAC volume field is 8 bits. */ 490 nvol = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 491 if (nvol > 0xff) 492 nvol = 0xff; 493 494 val |= __SHIFTIN(nvol, HW_AUDIOOUT_DACVOLUME_VOLUME_LEFT); 495 496 nvol = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 497 if (nvol > 0xff) 498 nvol = 0xff; 499 500 val |= __SHIFTIN(nvol, HW_AUDIOOUT_DACVOLUME_VOLUME_RIGHT); 501 502 AO_WR(sc, HW_AUDIOOUT_DACVOLUME, val); 503 504 return 0; 505 506 case DIGFILT_OUTPUT_HP_VOLUME: 507 val = AO_RD(sc, HW_AUDIOOUT_HPVOL); 508 val &= ~(HW_AUDIOOUT_HPVOL_VOL_LEFT | 509 HW_AUDIOOUT_HPVOL_VOL_RIGHT); 510 511 /* HP volume field is 7 bits. */ 512 nvol = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 513 if (nvol > 0x7f) 514 nvol = 0x7f; 515 516 nvol = ~nvol; 517 val |= __SHIFTIN(nvol, HW_AUDIOOUT_HPVOL_VOL_LEFT); 518 519 nvol = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 520 if (nvol > 0x7f) 521 nvol = 0x7f; 522 523 nvol = ~nvol; 524 val |= __SHIFTIN(nvol, HW_AUDIOOUT_HPVOL_VOL_RIGHT); 525 526 AO_WR(sc, HW_AUDIOOUT_HPVOL, val); 527 528 return 0; 529 530 case DIGFILT_OUTPUT_LINE_VOLUME: 531 return 1; 532 533 case DIGFILT_OUTPUT_DAC_MUTE: 534 if (mc->un.ord) 535 sc->sc_mute |= DIGFILT_MUTE_DAC; 536 else 537 sc->sc_mute &= ~DIGFILT_MUTE_DAC; 538 539 digfilt_ao_apply_mutes(sc); 540 541 return 0; 542 543 case DIGFILT_OUTPUT_HP_MUTE: 544 if (mc->un.ord) 545 sc->sc_mute |= DIGFILT_MUTE_HP; 546 else 547 sc->sc_mute &= ~DIGFILT_MUTE_HP; 548 549 digfilt_ao_apply_mutes(sc); 550 551 return 0; 552 553 case DIGFILT_OUTPUT_LINE_MUTE: 554 if (mc->un.ord) 555 sc->sc_mute |= DIGFILT_MUTE_LINE; 556 else 557 sc->sc_mute &= ~DIGFILT_MUTE_LINE; 558 559 digfilt_ao_apply_mutes(sc); 560 561 return 0; 562 } 563 564 return ENXIO; 565 } 566 567 static int 568 digfilt_get_port(void *priv, mixer_ctrl_t *mc) 569 { 570 struct digfilt_softc *sc = priv; 571 uint32_t val; 572 uint8_t nvol; 573 574 switch (mc->dev) { 575 case DIGFILT_OUTPUT_DAC_VOLUME: 576 val = AO_RD(sc, HW_AUDIOOUT_DACVOLUME); 577 578 nvol = __SHIFTOUT(val, HW_AUDIOOUT_DACVOLUME_VOLUME_LEFT); 579 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = nvol; 580 581 nvol = __SHIFTOUT(val, HW_AUDIOOUT_DACVOLUME_VOLUME_RIGHT); 582 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = nvol; 583 584 return 0; 585 586 case DIGFILT_OUTPUT_HP_VOLUME: 587 val = AO_RD(sc, HW_AUDIOOUT_HPVOL); 588 589 nvol = __SHIFTOUT(val, HW_AUDIOOUT_HPVOL_VOL_LEFT); 590 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = ~nvol & 0x7f; 591 592 nvol = __SHIFTOUT(val, HW_AUDIOOUT_HPVOL_VOL_RIGHT); 593 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = ~nvol & 0x7f; 594 595 return 0; 596 597 case DIGFILT_OUTPUT_LINE_VOLUME: 598 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 255; 599 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 255; 600 601 return 0; 602 603 case DIGFILT_OUTPUT_DAC_MUTE: 604 val = AO_RD(sc, HW_AUDIOOUT_DACVOLUME); 605 606 mc->un.ord = (val & (HW_AUDIOOUT_DACVOLUME_MUTE_LEFT | 607 HW_AUDIOOUT_DACVOLUME_MUTE_RIGHT)) ? 1 : 0; 608 609 return 0; 610 611 case DIGFILT_OUTPUT_HP_MUTE: 612 val = AO_RD(sc, HW_AUDIOOUT_HPVOL); 613 614 mc->un.ord = (val & HW_AUDIOOUT_HPVOL_MUTE) ? 1 : 0; 615 616 return 0; 617 618 case DIGFILT_OUTPUT_LINE_MUTE: 619 val = AO_RD(sc, HW_AUDIOOUT_SPEAKERCTRL); 620 621 mc->un.ord = (val & HW_AUDIOOUT_SPEAKERCTRL_MUTE) ? 1 : 0; 622 623 return 0; 624 } 625 626 return ENXIO; 627 } 628 629 static int 630 digfilt_query_devinfo(void *priv, mixer_devinfo_t *di) 631 { 632 633 switch (di->index) { 634 case DIGFILT_OUTPUT_CLASS: 635 di->mixer_class = DIGFILT_OUTPUT_CLASS; 636 strcpy(di->label.name, AudioCoutputs); 637 di->type = AUDIO_MIXER_CLASS; 638 di->next = di->prev = AUDIO_MIXER_LAST; 639 return 0; 640 641 case DIGFILT_OUTPUT_DAC_VOLUME: 642 di->mixer_class = DIGFILT_OUTPUT_CLASS; 643 strcpy(di->label.name, AudioNdac); 644 di->type = AUDIO_MIXER_VALUE; 645 di->prev = AUDIO_MIXER_LAST; 646 di->next = DIGFILT_OUTPUT_DAC_MUTE; 647 di->un.v.num_channels = 2; 648 strcpy(di->un.v.units.name, AudioNvolume); 649 return 0; 650 651 case DIGFILT_OUTPUT_DAC_MUTE: 652 di->mixer_class = DIGFILT_OUTPUT_CLASS; 653 di->type = AUDIO_MIXER_ENUM; 654 di->prev = DIGFILT_OUTPUT_DAC_VOLUME; 655 di->next = AUDIO_MIXER_LAST; 656 mute: 657 strlcpy(di->label.name, AudioNmute, sizeof(di->label.name)); 658 di->un.e.num_mem = 2; 659 strlcpy(di->un.e.member[0].label.name, AudioNon, 660 sizeof(di->un.e.member[0].label.name)); 661 di->un.e.member[0].ord = 1; 662 strlcpy(di->un.e.member[1].label.name, AudioNoff, 663 sizeof(di->un.e.member[1].label.name)); 664 di->un.e.member[1].ord = 0; 665 return 0; 666 667 case DIGFILT_OUTPUT_HP_VOLUME: 668 di->mixer_class = DIGFILT_OUTPUT_CLASS; 669 strcpy(di->label.name, AudioNheadphone); 670 di->type = AUDIO_MIXER_VALUE; 671 di->prev = AUDIO_MIXER_LAST; 672 di->next = DIGFILT_OUTPUT_HP_MUTE; 673 di->un.v.num_channels = 2; 674 strcpy(di->un.v.units.name, AudioNvolume); 675 return 0; 676 677 case DIGFILT_OUTPUT_HP_MUTE: 678 di->mixer_class = DIGFILT_OUTPUT_CLASS; 679 di->type = AUDIO_MIXER_ENUM; 680 di->prev = DIGFILT_OUTPUT_HP_VOLUME; 681 di->next = AUDIO_MIXER_LAST; 682 goto mute; 683 684 case DIGFILT_OUTPUT_LINE_VOLUME: 685 di->mixer_class = DIGFILT_OUTPUT_CLASS; 686 strcpy(di->label.name, AudioNline); 687 di->type = AUDIO_MIXER_VALUE; 688 di->prev = AUDIO_MIXER_LAST; 689 di->next = DIGFILT_OUTPUT_LINE_MUTE; 690 di->un.v.num_channels = 2; 691 strcpy(di->un.v.units.name, AudioNvolume); 692 return 0; 693 694 case DIGFILT_OUTPUT_LINE_MUTE: 695 di->mixer_class = DIGFILT_OUTPUT_CLASS; 696 di->type = AUDIO_MIXER_ENUM; 697 di->prev = DIGFILT_OUTPUT_LINE_VOLUME; 698 di->next = AUDIO_MIXER_LAST; 699 goto mute; 700 } 701 702 return ENXIO; 703 } 704 705 static void * 706 digfilt_allocm(void *priv, int direction, size_t size) 707 { 708 struct digfilt_softc *sc = priv; 709 int rsegs; 710 int error; 711 712 sc->sc_buffer = NULL; 713 714 /* 715 * AUMODE_PLAY is DMA from memory to device. 716 */ 717 if (direction != AUMODE_PLAY) 718 return NULL; 719 720 error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &sc->sc_ds[0], DIGFILT_DMA_NSEGS, &rsegs, BUS_DMA_NOWAIT); 721 if (error) { 722 aprint_error_dev(sc->sc_dev, 723 "bus_dmamem_alloc: %d\n", error); 724 goto out; 725 } 726 727 error = bus_dmamem_map(sc->sc_dmat, sc->sc_ds, DIGFILT_DMA_NSEGS, size, &sc->sc_buffer, BUS_DMA_NOWAIT); 728 if (error) { 729 aprint_error_dev(sc->sc_dev, "bus_dmamem_map: %d\n", error); 730 goto dmamem_free; 731 } 732 733 /* After load sc_dmamp is valid. */ 734 error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamp, sc->sc_buffer, size, NULL, BUS_DMA_NOWAIT|BUS_DMA_WRITE); 735 if (error) { 736 aprint_error_dev(sc->sc_dev, "bus_dmamap_load: %d\n", error); 737 goto dmamem_unmap; 738 } 739 740 memset(sc->sc_buffer, 0x00, size); 741 742 return sc->sc_buffer; 743 744 dmamem_unmap: 745 bus_dmamem_unmap(sc->sc_dmat, sc->sc_buffer, size); 746 dmamem_free: 747 bus_dmamem_free(sc->sc_dmat, sc->sc_ds, DIGFILT_DMA_NSEGS); 748 out: 749 return NULL; 750 } 751 752 static void 753 digfilt_freem(void *priv, void *kvap, size_t size) 754 { 755 struct digfilt_softc *sc = priv; 756 757 bus_dmamem_unmap(sc->sc_dmat, kvap, size); 758 bus_dmamem_free(sc->sc_dmat, sc->sc_ds, DIGFILT_DMA_NSEGS); 759 760 return; 761 } 762 763 static size_t 764 digfilt_round_buffersize(void *hdl, int direction, size_t bs) 765 { 766 int bufsize; 767 768 bufsize = bs & ~(DIGFILT_BLOCKSIZE_MAX-1); 769 770 return bufsize; 771 } 772 773 static int 774 digfilt_get_props(void *sc) 775 { 776 return (AUDIO_PROP_PLAYBACK | AUDIO_PROP_INDEPENDENT); 777 } 778 779 static void 780 digfilt_get_locks(void *priv, kmutex_t **intr, kmutex_t **thread) 781 { 782 struct digfilt_softc *sc = priv; 783 784 *intr = &sc->sc_intr_lock; 785 *thread = &sc->sc_lock; 786 787 return; 788 } 789 790 /* 791 * IRQ for DAC error. 792 */ 793 static int 794 dac_error_intr(void *arg) 795 { 796 struct digfilt_softc *sc = arg; 797 AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ); 798 return 1; 799 } 800 801 /* 802 * IRQ from DMA. 803 */ 804 static int 805 dac_dma_intr(void *arg) 806 { 807 struct digfilt_softc *sc = arg; 808 809 unsigned int dma_err; 810 811 mutex_enter(&sc->sc_intr_lock); 812 813 dma_err = apbdma_intr_status(sc->sc_dmac, DIGFILT_DMA_CHANNEL); 814 815 if (dma_err) { 816 apbdma_ack_error_intr(sc->sc_dmac, DIGFILT_DMA_CHANNEL); 817 } 818 819 sc->sc_intr(sc->sc_intarg); 820 apbdma_ack_intr(sc->sc_dmac, DIGFILT_DMA_CHANNEL); 821 822 mutex_exit(&sc->sc_intr_lock); 823 824 /* Return 1 to acknowledge IRQ. */ 825 return 1; 826 } 827 828 static void * 829 digfilt_ao_alloc_dmachain(void *priv, size_t size) 830 { 831 struct digfilt_softc *sc = priv; 832 int rsegs; 833 int error; 834 void *kvap; 835 836 kvap = NULL; 837 838 error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &sc->sc_c_ds[0], DIGFILT_DMA_NSEGS, &rsegs, BUS_DMA_NOWAIT); 839 if (error) { 840 aprint_error_dev(sc->sc_dev, 841 "bus_dmamem_alloc: %d\n", error); 842 goto out; 843 } 844 845 error = bus_dmamem_map(sc->sc_dmat, sc->sc_c_ds, DIGFILT_DMA_NSEGS, size, &kvap, BUS_DMA_NOWAIT); 846 if (error) { 847 aprint_error_dev(sc->sc_dev, "bus_dmamem_map: %d\n", error); 848 goto dmamem_free; 849 } 850 851 /* After load sc_c_dmamp is valid. */ 852 error = bus_dmamap_load(sc->sc_dmat, sc->sc_c_dmamp, kvap, size, NULL, BUS_DMA_NOWAIT|BUS_DMA_WRITE); 853 if (error) { 854 aprint_error_dev(sc->sc_dev, "bus_dmamap_load: %d\n", error); 855 goto dmamem_unmap; 856 } 857 858 memset(kvap, 0x00, size); 859 860 return kvap; 861 862 dmamem_unmap: 863 bus_dmamem_unmap(sc->sc_dmat, kvap, size); 864 dmamem_free: 865 bus_dmamem_free(sc->sc_dmat, sc->sc_c_ds, DIGFILT_DMA_NSEGS); 866 out: 867 868 return kvap; 869 } 870 871 static void 872 digfilt_ao_apply_mutes(struct digfilt_softc *sc) 873 { 874 875 /* DAC. */ 876 if (sc->sc_mute & DIGFILT_MUTE_DAC) { 877 AO_WR(sc, HW_AUDIOOUT_DACVOLUME_SET, 878 HW_AUDIOOUT_DACVOLUME_MUTE_LEFT | 879 HW_AUDIOOUT_DACVOLUME_MUTE_RIGHT 880 ); 881 882 } else { 883 AO_WR(sc, HW_AUDIOOUT_DACVOLUME_CLR, 884 HW_AUDIOOUT_DACVOLUME_MUTE_LEFT | 885 HW_AUDIOOUT_DACVOLUME_MUTE_RIGHT 886 ); 887 } 888 889 /* HP. */ 890 if (sc->sc_mute & DIGFILT_MUTE_HP) 891 AO_WR(sc, HW_AUDIOOUT_HPVOL_SET, HW_AUDIOOUT_HPVOL_MUTE); 892 else 893 AO_WR(sc, HW_AUDIOOUT_HPVOL_CLR, HW_AUDIOOUT_HPVOL_MUTE); 894 895 /* Line. */ 896 if (sc->sc_mute & DIGFILT_MUTE_LINE) 897 AO_WR(sc, HW_AUDIOOUT_SPEAKERCTRL_SET, 898 HW_AUDIOOUT_SPEAKERCTRL_MUTE); 899 else 900 AO_WR(sc, HW_AUDIOOUT_SPEAKERCTRL_CLR, 901 HW_AUDIOOUT_SPEAKERCTRL_MUTE); 902 903 return; 904 } 905 906 /* 907 * Initialize audio system. 908 */ 909 static void 910 digfilt_ao_init(struct digfilt_softc *sc) 911 { 912 913 AO_WR(sc, HW_AUDIOOUT_ANACLKCTRL_CLR, HW_AUDIOOUT_ANACLKCTRL_CLKGATE); 914 while ((AO_RD(sc, HW_AUDIOOUT_ANACLKCTRL) & 915 HW_AUDIOOUT_ANACLKCTRL_CLKGATE)); 916 917 /* Hold headphones outputs at ground. */ 918 AO_WR(sc, HW_AUDIOOUT_ANACTRL_SET, HW_AUDIOOUT_ANACTRL_HP_HOLD_GND); 919 920 /* Remove pulldown resistors on headphone outputs. */ 921 rtc_release_gnd(1); 922 923 /* Release pull down */ 924 AO_WR(sc, HW_AUDIOOUT_ANACTRL_CLR, HW_AUDIOOUT_ANACTRL_HP_HOLD_GND); 925 926 AO_WR(sc, HW_AUDIOOUT_ANACTRL_SET, HW_AUDIOOUT_ANACTRL_HP_CLASSAB); 927 928 /* Enable Modules. */ 929 AO_WR(sc, HW_AUDIOOUT_PWRDN_CLR, 930 HW_AUDIOOUT_PWRDN_RIGHT_ADC | 931 HW_AUDIOOUT_PWRDN_DAC | 932 HW_AUDIOOUT_PWRDN_CAPLESS | 933 HW_AUDIOOUT_PWRDN_HEADPHONE 934 ); 935 936 return; 937 } 938 939 /* 940 * Reset the AUDIOOUT block. 941 * 942 * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block" 943 */ 944 static void 945 digfilt_ao_reset(struct digfilt_softc *sc) 946 { 947 unsigned int loop; 948 949 /* Prepare for soft-reset by making sure that SFTRST is not currently 950 * asserted. Also clear CLKGATE so we can wait for its assertion below. 951 */ 952 AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_SFTRST); 953 954 /* Wait at least a microsecond for SFTRST to deassert. */ 955 loop = 0; 956 while ((AO_RD(sc, HW_AUDIOOUT_CTRL) & HW_AUDIOOUT_CTRL_SFTRST) || 957 (loop < DIGFILT_SOFT_RST_LOOP)) 958 loop++; 959 960 /* Clear CLKGATE so we can wait for its assertion below. */ 961 AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_CLKGATE); 962 963 /* Soft-reset the block. */ 964 AO_WR(sc, HW_AUDIOOUT_CTRL_SET, HW_AUDIOOUT_CTRL_SFTRST); 965 966 /* Wait until clock is in the gated state. */ 967 while (!(AO_RD(sc, HW_AUDIOOUT_CTRL) & HW_AUDIOOUT_CTRL_CLKGATE)); 968 969 /* Bring block out of reset. */ 970 AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_SFTRST); 971 972 loop = 0; 973 while ((AO_RD(sc, HW_AUDIOOUT_CTRL) & HW_AUDIOOUT_CTRL_SFTRST) || 974 (loop < DIGFILT_SOFT_RST_LOOP)) 975 loop++; 976 977 AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_CLKGATE); 978 979 /* Wait until clock is in the NON-gated state. */ 980 while (AO_RD(sc, HW_AUDIOOUT_CTRL) & HW_AUDIOOUT_CTRL_CLKGATE); 981 982 return; 983 } 984 985 static void 986 digfilt_ao_set_rate(struct digfilt_softc *sc, int sr) 987 { 988 uint32_t val; 989 990 991 val = AO_RD(sc, HW_AUDIOOUT_DACSRR); 992 993 994 val &= ~(HW_AUDIOOUT_DACSRR_BASEMULT | HW_AUDIOOUT_DACSRR_SRC_HOLD | 995 HW_AUDIOOUT_DACSRR_SRC_INT | HW_AUDIOOUT_DACSRR_SRC_FRAC); 996 997 switch(sr) { 998 case 8000: 999 val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) | 1000 __SHIFTIN(0x3, HW_AUDIOOUT_DACSRR_SRC_HOLD) | 1001 __SHIFTIN(0x17, HW_AUDIOOUT_DACSRR_SRC_INT) | 1002 __SHIFTIN(0x0E00, HW_AUDIOOUT_DACSRR_SRC_FRAC)); 1003 break; 1004 case 11025: 1005 val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) | 1006 __SHIFTIN(0x3, HW_AUDIOOUT_DACSRR_SRC_HOLD) | 1007 __SHIFTIN(0x11, HW_AUDIOOUT_DACSRR_SRC_INT) | 1008 __SHIFTIN(0x0037, HW_AUDIOOUT_DACSRR_SRC_FRAC)); 1009 break; 1010 case 12000: 1011 val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) | 1012 __SHIFTIN(0x3, HW_AUDIOOUT_DACSRR_SRC_HOLD) | 1013 __SHIFTIN(0x0F, HW_AUDIOOUT_DACSRR_SRC_INT) | 1014 __SHIFTIN(0x13FF, HW_AUDIOOUT_DACSRR_SRC_FRAC)); 1015 break; 1016 case 16000: 1017 val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) | 1018 __SHIFTIN(0x1, HW_AUDIOOUT_DACSRR_SRC_HOLD) | 1019 __SHIFTIN(0x17, HW_AUDIOOUT_DACSRR_SRC_INT) | 1020 __SHIFTIN(0x0E00, HW_AUDIOOUT_DACSRR_SRC_FRAC)); 1021 break; 1022 case 22050: 1023 val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) | 1024 __SHIFTIN(0x1, HW_AUDIOOUT_DACSRR_SRC_HOLD) | 1025 __SHIFTIN(0x11, HW_AUDIOOUT_DACSRR_SRC_INT) | 1026 __SHIFTIN(0x0037, HW_AUDIOOUT_DACSRR_SRC_FRAC)); 1027 break; 1028 case 24000: 1029 val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) | 1030 __SHIFTIN(0x1, HW_AUDIOOUT_DACSRR_SRC_HOLD) | 1031 __SHIFTIN(0x0F, HW_AUDIOOUT_DACSRR_SRC_INT) | 1032 __SHIFTIN(0x13FF, HW_AUDIOOUT_DACSRR_SRC_FRAC)); 1033 break; 1034 case 32000: 1035 val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) | 1036 __SHIFTIN(0x0, HW_AUDIOOUT_DACSRR_SRC_HOLD) | 1037 __SHIFTIN(0x17, HW_AUDIOOUT_DACSRR_SRC_INT) | 1038 __SHIFTIN(0x0E00, HW_AUDIOOUT_DACSRR_SRC_FRAC)); 1039 break; 1040 default: 1041 aprint_error_dev(sc->sc_dev, "uknown sample rate: %d\n", sr); 1042 case 44100: 1043 val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) | 1044 __SHIFTIN(0x0, HW_AUDIOOUT_DACSRR_SRC_HOLD) | 1045 __SHIFTIN(0x11, HW_AUDIOOUT_DACSRR_SRC_INT) | 1046 __SHIFTIN(0x0037, HW_AUDIOOUT_DACSRR_SRC_FRAC)); 1047 break; 1048 } 1049 1050 AO_WR(sc, HW_AUDIOOUT_DACSRR, val); 1051 1052 val = AO_RD(sc, HW_AUDIOOUT_DACSRR); 1053 1054 return; 1055 } 1056 #if 0 1057 /* 1058 * Reset the AUDIOIN block. 1059 * 1060 * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block" 1061 */ 1062 static void 1063 digfilt_ai_reset(struct digfilt_softc *sc) 1064 { 1065 unsigned int loop; 1066 1067 /* Prepare for soft-reset by making sure that SFTRST is not currently 1068 * asserted. Also clear CLKGATE so we can wait for its assertion below. 1069 */ 1070 AI_WR(sc, HW_AUDIOIN_CTRL_CLR, HW_AUDIOIN_CTRL_SFTRST); 1071 1072 /* Wait at least a microsecond for SFTRST to deassert. */ 1073 loop = 0; 1074 while ((AI_RD(sc, HW_AUDIOIN_CTRL) & HW_AUDIOIN_CTRL_SFTRST) || 1075 (loop < DIGFILT_SOFT_RST_LOOP)) 1076 loop++; 1077 1078 /* Clear CLKGATE so we can wait for its assertion below. */ 1079 AI_WR(sc, HW_AUDIOIN_CTRL_CLR, HW_AUDIOIN_CTRL_CLKGATE); 1080 1081 /* Soft-reset the block. */ 1082 AI_WR(sc, HW_AUDIOIN_CTRL_SET, HW_AUDIOIN_CTRL_SFTRST); 1083 1084 /* Wait until clock is in the gated state. */ 1085 while (!(AI_RD(sc, HW_AUDIOIN_CTRL) & HW_AUDIOIN_CTRL_CLKGATE)); 1086 1087 /* Bring block out of reset. */ 1088 AI_WR(sc, HW_AUDIOIN_CTRL_CLR, HW_AUDIOIN_CTRL_SFTRST); 1089 1090 loop = 0; 1091 while ((AI_RD(sc, HW_AUDIOIN_CTRL) & HW_AUDIOIN_CTRL_SFTRST) || 1092 (loop < DIGFILT_SOFT_RST_LOOP)) 1093 loop++; 1094 1095 AI_WR(sc, HW_AUDIOIN_CTRL_CLR, HW_AUDIOIN_CTRL_CLKGATE); 1096 1097 /* Wait until clock is in the NON-gated state. */ 1098 while (AI_RD(sc, HW_AUDIOIN_CTRL) & HW_AUDIOIN_CTRL_CLKGATE); 1099 1100 return; 1101 } 1102 #endif 1103