1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Platform specifc code for the APC DMA controller. The APC is an SBus 28 * IC that includes play and record DMA engines and an interface for 29 * the CS4231. 30 */ 31 32 #include <sys/systm.h> 33 #include <sys/ddi.h> 34 #include <sys/sunddi.h> 35 #include <sys/note.h> 36 #include <sys/audio/audio_driver.h> 37 #include "audio_4231.h" 38 39 /* 40 * Attribute structure for the APC, used to create DMA handles. 41 */ 42 static ddi_dma_attr_t apc_dma_attr = { 43 DMA_ATTR_V0, /* version */ 44 0x0000000000000000LL, /* dlim_addr_lo */ 45 0x00000000ffffffffLL, /* dlim_addr_hi */ 46 0x0000000000000fffLL, /* DMA counter register */ 47 0x0000000000000001LL, /* DMA address alignment */ 48 0x00000014, /* 4 and 16 byte burst sizes */ 49 0x00000001, /* min effective DMA size */ 50 0x0000000000000fffLL, /* maximum transfer size, 8k */ 51 0x000000000000ffffLL, /* segment boundary, 32k */ 52 0x00000001, /* s/g list length, no s/g */ 53 0x00000001, /* granularity of device, don't care */ 54 0 /* DMA flags */ 55 }; 56 57 static ddi_device_acc_attr_t acc_attr = { 58 DDI_DEVICE_ATTR_V0, 59 DDI_STRUCTURE_BE_ACC, 60 DDI_STRICTORDER_ACC 61 }; 62 63 /* 64 * Local routines 65 */ 66 static uint_t apc_intr(caddr_t); 67 static void apc_load_fragment(CS_engine_t *); 68 69 /* 70 * DMA ops vector functions 71 */ 72 static int apc_map_regs(CS_state_t *); 73 static void apc_unmap_regs(CS_state_t *); 74 static void apc_reset(CS_state_t *); 75 static int apc_add_intr(CS_state_t *); 76 static void apc_rem_intr(CS_state_t *); 77 static int apc_start_engine(CS_engine_t *); 78 static void apc_stop_engine(CS_engine_t *); 79 static void apc_power(CS_state_t *, int); 80 81 cs4231_dma_ops_t cs4231_apcdma_ops = { 82 "APC DMA controller", 83 &apc_dma_attr, 84 apc_map_regs, 85 apc_unmap_regs, 86 apc_reset, 87 apc_add_intr, 88 apc_rem_intr, 89 apc_start_engine, 90 apc_stop_engine, 91 apc_power, 92 }; 93 94 /* 95 * apc_map_regs() 96 * 97 * Description: 98 * This routine allocates the DMA handles and the memory for the 99 * DMA engines to use. It then binds each of the buffers to its 100 * respective handle, getting a DMA cookie. Finally, the registers 101 * are mapped in. 102 * 103 * NOTE: All of the ddi_dma_... routines sleep if they cannot get 104 * memory. This means these calls will almost always succeed. 105 * 106 * Arguments: 107 * CS_state_t *state The device's state structure 108 * 109 * Returns: 110 * AUDIO_SUCCESS Registers successfully mapped 111 * AUDIO_FAILURE Registers not successfully mapped 112 */ 113 static int 114 apc_map_regs(CS_state_t *state) 115 { 116 ddi_acc_handle_t *handle = &APC_HANDLE; 117 dev_info_t *dip = state->cs_dip; 118 119 /* map in the registers, getting a handle */ 120 if (ddi_regs_map_setup(dip, 0, (caddr_t *)&state->cs_regs, 0, 121 sizeof (cs4231_regs_t), &acc_attr, handle) != DDI_SUCCESS) { 122 audio_dev_warn(state->cs_adev, "ddi_regs_map_setup() failed"); 123 return (DDI_FAILURE); 124 } 125 126 /* clear the CSR so we have all interrupts disabled */ 127 ddi_put32(*handle, &APC_DMACSR, APC_CLEAR_RESET_VALUE); 128 129 return (DDI_SUCCESS); 130 } /* apc_map_regs() */ 131 132 /* 133 * apc_unmap_regs() 134 * 135 * Description: 136 * This routine unmaps the Codec's and DMA engine's registers. 137 * It must be idempotent. 138 * 139 * Arguments: 140 * CS_state_t *state The device's state structure 141 * 142 * Returns: 143 * void 144 */ 145 static void 146 apc_unmap_regs(CS_state_t *state) 147 { 148 if (APC_HANDLE) 149 ddi_regs_map_free(&APC_HANDLE); 150 151 } /* apc_unmap_regs() */ 152 153 /* 154 * apc_reset() 155 * 156 * Description: 157 * Reset both the play and record DMA engines. The engines are left 158 * with interrupts and the DMA engine disabled. 159 * 160 * Arguments: 161 * dev_info_t *dip Pointer to the device's devinfo structure 162 * CS_state_t *state The device's state structure 163 * 164 * Returns: 165 * void 166 */ 167 static void 168 apc_reset(CS_state_t *state) 169 { 170 ddi_acc_handle_t handle = APC_HANDLE; 171 172 /* 173 * The APC has a bug where the reset is not done 174 * until you do the next pio to the APC. This 175 * next write to the CSR causes the posted reset to 176 * happen. 177 */ 178 179 ddi_put32(handle, &APC_DMACSR, APC_RESET); 180 ddi_put32(handle, &APC_DMACSR, APC_CLEAR_RESET_VALUE); 181 182 } /* apc_reset() */ 183 184 /* 185 * apc_add_intr() 186 * 187 * Description: 188 * Register the APC interrupts with the kernel. 189 * 190 * NOTE: This does NOT turn on interrupts. 191 * 192 * CAUTION: While the interrupts are added, the Codec interrupts are 193 * not enabled. 194 * 195 * Arguments: 196 * CS_state_t *state Pointer to the device's state structure 197 * 198 * Returns: 199 * DDI_SUCCESS Registers successfully mapped 200 * DDI_FAILURE Registers not successfully mapped 201 */ 202 static int 203 apc_add_intr(CS_state_t *state) 204 { 205 dev_info_t *dip = state->cs_dip; 206 207 /* first we make sure this isn't a high level interrupt */ 208 if (ddi_intr_hilevel(dip, 0) != 0) { 209 audio_dev_warn(state->cs_adev, 210 "unsupported high level interrupt"); 211 return (DDI_FAILURE); 212 } 213 214 /* okay to register the interrupt */ 215 if (ddi_add_intr(dip, 0, NULL, NULL, apc_intr, (caddr_t)state) != 216 DDI_SUCCESS) { 217 audio_dev_warn(state->cs_adev, "bad interrupt specification"); 218 return (DDI_FAILURE); 219 } 220 221 return (DDI_SUCCESS); 222 223 } /* apc_add_intr() */ 224 225 /* 226 * apc_rem_intr() 227 * 228 * Description: 229 * Unregister the APC interrupts from the kernel. 230 * 231 * CAUTION: While the interrupts are removed, the Codec interrupts are 232 * not disabled, but then, they never should have been on in 233 * the first place. 234 * 235 * Arguments: 236 * CS_state_t *state Pointer to the device's state structure 237 * 238 * Returns: 239 * void 240 */ 241 static void 242 apc_rem_intr(CS_state_t *state) 243 { 244 ddi_remove_intr(state->cs_dip, 0, NULL); 245 } /* apc_rem_intr() */ 246 247 /* 248 * apc_start_engine() 249 * 250 * Description: 251 * This routine starts the DMA engine. 252 * 253 * For hard starts the DMA engine is started by programming the 254 * Next Virtual Address and then the Next Counter twice, and 255 * finally enabling the DMA engine. 256 * 257 * NOTE: The state structure must be locked before this routine is called. 258 * 259 * CAUTION: ?!? This routine doesn't start the Codec because the first 260 * interrupt causes a recursive mutex_enter. 261 * 262 * Arguments: 263 * CS_engine_t *eng The engine to start 264 * 265 * Returns: 266 * DDI_SUCCESS The DMA engine was started 267 * DDI_FAILURE The DMA engine was not started 268 */ 269 static int 270 apc_start_engine(CS_engine_t *eng) 271 { 272 CS_state_t *state = eng->ce_state; 273 ddi_acc_handle_t handle = APC_HANDLE; 274 uint32_t csr; 275 uint32_t enable; 276 uint32_t dirty; 277 int x; 278 279 ASSERT(mutex_owned(&state->cs_lock)); 280 281 if (eng->ce_num == CS4231_PLAY) { 282 enable = APC_PLAY_ENABLE; 283 dirty = APC_PD; 284 } else { 285 enable = APC_CAP_ENABLE; 286 dirty = APC_CD; 287 } 288 289 /* make sure it's okay to program the Next Address/Count registers */ 290 csr = ddi_get32(handle, &APC_DMACSR); 291 for (x = 0; !(csr & dirty) && x < CS4231_TIMEOUT; x++) { 292 drv_usecwait(1); /* no reason to beat on the bus */ 293 csr = ddi_get32(handle, &APC_DMACSR); 294 } 295 if (x >= CS4231_TIMEOUT) { 296 audio_dev_warn(state->cs_adev, 297 "timeout waiting for engine, not started!"); 298 return (DDI_FAILURE); 299 } 300 301 /* 302 * Program the first fragment. 303 */ 304 apc_load_fragment(eng); 305 306 /* 307 * Start the DMA engine, including interrupts. 308 */ 309 OR_SET_WORD(handle, &APC_DMACSR, enable); 310 311 /* 312 * Program the second fragment. 313 */ 314 apc_load_fragment(eng); 315 316 return (DDI_SUCCESS); 317 } 318 319 /* 320 * apc_stop_engine() 321 * 322 * Description: 323 * This routine stops the engine. 324 * 325 * The DMA engine is stopped by using the CAP_ABORT bit. 326 * 327 * NOTE: The state structure must be locked before this routine is called. 328 * 329 * Arguments: 330 * CS_engine_t *eng The engine to sotp 331 * 332 * Returns: 333 * void 334 */ 335 static void 336 apc_stop_engine(CS_engine_t *eng) 337 { 338 CS_state_t *state = eng->ce_state; 339 ddi_acc_handle_t handle = APC_HANDLE; 340 uint32_t reg; 341 uint32_t intren; 342 uint32_t abort; 343 uint32_t drainbit; 344 uint32_t disable; 345 346 ASSERT(mutex_owned(&state->cs_lock)); 347 348 if (eng->ce_num == CS4231_PLAY) { 349 intren = APC_PINTR_ENABLE; 350 abort = APC_P_ABORT; 351 drainbit = APC_PM; 352 disable = APC_PLAY_DISABLE; 353 } else { 354 intren = APC_CINTR_ENABLE; 355 abort = APC_C_ABORT; 356 drainbit = APC_CX; 357 disable = APC_CAP_DISABLE; 358 } 359 360 /* clear the interrupts so the ISR doesn't get involved */ 361 AND_SET_WORD(handle, &APC_DMACSR, ~intren); 362 363 /* first, abort the DMA engine */ 364 OR_SET_WORD(handle, &APC_DMACSR, abort); 365 366 /* wait for the pipeline to empty */ 367 reg = ddi_get32(handle, &APC_DMACSR); 368 for (int x = 0; (!(reg & drainbit)) && (x < CS4231_TIMEOUT); x++) { 369 drv_usecwait(1); /* don't beat on bus */ 370 reg = ddi_get32(handle, &APC_DMACSR); 371 } 372 373 /* now clear the enable and abort bits */ 374 AND_SET_WORD(handle, &APC_DMACSR, ~(abort|disable)); 375 } 376 377 378 /* 379 * apc_power() 380 * 381 * Description: 382 * This routine turns the Codec off by using the COD_PDWN bit in the 383 * apc chip. To turn power on we have to reset the APC, which clears 384 * the COD_PDWN bit. However, this is a settling bug in the APC which 385 * requires the driver to delay quite a while before we may continue. 386 * Since this is the first time this feature has actually been used 387 * it isn't too surprising that it has some problems. 388 * 389 * NOTE: The state structure must be locked when this routine is called. 390 * 391 * Arguments: 392 * CS_state_t *state Ptr to the device's state structure 393 * int level Power level to set 394 * 395 * Returns: 396 * void 397 */ 398 static void 399 apc_power(CS_state_t *state, int level) 400 { 401 ddi_acc_handle_t handle = APC_HANDLE; 402 403 if (level == CS4231_PWR_ON) { /* turn power on */ 404 AND_SET_WORD(handle, &APC_DMACSR, ~APC_COD_PDWN); 405 OR_SET_WORD(handle, &APC_DMACSR, APC_RESET); 406 AND_SET_WORD(handle, &APC_DMACSR, ~APC_RESET); 407 408 /* 409 * wait for state change, 410 */ 411 delay(drv_usectohz(CS4231_300MS)); 412 } else { /* turn power off */ 413 ASSERT(level == CS4231_PWR_OFF); 414 OR_SET_WORD(handle, &APC_DMACSR, APC_COD_PDWN); 415 } 416 417 } /* apc_power() */ 418 419 420 /* ******* Local Routines ************************************************** */ 421 422 /* 423 * apc_intr() 424 * 425 * Description: 426 * APC interrupt service routine, which services both play and capture 427 * interrupts. First we find out why there was an interrupt, then we 428 * take the appropriate action. 429 * 430 * Because this ISR deals with both play and record interrupts we have 431 * to be careful to not lose an interrupt. So we service the record 432 * interrupt first and save the incoming data until later. This is all 433 * done without releasing the lock, thus there can be no race conditions. 434 * Then we process the play interrupt. While processing the play interrupt 435 * we have to release the lock. When this happens we send recorded data 436 * to the mixer and then get the next chunk of data to play. If there 437 * wasn't a play interrupt then we finish by sending the recorded data, 438 * if any. 439 * 440 * Arguments: 441 * caddr_t T Pointer to the interrupting device's state 442 * structure 443 * 444 * Returns: 445 * DDI_INTR_CLAIMED Interrupt claimed and processed 446 * DDI_INTR_UNCLAIMED Interrupt not claimed, and thus ignored 447 */ 448 static uint_t 449 apc_intr(caddr_t T) 450 { 451 CS_state_t *state = (void *)T; 452 ddi_acc_handle_t handle = APC_HANDLE; 453 uint_t csr; 454 int rc = DDI_INTR_UNCLAIMED; 455 456 /* the state must be protected */ 457 mutex_enter(&state->cs_lock); 458 459 if (state->cs_suspended) { 460 mutex_exit(&state->cs_lock); 461 return (DDI_INTR_UNCLAIMED); 462 } 463 464 /* get the APC CSR */ 465 csr = ddi_get32(handle, &APC_DMACSR); 466 467 /* make sure this device sent the interrupt */ 468 if (!(csr & APC_IP)) { 469 if (csr & APC_PMI_EN) { 470 /* 471 * Clear device generated interrupt while play is 472 * active (Only seen while playing and insane mode 473 * switching) 474 */ 475 mutex_exit(&state->cs_lock); 476 return (DDI_INTR_CLAIMED); 477 } else { 478 /* nope, this isn't our interrupt */ 479 mutex_exit(&state->cs_lock); 480 return (DDI_INTR_UNCLAIMED); 481 } 482 } 483 484 /* clear all interrupts we captured this time */ 485 ddi_put32(handle, &APC_DMACSR, csr); 486 487 if (csr & APC_CINTR_MASK) { 488 /* try to load the next record buffer */ 489 apc_load_fragment(state->cs_engines[CS4231_REC]); 490 rc = DDI_INTR_CLAIMED; 491 } 492 493 if (csr & APC_PINTR_MASK) { 494 /* try to load the next play buffer */ 495 apc_load_fragment(state->cs_engines[CS4231_PLAY]); 496 rc = DDI_INTR_CLAIMED; 497 } 498 499 done: 500 501 /* APC error interrupt, not sure what to do here */ 502 if (csr & APC_EI) { 503 audio_dev_warn(state->cs_adev, "error interrupt: 0x%x", csr); 504 rc = DDI_INTR_CLAIMED; 505 } 506 507 /* update the kernel interrupt statistics */ 508 if (state->cs_ksp) { 509 if (rc == DDI_INTR_CLAIMED) { 510 KIOP(state)->intrs[KSTAT_INTR_HARD]++; 511 } 512 } 513 514 mutex_exit(&state->cs_lock); 515 516 if (csr & APC_CINTR_MASK) { 517 CS_engine_t *eng = state->cs_engines[CS4231_REC]; 518 if (eng->ce_started) 519 audio_engine_produce(eng->ce_engine); 520 } 521 if (csr & APC_PINTR_MASK) { 522 CS_engine_t *eng = state->cs_engines[CS4231_PLAY]; 523 if (eng->ce_started) 524 audio_engine_consume(eng->ce_engine); 525 } 526 527 return (rc); 528 529 } /* apc_intr() */ 530 531 static void 532 apc_load_fragment(CS_engine_t *eng) 533 { 534 CS_state_t *state = eng->ce_state; 535 ddi_acc_handle_t handle = APC_HANDLE; 536 uint32_t dirty; 537 uint32_t *nva; /* next VA reg */ 538 uint32_t *nc; /* next count reg */ 539 540 if (eng->ce_num == CS4231_PLAY) { 541 dirty = APC_PD; 542 nva = &APC_DMAPNVA; 543 nc = &APC_DMAPNC; 544 } else { 545 dirty = APC_CD; 546 nva = &APC_DMACNVA; 547 nc = &APC_DMACNC; 548 } 549 550 /* if we can't load another address, then don't */ 551 if ((ddi_get32(handle, &APC_DMACSR) & dirty) == 0) { 552 return; 553 } 554 555 /* read the NVA, as per APC document */ 556 (void) ddi_get32(handle, nva); 557 558 /* write the address of the next fragment */ 559 ddi_put32(handle, nva, eng->ce_paddr[eng->ce_cfrag]); 560 561 /* now program the NC reg., which enables the state machine */ 562 ddi_put32(handle, nc, eng->ce_fragsz); 563 564 eng->ce_cfrag++; 565 eng->ce_cfrag %= CS4231_NFRAGS; 566 eng->ce_count += eng->ce_fragfr; 567 } 568