audiopci.c revision 11936:54dc8a89ba0d
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 2010 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25/*
26 * Purpose: Creative/Ensoniq AudioPCI  driver (ES1370)
27 *
28 * This driver is used with the original Ensoniq AudioPCI.
29 */
30
31/*
32 * This file is part of Open Sound System
33 *
34 * Copyright (C) 4Front Technologies 1996-2008.
35 *
36 * This software is released under CDDL 1.0 source license.
37 * See the COPYING file included in the main directory of this source
38 * distribution for the license terms and conditions.
39 */
40
41#include <sys/audio/audio_driver.h>
42#include <sys/note.h>
43#include <sys/pci.h>
44#include "audiopci.h"
45
46/*
47 * The original OSS driver used a single duplex engine and a separate
48 * playback only engine.  Instead, we expose three engines, one for input
49 * and two for output.
50 */
51
52#define	ENSONIQ_VENDOR_ID	0x1274
53#define	CREATIVE_VENDOR_ID	0x1102
54#define	ENSONIQ_ES1370		0x5000
55
56#define	DRVNAME			"audiopci"
57
58#define	INPUT_MIC	0
59#define	INPUT_LINEIN	1
60#define	INPUT_CD	2
61#define	INPUT_VIDEO	3
62#define	INPUT_PHONE	4
63#define	INSRCS		0x1f		/* bits 0-4 */
64
65static const char *audiopci_insrcs[] = {
66	AUDIO_PORT_MIC,
67	AUDIO_PORT_LINEIN,
68	AUDIO_PORT_CD,
69	AUDIO_PORT_VIDEO,
70	AUDIO_PORT_PHONE,
71	NULL
72};
73
74typedef struct audiopci_port
75{
76	/* Audio parameters */
77	int			speed;
78	int			fmt;
79
80	int			num;
81#define	PORT_DAC		0
82#define	PORT_SYN		1
83#define	PORT_ADC		2
84#define	PORT_MAX		PORT_ADC
85
86	caddr_t			kaddr;
87	uint32_t		paddr;
88	ddi_acc_handle_t	acch;
89	ddi_dma_handle_t	dmah;
90	unsigned		nframes;
91	unsigned		frameno;
92	uint64_t		count;
93
94	struct audiopci_dev	*dev;
95	audio_engine_t		*engine;
96} audiopci_port_t;
97
98typedef enum {
99	CTL_VOLUME = 0,
100	CTL_FRONT,
101	CTL_MONO,
102	CTL_MIC,
103	CTL_LINE,
104	CTL_CD,
105	CTL_VID,
106	CTL_PHONE,
107	CTL_MICBOOST,
108	CTL_RECSRC,
109	CTL_MONSRC,
110	CTL_NUM		/* must be last */
111} audiopci_ctrl_num_t;
112
113typedef struct audiopci_ctrl
114{
115	struct audiopci_dev	*dev;
116	audio_ctrl_t		*ctrl;
117	audiopci_ctrl_num_t	num;
118	uint64_t		val;
119} audiopci_ctrl_t;
120
121
122typedef struct audiopci_dev
123{
124	audio_dev_t		*adev;
125	kmutex_t		mutex;
126	uint16_t		devid;
127	dev_info_t		*dip;
128
129	uint8_t			ak_regs[0x20];
130	int			micbias;
131
132	/*
133	 * Controls
134	 */
135	audiopci_ctrl_t		controls[CTL_NUM];
136#if 0
137	audiopci_ctrl_t		*micbias;
138#endif
139
140	audiopci_port_t		port[PORT_MAX + 1];
141
142
143	caddr_t			regs;
144	ddi_acc_handle_t	acch;
145} audiopci_dev_t;
146
147static ddi_device_acc_attr_t acc_attr = {
148	DDI_DEVICE_ATTR_V0,
149	DDI_STRUCTURE_LE_ACC,
150	DDI_STRICTORDER_ACC
151};
152
153static ddi_device_acc_attr_t buf_attr = {
154	DDI_DEVICE_ATTR_V0,
155	DDI_NEVERSWAP_ACC,
156	DDI_STRICTORDER_ACC
157};
158
159/*
160 * The hardware appears to be able to address up to 16-bits worth of longwords,
161 * giving a total address space of 256K.  But we need substantially less.
162 */
163#define	AUDIOPCI_BUF_LEN	(16384)
164
165static ddi_dma_attr_t dma_attr = {
166	DMA_ATTR_VERSION,	/* dma_attr_version */
167	0x0,			/* dma_attr_addr_lo */
168	0xffffffffU,		/* dma_attr_addr_hi */
169	0x3ffff,		/* dma_attr_count_max */
170	0x8,			/* dma_attr_align */
171	0x7f,			/* dma_attr_burstsizes */
172	0x1,			/* dma_attr_minxfer */
173	0x3ffff,		/* dma_attr_maxxfer */
174	0x3ffff,		/* dma_attr_seg */
175	0x1,			/* dma_attr_sgllen */
176	0x1,			/* dma_attr_granular */
177	0			/* dma_attr_flags */
178};
179
180#define	GET8(dev, offset)	\
181	ddi_get8(dev->acch, (uint8_t *)(dev->regs + (offset)))
182#define	GET16(dev, offset)	\
183	ddi_get16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)))
184#define	GET32(dev, offset)	\
185	ddi_get32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset)))
186#define	PUT8(dev, offset, v)	\
187	ddi_put8(dev->acch, (uint8_t *)(dev->regs + (offset)), v)
188#define	PUT16(dev, offset, v)	\
189	ddi_put16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)), v)
190#define	PUT32(dev, offset, v)	\
191	ddi_put32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset)), v)
192
193#define	CLR8(dev, offset, v)	PUT8(dev, offset, GET8(dev, offset) & ~(v))
194#define	SET8(dev, offset, v)	PUT8(dev, offset, GET8(dev, offset) | (v))
195#define	CLR16(dev, offset, v)	PUT16(dev, offset, GET16(dev, offset) & ~(v))
196#define	SET16(dev, offset, v)	PUT16(dev, offset, GET16(dev, offset) | (v))
197
198static void audiopci_init_hw(audiopci_dev_t *);
199static void audiopci_init_port(audiopci_port_t *);
200static uint16_t audiopci_dac_rate(int);
201static int audiopci_add_controls(audiopci_dev_t *);
202static void audiopci_del_controls(audiopci_dev_t *);
203static void audiopci_ak_write(audiopci_dev_t *, uint16_t, uint8_t);
204
205static int
206audiopci_ak_wait(audiopci_dev_t *dev, uint8_t wstat)
207{
208	for (int i = 4000; i; i--) {
209		if (!(GET8(dev, CONC_bCODECSTAT_OFF) & wstat))
210			return (DDI_SUCCESS);
211		drv_usecwait(10);
212	}
213	return (DDI_FAILURE);
214}
215
216static void
217audiopci_ak_idle(audiopci_dev_t *dev)
218{
219	for (int i = 0; i < 5; i++) {
220		if (audiopci_ak_wait(dev, CONC_CSTAT_CSTAT) == DDI_SUCCESS)
221			return;
222	}
223	audio_dev_warn(dev->adev, "timed out waiting for codec to idle");
224}
225
226static void
227audiopci_ak_write(audiopci_dev_t *dev, uint16_t addr, uint8_t data)
228{
229	uint8_t	wstat;
230
231	/* shadow the value */
232	dev->ak_regs[addr] = data;
233
234	wstat = addr == CODEC_RESET_PWRD ? CONC_CSTAT_CWRIP : CONC_CSTAT_CSTAT;
235
236	/* wait for codec to be available */
237	if (audiopci_ak_wait(dev, wstat) != DDI_SUCCESS) {
238		audio_dev_warn(dev->adev, "timeout waiting for codec");
239	}
240
241	PUT16(dev, CONC_wCODECCTL_OFF, (addr << 8) | data);
242}
243
244static void
245audiopci_writemem(audiopci_dev_t *dev, uint32_t page, uint32_t offs,
246    uint32_t data)
247{
248	/* Select memory page */
249	PUT32(dev, CONC_bMEMPAGE_OFF, page);
250	PUT32(dev, offs, data);
251}
252
253static uint32_t
254audiopci_readmem(audiopci_dev_t *dev, uint32_t page, uint32_t offs)
255{
256	PUT32(dev, CONC_bMEMPAGE_OFF, page);	/* Select memory page */
257	return (GET32(dev, offs));
258}
259
260/*
261 * Audio routines
262 */
263
264static int
265audiopci_format(void *arg)
266{
267	_NOTE(ARGUNUSED(arg));
268	return (AUDIO_FORMAT_S16_LE);
269}
270
271static int
272audiopci_channels(void *arg)
273{
274	_NOTE(ARGUNUSED(arg));
275	return (2);
276}
277
278static int
279audiopci_rate(void *arg)
280{
281	audiopci_port_t	*port = arg;
282
283	return (port->speed);
284}
285
286static void
287audiopci_init_port(audiopci_port_t *port)
288{
289	audiopci_dev_t	*dev = port->dev;
290	unsigned tmp;
291
292	switch (port->num) {
293	case PORT_DAC:
294
295		/* Set physical address of the DMA buffer */
296		audiopci_writemem(dev, CONC_DACCTL_PAGE, CONC_dDACPADDR_OFF,
297		    port->paddr);
298
299		/* Set DAC rate */
300		PUT16(dev, CONC_wDACRATE_OFF, audiopci_dac_rate(48000));
301
302		/* Set format */
303		tmp = GET8(dev, CONC_bSERFMT_OFF);
304		tmp |= CONC_PCM_DAC_16BIT;
305		tmp |= CONC_PCM_DAC_STEREO;
306
307		PUT8(dev, CONC_bSKIPC_OFF, 0x10);
308		PUT8(dev, CONC_bSERFMT_OFF, tmp);
309
310		/* Set the frame count */
311		audiopci_writemem(dev, CONC_DACCTL_PAGE, CONC_wDACFC_OFF,
312		    port->nframes - 1);
313
314		/* Set # of frames between interrupts */
315		PUT16(dev, CONC_wDACIC_OFF, port->nframes - 1);
316
317		break;
318
319	case PORT_SYN:
320
321		/* Set physical address of the DMA buffer */
322		audiopci_writemem(dev, CONC_SYNCTL_PAGE, CONC_dSYNPADDR_OFF,
323		    port->paddr);
324
325		/* Set rate - we force to 44.1 kHz */
326		SET8(dev, CONC_bMISCCTL_OFF, CONC_MISCCTL_SYN_44KHZ);
327
328		/* Set format */
329		tmp = GET8(dev, CONC_bSERFMT_OFF);
330		tmp |= CONC_PCM_SYN_16BIT;
331		tmp |= CONC_PCM_SYN_STEREO;
332
333		PUT8(dev, CONC_bSERFMT_OFF, tmp);
334
335		/* Set the frame count */
336		audiopci_writemem(dev, CONC_SYNCTL_PAGE, CONC_wSYNFC_OFF,
337		    port->nframes - 1);
338
339		/* Set # of frames between interrupts */
340		PUT16(dev, CONC_wSYNIC_OFF, port->nframes - 1);
341
342		break;
343
344	case PORT_ADC:
345		/* Set physical address of the DMA buffer */
346		audiopci_writemem(dev, CONC_ADCCTL_PAGE, CONC_dADCPADDR_OFF,
347		    port->paddr);
348
349		/* Set ADC rate */
350		PUT16(dev, CONC_wDACRATE_OFF, audiopci_dac_rate(48000));
351
352		/* Set format - for input we only support 16 bit input */
353		tmp = GET8(dev, CONC_bSERFMT_OFF);
354		tmp |= CONC_PCM_ADC_16BIT;
355		tmp |= CONC_PCM_ADC_STEREO;
356
357		PUT8(dev, CONC_bSKIPC_OFF, 0x10);
358
359		PUT8(dev, CONC_bSERFMT_OFF, tmp);
360
361		/* Set the frame count */
362		audiopci_writemem(dev, CONC_ADCCTL_PAGE, CONC_wADCFC_OFF,
363		    port->nframes - 1);
364
365		/* Set # of frames between interrupts */
366		PUT16(dev, CONC_wADCIC_OFF, port->nframes - 1);
367
368		break;
369	}
370
371	port->frameno = 0;
372}
373
374static int
375audiopci_open(void *arg, int flag, unsigned *nframes, caddr_t *bufp)
376{
377	audiopci_port_t	*port = arg;
378
379	_NOTE(ARGUNUSED(flag));
380
381	/* NB: frame size = 4 (16-bit stereo) */
382	port->nframes = AUDIOPCI_BUF_LEN / 4;
383	port->count = 0;
384
385	*nframes = port->nframes;
386	*bufp = port->kaddr;
387
388	return (0);
389}
390
391static int
392audiopci_start(void *arg)
393{
394	audiopci_port_t *port = arg;
395	audiopci_dev_t *dev = port->dev;
396
397	mutex_enter(&dev->mutex);
398
399	audiopci_init_port(port);
400
401	switch (port->num) {
402	case PORT_DAC:
403		SET8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_DAC_EN);
404		break;
405	case PORT_SYN:
406		SET8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_SYN_EN);
407		break;
408	case PORT_ADC:
409		SET8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_ADC_EN);
410		break;
411	}
412	mutex_exit(&dev->mutex);
413
414	return (0);
415}
416
417static void
418audiopci_stop(void *arg)
419{
420	audiopci_port_t *port = arg;
421	audiopci_dev_t *dev = port->dev;
422
423	mutex_enter(&dev->mutex);
424	switch (port->num) {
425	case PORT_DAC:
426		CLR8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_DAC_EN);
427		break;
428	case PORT_SYN:
429		CLR8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_SYN_EN);
430		break;
431	case PORT_ADC:
432		CLR8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_ADC_EN);
433		break;
434	}
435	mutex_exit(&dev->mutex);
436}
437
438static uint64_t
439audiopci_count(void *arg)
440{
441	audiopci_port_t *port = arg;
442	audiopci_dev_t *dev = port->dev;
443	uint64_t val;
444	uint32_t page, offs;
445	int frameno, n;
446
447	switch (port->num) {
448	case PORT_DAC:
449		page = CONC_DACCTL_PAGE;
450		offs = CONC_wDACFC_OFF;
451		break;
452
453	case PORT_SYN:
454		page = CONC_SYNCTL_PAGE;
455		offs = CONC_wSYNFC_OFF;
456		break;
457
458	case PORT_ADC:
459		page = CONC_ADCCTL_PAGE;
460		offs = CONC_wADCFC_OFF;
461		break;
462	}
463
464	/*
465	 * Note that the current frame counter is in the high nybble.
466	 */
467	mutex_enter(&dev->mutex);
468	frameno = audiopci_readmem(port->dev, page, offs) >> 16;
469	mutex_exit(&dev->mutex);
470
471	n = frameno >= port->frameno ?
472	    frameno - port->frameno :
473	    frameno + port->nframes - port->frameno;
474	port->frameno = frameno;
475	port->count += n;
476
477	val = port->count;
478	return (val);
479}
480
481static void
482audiopci_close(void *arg)
483{
484	_NOTE(ARGUNUSED(arg));
485}
486
487static void
488audiopci_sync(void *arg, unsigned nframes)
489{
490	audiopci_port_t *port = arg;
491
492	_NOTE(ARGUNUSED(nframes));
493
494	if (port->num == PORT_ADC) {
495		(void) ddi_dma_sync(port->dmah, 0, 0, DDI_DMA_SYNC_FORCPU);
496	} else {
497		(void) ddi_dma_sync(port->dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
498	}
499}
500
501audio_engine_ops_t audiopci_engine_ops = {
502	AUDIO_ENGINE_VERSION,		/* version number */
503	audiopci_open,
504	audiopci_close,
505	audiopci_start,
506	audiopci_stop,
507	audiopci_count,
508	audiopci_format,
509	audiopci_channels,
510	audiopci_rate,
511	audiopci_sync,
512	NULL,
513	NULL,
514	NULL,
515};
516
517static uint16_t
518audiopci_dac_rate(int samPerSec)
519{
520	unsigned short usTemp;
521
522	/* samPerSec /= 2; */
523
524	usTemp = (unsigned short) ((DAC_CLOCK_DIVIDE / 8) / samPerSec);
525
526	if (usTemp & 0x00000001) {
527		usTemp >>= 1;
528		usTemp -= 1;
529	} else {
530		usTemp >>= 1;
531		usTemp -= 2;
532	}
533	return (usTemp);
534}
535
536void
537audiopci_init_hw(audiopci_dev_t *dev)
538{
539	int tmp;
540
541	/* setup DAC frequency */
542	PUT16(dev, CONC_wDACRATE_OFF, audiopci_dac_rate(48000));
543
544	CLR8(dev, CONC_bMISCCTL_OFF, CONC_MISCCTL_CCB_INTRM);
545	SET8(dev, CONC_bMISCCTL_OFF, CONC_MISCCTL_SYN_44KHZ);
546
547	/* Turn on CODEC (UART and joystick left disabled) */
548	tmp = GET8(dev, CONC_bDEVCTL_OFF);
549	tmp |= CONC_DEVCTL_SERR_DIS;
550	tmp |= CONC_DEVCTL_CODEC_EN;
551	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
552
553	/* Reset the UART */
554	PUT8(dev, CONC_bUARTCSTAT_OFF, 0x00);
555
556	/* Disable NMI */
557	PUT8(dev, CONC_bNMIENA_OFF, 0);
558	PUT16(dev, CONC_wNMISTAT_OFF, 0);
559
560	/* Initialize serial interface */
561	PUT8(dev, CONC_bSERCTL_OFF, 0);
562	PUT8(dev, CONC_bSERFMT_OFF,
563	    CONC_PCM_SYN_STEREO | CONC_PCM_SYN_16BIT);
564
565	/* Unmute codec */
566	CLR8(dev, CONC_bMISCCTL_OFF, CONC_MISCCTL_MUTE);
567
568	/* mixer initialization */
569	audiopci_ak_idle(dev);
570
571	/* power/reset down the codec */
572	audiopci_ak_write(dev, CODEC_RESET_PWRD, 0);
573	drv_usecwait(10);
574
575	/* now powerup and bring out of reset */
576	audiopci_ak_write(dev, CODEC_RESET_PWRD, 0x3);
577	audiopci_ak_idle(dev);
578
579	/* enable PLL for DAC2 */
580	audiopci_ak_write(dev, CODEC_CLKSELECT, 0);
581
582	/* select input mixer */
583	audiopci_ak_write(dev, CODEC_ADSELECT, 0);
584
585	/* mark FM for output mixer */
586	audiopci_ak_write(dev, CODEC_OUT_SW1, CODEC_OUT_ENABLE_SYNTH);
587	audiopci_ak_write(dev, CODEC_OUT_SW2, CODEC_OUT_ENABLE_WAVE);
588
589	/* initialize some reasonable values for the WAVE and SYNTH inputs */
590	audiopci_ak_write(dev, CODEC_VOL_WAVE_L, 6);
591	audiopci_ak_write(dev, CODEC_VOL_WAVE_R, 6);
592	audiopci_ak_write(dev, CODEC_VOL_SYNTH_L, 6);
593	audiopci_ak_write(dev, CODEC_VOL_SYNTH_R, 6);
594
595	/* enable microphone phantom power */
596	if (dev->micbias) {
597		SET16(dev, 2, CONC_DEVCTL_MICBIAS);
598	}
599}
600
601static int
602audiopci_init(audiopci_dev_t *dev)
603{
604	dev->micbias = 1;
605
606	audiopci_init_hw(dev);
607
608	for (int i = 0; i <= PORT_MAX; i++) {
609		audiopci_port_t *port;
610		unsigned caps;
611		unsigned dmaflags;
612		size_t rlen;
613		ddi_dma_cookie_t c;
614		unsigned ccnt;
615
616		port = &dev->port[i];
617		port->dev = dev;
618
619		switch (i) {
620		case PORT_SYN:
621			caps = ENGINE_OUTPUT_CAP;
622			dmaflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
623			port->speed = 44100;
624			break;
625
626		case PORT_DAC:
627			caps = ENGINE_OUTPUT_CAP;
628			dmaflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
629			port->speed = 48000;
630			break;
631
632		case PORT_ADC:
633			caps = ENGINE_INPUT_CAP;
634			dmaflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
635			port->speed = 48000;
636			break;
637		}
638
639		port->num = i;
640
641		/*
642		 * Allocate DMA resources.
643		 */
644
645		if (ddi_dma_alloc_handle(dev->dip, &dma_attr, DDI_DMA_SLEEP,
646		    NULL, &port->dmah) != DDI_SUCCESS) {
647			audio_dev_warn(dev->adev,
648			    "port %d: dma handle allocation failed", i);
649			return (DDI_FAILURE);
650		}
651		if (ddi_dma_mem_alloc(port->dmah, AUDIOPCI_BUF_LEN, &buf_attr,
652		    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &port->kaddr,
653		    &rlen, &port->acch) != DDI_SUCCESS) {
654			audio_dev_warn(dev->adev,
655			    "port %d: dma memory allocation failed", i);
656			return (DDI_FAILURE);
657		}
658		/* ensure that the buffer is zeroed out properly */
659		bzero(port->kaddr, rlen);
660		if (ddi_dma_addr_bind_handle(port->dmah, NULL, port->kaddr,
661		    AUDIOPCI_BUF_LEN, dmaflags, DDI_DMA_SLEEP, NULL,
662		    &c, &ccnt) != DDI_DMA_MAPPED) {
663			audio_dev_warn(dev->adev,
664			    "port %d: dma binding failed", i);
665			return (DDI_FAILURE);
666		}
667		port->paddr = c.dmac_address;
668
669		/*
670		 * Allocate and configure audio engine.
671		 */
672		port->engine = audio_engine_alloc(&audiopci_engine_ops, caps);
673		if (port->engine == NULL) {
674			audio_dev_warn(dev->adev,
675			    "port %d: audio_engine_alloc failed", i);
676			return (DDI_FAILURE);
677		}
678
679		audio_engine_set_private(port->engine, port);
680		audio_dev_add_engine(dev->adev, port->engine);
681	}
682
683	/*
684	 * Register audio controls.
685	 */
686	if (audiopci_add_controls(dev) == DDI_FAILURE) {
687		return (DDI_FAILURE);
688	}
689
690
691	if (audio_dev_register(dev->adev) != DDI_SUCCESS) {
692		audio_dev_warn(dev->adev,
693		    "unable to register with audio framework");
694		return (DDI_FAILURE);
695	}
696
697	return (DDI_SUCCESS);
698}
699
700static void
701audiopci_destroy(audiopci_dev_t *dev)
702{
703	int	i;
704
705	mutex_destroy(&dev->mutex);
706
707	/* free up ports, including DMA resources for ports */
708	for (i = 0; i <= PORT_MAX; i++) {
709		audiopci_port_t	*port = &dev->port[i];
710
711		if (port->paddr != 0)
712			(void) ddi_dma_unbind_handle(port->dmah);
713		if (port->acch != NULL)
714			ddi_dma_mem_free(&port->acch);
715		if (port->dmah != NULL)
716			ddi_dma_free_handle(&port->dmah);
717
718		if (port->engine != NULL) {
719			audio_dev_remove_engine(dev->adev, port->engine);
720			audio_engine_free(port->engine);
721		}
722	}
723
724	if (dev->acch != NULL) {
725		ddi_regs_map_free(&dev->acch);
726	}
727
728	audiopci_del_controls(dev);
729
730	if (dev->adev != NULL) {
731		audio_dev_free(dev->adev);
732	}
733
734	kmem_free(dev, sizeof (*dev));
735}
736
737static void
738audiopci_stereo(audiopci_dev_t *dev, audiopci_ctrl_num_t num, uint8_t lreg)
739{
740	uint8_t		lval, rval;
741	uint8_t		lmute, rmute;
742	uint64_t	val;
743	uint8_t		rreg;
744
745	rreg = lreg + 1;
746	val = dev->controls[num].val;
747	lval = (val & 0xff00) >> 8;
748	rval = val & 0xff;
749
750	lmute = lval ? 0 : CODEC_ATT_MUTE;
751	rmute = rval ? 0 : CODEC_ATT_MUTE;
752
753	/* convert to attenuation & apply mute if appropriate */
754	lval = ((((100U - lval) * CODEC_ATT_MAX) / 100) & 0xff) | lmute;
755	rval = ((((100U - rval) * CODEC_ATT_MAX) / 100) & 0xff) | rmute;
756
757	audiopci_ak_write(dev, lreg, lval);
758	audiopci_ak_write(dev, rreg, rval);
759}
760
761static void
762audiopci_mono(audiopci_dev_t *dev, audiopci_ctrl_num_t num, uint8_t reg)
763{
764	uint64_t val = (dev->controls[num].val & 0xff);
765	uint8_t mute;
766
767	mute = val ? 0 : CODEC_ATT_MUTE;
768	val = ((((100U - val) * CODEC_ATT_MAX) / 100) & 0xff) | mute;
769
770	audiopci_ak_write(dev, reg, val);
771}
772
773static void
774audiopci_mono8(audiopci_dev_t *dev, audiopci_ctrl_num_t num, uint8_t reg)
775{
776	uint64_t val = (dev->controls[num].val & 0xff);
777	uint8_t mute;
778
779	mute = val ? 0 : CODEC_ATT_MUTE;
780	val = ((((100U - val) * CODEC_ATT_MONO) / 100) & 0xff) | mute;
781
782	audiopci_ak_write(dev, reg, val);
783}
784
785static int
786audiopci_get_value(void *arg, uint64_t *val)
787{
788	audiopci_ctrl_t	*pc = arg;
789
790	*val = pc->val;
791
792	return (0);
793}
794
795static void
796audiopci_configure_output(audiopci_dev_t *dev)
797{
798	uint64_t val;
799	uint8_t	tmp;
800
801	/* PCM/Wave level */
802	audiopci_mono(dev, CTL_VOLUME, CODEC_VOL_WAVE_L);
803	audiopci_mono(dev, CTL_VOLUME, CODEC_VOL_WAVE_R);
804	audiopci_mono(dev, CTL_VOLUME, CODEC_VOL_SYNTH_L);
805	audiopci_mono(dev, CTL_VOLUME, CODEC_VOL_SYNTH_R);
806
807	/* front & mono outputs */
808	audiopci_stereo(dev, CTL_FRONT, CODEC_VOL_MASTER_L);
809	audiopci_mono8(dev, CTL_MONO, CODEC_VOL_MONO);
810
811	val = dev->controls[CTL_MONSRC].val;
812
813	/* setup output monitoring as well */
814	tmp = CODEC_OUT_ENABLE_SYNTH;
815	if (val & (1U << INPUT_MIC))
816		tmp |= CODEC_OUT_ENABLE_MIC;
817	if (val & (1U << INPUT_CD))
818		tmp |= CODEC_OUT_ENABLE_CD;
819	if (val & (1U << INPUT_LINEIN))
820		tmp |= CODEC_OUT_ENABLE_AUX;
821	audiopci_ak_write(dev, CODEC_OUT_SW1, tmp);
822
823	tmp = CODEC_OUT_ENABLE_WAVE;
824	if (val & (1U << INPUT_VIDEO))
825		tmp |= CODEC_OUT_ENABLE_TV;
826	if (val & (1U << INPUT_PHONE))
827		tmp |= CODEC_OUT_ENABLE_TAD;
828	audiopci_ak_write(dev, CODEC_OUT_SW2, tmp);
829}
830
831static void
832audiopci_configure_input(audiopci_dev_t *dev)
833{
834	uint64_t	val = dev->controls[CTL_RECSRC].val;
835	uint8_t		tmp;
836
837	tmp = 0;
838	if (val & (1U << INPUT_LINEIN))
839		tmp |= CODEC_IN_ENABLE_AUX_L;
840	if (val & (1U << INPUT_CD))
841		tmp |= CODEC_IN_ENABLE_CD_L;
842	if (val & (1U << INPUT_MIC))
843		tmp |= CODEC_IN_ENABLE_MIC;
844	if (val & (1U << INPUT_PHONE))
845		tmp |= CODEC_IN_ENABLE_TAD;
846	audiopci_ak_write(dev, CODEC_LIN_SW1, tmp);
847
848	tmp = 0;
849	if (val & (1U << INPUT_LINEIN))
850		tmp |= CODEC_IN_ENABLE_AUX_R;
851	if (val & (1U << INPUT_CD))
852		tmp |= CODEC_IN_ENABLE_CD_R;
853	if (val & (1U << INPUT_PHONE))
854		tmp |= CODEC_IN_ENABLE_TAD;
855	if (val & (1U << INPUT_MIC))
856		tmp |= CODEC_IN_ENABLE_MIC;
857	audiopci_ak_write(dev, CODEC_RIN_SW1, tmp);
858
859	tmp = 0;
860	if (val & (1U << INPUT_VIDEO))
861		tmp |= CODEC_IN_ENABLE_TV_L;
862	if (val & (1U << INPUT_MIC))
863		tmp |= CODEC_IN_ENABLE_TMIC;
864	audiopci_ak_write(dev, CODEC_LIN_SW2, tmp);
865
866	tmp = 0;
867	if (val & (1U << INPUT_VIDEO))
868		tmp |= CODEC_IN_ENABLE_TV_R;
869	if (val & (1U << INPUT_MIC))
870		tmp |= CODEC_IN_ENABLE_TMIC;
871	audiopci_ak_write(dev, CODEC_RIN_SW2, tmp);
872
873	/* configure volumes */
874	audiopci_mono(dev, CTL_MIC, CODEC_VOL_MIC);
875	audiopci_mono(dev, CTL_PHONE, CODEC_VOL_TAD);
876	audiopci_stereo(dev, CTL_LINE, CODEC_VOL_AUX_L);
877	audiopci_stereo(dev, CTL_CD, CODEC_VOL_CD_L);
878	audiopci_stereo(dev, CTL_VID, CODEC_VOL_TV_L);
879
880	/* activate 30dB mic boost */
881	audiopci_ak_write(dev, CODEC_MICBOOST,
882	    dev->controls[CTL_MICBOOST].val ? 1 : 0);
883}
884
885static int
886audiopci_set_reclevel(void *arg, uint64_t val)
887{
888	audiopci_ctrl_t	*pc = arg;
889	audiopci_dev_t	*dev = pc->dev;
890	uint8_t		l;
891	uint8_t		r;
892
893	l = (val & 0xff00) >> 8;
894	r = val & 0xff;
895
896	if ((l > 100) || (r > 100))
897		return (EINVAL);
898
899	mutex_enter(&dev->mutex);
900	pc->val = val;
901	audiopci_configure_input(dev);
902
903	mutex_exit(&dev->mutex);
904	return (0);
905}
906
907static int
908audiopci_set_micboost(void *arg, uint64_t val)
909{
910	audiopci_ctrl_t	*pc = arg;
911	audiopci_dev_t	*dev = pc->dev;
912
913	mutex_enter(&dev->mutex);
914	pc->val = val;
915	audiopci_configure_input(dev);
916	mutex_exit(&dev->mutex);
917	return (0);
918}
919
920static int
921audiopci_set_monsrc(void *arg, uint64_t val)
922{
923	audiopci_ctrl_t	*pc = arg;
924	audiopci_dev_t	*dev = pc->dev;
925
926	if ((val & ~INSRCS) != 0)
927		return (EINVAL);
928
929	mutex_enter(&dev->mutex);
930	pc->val = val;
931	audiopci_configure_output(dev);
932	mutex_exit(&dev->mutex);
933	return (0);
934}
935
936static int
937audiopci_set_recsrc(void *arg, uint64_t val)
938{
939	audiopci_ctrl_t	*pc = arg;
940	audiopci_dev_t	*dev = pc->dev;
941
942	if ((val & ~INSRCS) != 0)
943		return (EINVAL);
944
945	mutex_enter(&dev->mutex);
946	pc->val = val;
947	audiopci_configure_input(dev);
948	mutex_exit(&dev->mutex);
949	return (0);
950}
951
952static int
953audiopci_set_volume(void *arg, uint64_t val)
954{
955	audiopci_ctrl_t	*pc = arg;
956	audiopci_dev_t	*dev = pc->dev;
957
958	val &= 0xff;
959	if (val > 100)
960		return (EINVAL);
961
962	val = (val & 0xff) | ((val & 0xff) << 8);
963
964	mutex_enter(&dev->mutex);
965	pc->val = val;
966	audiopci_configure_output(dev);
967	mutex_exit(&dev->mutex);
968
969	return (0);
970}
971
972static int
973audiopci_set_front(void *arg, uint64_t val)
974{
975	audiopci_ctrl_t	*pc = arg;
976	audiopci_dev_t	*dev = pc->dev;
977	uint8_t		l;
978	uint8_t		r;
979
980	l = (val & 0xff00) >> 8;
981	r = val & 0xff;
982
983	if ((l > 100) || (r > 100))
984		return (EINVAL);
985
986	mutex_enter(&dev->mutex);
987	pc->val = val;
988	audiopci_configure_output(dev);
989
990	mutex_exit(&dev->mutex);
991	return (0);
992}
993
994static int
995audiopci_set_speaker(void *arg, uint64_t val)
996{
997	audiopci_ctrl_t	*pc = arg;
998	audiopci_dev_t	*dev = pc->dev;
999
1000	val &= 0xff;
1001
1002	if (val > 100)
1003		return (EINVAL);
1004
1005	mutex_enter(&dev->mutex);
1006	pc->val = val;
1007	audiopci_configure_output(dev);
1008
1009	mutex_exit(&dev->mutex);
1010	return (0);
1011}
1012
1013#define	PLAYCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_PLAY)
1014#define	RECCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC)
1015#define	MONCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_MONITOR)
1016#define	PCMVOL	(PLAYCTL | AUDIO_CTRL_FLAG_PCMVOL)
1017#define	MAINVOL	(PLAYCTL | AUDIO_CTRL_FLAG_MAINVOL)
1018#define	RECVOL	(RECCTL | AUDIO_CTRL_FLAG_RECVOL)
1019
1020static void
1021audiopci_alloc_ctrl(audiopci_dev_t *dev, uint32_t num, uint64_t val)
1022{
1023	audio_ctrl_desc_t	desc;
1024	audio_ctrl_wr_t		fn;
1025	audiopci_ctrl_t		*pc;
1026
1027	bzero(&desc, sizeof (desc));
1028
1029	pc = &dev->controls[num];
1030	pc->num = num;
1031	pc->dev = dev;
1032
1033	switch (num) {
1034	case CTL_VOLUME:
1035		desc.acd_name = AUDIO_CTRL_ID_VOLUME;
1036		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
1037		desc.acd_minvalue = 0;
1038		desc.acd_maxvalue = 100;
1039		desc.acd_flags = PCMVOL;
1040		fn = audiopci_set_volume;
1041		break;
1042
1043	case CTL_FRONT:
1044		desc.acd_name = AUDIO_CTRL_ID_LINEOUT;
1045		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1046		desc.acd_minvalue = 0;
1047		desc.acd_maxvalue = 100;
1048		desc.acd_flags = MAINVOL;
1049		fn = audiopci_set_front;
1050		break;
1051
1052	case CTL_MONO:
1053		desc.acd_name = AUDIO_CTRL_ID_SPEAKER;
1054		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
1055		desc.acd_minvalue = 0;
1056		desc.acd_maxvalue = 100;
1057		desc.acd_flags = MAINVOL;
1058		fn = audiopci_set_speaker;
1059		break;
1060
1061	case CTL_MIC:
1062		desc.acd_name = AUDIO_CTRL_ID_MIC;
1063		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
1064		desc.acd_minvalue = 0;
1065		desc.acd_maxvalue = 100;
1066		desc.acd_flags = RECVOL;
1067		fn = audiopci_set_reclevel;
1068		break;
1069
1070	case CTL_LINE:
1071		desc.acd_name = AUDIO_CTRL_ID_LINEIN;
1072		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1073		desc.acd_minvalue = 0;
1074		desc.acd_maxvalue = 100;
1075		desc.acd_flags = RECVOL;
1076		fn = audiopci_set_reclevel;
1077		break;
1078
1079	case CTL_CD:
1080		desc.acd_name = AUDIO_CTRL_ID_CD;
1081		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1082		desc.acd_minvalue = 0;
1083		desc.acd_maxvalue = 100;
1084		desc.acd_flags = RECVOL;
1085		fn = audiopci_set_reclevel;
1086		break;
1087
1088	case CTL_VID:
1089		desc.acd_name = AUDIO_CTRL_ID_VIDEO;
1090		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1091		desc.acd_minvalue = 0;
1092		desc.acd_maxvalue = 100;
1093		desc.acd_flags = RECVOL;
1094		fn = audiopci_set_reclevel;
1095		break;
1096
1097	case CTL_PHONE:
1098		desc.acd_name = AUDIO_CTRL_ID_PHONE;
1099		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
1100		desc.acd_minvalue = 0;
1101		desc.acd_maxvalue = 100;
1102		desc.acd_flags = RECVOL;
1103		fn = audiopci_set_reclevel;
1104		break;
1105
1106	case CTL_RECSRC:
1107		desc.acd_name = AUDIO_CTRL_ID_RECSRC;
1108		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
1109		desc.acd_minvalue = INSRCS;
1110		desc.acd_maxvalue = INSRCS;
1111		desc.acd_flags = RECCTL | AUDIO_CTRL_FLAG_MULTI;
1112		for (int i = 0; audiopci_insrcs[i]; i++) {
1113			desc.acd_enum[i] = audiopci_insrcs[i];
1114		}
1115		fn = audiopci_set_recsrc;
1116		break;
1117
1118	case CTL_MONSRC:
1119		desc.acd_name = AUDIO_CTRL_ID_MONSRC;
1120		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
1121		desc.acd_minvalue = INSRCS;
1122		desc.acd_maxvalue = INSRCS;
1123		desc.acd_flags = MONCTL | AUDIO_CTRL_FLAG_MULTI;
1124		for (int i = 0; audiopci_insrcs[i]; i++) {
1125			desc.acd_enum[i] = audiopci_insrcs[i];
1126		}
1127		fn = audiopci_set_monsrc;
1128		break;
1129
1130	case CTL_MICBOOST:
1131		desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
1132		desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
1133		desc.acd_minvalue = 0;
1134		desc.acd_maxvalue = 100;
1135		desc.acd_flags = RECCTL;
1136		fn = audiopci_set_micboost;
1137		break;
1138	}
1139
1140	pc->val = val;
1141	pc->ctrl = audio_dev_add_control(dev->adev, &desc,
1142	    audiopci_get_value, fn, pc);
1143}
1144
1145static int
1146audiopci_add_controls(audiopci_dev_t *dev)
1147{
1148	audiopci_alloc_ctrl(dev, CTL_VOLUME, 75);
1149	audiopci_alloc_ctrl(dev, CTL_FRONT, ((75) | (75 << 8)));
1150	audiopci_alloc_ctrl(dev, CTL_MONO, 75);
1151	audiopci_alloc_ctrl(dev, CTL_MIC, 50);
1152	audiopci_alloc_ctrl(dev, CTL_LINE, 0);
1153	audiopci_alloc_ctrl(dev, CTL_CD, 0);
1154	audiopci_alloc_ctrl(dev, CTL_VID, 0);
1155	audiopci_alloc_ctrl(dev, CTL_PHONE, 0);
1156	audiopci_alloc_ctrl(dev, CTL_RECSRC, (1U << INPUT_MIC));
1157	audiopci_alloc_ctrl(dev, CTL_MONSRC, 0);
1158	audiopci_alloc_ctrl(dev, CTL_MICBOOST, 1);
1159
1160	audiopci_configure_output(dev);
1161	audiopci_configure_input(dev);
1162
1163	return (DDI_SUCCESS);
1164}
1165
1166static void
1167audiopci_del_controls(audiopci_dev_t *dev)
1168{
1169	for (int i = 0; i < CTL_NUM; i++) {
1170		if (dev->controls[i].ctrl) {
1171			audio_dev_del_control(dev->controls[i].ctrl);
1172		}
1173	}
1174}
1175
1176static int
1177audiopci_attach(dev_info_t *dip)
1178{
1179	uint16_t pci_command, vendor, device;
1180	audiopci_dev_t *dev;
1181	ddi_acc_handle_t pcih;
1182
1183	dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
1184	dev->dip = dip;
1185	ddi_set_driver_private(dip, dev);
1186
1187	mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, NULL);
1188
1189	if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
1190		audio_dev_warn(dev->adev, "pci_config_setup failed");
1191		mutex_destroy(&dev->mutex);
1192		kmem_free(dev, sizeof (*dev));
1193		return (DDI_FAILURE);
1194	}
1195
1196	vendor = pci_config_get16(pcih, PCI_CONF_VENID);
1197	device = pci_config_get16(pcih, PCI_CONF_DEVID);
1198
1199	if ((vendor != ENSONIQ_VENDOR_ID && vendor != CREATIVE_VENDOR_ID) ||
1200	    (device != ENSONIQ_ES1370))
1201		goto err_exit;
1202
1203	dev->devid = device;
1204
1205	dev->adev = audio_dev_alloc(dip, 0);
1206	if (dev->adev == NULL) {
1207		goto err_exit;
1208	}
1209
1210	audio_dev_set_description(dev->adev, "AudioPCI");
1211	audio_dev_set_version(dev->adev, "ES1370");
1212	audio_dev_add_info(dev->adev, "Legacy codec: Asahi Kasei AK4531");
1213
1214	/* activate the device */
1215	pci_command = pci_config_get16(pcih, PCI_CONF_COMM);
1216	pci_command |= PCI_COMM_ME | PCI_COMM_IO;
1217	pci_config_put16(pcih, PCI_CONF_COMM, pci_command);
1218
1219	/* map registers */
1220	if (ddi_regs_map_setup(dip, 1, &dev->regs, 0, 0, &acc_attr,
1221	    &dev->acch) != DDI_SUCCESS) {
1222		audio_dev_warn(dev->adev, "can't map registers");
1223		goto err_exit;
1224	}
1225
1226
1227	/* This allocates and configures the engines */
1228	if (audiopci_init(dev) != DDI_SUCCESS) {
1229		audio_dev_warn(dev->adev, "can't init device");
1230		goto err_exit;
1231	}
1232
1233	pci_config_teardown(&pcih);
1234
1235	ddi_report_dev(dip);
1236
1237	return (DDI_SUCCESS);
1238
1239err_exit:
1240	mutex_destroy(&dev->mutex);
1241	pci_config_teardown(&pcih);
1242
1243	audiopci_destroy(dev);
1244
1245	return (DDI_FAILURE);
1246}
1247
1248static int
1249audiopci_detach(audiopci_dev_t *dev)
1250{
1251	int tmp;
1252
1253	/* first unregister us from the DDI framework, might be busy */
1254	if (audio_dev_unregister(dev->adev) != DDI_SUCCESS)
1255		return (DDI_FAILURE);
1256
1257	mutex_enter(&dev->mutex);
1258
1259	tmp = GET8(dev, CONC_bSERCTL_OFF) &
1260	    ~(CONC_SERCTL_DACIE | CONC_SERCTL_SYNIE | CONC_SERCTL_ADCIE);
1261	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1262	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1263	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1264	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1265
1266	tmp = GET8(dev, CONC_bDEVCTL_OFF) &
1267	    ~(CONC_DEVCTL_DAC_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_SYN_EN);
1268	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1269	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1270	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1271	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1272
1273	mutex_exit(&dev->mutex);
1274
1275	audiopci_destroy(dev);
1276
1277	return (DDI_SUCCESS);
1278}
1279
1280static int
1281audiopci_resume(audiopci_dev_t *dev)
1282{
1283	/* reinitialize hardware */
1284	audiopci_init_hw(dev);
1285
1286	audio_dev_resume(dev->adev);
1287	return (DDI_SUCCESS);
1288}
1289
1290static int
1291audiopci_suspend(audiopci_dev_t *dev)
1292{
1293	audio_dev_suspend(dev->adev);
1294
1295	return (DDI_SUCCESS);
1296}
1297
1298static int
1299audiopci_quiesce(dev_info_t *dip)
1300{
1301	audiopci_dev_t	*dev;
1302	uint8_t		tmp;
1303
1304	if ((dev = ddi_get_driver_private(dip)) == NULL) {
1305		return (DDI_FAILURE);
1306	}
1307
1308	/* This disables all DMA engines and interrupts */
1309	tmp = GET8(dev, CONC_bSERCTL_OFF) &
1310	    ~(CONC_SERCTL_DACIE | CONC_SERCTL_SYNIE | CONC_SERCTL_ADCIE);
1311	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1312	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1313	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1314	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1315
1316	tmp = GET8(dev, CONC_bDEVCTL_OFF) &
1317	    ~(CONC_DEVCTL_DAC_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_SYN_EN);
1318	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1319	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1320	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1321	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1322
1323	return (DDI_SUCCESS);
1324}
1325
1326
1327static int
1328audiopci_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1329{
1330	audiopci_dev_t *dev;
1331
1332	switch (cmd) {
1333	case DDI_ATTACH:
1334		return (audiopci_attach(dip));
1335
1336	case DDI_RESUME:
1337		if ((dev = ddi_get_driver_private(dip)) == NULL) {
1338			return (DDI_FAILURE);
1339		}
1340		return (audiopci_resume(dev));
1341
1342	default:
1343		return (DDI_FAILURE);
1344	}
1345}
1346
1347static int
1348audiopci_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1349{
1350	audiopci_dev_t *dev;
1351
1352	if ((dev = ddi_get_driver_private(dip)) == NULL) {
1353		return (DDI_FAILURE);
1354	}
1355
1356	switch (cmd) {
1357	case DDI_DETACH:
1358		return (audiopci_detach(dev));
1359
1360	case DDI_SUSPEND:
1361		return (audiopci_suspend(dev));
1362	default:
1363		return (DDI_FAILURE);
1364	}
1365}
1366
1367static struct dev_ops audiopci_dev_ops = {
1368	DEVO_REV,		/* rev */
1369	0,			/* refcnt */
1370	NULL,			/* getinfo */
1371	nulldev,		/* identify */
1372	nulldev,		/* probe */
1373	audiopci_ddi_attach,	/* attach */
1374	audiopci_ddi_detach,	/* detach */
1375	nodev,			/* reset */
1376	NULL,			/* cb_ops */
1377	NULL,			/* bus_ops */
1378	NULL,			/* power */
1379	audiopci_quiesce,	/* quiesce */
1380};
1381
1382static struct modldrv audiopci_modldrv = {
1383	&mod_driverops,			/* drv_modops */
1384	"Ensoniq 1370 Audio",		/* linkinfo */
1385	&audiopci_dev_ops,		/* dev_ops */
1386};
1387
1388static struct modlinkage modlinkage = {
1389	MODREV_1,
1390	{ &audiopci_modldrv, NULL }
1391};
1392
1393int
1394_init(void)
1395{
1396	int	rv;
1397
1398	audio_init_ops(&audiopci_dev_ops, DRVNAME);
1399	if ((rv = mod_install(&modlinkage)) != 0) {
1400		audio_fini_ops(&audiopci_dev_ops);
1401	}
1402	return (rv);
1403}
1404
1405int
1406_fini(void)
1407{
1408	int	rv;
1409
1410	if ((rv = mod_remove(&modlinkage)) == 0) {
1411		audio_fini_ops(&audiopci_dev_ops);
1412	}
1413	return (rv);
1414}
1415
1416int
1417_info(struct modinfo *modinfop)
1418{
1419	return (mod_info(&modlinkage, modinfop));
1420}
1421