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