audio_4231.c revision 9484:fbd5ddc28e96
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 */
69static int audiocs_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
70static int audiocs_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
71static int audiocs_ddi_power(dev_info_t *, int, int);
72
73/*
74 * Entry point routine prototypes
75 */
76static int audiocs_open(void *, int, unsigned *, unsigned *, caddr_t *);
77static void audiocs_close(void *);
78static int audiocs_start(void *);
79static void audiocs_stop(void *);
80static int audiocs_format(void *);
81static int audiocs_channels(void *);
82static int audiocs_rate(void *);
83static uint64_t audiocs_count(void *);
84static void audiocs_sync(void *, unsigned);
85static size_t audiocs_qlen(void *);
86
87/*
88 * Control callbacks.
89 */
90static int audiocs_get_value(void *, uint64_t *);
91static int audiocs_set_ogain(void *, uint64_t);
92static int audiocs_set_igain(void *, uint64_t);
93static int audiocs_set_mgain(void *, uint64_t);
94static int audiocs_set_inputs(void *, uint64_t);
95static int audiocs_set_outputs(void *, uint64_t);
96static int audiocs_set_micboost(void *, uint64_t);
97
98/* Local Routines */
99static int audiocs_resume(dev_info_t *);
100static int audiocs_attach(dev_info_t *);
101static int audiocs_detach(dev_info_t *);
102static int audiocs_suspend(dev_info_t *);
103
104static void audiocs_destroy(CS_state_t *);
105static int audiocs_init_state(CS_state_t *);
106static int audiocs_chip_init(CS_state_t *);
107static int audiocs_alloc_engine(CS_state_t *, int);
108static void audiocs_free_engine(CS_engine_t *);
109static void audiocs_reset_engine(CS_engine_t *);
110static int audiocs_start_engine(CS_engine_t *);
111static void audiocs_stop_engine(CS_engine_t *);
112static void audiocs_get_ports(CS_state_t *);
113static void audiocs_configure_input(CS_state_t *);
114static void audiocs_configure_output(CS_state_t *);
115static CS_ctrl_t *audiocs_alloc_ctrl(CS_state_t *, uint32_t, uint64_t);
116static void audiocs_free_ctrl(CS_ctrl_t *);
117static int audiocs_add_controls(CS_state_t *);
118static void audiocs_del_controls(CS_state_t *);
119static void audiocs_power_up(CS_state_t *);
120static void audiocs_power_down(CS_state_t *);
121static int audiocs_poll_ready(CS_state_t *);
122#ifdef	DEBUG
123static void audiocs_put_index(CS_state_t *,  uint8_t, uint8_t, int);
124static 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
128static void audiocs_put_index(CS_state_t *,  uint8_t, uint8_t);
129static 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
143static 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
161static 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
173static 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 */
186static 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 */
250static 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 */
266static 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 */
273static 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 */
291int
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 */
314int
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 */
338int
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 */
361static int
362audiocs_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 */
390static int
391audiocs_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 */
419static int
420audiocs_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
465static void
466audiocs_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 */
514static int
515audiocs_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	/* initialize the audio chip */
553	if ((audiocs_chip_init(state)) == DDI_FAILURE) {
554		audio_dev_warn(adev, "chip_init() failed");
555		goto error;
556	}
557	/* chip init will have powered us up */
558	state->cs_powered = B_TRUE;
559
560	/* set up kernel statistics */
561	if ((state->cs_ksp = kstat_create(ddi_driver_name(dip),
562	    ddi_get_instance(dip), ddi_driver_name(dip),
563	    "controller", KSTAT_TYPE_INTR, 1, KSTAT_FLAG_PERSISTENT)) != NULL) {
564		kstat_install(state->cs_ksp);
565	}
566
567	/* we're ready, set up the interrupt handler */
568	if (CS4231_DMA_ADD_INTR(state) != DDI_SUCCESS) {
569		goto error;
570	}
571
572	/* finally register with framework to kick everything off */
573	if (audio_dev_register(state->cs_adev) != DDI_SUCCESS) {
574		audio_dev_warn(state->cs_adev, "unable to register audio dev");
575	}
576
577	/* everything worked out, so report the device */
578	ddi_report_dev(dip);
579
580	return (DDI_SUCCESS);
581
582error:
583	audiocs_destroy(state);
584	return (DDI_FAILURE);
585}
586
587/*
588 * audiocs_resume()
589 *
590 * Description:
591 *	Resume a suspended device instance.
592 *
593 * Arguments:
594 *	dev_info_t	*dip	Pointer to the device's dev_info struct
595 *
596 * Returns:
597 *	DDI_SUCCESS		The driver was initialized properly
598 *	DDI_FAILURE		The driver couldn't be initialized properly
599 */
600static int
601audiocs_resume(dev_info_t *dip)
602{
603	CS_state_t		*state;
604	audio_dev_t		*adev;
605
606	/* we've already allocated the state structure so get ptr */
607	state = ddi_get_driver_private(dip);
608	adev = state->cs_adev;
609
610	ASSERT(dip == state->cs_dip);
611	ASSERT(!mutex_owned(&state->cs_lock));
612
613	/* mark the Codec busy -- this should keep power(9e) away */
614	(void) pm_busy_component(state->cs_dip, CS4231_COMPONENT);
615
616	/* power it up */
617	audiocs_power_up(state);
618	state->cs_powered = B_TRUE;
619
620	/* initialize the audio chip */
621	if ((audiocs_chip_init(state)) == DDI_FAILURE) {
622		audio_dev_warn(adev, "chip_init() failed");
623		(void) pm_idle_component(state->cs_dip, CS4231_COMPONENT);
624		return (DDI_FAILURE);
625	}
626
627	mutex_enter(&state->cs_lock);
628	state->cs_suspended = B_FALSE;
629
630	/* restore mixer settings */
631	audiocs_configure_output(state);
632	audiocs_configure_input(state);
633
634	for (int i = CS4231_PLAY; i <= CS4231_REC; i++) {
635		CS_engine_t	*eng = state->cs_engines[i];
636
637		audiocs_reset_engine(eng);
638		if (eng->ce_started) {
639			(void) audiocs_start_engine(eng);
640		} else {
641			audiocs_stop_engine(eng);
642		}
643	}
644	mutex_exit(&state->cs_lock);
645
646	/*
647	 * We have already powered up the chip, but this alerts the
648	 * framework to the fact.
649	 */
650	(void) pm_raise_power(dip, CS4231_COMPONENT, CS4231_PWR_ON);
651	(void) pm_idle_component(state->cs_dip, CS4231_COMPONENT);
652
653	return (DDI_SUCCESS);
654}
655
656/*
657 * audiocs_detach()
658 *
659 * Description:
660 *	Detach an instance of the CS4231 driver.
661 *
662 * Arguments:
663 *	dev_info_t	*dip	Pointer to the device's dev_info struct
664 *
665 * Returns:
666 *	DDI_SUCCESS		The driver was detached
667 *	DDI_FAILURE		The driver couldn't be detached (busy)
668 */
669static int
670audiocs_detach(dev_info_t *dip)
671{
672	CS_state_t		*state;
673	audio_dev_t		*adev;
674	ddi_acc_handle_t	handle;
675
676	/* get the state structure */
677	state = ddi_get_driver_private(dip);
678	handle = CODEC_HANDLE;
679	adev = state->cs_adev;
680
681	/* don't detach if still in use */
682	if (audio_dev_unregister(adev) != DDI_SUCCESS) {
683		return (DDI_FAILURE);
684	}
685
686	if (state->cs_powered) {
687		/*
688		 * Make sure the Codec and DMA engine are off.
689		 */
690		SELIDX(state, INTC_REG);
691		ANDIDX(state, ~(INTC_PEN|INTC_CEN), INTC_VALID_MASK);
692
693		/* make sure the DMA engine isn't going to do anything */
694		CS4231_DMA_RESET(state);
695
696		/*
697		 * power down the device, no reason to waste power without
698		 * a driver
699		 */
700		(void) pm_lower_power(dip, CS4231_COMPONENT, CS4231_PWR_OFF);
701	}
702
703	audiocs_destroy(state);
704
705	return (DDI_SUCCESS);
706}
707
708/*
709 * audiocs_suspend()
710 *
711 * Description:
712 *	Suspend an instance of the CS4231 driver.
713 *
714 * Arguments:
715 *	dev_info_t	*dip	Pointer to the device's dev_info struct
716 *
717 * Returns:
718 *	DDI_SUCCESS		The driver was detached
719 *	DDI_FAILURE		The driver couldn't be detached
720 */
721static int
722audiocs_suspend(dev_info_t *dip)
723{
724	CS_state_t		*state;
725
726	/* get the state structure */
727	state = ddi_get_driver_private(dip);
728
729	ASSERT(!mutex_owned(&state->cs_lock));
730
731	mutex_enter(&state->cs_lock);
732
733	ASSERT(!state->cs_suspended);
734
735	if (state->cs_powered) {
736		/* stop playing and recording */
737		CS4231_DMA_STOP(state, state->cs_engines[CS4231_PLAY]);
738		CS4231_DMA_STOP(state, state->cs_engines[CS4231_REC]);
739
740		/* now we can power down the Codec */
741		audiocs_power_down(state);
742		state->cs_powered = B_FALSE;
743	}
744	state->cs_suspended = B_TRUE;	/* stop new ops */
745	mutex_exit(&state->cs_lock);
746
747	ASSERT(!mutex_owned(&state->cs_lock));
748	return (DDI_SUCCESS);
749}
750
751#define	PLAYCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_PLAY)
752#define	RECCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC)
753#define	MONCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_MONITOR)
754#define	PCMVOL	(PLAYCTL | AUDIO_CTRL_FLAG_PCMVOL)
755#define	MAINVOL	(PLAYCTL | AUDIO_CTRL_FLAG_MAINVOL)
756#define	RECVOL	(RECCTL | AUDIO_CTRL_FLAG_RECVOL)
757#define	MONVOL	(MONCTL | AUDIO_CTRL_FLAG_MONVOL)
758
759/*
760 * audiocs_alloc_ctrl
761 *
762 * Description:
763 *	Allocates a control structure for the audio mixer.
764 *
765 * Arguments:
766 *	CS_state_t	*state		Device soft state.
767 *	uint32_t	num		Control number to allocate.
768 *	uint64_t	val		Initial value.
769 *
770 * Returns:
771 *	Pointer to newly allocated CS_ctrl_t structure.
772 */
773static CS_ctrl_t *
774audiocs_alloc_ctrl(CS_state_t *state, uint32_t num, uint64_t val)
775{
776	audio_ctrl_desc_t	desc;
777	audio_ctrl_wr_t		fn;
778	CS_ctrl_t		*cc;
779
780	cc = kmem_zalloc(sizeof (*cc), KM_SLEEP);
781	cc->cc_state = state;
782	cc->cc_num = num;
783
784	bzero(&desc, sizeof (desc));
785
786	switch (num) {
787	case CTL_VOLUME:
788		desc.acd_name = AUDIO_CTRL_ID_VOLUME;
789		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
790		desc.acd_minvalue = 0;
791		desc.acd_maxvalue = 100;
792		desc.acd_flags = PCMVOL;
793		fn = audiocs_set_ogain;
794		break;
795
796	case CTL_IGAIN:
797		desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
798		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
799		desc.acd_minvalue = 0;
800		desc.acd_maxvalue = 100;
801		desc.acd_flags = RECVOL;
802		fn = audiocs_set_igain;
803		break;
804
805	case CTL_MGAIN:
806		desc.acd_name = AUDIO_CTRL_ID_MONGAIN;
807		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
808		desc.acd_minvalue = 0;
809		desc.acd_maxvalue = 100;
810		desc.acd_flags = MONVOL;
811		fn = audiocs_set_mgain;
812		break;
813
814	case CTL_INPUTS:
815		desc.acd_name = AUDIO_CTRL_ID_RECSRC;
816		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
817		desc.acd_minvalue = state->cs_imask;
818		desc.acd_maxvalue = state->cs_imask;
819		desc.acd_flags = RECCTL;
820		for (int i = 0; audiocs_inputs[i]; i++) {
821			desc.acd_enum[i] = audiocs_inputs[i];
822		}
823		fn = audiocs_set_inputs;
824
825		break;
826
827	case CTL_OUTPUTS:
828		desc.acd_name = AUDIO_CTRL_ID_OUTPUTS;
829		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
830		desc.acd_minvalue = state->cs_omod;
831		desc.acd_maxvalue = state->cs_omask;
832		desc.acd_flags = PLAYCTL | AUDIO_CTRL_FLAG_MULTI;
833		for (int i = 0; audiocs_outputs[i]; i++) {
834			desc.acd_enum[i] = audiocs_outputs[i];
835		}
836		fn = audiocs_set_outputs;
837		break;
838
839	case CTL_MICBOOST:
840		desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
841		desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
842		desc.acd_minvalue = 0;
843		desc.acd_maxvalue = 1;
844		desc.acd_flags = RECCTL;
845		fn = audiocs_set_micboost;
846		break;
847	}
848
849	cc->cc_val = val;
850	cc->cc_ctrl = audio_dev_add_control(state->cs_adev, &desc,
851	    audiocs_get_value, fn, cc);
852
853	return (cc);
854}
855
856/*
857 * audiocs_free_ctrl
858 *
859 * Description:
860 *	Frees a control and all resources associated with it.
861 *
862 * Arguments:
863 *	CS_ctrl_t	*cc	Pointer to control structure.
864 */
865static void
866audiocs_free_ctrl(CS_ctrl_t *cc)
867{
868	if (cc == NULL)
869		return;
870	if (cc->cc_ctrl)
871		audio_dev_del_control(cc->cc_ctrl);
872	kmem_free(cc, sizeof (*cc));
873}
874
875/*
876 * audiocs_add_controls
877 *
878 * Description:
879 *	Allocates and registers all controls for this device.
880 *
881 * Arguments:
882 *	CS_state_t	*state		Device soft state.
883 *
884 * Returns:
885 *	DDI_SUCCESS	All controls added and registered
886 *	DDI_FAILURE	At least one control was not added or registered.
887 */
888static int
889audiocs_add_controls(CS_state_t *state)
890{
891#define	ADD_CTRL(CTL, ID, VAL)						\
892	state->cs_##CTL = audiocs_alloc_ctrl(state, ID, VAL);		\
893	if (state->cs_##CTL == NULL) {					\
894		audio_dev_warn(state->cs_adev,				\
895		    "unable to allocate %s control", #ID);		\
896		return (DDI_FAILURE);					\
897	}
898
899	ADD_CTRL(ogain, CTL_VOLUME, 0x4b4b);
900	ADD_CTRL(igain, CTL_IGAIN, 0x3232);
901	ADD_CTRL(mgain, CTL_MGAIN, 0);
902	ADD_CTRL(micboost, CTL_MICBOOST, 0);
903	ADD_CTRL(outputs, CTL_OUTPUTS, (state->cs_omask & ~state->cs_omod) |
904	    (1U << OUTPUT_SPEAKER));
905	ADD_CTRL(inputs, CTL_INPUTS, (1U << INPUT_MIC));
906
907	mutex_enter(&state->cs_lock);
908	audiocs_configure_output(state);
909	audiocs_configure_input(state);
910	mutex_exit(&state->cs_lock);
911
912	return (DDI_SUCCESS);
913}
914/*
915 * audiocs_del_controls
916 *
917 * Description:
918 *	Unregisters and frees all controls for this device.
919 *
920 * Arguments:
921 *	CS_state_t	*state		Device soft state.
922 */
923void
924audiocs_del_controls(CS_state_t *state)
925{
926	audiocs_free_ctrl(state->cs_ogain);
927	audiocs_free_ctrl(state->cs_igain);
928	audiocs_free_ctrl(state->cs_mgain);
929	audiocs_free_ctrl(state->cs_micboost);
930	audiocs_free_ctrl(state->cs_inputs);
931	audiocs_free_ctrl(state->cs_outputs);
932}
933
934
935/*
936 * audiocs_chip_init()
937 *
938 * Description:
939 *	Power up the audio core, initialize the audio Codec, prepare the chip
940 *	for use.
941 *
942 * Arguments:
943 *	CS_state_t	*state		The device's state structure
944 *
945 * Returns:
946 *	DDI_SUCCESS			Chip initialized and ready to use
947 *	DDI_FAILURE			Chip not initialized and not ready
948 */
949static int
950audiocs_chip_init(CS_state_t *state)
951{
952	ddi_acc_handle_t	handle = CODEC_HANDLE;
953
954	/* make sure we are powered up */
955	CS4231_DMA_POWER(state, CS4231_PWR_ON);
956
957	CS4231_DMA_RESET(state);
958
959	/* activate registers 16 -> 31 */
960	SELIDX(state, MID_REG);
961	ddi_put8(handle, &CS4231_IDR, MID_MODE2);
962
963	/* now figure out what version we have */
964	SELIDX(state, VID_REG);
965	if (ddi_get8(handle, &CS4231_IDR) & VID_A) {
966		state->cs_revA = B_TRUE;
967	} else {
968		state->cs_revA = B_FALSE;
969	}
970
971	/* get rid of annoying popping by muting the output channels */
972	SELIDX(state, LDACO_REG);
973	PUTIDX(state, LDACO_LDM | LDACO_MID_GAIN, LDAC0_VALID_MASK);
974	SELIDX(state, RDACO_REG);
975	PUTIDX(state, RDACO_RDM | RDACO_MID_GAIN, RDAC0_VALID_MASK);
976
977	/* initialize aux input channels to known gain values & muted */
978	SELIDX(state, LAUX1_REG);
979	PUTIDX(state, LAUX1_LX1M | LAUX1_UNITY_GAIN, LAUX1_VALID_MASK);
980	SELIDX(state, RAUX1_REG);
981	PUTIDX(state, RAUX1_RX1M | RAUX1_UNITY_GAIN, RAUX1_VALID_MASK);
982	SELIDX(state, LAUX2_REG);
983	PUTIDX(state, LAUX2_LX2M | LAUX2_UNITY_GAIN, LAUX2_VALID_MASK);
984	SELIDX(state, RAUX2_REG);
985	PUTIDX(state, RAUX2_RX2M | RAUX2_UNITY_GAIN, RAUX2_VALID_MASK);
986
987	/* initialize aux input channels to known gain values & muted */
988	SELIDX(state, LLIC_REG);
989	PUTIDX(state, LLIC_LLM | LLIC_UNITY_GAIN, LLIC_VALID_MASK);
990	SELIDX(state, RLIC_REG);
991	PUTIDX(state, RLIC_RLM | RLIC_UNITY_GAIN, RLIC_VALID_MASK);
992
993	/* program the sample rate, play and capture must be the same */
994	SELIDX(state, FSDF_REG | IAR_MCE);
995	PUTIDX(state, FS_48000 | PDF_LINEAR16NE | PDF_STEREO, FSDF_VALID_MASK);
996	SELIDX(state, FSDF_REG);
997	SELIDX(state, CDF_REG | IAR_MCE);
998	PUTIDX(state, CDF_LINEAR16NE | CDF_STEREO, CDF_VALID_MASK);
999	SELIDX(state, CDF_REG);
1000
1001	/*
1002	 * Set up the Codec for playback and capture disabled, dual DMA, and
1003	 * playback and capture DMA.
1004	 */
1005	SELIDX(state, (INTC_REG | IAR_MCE));
1006	PUTIDX(state, INTC_DDC | INTC_PDMA | INTC_CDMA, INTC_VALID_MASK);
1007
1008	/* turn off the MCE bit */
1009	SELIDX(state, LADCI_REG);
1010
1011	/* wait for the Codec before we continue XXX - do we need this? */
1012	if (audiocs_poll_ready(state) == DDI_FAILURE) {
1013		return (DDI_FAILURE);
1014	}
1015
1016	/*
1017	 * Turn on the output level bit to be 2.8 Vpp. Also, don't go to 0 on
1018	 * underflow.
1019	 */
1020	SELIDX(state, AFE1_REG);
1021	PUTIDX(state, AFE1_OLB, AFE1_VALID_MASK);
1022
1023	/* turn on the high pass filter if Rev A */
1024	SELIDX(state, AFE2_REG);
1025	if (state->cs_revA) {
1026		PUTIDX(state, AFE2_HPF, AFE2_VALID_MASK);
1027	} else {
1028		PUTIDX(state, 0, AFE2_VALID_MASK);
1029	}
1030
1031	/* clear the play and capture interrupt flags */
1032	SELIDX(state, AFS_REG);
1033	ddi_put8(handle, &CS4231_STATUS, (AFS_RESET_STATUS));
1034
1035	/* the play and record gains will be set by the audio mixer */
1036
1037	/* unmute the output */
1038	SELIDX(state, LDACO_REG);
1039	ANDIDX(state, ~LDACO_LDM, LDAC0_VALID_MASK);
1040	SELIDX(state, RDACO_REG);
1041	ANDIDX(state, ~RDACO_RDM, RDAC0_VALID_MASK);
1042
1043	/* unmute the mono speaker and mute mono in */
1044	SELIDX(state, MIOC_REG);
1045	PUTIDX(state, MIOC_MIM, MIOC_VALID_MASK);
1046
1047	/* clear the mode change bit */
1048	SELIDX(state, RDACO_REG);
1049
1050	/* wait for the Codec before we continue XXX - do we need this? */
1051	if (audiocs_poll_ready(state) == DDI_FAILURE) {
1052		return (DDI_FAILURE);
1053	}
1054
1055	return (DDI_SUCCESS);
1056}
1057
1058/*
1059 * audiocs_init_state()
1060 *
1061 * Description:
1062 *	This routine initializes the audio driver's state structure and
1063 *	maps in the registers. This also includes reading the properties.
1064 *
1065 *	CAUTION: This routine maps the registers and initializes a mutex.
1066 *		 Failure cleanup is handled by cs4231_attach(). It is not
1067 *		 handled locally by this routine.
1068 *
1069 * Arguments:
1070 *	CS_state_t	*state		The device's state structure
1071 *
1072 * Returns:
1073 *	DDI_SUCCESS			State structure initialized
1074 *	DDI_FAILURE			State structure not initialized
1075 */
1076static int
1077audiocs_init_state(CS_state_t *state)
1078{
1079	audio_dev_t	*adev = state->cs_adev;
1080	dev_info_t	*dip = state->cs_dip;
1081	char		*prop_str;
1082	char		*pm_comp[] = {
1083				"NAME=audiocs audio device",
1084				"0=off",
1085				"1=on" };
1086
1087	/* set up the pm-components */
1088	if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
1089	    "pm-components", pm_comp, 3) != DDI_PROP_SUCCESS) {
1090		audio_dev_warn(adev, "couldn't create pm-components property");
1091		return (DDI_FAILURE);
1092	}
1093
1094	/* figure out which DMA engine hardware we have */
1095	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1096	    "dma-model", &prop_str) == DDI_PROP_SUCCESS) {
1097		if (strcmp(prop_str, "eb2dma") == 0) {
1098			state->cs_dma_engine = EB2_DMA;
1099			state->cs_dma_ops = &cs4231_eb2dma_ops;
1100		} else {
1101			state->cs_dma_engine = APC_DMA;
1102			state->cs_dma_ops = &cs4231_apcdma_ops;
1103		}
1104		ddi_prop_free(prop_str);
1105	} else {
1106		state->cs_dma_engine = APC_DMA;
1107		state->cs_dma_ops = &cs4231_apcdma_ops;
1108	}
1109
1110	/* cs_regs, cs_eb2_regs and cs_handles filled in later */
1111
1112	/* most of what's left is filled in when the registers are mapped */
1113
1114	audiocs_get_ports(state);
1115
1116	/* Allocate engines, must be done before register mapping called  */
1117	if ((audiocs_alloc_engine(state, CS4231_PLAY) != DDI_SUCCESS) ||
1118	    (audiocs_alloc_engine(state, CS4231_REC) != DDI_SUCCESS)) {
1119		return (DDI_FAILURE);
1120	}
1121
1122	/* Map in the registers */
1123	if (CS4231_DMA_MAP_REGS(state) == DDI_FAILURE) {
1124		return (DDI_FAILURE);
1125	}
1126
1127
1128	/* Allocate and add controls, must be done *after* registers mapped */
1129	if (audiocs_add_controls(state) != DDI_SUCCESS) {
1130		return (DDI_FAILURE);
1131	}
1132
1133	state->cs_suspended = B_FALSE;
1134	state->cs_powered = B_FALSE;
1135
1136	return (DDI_SUCCESS);
1137}
1138
1139/*
1140 * audiocs_get_ports()
1141 *
1142 * Description:
1143 *	Get which audiocs h/w version we have and use this to
1144 *	determine the input and output ports as well whether or not
1145 *	the hardware has internal loopbacks or not. We also have three
1146 *	different ways for the properties to be specified, which we
1147 *	also need to worry about.
1148 *
1149 * Vers	Platform(s)	DMA eng.	audio-module**	loopback
1150 * a    SS-4+/SS-5+	apcdma		no		no
1151 * b	Ultra-1&2	apcdma		no		yes
1152 * c	positron	apcdma		no		yes
1153 * d	PPC - retired
1154 * e	x86 - retired
1155 * f	tazmo		eb2dma		Perigee		no
1156 * g	tazmo		eb2dma		Quark		yes
1157 * h	darwin+		eb2dma		no		N/A
1158 *
1159 * Vers	model~		aux1*		aux2*
1160 * a	N/A		N/A		N/A
1161 * b	N/A		N/A		N/A
1162 * c	N/A		N/A		N/A
1163 * d	retired
1164 * e	retired
1165 * f	SUNW,CS4231f	N/A		N/A
1166 * g	SUNW,CS4231g	N/A		N/A
1167 * h	SUNW,CS4231h	cdrom		none
1168 *
1169 * *   = Replaces internal-loopback for latest property type, can be
1170 *	 set to "cdrom", "loopback", or "none".
1171 *
1172 * **  = For plugin audio modules only. Starting with darwin, this
1173 *	 property is replaces by the model property.
1174 *
1175 * ~   = Replaces audio-module.
1176 *
1177 * +   = Has the capability of having a cable run from the internal
1178 *	 CD-ROM to the audio device.
1179 *
1180 * N/A = Not applicable, the property wasn't created for early
1181 *	 platforms, or the property has been retired.
1182 *
1183 * NOTE: Older tazmo and quark machines don't have the model property.
1184 *
1185 * Arguments:
1186 *	CS_state_t	*state		The device's state structure
1187 */
1188static void
1189audiocs_get_ports(CS_state_t *state)
1190{
1191	dev_info_t	*dip = state->cs_dip;
1192	audio_dev_t	*adev = state->cs_adev;
1193	char		*prop_str;
1194
1195	/* First we set the common ports, etc. */
1196	state->cs_omask = state->cs_omod =
1197	    (1U << OUTPUT_SPEAKER) |
1198	    (1U << OUTPUT_HEADPHONES) |
1199	    (1U << OUTPUT_LINEOUT);
1200	state->cs_imask =
1201	    (1U << INPUT_MIC) |
1202	    (1U << INPUT_LINEIN) |
1203	    (1U << INPUT_STEREOMIX);
1204
1205	/* now we try the new "model" property */
1206	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1207	    "model", &prop_str) == DDI_PROP_SUCCESS) {
1208		if (strcmp(prop_str, "SUNW,CS4231h") == 0) {
1209			/* darwin */
1210			audio_dev_set_version(adev, CS_DEV_VERSION_H);
1211			state->cs_imask |= (1U << INPUT_CD);
1212			state->cs_omod = (1U << OUTPUT_SPEAKER);
1213		} else if (strcmp(prop_str, "SUNW,CS4231g") == 0) {
1214			/* quark audio module */
1215			audio_dev_set_version(adev, CS_DEV_VERSION_G);
1216			/*
1217			 * NB: This could do SUNVTS LOOPBACK, but we
1218			 * don't support it for now... owing to no
1219			 * support in framework.
1220			 */
1221		} else if (strcmp(prop_str, "SUNW,CS4231f") == 0) {
1222			/* tazmo */
1223			audio_dev_set_version(adev, CS_DEV_VERSION_F);
1224		} else {
1225			audio_dev_set_version(adev, prop_str);
1226			audio_dev_warn(adev,
1227			    "unknown audio model: %s, some parts of "
1228			    "audio may not work correctly", prop_str);
1229		}
1230		ddi_prop_free(prop_str);	/* done with the property */
1231	} else {	/* now try the older "audio-module" property */
1232		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
1233		    DDI_PROP_DONTPASS, "audio-module", &prop_str) ==
1234		    DDI_PROP_SUCCESS) {
1235			switch (*prop_str) {
1236			case 'Q':	/* quark audio module */
1237				audio_dev_set_version(adev, CS_DEV_VERSION_G);
1238				/* See quark comment above about SunVTS */
1239				break;
1240			case 'P':	/* tazmo */
1241				audio_dev_set_version(adev, CS_DEV_VERSION_F);
1242				break;
1243			default:
1244				audio_dev_set_version(adev, prop_str);
1245				audio_dev_warn(adev,
1246				    "unknown audio module: %s, some "
1247				    "parts of audio may not work correctly",
1248				    prop_str);
1249				break;
1250			}
1251			ddi_prop_free(prop_str);	/* done with the prop */
1252		} else {	/* now try heuristics, ;-( */
1253			if (ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1254			    DDI_PROP_DONTPASS, "internal-loopback", B_FALSE)) {
1255				if (state->cs_dma_engine == EB2_DMA) {
1256					audio_dev_set_version(adev,
1257					    CS_DEV_VERSION_C);
1258				} else {
1259					audio_dev_set_version(adev,
1260					    CS_DEV_VERSION_B);
1261				}
1262				/*
1263				 * Again, we don't support SunVTS for these
1264				 * boards, although we potentially could.
1265				 */
1266			} else {
1267				audio_dev_set_version(adev, CS_DEV_VERSION_A);
1268				state->cs_imask |= (1U << INPUT_CD);
1269			}
1270		}
1271	}
1272}
1273
1274/*
1275 * audiocs_power_up()
1276 *
1277 * Description:
1278 *	Power up the Codec and restore the codec's registers.
1279 *
1280 *	NOTE: We don't worry about locking since the only routines
1281 *		that may call us are attach() and power() Both of
1282 *		which should be the only threads in the driver.
1283 *
1284 * Arguments:
1285 *	CS_state_t	*state		The device's state structure
1286 */
1287static void
1288audiocs_power_up(CS_state_t *state)
1289{
1290	ddi_acc_handle_t	handle = CODEC_HANDLE;
1291	int			i;
1292
1293	/* turn on the Codec */
1294	CS4231_DMA_POWER(state, CS4231_PWR_ON);
1295
1296	/* reset the DMA engine(s) */
1297	CS4231_DMA_RESET(state);
1298
1299	/*
1300	 * Reload the Codec's registers, the DMA engines will be
1301	 * taken care of when play and record start up again. But
1302	 * first enable registers 16 -> 31.
1303	 */
1304	SELIDX(state, MID_REG);
1305	PUTIDX(state, state->cs_save[MID_REG], MID_VALID_MASK);
1306
1307	for (i = 0; i < CS4231_REGS; i++) {
1308		/* restore Codec registers */
1309		SELIDX(state, (i | IAR_MCE));
1310		ddi_put8(handle, &CS4231_IDR, state->cs_save[i]);
1311		drv_usecwait(500);	/* chip bug */
1312	}
1313	/* clear MCE bit */
1314	SELIDX(state, 0);
1315}
1316
1317/*
1318 * audiocs_power_down()
1319 *
1320 * Description:
1321 *	Power down the Codec and save the codec's registers.
1322 *
1323 *	NOTE: See the note in cs4231_power_up() about locking.
1324 *
1325 * Arguments:
1326 *	CS_state_t	*state		The device's state structure
1327 */
1328static void
1329audiocs_power_down(CS_state_t *state)
1330{
1331	ddi_acc_handle_t	handle;
1332	int			i;
1333
1334	handle = state->cs_handles.cs_codec_hndl;
1335
1336	/*
1337	 * We are powering down, so we don't need to do a thing with
1338	 * the DMA engines. However, we do need to save the Codec
1339	 * registers.
1340	 */
1341
1342	for (i = 0; i < CS4231_REGS; i++) {
1343		/* save Codec regs */
1344		SELIDX(state, i);
1345		state->cs_save[i] = ddi_get8(handle, &CS4231_IDR);
1346	}
1347
1348	/* turn off the Codec */
1349	CS4231_DMA_POWER(state, CS4231_PWR_OFF);
1350
1351}	/* cs4231_power_down() */
1352
1353/*
1354 * audiocs_configure_input()
1355 *
1356 * Description:
1357 *	Configure input properties of the mixer (e.g. igain, ports).
1358 *
1359 * Arguments:
1360 *	CS_state_t	*state		The device's state structure
1361 */
1362static void
1363audiocs_configure_input(CS_state_t *state)
1364{
1365	uint8_t		l, r;
1366	uint64_t	inputs;
1367	uint64_t	micboost;
1368
1369	ASSERT(mutex_owned(&state->cs_lock));
1370
1371	if (state->cs_suspended)
1372		return;
1373
1374	inputs = state->cs_inputs->cc_val;
1375	micboost = state->cs_micboost->cc_val;
1376	r = (state->cs_igain->cc_val & 0xff);
1377	l = ((state->cs_igain->cc_val & 0xff00) >> 8);
1378
1379	/* rescale these for our atten array */
1380	l = (((uint32_t)l * 255) / 100) & 0xff;
1381	r = (((uint32_t)r * 255) / 100) & 0xff;
1382
1383	/* we downshift by 4 bits -- igain only has 16 possible values */
1384	/* NB: that we do not scale here!  The SADA driver didn't do so. */
1385	l = l >> 4;
1386	r = r >> 4;
1387
1388	if (inputs & (1U << INPUT_MIC)) {
1389		l |= LADCI_LMIC;
1390		r |= RADCI_RMIC;
1391	}
1392	if (inputs & (1U << INPUT_LINEIN)) {
1393		l |= LADCI_LLINE;
1394		r |= RADCI_RLINE;
1395	}
1396	if (inputs & (1U << INPUT_CD)) {
1397		/* note that SunVTS also uses this */
1398		l |= LADCI_LAUX1;
1399		r |= RADCI_RAUX1;
1400	}
1401	if (inputs & (1U << INPUT_STEREOMIX)) {
1402		l |= LADCI_LLOOP;
1403		r |= RADCI_RLOOP;
1404	}
1405	if (micboost) {
1406		l |= LADCI_LMGE;
1407		r |= RADCI_RMGE;
1408	}
1409
1410	SELIDX(state, LADCI_REG);
1411	PUTIDX(state, l, LADCI_VALID_MASK);
1412
1413	SELIDX(state, RADCI_REG);
1414	PUTIDX(state, r, RADCI_VALID_MASK);
1415}
1416
1417/*
1418 * audiocs_configure_output()
1419 *
1420 * Description:
1421 *	Configure output properties of the mixer (e.g. ogain, mgain).
1422 *
1423 * Arguments:
1424 *	CS_state_t	*state		The device's state structure
1425 */
1426static void
1427audiocs_configure_output(CS_state_t *state)
1428{
1429	uint64_t		outputs;
1430	uint8_t			l, r;
1431	uint8_t			rmute, lmute;
1432	uint8_t			mgain;
1433	ddi_acc_handle_t	handle = CODEC_HANDLE;
1434
1435	rmute = lmute = 0;
1436
1437	ASSERT(mutex_owned(&state->cs_lock));
1438
1439	if (state->cs_suspended)
1440		return;
1441
1442	outputs = state->cs_outputs->cc_val;
1443
1444	/* port selection */
1445	SELIDX(state, MIOC_REG);
1446	if (outputs & (1U << OUTPUT_SPEAKER)) {
1447		ANDIDX(state, ~MIOC_MONO_SPKR_MUTE, MIOC_VALID_MASK);
1448	} else {
1449		ORIDX(state, MIOC_MONO_SPKR_MUTE, MIOC_VALID_MASK);
1450	}
1451	SELIDX(state, PC_REG);
1452	if (outputs & (1U << OUTPUT_HEADPHONES)) {
1453		ANDIDX(state, ~PC_HEADPHONE_MUTE, PC_VALID_MASK);
1454	} else {
1455		ORIDX(state, PC_HEADPHONE_MUTE, PC_VALID_MASK);
1456	}
1457	SELIDX(state, PC_REG);
1458	if (outputs & (1U << OUTPUT_LINEOUT)) {
1459		ANDIDX(state, ~PC_LINE_OUT_MUTE, PC_VALID_MASK);
1460	} else {
1461		ORIDX(state, PC_LINE_OUT_MUTE, PC_VALID_MASK);
1462	}
1463
1464	/* monitor gain */
1465	mgain = cs4231_atten[((state->cs_mgain->cc_val * 255) / 100) & 0xff];
1466	SELIDX(state, LC_REG);
1467	if (mgain == 0) {
1468		/* disable loopbacks when gain == 0 */
1469		PUTIDX(state, LC_OFF, LC_VALID_MASK);
1470	} else {
1471		/* we use cs4231_atten[] to linearize attenuation */
1472		PUTIDX(state, (mgain << 2) | LC_LBE, LC_VALID_MASK);
1473	}
1474
1475	/* output gain */
1476	l = ((state->cs_ogain->cc_val >> 8) & 0xff);
1477	r = (state->cs_ogain->cc_val & 0xff);
1478	if (l == 0) {
1479		lmute = LDACO_LDM;
1480	}
1481	if (r == 0) {
1482		rmute = RDACO_RDM;
1483	}
1484
1485	/* rescale these for our atten array */
1486	l = cs4231_atten[(((uint32_t)l * 255) / 100) & 0xff] | lmute;
1487	r = cs4231_atten[(((uint32_t)r * 255) / 100) & 0xff] | rmute;
1488
1489	SELIDX(state, LDACO_REG);
1490	PUTIDX(state, l, LDAC0_VALID_MASK);
1491	SELIDX(state, RDACO_REG);
1492	PUTIDX(state, r, RDAC0_VALID_MASK);
1493}
1494
1495/*
1496 * audiocs_get_value()
1497 *
1498 * Description:
1499 *	Get a control value
1500 *
1501 * Arguments:
1502 *	void		*arg		The device's state structure
1503 *	uint64_t	*valp		Pointer to store value.
1504 *
1505 * Returns:
1506 *	0		The Codec parameter has been retrieved.
1507 */
1508static int
1509audiocs_get_value(void *arg, uint64_t *valp)
1510{
1511	CS_ctrl_t		*cc = arg;
1512	CS_state_t		*state = cc->cc_state;
1513
1514	mutex_enter(&state->cs_lock);
1515	*valp = cc->cc_val;
1516	mutex_exit(&state->cs_lock);
1517	return (0);
1518}
1519
1520
1521/*
1522 * audiocs_set_ogain()
1523 *
1524 * Description:
1525 *	Set the play gain.
1526 *
1527 * Arguments:
1528 *	void		*arg		The device's state structure
1529 *	uint64_t	val		The gain to set (both left and right)
1530 *
1531 * Returns:
1532 *	0		The Codec parameter has been set
1533 */
1534static int
1535audiocs_set_ogain(void *arg, uint64_t val)
1536{
1537	CS_ctrl_t		*cc = arg;
1538	CS_state_t		*state = cc->cc_state;
1539
1540	if ((val & ~0xffff) ||
1541	    ((val & 0xff) > 100) ||
1542	    (((val & 0xff00) >> 8) > 100))
1543		return (EINVAL);
1544
1545	mutex_enter(&state->cs_lock);
1546	cc->cc_val = val;
1547	audiocs_configure_output(state);
1548	mutex_exit(&state->cs_lock);
1549	return (0);
1550}
1551
1552/*
1553 * audiocs_set_micboost()
1554 *
1555 * Description:
1556 *	Set the 20 dB microphone boost.
1557 *
1558 * Arguments:
1559 *	void		*arg		The device's state structure
1560 *	uint64_t	val		The 1 to enable, 0 to disable.
1561 *
1562 * Returns:
1563 *	0		The Codec parameter has been set
1564 */
1565static int
1566audiocs_set_micboost(void *arg, uint64_t val)
1567{
1568	CS_ctrl_t	*cc = arg;
1569	CS_state_t	*state = cc->cc_state;
1570
1571	mutex_enter(&state->cs_lock);
1572	cc->cc_val = val ? B_TRUE : B_FALSE;
1573	audiocs_configure_input(state);
1574	mutex_exit(&state->cs_lock);
1575	return (0);
1576}
1577
1578/*
1579 * audiocs_set_igain()
1580 *
1581 * Description:
1582 *	Set the record gain.
1583 *
1584 * Arguments:
1585 *	void		*arg		The device's state structure
1586 *	uint64_t	val		The gain to set (both left and right)
1587 *
1588 * Returns:
1589 *	0		The Codec parameter has been set
1590 */
1591static int
1592audiocs_set_igain(void *arg, uint64_t val)
1593{
1594	CS_ctrl_t	*cc = arg;
1595	CS_state_t	*state = cc->cc_state;
1596
1597	if ((val & ~0xffff) ||
1598	    ((val & 0xff) > 100) ||
1599	    (((val & 0xff00) >> 8) > 100))
1600		return (EINVAL);
1601
1602	mutex_enter(&state->cs_lock);
1603	cc->cc_val = val;
1604	audiocs_configure_input(state);
1605	mutex_exit(&state->cs_lock);
1606
1607	return (0);
1608}
1609
1610/*
1611 * audiocs_set_inputs()
1612 *
1613 * Description:
1614 *	Set the input ports.
1615 *
1616 * Arguments:
1617 *	void		*arg		The device's state structure
1618 *	uint64_t	val		The mask of output ports.
1619 *
1620 * Returns:
1621 *	0		The Codec parameter has been set
1622 */
1623static int
1624audiocs_set_inputs(void *arg, uint64_t val)
1625{
1626	CS_ctrl_t	*cc = arg;
1627	CS_state_t	*state = cc->cc_state;
1628
1629	if (val & ~(state->cs_imask))
1630		return (EINVAL);
1631
1632	mutex_enter(&state->cs_lock);
1633	cc->cc_val = val;
1634	audiocs_configure_input(state);
1635	mutex_exit(&state->cs_lock);
1636
1637	return (0);
1638}
1639
1640/*
1641 * audiocs_set_outputs()
1642 *
1643 * Description:
1644 *	Set the output ports.
1645 *
1646 * Arguments:
1647 *	void		*arg		The device's state structure
1648 *	uint64_t	val		The mask of input ports.
1649 *
1650 * Returns:
1651 *	0		The Codec parameter has been set
1652 */
1653static int
1654audiocs_set_outputs(void *arg, uint64_t val)
1655{
1656	CS_ctrl_t	*cc = arg;
1657	CS_state_t	*state = cc->cc_state;
1658
1659	if ((val & ~(state->cs_omod)) !=
1660	    (state->cs_omask & ~state->cs_omod))
1661		return (EINVAL);
1662
1663	mutex_enter(&state->cs_lock);
1664	cc->cc_val = val;
1665	audiocs_configure_output(state);
1666	mutex_exit(&state->cs_lock);
1667
1668	return (0);
1669}
1670
1671/*
1672 * audiocs_set_mgain()
1673 *
1674 * Description:
1675 *	Set the monitor gain.
1676 *
1677 * Arguments:
1678 *	void		*arg		The device's state structure
1679 *	uint64_t	val		The gain to set (monoaural).)
1680 *
1681 * Returns:
1682 *	0		The Codec parameter has been set
1683 */
1684static int
1685audiocs_set_mgain(void *arg, uint64_t gain)
1686{
1687	CS_ctrl_t	*cc = arg;
1688	CS_state_t	*state = cc->cc_state;
1689
1690	if (gain > 100)
1691		return (EINVAL);
1692
1693	mutex_enter(&state->cs_lock);
1694	cc->cc_val = gain;
1695	audiocs_configure_output(state);
1696	mutex_exit(&state->cs_lock);
1697
1698	return (0);
1699}
1700
1701/*
1702 * audiocs_open()
1703 *
1704 * Description:
1705 *	Opens a DMA engine for use.
1706 *
1707 * Arguments:
1708 *	void		*arg		The DMA engine to set up
1709 *	int		flag		Open flags
1710 *	unsigned	*fragfrp	Receives number of frames per fragment
1711 *	unsigned	*nfragsp	Receives number of fragments
1712 *	caddr_t		*bufp		Receives kernel data buffer
1713 *
1714 * Returns:
1715 *	0	on success
1716 *	errno	on failure
1717 */
1718static int
1719audiocs_open(void *arg, int flag,
1720    unsigned *fragfrp, unsigned *nfragsp, caddr_t *bufp)
1721{
1722	CS_engine_t	*eng = arg;
1723	CS_state_t	*state = eng->ce_state;
1724	dev_info_t	*dip = state->cs_dip;
1725
1726	_NOTE(ARGUNUSED(flag));
1727
1728	(void) pm_busy_component(dip, CS4231_COMPONENT);
1729	if (pm_raise_power(dip, CS4231_COMPONENT, CS4231_PWR_ON) ==
1730	    DDI_FAILURE) {
1731
1732		/* match the busy call above */
1733		(void) pm_idle_component(dip, CS4231_COMPONENT);
1734
1735		audio_dev_warn(state->cs_adev, "power up failed");
1736	}
1737
1738	eng->ce_started = B_FALSE;
1739	eng->ce_count = 0;
1740
1741	*fragfrp = eng->ce_fragfr;
1742	*nfragsp = CS4231_NFRAGS;
1743	*bufp = eng->ce_kaddr;
1744
1745	mutex_enter(&state->cs_lock);
1746	audiocs_reset_engine(eng);
1747	mutex_exit(&state->cs_lock);
1748	return (0);
1749}
1750
1751/*
1752 * audiocs_close()
1753 *
1754 * Description:
1755 *	Closes an audio DMA engine that was previously opened.  Since
1756 *	nobody is using it, we take this opportunity to possibly power
1757 *	down the entire device.
1758 *
1759 * Arguments:
1760 *	void	*arg		The DMA engine to shut down
1761 */
1762static void
1763audiocs_close(void *arg)
1764{
1765	CS_engine_t	*eng = arg;
1766	CS_state_t	*state = eng->ce_state;
1767
1768	mutex_enter(&state->cs_lock);
1769	audiocs_stop_engine(eng);
1770	eng->ce_started = B_FALSE;
1771	mutex_exit(&state->cs_lock);
1772
1773	(void) pm_idle_component(state->cs_dip, CS4231_COMPONENT);
1774}
1775
1776/*
1777 * audiocs_stop()
1778 *
1779 * Description:
1780 *	This is called by the framework to stop an engine that is
1781 *	transferring data.
1782 *
1783 * Arguments:
1784 *	void	*arg		The DMA engine to stop
1785 */
1786static void
1787audiocs_stop(void *arg)
1788{
1789	CS_engine_t	*eng = arg;
1790	CS_state_t	*state = eng->ce_state;
1791
1792	mutex_enter(&state->cs_lock);
1793	if (eng->ce_started) {
1794		audiocs_stop_engine(eng);
1795		eng->ce_started = B_FALSE;
1796	}
1797	mutex_exit(&state->cs_lock);
1798}
1799
1800/*
1801 * audiocs_start()
1802 *
1803 * Description:
1804 *	This is called by the framework to start an engine transferring data.
1805 *
1806 * Arguments:
1807 *	void	*arg		The DMA engine to start
1808 *
1809 * Returns:
1810 *	0 	on success, an errno otherwise
1811 */
1812static int
1813audiocs_start(void *arg)
1814{
1815	CS_engine_t	*eng = arg;
1816	CS_state_t	*state = eng->ce_state;
1817	int		rv = 0;
1818
1819	mutex_enter(&state->cs_lock);
1820	if (!eng->ce_started) {
1821		if (audiocs_start_engine(eng) == DDI_SUCCESS) {
1822			eng->ce_started = B_TRUE;
1823		} else {
1824			rv = EIO;
1825		}
1826	}
1827	mutex_exit(&state->cs_lock);
1828	return (rv);
1829}
1830
1831/*
1832 * audiocs_format()
1833 *
1834 * Description:
1835 *	Called by the framework to query the format of the device.
1836 *
1837 * Arguments:
1838 *	void	*arg		The DMA engine to query
1839 *
1840 * Returns:
1841 *	AUDIO_FORMAT_S16_NE
1842 */
1843static int
1844audiocs_format(void *arg)
1845{
1846	_NOTE(ARGUNUSED(arg));
1847
1848	return (AUDIO_FORMAT_S16_NE);
1849}
1850
1851/*
1852 * audiocs_channels()
1853 *
1854 * Description:
1855 *	Called by the framework to query the channels of the device.
1856 *
1857 * Arguments:
1858 *	void	*arg		The DMA engine to query
1859 *
1860 * Returns:
1861 *	2 (stereo)
1862 */
1863static int
1864audiocs_channels(void *arg)
1865{
1866	_NOTE(ARGUNUSED(arg));
1867
1868	return (2);
1869}
1870
1871/*
1872 * audiocs_rates()
1873 *
1874 * Description:
1875 *	Called by the framework to query the sample rate of the device.
1876 *
1877 * Arguments:
1878 *	void	*arg		The DMA engine to query
1879 *
1880 * Returns:
1881 *	48000
1882 */
1883static int
1884audiocs_rate(void *arg)
1885{
1886	_NOTE(ARGUNUSED(arg));
1887
1888	return (48000);
1889}
1890
1891/*
1892 * audiocs_count()
1893 *
1894 * Description:
1895 *	This is called by the framework to get the engine's frame counter
1896 *
1897 * Arguments:
1898 *	void	*arg		The DMA engine to query
1899 *
1900 * Returns:
1901 *	frame count for current engine
1902 */
1903static uint64_t
1904audiocs_count(void *arg)
1905{
1906	CS_engine_t	*eng = arg;
1907	CS_state_t	*state = eng->ce_state;
1908	uint64_t	val;
1909
1910	mutex_enter(&state->cs_lock);
1911	val = eng->ce_count;
1912	mutex_exit(&state->cs_lock);
1913
1914	return (val);
1915}
1916
1917/*
1918 * audiocs_sync()
1919 *
1920 * Description:
1921 *	This is called by the framework to synchronize DMA caches.
1922 *
1923 * Arguments:
1924 *	void	*arg		The DMA engine to sync
1925 */
1926static void
1927audiocs_sync(void *arg, unsigned nframes)
1928{
1929	CS_engine_t *eng = arg;
1930	_NOTE(ARGUNUSED(nframes));
1931
1932	(void) ddi_dma_sync(eng->ce_dmah, 0, 0, eng->ce_syncdir);
1933}
1934
1935/*
1936 * audiocs_qlen()
1937 *
1938 * Description:
1939 *	This is called by the framework to determine on-device queue length.
1940 *
1941 * Arguments:
1942 *	void	*arg		The DMA engine to query
1943 *
1944 * Returns:
1945 *	hardware queue length not reported by count (0 for this device)
1946 */
1947static size_t
1948audiocs_qlen(void *arg)
1949{
1950	CS_engine_t	*eng = arg;
1951
1952	return (eng->ce_fragfr);
1953}
1954
1955
1956/*
1957 * audiocs_reset_engine()
1958 *
1959 * Description:
1960 *	This routine resets the DMA engine pareparing it for work.
1961 *
1962 * Arguments:
1963 *	CS_engine_t	*engine		DMA engine to stop.
1964 */
1965void
1966audiocs_reset_engine(CS_engine_t *eng)
1967{
1968	CS_state_t	*state = eng->ce_state;
1969	uint8_t		mask;
1970	uint8_t		value;
1971	uint8_t		reg;
1972
1973	if (eng->ce_num == CS4231_PLAY) {
1974		/* sample rate only set on play side */
1975		value = FS_48000 | PDF_STEREO | PDF_LINEAR16NE;
1976		reg = FSDF_REG;
1977		mask = FSDF_VALID_MASK;
1978	} else {
1979		value = CDF_STEREO | CDF_LINEAR16NE;
1980		reg = CDF_REG;
1981		mask = CDF_VALID_MASK;
1982	}
1983
1984	SELIDX(state, reg | IAR_MCE);
1985	PUTIDX(state, value, mask);
1986
1987	(void) audiocs_poll_ready(state);
1988
1989	/* clear the mode change bit */
1990	SELIDX(state, reg);
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 */
2007int
2008audiocs_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 */
2134void
2135audiocs_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 */
2171int
2172audiocs_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 */
2209void
2210audiocs_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 */
2253int
2254audiocs_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 */
2318void
2319#ifdef	DEBUG
2320audiocs_sel_index(CS_state_t *state, uint8_t reg, int n)
2321#else
2322audiocs_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 */
2371void
2372#ifdef DEBUG
2373audiocs_put_index(CS_state_t *state, uint8_t val, uint8_t mask, int n)
2374#else
2375audiocs_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