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 2010 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 * DMA ops vector functions 65 */ 66 static int apc_map_regs(CS_state_t *); 67 static void apc_unmap_regs(CS_state_t *); 68 static void apc_reset(CS_state_t *); 69 static int apc_start_engine(CS_engine_t *); 70 static void apc_stop_engine(CS_engine_t *); 71 static void apc_power(CS_state_t *, int); 72 static void apc_reload(CS_engine_t *); 73 static uint32_t apc_addr(CS_engine_t *); 74 75 cs4231_dma_ops_t cs4231_apcdma_ops = { 76 "APC DMA controller", 77 &apc_dma_attr, 78 apc_map_regs, 79 apc_unmap_regs, 80 apc_reset, 81 apc_start_engine, 82 apc_stop_engine, 83 apc_power, 84 apc_reload, 85 apc_addr, 86 }; 87 88 /* 89 * apc_map_regs() 90 * 91 * Description: 92 * This routine allocates the DMA handles and the memory for the 93 * DMA engines to use. It then binds each of the buffers to its 94 * respective handle, getting a DMA cookie. Finally, the registers 95 * are mapped in. 96 * 97 * NOTE: All of the ddi_dma_... routines sleep if they cannot get 98 * memory. This means these calls will almost always succeed. 99 * 100 * Arguments: 101 * CS_state_t *state The device's state structure 102 * 103 * Returns: 104 * AUDIO_SUCCESS Registers successfully mapped 105 * AUDIO_FAILURE Registers not successfully mapped 106 */ 107 static int 108 apc_map_regs(CS_state_t *state) 109 { 110 ddi_acc_handle_t *handle = &APC_HANDLE; 111 dev_info_t *dip = state->cs_dip; 112 113 /* map in the registers, getting a handle */ 114 if (ddi_regs_map_setup(dip, 0, (caddr_t *)&state->cs_regs, 0, 115 sizeof (cs4231_regs_t), &acc_attr, handle) != DDI_SUCCESS) { 116 audio_dev_warn(state->cs_adev, "ddi_regs_map_setup() failed"); 117 return (DDI_FAILURE); 118 } 119 120 /* clear the CSR so we have all interrupts disabled */ 121 ddi_put32(*handle, &APC_DMACSR, APC_CLEAR_RESET_VALUE); 122 123 return (DDI_SUCCESS); 124 } /* apc_map_regs() */ 125 126 /* 127 * apc_unmap_regs() 128 * 129 * Description: 130 * This routine unmaps the Codec's and DMA engine's registers. 131 * It must be idempotent. 132 * 133 * Arguments: 134 * CS_state_t *state The device's state structure 135 * 136 * Returns: 137 * void 138 */ 139 static void 140 apc_unmap_regs(CS_state_t *state) 141 { 142 if (APC_HANDLE) 143 ddi_regs_map_free(&APC_HANDLE); 144 145 } /* apc_unmap_regs() */ 146 147 /* 148 * apc_reset() 149 * 150 * Description: 151 * Reset both the play and record DMA engines. The engines are left 152 * with interrupts and the DMA engine disabled. 153 * 154 * Arguments: 155 * dev_info_t *dip Pointer to the device's devinfo structure 156 * CS_state_t *state The device's state structure 157 * 158 * Returns: 159 * void 160 */ 161 static void 162 apc_reset(CS_state_t *state) 163 { 164 ddi_acc_handle_t handle = APC_HANDLE; 165 166 /* 167 * The APC has a bug where the reset is not done 168 * until you do the next pio to the APC. This 169 * next write to the CSR causes the posted reset to 170 * happen. 171 */ 172 173 ddi_put32(handle, &APC_DMACSR, APC_RESET); 174 ddi_put32(handle, &APC_DMACSR, APC_CLEAR_RESET_VALUE); 175 176 } /* apc_reset() */ 177 178 /* 179 * apc_start_engine() 180 * 181 * Description: 182 * This routine starts the DMA engine. 183 * 184 * For hard starts the DMA engine is started by programming the 185 * Next Virtual Address and then the Next Counter twice, and 186 * finally enabling the DMA engine. 187 * 188 * NOTE: The state structure must be locked before this routine is called. 189 * 190 * CAUTION: ?!? This routine doesn't start the Codec because the first 191 * interrupt causes a recursive mutex_enter. 192 * 193 * Arguments: 194 * CS_engine_t *eng The engine to start 195 * 196 * Returns: 197 * DDI_SUCCESS The DMA engine was started 198 * DDI_FAILURE The DMA engine was not started 199 */ 200 static int 201 apc_start_engine(CS_engine_t *eng) 202 { 203 CS_state_t *state = eng->ce_state; 204 ddi_acc_handle_t handle = APC_HANDLE; 205 uint32_t csr; 206 uint32_t enable; 207 uint32_t dirty; 208 int x; 209 210 ASSERT(mutex_owned(&state->cs_lock)); 211 212 if (eng->ce_num == CS4231_PLAY) { 213 enable = APC_PDMA_GO; 214 dirty = APC_PD; 215 } else { 216 enable = APC_CDMA_GO; 217 dirty = APC_CD; 218 } 219 220 /* make sure it's okay to program the Next Address/Count registers */ 221 csr = ddi_get32(handle, &APC_DMACSR); 222 for (x = 0; !(csr & dirty) && x < CS4231_TIMEOUT; x++) { 223 drv_usecwait(1); /* no reason to beat on the bus */ 224 csr = ddi_get32(handle, &APC_DMACSR); 225 } 226 if (x >= CS4231_TIMEOUT) { 227 audio_dev_warn(state->cs_adev, 228 "timeout waiting for engine, not started!"); 229 return (DDI_FAILURE); 230 } 231 232 /* 233 * Program the first fragment. 234 */ 235 apc_reload(eng); 236 237 /* 238 * Start the DMA engine, including interrupts. 239 */ 240 OR_SET_WORD(handle, &APC_DMACSR, enable); 241 242 /* 243 * Program the double buffering. 244 */ 245 apc_reload(eng); 246 247 return (DDI_SUCCESS); 248 } 249 250 /* 251 * apc_stop_engine() 252 * 253 * Description: 254 * This routine stops the engine. 255 * 256 * The DMA engine is stopped by using the CAP_ABORT bit. 257 * 258 * NOTE: The state structure must be locked before this routine is called. 259 * 260 * Arguments: 261 * CS_engine_t *eng The engine to sotp 262 * 263 * Returns: 264 * void 265 */ 266 static void 267 apc_stop_engine(CS_engine_t *eng) 268 { 269 CS_state_t *state = eng->ce_state; 270 ddi_acc_handle_t handle = APC_HANDLE; 271 uint32_t reg; 272 uint32_t abort; 273 uint32_t drainbit; 274 uint32_t disable; 275 276 ASSERT(mutex_owned(&state->cs_lock)); 277 278 if (eng->ce_num == CS4231_PLAY) { 279 abort = APC_P_ABORT; 280 drainbit = APC_PM; 281 disable = APC_PLAY_DISABLE; 282 } else { 283 abort = APC_C_ABORT; 284 drainbit = APC_CX; 285 disable = APC_CAP_DISABLE; 286 } 287 288 /* first, abort the DMA engine */ 289 OR_SET_WORD(handle, &APC_DMACSR, abort); 290 291 /* wait for the pipeline to empty */ 292 reg = ddi_get32(handle, &APC_DMACSR); 293 for (int x = 0; (!(reg & drainbit)) && (x < CS4231_TIMEOUT); x++) { 294 drv_usecwait(1); /* don't beat on bus */ 295 reg = ddi_get32(handle, &APC_DMACSR); 296 } 297 298 /* now clear the enable and abort bits */ 299 AND_SET_WORD(handle, &APC_DMACSR, ~(abort|disable)); 300 } 301 302 303 /* 304 * apc_power() 305 * 306 * Description: 307 * This routine turns the Codec off by using the COD_PDWN bit in the 308 * apc chip. To turn power on we have to reset the APC, which clears 309 * the COD_PDWN bit. However, this is a settling bug in the APC which 310 * requires the driver to delay quite a while before we may continue. 311 * Since this is the first time this feature has actually been used 312 * it isn't too surprising that it has some problems. 313 * 314 * NOTE: The state structure must be locked when this routine is called. 315 * 316 * Arguments: 317 * CS_state_t *state Ptr to the device's state structure 318 * int level Power level to set 319 */ 320 static void 321 apc_power(CS_state_t *state, int level) 322 { 323 ddi_acc_handle_t handle = APC_HANDLE; 324 325 if (level == CS4231_PWR_ON) { /* turn power on */ 326 AND_SET_WORD(handle, &APC_DMACSR, ~APC_COD_PDWN); 327 OR_SET_WORD(handle, &APC_DMACSR, APC_RESET); 328 AND_SET_WORD(handle, &APC_DMACSR, ~APC_RESET); 329 330 /* 331 * wait for state change, 332 */ 333 delay(drv_usectohz(CS4231_300MS)); 334 } else { /* turn power off */ 335 ASSERT(level == CS4231_PWR_OFF); 336 OR_SET_WORD(handle, &APC_DMACSR, APC_COD_PDWN); 337 } 338 339 } /* apc_power() */ 340 341 342 static void 343 apc_reload(CS_engine_t *eng) 344 { 345 CS_state_t *state = eng->ce_state; 346 ddi_acc_handle_t handle = APC_HANDLE; 347 uint32_t dirty; 348 uint32_t *nva; /* next VA reg */ 349 uint32_t *nc; /* next count reg */ 350 351 if (eng->ce_num == CS4231_PLAY) { 352 dirty = APC_PD; 353 nva = &APC_DMAPNVA; 354 nc = &APC_DMAPNC; 355 } else { 356 dirty = APC_CD; 357 nva = &APC_DMACNVA; 358 nc = &APC_DMACNC; 359 } 360 361 /* if we can't load another address, then don't */ 362 if ((ddi_get32(handle, &APC_DMACSR) & dirty) == 0) { 363 return; 364 } 365 366 /* read the NVA, as per APC document */ 367 (void) ddi_get32(handle, nva); 368 369 /* write the address of the next fragment */ 370 ddi_put32(handle, nva, 371 eng->ce_paddr + (CS4231_FRAGSZ * eng->ce_curidx)); 372 eng->ce_curidx++; 373 eng->ce_curidx %= CS4231_NFRAGS; 374 375 /* now program the NC reg., which enables the state machine */ 376 ddi_put32(handle, nc, CS4231_FRAGSZ); 377 } 378 379 /* 380 * apc_addr() 381 * 382 * Description: 383 * This routine returns the current DMA address for the engine (the 384 * next address being accessed). 385 * 386 * Arguments: 387 * CS_engine_t *eng The engine 388 * 389 * Returns: 390 * Physical DMA address for current transfer. 391 */ 392 static uint32_t 393 apc_addr(CS_engine_t *eng) 394 { 395 CS_state_t *state = eng->ce_state; 396 ddi_acc_handle_t handle = APC_HANDLE; 397 uint32_t *va; /* VA reg */ 398 399 if (eng->ce_num == CS4231_PLAY) { 400 va = &APC_DMAPVA; 401 } else { 402 va = &APC_DMACVA; 403 } 404 405 return (ddi_get32(handle, va)); 406 } 407