xref: /illumos-gate/usr/src/uts/common/io/audio/drv/audioens/audioens.c (revision 635216b673cf196ac523ff2a7ab715717e553292)
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  * Purpose: Creative/Ensoniq AudioPCI97  driver (ES1371/ES1373)
27  *
28  * This driver is used with the original Ensoniq AudioPCI97 card and many
29  * PCI based Sound Blaster cards by Creative Technologies. For example
30  * Sound Blaster PCI128 and Creative/Ectiva EV1938.
31  */
32 
33 /*
34  * This file is part of Open Sound System
35  *
36  * Copyright (C) 4Front Technologies 1996-2008.
37  *
38  * This software is released under CDDL 1.0 source license.
39  * See the COPYING file included in the main directory of this source
40  * distribution for the license terms and conditions.
41  */
42 
43 #include <sys/audio/audio_driver.h>
44 #include <sys/audio/ac97.h>
45 #include <sys/note.h>
46 #include <sys/pci.h>
47 #include "audioens.h"
48 
49 /*
50  * The original OSS driver used a single duplex engine and a separate
51  * playback only engine.  Instead, we expose three engines, one for input
52  * and two for output.
53  */
54 
55 /*
56  * Set the latency to 32, 64, 96, 128 clocks - some APCI97 devices exhibit
57  * garbled audio in some cases and setting the latency to higer values fixes it
58  * Values: 32, 64, 96, 128 - Default: 64 (or defined by bios)
59  */
60 int audioens_latency = 0;
61 
62 /*
63  * Enable SPDIF port on SoundBlaster 128D or Sound Blaster Digital-4.1 models
64  * Values: 1=Enable 0=Disable Default: 0
65  */
66 int audioens_spdif = 0;
67 
68 /*
69  * Note: Latest devices can support SPDIF with AC3 pass thru.
70  * However, in order to do this, one of the two DMA engines must be
71  * dedicated to this, which would prevent the card from supporting 4
72  * channel audio.  For now we don't bother with the AC3 pass through
73  * mode, and instead just focus on 4 channel support.  In the future,
74  * this could be selectable via a property.
75  */
76 
77 #define	ENSONIQ_VENDOR_ID	0x1274
78 #define	CREATIVE_VENDOR_ID	0x1102
79 #define	ECTIVA_VENDOR_ID	0x1102
80 #define	ENSONIQ_ES1371		0x1371
81 #define	ENSONIQ_ES5880		0x8001
82 #define	ENSONIQ_ES5880A		0x8002
83 #define	ENSONIQ_ES5880B		0x5880
84 #define	ECTIVA_ES1938		0x8938
85 
86 #define	DEFRATE			48000
87 #define	DEFINTS			75
88 #define	DRVNAME			"audioens"
89 
90 typedef struct audioens_port
91 {
92 	/* Audio parameters */
93 	boolean_t		trigger;
94 	boolean_t		suspended;
95 
96 	int			speed;
97 
98 	int			num;
99 #define	PORT_DAC		0
100 #define	PORT_ADC		1
101 #define	PORT_MAX		PORT_ADC
102 
103 	caddr_t			kaddr;
104 	uint32_t		paddr;
105 	ddi_acc_handle_t	acch;
106 	ddi_dma_handle_t	dmah;
107 	int			nchan;
108 	unsigned		fragfr;
109 	unsigned		nfrags;
110 	unsigned		nframes;
111 	unsigned		frameno;
112 	uint64_t		count;
113 
114 	struct audioens_dev	*dev;
115 	audio_engine_t	*engine;
116 } audioens_port_t;
117 
118 typedef struct audioens_dev
119 {
120 	audio_dev_t		*osdev;
121 	kmutex_t		mutex;
122 	uint16_t		devid;
123 	uint8_t			revision;
124 	dev_info_t		*dip;
125 	boolean_t		enabled;
126 
127 
128 	int			pintrs;
129 	int			rintrs;
130 
131 	kstat_t			*ksp;
132 
133 	audioens_port_t		port[PORT_MAX + 1];
134 
135 	ac97_t			*ac97;
136 
137 	caddr_t			regs;
138 	ddi_acc_handle_t	acch;
139 	ddi_intr_handle_t	ihandle[1];
140 } audioens_dev_t;
141 
142 static ddi_device_acc_attr_t acc_attr = {
143 	DDI_DEVICE_ATTR_V0,
144 	DDI_STRUCTURE_LE_ACC,
145 	DDI_STRICTORDER_ACC
146 };
147 
148 static ddi_device_acc_attr_t buf_attr = {
149 	DDI_DEVICE_ATTR_V0,
150 	DDI_NEVERSWAP_ACC,
151 	DDI_STRICTORDER_ACC
152 };
153 
154 /*
155  * The hardware appears to be able to address up to 16-bits worth of longwords,
156  * giving a total address space of 256K.  Note, however, that we will restrict
157  * this further when we do fragment and memory allocation.  At its very highest
158  * clock rate (48 kHz) and sample size (16-bit stereo), and lowest interrupt
159  * rate (32 Hz), we only need 6000 bytes per fragment.
160  *
161  * So with an allocated buffer size of 64K, we can support at least 10 frags,
162  * which is more than enough.  (The legacy Sun driver used only 2 fragments.)
163  */
164 #define	AUDIOENS_BUF_LEN	(65536)
165 
166 static ddi_dma_attr_t dma_attr = {
167 	DMA_ATTR_VERSION,	/* dma_attr_version */
168 	0x0,			/* dma_attr_addr_lo */
169 	0xffffffffU,		/* dma_attr_addr_hi */
170 	0x3ffff,		/* dma_attr_count_max */
171 	0x8,			/* dma_attr_align */
172 	0x7f,			/* dma_attr_burstsizes */
173 	0x1,			/* dma_attr_minxfer */
174 	0x3ffff,		/* dma_attr_maxxfer */
175 	0x3ffff,		/* dma_attr_seg */
176 	0x1,			/* dma_attr_sgllen */
177 	0x1,			/* dma_attr_granular */
178 	0			/* dma_attr_flags */
179 };
180 
181 #define	GET8(dev, offset)	\
182 	ddi_get8(dev->acch, (uint8_t *)(dev->regs + (offset)))
183 #define	GET16(dev, offset)	\
184 	ddi_get16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)))
185 #define	GET32(dev, offset)	\
186 	ddi_get32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset)))
187 #define	PUT8(dev, offset, v)	\
188 	ddi_put8(dev->acch, (uint8_t *)(dev->regs + (offset)), v)
189 #define	PUT16(dev, offset, v)	\
190 	ddi_put16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)), v)
191 #define	PUT32(dev, offset, v)	\
192 	ddi_put32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset)), v)
193 
194 #define	CLR8(dev, offset, v)	PUT8(dev, offset, GET8(dev, offset) & ~(v))
195 #define	SET8(dev, offset, v)	PUT8(dev, offset, GET8(dev, offset) | (v))
196 #define	CLR32(dev, offset, v)	PUT32(dev, offset, GET32(dev, offset) & ~(v))
197 #define	SET32(dev, offset, v)	PUT32(dev, offset, GET32(dev, offset) | (v))
198 
199 #define	KSINTR(dev)	((kstat_intr_t *)((dev)->ksp->ks_data))
200 
201 static void audioens_init_hw(audioens_dev_t *);
202 static void audioens_init_port(audioens_port_t *);
203 static void audioens_start_port(audioens_port_t *);
204 static void audioens_stop_port(audioens_port_t *);
205 static void audioens_update_port(audioens_port_t *);
206 
207 static uint16_t
208 audioens_rd97(void *dev_, uint8_t wAddr)
209 {
210 	audioens_dev_t *dev = dev_;
211 	int i, dtemp;
212 
213 	mutex_enter(&dev->mutex);
214 	dtemp = GET32(dev, CONC_dCODECCTL_OFF);
215 	/* wait for WIP to go away saving the current state for later */
216 	for (i = 0; i < 0x100UL; ++i) {
217 		dtemp = GET32(dev, CONC_dCODECCTL_OFF);
218 		if ((dtemp & (1UL << 30)) == 0)
219 			break;
220 	}
221 
222 	/* write addr w/data=0 and assert read request ... */
223 	PUT32(dev, CONC_dCODECCTL_OFF, ((int)wAddr << 16) | (1UL << 23));
224 
225 	/* now wait for the data (RDY) */
226 	for (i = 0; i < 0x100UL; ++i) {
227 		dtemp = GET32(dev, CONC_dCODECCTL_OFF);
228 		if (dtemp & (1UL << 31))
229 			break;
230 	}
231 	dtemp = GET32(dev, CONC_dCODECCTL_OFF);
232 	mutex_exit(&dev->mutex);
233 
234 	return (dtemp & 0xffff);
235 }
236 
237 static void
238 audioens_wr97(void *dev_, uint8_t wAddr, uint16_t wData)
239 {
240 	audioens_dev_t *dev = dev_;
241 	int i, dtemp;
242 
243 	mutex_enter(&dev->mutex);
244 	/* wait for WIP to go away */
245 	for (i = 0; i < 0x100UL; ++i) {
246 		dtemp = GET32(dev, CONC_dCODECCTL_OFF);
247 		if ((dtemp & (1UL << 30)) == 0)
248 			break;
249 	}
250 
251 	PUT32(dev, CONC_dCODECCTL_OFF, ((int)wAddr << 16) | wData);
252 
253 	mutex_exit(&dev->mutex);
254 }
255 
256 static unsigned short
257 SRCRegRead(audioens_dev_t *dev, unsigned short reg)
258 {
259 	int i, dtemp;
260 
261 	dtemp = GET32(dev, CONC_dSRCIO_OFF);
262 	/* wait for ready */
263 	for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
264 		dtemp = GET32(dev, CONC_dSRCIO_OFF);
265 		if ((dtemp & SRC_BUSY) == 0)
266 			break;
267 	}
268 
269 	/* assert a read request */
270 	PUT32(dev, CONC_dSRCIO_OFF, (dtemp & SRC_CTLMASK) | ((int)reg << 25));
271 
272 	/* now wait for the data */
273 	for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
274 		dtemp = GET32(dev, CONC_dSRCIO_OFF);
275 		if ((dtemp & SRC_BUSY) == 0)
276 			break;
277 	}
278 
279 	return ((unsigned short) dtemp);
280 }
281 
282 static void
283 SRCRegWrite(audioens_dev_t *dev, unsigned short reg, unsigned short val)
284 {
285 	int i, dtemp;
286 	int writeval;
287 
288 	dtemp = GET32(dev, CONC_dSRCIO_OFF);
289 	/* wait for ready */
290 	for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
291 		dtemp = GET32(dev, CONC_dSRCIO_OFF);
292 		if ((dtemp & SRC_BUSY) == 0)
293 			break;
294 	}
295 
296 	/* assert the write request */
297 	writeval = (dtemp & SRC_CTLMASK) | SRC_WENABLE |
298 	    ((int)reg << 25) | val;
299 	PUT32(dev, CONC_dSRCIO_OFF, writeval);
300 }
301 
302 static void
303 SRCSetRate(audioens_dev_t *dev, unsigned char base, unsigned short rate)
304 {
305 	int i, freq, dtemp;
306 	unsigned short N, truncM, truncStart;
307 
308 	if (base != SRC_ADC_BASE) {
309 		/* freeze the channel */
310 		dtemp = (base == SRC_DAC1_BASE) ?
311 		    SRC_DAC1FREEZE : SRC_DAC2FREEZE;
312 		for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
313 			if (!(GET32(dev, CONC_dSRCIO_OFF) & SRC_BUSY))
314 				break;
315 		}
316 		PUT32(dev, CONC_dSRCIO_OFF,
317 		    (GET32(dev, CONC_dSRCIO_OFF) & SRC_CTLMASK) | dtemp);
318 
319 		/* calculate new frequency and write it - preserve accum */
320 		freq = ((int)rate << 16) / 3000U;
321 		SRCRegWrite(dev, (unsigned short) base + SRC_INT_REGS_OFF,
322 		    (SRCRegRead(dev, (unsigned short) base + SRC_INT_REGS_OFF)
323 		    & 0x00ffU) | ((unsigned short) (freq >> 6) & 0xfc00));
324 		SRCRegWrite(dev, (unsigned short) base + SRC_VFREQ_FRAC_OFF,
325 		    (unsigned short) freq >> 1);
326 
327 		/* un-freeze the channel */
328 		for (i = 0; i < SRC_IOPOLL_COUNT; ++i)
329 			if (!(GET32(dev, CONC_dSRCIO_OFF) & SRC_BUSY))
330 				break;
331 		PUT32(dev, CONC_dSRCIO_OFF,
332 		    (GET32(dev, CONC_dSRCIO_OFF) & SRC_CTLMASK) & ~dtemp);
333 	} else {
334 		/* derive oversample ratio */
335 		N = rate / 3000U;
336 		if (N == 15 || N == 13 || N == 11 || N == 9)
337 			--N;
338 
339 		/* truncate the filter and write n/trunc_start */
340 		truncM = (21 * N - 1) | 1;
341 		if (rate >= 24000U) {
342 			if (truncM > 239)
343 				truncM = 239;
344 			truncStart = (239 - truncM) >> 1;
345 
346 			SRCRegWrite(dev, base + SRC_TRUNC_N_OFF,
347 			    (truncStart << 9) | (N << 4));
348 		} else {
349 			if (truncM > 119)
350 				truncM = 119;
351 			truncStart = (119 - truncM) >> 1;
352 
353 			SRCRegWrite(dev, base + SRC_TRUNC_N_OFF,
354 			    0x8000U | (truncStart << 9) | (N << 4));
355 		}
356 
357 		/* calculate new frequency and write it - preserve accum */
358 		freq = ((48000UL << 16) / rate) * N;
359 		SRCRegWrite(dev, base + SRC_INT_REGS_OFF,
360 		    (SRCRegRead(dev, (unsigned short) base + SRC_INT_REGS_OFF)
361 		    & 0x00ff) | ((unsigned short) (freq >> 6) & 0xfc00));
362 		SRCRegWrite(dev, base + SRC_VFREQ_FRAC_OFF,
363 		    (unsigned short) freq >> 1);
364 
365 		SRCRegWrite(dev, SRC_ADC_VOL_L, N << 8);
366 		SRCRegWrite(dev, SRC_ADC_VOL_R, N << 8);
367 	}
368 }
369 
370 static void
371 SRCInit(audioens_dev_t *dev)
372 {
373 	int i;
374 
375 	/* Clear all SRC RAM then init - keep SRC disabled until done */
376 	for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
377 		if (!(GET32(dev, CONC_dSRCIO_OFF) & SRC_BUSY))
378 			break;
379 	}
380 	PUT32(dev, CONC_dSRCIO_OFF, SRC_DISABLE);
381 
382 	for (i = 0; i < 0x80; ++i)
383 		SRCRegWrite(dev, (unsigned short) i, 0U);
384 
385 	SRCRegWrite(dev, SRC_DAC1_BASE + SRC_TRUNC_N_OFF, 16 << 4);
386 	SRCRegWrite(dev, SRC_DAC1_BASE + SRC_INT_REGS_OFF, 16 << 10);
387 	SRCRegWrite(dev, SRC_DAC2_BASE + SRC_TRUNC_N_OFF, 16 << 4);
388 	SRCRegWrite(dev, SRC_DAC2_BASE + SRC_INT_REGS_OFF, 16 << 10);
389 	SRCRegWrite(dev, SRC_DAC1_VOL_L, 1 << 12);
390 	SRCRegWrite(dev, SRC_DAC1_VOL_R, 1 << 12);
391 	SRCRegWrite(dev, SRC_DAC2_VOL_L, 1 << 12);
392 	SRCRegWrite(dev, SRC_DAC2_VOL_R, 1 << 12);
393 	SRCRegWrite(dev, SRC_ADC_VOL_L, 1 << 12);
394 	SRCRegWrite(dev, SRC_ADC_VOL_R, 1 << 12);
395 
396 	/* default some rates */
397 	SRCSetRate(dev, SRC_DAC1_BASE, 48000);
398 	SRCSetRate(dev, SRC_DAC2_BASE, 48000);
399 	SRCSetRate(dev, SRC_ADC_BASE, 48000);
400 
401 	/* now enable the whole deal */
402 	for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
403 		if (!(GET32(dev, CONC_dSRCIO_OFF) & SRC_BUSY))
404 			break;
405 	}
406 	PUT32(dev, CONC_dSRCIO_OFF, 0);
407 }
408 
409 static void
410 audioens_writemem(audioens_dev_t *dev, uint32_t page, uint32_t offs,
411     uint32_t data)
412 {
413 	/* Select memory page */
414 	PUT32(dev, CONC_bMEMPAGE_OFF, page);
415 	PUT32(dev, offs, data);
416 }
417 
418 static uint32_t
419 audioens_readmem(audioens_dev_t *dev, uint32_t page, uint32_t offs)
420 {
421 	PUT32(dev, CONC_bMEMPAGE_OFF, page);	/* Select memory page */
422 	return (GET32(dev, offs));
423 }
424 
425 static uint_t
426 audioens_intr(caddr_t arg1, caddr_t arg2)
427 {
428 	audioens_dev_t *dev = (void *)arg1;
429 	int stats;
430 	int tmp;
431 	unsigned char ackbits = 0;
432 	audioens_port_t *port;
433 	audio_engine_t *do_dac, *do_adc;
434 
435 	_NOTE(ARGUNUSED(arg2));
436 
437 	/*
438 	 * NB: The old audioens didn't report spurious interrupts.  On
439 	 * a system with shared interrupts (typical!) there will
440 	 * normally be lots of these (each time the "other" device
441 	 * interrupts).
442 	 *
443 	 * Also, because of the way the interrupt chain handling
444 	 * works, reporting of spurious interrupts is probably not
445 	 * terribly useful.
446 	 *
447 	 * However, we can count interrupts where the master interrupt
448 	 * bit is set but none of the ackbits that we are prepared to
449 	 * process is set.  That is probably useful.
450 	 */
451 	mutex_enter(&dev->mutex);
452 	if (!dev->enabled) {
453 
454 		mutex_exit(&dev->mutex);
455 		return (DDI_INTR_UNCLAIMED);
456 	}
457 
458 	stats = GET32(dev, CONC_dSTATUS_OFF);
459 
460 	if (!(stats & CONC_STATUS_PENDING)) {	/* No interrupt pending */
461 		mutex_exit(&dev->mutex);
462 		return (DDI_INTR_UNCLAIMED);
463 	}
464 
465 	do_dac = do_adc = NULL;
466 
467 	/* DAC1 (synth) interrupt */
468 	if (stats & CONC_STATUS_DAC1INT) {
469 
470 		ackbits |= CONC_SERCTL_DAC1IE;
471 		port = &dev->port[PORT_DAC];
472 		if (port->trigger) {
473 			do_dac = port->engine;
474 		}
475 	}
476 
477 	/* DAC2 interrupt */
478 	if (stats & CONC_STATUS_DAC2INT) {
479 
480 		ackbits |= CONC_SERCTL_DAC2IE;
481 	}
482 
483 	/* ADC interrupt */
484 	if (stats & CONC_STATUS_ADCINT) {
485 
486 		ackbits |= CONC_SERCTL_ADCIE;
487 		port = &dev->port[PORT_ADC];
488 
489 		if (port->trigger) {
490 			do_adc = port->engine;
491 		}
492 	}
493 
494 	/* UART interrupt - we shouldn't get this! */
495 	if (stats & CONC_STATUS_UARTINT) {
496 		uint8_t uart_stat = GET8(dev, CONC_bUARTCSTAT_OFF);
497 		while (uart_stat & CONC_UART_RXRDY)
498 			uart_stat = GET8(dev, CONC_bUARTCSTAT_OFF);
499 	}
500 
501 	/* Ack the interrupt */
502 	tmp = GET8(dev, CONC_bSERCTL_OFF);
503 	PUT8(dev, CONC_bSERCTL_OFF, tmp & (~ackbits));	/* Clear bits */
504 	PUT8(dev, CONC_bSERCTL_OFF, tmp | ackbits);	/* Turn them back on */
505 
506 	if (dev->ksp) {
507 		if (ackbits == 0) {
508 			KSINTR(dev)->intrs[KSTAT_INTR_SPURIOUS]++;
509 		} else {
510 			KSINTR(dev)->intrs[KSTAT_INTR_HARD]++;
511 		}
512 	}
513 
514 	mutex_exit(&dev->mutex);
515 
516 	if (do_dac)
517 		audio_engine_consume(do_dac);
518 	if (do_adc)
519 		audio_engine_produce(do_adc);
520 
521 	return (DDI_INTR_CLAIMED);
522 }
523 
524 /*
525  * Audio routines
526  */
527 static int
528 audioens_format(void *arg)
529 {
530 	_NOTE(ARGUNUSED(arg));
531 
532 	/* hardware can also do AUDIO_FORMAT_U8, but no need for it */
533 	return (AUDIO_FORMAT_S16_LE);
534 }
535 
536 static int
537 audioens_channels(void *arg)
538 {
539 	audioens_port_t *port = arg;
540 
541 	return (port->nchan);
542 }
543 
544 static int
545 audioens_rate(void *arg)
546 {
547 	audioens_port_t *port = arg;
548 
549 	return (port->speed);
550 }
551 
552 static void
553 audioens_init_port(audioens_port_t *port)
554 {
555 	audioens_dev_t	*dev = port->dev;
556 	unsigned tmp;
557 
558 	if (port->suspended)
559 		return;
560 
561 	switch (port->num) {
562 	case PORT_DAC:
563 		/* Set physical address of the DMA buffer */
564 		audioens_writemem(dev, CONC_DAC1CTL_PAGE, CONC_dDAC1PADDR_OFF,
565 		    port->paddr);
566 		audioens_writemem(dev, CONC_DAC2CTL_PAGE, CONC_dDAC2PADDR_OFF,
567 		    port->paddr + (port->nframes * sizeof (int16_t) * 2));
568 
569 		/* Set DAC rate */
570 		SRCSetRate(dev, SRC_DAC1_BASE, port->speed);
571 		SRCSetRate(dev, SRC_DAC2_BASE, port->speed);
572 
573 		/* Configure the channel setup - SPDIF only uses front */
574 		tmp = GET32(dev, CONC_dSTATUS_OFF);
575 		tmp &= ~(CONC_STATUS_SPKR_MASK | CONC_STATUS_SPDIF_MASK);
576 		tmp |= CONC_STATUS_SPKR_4CH | CONC_STATUS_SPDIF_P1;
577 		PUT32(dev, CONC_dSTATUS_OFF, tmp);
578 
579 		/* Set format */
580 		PUT8(dev, CONC_bSKIPC_OFF, 0x10);
581 		SET8(dev, CONC_bSERFMT_OFF,
582 		    CONC_PCM_DAC1_16BIT | CONC_PCM_DAC2_16BIT |
583 		    CONC_PCM_DAC1_STEREO | CONC_PCM_DAC2_STEREO);
584 
585 		/* Set the frame count */
586 		audioens_writemem(dev, CONC_DAC1CTL_PAGE, CONC_wDAC1FC_OFF,
587 		    port->nframes - 1);
588 		audioens_writemem(dev, CONC_DAC2CTL_PAGE, CONC_wDAC2FC_OFF,
589 		    port->nframes - 1);
590 
591 		/* Set # of frames between interrupts */
592 		PUT16(dev, CONC_wDAC1IC_OFF, port->fragfr - 1);
593 		PUT16(dev, CONC_wDAC2IC_OFF, port->fragfr - 1);
594 		break;
595 
596 	case PORT_ADC:
597 		/* Set physical address of the DMA buffer */
598 		audioens_writemem(dev, CONC_ADCCTL_PAGE, CONC_dADCPADDR_OFF,
599 		    port->paddr);
600 
601 		/* Set ADC rate */
602 		SRCSetRate(dev, SRC_ADC_BASE, port->speed);
603 
604 		/* Set format - for input we only support 16 bit input */
605 		tmp = GET8(dev, CONC_bSERFMT_OFF);
606 		tmp |= CONC_PCM_ADC_16BIT;
607 		tmp |= CONC_PCM_ADC_STEREO;
608 
609 		PUT8(dev, CONC_bSKIPC_OFF, 0x10);
610 
611 		PUT8(dev, CONC_bSERFMT_OFF, tmp);
612 
613 		/* Set the frame count */
614 		audioens_writemem(dev, CONC_ADCCTL_PAGE, CONC_wADCFC_OFF,
615 		    port->nframes - 1);
616 
617 		/* Set # of frames between interrupts */
618 		PUT16(dev, CONC_wADCIC_OFF, port->fragfr - 1);
619 
620 		break;
621 	}
622 
623 	port->frameno = 0;
624 }
625 
626 static int
627 audioens_open(void *arg, int flag, unsigned *fragfrp, unsigned *nfragsp,
628     caddr_t *bufp)
629 {
630 	audioens_port_t	*port = arg;
631 	audioens_dev_t	*dev = port->dev;
632 	int intrs;
633 
634 	_NOTE(ARGUNUSED(flag));
635 
636 	mutex_enter(&dev->mutex);
637 
638 	if (port->num == PORT_ADC) {
639 		intrs = dev->rintrs;
640 	} else {
641 		intrs = dev->pintrs;
642 	}
643 
644 	/* interrupt at least at 25 Hz, and not more than 250 Hz */
645 	intrs = min(250, max(25, intrs));
646 
647 	port->fragfr = (port->speed / intrs);
648 	port->nfrags = AUDIOENS_BUF_LEN /
649 	    (port->fragfr * port->nchan * sizeof (int16_t));
650 	port->nfrags = max(4, min(port->nfrags, 1024));
651 	port->nframes = port->nfrags * port->fragfr;
652 	port->trigger = B_FALSE;
653 	port->count = 0;
654 
655 	audioens_init_port(port);
656 
657 	*fragfrp = port->fragfr;
658 	*nfragsp = port->nfrags;
659 	*bufp = port->kaddr;
660 	mutex_exit(&dev->mutex);
661 
662 	return (0);
663 }
664 
665 static void
666 audioens_start_port(audioens_port_t *port)
667 {
668 	audioens_dev_t *dev = port->dev;
669 
670 	if (!port->suspended) {
671 		switch (port->num) {
672 		case PORT_DAC:
673 			SET8(dev, CONC_bDEVCTL_OFF,
674 			    CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_DAC1_EN);
675 			SET8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_DAC1IE);
676 			break;
677 		case PORT_ADC:
678 			SET8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_ADC_EN);
679 			SET8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_ADCIE);
680 			break;
681 		}
682 	}
683 }
684 
685 static void
686 audioens_stop_port(audioens_port_t *port)
687 {
688 	audioens_dev_t *dev = port->dev;
689 
690 	if (!port->suspended) {
691 		switch (port->num) {
692 		case PORT_DAC:
693 			CLR8(dev, CONC_bDEVCTL_OFF,
694 			    CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_DAC1_EN);
695 			CLR8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_DAC1IE);
696 			break;
697 		case PORT_ADC:
698 			CLR8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_ADC_EN);
699 			CLR8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_ADCIE);
700 			break;
701 		}
702 	}
703 }
704 
705 static int
706 audioens_start(void *arg)
707 {
708 	audioens_port_t *port = arg;
709 	audioens_dev_t *dev = port->dev;
710 
711 	mutex_enter(&dev->mutex);
712 	if (!port->trigger) {
713 		port->trigger = B_TRUE;
714 		audioens_start_port(port);
715 	}
716 	mutex_exit(&dev->mutex);
717 
718 	return (0);
719 }
720 
721 static void
722 audioens_stop(void *arg)
723 {
724 	audioens_port_t *port = arg;
725 	audioens_dev_t *dev = port->dev;
726 
727 	mutex_enter(&dev->mutex);
728 	if (port->trigger) {
729 		port->trigger = B_FALSE;
730 		audioens_stop_port(port);
731 	}
732 	mutex_exit(&dev->mutex);
733 }
734 
735 static void
736 audioens_update_port(audioens_port_t *port)
737 {
738 	uint32_t page, offs;
739 	int frameno, n;
740 
741 	switch (port->num) {
742 	case PORT_DAC:
743 		page = CONC_DAC1CTL_PAGE;
744 		offs = CONC_wDAC1FC_OFF;
745 		break;
746 
747 	case PORT_ADC:
748 		page = CONC_ADCCTL_PAGE;
749 		offs = CONC_wADCFC_OFF;
750 		break;
751 	}
752 
753 	/*
754 	 * Note that the current frame counter is in the high nybble.
755 	 */
756 	frameno = audioens_readmem(port->dev, page, offs) >> 16;
757 	n = frameno >= port->frameno ?
758 	    frameno - port->frameno :
759 	    frameno + port->nframes - port->frameno;
760 	port->frameno = frameno;
761 	port->count += n;
762 }
763 
764 static uint64_t
765 audioens_count(void *arg)
766 {
767 	audioens_port_t *port = arg;
768 	audioens_dev_t *dev = port->dev;
769 	uint64_t val;
770 
771 	mutex_enter(&dev->mutex);
772 	if (!port->suspended) {
773 		audioens_update_port(port);
774 	}
775 	val = port->count;
776 	mutex_exit(&dev->mutex);
777 	return (val);
778 }
779 
780 static void
781 audioens_close(void *arg)
782 {
783 	audioens_port_t *port = arg;
784 
785 	audioens_stop(port);
786 }
787 
788 static void
789 audioens_sync(void *arg, unsigned nframes)
790 {
791 	audioens_port_t *port = arg;
792 
793 	_NOTE(ARGUNUSED(nframes));
794 
795 	if (port->num == PORT_ADC) {
796 		(void) ddi_dma_sync(port->dmah, 0, 0, DDI_DMA_SYNC_FORCPU);
797 	} else {
798 		(void) ddi_dma_sync(port->dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
799 	}
800 }
801 
802 static size_t
803 audioens_qlen(void *arg)
804 {
805 	audioens_port_t *port = arg;
806 
807 	return (port->fragfr);
808 }
809 
810 static void
811 audioens_chinfo(void *arg, int chan, unsigned *offset, unsigned *incr)
812 {
813 	audioens_port_t *port = arg;
814 
815 	if ((port->num == PORT_DAC) && (chan >= 2)) {
816 		*offset = (port->nframes * 2) + (chan % 2);
817 		*incr = 2;
818 	} else {
819 		*offset = chan;
820 		*incr = 2;
821 	}
822 }
823 
824 audio_engine_ops_t audioens_engine_ops = {
825 	AUDIO_ENGINE_VERSION,		/* version number */
826 	audioens_open,
827 	audioens_close,
828 	audioens_start,
829 	audioens_stop,
830 	audioens_count,
831 	audioens_format,
832 	audioens_channels,
833 	audioens_rate,
834 	audioens_sync,
835 	audioens_qlen,
836 	audioens_chinfo
837 };
838 
839 void
840 audioens_init_hw(audioens_dev_t *dev)
841 {
842 	int tmp;
843 
844 	if ((dev->devid == ENSONIQ_ES5880) ||
845 	    (dev->devid == ENSONIQ_ES5880A) ||
846 	    (dev->devid == ENSONIQ_ES5880B) ||
847 	    (dev->devid == 0x1371 && dev->revision == 7) ||
848 	    (dev->devid == 0x1371 && dev->revision >= 9)) {
849 
850 		/* Have a ES5880 so enable the codec manually */
851 		tmp = GET8(dev, CONC_bINTSUMM_OFF) & 0xff;
852 		tmp |= 0x20;
853 		PUT8(dev, CONC_bINTSUMM_OFF, tmp);
854 		for (int i = 0; i < 2000; i++)
855 			drv_usecwait(10);
856 	}
857 
858 	SRCInit(dev);
859 
860 #if 0
861 	PUT8(dev, CONC_bSERCTL_OFF, 0x00);
862 	PUT8(dev, CONC_bNMIENA_OFF, 0x00); /* NMI off */
863 	PUT8(dev, CONC_wNMISTAT_OFF, 0x00); /* PUT8? */
864 #endif
865 
866 	/*
867 	 * Turn on CODEC (UART and joystick left disabled)
868 	 */
869 	tmp = GET32(dev, CONC_bDEVCTL_OFF) & 0xff;
870 	tmp &= ~(CONC_DEVCTL_PCICLK_DS | CONC_DEVCTL_XTALCLK_DS);
871 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
872 	PUT8(dev, CONC_bUARTCSTAT_OFF, 0x00);
873 
874 	/* Perform AC97 codec warm reset */
875 	tmp = GET8(dev, CONC_bMISCCTL_OFF) & 0xff;
876 	PUT8(dev, CONC_bMISCCTL_OFF, tmp | CONC_MISCCTL_SYNC_RES);
877 	drv_usecwait(200);
878 	PUT8(dev, CONC_bMISCCTL_OFF, tmp);
879 	drv_usecwait(200);
880 
881 	if (dev->revision >= 4) {
882 		/* XXX: enable SPDIF - PCM only for now */
883 		if (audioens_spdif) {
884 			/* enable SPDIF */
885 			PUT32(dev, 0x04, GET32(dev, 0x04) | (1 << 18));
886 			/* SPDIF out = data from DAC */
887 			PUT32(dev, 0x00, GET32(dev, 0x00) | (1 << 26));
888 			CLR32(dev, CONC_dSPDIF_OFF, CONC_SPDIF_AC3);
889 
890 		} else {
891 			/* disable spdif out */
892 			PUT32(dev, 0x04, GET32(dev, 0x04) & ~(1 << 18));
893 			PUT32(dev, 0x00, GET32(dev, 0x00) & ~(1 << 26));
894 		}
895 
896 		/* we want to run each channel independently */
897 		CLR32(dev, CONC_dSTATUS_OFF, CONC_STATUS_ECHO);
898 	}
899 
900 	dev->enabled = B_TRUE;
901 }
902 
903 static int
904 audioens_init(audioens_dev_t *dev)
905 {
906 
907 	audioens_init_hw(dev);
908 
909 	/*
910 	 * On this hardware, we want to disable the internal speaker by
911 	 * default, if it exists.  (We don't have a speakerphone on any
912 	 * of these cards, and no SPARC hardware uses it either!)
913 	 */
914 	(void) ddi_prop_update_int(DDI_DEV_T_NONE, dev->dip, AC97_PROP_SPEAKER,
915 	    0);
916 
917 	/*
918 	 * Init mixer
919 	 */
920 
921 	dev->ac97 = ac97_alloc(dev->dip, audioens_rd97, audioens_wr97, dev);
922 	if (dev->ac97 == NULL)
923 		return (DDI_FAILURE);
924 
925 	if (ac97_init(dev->ac97, dev->osdev) != 0) {
926 		return (DDI_FAILURE);
927 	}
928 
929 	dev->pintrs = ddi_prop_get_int(DDI_DEV_T_ANY, dev->dip,
930 	    DDI_PROP_DONTPASS, "play-interrupts", DEFINTS);
931 
932 	dev->rintrs = ddi_prop_get_int(DDI_DEV_T_ANY, dev->dip,
933 	    DDI_PROP_DONTPASS, "record-interrupts", DEFINTS);
934 
935 	for (int i = 0; i <= PORT_MAX; i++) {
936 		audioens_port_t *port;
937 		unsigned caps;
938 		unsigned dmaflags;
939 		size_t rlen;
940 		ddi_dma_cookie_t c;
941 		unsigned ccnt;
942 
943 		port = &dev->port[i];
944 		port->dev = dev;
945 
946 		switch (i) {
947 		case PORT_DAC:
948 			port->nchan = 4;
949 			port->speed = 48000;
950 			caps = ENGINE_OUTPUT_CAP;
951 			dmaflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
952 			break;
953 
954 		case PORT_ADC:
955 			port->nchan = 2;
956 			port->speed = 48000;
957 			caps = ENGINE_INPUT_CAP;
958 			dmaflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
959 			break;
960 		}
961 
962 		port->num = i;
963 
964 		/*
965 		 * Allocate DMA resources.
966 		 */
967 
968 		if (ddi_dma_alloc_handle(dev->dip, &dma_attr, DDI_DMA_SLEEP,
969 		    NULL, &port->dmah) != DDI_SUCCESS) {
970 			audio_dev_warn(dev->osdev,
971 			    "port %d: dma handle allocation failed", i);
972 			return (DDI_FAILURE);
973 		}
974 		if (ddi_dma_mem_alloc(port->dmah, AUDIOENS_BUF_LEN, &buf_attr,
975 		    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &port->kaddr,
976 		    &rlen, &port->acch) != DDI_SUCCESS) {
977 			audio_dev_warn(dev->osdev,
978 			    "port %d: dma memory allocation failed", i);
979 			return (DDI_FAILURE);
980 		}
981 		/* ensure that the buffer is zeroed out properly */
982 		bzero(port->kaddr, rlen);
983 		if (ddi_dma_addr_bind_handle(port->dmah, NULL, port->kaddr,
984 		    AUDIOENS_BUF_LEN, dmaflags, DDI_DMA_SLEEP, NULL,
985 		    &c, &ccnt) != DDI_DMA_MAPPED) {
986 			audio_dev_warn(dev->osdev,
987 			    "port %d: dma binding failed", i);
988 			return (DDI_FAILURE);
989 		}
990 		port->paddr = c.dmac_address;
991 
992 		/*
993 		 * Allocate and configure audio engine.
994 		 */
995 		port->engine = audio_engine_alloc(&audioens_engine_ops, caps);
996 		if (port->engine == NULL) {
997 			audio_dev_warn(dev->osdev,
998 			    "port %d: audio_engine_alloc failed", i);
999 			return (DDI_FAILURE);
1000 		}
1001 
1002 		audio_engine_set_private(port->engine, port);
1003 		audio_dev_add_engine(dev->osdev, port->engine);
1004 	}
1005 
1006 	/*
1007 	 * Set up kstats for interrupt reporting.
1008 	 */
1009 	dev->ksp = kstat_create(ddi_driver_name(dev->dip),
1010 	    ddi_get_instance(dev->dip), ddi_driver_name(dev->dip),
1011 	    "controller", KSTAT_TYPE_INTR, 1, KSTAT_FLAG_PERSISTENT);
1012 	if (dev->ksp != NULL) {
1013 		kstat_install(dev->ksp);
1014 	}
1015 
1016 	if (audio_dev_register(dev->osdev) != DDI_SUCCESS) {
1017 		audio_dev_warn(dev->osdev,
1018 		    "unable to register with audio framework");
1019 		return (DDI_FAILURE);
1020 	}
1021 
1022 	return (DDI_SUCCESS);
1023 }
1024 
1025 int
1026 audioens_setup_interrupts(audioens_dev_t *dev)
1027 {
1028 	int actual;
1029 	uint_t ipri;
1030 
1031 	if ((ddi_intr_alloc(dev->dip, dev->ihandle, DDI_INTR_TYPE_FIXED,
1032 	    0, 1, &actual, DDI_INTR_ALLOC_NORMAL) != DDI_SUCCESS) ||
1033 	    (actual != 1)) {
1034 		audio_dev_warn(dev->osdev, "can't alloc intr handle");
1035 		return (DDI_FAILURE);
1036 	}
1037 
1038 	if (ddi_intr_get_pri(dev->ihandle[0], &ipri) != DDI_SUCCESS) {
1039 		audio_dev_warn(dev->osdev,  "can't determine intr priority");
1040 		(void) ddi_intr_free(dev->ihandle[0]);
1041 		dev->ihandle[0] = NULL;
1042 		return (DDI_FAILURE);
1043 	}
1044 
1045 	if (ddi_intr_add_handler(dev->ihandle[0], audioens_intr, dev,
1046 	    NULL) != DDI_SUCCESS) {
1047 		audio_dev_warn(dev->osdev, "can't add intr handler");
1048 		(void) ddi_intr_free(dev->ihandle[0]);
1049 		dev->ihandle[0] = NULL;
1050 		return (DDI_FAILURE);
1051 	}
1052 
1053 	mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, DDI_INTR_PRI(ipri));
1054 
1055 	return (DDI_SUCCESS);
1056 }
1057 
1058 void
1059 audioens_destroy(audioens_dev_t *dev)
1060 {
1061 	int	i;
1062 
1063 	if (dev->ihandle[0] != NULL) {
1064 		(void) ddi_intr_disable(dev->ihandle[0]);
1065 		(void) ddi_intr_remove_handler(dev->ihandle[0]);
1066 		(void) ddi_intr_free(dev->ihandle[0]);
1067 		mutex_destroy(&dev->mutex);
1068 	}
1069 
1070 	if (dev->ksp != NULL) {
1071 		kstat_delete(dev->ksp);
1072 	}
1073 
1074 	/* free up ports, including DMA resources for ports */
1075 	for (i = 0; i <= PORT_MAX; i++) {
1076 		audioens_port_t	*port = &dev->port[i];
1077 
1078 		if (port->paddr != 0)
1079 			(void) ddi_dma_unbind_handle(port->dmah);
1080 		if (port->acch != NULL)
1081 			ddi_dma_mem_free(&port->acch);
1082 		if (port->dmah != NULL)
1083 			ddi_dma_free_handle(&port->dmah);
1084 
1085 		if (port->engine != NULL) {
1086 			audio_dev_remove_engine(dev->osdev, port->engine);
1087 			audio_engine_free(port->engine);
1088 		}
1089 	}
1090 
1091 	if (dev->acch != NULL) {
1092 		ddi_regs_map_free(&dev->acch);
1093 	}
1094 
1095 	if (dev->ac97) {
1096 		ac97_free(dev->ac97);
1097 	}
1098 
1099 	if (dev->osdev != NULL) {
1100 		audio_dev_free(dev->osdev);
1101 	}
1102 
1103 	kmem_free(dev, sizeof (*dev));
1104 }
1105 
1106 int
1107 audioens_attach(dev_info_t *dip)
1108 {
1109 	uint16_t pci_command, vendor, device;
1110 	uint8_t revision;
1111 	audioens_dev_t *dev;
1112 	ddi_acc_handle_t pcih;
1113 	const char *chip_name;
1114 	const char *chip_vers;
1115 
1116 	dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
1117 	dev->dip = dip;
1118 	ddi_set_driver_private(dip, dev);
1119 
1120 	if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
1121 		audio_dev_warn(dev->osdev, "pci_config_setup failed");
1122 		kmem_free(dev, sizeof (*dev));
1123 		return (DDI_FAILURE);
1124 	}
1125 
1126 	vendor = pci_config_get16(pcih, PCI_CONF_VENID);
1127 	device = pci_config_get16(pcih, PCI_CONF_DEVID);
1128 	revision = pci_config_get8(pcih, PCI_CONF_REVID);
1129 
1130 	if ((vendor != ENSONIQ_VENDOR_ID && vendor != CREATIVE_VENDOR_ID) ||
1131 	    (device != ENSONIQ_ES1371 && device != ENSONIQ_ES5880 &&
1132 	    device != ENSONIQ_ES5880A && device != ECTIVA_ES1938 &&
1133 	    device != ENSONIQ_ES5880B))
1134 		goto err_exit;
1135 
1136 	chip_name = "AudioPCI97";
1137 	chip_vers = "unknown";
1138 
1139 	switch (device) {
1140 	case ENSONIQ_ES1371:
1141 		chip_name = "AudioPCI97";
1142 		switch (revision) {
1143 		case 0x02:
1144 		case 0x09:
1145 		default:
1146 			chip_vers = "ES1371";
1147 			break;
1148 		case 0x04:
1149 		case 0x06:
1150 		case 0x08:
1151 			chip_vers = "ES1373";
1152 			break;
1153 		case 0x07:
1154 			chip_vers = "ES5880";
1155 			break;
1156 		}
1157 		break;
1158 
1159 	case ENSONIQ_ES5880:
1160 		chip_name = "SB PCI128";
1161 		chip_vers = "ES5880";
1162 		break;
1163 	case ENSONIQ_ES5880A:
1164 		chip_name = "SB PCI128";
1165 		chip_vers = "ES5880A";
1166 		break;
1167 	case ENSONIQ_ES5880B:
1168 		chip_name = "SB PCI128";
1169 		chip_vers = "ES5880B";
1170 		break;
1171 
1172 	case ECTIVA_ES1938:
1173 		chip_name = "AudioPCI";
1174 		chip_vers = "ES1938";
1175 		break;
1176 	}
1177 
1178 	dev->revision = revision;
1179 	dev->devid = device;
1180 
1181 	dev->osdev = audio_dev_alloc(dip, 0);
1182 	if (dev->osdev == NULL) {
1183 		goto err_exit;
1184 	}
1185 
1186 	audio_dev_set_description(dev->osdev, chip_name);
1187 	audio_dev_set_version(dev->osdev, chip_vers);
1188 
1189 	/* set the PCI latency */
1190 	if ((audioens_latency == 32) || (audioens_latency == 64) ||
1191 	    (audioens_latency == 96))
1192 		pci_config_put8(pcih, PCI_CONF_LATENCY_TIMER,
1193 		    audioens_latency);
1194 
1195 	/* activate the device */
1196 	pci_command = pci_config_get16(pcih, PCI_CONF_COMM);
1197 	pci_command |= PCI_COMM_ME | PCI_COMM_IO;
1198 	pci_config_put16(pcih, PCI_CONF_COMM, pci_command);
1199 
1200 	/* map registers */
1201 	if (ddi_regs_map_setup(dip, 1, &dev->regs, 0, 0, &acc_attr,
1202 	    &dev->acch) != DDI_SUCCESS) {
1203 		audio_dev_warn(dev->osdev, "can't map registers");
1204 		goto err_exit;
1205 	}
1206 
1207 	if (audioens_setup_interrupts(dev) != DDI_SUCCESS) {
1208 		audio_dev_warn(dev->osdev, "can't register interrupts");
1209 		goto err_exit;
1210 	}
1211 
1212 	/* This allocates and configures the engines */
1213 	if (audioens_init(dev) != DDI_SUCCESS) {
1214 		audio_dev_warn(dev->osdev, "can't init device");
1215 		goto err_exit;
1216 	}
1217 
1218 	(void) ddi_intr_enable(dev->ihandle[0]);
1219 
1220 	pci_config_teardown(&pcih);
1221 
1222 	ddi_report_dev(dip);
1223 
1224 	return (DDI_SUCCESS);
1225 
1226 err_exit:
1227 	pci_config_teardown(&pcih);
1228 
1229 	audioens_destroy(dev);
1230 
1231 	return (DDI_FAILURE);
1232 }
1233 
1234 int
1235 audioens_detach(audioens_dev_t *dev)
1236 {
1237 	int tmp;
1238 
1239 	/* first unregister us from the DDI framework, might be busy */
1240 	if (audio_dev_unregister(dev->osdev) != DDI_SUCCESS)
1241 		return (DDI_FAILURE);
1242 
1243 	mutex_enter(&dev->mutex);
1244 
1245 	tmp = GET8(dev, CONC_bSERCTL_OFF) &
1246 	    ~(CONC_SERCTL_DAC2IE | CONC_SERCTL_DAC1IE | CONC_SERCTL_ADCIE);
1247 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1248 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1249 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1250 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1251 
1252 	tmp = GET8(dev, CONC_bDEVCTL_OFF) &
1253 	    ~(CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_DAC1_EN);
1254 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1255 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1256 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1257 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1258 
1259 	dev->enabled = B_FALSE;
1260 
1261 	mutex_exit(&dev->mutex);
1262 
1263 	audioens_destroy(dev);
1264 
1265 	return (DDI_SUCCESS);
1266 }
1267 
1268 /*ARGSUSED*/
1269 static int
1270 audioens_resume(audioens_dev_t *dev)
1271 {
1272 	/* ask framework to reset/relocate engine data */
1273 	for (int i = 0; i <= PORT_MAX; i++) {
1274 		audio_engine_reset(dev->port[i].engine);
1275 	}
1276 
1277 	/* reinitialize hardware */
1278 	audioens_init_hw(dev);
1279 
1280 	/* restore AC97 state */
1281 	ac97_resume(dev->ac97);
1282 
1283 	/* restart ports */
1284 	mutex_enter(&dev->mutex);
1285 	for (int i = 0; i < PORT_MAX; i++) {
1286 		audioens_port_t	*port = &dev->port[i];
1287 		port->suspended = B_FALSE;
1288 		audioens_init_port(port);
1289 		/* possibly start it up if was going when we suspended */
1290 		if (port->trigger) {
1291 			audioens_start_port(port);
1292 
1293 		}
1294 	}
1295 	mutex_exit(&dev->mutex);
1296 	for (int i = 0; i < PORT_MAX; i++) {
1297 		audioens_port_t	*port = &dev->port[i];
1298 		/* signal callbacks on resume */
1299 		if (!port->trigger)
1300 			continue;
1301 		if (port->num == PORT_ADC) {
1302 			audio_engine_produce(port->engine);
1303 		} else {
1304 			audio_engine_consume(port->engine);
1305 		}
1306 	}
1307 	return (DDI_SUCCESS);
1308 }
1309 
1310 /*ARGSUSED*/
1311 static int
1312 audioens_suspend(audioens_dev_t *dev)
1313 {
1314 	/*
1315 	 * Stop all engines/DMA data.
1316 	 */
1317 	mutex_enter(&dev->mutex);
1318 	for (int i = 0; i <= PORT_MAX; i++) {
1319 		audioens_stop_port(&dev->port[i]);
1320 		audioens_update_port(&dev->port[i]);
1321 		dev->port[i].suspended = B_TRUE;
1322 	}
1323 	dev->enabled = B_FALSE;
1324 	mutex_exit(&dev->mutex);
1325 
1326 	/*
1327 	 * Framework needs to save off AC'97 state.
1328 	 */
1329 	ac97_suspend(dev->ac97);
1330 
1331 	return (DDI_SUCCESS);
1332 }
1333 
1334 static int
1335 audioens_quiesce(dev_info_t *dip)
1336 {
1337 	audioens_dev_t	*dev;
1338 	uint8_t		tmp;
1339 
1340 	if ((dev = ddi_get_driver_private(dip)) == NULL) {
1341 		return (DDI_FAILURE);
1342 	}
1343 
1344 	/* This disables all DMA engines and interrupts */
1345 	tmp = GET8(dev, CONC_bSERCTL_OFF) &
1346 	    ~(CONC_SERCTL_DAC2IE | CONC_SERCTL_DAC1IE | CONC_SERCTL_ADCIE);
1347 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1348 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1349 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1350 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1351 
1352 	tmp = GET8(dev, CONC_bDEVCTL_OFF) &
1353 	    ~(CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_DAC1_EN);
1354 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1355 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1356 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1357 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1358 
1359 	return (DDI_SUCCESS);
1360 }
1361 
1362 
1363 static int
1364 audioens_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1365 {
1366 	audioens_dev_t *dev;
1367 
1368 	switch (cmd) {
1369 	case DDI_ATTACH:
1370 		return (audioens_attach(dip));
1371 
1372 	case DDI_RESUME:
1373 		if ((dev = ddi_get_driver_private(dip)) == NULL) {
1374 			return (DDI_FAILURE);
1375 		}
1376 		return (audioens_resume(dev));
1377 
1378 	default:
1379 		return (DDI_FAILURE);
1380 	}
1381 }
1382 
1383 static int
1384 audioens_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1385 {
1386 	audioens_dev_t *dev;
1387 
1388 	if ((dev = ddi_get_driver_private(dip)) == NULL) {
1389 		return (DDI_FAILURE);
1390 	}
1391 
1392 	switch (cmd) {
1393 	case DDI_DETACH:
1394 		return (audioens_detach(dev));
1395 
1396 	case DDI_SUSPEND:
1397 		return (audioens_suspend(dev));
1398 	default:
1399 		return (DDI_FAILURE);
1400 	}
1401 }
1402 
1403 static int audioens_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
1404 static int audioens_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
1405 
1406 static struct dev_ops audioens_dev_ops = {
1407 	DEVO_REV,		/* rev */
1408 	0,			/* refcnt */
1409 	NULL,			/* getinfo */
1410 	nulldev,		/* identify */
1411 	nulldev,		/* probe */
1412 	audioens_ddi_attach,	/* attach */
1413 	audioens_ddi_detach,	/* detach */
1414 	nodev,			/* reset */
1415 	NULL,			/* cb_ops */
1416 	NULL,			/* bus_ops */
1417 	NULL,			/* power */
1418 	audioens_quiesce,	/* quiesce */
1419 };
1420 
1421 static struct modldrv audioens_modldrv = {
1422 	&mod_driverops,			/* drv_modops */
1423 	"Ensoniq 1371/1373 Audio",	/* linkinfo */
1424 	&audioens_dev_ops,		/* dev_ops */
1425 };
1426 
1427 static struct modlinkage modlinkage = {
1428 	MODREV_1,
1429 	{ &audioens_modldrv, NULL }
1430 };
1431 
1432 int
1433 _init(void)
1434 {
1435 	int	rv;
1436 
1437 	audio_init_ops(&audioens_dev_ops, DRVNAME);
1438 	if ((rv = mod_install(&modlinkage)) != 0) {
1439 		audio_fini_ops(&audioens_dev_ops);
1440 	}
1441 	return (rv);
1442 }
1443 
1444 int
1445 _fini(void)
1446 {
1447 	int	rv;
1448 
1449 	if ((rv = mod_remove(&modlinkage)) == 0) {
1450 		audio_fini_ops(&audioens_dev_ops);
1451 	}
1452 	return (rv);
1453 }
1454 
1455 int
1456 _info(struct modinfo *modinfop)
1457 {
1458 	return (mod_info(&modlinkage, modinfop));
1459 }
1460