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