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
apc_map_regs(CS_state_t * state)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
apc_unmap_regs(CS_state_t * state)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
apc_reset(CS_state_t * state)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
apc_start_engine(CS_engine_t * eng)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
apc_stop_engine(CS_engine_t * eng)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
apc_power(CS_state_t * state,int level)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
apc_reload(CS_engine_t * eng)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
apc_addr(CS_engine_t * eng)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