xref: /illumos-gate/usr/src/uts/sun/io/audio/drv/audiocs/audio_4231_eb2dma.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 EB2 DMA controller. The EB2 is a PCI bus
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 eb2_dma_attr = {
43 	DMA_ATTR_V0,			/* version */
44 	0x0000000000000000LL,		/* dlim_addr_lo */
45 	0x00000000ffffffffLL,		/* dlim_addr_hi */
46 	0x0000000000ffffffLL,		/* DMA counter register */
47 	0x0000000000000001LL,		/* DMA address alignment */
48 	0x00000074,			/* 4 and 16 byte burst sizes */
49 	0x00000001,			/* min effective DMA size */
50 	0x000000000000ffffLL,		/* 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 codec_attr = {
58 	DDI_DEVICE_ATTR_V0,
59 	DDI_STRUCTURE_BE_ACC,
60 	DDI_STRICTORDER_ACC
61 };
62 
63 static ddi_device_acc_attr_t eb2_attr = {
64 	DDI_DEVICE_ATTR_V0,
65 	DDI_STRUCTURE_LE_ACC,
66 	DDI_STRICTORDER_ACC
67 };
68 
69 /*
70  * Local routines
71  */
72 static uint_t eb2_intr(caddr_t);
73 static void eb2_load_fragment(CS_engine_t *);
74 
75 /*
76  * DMA ops vector functions
77  */
78 static int eb2_map_regs(CS_state_t *);
79 static void eb2_unmap_regs(CS_state_t *);
80 static void eb2_reset(CS_state_t *);
81 static int eb2_add_intr(CS_state_t *);
82 static void eb2_rem_intr(CS_state_t *);
83 static int eb2_start_engine(CS_engine_t *);
84 static void eb2_stop_engine(CS_engine_t *);
85 static void eb2_power(CS_state_t *, int);
86 
87 cs4231_dma_ops_t cs4231_eb2dma_ops = {
88 	"EB2 DMA controller",
89 	&eb2_dma_attr,
90 	eb2_map_regs,
91 	eb2_unmap_regs,
92 	eb2_reset,
93 	eb2_add_intr,
94 	eb2_rem_intr,
95 	eb2_start_engine,
96 	eb2_stop_engine,
97 	eb2_power,
98 };
99 
100 /*
101  * eb2_map_regs()
102  *
103  * Description:
104  *	This routine allocates the DMA handles and the memory for the
105  *	DMA engines to use. It then binds each of the buffers to its
106  *	respective handle, getting a DMA cookie. Finally, the registers
107  *	are mapped in.
108  *
109  *	NOTE: All of the ddi_dma_... routines sleep if they cannot get
110  *		memory. This means these calls will almost always succeed.
111  *
112  * Arguments:
113  *	CS_state_t	*state		The device's state
114  *
115  * Returns:
116  *	DDI_SUCCESS		Registers successfully mapped
117  *	DDI_FAILURE		Registers not successfully mapped
118  */
119 static int
120 eb2_map_regs(CS_state_t *state)
121 {
122 	dev_info_t	*dip = state->cs_dip;
123 
124 	/* now, map the codec */
125 	if (ddi_regs_map_setup(dip, 0, (caddr_t *)&state->cs_regs, 0,
126 	    sizeof (cs4231_pioregs_t), &codec_attr, &CODEC_HANDLE) !=
127 	    DDI_SUCCESS) {
128 		audio_dev_warn(state->cs_adev, "failed mapping codec regs");
129 		goto error;
130 	}
131 
132 	/* next the play registers */
133 	if (ddi_regs_map_setup(dip, 1, (caddr_t *)&state->cs_eb2_regs.play, 0,
134 	    sizeof (cs4231_eb2regs_t), &eb2_attr, &EB2_PLAY_HNDL) !=
135 	    DDI_SUCCESS) {
136 		audio_dev_warn(state->cs_adev, "failed mapping play regs");
137 		goto error;
138 	}
139 	state->cs_engines[CS4231_PLAY]->ce_regsh = EB2_PLAY_HNDL;
140 	state->cs_engines[CS4231_PLAY]->ce_eb2regs = state->cs_eb2_regs.play;
141 
142 	/* now the capture registers */
143 	if (ddi_regs_map_setup(dip, 2, (caddr_t *)&state->cs_eb2_regs.record, 0,
144 	    sizeof (cs4231_eb2regs_t), &eb2_attr, &EB2_REC_HNDL) !=
145 	    DDI_SUCCESS) {
146 		audio_dev_warn(state->cs_adev, "failed mapping rec regs");
147 		goto error;
148 	}
149 	state->cs_engines[CS4231_REC]->ce_regsh = EB2_REC_HNDL;
150 	state->cs_engines[CS4231_REC]->ce_eb2regs = state->cs_eb2_regs.record;
151 
152 	/* finally the auxio register */
153 	if (ddi_regs_map_setup(dip, 3, (caddr_t *)&state->cs_eb2_regs.auxio, 0,
154 	    sizeof (uint_t), &eb2_attr, &EB2_AUXIO_HNDL) != DDI_SUCCESS) {
155 		audio_dev_warn(state->cs_adev, "failed mapping auxio reg");
156 		goto error;
157 	}
158 
159 	/* disable play and record interrupts */
160 	ddi_put32(EB2_PLAY_HNDL, &EB2_PLAY_CSR, EB2_PCLEAR_RESET_VALUE);
161 	ddi_put32(EB2_REC_HNDL, &EB2_REC_CSR, EB2_RCLEAR_RESET_VALUE);
162 
163 	return (DDI_SUCCESS);
164 
165 error:
166 	eb2_unmap_regs(state);
167 	return (DDI_FAILURE);
168 
169 }	/* eb2_map_regs() */
170 
171 /*
172  * eb2_unmap_regs()
173  *
174  * Description:
175  *	This routine unmaps the Codec's and DMA engine's registers.
176  *	It must be idempotent.
177  *
178  * Arguments:
179  *	CS_state_t	*state	The device's state
180  *
181  * Returns:
182  *	void
183  */
184 static void
185 eb2_unmap_regs(CS_state_t *state)
186 {
187 	if (CODEC_HANDLE)
188 		ddi_regs_map_free(&CODEC_HANDLE);
189 	if (EB2_PLAY_HNDL)
190 		ddi_regs_map_free(&EB2_PLAY_HNDL);
191 	if (EB2_REC_HNDL)
192 		ddi_regs_map_free(&EB2_REC_HNDL);
193 	if (EB2_AUXIO_HNDL)
194 		ddi_regs_map_free(&EB2_AUXIO_HNDL);
195 
196 }	/* eb2_unmap_regs() */
197 
198 /*
199  * eb2_reset()
200  *
201  * Description:
202  *	Reset both the play and record DMA engines. The engines are left
203  *	with interrupts and the DMA engine disabled.
204  *
205  * Arguments:
206  *	dev_info_t	*dip	Pointer to the device's devinfo structure
207  *	CS_state_t	*state	The device's state structure
208  *
209  * Returns:
210  *	void
211  */
212 static void
213 eb2_reset(CS_state_t *state)
214 {
215 	ddi_acc_handle_t	phandle = EB2_PLAY_HNDL;
216 	ddi_acc_handle_t	rhandle = EB2_REC_HNDL;
217 	uint_t			reg;
218 	int			x;
219 
220 	/* start with the play side */
221 	ddi_put32(phandle, &EB2_PLAY_CSR, EB2_RESET);
222 	/* wait for play data to drain */
223 	reg = ddi_get32(phandle, &EB2_PLAY_CSR);
224 	for (x = 0; (reg & EB2_FIFO_DRAIN) && x < CS4231_TIMEOUT; x++) {
225 		drv_usecwait(1);	/* don't beat on the bus */
226 		reg = ddi_get32(phandle, &EB2_PLAY_CSR);
227 	}
228 	/* clear the reset bit and program for chaining */
229 	ddi_put32(phandle, &EB2_PLAY_CSR, EB2_PCLEAR_RESET_VALUE);
230 
231 	/* now do the record side and program for chaining */
232 	ddi_put32(rhandle, &EB2_REC_CSR, EB2_RESET);
233 	/* wait for record data to drain */
234 	reg = ddi_get32(rhandle, &EB2_REC_CSR);
235 	for (x = 0; (reg & EB2_FIFO_DRAIN) && x < CS4231_TIMEOUT; x++) {
236 		drv_usecwait(1);	/* don't beat on the bus */
237 		reg = ddi_get32(rhandle, &EB2_REC_CSR);
238 	}
239 	/* clear the reset bit */
240 	ddi_put32(rhandle, &EB2_REC_CSR, EB2_RCLEAR_RESET_VALUE);
241 
242 }	/* eb2_reset() */
243 
244 /*
245  * eb2_add_intr()
246  *
247  * Description:
248  *	Register the EB2 interrupts with the kernel.
249  *
250  *	NOTE: This does NOT turn on interrupts.
251  *
252  *	CAUTION: While the interrupts are added, the Codec interrupts are
253  *		not enabled.
254  *
255  * Arguments:
256  *	CS_state_t	*state	Pointer to the device's state structure
257  *
258  * Returns:
259  *	DDI_SUCCESS		Interrupts added
260  *	DDI_FAILURE		Interrupts not added
261  */
262 static int
263 eb2_add_intr(CS_state_t *state)
264 {
265 	dev_info_t	*dip = state->cs_dip;
266 
267 	/* first we make sure these aren't high level interrupts */
268 	if (ddi_intr_hilevel(dip, 0) != 0) {
269 		audio_dev_warn(state->cs_adev, "unsupported hi level intr 0");
270 		return (DDI_FAILURE);
271 	}
272 	if (ddi_intr_hilevel(dip, 1) != 0) {
273 		audio_dev_warn(state->cs_adev, "unsupported hi level intr 1");
274 		return (DDI_FAILURE);
275 	}
276 
277 	/* okay to register the interrupts */
278 	if (ddi_add_intr(dip, 0, NULL, NULL, eb2_intr,
279 	    (caddr_t)state->cs_engines[CS4231_REC]) != DDI_SUCCESS) {
280 		audio_dev_warn(state->cs_adev, "bad record interrupt spec");
281 		return (DDI_FAILURE);
282 	}
283 
284 	if (ddi_add_intr(dip, 1, NULL, NULL, eb2_intr,
285 	    (caddr_t)state->cs_engines[CS4231_PLAY]) != DDI_SUCCESS) {
286 		audio_dev_warn(state->cs_adev, "play interrupt spec");
287 		ddi_remove_intr(dip, 0, NULL);
288 		return (DDI_FAILURE);
289 	}
290 
291 	return (DDI_SUCCESS);
292 
293 }	/* eb2_add_intr() */
294 
295 /*
296  * eb2_rem_intr()
297  *
298  * Description:
299  *	Unregister the EB2 interrupts from the kernel.
300  *
301  *	CAUTION: While the interrupts are removed, the Codec interrupts are
302  *		not disabled, but then, they never should have been on in
303  *		the first place.
304  *
305  * Arguments:
306  *	CS_state_t	*state	Pointer to the device's soft state
307  *
308  * Returns:
309  *	void
310  */
311 static void
312 eb2_rem_intr(CS_state_t *state)
313 {
314 	ddi_remove_intr(state->cs_dip, 0, NULL);
315 	ddi_remove_intr(state->cs_dip, 1, NULL);
316 }	/* eb2_rem_intr() */
317 
318 /*
319  * eb2_start_engine()
320  *
321  * Description:
322  *	This routine starts the DMA engine.
323  *
324  *	NOTE: The state structure must be locked before this routine is called.
325  *
326  * Arguments:
327  *	CS_engine_t	*eng	The DMA engine's state structure
328  *
329  * Returns:
330  *	DDI_SUCCESS		The DMA engine was started
331  *	DDI_FAILURE		The DMA engine was not started
332  */
333 static int
334 eb2_start_engine(CS_engine_t *eng)
335 {
336 	CS_state_t		*state = eng->ce_state;
337 	ddi_acc_handle_t	handle = eng->ce_regsh;
338 	cs4231_eb2regs_t	*regs = eng->ce_eb2regs;
339 	uint_t			csr;
340 	int			x;
341 	uint32_t		reset;
342 	uint32_t		enable;
343 
344 	if (eng->ce_num == CS4231_PLAY) {
345 		reset = EB2_PCLEAR_RESET_VALUE;
346 		enable = EB2_PLAY_ENABLE;
347 	} else {
348 		reset = EB2_RCLEAR_RESET_VALUE;
349 		enable = EB2_REC_ENABLE;
350 	}
351 
352 	ASSERT(mutex_owned(&state->cs_lock));
353 
354 	/* reset the DMA engine so we have a good starting place */
355 	OR_SET_WORD(handle, &regs->eb2csr, EB2_RESET);
356 
357 	/* wait for the FIFO to drain, it should be empty */
358 	csr = ddi_get32(handle, &regs->eb2csr);
359 	for (x = 0; (csr & EB2_FIFO_DRAIN) && x < CS4231_TIMEOUT; x++) {
360 		drv_usecwait(1);	/* no reason to beat on the bus */
361 		csr = ddi_get32(handle, &regs->eb2csr);
362 	}
363 	if (x >= CS4231_TIMEOUT) {
364 		audio_dev_warn(state->cs_adev,
365 		    "timeout waiting for engine, not started!");
366 		return (DDI_FAILURE);
367 	}
368 
369 	/* now clear the RESET and EN_DMA bits */
370 	AND_SET_WORD(handle, &regs->eb2csr, ~(EB2_RESET|EB2_EN_DMA));
371 
372 	/* put into chaining mode, enable byte counts  */
373 	OR_SET_WORD(handle, &regs->eb2csr, reset);
374 
375 	/*
376 	 * Program the DMA engine.
377 	 */
378 	eb2_load_fragment(eng);
379 
380 	/*
381 	 * Start playing before we load the next fragment.
382 	 */
383 	OR_SET_WORD(handle, &regs->eb2csr, enable);
384 
385 	/*
386 	 * Program a 2nd fragment.
387 	 */
388 	eb2_load_fragment(eng);
389 
390 	return (DDI_SUCCESS);
391 
392 }	/* eb2_start_engine() */
393 
394 /*
395  * eb2_stop_engine()
396  *
397  * Description:
398  *	This routine stops the DMA engine.
399  *
400  *	NOTE: The state structure must be locked before this routine is called.
401  *
402  * Arguments:
403  *	CS_engine_t	*eng	The engine to stop
404  *
405  * Returns:
406  *	void
407  */
408 static void
409 eb2_stop_engine(CS_engine_t *eng)
410 {
411 	ddi_acc_handle_t	handle = eng->ce_regsh;
412 	cs4231_eb2regs_t	*regs = eng->ce_eb2regs;
413 	uint_t			csr;
414 
415 	/* shut off DMA and disable interrupts */
416 	AND_SET_WORD(handle, &regs->eb2csr, ~(EB2_EN_DMA | EB2_INT_EN));
417 
418 	csr = ddi_get32(handle, &regs->eb2csr);
419 	for (int x = 0; (csr & EB2_CYC_PENDING) && x < CS4231_TIMEOUT; x++) {
420 		drv_usecwait(1);
421 		csr = ddi_get32(handle, &regs->eb2csr);
422 	}
423 
424 	/* set the RESET bit to stop audio, also clear any TC interrupt */
425 	OR_SET_WORD(handle, &regs->eb2csr, EB2_RESET | EB2_TC);
426 
427 	/* wait for the FIFO to drain */
428 	csr = ddi_get32(handle, &regs->eb2csr);
429 	for (int x = 0; (csr & EB2_FIFO_DRAIN) && x < CS4231_TIMEOUT; x++) {
430 		drv_usecwait(1);		/* don't beat on the bus */
431 		csr = ddi_get32(handle, &regs->eb2csr);
432 	}
433 
434 	/* clear the RESET and EN_DMA bits */
435 	AND_SET_WORD(handle, &regs->eb2csr, ~(EB2_RESET|EB2_EN_DMA));
436 
437 }	/* eb2_stop_engine() */
438 
439 /*
440  * eb2_power()
441  *
442  * Description:
443  *	This routine turns the Codec on or off using the auxio register
444  *	in the eb2 device (cheerio or rio). Fortunately we don't need
445  *	to delay like we do with the APC.
446  *
447  *	NOTE: The state structure must be locked when this routine is called.
448  *
449  * Arguments:
450  *	CS_state_t	*state		Ptr to the device's state structure
451  *	int		level		Power level to set
452  *
453  * Returns:
454  *	void
455  */
456 static void
457 eb2_power(CS_state_t *state, int level)
458 {
459 	ddi_acc_handle_t	xhandle = EB2_AUXIO_HNDL;
460 
461 	if (level == CS4231_PWR_ON) {	/* turn power on */
462 		AND_SET_WORD(xhandle, EB2_AUXIO_REG, ~EB2_AUXIO_COD_PDWN);
463 	} else {	/* turn power off */
464 		OR_SET_WORD(xhandle, EB2_AUXIO_REG, EB2_AUXIO_COD_PDWN);
465 	}
466 
467 }	/* eb2_power() */
468 
469 
470 /* *******  Local Routines ************************************************** */
471 
472 /*
473  * eb2_intr()
474  *
475  * Description:
476  *	EB2 interrupt serivce routine. First we find out why there was an
477  *	interrupt, then we take the appropriate action.
478  *
479  * Arguments:
480  *	caddr_t		T	Pointer to the interrupting device's state
481  *				structure
482  *
483  * Returns:
484  *	DDI_INTR_CLAIMED	Interrupt claimed and processed
485  *	DDI_INTR_UNCLAIMED	Interrupt not claimed, and thus ignored
486  */
487 static uint_t
488 eb2_intr(caddr_t T)
489 {
490 	CS_engine_t		*eng = (void *)T;
491 	CS_state_t		*state = eng->ce_state;
492 	cs4231_eb2regs_t	*regs = eng->ce_eb2regs;
493 	ddi_acc_handle_t	handle = eng->ce_regsh;
494 	uint32_t		csr;
495 	boolean_t		doit = B_FALSE;
496 
497 	/* the state must be protected */
498 	mutex_enter(&state->cs_lock);
499 	if (state->cs_suspended) {
500 		mutex_exit(&state->cs_lock);
501 		return (DDI_INTR_UNCLAIMED);
502 	}
503 
504 	/* get the EB2 CSR */
505 	csr = ddi_get32(handle, &regs->eb2csr);
506 
507 	/* make sure this device sent the interrupt */
508 	if (!(csr & EB2_INT_PEND)) {
509 		mutex_exit(&state->cs_lock);
510 		/* nope, this isn't our interrupt */
511 		return (DDI_INTR_UNCLAIMED);
512 	}
513 
514 	/* clear all interrupts we captured at this time */
515 	ddi_put32(handle, &regs->eb2csr, (csr|EB2_TC));
516 
517 	if (csr & EB2_TC) {
518 
519 		/* try to load the next audio buffer */
520 		eb2_load_fragment(eng);
521 
522 		/* if engine was started, then we want to consume later */
523 		doit = eng->ce_started;
524 
525 	} else if (csr & EB2_ERR_PEND) {
526 		audio_dev_warn(state->cs_adev, "error intr: 0x%x", csr);
527 
528 	} else {
529 		audio_dev_warn(state->cs_adev, "unknown intr: 0x%x", csr);
530 	}
531 
532 	/* update the kernel interrupt statisitcs */
533 	if (state->cs_ksp) {
534 		KIOP(state)->intrs[KSTAT_INTR_HARD]++;
535 	}
536 
537 	mutex_exit(&state->cs_lock);
538 
539 	if (doit) {
540 		if (eng->ce_num == CS4231_PLAY) {
541 			audio_engine_consume(eng->ce_engine);
542 		} else {
543 			audio_engine_produce(eng->ce_engine);
544 		}
545 	}
546 
547 	return (DDI_INTR_CLAIMED);
548 
549 }	/* eb2_intr() */
550 
551 static void
552 eb2_load_fragment(CS_engine_t *eng)
553 {
554 	ddi_acc_handle_t	handle = eng->ce_regsh;
555 	cs4231_eb2regs_t	*regs = eng->ce_eb2regs;
556 
557 	/* if next address already loaded, then we're done */
558 	if ((ddi_get32(handle, &regs->eb2csr) & EB2_NA_LOADED)) {
559 		return;
560 	}
561 
562 	/*
563 	 * For eb2 we first program the Next Byte Count Register.
564 	 */
565 	ddi_put32(handle, &regs->eb2bcr, eng->ce_fragsz);
566 
567 	/* now program the Next Address Register */
568 	ddi_put32(handle, &regs->eb2acr, eng->ce_paddr[eng->ce_cfrag]);
569 
570 	eng->ce_cfrag++;
571 	eng->ce_cfrag %= CS4231_NFRAGS;
572 	eng->ce_count += eng->ce_fragfr;
573 }
574