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