xref: /illumos-gate/usr/src/uts/common/io/audio/drv/audiols/audiols.c (revision 183ef8a1713ca188e24d970f22c6f9cc333007fd)
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 /*
23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Purpose: Driver for the Creative Audigy LS sound card
29  */
30 /*
31  *
32  * Copyright (C) 4Front Technologies 1996-2009.
33  */
34 
35 #include <sys/types.h>
36 #include <sys/modctl.h>
37 #include <sys/kmem.h>
38 #include <sys/conf.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41 #include <sys/pci.h>
42 #include <sys/note.h>
43 #include <sys/audio/audio_driver.h>
44 #include <sys/audio/ac97.h>
45 
46 #include "audiols.h"
47 
48 static struct ddi_device_acc_attr dev_attr = {
49 	DDI_DEVICE_ATTR_V0,
50 	DDI_STRUCTURE_LE_ACC,
51 	DDI_STRICTORDER_ACC
52 };
53 
54 static struct ddi_device_acc_attr buf_attr = {
55 	DDI_DEVICE_ATTR_V0,
56 	DDI_NEVERSWAP_ACC,
57 	DDI_STRICTORDER_ACC
58 };
59 
60 static ddi_dma_attr_t dma_attr_buf = {
61 	DMA_ATTR_V0,		/* version number */
62 	0x00000000,		/* low DMA address range */
63 	0xffffffff,		/* high DMA address range */
64 	0x000fffff,		/* DMA counter (16 bits only in Audigy LS) */
65 	4,			/* DMA address alignment */
66 	0x3c,			/* DMA burstsizes */
67 	4,			/* min effective DMA size */
68 	0xffffffff,		/* max DMA xfer size */
69 	0xffffffff,		/* segment boundary */
70 	1,			/* s/g length */
71 	4,			/* granularity of device */
72 	0			/* Bus specific DMA flags */
73 };
74 
75 static int audigyls_attach(dev_info_t *);
76 static int audigyls_resume(dev_info_t *);
77 static int audigyls_detach(audigyls_dev_t *);
78 static int audigyls_suspend(audigyls_dev_t *);
79 
80 static int audigyls_open(void *, int, unsigned *, caddr_t *);
81 static void audigyls_close(void *);
82 static int audigyls_start(void *);
83 static void audigyls_stop(void *);
84 static int audigyls_format(void *);
85 static int audigyls_channels(void *);
86 static int audigyls_rate(void *);
87 static uint64_t audigyls_count(void *);
88 static void audigyls_sync(void *, unsigned);
89 static void audigyls_chinfo(void *, int, unsigned *, unsigned *);
90 
91 
92 static uint16_t audigyls_read_ac97(void *, uint8_t);
93 static void audigyls_write_ac97(void *, uint8_t, uint16_t);
94 static int audigyls_alloc_port(audigyls_dev_t *, int);
95 static void audigyls_destroy(audigyls_dev_t *);
96 static void audigyls_hwinit(audigyls_dev_t *);
97 static void audigyls_configure_mixer(audigyls_dev_t *dev);
98 
99 static audio_engine_ops_t audigyls_engine_ops = {
100 	AUDIO_ENGINE_VERSION,
101 	audigyls_open,
102 	audigyls_close,
103 	audigyls_start,
104 	audigyls_stop,
105 	audigyls_count,
106 	audigyls_format,
107 	audigyls_channels,
108 	audigyls_rate,
109 	audigyls_sync,
110 	NULL,
111 	audigyls_chinfo,
112 	NULL
113 };
114 
115 /*
116  * Audigy LS uses AC'97 strictly for the recording side of things.
117  * While the chip can supposedly route output to AC'97 for playback,
118  * the PCI devices use a separate I2S DAC instead.  As a result we
119  * need to suppress controls that the AC'97 codec registers.
120  *
121  * Furthermore, even then the AC'97 codec offers inputs that we just
122  * aren't interested in.
123  */
124 const char *audigyls_remove_ac97[] = {
125 	AUDIO_CTRL_ID_VOLUME,
126 	AUDIO_CTRL_ID_LINEOUT,
127 	AUDIO_CTRL_ID_HEADPHONE,
128 	AUDIO_CTRL_ID_CD,
129 	AUDIO_CTRL_ID_VIDEO,
130 	AUDIO_CTRL_ID_3DDEPTH,
131 	AUDIO_CTRL_ID_3DENHANCE,
132 	AUDIO_CTRL_ID_BEEP,
133 	AUDIO_CTRL_ID_RECGAIN,
134 	AUDIO_CTRL_ID_RECSRC,
135 	AUDIO_CTRL_ID_LOOPBACK,
136 	NULL,
137 };
138 
139 /*
140  * AC'97 sources we don't want to expose.
141  */
142 const char *audigyls_badsrcs[] = {
143 	AUDIO_PORT_VIDEO,
144 	AUDIO_PORT_CD,
145 	AUDIO_PORT_STEREOMIX,
146 	AUDIO_PORT_MONOMIX,
147 	NULL,
148 };
149 
150 static unsigned int
151 read_chan(audigyls_dev_t *dev, int reg, int chn)
152 {
153 	uint32_t val;
154 
155 	mutex_enter(&dev->low_mutex);
156 	/* Pointer */
157 	OUTL(dev, PR, (reg << 16) | (chn & 0xffff));
158 	/* Data */
159 	val = INL(dev, DR);
160 	mutex_exit(&dev->low_mutex);
161 
162 	return (val);
163 }
164 
165 static void
166 write_chan(audigyls_dev_t *dev, int reg, int chn, uint32_t value)
167 {
168 	mutex_enter(&dev->low_mutex);
169 	/* Pointer */
170 	OUTL(dev, PR, (reg << 16) | (chn & 0x7));
171 	/* Data */
172 	OUTL(dev, DR, value);
173 	mutex_exit(&dev->low_mutex);
174 }
175 
176 static unsigned int
177 read_reg(audigyls_dev_t *dev, int reg)
178 {
179 	return (read_chan(dev, reg, 0));
180 }
181 
182 static void
183 write_reg(audigyls_dev_t *dev, int reg, uint32_t value)
184 {
185 	write_chan(dev, reg, 0, value);
186 }
187 
188 
189 static uint16_t
190 audigyls_read_ac97(void *arg, uint8_t index)
191 {
192 	audigyls_dev_t *dev = arg;
193 	uint16_t dtemp = 0;
194 	int i;
195 
196 	mutex_enter(&dev->low_mutex);
197 	OUTB(dev, AC97A, index);
198 	for (i = 0; i < 10000; i++) {
199 		if (INB(dev, AC97A) & 0x80)
200 			break;
201 	}
202 	if (i == 10000) {	/* Timeout */
203 		mutex_exit(&dev->low_mutex);
204 		return (0xffff);
205 	}
206 	dtemp = INW(dev, AC97D);
207 	mutex_exit(&dev->low_mutex);
208 
209 	return (dtemp);
210 }
211 
212 static void
213 audigyls_write_ac97(void *arg, uint8_t index, uint16_t data)
214 {
215 	audigyls_dev_t *dev = arg;
216 	int i;
217 
218 	mutex_enter(&dev->low_mutex);
219 	OUTB(dev, AC97A, index);
220 	for (i = 0; i < 50000; i++) {
221 		if (INB(dev, AC97A) & 0x80)
222 			break;
223 	}
224 	if (i == 50000) {
225 		mutex_exit(&dev->low_mutex);
226 		return;
227 	}
228 	OUTW(dev, AC97D, data);
229 	mutex_exit(&dev->low_mutex);
230 }
231 
232 static void
233 select_digital_enable(audigyls_dev_t *dev, int mode)
234 {
235 	/*
236 	 * Set the out3/spdif combo jack format.
237 	 * mode0=analog rear/center, 1=spdif
238 	 */
239 
240 	if (mode == 0) {
241 		write_reg(dev, SPC, 0x00000f00);
242 	} else {
243 		write_reg(dev, SPC, 0x0000000f);
244 	}
245 }
246 
247 /* only for SBLive 7.1 */
248 void
249 audigyls_i2c_write(audigyls_dev_t *dev, int reg, int data)
250 {
251 	int i, timeout, tmp;
252 
253 	tmp = (reg << 9 | data) << 16;	/* set the upper 16 bits */
254 	/* first write the command to the data reg */
255 	write_reg(dev, I2C_1, tmp);
256 	for (i = 0; i < 20; i++) {
257 		tmp = read_reg(dev, I2C_A) & ~0x6fe;
258 		/* see audigyls.pdf for bits */
259 		tmp |= 0x400 | 0x100 | 0x34;
260 		write_reg(dev, I2C_A, tmp);
261 		/* now wait till controller sets valid bit (0x100) to 0 */
262 		timeout = 0;
263 		for (;;) {
264 			tmp = read_reg(dev, I2C_A);
265 			if ((tmp & 0x100) == 0)
266 				break;
267 
268 			if (timeout > 100)
269 				break;
270 
271 			timeout++;
272 		}
273 
274 		/* transaction aborted */
275 		if (tmp & 0x200)
276 			break;
277 	}
278 }
279 
280 int
281 audigyls_spi_write(audigyls_dev_t *dev, int data)
282 {
283 	unsigned int orig;
284 	unsigned int tmp;
285 	int i, valid;
286 
287 	tmp = read_reg(dev, SPI);
288 	orig = (tmp & ~0x3ffff) | 0x30000;
289 	write_reg(dev, SPI, orig | data);
290 	valid = 0;
291 	/* Wait for status bit to return to 0 */
292 	for (i = 0; i < 1000; i++) {
293 		drv_usecwait(100);
294 		tmp = read_reg(dev, SPI);
295 		if (!(tmp & 0x10000)) {
296 			valid = 1;
297 			break;
298 		}
299 	}
300 	if (!valid)			/* Timed out */
301 		return (0);
302 
303 	return (1);
304 }
305 
306 /*
307  * Audio routines
308  */
309 
310 int
311 audigyls_open(void *arg, int flag, unsigned *nframesp, caddr_t *bufp)
312 {
313 	audigyls_port_t	 *port = arg;
314 	audigyls_dev_t	 *dev = port->dev;
315 
316 	_NOTE(ARGUNUSED(flag));
317 
318 	mutex_enter(&dev->mutex);
319 
320 	port->count = 0;
321 	*nframesp = port->buf_frames;
322 	*bufp = port->buf_kaddr;
323 	mutex_exit(&dev->mutex);
324 
325 	return (0);
326 }
327 
328 void
329 audigyls_close(void *arg)
330 {
331 	_NOTE(ARGUNUSED(arg));
332 }
333 
334 int
335 audigyls_start(void *arg)
336 {
337 	audigyls_port_t *port = arg;
338 	audigyls_dev_t	*dev = port->dev;
339 	uint32_t	tmp;
340 
341 	mutex_enter(&dev->mutex);
342 
343 	port->offset = 0;
344 
345 	switch (port->direction) {
346 	case AUDIGYLS_PLAY_PORT:
347 		write_chan(dev, PTCA, 0, 0);
348 		write_chan(dev, CPFA, 0, 0);
349 		write_chan(dev, CPCAV, 0, 0);
350 		write_chan(dev, PTCA, 1, 0);
351 		write_chan(dev, CPFA, 1, 0);
352 		write_chan(dev, CPCAV, 1, 0);
353 		write_chan(dev, PTCA, 3, 0);
354 		write_chan(dev, CPFA, 3, 0);
355 		write_chan(dev, CPCAV, 3, 0);
356 
357 		tmp = read_reg(dev, SA);
358 		tmp |= SA_SPA(0);
359 		tmp |= SA_SPA(1);
360 		tmp |= SA_SPA(3);
361 		write_reg(dev, SA, tmp);
362 		break;
363 
364 	case AUDIGYLS_REC_PORT:
365 		write_chan(dev, CRFA, 2, 0);
366 		write_chan(dev, CRCAV, 2, 0);
367 
368 		tmp = read_reg(dev, SA);
369 		tmp |= SA_SRA(2);
370 		write_reg(dev, SA, tmp);
371 		break;
372 	}
373 
374 	mutex_exit(&dev->mutex);
375 	return (0);
376 }
377 
378 void
379 audigyls_stop(void *arg)
380 {
381 	audigyls_port_t	*port = arg;
382 	audigyls_dev_t	*dev = port->dev;
383 	uint32_t	tmp;
384 
385 	mutex_enter(&dev->mutex);
386 
387 	switch (port->direction) {
388 	case AUDIGYLS_PLAY_PORT:
389 		tmp = read_reg(dev, SA);
390 		tmp &= ~SA_SPA(0);
391 		tmp &= ~SA_SPA(1);
392 		tmp &= ~SA_SPA(3);
393 		write_reg(dev, SA, tmp);
394 		break;
395 
396 	case AUDIGYLS_REC_PORT:
397 		tmp = read_reg(dev, SA);
398 		tmp &= ~SA_SRA(2);
399 		write_reg(dev, SA, tmp);
400 		break;
401 	}
402 
403 	mutex_exit(&dev->mutex);
404 }
405 
406 int
407 audigyls_format(void *arg)
408 {
409 	_NOTE(ARGUNUSED(arg));
410 
411 	return (AUDIO_FORMAT_S16_LE);
412 }
413 
414 int
415 audigyls_channels(void *arg)
416 {
417 	audigyls_port_t	*port = arg;
418 
419 	return (port->nchan);
420 }
421 
422 int
423 audigyls_rate(void *arg)
424 {
425 	_NOTE(ARGUNUSED(arg));
426 
427 	return (48000);
428 }
429 
430 void
431 audigyls_sync(void *arg, unsigned nframes)
432 {
433 	audigyls_port_t *port = arg;
434 	_NOTE(ARGUNUSED(nframes));
435 
436 	(void) ddi_dma_sync(port->buf_dmah, 0, 0, port->syncdir);
437 }
438 
439 uint64_t
440 audigyls_count(void *arg)
441 {
442 	audigyls_port_t	*port = arg;
443 	audigyls_dev_t	*dev = port->dev;
444 	uint64_t	count;
445 	uint32_t	offset, n;
446 
447 	mutex_enter(&dev->mutex);
448 
449 	if (port->direction == AUDIGYLS_PLAY_PORT) {
450 		offset = read_chan(dev, CPFA, 0);
451 	} else {
452 		offset = read_chan(dev, CRFA, 2);
453 	}
454 
455 	/* get the offset, and switch to frames */
456 	offset /= (2 * sizeof (uint16_t));
457 
458 	if (offset >= port->offset) {
459 		n = offset - port->offset;
460 	} else {
461 		n = offset + (port->buf_frames - port->offset);
462 	}
463 	port->offset = offset;
464 	port->count += n;
465 
466 	count = port->count;
467 	mutex_exit(&dev->mutex);
468 	return (count);
469 }
470 
471 static void
472 audigyls_chinfo(void *arg, int chan, unsigned *offset, unsigned *incr)
473 {
474 	audigyls_port_t *port = arg;
475 
476 	if (port->direction == AUDIGYLS_PLAY_PORT) {
477 		*offset = (port->buf_frames * 2 * (chan / 2)) + (chan % 2);
478 		*incr = 2;
479 	} else {
480 		*offset = chan;
481 		*incr = 2;
482 	}
483 }
484 
485 /* private implementation bits */
486 
487 int
488 audigyls_alloc_port(audigyls_dev_t *dev, int num)
489 {
490 	audigyls_port_t		*port;
491 	size_t			len;
492 	ddi_dma_cookie_t	cookie;
493 	uint_t			count;
494 	int			dir;
495 	unsigned		caps;
496 	audio_dev_t		*adev;
497 
498 	adev = dev->adev;
499 	port = kmem_zalloc(sizeof (*port), KM_SLEEP);
500 	dev->port[num] = port;
501 	port->dev = dev;
502 	port->direction = num;
503 
504 	switch (num) {
505 	case AUDIGYLS_REC_PORT:
506 		port->syncdir = DDI_DMA_SYNC_FORKERNEL;
507 		caps = ENGINE_INPUT_CAP;
508 		dir = DDI_DMA_READ;
509 		port->nchan = 2;
510 		break;
511 	case AUDIGYLS_PLAY_PORT:
512 		port->syncdir = DDI_DMA_SYNC_FORDEV;
513 		caps = ENGINE_OUTPUT_CAP;
514 		dir = DDI_DMA_WRITE;
515 		port->nchan = 6;
516 		break;
517 	default:
518 		return (DDI_FAILURE);
519 	}
520 
521 	port->buf_frames = 2048;
522 	port->buf_size = port->buf_frames * port->nchan * sizeof (int16_t);
523 
524 	/* Alloc buffers */
525 	if (ddi_dma_alloc_handle(dev->dip, &dma_attr_buf, DDI_DMA_SLEEP, NULL,
526 	    &port->buf_dmah) != DDI_SUCCESS) {
527 		audio_dev_warn(adev, "failed to allocate BUF handle");
528 		return (DDI_FAILURE);
529 	}
530 
531 	if (ddi_dma_mem_alloc(port->buf_dmah, port->buf_size,
532 	    &buf_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
533 	    &port->buf_kaddr, &len, &port->buf_acch) != DDI_SUCCESS) {
534 		audio_dev_warn(adev, "failed to allocate BUF memory");
535 		return (DDI_FAILURE);
536 	}
537 
538 	if (ddi_dma_addr_bind_handle(port->buf_dmah, NULL, port->buf_kaddr,
539 	    len, DDI_DMA_CONSISTENT | dir, DDI_DMA_SLEEP, NULL, &cookie,
540 	    &count) != DDI_SUCCESS) {
541 		audio_dev_warn(adev, "failed binding BUF DMA handle");
542 		return (DDI_FAILURE);
543 	}
544 	port->buf_paddr = cookie.dmac_address;
545 
546 	port->engine = audio_engine_alloc(&audigyls_engine_ops, caps);
547 	if (port->engine == NULL) {
548 		audio_dev_warn(adev, "audio_engine_alloc failed");
549 		return (DDI_FAILURE);
550 	}
551 
552 	audio_engine_set_private(port->engine, port);
553 	audio_dev_add_engine(adev, port->engine);
554 
555 	return (DDI_SUCCESS);
556 }
557 
558 void
559 audigyls_del_controls(audigyls_dev_t *dev)
560 {
561 	for (int i = 0; i < CTL_NUM; i++) {
562 		if (dev->controls[i].ctrl) {
563 			audio_dev_del_control(dev->controls[i].ctrl);
564 			dev->controls[i].ctrl = NULL;
565 		}
566 	}
567 }
568 
569 void
570 audigyls_destroy(audigyls_dev_t *dev)
571 {
572 	mutex_destroy(&dev->mutex);
573 	mutex_destroy(&dev->low_mutex);
574 
575 	for (int i = 0; i < AUDIGYLS_NUM_PORT; i++) {
576 		audigyls_port_t *port = dev->port[i];
577 		if (!port)
578 			continue;
579 		if (port->engine) {
580 			audio_dev_remove_engine(dev->adev, port->engine);
581 			audio_engine_free(port->engine);
582 		}
583 		if (port->buf_paddr) {
584 			(void) ddi_dma_unbind_handle(port->buf_dmah);
585 		}
586 		if (port->buf_acch) {
587 			ddi_dma_mem_free(&port->buf_acch);
588 		}
589 		if (port->buf_dmah) {
590 			ddi_dma_free_handle(&port->buf_dmah);
591 		}
592 		kmem_free(port, sizeof (*port));
593 	}
594 
595 	if (dev->ac97 != NULL) {
596 		ac97_free(dev->ac97);
597 	}
598 
599 	audigyls_del_controls(dev);
600 
601 	if (dev->adev != NULL) {
602 		audio_dev_free(dev->adev);
603 	}
604 	if (dev->regsh != NULL) {
605 		ddi_regs_map_free(&dev->regsh);
606 	}
607 	if (dev->pcih != NULL) {
608 		pci_config_teardown(&dev->pcih);
609 	}
610 	kmem_free(dev, sizeof (*dev));
611 }
612 
613 void
614 audigyls_hwinit(audigyls_dev_t *dev)
615 {
616 	static unsigned int spi_dac[] = {
617 		0x00ff, 0x02ff, 0x0400, 0x520, 0x0620, 0x08ff, 0x0aff, 0x0cff,
618 		0x0eff, 0x10ff, 0x1200, 0x1400, 0x1800, 0x1aff, 0x1cff,
619 		0x1e00, 0x0530, 0x0602, 0x0622, 0x1400,
620 	};
621 
622 	uint32_t	tmp;
623 	int		i, tries;
624 	uint32_t	paddr;
625 	uint32_t	chunksz;
626 	audigyls_port_t	*port;
627 
628 
629 	/* Set the orange jack to be analog out or S/PDIF */
630 	select_digital_enable(dev, dev->digital_enable);
631 
632 	/*
633 	 * In P17, there's 8 GPIO pins.
634 	 * GPIO register: 0x00XXYYZZ
635 	 * XX: Configure GPIO to be either GPI (0) or GPO (1).
636 	 * YY: GPO values, applicable if the pin is configure to be GPO.
637 	 * ZZ: GPI values, applicable if the pin is configure to be GPI.
638 	 *
639 	 * in SB570, pin 0-4 and 6 is used as GPO and pin 5 and 7 is
640 	 * used as GPI.
641 	 *
642 	 * GPO0:
643 	 * 1 ==> Analog output
644 	 * 0 ==> Digital output
645 	 * GPO1:
646 	 * 1 ==> Enable output on card
647 	 * 0 ==> Disable output on card
648 	 * GPO2:
649 	 * 1 ==> Enable Mic Bias and Mic Path
650 	 * 0 ==> Disable Mic Bias and Mic Path
651 	 * GPO3:
652 	 * 1 ==> Disable SPDIF-IO output
653 	 * 0 ==> Enable SPDIF-IO output
654 	 * GPO4 and GPO6:
655 	 * DAC sampling rate selection:
656 	 * Not applicable to SB570 since DAC is controlled through SPI
657 	 * GPI5:
658 	 * 1 ==> Front Panel is not connected
659 	 * 0 ==> Front Panel is connected
660 	 * GPI7:
661 	 * 1 ==> Front Panel Headphone is not connected
662 	 * 0 ==> Front Panel Headphone is connected
663 	 */
664 	if (dev->ac97)
665 		OUTL(dev, GPIO, 0x005f03a3);
666 	else {
667 		/* for SBLive 7.1 */
668 		OUTL(dev, GPIO, 0x005f4301);
669 
670 		audigyls_i2c_write(dev, 0x15, 0x2);
671 		tries = 0;
672 	again:
673 		for (i = 0; i < sizeof (spi_dac); i++) {
674 			if (!audigyls_spi_write(dev, spi_dac[i]) &&
675 			    tries < 100) {
676 				tries++;
677 				goto again;
678 			}
679 		}
680 	}
681 
682 	OUTL(dev, IER, 0);
683 	OUTL(dev, HC, 0x00000009);	/* Enable audio, use 48 kHz */
684 
685 	tmp = read_chan(dev, SRCTL, 0);
686 	if (dev->ac97)
687 		tmp |= 0xf0c81000;	/* Record src0/src1 from ac97 */
688 	else
689 		tmp |= 0x50c81000;	/* Record src0/src1 from I2SIN */
690 	tmp &= ~0x0303c00f;		/* Set sample rates to 48 kHz */
691 	write_chan(dev, SRCTL, 0, tmp);
692 
693 	write_reg(dev, HMIXMAP_I2S, 0x76543210);	/* Default out route */
694 	write_reg(dev, AUDCTL, 0x0f0f003f);	/* Enable all outputs */
695 
696 	/* All audio stopped! */
697 	write_reg(dev, SA, 0);
698 
699 	for (i = 0; i < 4; i++) {
700 		/*
701 		 * Reset DMA pointers and counters.  Note that we do
702 		 * not use scatter/gather.
703 		 */
704 		write_chan(dev, PTBA, i, 0);
705 		write_chan(dev, PTBS, i, 0);
706 		write_chan(dev, PTCA, i, 0);
707 
708 		write_chan(dev, CPFA, i, 0);
709 		write_chan(dev, PFEA, i, 0);
710 		write_chan(dev, CPCAV, i, 0);
711 
712 		write_chan(dev, CRFA, i, 0);
713 		write_chan(dev, CRCAV, i, 0);
714 	}
715 
716 	/*
717 	 * The 5.1 play port made up channels 0, 1, and 3.  The record
718 	 * port is channel 2.
719 	 */
720 	port = dev->port[AUDIGYLS_PLAY_PORT];
721 	paddr = port->buf_paddr;
722 	chunksz = port->buf_frames * 4;
723 	write_chan(dev, PFBA, 0, paddr);
724 	write_chan(dev, PFBS, 0, chunksz << 16);
725 	paddr += chunksz;
726 	write_chan(dev, PFBA, 1, paddr);
727 	write_chan(dev, PFBS, 1, chunksz << 16);
728 	paddr += chunksz;
729 	write_chan(dev, PFBA, 3, paddr);
730 	write_chan(dev, PFBS, 3, chunksz << 16);
731 
732 	/* Record */
733 	port = dev->port[AUDIGYLS_REC_PORT];
734 	paddr = port->buf_paddr;
735 	chunksz = port->buf_frames * 4;
736 	write_chan(dev, RFBA, 2, paddr);
737 	write_chan(dev, RFBS, 2, chunksz << 16);
738 
739 	/* Set sample rates to 48 kHz. */
740 	tmp = read_chan(dev, SRCTL, 0) & ~0x0303c00f;
741 	write_chan(dev, SRCTL, 0, tmp);
742 
743 	write_reg(dev, SCS0, 0x02108004);	/* Audio */
744 	write_reg(dev, SCS1, 0x02108004);	/* Audio */
745 	write_reg(dev, SCS2, 0x02108004);	/* Audio */
746 	write_reg(dev, SCS3, 0x02108004);	/* Audio */
747 }
748 
749 #define	PLAYCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_PLAY)
750 #define	RECCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC)
751 #define	MONCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_MONITOR)
752 #define	PCMVOL	(PLAYCTL | AUDIO_CTRL_FLAG_PCMVOL)
753 #define	MAINVOL	(PLAYCTL | AUDIO_CTRL_FLAG_MAINVOL)
754 #define	RECVOL	(RECCTL | AUDIO_CTRL_FLAG_RECVOL)
755 #define	MONVOL	(MONCTL | AUDIO_CTRL_FLAG_MONVOL)
756 
757 #define	MASK(nbits)	((1 << (nbits)) - 1)
758 #define	SCALE(val, nbits)	\
759 	((uint8_t)((((val) * MASK(nbits)) / 100)) << (8 - (nbits)))
760 
761 static uint32_t
762 audigyls_stereo_scale(uint32_t value, uint8_t bits)
763 {
764 	uint8_t			left, right;
765 	uint32_t		val;
766 
767 	left = (value >> 8) & 0xff;
768 	right = value & 0xff;
769 
770 	val = (((left * ((1 << bits) - 1) / 100) << 8) |
771 	    (right * ((1 << bits) - 1) / 100));
772 	return (val);
773 }
774 
775 static void
776 audigyls_configure_mixer(audigyls_dev_t *dev)
777 {
778 	unsigned int	r, v1, v2;
779 
780 	/* output items */
781 	/* front */
782 	r = 0xffff - audigyls_stereo_scale(dev->controls[CTL_FRONT].val, 8);
783 	r = (r << 16) | r;
784 	write_chan(dev, MIXVOL_I2S, 0, r);
785 
786 	/* surround */
787 	r = 0xffff - audigyls_stereo_scale(dev->controls[CTL_SURROUND].val, 8);
788 	r = (r << 16) | r;
789 	write_chan(dev, MIXVOL_I2S, 3, r);
790 
791 	/* center/lfe */
792 	v1 = 255 - SCALE(dev->controls[CTL_CENTER].val, 8);
793 	v2 = 255 - SCALE(dev->controls[CTL_LFE].val, 8);
794 	r = (v1 << 8) | v2;
795 	r = (r << 16) | r;
796 	write_chan(dev, MIXVOL_I2S, 1, r);
797 
798 	/* spread */
799 	r = dev->controls[CTL_SPREAD].val ? 0x10101010 : 0x76543210;
800 	write_reg(dev, HMIXMAP_I2S, r);
801 
802 	/* input items */
803 
804 	/* recgain */
805 	v1 = dev->controls[CTL_RECORDVOL].val;
806 	if (dev->ac97_recgain && !dev->controls[CTL_LOOP].val) {
807 		/*
808 		 * For AC'97, we use the AC'97 record gain, unless we are
809 		 * in loopback.
810 		 */
811 		(void) ac97_control_set(dev->ac97_recgain, v1);
812 		write_reg(dev, P17RECVOLL, 0x30303030);
813 		write_reg(dev, P17RECVOLH, 0x30303030);
814 	} else {
815 		/*
816 		 * Otherwise we set the P17 gain.
817 		 */
818 		r = 0xffff - audigyls_stereo_scale(v1, 8);
819 		r = r << 16 | r;
820 		write_reg(dev, P17RECVOLL, r);
821 		write_reg(dev, P17RECVOLH, r);
822 	}
823 
824 	/* monitor gain */
825 	if (dev->ac97) {
826 		/* AC'97 monitor gain is done by the AC'97 codec */
827 		write_chan(dev, SRCTL, 1, 0x30303030);
828 		write_reg(dev, SMIXMAP_I2S, 0x10101076);
829 	} else {
830 		/* For non-AC'97 devices, just a single master monitor gain */
831 		r = 255 - SCALE(dev->controls[CTL_MONGAIN].val, 8);
832 		write_chan(dev, SRCTL, 1, 0xffff0000 | r << 8 | r);
833 		if (r != 0xff) {
834 			write_reg(dev, SMIXMAP_I2S, 0x10101076);
835 		} else {
836 			write_reg(dev, SMIXMAP_I2S, 0x10101010);
837 		}
838 	}
839 
840 	/* record source */
841 	if (dev->ac97_recsrc != NULL) {
842 		(void) ac97_control_set(dev->ac97_recsrc,
843 		    dev->controls[CTL_RECSRC].val);
844 		v1 = RECSEL_AC97;	/* Audigy LS */
845 	} else {
846 		switch (dev->controls[CTL_RECSRC].val) {
847 		case 1:
848 			audigyls_i2c_write(dev, 0x15, 0x2);   /* Mic */
849 			OUTL(dev, GPIO, INL(dev, GPIO) | 0x400);
850 			break;
851 
852 		case 2:
853 			audigyls_i2c_write(dev, 0x15, 0x4);   /* Line */
854 			OUTL(dev, GPIO, INL(dev, GPIO) & ~0x400);
855 			break;
856 		}
857 		v1 = RECSEL_I2SIN;	/* SB 7.1 value */
858 	}
859 
860 	/* If loopback, record what you hear instead */
861 
862 	if (dev->controls[CTL_LOOP].val) {
863 		r = 0;
864 		v1 = RECSEL_I2SOUT;
865 		r |= (v1 << 28) | (v1 << 24) | (v1 << 20) | (v1 << 16) | v1;
866 	} else {
867 		/*
868 		 * You'd think this would be the same as the logic
869 		 * above, but experience shows that what you need for
870 		 * loopback is different.  This whole thing looks
871 		 * particularly fishy to me.  I suspect someone has
872 		 * made a mistake somewhere.  But I can't seem to
873 		 * figure out where it lies.
874 		 */
875 		if (dev->ac97_recsrc != NULL) {
876 			r = 0xe4;
877 			for (int i = 0; i < 4; i++)
878 				r |= v1 << (16 + i * 3); /* Select input */
879 		} else {
880 			r = (v1 << 28) | (v1 << 24) | (v1 << 20) | (v1 << 16) |
881 			    v1;
882 		}
883 	}
884 
885 	write_reg(dev, P17RECSEL, r);
886 }
887 
888 static int
889 audigyls_set_control(void *arg, uint64_t val)
890 {
891 	audigyls_ctrl_t	*pc = arg;
892 	audigyls_dev_t	*dev = pc->dev;
893 
894 	switch (pc->num) {
895 
896 	case CTL_FRONT:
897 	case CTL_SURROUND:
898 	case CTL_RECORDVOL:
899 		if (((val & 0xff) > 100) ||
900 		    (((val & 0xff00) >> 8) > 100) ||
901 		    ((val & ~0xffff) != 0)) {
902 			return (EINVAL);
903 		}
904 		break;
905 
906 	case CTL_CENTER:
907 	case CTL_LFE:
908 	case CTL_MONGAIN:
909 		if (val > 100) {
910 			return (EINVAL);
911 		}
912 		break;
913 
914 	case CTL_RECSRC:
915 		if (((1U << val) & (dev->recmask)) == 0) {
916 			return (EINVAL);
917 		}
918 		break;
919 
920 	case CTL_SPREAD:
921 	case CTL_LOOP:
922 		switch (val) {
923 		case 0:
924 		case 1:
925 			break;
926 		default:
927 			return (EINVAL);
928 		}
929 	}
930 
931 	mutex_enter(&dev->mutex);
932 	pc->val = val;
933 	audigyls_configure_mixer(dev);
934 
935 	mutex_exit(&dev->mutex);
936 
937 	return (0);
938 }
939 
940 static int
941 audigyls_get_control(void *arg, uint64_t *val)
942 {
943 	audigyls_ctrl_t	*pc = arg;
944 	audigyls_dev_t	*dev = pc->dev;
945 
946 	mutex_enter(&dev->mutex);
947 	*val = pc->val;
948 	mutex_exit(&dev->mutex);
949 	return (0);
950 }
951 
952 static void
953 audigyls_alloc_ctrl(audigyls_dev_t *dev, uint32_t num, uint64_t val)
954 {
955 	audio_ctrl_desc_t	desc;
956 	audigyls_ctrl_t		*pc;
957 
958 	bzero(&desc, sizeof (desc));
959 
960 	pc = &dev->controls[num];
961 	pc->num = num;
962 	pc->dev = dev;
963 
964 
965 	switch (num) {
966 	case CTL_FRONT:
967 		desc.acd_name = AUDIO_CTRL_ID_FRONT;
968 		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
969 		desc.acd_minvalue = 0;
970 		desc.acd_maxvalue = 100;
971 		desc.acd_flags = MAINVOL;
972 		break;
973 
974 	case CTL_SURROUND:
975 		desc.acd_name = AUDIO_CTRL_ID_SURROUND;
976 		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
977 		desc.acd_minvalue = 0;
978 		desc.acd_maxvalue = 100;
979 		desc.acd_flags = MAINVOL;
980 		break;
981 
982 	case CTL_CENTER:
983 		desc.acd_name = AUDIO_CTRL_ID_CENTER;
984 		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
985 		desc.acd_minvalue = 0;
986 		desc.acd_maxvalue = 100;
987 		desc.acd_flags = MAINVOL;
988 		break;
989 
990 	case CTL_LFE:
991 		desc.acd_name = AUDIO_CTRL_ID_LFE;
992 		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
993 		desc.acd_minvalue = 0;
994 		desc.acd_maxvalue = 100;
995 		desc.acd_flags = MAINVOL;
996 		break;
997 
998 	case CTL_RECORDVOL:
999 		desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
1000 		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1001 		desc.acd_minvalue = 0;
1002 		desc.acd_maxvalue = 100;
1003 		desc.acd_flags = RECVOL;
1004 		break;
1005 
1006 	case CTL_RECSRC:
1007 		desc.acd_name = AUDIO_CTRL_ID_RECSRC;
1008 		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
1009 		desc.acd_flags = RECCTL;
1010 
1011 		/*
1012 		 * For AC'97 devices, we want to expose the reasonable
1013 		 * AC'97 input sources, but suppress the stereomix,
1014 		 * because we use loopback instead.
1015 		 */
1016 		if (dev->ac97_recsrc) {
1017 			int i, j;
1018 			const char *n;
1019 			const audio_ctrl_desc_t *adp;
1020 
1021 			adp = ac97_control_desc(dev->ac97_recsrc);
1022 			for (i = 0; i < 64; i++) {
1023 				n = adp->acd_enum[i];
1024 
1025 				if (((adp->acd_minvalue & (1 << i)) == 0) ||
1026 				    (n == NULL)) {
1027 					continue;
1028 				}
1029 				for (j = 0; audigyls_badsrcs[j]; j++) {
1030 					if (strcmp(n, audigyls_badsrcs[j])
1031 					    == 0) {
1032 						n = NULL;
1033 						break;
1034 					}
1035 				}
1036 				if (n) {
1037 					desc.acd_enum[i] = n;
1038 					dev->recmask |= (1 << i);
1039 				}
1040 			}
1041 			desc.acd_minvalue = desc.acd_maxvalue = dev->recmask;
1042 		} else {
1043 			dev->recmask = 3;
1044 			desc.acd_minvalue = 3;
1045 			desc.acd_maxvalue = 3;
1046 			desc.acd_enum[0] = AUDIO_PORT_MIC;
1047 			desc.acd_enum[1] = AUDIO_PORT_LINEIN;
1048 		}
1049 		break;
1050 
1051 	case CTL_MONGAIN:
1052 		ASSERT(!dev->ac97);
1053 		desc.acd_name = AUDIO_CTRL_ID_MONGAIN;
1054 		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
1055 		desc.acd_minvalue = 0;
1056 		desc.acd_maxvalue = 100;
1057 		desc.acd_flags = MONVOL;
1058 		break;
1059 
1060 	case CTL_SPREAD:
1061 		desc.acd_name = AUDIO_CTRL_ID_SPREAD;
1062 		desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
1063 		desc.acd_minvalue = 0;
1064 		desc.acd_maxvalue = 1;
1065 		desc.acd_flags = PLAYCTL;
1066 		break;
1067 
1068 	case CTL_LOOP:
1069 		desc.acd_name = AUDIO_CTRL_ID_LOOPBACK;
1070 		desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
1071 		desc.acd_minvalue = 0;
1072 		desc.acd_maxvalue = 1;
1073 		desc.acd_flags = RECCTL;
1074 		break;
1075 	}
1076 
1077 	pc->val = val;
1078 	pc->ctrl = audio_dev_add_control(dev->adev, &desc,
1079 	    audigyls_get_control, audigyls_set_control, pc);
1080 }
1081 
1082 static void
1083 audigyls_add_controls(audigyls_dev_t *dev)
1084 {
1085 	(void) audio_dev_add_soft_volume(dev->adev);
1086 
1087 	audigyls_alloc_ctrl(dev, CTL_FRONT, 75 | (75 << 8));
1088 	audigyls_alloc_ctrl(dev, CTL_SURROUND, 75 | (75 << 8));
1089 	audigyls_alloc_ctrl(dev, CTL_CENTER, 75);
1090 	audigyls_alloc_ctrl(dev, CTL_LFE, 75);
1091 	audigyls_alloc_ctrl(dev, CTL_RECORDVOL, 75 | (75 << 8));
1092 	audigyls_alloc_ctrl(dev, CTL_RECSRC, 1);
1093 	audigyls_alloc_ctrl(dev, CTL_SPREAD, 0);
1094 	audigyls_alloc_ctrl(dev, CTL_LOOP, 0);
1095 	if (!dev->ac97) {
1096 		audigyls_alloc_ctrl(dev, CTL_MONGAIN, 0);
1097 	}
1098 }
1099 
1100 int
1101 audigyls_attach(dev_info_t *dip)
1102 {
1103 	uint16_t	pci_command, vendor, device;
1104 	uint32_t	subdevice;
1105 	audigyls_dev_t	*dev;
1106 	ddi_acc_handle_t pcih;
1107 	const char	*name, *version;
1108 	boolean_t	ac97 = B_FALSE;
1109 
1110 	dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
1111 	dev->dip = dip;
1112 	ddi_set_driver_private(dip, dev);
1113 	mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, NULL);
1114 	mutex_init(&dev->low_mutex, NULL, MUTEX_DRIVER, NULL);
1115 
1116 	if ((dev->adev = audio_dev_alloc(dip, 0)) == NULL) {
1117 		cmn_err(CE_WARN, "audio_dev_alloc failed");
1118 		goto error;
1119 	}
1120 
1121 	if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
1122 		audio_dev_warn(dev->adev, "pci_config_setup failed");
1123 		goto error;
1124 	}
1125 	dev->pcih = pcih;
1126 
1127 	vendor = pci_config_get16(pcih, PCI_CONF_VENID);
1128 	device = pci_config_get16(pcih, PCI_CONF_DEVID);
1129 	subdevice = pci_config_get16(pcih, PCI_CONF_SUBVENID);
1130 	subdevice <<= 16;
1131 	subdevice |= pci_config_get16(pcih, PCI_CONF_SUBSYSID);
1132 	if (vendor != PCI_VENDOR_ID_CREATIVE ||
1133 	    device != PCI_DEVICE_ID_CREATIVE_AUDIGYLS) {
1134 		audio_dev_warn(dev->adev, "Hardware not recognized "
1135 		    "(vendor=%x, dev=%x)", vendor, device);
1136 		goto error;
1137 	}
1138 
1139 	pci_command = pci_config_get16(pcih, PCI_CONF_COMM);
1140 	pci_command |= PCI_COMM_ME | PCI_COMM_IO;
1141 	pci_config_put16(pcih, PCI_CONF_COMM, pci_command);
1142 
1143 	if ((ddi_regs_map_setup(dip, 1, &dev->base, 0, 0, &dev_attr,
1144 	    &dev->regsh)) != DDI_SUCCESS) {
1145 		audio_dev_warn(dev->adev, "failed to map registers");
1146 		goto error;
1147 	}
1148 
1149 	/* Function of the orange jack: 0=analog, 1=digital */
1150 	dev->digital_enable = ddi_prop_get_int(DDI_DEV_T_ANY, dev->dip,
1151 	    DDI_PROP_DONTPASS, "digital-enable", 0);
1152 
1153 	switch (subdevice) {
1154 	case 0x11021001:	/* SB0310 */
1155 	case 0x11021002:	/* SB0310 */
1156 	case 0x11021005:	/* SB0310b */
1157 		name = "Creative Audigy LS";
1158 		version = "SB0310";	/* could also be SB0312 */
1159 		ac97 = B_TRUE;
1160 		break;
1161 	case 0x11021006:
1162 		name = "Creative Sound Blaster Live! 24 bit";
1163 		version = "SB0410";
1164 		break;
1165 	case 0x11021007:	/* Dell OEM version */
1166 		name = "Creative Sound Blaster Live! 24 bit";
1167 		version = "SB0413";
1168 		break;
1169 	case 0x1102100a:
1170 		name = "Creative Audigy SE";
1171 		version = "SB0570";
1172 		break;
1173 	case 0x11021011:
1174 		name = "Creative Audigy SE OEM";
1175 		version = "SB0570a";
1176 		break;
1177 	case 0x11021012:
1178 		name = "Creative X-Fi Extreme Audio";
1179 		version = "SB0790";
1180 		break;
1181 	case 0x14621009:
1182 		name = "MSI K8N Diamond MB";
1183 		version = "SB0438";
1184 		break;
1185 	case 0x12973038:
1186 		name = "Shuttle XPC SD31P";
1187 		version = "SD31P";
1188 		break;
1189 	case 0x12973041:
1190 		name = "Shuttle XPC SD11G5";
1191 		version = "SD11G5";
1192 		break;
1193 	default:
1194 		name = "Creative Audigy LS";
1195 		version = NULL;
1196 		break;
1197 	}
1198 
1199 	audio_dev_set_description(dev->adev, name);
1200 	if (version)
1201 		audio_dev_set_version(dev->adev, version);
1202 
1203 	if (ac97) {
1204 		ac97_ctrl_t *ctrl;
1205 
1206 		/* Original Audigy LS revision (AC97 based) */
1207 		dev->ac97 = ac97_allocate(dev->adev, dip,
1208 		    audigyls_read_ac97, audigyls_write_ac97, dev);
1209 		if (dev->ac97 == NULL) {
1210 			audio_dev_warn(dev->adev,
1211 			    "failed to allocate ac97 handle");
1212 			goto error;
1213 		}
1214 
1215 		ac97_probe_controls(dev->ac97);
1216 
1217 		/* remove the AC'97 controls we don't want to expose */
1218 		for (int i = 0; audigyls_remove_ac97[i]; i++) {
1219 			ctrl = ac97_control_find(dev->ac97,
1220 			    audigyls_remove_ac97[i]);
1221 			if (ctrl != NULL) {
1222 				ac97_control_unregister(ctrl);
1223 			}
1224 		}
1225 
1226 		dev->ac97_recgain = ac97_control_find(dev->ac97,
1227 		    AUDIO_CTRL_ID_RECGAIN);
1228 		dev->ac97_recsrc = ac97_control_find(dev->ac97,
1229 		    AUDIO_CTRL_ID_RECSRC);
1230 	}
1231 
1232 	audigyls_add_controls(dev);
1233 
1234 	if (dev->ac97) {
1235 		ac97_register_controls(dev->ac97);
1236 	}
1237 
1238 	if (audigyls_alloc_port(dev, AUDIGYLS_PLAY_PORT) != DDI_SUCCESS)
1239 		goto error;
1240 	if (audigyls_alloc_port(dev, AUDIGYLS_REC_PORT) != DDI_SUCCESS)
1241 		goto error;
1242 
1243 	audigyls_hwinit(dev);
1244 
1245 	audigyls_configure_mixer(dev);
1246 
1247 	if (audio_dev_register(dev->adev) != DDI_SUCCESS) {
1248 		audio_dev_warn(dev->adev, "unable to register with framework");
1249 		goto error;
1250 	}
1251 
1252 	ddi_report_dev(dip);
1253 
1254 	return (DDI_SUCCESS);
1255 
1256 error:
1257 	audigyls_destroy(dev);
1258 	return (DDI_FAILURE);
1259 }
1260 
1261 int
1262 audigyls_resume(dev_info_t *dip)
1263 {
1264 	audigyls_dev_t *dev;
1265 
1266 	dev = ddi_get_driver_private(dip);
1267 
1268 	audigyls_hwinit(dev);
1269 
1270 	/* allow ac97 operations again */
1271 	if (dev->ac97)
1272 		ac97_reset(dev->ac97);
1273 
1274 	audio_dev_resume(dev->adev);
1275 
1276 	return (DDI_SUCCESS);
1277 }
1278 
1279 int
1280 audigyls_detach(audigyls_dev_t *dev)
1281 {
1282 	if (audio_dev_unregister(dev->adev) != DDI_SUCCESS)
1283 		return (DDI_FAILURE);
1284 
1285 	audigyls_destroy(dev);
1286 	return (DDI_SUCCESS);
1287 }
1288 
1289 int
1290 audigyls_suspend(audigyls_dev_t *dev)
1291 {
1292 	audio_dev_suspend(dev->adev);
1293 
1294 	return (DDI_SUCCESS);
1295 }
1296 
1297 static int audigyls_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
1298 static int audigyls_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
1299 static int audigyls_ddi_quiesce(dev_info_t *);
1300 
1301 static struct dev_ops audigyls_dev_ops = {
1302 	DEVO_REV,		/* rev */
1303 	0,			/* refcnt */
1304 	NULL,			/* getinfo */
1305 	nulldev,		/* identify */
1306 	nulldev,		/* probe */
1307 	audigyls_ddi_attach,	/* attach */
1308 	audigyls_ddi_detach,	/* detach */
1309 	nodev,			/* reset */
1310 	NULL,			/* cb_ops */
1311 	NULL,			/* bus_ops */
1312 	NULL,			/* power */
1313 	audigyls_ddi_quiesce,	/* quiesce */
1314 };
1315 
1316 static struct modldrv audigyls_modldrv = {
1317 	&mod_driverops,			/* drv_modops */
1318 	"Creative Audigy LS Audio",		/* linkinfo */
1319 	&audigyls_dev_ops,			/* dev_ops */
1320 };
1321 
1322 static struct modlinkage modlinkage = {
1323 	MODREV_1,
1324 	{ &audigyls_modldrv, NULL }
1325 };
1326 
1327 int
1328 _init(void)
1329 {
1330 	int	rv;
1331 
1332 	audio_init_ops(&audigyls_dev_ops, AUDIGYLS_NAME);
1333 	if ((rv = mod_install(&modlinkage)) != 0) {
1334 		audio_fini_ops(&audigyls_dev_ops);
1335 	}
1336 	return (rv);
1337 }
1338 
1339 int
1340 _fini(void)
1341 {
1342 	int	rv;
1343 
1344 	if ((rv = mod_remove(&modlinkage)) == 0) {
1345 		audio_fini_ops(&audigyls_dev_ops);
1346 	}
1347 	return (rv);
1348 }
1349 
1350 int
1351 _info(struct modinfo *modinfop)
1352 {
1353 	return (mod_info(&modlinkage, modinfop));
1354 }
1355 
1356 int
1357 audigyls_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1358 {
1359 	switch (cmd) {
1360 	case DDI_ATTACH:
1361 		return (audigyls_attach(dip));
1362 
1363 	case DDI_RESUME:
1364 		return (audigyls_resume(dip));
1365 
1366 	default:
1367 		return (DDI_FAILURE);
1368 	}
1369 }
1370 
1371 int
1372 audigyls_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1373 {
1374 	audigyls_dev_t *dev;
1375 
1376 	dev = ddi_get_driver_private(dip);
1377 
1378 	switch (cmd) {
1379 	case DDI_DETACH:
1380 		return (audigyls_detach(dev));
1381 
1382 	case DDI_SUSPEND:
1383 		return (audigyls_suspend(dev));
1384 
1385 	default:
1386 		return (DDI_FAILURE);
1387 	}
1388 }
1389 
1390 int
1391 audigyls_ddi_quiesce(dev_info_t *dip)
1392 {
1393 	audigyls_dev_t	*dev;
1394 	uint32_t status;
1395 
1396 	/*
1397 	 * Turn off the hardware
1398 	 */
1399 	dev = ddi_get_driver_private(dip);
1400 
1401 	write_reg(dev, SA, 0);
1402 	OUTL(dev, IER, 0);	/* Interrupt disable */
1403 	write_reg(dev, AIE, 0);	/* Disable audio interrupts */
1404 	status = INL(dev, IPR);
1405 	OUTL(dev, IPR, status);	/* Acknowledge */
1406 	return (DDI_SUCCESS);
1407 }
1408