xref: /illumos-gate/usr/src/uts/sun/io/audio/drv/audiocs/audio_4231.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 /*
28  * audiocs Audio Driver
29  *
30  * This Audio Driver controls the Crystal CS4231 Codec used on many SPARC
31  * platforms. It does not support the CS4231 on Power PCs or x86 PCs. It
32  * does support two different DMA engines, the APC and EB2. The code for
33  * those DMA engines is split out and a well defined, but private, interface
34  * is used to control those DMA engines.
35  *
36  * For some reason setting the CS4231's registers doesn't always
37  * succeed.  Therefore every time we set a register we always read it
38  * back to make sure it was set. If not we wait a little while and
39  * then try again. This is all taken care of in the routines
40  * audiocs_put_index() and audiocs_sel_index() and the macros ORIDX()
41  * and ANDIDX(). We don't worry about the status register because it
42  * is cleared by writing anything to it.  So it doesn't matter what
43  * the value written is.
44  *
45  * This driver supports suspending and resuming. A suspend just stops playing
46  * and recording. The play DMA buffers end up getting thrown away, but when
47  * you shut down the machine there is a break in the audio anyway, so they
48  * won't be missed and it isn't worth the effort to save them. When we resume
49  * we always start playing and recording. If they aren't needed they get
50  * shut off by the mixer.
51  *
52  * Power management is supported by this driver.
53  *
54  *	NOTE: This module depends on drv/audio being loaded first.
55  */
56 
57 #include <sys/modctl.h>
58 #include <sys/kmem.h>
59 #include <sys/stropts.h>
60 #include <sys/ddi.h>
61 #include <sys/sunddi.h>
62 #include <sys/note.h>
63 #include <sys/audio/audio_driver.h>
64 #include "audio_4231.h"
65 
66 /*
67  * Module linkage routines for the kernel
68  */
69 static int audiocs_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
70 static int audiocs_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
71 static int audiocs_ddi_power(dev_info_t *, int, int);
72 
73 /*
74  * Entry point routine prototypes
75  */
76 static int audiocs_open(void *, int, unsigned *, unsigned *, caddr_t *);
77 static void audiocs_close(void *);
78 static int audiocs_start(void *);
79 static void audiocs_stop(void *);
80 static int audiocs_format(void *);
81 static int audiocs_channels(void *);
82 static int audiocs_rate(void *);
83 static uint64_t audiocs_count(void *);
84 static void audiocs_sync(void *, unsigned);
85 static size_t audiocs_qlen(void *);
86 
87 /*
88  * Control callbacks.
89  */
90 static int audiocs_get_value(void *, uint64_t *);
91 static int audiocs_set_ogain(void *, uint64_t);
92 static int audiocs_set_igain(void *, uint64_t);
93 static int audiocs_set_mgain(void *, uint64_t);
94 static int audiocs_set_inputs(void *, uint64_t);
95 static int audiocs_set_outputs(void *, uint64_t);
96 static int audiocs_set_micboost(void *, uint64_t);
97 
98 /* Local Routines */
99 static int audiocs_resume(dev_info_t *);
100 static int audiocs_attach(dev_info_t *);
101 static int audiocs_detach(dev_info_t *);
102 static int audiocs_suspend(dev_info_t *);
103 
104 static void audiocs_destroy(CS_state_t *);
105 static int audiocs_init_state(CS_state_t *);
106 static int audiocs_chip_init(CS_state_t *);
107 static int audiocs_alloc_engine(CS_state_t *, int);
108 static void audiocs_free_engine(CS_engine_t *);
109 static void audiocs_reset_engine(CS_engine_t *);
110 static int audiocs_start_engine(CS_engine_t *);
111 static void audiocs_stop_engine(CS_engine_t *);
112 static void audiocs_get_ports(CS_state_t *);
113 static void audiocs_configure_input(CS_state_t *);
114 static void audiocs_configure_output(CS_state_t *);
115 static CS_ctrl_t *audiocs_alloc_ctrl(CS_state_t *, uint32_t, uint64_t);
116 static void audiocs_free_ctrl(CS_ctrl_t *);
117 static int audiocs_add_controls(CS_state_t *);
118 static void audiocs_del_controls(CS_state_t *);
119 static void audiocs_power_up(CS_state_t *);
120 static void audiocs_power_down(CS_state_t *);
121 static int audiocs_poll_ready(CS_state_t *);
122 #ifdef	DEBUG
123 static void audiocs_put_index(CS_state_t *,  uint8_t, uint8_t, int);
124 static void audiocs_sel_index(CS_state_t *, uint8_t, int);
125 #define	SELIDX(s, idx)		audiocs_sel_index(s, idx, __LINE__)
126 #define	PUTIDX(s, val, mask)	audiocs_put_index(s, val, mask, __LINE__)
127 #else
128 static void audiocs_put_index(CS_state_t *,  uint8_t, uint8_t);
129 static void audiocs_sel_index(CS_state_t *, uint8_t);
130 #define	SELIDX(s, idx)		audiocs_sel_index(s, idx)
131 #define	PUTIDX(s, val, mask)	audiocs_put_index(s, val, mask)
132 #endif
133 
134 #define	ORIDX(s, val, mask)						\
135 	PUTIDX(s,							\
136 	    (ddi_get8((handle), &CS4231_IDR) | (uint8_t)(val)),		\
137 	    (uint8_t)(mask))
138 
139 #define	ANDIDX(s, val, mask)						\
140 	PUTIDX(s, (ddi_get8((handle), &CS4231_IDR) & (uint8_t)(val)),	\
141 	    (uint8_t)(mask))
142 
143 static audio_engine_ops_t audiocs_engine_ops = {
144 	AUDIO_ENGINE_VERSION,
145 	audiocs_open,
146 	audiocs_close,
147 	audiocs_start,
148 	audiocs_stop,
149 	audiocs_count,
150 	audiocs_format,
151 	audiocs_channels,
152 	audiocs_rate,
153 	audiocs_sync,
154 	audiocs_qlen
155 };
156 
157 #define	OUTPUT_SPEAKER		0
158 #define	OUTPUT_HEADPHONES	1
159 #define	OUTPUT_LINEOUT		2
160 
161 static const char *audiocs_outputs[] = {
162 	AUDIO_PORT_SPEAKER,
163 	AUDIO_PORT_HEADPHONES,
164 	AUDIO_PORT_LINEOUT,
165 	NULL
166 };
167 
168 #define	INPUT_MIC		0
169 #define	INPUT_LINEIN		1
170 #define	INPUT_STEREOMIX		2
171 #define	INPUT_CD		3
172 
173 static const char *audiocs_inputs[] = {
174 	AUDIO_PORT_MIC,
175 	AUDIO_PORT_LINEIN,
176 	AUDIO_PORT_STEREOMIX,
177 	AUDIO_PORT_CD,
178 	NULL
179 };
180 
181 /*
182  * Global variables, but viewable only by this file.
183  */
184 
185 /* play gain array, converts linear gain to 64 steps of log10 gain */
186 static uint8_t cs4231_atten[] = {
187 	0x3f,	0x3e,	0x3d,	0x3c,	0x3b,	/* [000] -> [004] */
188 	0x3a,	0x39,	0x38,	0x37,	0x36,	/* [005] -> [009] */
189 	0x35,	0x34,	0x33,	0x32,	0x31,	/* [010] -> [014] */
190 	0x30,	0x2f,	0x2e,	0x2d,	0x2c,	/* [015] -> [019] */
191 	0x2b,	0x2a,	0x29,	0x29,	0x28,	/* [020] -> [024] */
192 	0x28,	0x27,	0x27,	0x26,	0x26,	/* [025] -> [029] */
193 	0x25,	0x25,	0x24,	0x24,	0x23,	/* [030] -> [034] */
194 	0x23,	0x22,	0x22,	0x21,	0x21,	/* [035] -> [039] */
195 	0x20,	0x20,	0x1f,	0x1f,	0x1f,	/* [040] -> [044] */
196 	0x1e,	0x1e,	0x1e,	0x1d,	0x1d,	/* [045] -> [049] */
197 	0x1d,	0x1c,	0x1c,	0x1c,	0x1b,	/* [050] -> [054] */
198 	0x1b,	0x1b,	0x1a,	0x1a,	0x1a,	/* [055] -> [059] */
199 	0x1a,	0x19,	0x19,	0x19,	0x19,	/* [060] -> [064] */
200 	0x18,	0x18,	0x18,	0x18,	0x17,	/* [065] -> [069] */
201 	0x17,	0x17,	0x17,	0x16,	0x16,	/* [070] -> [074] */
202 	0x16,	0x16,	0x16,	0x15,	0x15,	/* [075] -> [079] */
203 	0x15,	0x15,	0x15,	0x14,	0x14,	/* [080] -> [084] */
204 	0x14,	0x14,	0x14,	0x13,	0x13,	/* [085] -> [089] */
205 	0x13,	0x13,	0x13,	0x12,	0x12,	/* [090] -> [094] */
206 	0x12,	0x12,	0x12,	0x12,	0x11,	/* [095] -> [099] */
207 	0x11,	0x11,	0x11,	0x11,	0x11,	/* [100] -> [104] */
208 	0x10,	0x10,	0x10,	0x10,	0x10,	/* [105] -> [109] */
209 	0x10,	0x0f,	0x0f,	0x0f,	0x0f,	/* [110] -> [114] */
210 	0x0f,	0x0f,	0x0e,	0x0e,	0x0e,	/* [114] -> [119] */
211 	0x0e,	0x0e,	0x0e,	0x0e,	0x0d,	/* [120] -> [124] */
212 	0x0d,	0x0d,	0x0d,	0x0d,	0x0d,	/* [125] -> [129] */
213 	0x0d,	0x0c,	0x0c,	0x0c,	0x0c,	/* [130] -> [134] */
214 	0x0c,	0x0c,	0x0c,	0x0b,	0x0b,	/* [135] -> [139] */
215 	0x0b,	0x0b,	0x0b,	0x0b,	0x0b,	/* [140] -> [144] */
216 	0x0b,	0x0a,	0x0a,	0x0a,	0x0a,	/* [145] -> [149] */
217 	0x0a,	0x0a,	0x0a,	0x0a,	0x09,	/* [150] -> [154] */
218 	0x09,	0x09,	0x09,	0x09,	0x09,	/* [155] -> [159] */
219 	0x09,	0x09,	0x08,	0x08,	0x08,	/* [160] -> [164] */
220 	0x08,	0x08,	0x08,	0x08,	0x08,	/* [165] -> [169] */
221 	0x08,	0x07,	0x07,	0x07,	0x07,	/* [170] -> [174] */
222 	0x07,	0x07,	0x07,	0x07,	0x07,	/* [175] -> [179] */
223 	0x06,	0x06,	0x06,	0x06,	0x06,	/* [180] -> [184] */
224 	0x06,	0x06,	0x06,	0x06,	0x05,	/* [185] -> [189] */
225 	0x05,	0x05,	0x05,	0x05,	0x05,	/* [190] -> [194] */
226 	0x05,	0x05,	0x05,	0x05,	0x04,	/* [195] -> [199] */
227 	0x04,	0x04,	0x04,	0x04,	0x04,	/* [200] -> [204] */
228 	0x04,	0x04,	0x04,	0x04,	0x03,	/* [205] -> [209] */
229 	0x03,	0x03,	0x03,	0x03,	0x03,	/* [210] -> [214] */
230 	0x03,	0x03,	0x03,	0x03,	0x03,	/* [215] -> [219] */
231 	0x02,	0x02,	0x02,	0x02,	0x02,	/* [220] -> [224] */
232 	0x02,	0x02,	0x02,	0x02,	0x02,	/* [225] -> [229] */
233 	0x02,	0x01,	0x01,	0x01,	0x01,	/* [230] -> [234] */
234 	0x01,	0x01,	0x01,	0x01,	0x01,	/* [235] -> [239] */
235 	0x01,	0x01,	0x01,	0x00,	0x00,	/* [240] -> [244] */
236 	0x00,	0x00,	0x00,	0x00,	0x00,	/* [245] -> [249] */
237 	0x00,	0x00,	0x00,	0x00,	0x00,	/* [250] -> [254] */
238 	0x00					/* [255] */
239 };
240 
241 /*
242  * STREAMS Structures
243  */
244 
245 /*
246  * DDI Structures
247  */
248 
249 /* Device operations structure */
250 static struct dev_ops audiocs_dev_ops = {
251 	DEVO_REV,			/* devo_rev */
252 	0,				/* devo_refcnt */
253 	NULL,				/* devo_getinfo */
254 	nulldev,			/* devo_identify - obsolete */
255 	nulldev,			/* devo_probe - not needed */
256 	audiocs_ddi_attach,		/* devo_attach */
257 	audiocs_ddi_detach,		/* devo_detach */
258 	nodev,				/* devo_reset */
259 	NULL,				/* devi_cb_ops */
260 	NULL,				/* devo_bus_ops */
261 	audiocs_ddi_power,		/* devo_power */
262 	ddi_quiesce_not_supported,	/* devo_quiesce */
263 };
264 
265 /* Linkage structure for loadable drivers */
266 static struct modldrv audiocs_modldrv = {
267 	&mod_driverops,		/* drv_modops */
268 	CS4231_MOD_NAME,	/* drv_linkinfo */
269 	&audiocs_dev_ops	/* drv_dev_ops */
270 };
271 
272 /* Module linkage structure */
273 static struct modlinkage audiocs_modlinkage = {
274 	MODREV_1,			/* ml_rev */
275 	(void *)&audiocs_modldrv,	/* ml_linkage */
276 	NULL				/* NULL terminates the list */
277 };
278 
279 
280 /* *******  Loadable Module Configuration Entry Points  ********************* */
281 
282 /*
283  * _init()
284  *
285  * Description:
286  *	Implements _init(9E).
287  *
288  * Returns:
289  *	mod_install() status, see mod_install(9f)
290  */
291 int
292 _init(void)
293 {
294 	int	rv;
295 
296 	audio_init_ops(&audiocs_dev_ops, CS4231_NAME);
297 
298 	if ((rv = mod_install(&audiocs_modlinkage)) != 0) {
299 		audio_fini_ops(&audiocs_dev_ops);
300 	}
301 
302 	return (rv);
303 }
304 
305 /*
306  * _fini()
307  *
308  * Description:
309  *	Implements _fini(9E).
310  *
311  * Returns:
312  *	mod_remove() status, see mod_remove(9f)
313  */
314 int
315 _fini(void)
316 {
317 	int	rv;
318 
319 	if ((rv = mod_remove(&audiocs_modlinkage)) == 0) {
320 		audio_fini_ops(&audiocs_dev_ops);
321 	}
322 
323 	return (rv);
324 }
325 
326 /*
327  * _info()
328  *
329  * Description:
330  *	Implements _info(9E).
331  *
332  * Arguments:
333  *	modinfo *modinfop	Pointer to the opaque modinfo structure
334  *
335  * Returns:
336  *	mod_info() status, see mod_info(9f)
337  */
338 int
339 _info(struct modinfo *modinfop)
340 {
341 	return (mod_info(&audiocs_modlinkage, modinfop));
342 }
343 
344 
345 /* *******  Driver Entry Points  ******************************************** */
346 
347 /*
348  * audiocs_ddi_attach()
349  *
350  * Description:
351  *	Implement attach(9e).
352  *
353  * Arguments:
354  *	dev_info_t	*dip	Pointer to the device's dev_info struct
355  *	ddi_attach_cmd_t cmd	Attach command
356  *
357  * Returns:
358  *	DDI_SUCCESS		The driver was initialized properly
359  *	DDI_FAILURE		The driver couldn't be initialized properly
360  */
361 static int
362 audiocs_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
363 {
364 	switch (cmd) {
365 	case DDI_ATTACH:
366 		return (audiocs_attach(dip));
367 
368 	case DDI_RESUME:
369 		return (audiocs_resume(dip));
370 
371 	default:
372 		return (DDI_FAILURE);
373 	}
374 }
375 
376 /*
377  * audiocs_ddi_detach()
378  *
379  * Description:
380  *	Implement detach(9e).
381  *
382  * Arguments:
383  *	dev_info_t	*dip	Pointer to the device's dev_info struct
384  *	ddi_detach_cmd_t cmd	Detach command
385  *
386  * Returns:
387  *	DDI_SUCCESS		Success.
388  *	DDI_FAILURE		Failure.
389  */
390 static int
391 audiocs_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
392 {
393 	switch (cmd) {
394 	case DDI_DETACH:
395 		return (audiocs_detach(dip));
396 
397 	case DDI_SUSPEND:
398 		return (audiocs_suspend(dip));
399 
400 	default:
401 		return (DDI_FAILURE);
402 	}
403 }
404 
405 /*
406  * audiocs_ddi_power()
407  *
408  * Description:
409  *	Implements power(9E).
410  *
411  * Arguments:
412  *	def_info_t	*dip		Ptr to the device's dev_info structure
413  *	int		component	Which component to power up/down
414  *	int		level		The power level for the component
415  *
416  * Returns:
417  *	DDI_SUCCESS		Power level changed, we always succeed
418  */
419 static int
420 audiocs_ddi_power(dev_info_t *dip, int component, int level)
421 {
422 	CS_state_t		*state;
423 
424 	if (component != CS4231_COMPONENT)
425 		return (DDI_FAILURE);
426 
427 	/* get the state structure */
428 	state = ddi_get_driver_private(dip);
429 
430 	ASSERT(!mutex_owned(&state->cs_lock));
431 
432 	/* make sure we have some work to do */
433 	mutex_enter(&state->cs_lock);
434 
435 	/*
436 	 * We don't do anything if we're suspended.  Suspend/resume diddles
437 	 * with power anyway.
438 	 */
439 	if (!state->cs_suspended) {
440 
441 		/* check the level change to see what we need to do */
442 		if (level == CS4231_PWR_OFF && state->cs_powered) {
443 
444 			/* power down and save the state */
445 			audiocs_power_down(state);
446 			state->cs_powered = B_FALSE;
447 
448 		} else if (level == CS4231_PWR_ON && !state->cs_powered) {
449 
450 			/* power up */
451 			audiocs_power_up(state);
452 			state->cs_powered = B_TRUE;
453 		}
454 	}
455 
456 	mutex_exit(&state->cs_lock);
457 
458 	ASSERT(!mutex_owned(&state->cs_lock));
459 
460 	return (DDI_SUCCESS);
461 }
462 
463 /* ******* Local Routines *************************************************** */
464 
465 static void
466 audiocs_destroy(CS_state_t *state)
467 {
468 	if (state == NULL)
469 		return;
470 
471 	/*
472 	 * Unregister any interrupts. That way we can't get called by and
473 	 * interrupt after the audio framework is removed.
474 	 */
475 	CS4231_DMA_REM_INTR(state);
476 
477 	for (int i = CS4231_PLAY; i <= CS4231_REC; i++) {
478 		audiocs_free_engine(state->cs_engines[i]);
479 	}
480 	audiocs_del_controls(state);
481 
482 	/* free the kernel statistics structure */
483 	if (state->cs_ksp) {
484 		kstat_delete(state->cs_ksp);
485 	}
486 
487 	if (state->cs_adev) {
488 		audio_dev_free(state->cs_adev);
489 	}
490 
491 	/* unmap the registers */
492 	CS4231_DMA_UNMAP_REGS(state);
493 
494 	/* destroy the state mutex */
495 	mutex_destroy(&state->cs_lock);
496 	kmem_free(state, sizeof (*state));
497 }
498 
499 /*
500  * audiocs_attach()
501  *
502  * Description:
503  *	Attach an instance of the CS4231 driver. This routine does the device
504  *	dependent attach tasks.  When it is complete it calls
505  *	audio_dev_register() to register with the framework.
506  *
507  * Arguments:
508  *	dev_info_t	*dip	Pointer to the device's dev_info struct
509  *
510  * Returns:
511  *	DDI_SUCCESS		The driver was initialized properly
512  *	DDI_FAILURE		The driver couldn't be initialized properly
513  */
514 static int
515 audiocs_attach(dev_info_t *dip)
516 {
517 	CS_state_t		*state;
518 	audio_dev_t		*adev;
519 
520 	/* allocate the state structure */
521 	state = kmem_zalloc(sizeof (*state), KM_SLEEP);
522 	state->cs_dip = dip;
523 	ddi_set_driver_private(dip, state);
524 
525 	/* get the iblock cookie needed for interrupt context */
526 	if (ddi_get_iblock_cookie(dip, 0, &state->cs_iblock) != DDI_SUCCESS) {
527 		audio_dev_warn(NULL, "cannot get iblock cookie");
528 		kmem_free(state, sizeof (*state));
529 		return (DDI_FAILURE);
530 	}
531 
532 	/* now fill it in, initialize the state mutexs first */
533 	mutex_init(&state->cs_lock, NULL, MUTEX_DRIVER, state->cs_iblock);
534 
535 	/*
536 	 * audio state initialization... should always succeed,
537 	 * framework will message failure.
538 	 */
539 	if ((state->cs_adev = audio_dev_alloc(dip, 0)) == NULL) {
540 		goto error;
541 	}
542 	adev = state->cs_adev;
543 	audio_dev_set_description(adev, CS_DEV_CONFIG_ONBRD1);
544 	audio_dev_add_info(adev, "Legacy codec: Crystal Semiconductor CS4231");
545 
546 	/* initialize the audio state structures */
547 	if ((audiocs_init_state(state)) == DDI_FAILURE) {
548 		audio_dev_warn(adev, "init_state() failed");
549 		goto error;
550 	}
551 
552 	mutex_enter(&state->cs_lock);
553 
554 	/* initialize the audio chip */
555 	if ((audiocs_chip_init(state)) == DDI_FAILURE) {
556 		mutex_exit(&state->cs_lock);
557 		audio_dev_warn(adev, "chip_init() failed");
558 		goto error;
559 	}
560 	/* chip init will have powered us up */
561 	state->cs_powered = B_TRUE;
562 
563 	/* set up kernel statistics */
564 	if ((state->cs_ksp = kstat_create(ddi_driver_name(dip),
565 	    ddi_get_instance(dip), ddi_driver_name(dip),
566 	    "controller", KSTAT_TYPE_INTR, 1, KSTAT_FLAG_PERSISTENT)) != NULL) {
567 		kstat_install(state->cs_ksp);
568 	}
569 
570 	/* we're ready, set up the interrupt handler */
571 	if (CS4231_DMA_ADD_INTR(state) != DDI_SUCCESS) {
572 		mutex_exit(&state->cs_lock);
573 		goto error;
574 	}
575 	mutex_exit(&state->cs_lock);
576 
577 	/* finally register with framework to kick everything off */
578 	if (audio_dev_register(state->cs_adev) != DDI_SUCCESS) {
579 		audio_dev_warn(state->cs_adev, "unable to register audio dev");
580 	}
581 
582 	/* everything worked out, so report the device */
583 	ddi_report_dev(dip);
584 
585 	return (DDI_SUCCESS);
586 
587 error:
588 	audiocs_destroy(state);
589 	return (DDI_FAILURE);
590 }
591 
592 /*
593  * audiocs_resume()
594  *
595  * Description:
596  *	Resume a suspended device instance.
597  *
598  * Arguments:
599  *	dev_info_t	*dip	Pointer to the device's dev_info struct
600  *
601  * Returns:
602  *	DDI_SUCCESS		The driver was initialized properly
603  *	DDI_FAILURE		The driver couldn't be initialized properly
604  */
605 static int
606 audiocs_resume(dev_info_t *dip)
607 {
608 	CS_state_t		*state;
609 	audio_dev_t		*adev;
610 
611 	/* we've already allocated the state structure so get ptr */
612 	state = ddi_get_driver_private(dip);
613 	adev = state->cs_adev;
614 
615 	ASSERT(dip == state->cs_dip);
616 	ASSERT(!mutex_owned(&state->cs_lock));
617 
618 	/* mark the Codec busy -- this should keep power(9e) away */
619 	(void) pm_busy_component(state->cs_dip, CS4231_COMPONENT);
620 
621 	/* power it up */
622 	audiocs_power_up(state);
623 	state->cs_powered = B_TRUE;
624 
625 	mutex_enter(&state->cs_lock);
626 
627 	/* initialize the audio chip */
628 	if ((audiocs_chip_init(state)) == DDI_FAILURE) {
629 		mutex_exit(&state->cs_lock);
630 		audio_dev_warn(adev, "chip_init() failed");
631 		(void) pm_idle_component(state->cs_dip, CS4231_COMPONENT);
632 		return (DDI_FAILURE);
633 	}
634 
635 	state->cs_suspended = B_FALSE;
636 
637 	for (int i = CS4231_PLAY; i <= CS4231_REC; i++) {
638 		CS_engine_t	*eng = state->cs_engines[i];
639 
640 		audiocs_reset_engine(eng);
641 		if (eng->ce_started) {
642 			(void) audiocs_start_engine(eng);
643 		} else {
644 			audiocs_stop_engine(eng);
645 		}
646 	}
647 	mutex_exit(&state->cs_lock);
648 
649 	/*
650 	 * We have already powered up the chip, but this alerts the
651 	 * framework to the fact.
652 	 */
653 	(void) pm_raise_power(dip, CS4231_COMPONENT, CS4231_PWR_ON);
654 	(void) pm_idle_component(state->cs_dip, CS4231_COMPONENT);
655 
656 	return (DDI_SUCCESS);
657 }
658 
659 /*
660  * audiocs_detach()
661  *
662  * Description:
663  *	Detach an instance of the CS4231 driver.
664  *
665  * Arguments:
666  *	dev_info_t	*dip	Pointer to the device's dev_info struct
667  *
668  * Returns:
669  *	DDI_SUCCESS		The driver was detached
670  *	DDI_FAILURE		The driver couldn't be detached (busy)
671  */
672 static int
673 audiocs_detach(dev_info_t *dip)
674 {
675 	CS_state_t		*state;
676 	audio_dev_t		*adev;
677 	ddi_acc_handle_t	handle;
678 
679 	/* get the state structure */
680 	state = ddi_get_driver_private(dip);
681 	handle = CODEC_HANDLE;
682 	adev = state->cs_adev;
683 
684 	/* don't detach if still in use */
685 	if (audio_dev_unregister(adev) != DDI_SUCCESS) {
686 		return (DDI_FAILURE);
687 	}
688 
689 	if (state->cs_powered) {
690 		/*
691 		 * Make sure the Codec and DMA engine are off.
692 		 */
693 		SELIDX(state, INTC_REG);
694 		ANDIDX(state, ~(INTC_PEN|INTC_CEN), INTC_VALID_MASK);
695 
696 		/* make sure the DMA engine isn't going to do anything */
697 		CS4231_DMA_RESET(state);
698 
699 		/*
700 		 * power down the device, no reason to waste power without
701 		 * a driver
702 		 */
703 		(void) pm_lower_power(dip, CS4231_COMPONENT, CS4231_PWR_OFF);
704 	}
705 
706 	audiocs_destroy(state);
707 
708 	return (DDI_SUCCESS);
709 }
710 
711 /*
712  * audiocs_suspend()
713  *
714  * Description:
715  *	Suspend an instance of the CS4231 driver.
716  *
717  * Arguments:
718  *	dev_info_t	*dip	Pointer to the device's dev_info struct
719  *
720  * Returns:
721  *	DDI_SUCCESS		The driver was detached
722  *	DDI_FAILURE		The driver couldn't be detached
723  */
724 static int
725 audiocs_suspend(dev_info_t *dip)
726 {
727 	CS_state_t		*state;
728 
729 	/* get the state structure */
730 	state = ddi_get_driver_private(dip);
731 
732 	ASSERT(!mutex_owned(&state->cs_lock));
733 
734 	mutex_enter(&state->cs_lock);
735 
736 	ASSERT(!state->cs_suspended);
737 
738 	if (state->cs_powered) {
739 		/* stop playing and recording */
740 		CS4231_DMA_STOP(state, state->cs_engines[CS4231_PLAY]);
741 		CS4231_DMA_STOP(state, state->cs_engines[CS4231_REC]);
742 
743 		/* now we can power down the Codec */
744 		audiocs_power_down(state);
745 		state->cs_powered = B_FALSE;
746 	}
747 	state->cs_suspended = B_TRUE;	/* stop new ops */
748 	mutex_exit(&state->cs_lock);
749 
750 	ASSERT(!mutex_owned(&state->cs_lock));
751 	return (DDI_SUCCESS);
752 }
753 
754 #define	PLAYCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_PLAY)
755 #define	RECCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC)
756 #define	MONCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_MONITOR)
757 #define	PCMVOL	(PLAYCTL | AUDIO_CTRL_FLAG_PCMVOL)
758 #define	MAINVOL	(PLAYCTL | AUDIO_CTRL_FLAG_MAINVOL)
759 #define	RECVOL	(RECCTL | AUDIO_CTRL_FLAG_RECVOL)
760 #define	MONVOL	(MONCTL | AUDIO_CTRL_FLAG_MONVOL)
761 
762 /*
763  * audiocs_alloc_ctrl
764  *
765  * Description:
766  *	Allocates a control structure for the audio mixer.
767  *
768  * Arguments:
769  *	CS_state_t	*state		Device soft state.
770  *	uint32_t	num		Control number to allocate.
771  *	uint64_t	val		Initial value.
772  *
773  * Returns:
774  *	Pointer to newly allocated CS_ctrl_t structure.
775  */
776 static CS_ctrl_t *
777 audiocs_alloc_ctrl(CS_state_t *state, uint32_t num, uint64_t val)
778 {
779 	audio_ctrl_desc_t	desc;
780 	audio_ctrl_wr_t		fn;
781 	CS_ctrl_t		*cc;
782 
783 	cc = kmem_zalloc(sizeof (*cc), KM_SLEEP);
784 	cc->cc_state = state;
785 	cc->cc_num = num;
786 
787 	bzero(&desc, sizeof (desc));
788 
789 	switch (num) {
790 	case CTL_VOLUME:
791 		desc.acd_name = AUDIO_CTRL_ID_VOLUME;
792 		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
793 		desc.acd_minvalue = 0;
794 		desc.acd_maxvalue = 100;
795 		desc.acd_flags = PCMVOL;
796 		fn = audiocs_set_ogain;
797 		break;
798 
799 	case CTL_IGAIN:
800 		desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
801 		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
802 		desc.acd_minvalue = 0;
803 		desc.acd_maxvalue = 100;
804 		desc.acd_flags = RECVOL;
805 		fn = audiocs_set_igain;
806 		break;
807 
808 	case CTL_MGAIN:
809 		desc.acd_name = AUDIO_CTRL_ID_MONGAIN;
810 		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
811 		desc.acd_minvalue = 0;
812 		desc.acd_maxvalue = 100;
813 		desc.acd_flags = MONVOL;
814 		fn = audiocs_set_mgain;
815 		break;
816 
817 	case CTL_INPUTS:
818 		desc.acd_name = AUDIO_CTRL_ID_RECSRC;
819 		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
820 		desc.acd_minvalue = state->cs_imask;
821 		desc.acd_maxvalue = state->cs_imask;
822 		desc.acd_flags = RECCTL;
823 		for (int i = 0; audiocs_inputs[i]; i++) {
824 			desc.acd_enum[i] = audiocs_inputs[i];
825 		}
826 		fn = audiocs_set_inputs;
827 
828 		break;
829 
830 	case CTL_OUTPUTS:
831 		desc.acd_name = AUDIO_CTRL_ID_OUTPUTS;
832 		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
833 		desc.acd_minvalue = state->cs_omod;
834 		desc.acd_maxvalue = state->cs_omask;
835 		desc.acd_flags = PLAYCTL | AUDIO_CTRL_FLAG_MULTI;
836 		for (int i = 0; audiocs_outputs[i]; i++) {
837 			desc.acd_enum[i] = audiocs_outputs[i];
838 		}
839 		fn = audiocs_set_outputs;
840 		break;
841 
842 	case CTL_MICBOOST:
843 		desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
844 		desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
845 		desc.acd_minvalue = 0;
846 		desc.acd_maxvalue = 1;
847 		desc.acd_flags = RECCTL;
848 		fn = audiocs_set_micboost;
849 		break;
850 	}
851 
852 	cc->cc_val = val;
853 	cc->cc_ctrl = audio_dev_add_control(state->cs_adev, &desc,
854 	    audiocs_get_value, fn, cc);
855 
856 	return (cc);
857 }
858 
859 /*
860  * audiocs_free_ctrl
861  *
862  * Description:
863  *	Frees a control and all resources associated with it.
864  *
865  * Arguments:
866  *	CS_ctrl_t	*cc	Pointer to control structure.
867  */
868 static void
869 audiocs_free_ctrl(CS_ctrl_t *cc)
870 {
871 	if (cc == NULL)
872 		return;
873 	if (cc->cc_ctrl)
874 		audio_dev_del_control(cc->cc_ctrl);
875 	kmem_free(cc, sizeof (*cc));
876 }
877 
878 /*
879  * audiocs_add_controls
880  *
881  * Description:
882  *	Allocates and registers all controls for this device.
883  *
884  * Arguments:
885  *	CS_state_t	*state		Device soft state.
886  *
887  * Returns:
888  *	DDI_SUCCESS	All controls added and registered
889  *	DDI_FAILURE	At least one control was not added or registered.
890  */
891 static int
892 audiocs_add_controls(CS_state_t *state)
893 {
894 #define	ADD_CTRL(CTL, ID, VAL)						\
895 	state->cs_##CTL = audiocs_alloc_ctrl(state, ID, VAL);		\
896 	if (state->cs_##CTL == NULL) {					\
897 		audio_dev_warn(state->cs_adev,				\
898 		    "unable to allocate %s control", #ID);		\
899 		return (DDI_FAILURE);					\
900 	}
901 
902 	ADD_CTRL(ogain, CTL_VOLUME, 0x4b4b);
903 	ADD_CTRL(igain, CTL_IGAIN, 0x3232);
904 	ADD_CTRL(mgain, CTL_MGAIN, 0);
905 	ADD_CTRL(micboost, CTL_MICBOOST, 0);
906 	ADD_CTRL(outputs, CTL_OUTPUTS, (state->cs_omask & ~state->cs_omod) |
907 	    (1U << OUTPUT_SPEAKER));
908 	ADD_CTRL(inputs, CTL_INPUTS, (1U << INPUT_MIC));
909 
910 	return (DDI_SUCCESS);
911 }
912 
913 /*
914  * audiocs_del_controls
915  *
916  * Description:
917  *	Unregisters and frees all controls for this device.
918  *
919  * Arguments:
920  *	CS_state_t	*state		Device soft state.
921  */
922 void
923 audiocs_del_controls(CS_state_t *state)
924 {
925 	audiocs_free_ctrl(state->cs_ogain);
926 	audiocs_free_ctrl(state->cs_igain);
927 	audiocs_free_ctrl(state->cs_mgain);
928 	audiocs_free_ctrl(state->cs_micboost);
929 	audiocs_free_ctrl(state->cs_inputs);
930 	audiocs_free_ctrl(state->cs_outputs);
931 }
932 
933 
934 /*
935  * audiocs_chip_init()
936  *
937  * Description:
938  *	Power up the audio core, initialize the audio Codec, prepare the chip
939  *	for use.
940  *
941  * Arguments:
942  *	CS_state_t	*state		The device's state structure
943  *
944  * Returns:
945  *	DDI_SUCCESS			Chip initialized and ready to use
946  *	DDI_FAILURE			Chip not initialized and not ready
947  */
948 static int
949 audiocs_chip_init(CS_state_t *state)
950 {
951 	ddi_acc_handle_t	handle = CODEC_HANDLE;
952 
953 	/* make sure we are powered up */
954 	CS4231_DMA_POWER(state, CS4231_PWR_ON);
955 
956 	CS4231_DMA_RESET(state);
957 
958 	/* wait for the Codec before we continue */
959 	if (audiocs_poll_ready(state) == DDI_FAILURE) {
960 		return (DDI_FAILURE);
961 	}
962 
963 	/* activate registers 16 -> 31 */
964 	SELIDX(state, MID_REG);
965 	ddi_put8(handle, &CS4231_IDR, MID_MODE2);
966 
967 	/* now figure out what version we have */
968 	SELIDX(state, VID_REG);
969 	if (ddi_get8(handle, &CS4231_IDR) & VID_A) {
970 		state->cs_revA = B_TRUE;
971 	} else {
972 		state->cs_revA = B_FALSE;
973 	}
974 
975 	/* get rid of annoying popping by muting the output channels */
976 	SELIDX(state, LDACO_REG);
977 	PUTIDX(state, LDACO_LDM | LDACO_MID_GAIN, LDAC0_VALID_MASK);
978 	SELIDX(state, RDACO_REG);
979 	PUTIDX(state, RDACO_RDM | RDACO_MID_GAIN, RDAC0_VALID_MASK);
980 
981 	/* initialize aux input channels to known gain values & muted */
982 	SELIDX(state, LAUX1_REG);
983 	PUTIDX(state, LAUX1_LX1M | LAUX1_UNITY_GAIN, LAUX1_VALID_MASK);
984 	SELIDX(state, RAUX1_REG);
985 	PUTIDX(state, RAUX1_RX1M | RAUX1_UNITY_GAIN, RAUX1_VALID_MASK);
986 	SELIDX(state, LAUX2_REG);
987 	PUTIDX(state, LAUX2_LX2M | LAUX2_UNITY_GAIN, LAUX2_VALID_MASK);
988 	SELIDX(state, RAUX2_REG);
989 	PUTIDX(state, RAUX2_RX2M | RAUX2_UNITY_GAIN, RAUX2_VALID_MASK);
990 
991 	/* initialize aux input channels to known gain values & muted */
992 	SELIDX(state, LLIC_REG);
993 	PUTIDX(state, LLIC_LLM | LLIC_UNITY_GAIN, LLIC_VALID_MASK);
994 	SELIDX(state, RLIC_REG);
995 	PUTIDX(state, RLIC_RLM | RLIC_UNITY_GAIN, RLIC_VALID_MASK);
996 
997 	/* program the sample rate, play and capture must be the same */
998 	SELIDX(state, FSDF_REG | IAR_MCE);
999 	PUTIDX(state, FS_48000 | PDF_LINEAR16NE | PDF_STEREO, FSDF_VALID_MASK);
1000 	if (audiocs_poll_ready(state) == DDI_FAILURE) {
1001 		return (DDI_FAILURE);
1002 	}
1003 
1004 	SELIDX(state, CDF_REG | IAR_MCE);
1005 	PUTIDX(state, CDF_LINEAR16NE | CDF_STEREO, CDF_VALID_MASK);
1006 	if (audiocs_poll_ready(state) == DDI_FAILURE) {
1007 		return (DDI_FAILURE);
1008 	}
1009 
1010 	/*
1011 	 * Set up the Codec for playback and capture disabled, dual DMA, and
1012 	 * playback and capture DMA.
1013 	 */
1014 	SELIDX(state, (INTC_REG | IAR_MCE));
1015 	PUTIDX(state, INTC_DDC | INTC_PDMA | INTC_CDMA, INTC_VALID_MASK);
1016 	if (audiocs_poll_ready(state) == DDI_FAILURE) {
1017 		return (DDI_FAILURE);
1018 	}
1019 
1020 	/*
1021 	 * Turn on the output level bit to be 2.8 Vpp. Also, don't go to 0 on
1022 	 * underflow.
1023 	 */
1024 	SELIDX(state, AFE1_REG);
1025 	PUTIDX(state, AFE1_OLB, AFE1_VALID_MASK);
1026 
1027 	/* turn on the high pass filter if Rev A */
1028 	SELIDX(state, AFE2_REG);
1029 	if (state->cs_revA) {
1030 		PUTIDX(state, AFE2_HPF, AFE2_VALID_MASK);
1031 	} else {
1032 		PUTIDX(state, 0, AFE2_VALID_MASK);
1033 	}
1034 
1035 	/* clear the play and capture interrupt flags */
1036 	SELIDX(state, AFS_REG);
1037 	ddi_put8(handle, &CS4231_STATUS, (AFS_RESET_STATUS));
1038 
1039 	/* the play and record gains will be set by the audio mixer */
1040 
1041 	/* unmute the output */
1042 	SELIDX(state, LDACO_REG);
1043 	ANDIDX(state, ~LDACO_LDM, LDAC0_VALID_MASK);
1044 	SELIDX(state, RDACO_REG);
1045 	ANDIDX(state, ~RDACO_RDM, RDAC0_VALID_MASK);
1046 
1047 	/* unmute the mono speaker and mute mono in */
1048 	SELIDX(state, MIOC_REG);
1049 	PUTIDX(state, MIOC_MIM, MIOC_VALID_MASK);
1050 
1051 	audiocs_configure_output(state);
1052 	audiocs_configure_input(state);
1053 
1054 	return (DDI_SUCCESS);
1055 }
1056 
1057 /*
1058  * audiocs_init_state()
1059  *
1060  * Description:
1061  *	This routine initializes the audio driver's state structure and
1062  *	maps in the registers. This also includes reading the properties.
1063  *
1064  *	CAUTION: This routine maps the registers and initializes a mutex.
1065  *		 Failure cleanup is handled by cs4231_attach(). It is not
1066  *		 handled locally by this routine.
1067  *
1068  * Arguments:
1069  *	CS_state_t	*state		The device's state structure
1070  *
1071  * Returns:
1072  *	DDI_SUCCESS			State structure initialized
1073  *	DDI_FAILURE			State structure not initialized
1074  */
1075 static int
1076 audiocs_init_state(CS_state_t *state)
1077 {
1078 	audio_dev_t	*adev = state->cs_adev;
1079 	dev_info_t	*dip = state->cs_dip;
1080 	char		*prop_str;
1081 	char		*pm_comp[] = {
1082 				"NAME=audiocs audio device",
1083 				"0=off",
1084 				"1=on" };
1085 
1086 	/* set up the pm-components */
1087 	if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
1088 	    "pm-components", pm_comp, 3) != DDI_PROP_SUCCESS) {
1089 		audio_dev_warn(adev, "couldn't create pm-components property");
1090 		return (DDI_FAILURE);
1091 	}
1092 
1093 	/* figure out which DMA engine hardware we have */
1094 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1095 	    "dma-model", &prop_str) == DDI_PROP_SUCCESS) {
1096 		if (strcmp(prop_str, "eb2dma") == 0) {
1097 			state->cs_dma_engine = EB2_DMA;
1098 			state->cs_dma_ops = &cs4231_eb2dma_ops;
1099 		} else {
1100 			state->cs_dma_engine = APC_DMA;
1101 			state->cs_dma_ops = &cs4231_apcdma_ops;
1102 		}
1103 		ddi_prop_free(prop_str);
1104 	} else {
1105 		state->cs_dma_engine = APC_DMA;
1106 		state->cs_dma_ops = &cs4231_apcdma_ops;
1107 	}
1108 
1109 	/* cs_regs, cs_eb2_regs and cs_handles filled in later */
1110 
1111 	/* most of what's left is filled in when the registers are mapped */
1112 
1113 	audiocs_get_ports(state);
1114 
1115 	/* Allocate engines, must be done before register mapping called  */
1116 	if ((audiocs_alloc_engine(state, CS4231_PLAY) != DDI_SUCCESS) ||
1117 	    (audiocs_alloc_engine(state, CS4231_REC) != DDI_SUCCESS)) {
1118 		return (DDI_FAILURE);
1119 	}
1120 
1121 	/* Map in the registers */
1122 	if (CS4231_DMA_MAP_REGS(state) == DDI_FAILURE) {
1123 		return (DDI_FAILURE);
1124 	}
1125 
1126 
1127 	/* Allocate and add controls, must be done *after* registers mapped */
1128 	if (audiocs_add_controls(state) != DDI_SUCCESS) {
1129 		return (DDI_FAILURE);
1130 	}
1131 
1132 	state->cs_suspended = B_FALSE;
1133 	state->cs_powered = B_FALSE;
1134 
1135 	return (DDI_SUCCESS);
1136 }
1137 
1138 /*
1139  * audiocs_get_ports()
1140  *
1141  * Description:
1142  *	Get which audiocs h/w version we have and use this to
1143  *	determine the input and output ports as well whether or not
1144  *	the hardware has internal loopbacks or not. We also have three
1145  *	different ways for the properties to be specified, which we
1146  *	also need to worry about.
1147  *
1148  * Vers	Platform(s)	DMA eng.	audio-module**	loopback
1149  * a    SS-4+/SS-5+	apcdma		no		no
1150  * b	Ultra-1&2	apcdma		no		yes
1151  * c	positron	apcdma		no		yes
1152  * d	PPC - retired
1153  * e	x86 - retired
1154  * f	tazmo		eb2dma		Perigee		no
1155  * g	tazmo		eb2dma		Quark		yes
1156  * h	darwin+		eb2dma		no		N/A
1157  *
1158  * Vers	model~		aux1*		aux2*
1159  * a	N/A		N/A		N/A
1160  * b	N/A		N/A		N/A
1161  * c	N/A		N/A		N/A
1162  * d	retired
1163  * e	retired
1164  * f	SUNW,CS4231f	N/A		N/A
1165  * g	SUNW,CS4231g	N/A		N/A
1166  * h	SUNW,CS4231h	cdrom		none
1167  *
1168  * *   = Replaces internal-loopback for latest property type, can be
1169  *	 set to "cdrom", "loopback", or "none".
1170  *
1171  * **  = For plugin audio modules only. Starting with darwin, this
1172  *	 property is replaces by the model property.
1173  *
1174  * ~   = Replaces audio-module.
1175  *
1176  * +   = Has the capability of having a cable run from the internal
1177  *	 CD-ROM to the audio device.
1178  *
1179  * N/A = Not applicable, the property wasn't created for early
1180  *	 platforms, or the property has been retired.
1181  *
1182  * NOTE: Older tazmo and quark machines don't have the model property.
1183  *
1184  * Arguments:
1185  *	CS_state_t	*state		The device's state structure
1186  */
1187 static void
1188 audiocs_get_ports(CS_state_t *state)
1189 {
1190 	dev_info_t	*dip = state->cs_dip;
1191 	audio_dev_t	*adev = state->cs_adev;
1192 	char		*prop_str;
1193 
1194 	/* First we set the common ports, etc. */
1195 	state->cs_omask = state->cs_omod =
1196 	    (1U << OUTPUT_SPEAKER) |
1197 	    (1U << OUTPUT_HEADPHONES) |
1198 	    (1U << OUTPUT_LINEOUT);
1199 	state->cs_imask =
1200 	    (1U << INPUT_MIC) |
1201 	    (1U << INPUT_LINEIN) |
1202 	    (1U << INPUT_STEREOMIX);
1203 
1204 	/* now we try the new "model" property */
1205 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1206 	    "model", &prop_str) == DDI_PROP_SUCCESS) {
1207 		if (strcmp(prop_str, "SUNW,CS4231h") == 0) {
1208 			/* darwin */
1209 			audio_dev_set_version(adev, CS_DEV_VERSION_H);
1210 			state->cs_imask |= (1U << INPUT_CD);
1211 			state->cs_omod = (1U << OUTPUT_SPEAKER);
1212 		} else if (strcmp(prop_str, "SUNW,CS4231g") == 0) {
1213 			/* quark audio module */
1214 			audio_dev_set_version(adev, CS_DEV_VERSION_G);
1215 			/*
1216 			 * NB: This could do SUNVTS LOOPBACK, but we
1217 			 * don't support it for now... owing to no
1218 			 * support in framework.
1219 			 */
1220 		} else if (strcmp(prop_str, "SUNW,CS4231f") == 0) {
1221 			/* tazmo */
1222 			audio_dev_set_version(adev, CS_DEV_VERSION_F);
1223 		} else {
1224 			audio_dev_set_version(adev, prop_str);
1225 			audio_dev_warn(adev,
1226 			    "unknown audio model: %s, some parts of "
1227 			    "audio may not work correctly", prop_str);
1228 		}
1229 		ddi_prop_free(prop_str);	/* done with the property */
1230 	} else {	/* now try the older "audio-module" property */
1231 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
1232 		    DDI_PROP_DONTPASS, "audio-module", &prop_str) ==
1233 		    DDI_PROP_SUCCESS) {
1234 			switch (*prop_str) {
1235 			case 'Q':	/* quark audio module */
1236 				audio_dev_set_version(adev, CS_DEV_VERSION_G);
1237 				/* See quark comment above about SunVTS */
1238 				break;
1239 			case 'P':	/* tazmo */
1240 				audio_dev_set_version(adev, CS_DEV_VERSION_F);
1241 				break;
1242 			default:
1243 				audio_dev_set_version(adev, prop_str);
1244 				audio_dev_warn(adev,
1245 				    "unknown audio module: %s, some "
1246 				    "parts of audio may not work correctly",
1247 				    prop_str);
1248 				break;
1249 			}
1250 			ddi_prop_free(prop_str);	/* done with the prop */
1251 		} else {	/* now try heuristics, ;-( */
1252 			if (ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1253 			    DDI_PROP_DONTPASS, "internal-loopback", B_FALSE)) {
1254 				if (state->cs_dma_engine == EB2_DMA) {
1255 					audio_dev_set_version(adev,
1256 					    CS_DEV_VERSION_C);
1257 				} else {
1258 					audio_dev_set_version(adev,
1259 					    CS_DEV_VERSION_B);
1260 				}
1261 				/*
1262 				 * Again, we don't support SunVTS for these
1263 				 * boards, although we potentially could.
1264 				 */
1265 			} else {
1266 				audio_dev_set_version(adev, CS_DEV_VERSION_A);
1267 				state->cs_imask |= (1U << INPUT_CD);
1268 			}
1269 		}
1270 	}
1271 }
1272 
1273 /*
1274  * audiocs_power_up()
1275  *
1276  * Description:
1277  *	Power up the Codec and restore the codec's registers.
1278  *
1279  *	NOTE: We don't worry about locking since the only routines
1280  *		that may call us are attach() and power() Both of
1281  *		which should be the only threads in the driver.
1282  *
1283  * Arguments:
1284  *	CS_state_t	*state		The device's state structure
1285  */
1286 static void
1287 audiocs_power_up(CS_state_t *state)
1288 {
1289 	ddi_acc_handle_t	handle = CODEC_HANDLE;
1290 	int			i;
1291 
1292 	/* turn on the Codec */
1293 	CS4231_DMA_POWER(state, CS4231_PWR_ON);
1294 
1295 	/* reset the DMA engine(s) */
1296 	CS4231_DMA_RESET(state);
1297 
1298 	(void) audiocs_poll_ready(state);
1299 
1300 	/*
1301 	 * Reload the Codec's registers, the DMA engines will be
1302 	 * taken care of when play and record start up again. But
1303 	 * first enable registers 16 -> 31.
1304 	 */
1305 	SELIDX(state, MID_REG);
1306 	PUTIDX(state, state->cs_save[MID_REG], MID_VALID_MASK);
1307 
1308 	for (i = 0; i < CS4231_REGS; i++) {
1309 		/* restore Codec registers */
1310 		SELIDX(state, (i | IAR_MCE));
1311 		ddi_put8(handle, &CS4231_IDR, state->cs_save[i]);
1312 		(void) audiocs_poll_ready(state);
1313 	}
1314 	/* clear MCE bit */
1315 	SELIDX(state, 0);
1316 }
1317 
1318 /*
1319  * audiocs_power_down()
1320  *
1321  * Description:
1322  *	Power down the Codec and save the codec's registers.
1323  *
1324  *	NOTE: See the note in cs4231_power_up() about locking.
1325  *
1326  * Arguments:
1327  *	CS_state_t	*state		The device's state structure
1328  */
1329 static void
1330 audiocs_power_down(CS_state_t *state)
1331 {
1332 	ddi_acc_handle_t	handle;
1333 	int			i;
1334 
1335 	handle = state->cs_handles.cs_codec_hndl;
1336 
1337 	/*
1338 	 * We are powering down, so we don't need to do a thing with
1339 	 * the DMA engines. However, we do need to save the Codec
1340 	 * registers.
1341 	 */
1342 
1343 	for (i = 0; i < CS4231_REGS; i++) {
1344 		/* save Codec regs */
1345 		SELIDX(state, i);
1346 		state->cs_save[i] = ddi_get8(handle, &CS4231_IDR);
1347 	}
1348 
1349 	/* turn off the Codec */
1350 	CS4231_DMA_POWER(state, CS4231_PWR_OFF);
1351 
1352 }	/* cs4231_power_down() */
1353 
1354 /*
1355  * audiocs_configure_input()
1356  *
1357  * Description:
1358  *	Configure input properties of the mixer (e.g. igain, ports).
1359  *
1360  * Arguments:
1361  *	CS_state_t	*state		The device's state structure
1362  */
1363 static void
1364 audiocs_configure_input(CS_state_t *state)
1365 {
1366 	uint8_t		l, r;
1367 	uint64_t	inputs;
1368 	uint64_t	micboost;
1369 
1370 	ASSERT(mutex_owned(&state->cs_lock));
1371 
1372 	if (state->cs_suspended)
1373 		return;
1374 
1375 	inputs = state->cs_inputs->cc_val;
1376 	micboost = state->cs_micboost->cc_val;
1377 	r = (state->cs_igain->cc_val & 0xff);
1378 	l = ((state->cs_igain->cc_val & 0xff00) >> 8);
1379 
1380 	/* rescale these for our atten array */
1381 	l = (((uint32_t)l * 255) / 100) & 0xff;
1382 	r = (((uint32_t)r * 255) / 100) & 0xff;
1383 
1384 	/* we downshift by 4 bits -- igain only has 16 possible values */
1385 	/* NB: that we do not scale here!  The SADA driver didn't do so. */
1386 	l = l >> 4;
1387 	r = r >> 4;
1388 
1389 	if (inputs & (1U << INPUT_MIC)) {
1390 		l |= LADCI_LMIC;
1391 		r |= RADCI_RMIC;
1392 	}
1393 	if (inputs & (1U << INPUT_LINEIN)) {
1394 		l |= LADCI_LLINE;
1395 		r |= RADCI_RLINE;
1396 	}
1397 	if (inputs & (1U << INPUT_CD)) {
1398 		/* note that SunVTS also uses this */
1399 		l |= LADCI_LAUX1;
1400 		r |= RADCI_RAUX1;
1401 	}
1402 	if (inputs & (1U << INPUT_STEREOMIX)) {
1403 		l |= LADCI_LLOOP;
1404 		r |= RADCI_RLOOP;
1405 	}
1406 	if (micboost) {
1407 		l |= LADCI_LMGE;
1408 		r |= RADCI_RMGE;
1409 	}
1410 
1411 	SELIDX(state, LADCI_REG);
1412 	PUTIDX(state, l, LADCI_VALID_MASK);
1413 
1414 	SELIDX(state, RADCI_REG);
1415 	PUTIDX(state, r, RADCI_VALID_MASK);
1416 }
1417 
1418 /*
1419  * audiocs_configure_output()
1420  *
1421  * Description:
1422  *	Configure output properties of the mixer (e.g. ogain, mgain).
1423  *
1424  * Arguments:
1425  *	CS_state_t	*state		The device's state structure
1426  */
1427 static void
1428 audiocs_configure_output(CS_state_t *state)
1429 {
1430 	uint64_t		outputs;
1431 	uint8_t			l, r;
1432 	uint8_t			rmute, lmute;
1433 	uint8_t			mgain;
1434 	ddi_acc_handle_t	handle = CODEC_HANDLE;
1435 
1436 	rmute = lmute = 0;
1437 
1438 	ASSERT(mutex_owned(&state->cs_lock));
1439 
1440 	if (state->cs_suspended)
1441 		return;
1442 
1443 	outputs = state->cs_outputs->cc_val;
1444 
1445 	/* port selection */
1446 	SELIDX(state, MIOC_REG);
1447 	if (outputs & (1U << OUTPUT_SPEAKER)) {
1448 		ANDIDX(state, ~MIOC_MONO_SPKR_MUTE, MIOC_VALID_MASK);
1449 	} else {
1450 		ORIDX(state, MIOC_MONO_SPKR_MUTE, MIOC_VALID_MASK);
1451 	}
1452 	SELIDX(state, PC_REG);
1453 	if (outputs & (1U << OUTPUT_HEADPHONES)) {
1454 		ANDIDX(state, ~PC_HEADPHONE_MUTE, PC_VALID_MASK);
1455 	} else {
1456 		ORIDX(state, PC_HEADPHONE_MUTE, PC_VALID_MASK);
1457 	}
1458 	SELIDX(state, PC_REG);
1459 	if (outputs & (1U << OUTPUT_LINEOUT)) {
1460 		ANDIDX(state, ~PC_LINE_OUT_MUTE, PC_VALID_MASK);
1461 	} else {
1462 		ORIDX(state, PC_LINE_OUT_MUTE, PC_VALID_MASK);
1463 	}
1464 
1465 	/* monitor gain */
1466 	mgain = cs4231_atten[((state->cs_mgain->cc_val * 255) / 100) & 0xff];
1467 	SELIDX(state, LC_REG);
1468 	if (mgain == 0) {
1469 		/* disable loopbacks when gain == 0 */
1470 		PUTIDX(state, LC_OFF, LC_VALID_MASK);
1471 	} else {
1472 		/* we use cs4231_atten[] to linearize attenuation */
1473 		PUTIDX(state, (mgain << 2) | LC_LBE, LC_VALID_MASK);
1474 	}
1475 
1476 	/* output gain */
1477 	l = ((state->cs_ogain->cc_val >> 8) & 0xff);
1478 	r = (state->cs_ogain->cc_val & 0xff);
1479 	if (l == 0) {
1480 		lmute = LDACO_LDM;
1481 	}
1482 	if (r == 0) {
1483 		rmute = RDACO_RDM;
1484 	}
1485 
1486 	/* rescale these for our atten array */
1487 	l = cs4231_atten[(((uint32_t)l * 255) / 100) & 0xff] | lmute;
1488 	r = cs4231_atten[(((uint32_t)r * 255) / 100) & 0xff] | rmute;
1489 
1490 	SELIDX(state, LDACO_REG);
1491 	PUTIDX(state, l, LDAC0_VALID_MASK);
1492 	SELIDX(state, RDACO_REG);
1493 	PUTIDX(state, r, RDAC0_VALID_MASK);
1494 }
1495 
1496 /*
1497  * audiocs_get_value()
1498  *
1499  * Description:
1500  *	Get a control value
1501  *
1502  * Arguments:
1503  *	void		*arg		The device's state structure
1504  *	uint64_t	*valp		Pointer to store value.
1505  *
1506  * Returns:
1507  *	0		The Codec parameter has been retrieved.
1508  */
1509 static int
1510 audiocs_get_value(void *arg, uint64_t *valp)
1511 {
1512 	CS_ctrl_t		*cc = arg;
1513 	CS_state_t		*state = cc->cc_state;
1514 
1515 	mutex_enter(&state->cs_lock);
1516 	*valp = cc->cc_val;
1517 	mutex_exit(&state->cs_lock);
1518 	return (0);
1519 }
1520 
1521 
1522 /*
1523  * audiocs_set_ogain()
1524  *
1525  * Description:
1526  *	Set the play gain.
1527  *
1528  * Arguments:
1529  *	void		*arg		The device's state structure
1530  *	uint64_t	val		The gain to set (both left and right)
1531  *
1532  * Returns:
1533  *	0		The Codec parameter has been set
1534  */
1535 static int
1536 audiocs_set_ogain(void *arg, uint64_t val)
1537 {
1538 	CS_ctrl_t		*cc = arg;
1539 	CS_state_t		*state = cc->cc_state;
1540 
1541 	if ((val & ~0xffff) ||
1542 	    ((val & 0xff) > 100) ||
1543 	    (((val & 0xff00) >> 8) > 100))
1544 		return (EINVAL);
1545 
1546 	mutex_enter(&state->cs_lock);
1547 	cc->cc_val = val;
1548 	audiocs_configure_output(state);
1549 	mutex_exit(&state->cs_lock);
1550 	return (0);
1551 }
1552 
1553 /*
1554  * audiocs_set_micboost()
1555  *
1556  * Description:
1557  *	Set the 20 dB microphone boost.
1558  *
1559  * Arguments:
1560  *	void		*arg		The device's state structure
1561  *	uint64_t	val		The 1 to enable, 0 to disable.
1562  *
1563  * Returns:
1564  *	0		The Codec parameter has been set
1565  */
1566 static int
1567 audiocs_set_micboost(void *arg, uint64_t val)
1568 {
1569 	CS_ctrl_t	*cc = arg;
1570 	CS_state_t	*state = cc->cc_state;
1571 
1572 	mutex_enter(&state->cs_lock);
1573 	cc->cc_val = val ? B_TRUE : B_FALSE;
1574 	audiocs_configure_input(state);
1575 	mutex_exit(&state->cs_lock);
1576 	return (0);
1577 }
1578 
1579 /*
1580  * audiocs_set_igain()
1581  *
1582  * Description:
1583  *	Set the record gain.
1584  *
1585  * Arguments:
1586  *	void		*arg		The device's state structure
1587  *	uint64_t	val		The gain to set (both left and right)
1588  *
1589  * Returns:
1590  *	0		The Codec parameter has been set
1591  */
1592 static int
1593 audiocs_set_igain(void *arg, uint64_t val)
1594 {
1595 	CS_ctrl_t	*cc = arg;
1596 	CS_state_t	*state = cc->cc_state;
1597 
1598 	if ((val & ~0xffff) ||
1599 	    ((val & 0xff) > 100) ||
1600 	    (((val & 0xff00) >> 8) > 100))
1601 		return (EINVAL);
1602 
1603 	mutex_enter(&state->cs_lock);
1604 	cc->cc_val = val;
1605 	audiocs_configure_input(state);
1606 	mutex_exit(&state->cs_lock);
1607 
1608 	return (0);
1609 }
1610 
1611 /*
1612  * audiocs_set_inputs()
1613  *
1614  * Description:
1615  *	Set the input ports.
1616  *
1617  * Arguments:
1618  *	void		*arg		The device's state structure
1619  *	uint64_t	val		The mask of output ports.
1620  *
1621  * Returns:
1622  *	0		The Codec parameter has been set
1623  */
1624 static int
1625 audiocs_set_inputs(void *arg, uint64_t val)
1626 {
1627 	CS_ctrl_t	*cc = arg;
1628 	CS_state_t	*state = cc->cc_state;
1629 
1630 	if (val & ~(state->cs_imask))
1631 		return (EINVAL);
1632 
1633 	mutex_enter(&state->cs_lock);
1634 	cc->cc_val = val;
1635 	audiocs_configure_input(state);
1636 	mutex_exit(&state->cs_lock);
1637 
1638 	return (0);
1639 }
1640 
1641 /*
1642  * audiocs_set_outputs()
1643  *
1644  * Description:
1645  *	Set the output ports.
1646  *
1647  * Arguments:
1648  *	void		*arg		The device's state structure
1649  *	uint64_t	val		The mask of input ports.
1650  *
1651  * Returns:
1652  *	0		The Codec parameter has been set
1653  */
1654 static int
1655 audiocs_set_outputs(void *arg, uint64_t val)
1656 {
1657 	CS_ctrl_t	*cc = arg;
1658 	CS_state_t	*state = cc->cc_state;
1659 
1660 	if ((val & ~(state->cs_omod)) !=
1661 	    (state->cs_omask & ~state->cs_omod))
1662 		return (EINVAL);
1663 
1664 	mutex_enter(&state->cs_lock);
1665 	cc->cc_val = val;
1666 	audiocs_configure_output(state);
1667 	mutex_exit(&state->cs_lock);
1668 
1669 	return (0);
1670 }
1671 
1672 /*
1673  * audiocs_set_mgain()
1674  *
1675  * Description:
1676  *	Set the monitor gain.
1677  *
1678  * Arguments:
1679  *	void		*arg		The device's state structure
1680  *	uint64_t	val		The gain to set (monoaural).)
1681  *
1682  * Returns:
1683  *	0		The Codec parameter has been set
1684  */
1685 static int
1686 audiocs_set_mgain(void *arg, uint64_t gain)
1687 {
1688 	CS_ctrl_t	*cc = arg;
1689 	CS_state_t	*state = cc->cc_state;
1690 
1691 	if (gain > 100)
1692 		return (EINVAL);
1693 
1694 	mutex_enter(&state->cs_lock);
1695 	cc->cc_val = gain;
1696 	audiocs_configure_output(state);
1697 	mutex_exit(&state->cs_lock);
1698 
1699 	return (0);
1700 }
1701 
1702 /*
1703  * audiocs_open()
1704  *
1705  * Description:
1706  *	Opens a DMA engine for use.
1707  *
1708  * Arguments:
1709  *	void		*arg		The DMA engine to set up
1710  *	int		flag		Open flags
1711  *	unsigned	*fragfrp	Receives number of frames per fragment
1712  *	unsigned	*nfragsp	Receives number of fragments
1713  *	caddr_t		*bufp		Receives kernel data buffer
1714  *
1715  * Returns:
1716  *	0	on success
1717  *	errno	on failure
1718  */
1719 static int
1720 audiocs_open(void *arg, int flag,
1721     unsigned *fragfrp, unsigned *nfragsp, caddr_t *bufp)
1722 {
1723 	CS_engine_t	*eng = arg;
1724 	CS_state_t	*state = eng->ce_state;
1725 	dev_info_t	*dip = state->cs_dip;
1726 
1727 	_NOTE(ARGUNUSED(flag));
1728 
1729 	(void) pm_busy_component(dip, CS4231_COMPONENT);
1730 	if (pm_raise_power(dip, CS4231_COMPONENT, CS4231_PWR_ON) ==
1731 	    DDI_FAILURE) {
1732 
1733 		/* match the busy call above */
1734 		(void) pm_idle_component(dip, CS4231_COMPONENT);
1735 
1736 		audio_dev_warn(state->cs_adev, "power up failed");
1737 	}
1738 
1739 	eng->ce_started = B_FALSE;
1740 	eng->ce_count = 0;
1741 
1742 	*fragfrp = eng->ce_fragfr;
1743 	*nfragsp = CS4231_NFRAGS;
1744 	*bufp = eng->ce_kaddr;
1745 
1746 	mutex_enter(&state->cs_lock);
1747 	audiocs_reset_engine(eng);
1748 	mutex_exit(&state->cs_lock);
1749 	return (0);
1750 }
1751 
1752 /*
1753  * audiocs_close()
1754  *
1755  * Description:
1756  *	Closes an audio DMA engine that was previously opened.  Since
1757  *	nobody is using it, we take this opportunity to possibly power
1758  *	down the entire device.
1759  *
1760  * Arguments:
1761  *	void	*arg		The DMA engine to shut down
1762  */
1763 static void
1764 audiocs_close(void *arg)
1765 {
1766 	CS_engine_t	*eng = arg;
1767 	CS_state_t	*state = eng->ce_state;
1768 
1769 	mutex_enter(&state->cs_lock);
1770 	audiocs_stop_engine(eng);
1771 	eng->ce_started = B_FALSE;
1772 	mutex_exit(&state->cs_lock);
1773 
1774 	(void) pm_idle_component(state->cs_dip, CS4231_COMPONENT);
1775 }
1776 
1777 /*
1778  * audiocs_stop()
1779  *
1780  * Description:
1781  *	This is called by the framework to stop an engine that is
1782  *	transferring data.
1783  *
1784  * Arguments:
1785  *	void	*arg		The DMA engine to stop
1786  */
1787 static void
1788 audiocs_stop(void *arg)
1789 {
1790 	CS_engine_t	*eng = arg;
1791 	CS_state_t	*state = eng->ce_state;
1792 
1793 	mutex_enter(&state->cs_lock);
1794 	if (eng->ce_started) {
1795 		audiocs_stop_engine(eng);
1796 		eng->ce_started = B_FALSE;
1797 	}
1798 	mutex_exit(&state->cs_lock);
1799 }
1800 
1801 /*
1802  * audiocs_start()
1803  *
1804  * Description:
1805  *	This is called by the framework to start an engine transferring data.
1806  *
1807  * Arguments:
1808  *	void	*arg		The DMA engine to start
1809  *
1810  * Returns:
1811  *	0 	on success, an errno otherwise
1812  */
1813 static int
1814 audiocs_start(void *arg)
1815 {
1816 	CS_engine_t	*eng = arg;
1817 	CS_state_t	*state = eng->ce_state;
1818 	int		rv = 0;
1819 
1820 	mutex_enter(&state->cs_lock);
1821 	if (!eng->ce_started) {
1822 		if (audiocs_start_engine(eng) == DDI_SUCCESS) {
1823 			eng->ce_started = B_TRUE;
1824 		} else {
1825 			rv = EIO;
1826 		}
1827 	}
1828 	mutex_exit(&state->cs_lock);
1829 	return (rv);
1830 }
1831 
1832 /*
1833  * audiocs_format()
1834  *
1835  * Description:
1836  *	Called by the framework to query the format of the device.
1837  *
1838  * Arguments:
1839  *	void	*arg		The DMA engine to query
1840  *
1841  * Returns:
1842  *	AUDIO_FORMAT_S16_NE
1843  */
1844 static int
1845 audiocs_format(void *arg)
1846 {
1847 	_NOTE(ARGUNUSED(arg));
1848 
1849 	return (AUDIO_FORMAT_S16_NE);
1850 }
1851 
1852 /*
1853  * audiocs_channels()
1854  *
1855  * Description:
1856  *	Called by the framework to query the channels of the device.
1857  *
1858  * Arguments:
1859  *	void	*arg		The DMA engine to query
1860  *
1861  * Returns:
1862  *	2 (stereo)
1863  */
1864 static int
1865 audiocs_channels(void *arg)
1866 {
1867 	_NOTE(ARGUNUSED(arg));
1868 
1869 	return (2);
1870 }
1871 
1872 /*
1873  * audiocs_rates()
1874  *
1875  * Description:
1876  *	Called by the framework to query the sample rate of the device.
1877  *
1878  * Arguments:
1879  *	void	*arg		The DMA engine to query
1880  *
1881  * Returns:
1882  *	48000
1883  */
1884 static int
1885 audiocs_rate(void *arg)
1886 {
1887 	_NOTE(ARGUNUSED(arg));
1888 
1889 	return (48000);
1890 }
1891 
1892 /*
1893  * audiocs_count()
1894  *
1895  * Description:
1896  *	This is called by the framework to get the engine's frame counter
1897  *
1898  * Arguments:
1899  *	void	*arg		The DMA engine to query
1900  *
1901  * Returns:
1902  *	frame count for current engine
1903  */
1904 static uint64_t
1905 audiocs_count(void *arg)
1906 {
1907 	CS_engine_t	*eng = arg;
1908 	CS_state_t	*state = eng->ce_state;
1909 	uint64_t	val;
1910 
1911 	mutex_enter(&state->cs_lock);
1912 	val = eng->ce_count;
1913 	mutex_exit(&state->cs_lock);
1914 
1915 	return (val);
1916 }
1917 
1918 /*
1919  * audiocs_sync()
1920  *
1921  * Description:
1922  *	This is called by the framework to synchronize DMA caches.
1923  *
1924  * Arguments:
1925  *	void	*arg		The DMA engine to sync
1926  */
1927 static void
1928 audiocs_sync(void *arg, unsigned nframes)
1929 {
1930 	CS_engine_t *eng = arg;
1931 	_NOTE(ARGUNUSED(nframes));
1932 
1933 	(void) ddi_dma_sync(eng->ce_dmah, 0, 0, eng->ce_syncdir);
1934 }
1935 
1936 /*
1937  * audiocs_qlen()
1938  *
1939  * Description:
1940  *	This is called by the framework to determine on-device queue length.
1941  *
1942  * Arguments:
1943  *	void	*arg		The DMA engine to query
1944  *
1945  * Returns:
1946  *	hardware queue length not reported by count (0 for this device)
1947  */
1948 static size_t
1949 audiocs_qlen(void *arg)
1950 {
1951 	CS_engine_t	*eng = arg;
1952 
1953 	return (eng->ce_fragfr);
1954 }
1955 
1956 
1957 /*
1958  * audiocs_reset_engine()
1959  *
1960  * Description:
1961  *	This routine resets the DMA engine pareparing it for work.
1962  *
1963  * Arguments:
1964  *	CS_engine_t	*engine		DMA engine to stop.
1965  */
1966 void
1967 audiocs_reset_engine(CS_engine_t *eng)
1968 {
1969 	CS_state_t	*state = eng->ce_state;
1970 	uint8_t		mask;
1971 	uint8_t		value;
1972 	uint8_t		reg;
1973 
1974 	if (eng->ce_num == CS4231_PLAY) {
1975 		/* sample rate only set on play side */
1976 		value = FS_48000 | PDF_STEREO | PDF_LINEAR16NE;
1977 		reg = FSDF_REG;
1978 		mask = FSDF_VALID_MASK;
1979 	} else {
1980 		value = CDF_STEREO | CDF_LINEAR16NE;
1981 		reg = CDF_REG;
1982 		mask = CDF_VALID_MASK;
1983 	}
1984 
1985 	SELIDX(state, reg | IAR_MCE);
1986 	PUTIDX(state, value, mask);
1987 
1988 	(void) audiocs_poll_ready(state);
1989 }
1990 
1991 /*
1992  * audiocs_alloc_engine()
1993  *
1994  * Description:
1995  *	Allocates the DMA handles and the memory for the DMA engine.
1996  *
1997  * Arguments:
1998  *	CS_state_t	*dip	Pointer to the device's soft state
1999  *	int		num	Engine number, CS4231_PLAY or CS4231_REC.
2000  *
2001  * Returns:
2002  *	DDI_SUCCESS		Engine initialized.
2003  *	DDI_FAILURE		Engine not initialized.
2004  */
2005 int
2006 audiocs_alloc_engine(CS_state_t *state, int num)
2007 {
2008 	char			*prop;
2009 	unsigned		caps;
2010 	int			dir;
2011 	int			rc;
2012 	audio_dev_t		*adev;
2013 	dev_info_t		*dip;
2014 	CS_engine_t		*eng;
2015 	uint_t			ccnt;
2016 	ddi_dma_cookie_t	dmac;
2017 
2018 	static ddi_device_acc_attr_t buf_attr = {
2019 		DDI_DEVICE_ATTR_V0,
2020 		DDI_NEVERSWAP_ACC,
2021 		DDI_STRICTORDER_ACC
2022 	};
2023 
2024 	adev = state->cs_adev;
2025 	dip = state->cs_dip;
2026 
2027 	eng = kmem_zalloc(sizeof (*eng), KM_SLEEP);
2028 	eng->ce_state = state;
2029 	eng->ce_started = B_FALSE;
2030 	eng->ce_num = num;
2031 
2032 	switch (num) {
2033 	case CS4231_REC:
2034 		prop = "record-interrupts";
2035 		dir = DDI_DMA_READ;
2036 		caps = ENGINE_INPUT_CAP;
2037 		eng->ce_syncdir = DDI_DMA_SYNC_FORKERNEL;
2038 		eng->ce_codec_en = INTC_CEN;
2039 		break;
2040 	case CS4231_PLAY:
2041 		prop = "play-interrupts";
2042 		dir = DDI_DMA_WRITE;
2043 		caps = ENGINE_OUTPUT_CAP;
2044 		eng->ce_syncdir = DDI_DMA_SYNC_FORDEV;
2045 		eng->ce_codec_en = INTC_PEN;
2046 		break;
2047 	default:
2048 		kmem_free(eng, sizeof (*eng));
2049 		audio_dev_warn(adev, "bad engine number (%d)!", num);
2050 		return (DDI_FAILURE);
2051 	}
2052 	state->cs_engines[num] = eng;
2053 
2054 	eng->ce_intrs = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2055 	    DDI_PROP_DONTPASS, prop, CS4231_INTS);
2056 
2057 	/* make sure the values are good */
2058 	if (eng->ce_intrs < CS4231_MIN_INTS) {
2059 		audio_dev_warn(adev, "%s too low, %d, resetting to %d",
2060 		    prop, eng->ce_intrs, CS4231_INTS);
2061 		eng->ce_intrs = CS4231_INTS;
2062 	} else if (eng->ce_intrs > CS4231_MAX_INTS) {
2063 		audio_dev_warn(adev, "%s too high, %d, resetting to %d",
2064 		    prop, eng->ce_intrs, CS4231_INTS);
2065 		eng->ce_intrs = CS4231_INTS;
2066 	}
2067 
2068 	/*
2069 	 * Figure out how much space we need.  Sample rate is 48kHz, and
2070 	 * we need to store 8 chunks.  (Note that this means that low
2071 	 * interrupt frequencies will require more RAM.  We could probably
2072 	 * do some cleverness to use a more dynamic list.)
2073 	 */
2074 	eng->ce_fragfr = 48000 / eng->ce_intrs;
2075 	eng->ce_fragfr &= ~(64 - 1);	/* align @ 64B boundaries */
2076 	eng->ce_fragfr = max(eng->ce_fragfr, 64);
2077 	eng->ce_fragsz = eng->ce_fragfr * 4;	/* each frame is 4 bytes */
2078 	eng->ce_size = eng->ce_fragsz * CS4231_NFRAGS;
2079 
2080 	/* allocate dma handle */
2081 	rc = ddi_dma_alloc_handle(dip, CS4231_DMA_ATTR(state), DDI_DMA_SLEEP,
2082 	    NULL, &eng->ce_dmah);
2083 	if (rc != DDI_SUCCESS) {
2084 		audio_dev_warn(adev, "ddi_dma_alloc_handle failed: %d", rc);
2085 		return (DDI_FAILURE);
2086 	}
2087 	/* allocate DMA buffer */
2088 	rc = ddi_dma_mem_alloc(eng->ce_dmah, eng->ce_size, &buf_attr,
2089 	    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &eng->ce_kaddr,
2090 	    &eng->ce_size, &eng->ce_acch);
2091 	if (rc == DDI_FAILURE) {
2092 		audio_dev_warn(adev, "dma_mem_alloc failed");
2093 		return (DDI_FAILURE);
2094 	}
2095 
2096 	/* bind DMA buffer */
2097 	rc = ddi_dma_addr_bind_handle(eng->ce_dmah, NULL,
2098 	    eng->ce_kaddr, eng->ce_size, dir | DDI_DMA_CONSISTENT,
2099 	    DDI_DMA_SLEEP, NULL, &dmac, &ccnt);
2100 	if ((rc != DDI_DMA_MAPPED) || (ccnt != 1)) {
2101 		audio_dev_warn(adev,
2102 		    "ddi_dma_addr_bind_handle failed: %d", rc);
2103 		return (DDI_FAILURE);
2104 	}
2105 
2106 	/* save off phys addresses for each frag */
2107 	for (int i = 0; i < CS4231_NFRAGS; i++) {
2108 		eng->ce_paddr[i] = dmac.dmac_address;
2109 		dmac.dmac_address += eng->ce_fragsz;
2110 	}
2111 
2112 	eng->ce_engine = audio_engine_alloc(&audiocs_engine_ops, caps);
2113 	if (eng->ce_engine == NULL) {
2114 		audio_dev_warn(adev, "audio_engine_alloc failed");
2115 		return (DDI_FAILURE);
2116 	}
2117 
2118 	audio_engine_set_private(eng->ce_engine, eng);
2119 	audio_dev_add_engine(adev, eng->ce_engine);
2120 	return (DDI_SUCCESS);
2121 }
2122 
2123 /*
2124  * audiocs_free_engine()
2125  *
2126  * Description:
2127  *	This routine fress the engine and all associated resources.
2128  *
2129  * Arguments:
2130  *	CS_engine_t	*eng	Engine to free.
2131  */
2132 void
2133 audiocs_free_engine(CS_engine_t *eng)
2134 {
2135 	CS_state_t	*state = eng->ce_state;
2136 	audio_dev_t	*adev = state->cs_adev;
2137 
2138 	if (eng == NULL)
2139 		return;
2140 	if (eng->ce_engine) {
2141 		audio_dev_remove_engine(adev, eng->ce_engine);
2142 		audio_engine_free(eng->ce_engine);
2143 	}
2144 	if (eng->ce_paddr[0]) {
2145 		(void) ddi_dma_unbind_handle(eng->ce_dmah);
2146 	}
2147 	if (eng->ce_acch) {
2148 		ddi_dma_mem_free(&eng->ce_acch);
2149 	}
2150 	if (eng->ce_dmah) {
2151 		ddi_dma_free_handle(&eng->ce_dmah);
2152 	}
2153 	kmem_free(eng, sizeof (*eng));
2154 }
2155 
2156 /*
2157  * audiocs_start_port()
2158  *
2159  * Description:
2160  *	This routine starts the DMA engine.
2161  *
2162  * Arguments:
2163  *	CS_engine_t	*eng		Port of DMA engine to start.
2164  *
2165  * Returns:
2166  *	DDI_SUCCESS	DMA engine started.
2167  *	DDI_FAILURE	DMA engine not started.
2168  */
2169 int
2170 audiocs_start_engine(CS_engine_t *eng)
2171 {
2172 	CS_state_t		*state = eng->ce_state;
2173 	ddi_acc_handle_t	handle = CODEC_HANDLE;
2174 
2175 	ASSERT(mutex_owned(&state->cs_lock));
2176 
2177 	/*
2178 	 * If we are suspended, we can't touch hardware.
2179 	 */
2180 	if (state->cs_suspended)
2181 		return (DDI_SUCCESS);
2182 
2183 	/*
2184 	 * Start the DMA engine.
2185 	 */
2186 	if (CS4231_DMA_START(state, eng) != DDI_SUCCESS)
2187 		return (DDI_FAILURE);
2188 
2189 	/*
2190 	 * Start the codec.
2191 	 */
2192 	SELIDX(state, INTC_REG);
2193 	ORIDX(state, eng->ce_codec_en, INTC_VALID_MASK);
2194 
2195 	return (DDI_SUCCESS);
2196 }
2197 
2198 /*
2199  * audiocs_stop_engine()
2200  *
2201  * Description:
2202  *	This routine stop the DMA engine.
2203  *
2204  * Arguments:
2205  *	CS_engine_t	*eng		DMA engine to stop.
2206  */
2207 void
2208 audiocs_stop_engine(CS_engine_t *eng)
2209 {
2210 	CS_state_t	*state = eng->ce_state;
2211 	ddi_acc_handle_t	handle = CODEC_HANDLE;
2212 
2213 	ASSERT(mutex_owned(&state->cs_lock));
2214 
2215 	/*
2216 	 * If we are suspended, we can't touch hardware.
2217 	 */
2218 	if (state->cs_suspended)
2219 		return;
2220 
2221 	/*
2222 	 * Stop the DMA engine.
2223 	 */
2224 	CS4231_DMA_STOP(state, eng);
2225 
2226 	/*
2227 	 * Stop the codec.
2228 	 */
2229 	SELIDX(state, INTC_REG);
2230 	ANDIDX(state, ~(eng->ce_codec_en), INTC_VALID_MASK);
2231 }
2232 
2233 /*
2234  * audiocs_poll_ready()
2235  *
2236  * Description:
2237  *	This routine waits for the Codec to complete its initialization
2238  *	sequence and is done with its autocalibration.
2239  *
2240  *	Early versions of the Codec have a bug that can take as long as
2241  *	15 seconds to complete its initialization. For these cases we
2242  *	use a timeout mechanism so we don't keep the machine locked up.
2243  *
2244  * Arguments:
2245  *	CS_state_t	*state	The device's state structure
2246  *
2247  * Returns:
2248  *	DDI_SUCCESS		The Codec is ready to continue
2249  *	DDI_FAILURE		The Codec isn't ready to continue
2250  */
2251 int
2252 audiocs_poll_ready(CS_state_t *state)
2253 {
2254 	ddi_acc_handle_t	handle = CODEC_HANDLE;
2255 	int			x = 0;
2256 	uint8_t			iar;
2257 	uint8_t			idr;
2258 
2259 	ASSERT(state->cs_regs != NULL);
2260 	ASSERT(handle != NULL);
2261 
2262 	/* wait for the chip to initialize itself */
2263 	iar = ddi_get8(handle, &CS4231_IAR);
2264 
2265 	while ((iar & IAR_INIT) && x++ < CS4231_TIMEOUT) {
2266 		drv_usecwait(50);
2267 		iar = ddi_get8(handle, &CS4231_IAR);
2268 	}
2269 
2270 	if (x >= CS4231_TIMEOUT) {
2271 		return (DDI_FAILURE);
2272 	}
2273 
2274 	x = 0;
2275 
2276 	/*
2277 	 * Now wait for the chip to complete its autocalibration.
2278 	 * Set the test register.
2279 	 */
2280 	SELIDX(state, ESI_REG);
2281 
2282 	idr = ddi_get8(handle, &CS4231_IDR);
2283 
2284 	while ((idr & ESI_ACI) && x++ < CS4231_TIMEOUT) {
2285 		drv_usecwait(50);
2286 		idr = ddi_get8(handle, &CS4231_IDR);
2287 	}
2288 
2289 	if (x >= CS4231_TIMEOUT) {
2290 		return (DDI_FAILURE);
2291 	}
2292 
2293 
2294 	return (DDI_SUCCESS);
2295 
2296 }
2297 
2298 /*
2299  * audiocs_sel_index()
2300  *
2301  * Description:
2302  *	Select a cs4231 register. The cs4231 has a hardware bug where a
2303  *	register is not always selected the first time. We try and try
2304  *	again until the proper register is selected or we time out and
2305  *	print an error message.
2306  *
2307  * Arguments:
2308  *	audiohdl_t	ahandle		Handle to this device
2309  *	ddi_acc_handle_t handle		A handle to the device's registers
2310  *	uint8_t		addr		The register address to program
2311  *	int		reg		The register to select
2312  *
2313  * Returns:
2314  *	void
2315  */
2316 void
2317 #ifdef	DEBUG
2318 audiocs_sel_index(CS_state_t *state, uint8_t reg, int n)
2319 #else
2320 audiocs_sel_index(CS_state_t *state, uint8_t reg)
2321 #endif
2322 {
2323 	int			x;
2324 	uint8_t			T;
2325 	ddi_acc_handle_t	handle = CODEC_HANDLE;
2326 	uint8_t			*addr = &CS4231_IAR;
2327 
2328 	for (x = 0; x < CS4231_RETRIES; x++) {
2329 		ddi_put8(handle, addr, reg);
2330 		T = ddi_get8(handle, addr);
2331 		if (T == reg) {
2332 			break;
2333 		}
2334 		drv_usecwait(1000);
2335 	}
2336 
2337 	if (x == CS4231_RETRIES) {
2338 		audio_dev_warn(state->cs_adev,
2339 #ifdef	DEBUG
2340 		    "line %d: Couldn't select index (0x%02x 0x%02x)", n,
2341 #else
2342 		    "Couldn't select index (0x%02x 0x%02x)",
2343 #endif
2344 		    T, reg);
2345 		audio_dev_warn(state->cs_adev,
2346 		    "audio may not work correctly until it is stopped and "
2347 		    "restarted");
2348 	}
2349 }
2350 
2351 /*
2352  * audiocs_put_index()
2353  *
2354  * Description:
2355  *	Program a cs4231 register. The cs4231 has a hardware bug where a
2356  *	register is not programmed properly the first time. We program a value,
2357  *	then immediately read back the value and reprogram if nescessary.
2358  *	We do this until the register is properly programmed or we time out and
2359  *	print an error message.
2360  *
2361  * Arguments:
2362  *	CS_state_t	state		Handle to this device
2363  *	uint8_t		mask		Mask to not set reserved register bits
2364  *	int		val		The value to program
2365  *
2366  * Returns:
2367  *	void
2368  */
2369 void
2370 #ifdef DEBUG
2371 audiocs_put_index(CS_state_t *state, uint8_t val, uint8_t mask, int n)
2372 #else
2373 audiocs_put_index(CS_state_t *state, uint8_t val, uint8_t mask)
2374 #endif
2375 {
2376 	int			x;
2377 	uint8_t			T;
2378 	ddi_acc_handle_t	handle = CODEC_HANDLE;
2379 	uint8_t			*addr = &CS4231_IDR;
2380 
2381 	val &= mask;
2382 
2383 	for (x = 0; x < CS4231_RETRIES; x++) {
2384 		ddi_put8(handle, addr, val);
2385 		T = ddi_get8(handle, addr);
2386 		if (T == val) {
2387 			break;
2388 		}
2389 		drv_usecwait(1000);
2390 	}
2391 
2392 	if (x == CS4231_RETRIES) {
2393 #ifdef DEBUG
2394 		audio_dev_warn(state->cs_adev,
2395 		    "line %d: Couldn't set value (0x%02x 0x%02x)", n, T, val);
2396 #else
2397 		audio_dev_warn(state->cs_adev,
2398 		    "Couldn't set value (0x%02x 0x%02x)", T, val);
2399 #endif
2400 		audio_dev_warn(state->cs_adev,
2401 		    "audio may not work correctly until it is stopped and "
2402 		    "restarted");
2403 	}
2404 }
2405