xref: /illumos-gate/usr/src/uts/common/io/audio/drv/audiocmi/audiocmi.c (revision 8119dad84d6416f13557b0ba8e2aaf9064cbcfd3)
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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 /*
25  * Purpose: Driver for CMEDIA CM8738 PCI audio controller.
26  */
27 /*
28  * This file is part of Open Sound System
29  *
30  * Copyright (C) 4Front Technologies 1996-2008.
31  */
32 
33 #include <sys/audio/audio_driver.h>
34 #include <sys/note.h>
35 #include <sys/pci.h>
36 #include <sys/sysmacros.h>
37 #include "audiocmi.h"
38 
39 /*
40  * Note: The original 4Front driver had support SPDIF and dual dac
41  * options.  Dual dac support is probably not terribly useful. SPDIF
42  * on the other hand might be quite useful, we just don't have a card
43  * that supports it at present.  Some variants of the chip are also
44  * capable of jack retasking, but we're electing to punt on supporting
45  * that as well, for now (we don't have any cards that would benefit
46  * from this feature.)
47  *
48  * Note that surround support requires the use of the second DMA
49  * engine, and that the same second DMA engine is the only way one can
50  * capture from SPDIF.  Rather than support a lot more complexity in
51  * the driver, we we will probably just punt on ever supporting
52  * capture of SPDIF.  (SPDIF playback should be doable, however.)
53  *
54  * Adding back support for the advanced features would be an
55  * interesting project for someone with access to suitable hardware.
56  *
57  * Note that each variant (CMI 8338, 8738-033, -037, -055, and 8768)
58  * seems to have significant differences in some of the registers.
59  * While programming these parts for basic stereo is pretty much the
60  * same on all parts, doing anything more than that can be
61  * sigificantly different for each part.
62  */
63 
64 static ddi_device_acc_attr_t acc_attr = {
65 	DDI_DEVICE_ATTR_V0,
66 	DDI_STRUCTURE_LE_ACC,
67 	DDI_STRICTORDER_ACC
68 };
69 
70 static ddi_device_acc_attr_t buf_attr = {
71 	DDI_DEVICE_ATTR_V0,
72 	DDI_NEVERSWAP_ACC,
73 	DDI_STRICTORDER_ACC
74 };
75 
76 static ddi_dma_attr_t dma_attr = {
77 	DMA_ATTR_VERSION,	/* dma_attr_version */
78 	0x0,			/* dma_attr_addr_lo */
79 	0xffffffffU,		/* dma_attr_addr_hi */
80 	0x3ffff,		/* dma_attr_count_max */
81 	0x8,			/* dma_attr_align */
82 	0x7f,			/* dma_attr_burstsizes */
83 	0x1,			/* dma_attr_minxfer */
84 	0x3ffff,		/* dma_attr_maxxfer */
85 	0x3ffff,		/* dma_attr_seg */
86 	0x1,			/* dma_attr_sgllen */
87 	0x1,			/* dma_attr_granular */
88 	0			/* dma_attr_flags */
89 };
90 
91 
92 static int
93 cmpci_open(void *arg, int flag, uint_t *nframesp, caddr_t *bufp)
94 {
95 	cmpci_port_t *port = arg;
96 	cmpci_dev_t *dev = port->dev;
97 
98 	_NOTE(ARGUNUSED(flag));
99 
100 	mutex_enter(&dev->mutex);
101 
102 	*nframesp = port->nframes;
103 	*bufp = port->kaddr;
104 
105 	port->count = 0;
106 	mutex_exit(&dev->mutex);
107 
108 	return (0);
109 }
110 
111 static void
112 cmpci_close(void *arg)
113 {
114 	_NOTE(ARGUNUSED(arg));
115 }
116 
117 static int
118 cmpci_start(void *arg)
119 {
120 	cmpci_port_t	*port = arg;
121 	cmpci_dev_t	*dev = port->dev;
122 
123 	mutex_enter(&dev->mutex);
124 
125 	port->offset = 0;
126 
127 	/* reset channel */
128 	SET32(dev, REG_FUNCTRL0, port->fc0_rst_bit);
129 	drv_usecwait(10);
130 	CLR32(dev, REG_FUNCTRL0, port->fc0_rst_bit);
131 	drv_usecwait(10);
132 
133 	/* Set 48k 16-bit stereo -- these are just with all bits set. */
134 	SET32(dev, REG_FUNCTRL1, port->fc1_rate_mask);
135 	SET32(dev, REG_CHFORMAT, port->chformat_mask);
136 
137 	if ((port->num == 1) && (dev->maxch > 2)) {
138 		CLR32(dev, REG_LEGACY, LEGACY_NXCHG);
139 
140 		if (port->nchan > 2) {
141 			SET32(dev, REG_MISC, MISC_XCHGDAC);
142 			CLR32(dev, REG_MISC, MISC_N4SPK3D);
143 		} else {
144 			CLR32(dev, REG_MISC, MISC_XCHGDAC);
145 			SET32(dev, REG_MISC, MISC_N4SPK3D);
146 		}
147 
148 		switch (port->nchan) {
149 		case 2:
150 			if (dev->maxch >= 8) {
151 				CLR8(dev, REG_MISC2, MISC2_CHB3D8C);
152 			}
153 			if (dev->maxch >= 6) {
154 				CLR32(dev, REG_CHFORMAT, CHFORMAT_CHB3D5C);
155 				CLR32(dev, REG_LEGACY, LEGACY_CHB3D6C);
156 			}
157 			if (dev->maxch >= 4) {
158 				CLR32(dev, REG_CHFORMAT, CHFORMAT_CHB3D);
159 			}
160 			break;
161 		case 4:
162 			if (dev->maxch >= 8) {
163 				CLR8(dev, REG_MISC2, MISC2_CHB3D8C);
164 			}
165 			if (dev->maxch >= 6) {
166 				CLR32(dev, REG_CHFORMAT, CHFORMAT_CHB3D5C);
167 				CLR32(dev, REG_LEGACY, LEGACY_CHB3D6C);
168 				CLR32(dev, REG_MISC, MISC_ENCENTER);
169 				CLR32(dev, REG_LEGACY, LEGACY_EXBASSEN);
170 			}
171 			SET32(dev, REG_CHFORMAT, CHFORMAT_CHB3D);
172 			break;
173 		case 6:
174 			if (dev->maxch >= 8) {
175 				CLR8(dev, REG_MISC2, MISC2_CHB3D8C);
176 			}
177 			SET32(dev, REG_CHFORMAT, CHFORMAT_CHB3D5C);
178 			SET32(dev, REG_LEGACY, LEGACY_CHB3D6C);
179 			CLR32(dev, REG_MISC, MISC_ENCENTER);
180 			CLR32(dev, REG_LEGACY, LEGACY_EXBASSEN);
181 			CLR32(dev, REG_CHFORMAT, CHFORMAT_CHB3D);
182 			break;
183 
184 		case 8:
185 			SET8(dev, REG_MISC2, MISC2_CHB3D8C);
186 			CLR32(dev, REG_MISC, MISC_ENCENTER);
187 			CLR32(dev, REG_LEGACY, LEGACY_EXBASSEN);
188 			CLR32(dev, REG_CHFORMAT, CHFORMAT_CHB3D5C);
189 			CLR32(dev, REG_LEGACY, LEGACY_CHB3D6C);
190 			CLR32(dev, REG_CHFORMAT, CHFORMAT_CHB3D);
191 			break;
192 		}
193 	}
194 
195 	PUT32(dev, port->reg_paddr, port->paddr);
196 	PUT16(dev, port->reg_bufsz, (port->bufsz / 4) - 1);
197 	PUT16(dev, port->reg_fragsz, (port->bufsz  / 4) - 1);
198 
199 	/* Analog output */
200 	if (port->capture) {
201 		/* Analog capture */
202 		SET32(dev, REG_FUNCTRL0, port->fc0_rec_bit);
203 	} else {
204 		CLR32(dev, REG_FUNCTRL0, port->fc0_rec_bit);
205 	}
206 
207 	SET32(dev, REG_FUNCTRL0, port->fc0_en_bit);
208 	mutex_exit(&dev->mutex);
209 
210 	return (0);
211 }
212 
213 static void
214 cmpci_stop(void *arg)
215 {
216 	cmpci_port_t	*port = arg;
217 	cmpci_dev_t	*dev = port->dev;
218 
219 	mutex_enter(&dev->mutex);
220 	CLR32(dev, REG_FUNCTRL0, port->fc0_en_bit);
221 	mutex_exit(&dev->mutex);
222 }
223 
224 static uint64_t
225 cmpci_count(void *arg)
226 {
227 	cmpci_port_t	*port = arg;
228 	cmpci_dev_t	*dev = port->dev;
229 	uint64_t	count;
230 	uint32_t	offset;
231 
232 	mutex_enter(&dev->mutex);
233 
234 	/* this gives us the offset in dwords */
235 	offset = (port->bufsz / 4) - (GET16(dev, port->reg_bufsz) + 1);
236 
237 	/* check for wrap - note that the count is given in dwords */
238 	if (offset < port->offset) {
239 		count = ((port->bufsz / 4) - port->offset) + offset;
240 	} else {
241 		count = offset - port->offset;
242 	}
243 	port->count += count;
244 	port->offset = offset;
245 	count = port->count;
246 
247 	mutex_exit(&dev->mutex);
248 
249 	/*
250 	 * convert dwords to frames - unfortunately this requires a
251 	 * divide
252 	 */
253 	return (count / (port->nchan / 2));
254 }
255 
256 #define	MASK(nbits)	((1 << (nbits)) - 1)
257 #define	SCALE(val, nbits)	\
258 	((uint8_t)((((val) * MASK(nbits)) / 100)) << (8 - (nbits)))
259 
260 #define	LEFT(dev, ctl)	min(((dev->controls[ctl].value) >> 8), 100)
261 #define	RIGHT(dev, ctl)	min(((dev->controls[ctl].value) & 0xff), 100)
262 #define	MONO(dev, ctl)	min(dev->controls[ctl].value, 100)
263 
264 static void
265 cmpci_setmixer(cmpci_dev_t *dev, uint8_t idx, uint8_t val)
266 {
267 	PUT8(dev, REG_IDXADDR, idx);
268 	PUT8(dev, REG_IDXDATA, val);
269 }
270 
271 static uint8_t
272 cmpci_getmixer(cmpci_dev_t *dev, uint8_t idx)
273 {
274 	PUT8(dev, REG_IDXADDR, idx);
275 	return (GET8(dev, REG_IDXDATA));
276 }
277 
278 
279 static void
280 cmpci_configure_mixer(cmpci_dev_t *dev)
281 {
282 	uint64_t	left, right;
283 	uint8_t		outmix;
284 	uint8_t		inmix[2];
285 	uint64_t	recsrcs;
286 	uint64_t	monsrcs;
287 
288 	/* reset all mix values */
289 	outmix = inmix[0] = inmix[1] = 0;
290 
291 	outmix = OUTMIX_MIC |
292 	    OUTMIX_CD_R | OUTMIX_CD_L | OUTMIX_LINE_R | OUTMIX_LINE_L;
293 
294 	inmix[0] = INMIX_LINE_L | INMIX_CD_L | INMIX_MIC;
295 	inmix[1] = INMIX_LINE_R | INMIX_CD_R | INMIX_MIC;
296 
297 	recsrcs = dev->controls[CTL_RECSRCS].value;
298 	monsrcs = dev->controls[CTL_MONSRCS].value;
299 
300 	/* program PCM volume */
301 	left = MONO(dev, CTL_VOLUME);
302 	if (left) {
303 		/* left and right are the same */
304 		cmpci_setmixer(dev, IDX_VOICE_LEFT, SCALE(left, 5));
305 		cmpci_setmixer(dev, IDX_VOICE_RIGHT, SCALE(left, 5));
306 		CLR8(dev, REG_MIX2, MIX2_WSMUTE);
307 	} else {
308 		cmpci_setmixer(dev, IDX_VOICE_LEFT, 0);
309 		cmpci_setmixer(dev, IDX_VOICE_RIGHT, 0);
310 		SET8(dev, REG_MIX2, MIX2_WSMUTE);
311 	}
312 
313 	left = LEFT(dev, CTL_LINEOUT);
314 	right = RIGHT(dev, CTL_LINEOUT);
315 
316 	/* lineout/master volume - no separate mute */
317 	cmpci_setmixer(dev, IDX_MASTER_LEFT, SCALE(left, 5));
318 	cmpci_setmixer(dev, IDX_MASTER_RIGHT, SCALE(right, 5));
319 
320 	/* speaker volume - mute in extension register, but we don't use */
321 	left = MONO(dev, CTL_SPEAKER);
322 	cmpci_setmixer(dev, IDX_SPEAKER, SCALE(left, 2));
323 
324 	/* mic gain */
325 	left = MONO(dev, CTL_MIC);
326 	if (left) {
327 		cmpci_setmixer(dev, IDX_MIC, SCALE(left, 5));
328 		/* set record mic gain */
329 		uint8_t v = GET8(dev, REG_MIX3);
330 		v &= ~(0x7 << 1);
331 		v |= ((left * 7) / 100) << 1;
332 		PUT8(dev, REG_MIX3, v);
333 		cmpci_setmixer(dev, 0x3f, SCALE(100, 2));
334 		cmpci_setmixer(dev, 0x40, SCALE(100, 2));
335 	} else {
336 		cmpci_setmixer(dev, IDX_MIC, 0);
337 		outmix &= ~OUTMIX_MIC;
338 		inmix[0] &= ~INMIX_MIC;
339 		inmix[1] &= ~INMIX_MIC;
340 	}
341 
342 	/* line in */
343 	left = LEFT(dev, CTL_LINEOUT);
344 	right = RIGHT(dev, CTL_LINEOUT);
345 	if (left) {
346 		cmpci_setmixer(dev, IDX_LINEIN_LEFT, SCALE(left, 5));
347 	} else {
348 		cmpci_setmixer(dev, IDX_LINEIN_LEFT, 0);
349 		inmix[0] &= ~INMIX_LINE_L;
350 		outmix &= ~OUTMIX_LINE_L;
351 	}
352 	if (right) {
353 		cmpci_setmixer(dev, IDX_LINEIN_RIGHT, SCALE(left, 5));
354 	} else {
355 		cmpci_setmixer(dev, IDX_LINEIN_RIGHT, 0);
356 		inmix[1] &= ~INMIX_LINE_R;
357 		outmix &= ~OUTMIX_LINE_R;
358 	}
359 
360 	/* cd */
361 	left = LEFT(dev, CTL_CD);
362 	right = RIGHT(dev, CTL_CD);
363 	if (left) {
364 		cmpci_setmixer(dev, IDX_CDDA_LEFT, SCALE(left, 5));
365 	} else {
366 		cmpci_setmixer(dev, IDX_CDDA_LEFT, 0);
367 		inmix[0] &= ~INMIX_CD_L;
368 		outmix &= ~OUTMIX_CD_L;
369 	}
370 	if (right) {
371 		cmpci_setmixer(dev, IDX_CDDA_RIGHT, SCALE(left, 5));
372 	} else {
373 		cmpci_setmixer(dev, IDX_CDDA_RIGHT, 0);
374 		inmix[1] &= ~INMIX_CD_R;
375 		outmix &= ~OUTMIX_CD_R;
376 	}
377 
378 	/* aux - trickier because it doesn't use regular sbpro mixer */
379 	left = LEFT(dev, CTL_AUX);
380 	right = RIGHT(dev, CTL_AUX);
381 	PUT8(dev, REG_VAUX, (((left * 15) / 100) << 4) | ((right * 15) / 100));
382 	/* maybe enable recording */
383 	if ((left || right) && (recsrcs & (1 << SRC_LINE))) {
384 		SET8(dev, REG_MIX3, MIX3_RAUXREN | MIX3_RAUXLEN);
385 	} else {
386 		CLR8(dev, REG_MIX3, MIX3_RAUXREN | MIX3_RAUXLEN);
387 	}
388 	/* maybe enable monitoring */
389 	if ((left || right) && (monsrcs & (1 << SRC_AUX))) {
390 		CLR8(dev, REG_MIX3, MIX3_VAUXRM | MIX3_VAUXLM);
391 	} else {
392 		SET8(dev, REG_MIX3, MIX3_VAUXRM | MIX3_VAUXLM);
393 	}
394 
395 	/* now do the recsrcs */
396 	if ((recsrcs & (1 << SRC_MIC)) == 0) {
397 		inmix[0] &= ~INMIX_MIC;
398 		inmix[1] &= ~INMIX_MIC;
399 	}
400 	if ((recsrcs & (1 << SRC_LINE)) == 0) {
401 		inmix[0] &= ~INMIX_LINE_L;
402 		inmix[1] &= ~INMIX_LINE_R;
403 	}
404 	if ((recsrcs & (1 << SRC_CD)) == 0) {
405 		inmix[0] &= ~INMIX_CD_L;
406 		inmix[1] &= ~INMIX_CD_R;
407 	}
408 	if (recsrcs & (1 << SRC_MIX)) {
409 		SET8(dev, REG_MIX2, MIX2_WAVEIN_L | MIX2_WAVEIN_R);
410 	} else {
411 		CLR8(dev, REG_MIX2, MIX2_WAVEIN_L | MIX2_WAVEIN_R);
412 	}
413 	cmpci_setmixer(dev, IDX_INMIX_L, inmix[0]);
414 	cmpci_setmixer(dev, IDX_INMIX_R, inmix[1]);
415 
416 	/* now the monsrcs */
417 	if ((monsrcs & (1 << SRC_MIC)) == 0) {
418 		outmix &= ~OUTMIX_MIC;
419 	}
420 	if ((monsrcs & (1 << SRC_LINE)) == 0) {
421 		outmix &= ~(OUTMIX_LINE_L | OUTMIX_LINE_R);
422 	}
423 	if ((monsrcs & (1 << SRC_CD)) == 0) {
424 		outmix &= ~(OUTMIX_CD_L | OUTMIX_CD_R);
425 	}
426 	cmpci_setmixer(dev, IDX_OUTMIX, outmix);
427 
428 	/* micboost */
429 	if (dev->controls[CTL_MICBOOST].value != 0) {
430 		CLR8(dev, REG_MIX3, MIX3_MICGAINZ);
431 		cmpci_setmixer(dev, IDX_EXTENSION,
432 		    cmpci_getmixer(dev, IDX_EXTENSION) & ~0x1);
433 	} else {
434 		SET8(dev, REG_MIX3, MIX3_MICGAINZ);
435 		cmpci_setmixer(dev, IDX_EXTENSION,
436 		    cmpci_getmixer(dev, IDX_EXTENSION) | 0x1);
437 	}
438 }
439 
440 static int
441 cmpci_set_ctrl(void *arg, uint64_t val)
442 {
443 	cmpci_ctrl_t *cc = arg;
444 	cmpci_dev_t *dev = cc->dev;
445 
446 	/*
447 	 * We don't bother to check for valid values - a bogus value
448 	 * will give incorrect volumes, but is otherwise harmless.
449 	 */
450 	mutex_enter(&dev->mutex);
451 	cc->value = val;
452 	cmpci_configure_mixer(dev);
453 	mutex_exit(&dev->mutex);
454 
455 	return (0);
456 }
457 
458 static int
459 cmpci_get_ctrl(void *arg, uint64_t *val)
460 {
461 	cmpci_ctrl_t *cc = arg;
462 	cmpci_dev_t *dev = cc->dev;
463 
464 	mutex_enter(&dev->mutex);
465 	*val = cc->value;
466 	mutex_exit(&dev->mutex);
467 	return (0);
468 }
469 
470 #define	PLAYCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_PLAY)
471 #define	RECCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC)
472 #define	MONCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_MONITOR)
473 #define	PCMVOL	(PLAYCTL | AUDIO_CTRL_FLAG_PCMVOL)
474 #define	MAINVOL	(PLAYCTL | AUDIO_CTRL_FLAG_MAINVOL)
475 #define	RECVOL	(RECCTL | AUDIO_CTRL_FLAG_RECVOL)
476 
477 static void
478 cmpci_alloc_ctrl(cmpci_dev_t *dev, uint32_t num, uint64_t val)
479 {
480 	audio_ctrl_desc_t	desc;
481 	cmpci_ctrl_t		*cc;
482 
483 	cc = &dev->controls[num];
484 	bzero(&desc, sizeof (desc));
485 	cc->dev = dev;
486 
487 	switch (num) {
488 	case CTL_VOLUME:
489 		desc.acd_name = AUDIO_CTRL_ID_VOLUME;
490 		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
491 		desc.acd_minvalue = 0;
492 		desc.acd_maxvalue = 100;
493 		desc.acd_flags = PCMVOL;
494 		break;
495 
496 	case CTL_LINEOUT:
497 		desc.acd_name = AUDIO_CTRL_ID_LINEOUT;
498 		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
499 		desc.acd_minvalue = 0;
500 		desc.acd_maxvalue = 100;
501 		desc.acd_flags = MAINVOL;
502 		break;
503 
504 	case CTL_SPEAKER:
505 		desc.acd_name = AUDIO_CTRL_ID_SPEAKER;
506 		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
507 		desc.acd_minvalue = 0;
508 		desc.acd_maxvalue = 100;
509 		desc.acd_flags = MAINVOL;
510 		break;
511 
512 	case CTL_MIC:
513 		desc.acd_name = AUDIO_CTRL_ID_MIC;
514 		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
515 		desc.acd_minvalue = 0;
516 		desc.acd_maxvalue = 100;
517 		desc.acd_flags = RECVOL;
518 		break;
519 
520 	case CTL_LINEIN:
521 		desc.acd_name = AUDIO_CTRL_ID_LINEIN;
522 		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
523 		desc.acd_minvalue = 0;
524 		desc.acd_maxvalue = 100;
525 		desc.acd_flags = RECVOL;
526 		break;
527 
528 	case CTL_CD:
529 		desc.acd_name = AUDIO_CTRL_ID_CD;
530 		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
531 		desc.acd_minvalue = 0;
532 		desc.acd_maxvalue = 100;
533 		desc.acd_flags = RECVOL;
534 		break;
535 
536 	case CTL_AUX:
537 		desc.acd_name = AUDIO_CTRL_ID_AUX1IN;
538 		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
539 		desc.acd_minvalue = 0;
540 		desc.acd_maxvalue = 100;
541 		desc.acd_flags = RECVOL;
542 		break;
543 
544 	case CTL_RECSRCS:
545 		desc.acd_name = AUDIO_CTRL_ID_RECSRC;
546 		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
547 		desc.acd_enum[SRC_MIC] = AUDIO_PORT_MIC;
548 		desc.acd_enum[SRC_LINE] = AUDIO_PORT_LINEIN;
549 		desc.acd_enum[SRC_CD] = AUDIO_PORT_CD;
550 		desc.acd_enum[SRC_AUX] = AUDIO_PORT_AUX1IN;
551 		desc.acd_enum[SRC_MIX] = AUDIO_PORT_STEREOMIX;
552 		desc.acd_minvalue = (1 << (SRC_MIX + 1)) - 1;
553 		desc.acd_maxvalue = desc.acd_minvalue;
554 		desc.acd_flags = RECCTL | AUDIO_CTRL_FLAG_MULTI;
555 		break;
556 
557 	case CTL_MONSRCS:
558 		desc.acd_name = AUDIO_CTRL_ID_MONSRC;
559 		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
560 		desc.acd_enum[SRC_MIC] = AUDIO_PORT_MIC;
561 		desc.acd_enum[SRC_LINE] = AUDIO_PORT_LINEIN;
562 		desc.acd_enum[SRC_CD] = AUDIO_PORT_CD;
563 		desc.acd_enum[SRC_AUX] = AUDIO_PORT_AUX1IN;
564 		desc.acd_minvalue = ((1 << (SRC_AUX + 1)) - 1);
565 		desc.acd_maxvalue = desc.acd_minvalue;
566 		desc.acd_flags = MONCTL | AUDIO_CTRL_FLAG_MULTI;
567 		break;
568 
569 	case CTL_MICBOOST:
570 		desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
571 		desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
572 		desc.acd_minvalue = 0;
573 		desc.acd_maxvalue = 1;
574 		desc.acd_flags = RECCTL;
575 		break;
576 	}
577 
578 	cc->value = val;
579 	cc->ctrl = audio_dev_add_control(dev->adev, &desc,
580 	    cmpci_get_ctrl, cmpci_set_ctrl, cc);
581 }
582 
583 static void
584 cmpci_add_controls(cmpci_dev_t *dev)
585 {
586 	if (dev->softvol) {
587 		audio_dev_add_soft_volume(dev->adev);
588 	} else {
589 		cmpci_alloc_ctrl(dev, CTL_VOLUME, 75);
590 	}
591 	cmpci_alloc_ctrl(dev, CTL_LINEOUT, 90 | (90 << 8));
592 	cmpci_alloc_ctrl(dev, CTL_SPEAKER, 75);
593 	cmpci_alloc_ctrl(dev, CTL_MIC, 32);
594 	cmpci_alloc_ctrl(dev, CTL_LINEIN, 64 | (64 << 8));
595 	cmpci_alloc_ctrl(dev, CTL_CD, 75 | (75 << 8));
596 	cmpci_alloc_ctrl(dev, CTL_AUX, 75 | (75 << 8));
597 	cmpci_alloc_ctrl(dev, CTL_RECSRCS, (1 << SRC_MIC));
598 	cmpci_alloc_ctrl(dev, CTL_MONSRCS, 0);
599 	cmpci_alloc_ctrl(dev, CTL_MICBOOST, 0);
600 }
601 
602 static void
603 cmpci_del_controls(cmpci_dev_t *dev)
604 {
605 	for (int i = 0; i < CTL_NUM; i++) {
606 		if (dev->controls[i].ctrl) {
607 			audio_dev_del_control(dev->controls[i].ctrl);
608 			dev->controls[i].ctrl = NULL;
609 		}
610 	}
611 }
612 
613 static void
614 cmpci_reset(cmpci_dev_t *dev)
615 {
616 	/* Full reset */
617 	SET32(dev, REG_MISC, MISC_RESET);
618 	(void) GET32(dev, REG_MISC);
619 	drv_usecwait(100);
620 	CLR32(dev, REG_MISC, MISC_RESET);
621 
622 	/* reset all channels */
623 	PUT32(dev, REG_FUNCTRL0, 0);
624 
625 	/* disable interrupts and such */
626 	CLR32(dev, REG_FUNCTRL0, FUNCTRL0_CH0_EN | FUNCTRL0_CH1_EN);
627 	CLR32(dev, REG_INTCTRL, INTCTRL_CH0_EN | INTCTRL_CH1_EN);
628 
629 	/* disable uart, joystick in Function Control Reg1 */
630 	CLR32(dev, REG_FUNCTRL1, FUNCTRL1_UART_EN | FUNCTRL1_JYSTK_EN);
631 
632 	/*
633 	 * Set DAC and ADC rates to 48 kHz - note that both rates have
634 	 * all bits set in them, so we can do this with a simple "set".
635 	 */
636 	SET32(dev, REG_FUNCTRL1,
637 	    FUNCTRL1_DAC_RATE_48K | FUNCTRL1_ADC_RATE_48K);
638 
639 	/* Set 16-bit stereo -- also these are just with all bits set. */
640 	SET32(dev, REG_CHFORMAT, CHFORMAT_CH0_16ST | CHFORMAT_CH1_16ST);
641 }
642 
643 static int
644 cmpci_format(void *unused)
645 {
646 	_NOTE(ARGUNUSED(unused));
647 	return (AUDIO_FORMAT_S16_LE);
648 }
649 
650 static int
651 cmpci_channels(void *arg)
652 {
653 	cmpci_port_t *port = arg;
654 
655 	return (port->nchan);
656 }
657 
658 static void
659 cmpci_chinfo(void *arg, int chan, unsigned *offset, unsigned *incr)
660 {
661 	cmpci_port_t *port = arg;
662 	static const int map8ch[] = { 0, 1, 4, 5, 2, 3, 6, 7 };
663 	static const int map4ch[] = { 0, 1, 2, 3 };
664 
665 	if (port->nchan <= 4) {
666 		*offset = map4ch[chan];
667 	} else {
668 		*offset = map8ch[chan];
669 	}
670 	*incr = port->nchan;
671 }
672 
673 static int
674 cmpci_rate(void *unused)
675 {
676 	_NOTE(ARGUNUSED(unused));
677 	return (48000);
678 }
679 
680 static void
681 cmpci_sync(void *arg, unsigned nframes)
682 {
683 	cmpci_port_t *port = arg;
684 
685 	_NOTE(ARGUNUSED(nframes));
686 
687 	(void) ddi_dma_sync(port->dmah, 0, 0, port->sync_dir);
688 }
689 
690 audio_engine_ops_t cmpci_engine_ops = {
691 	AUDIO_ENGINE_VERSION,		/* version number */
692 	cmpci_open,
693 	cmpci_close,
694 	cmpci_start,
695 	cmpci_stop,
696 	cmpci_count,
697 	cmpci_format,
698 	cmpci_channels,
699 	cmpci_rate,
700 	cmpci_sync,
701 	NULL,		/* qlen */
702 	cmpci_chinfo,
703 	NULL,		/* playahead */
704 };
705 
706 static int
707 cmpci_init(cmpci_dev_t *dev)
708 {
709 	audio_dev_t	*adev = dev->adev;
710 	int		playch;
711 
712 	playch  = ddi_prop_get_int(DDI_DEV_T_ANY, dev->dip,
713 	    DDI_PROP_DONTPASS, "channels", dev->maxch);
714 
715 	if ((playch % 2) || (playch < 2) || (playch > dev->maxch)) {
716 		audio_dev_warn(adev,
717 		    "Invalid channels property (%d), resetting to %d",
718 		    playch, dev->maxch);
719 		playch = dev->maxch;
720 	}
721 
722 	for (int i = 0; i < PORT_MAX; i++) {
723 
724 		cmpci_port_t *port;
725 		unsigned dmaflags;
726 		unsigned caps;
727 		size_t rlen;
728 		ddi_dma_cookie_t c;
729 		unsigned ccnt;
730 
731 		port = &dev->port[i];
732 		port->dev = dev;
733 		port->num = i;
734 
735 		/*
736 		 * Channel 0 is recording channel, unless we are in
737 		 * dual DAC mode.  The reason for this is simple --
738 		 * only channel "B" (which I presume to mean channel
739 		 * 1) supports multichannel configuration.
740 		 *
741 		 * However, if we're going to use SPDIF recording,
742 		 * then recording *must* occur on channel 1.  Yes, the
743 		 * hardware is "strange".
744 		 */
745 
746 		switch (i) {
747 		case 0:
748 			caps = ENGINE_INPUT_CAP;
749 			dmaflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
750 			port->reg_paddr = REG_CH0_PADDR;
751 			port->reg_bufsz = REG_CH0_BUFSZ;
752 			port->reg_fragsz = REG_CH0_FRAGSZ;
753 			port->fc0_rst_bit = FUNCTRL0_CH0_RST;
754 			port->fc0_rec_bit = FUNCTRL0_CH0_REC;
755 			port->fc0_en_bit = FUNCTRL0_CH0_EN;
756 			port->sync_dir = DDI_DMA_SYNC_FORKERNEL;
757 			port->capture = B_TRUE;
758 			port->fc1_rate_mask = FUNCTRL1_ADC_RATE_48K;
759 			port->chformat_mask = CHFORMAT_CH0_16ST;
760 			port->nchan = 2;
761 			break;
762 
763 		case 1:
764 			caps = ENGINE_OUTPUT_CAP;
765 			dmaflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
766 			port->reg_paddr = REG_CH1_PADDR;
767 			port->reg_bufsz = REG_CH1_BUFSZ;
768 			port->reg_fragsz = REG_CH1_FRAGSZ;
769 			port->fc0_rst_bit = FUNCTRL0_CH1_RST;
770 			port->fc0_rec_bit = FUNCTRL0_CH1_REC;
771 			port->fc0_en_bit = FUNCTRL0_CH1_EN;
772 			port->sync_dir = DDI_DMA_SYNC_FORDEV;
773 			port->capture = B_FALSE;
774 			port->fc1_rate_mask = FUNCTRL1_DAC_RATE_48K;
775 			port->chformat_mask = CHFORMAT_CH1_16ST;
776 			port->nchan = playch;
777 			break;
778 		}
779 
780 		/*
781 		 * For efficiency, we'd like to have the fragments
782 		 * evenly divisble by 64 bytes.  Since frames are
783 		 * already evenly divisble by 4 (16-bit stereo), this
784 		 * is adequate.  For a typical configuration (175 Hz
785 		 * requested) this will translate to 166 Hz.
786 		 */
787 		port->nframes = 2048;
788 		port->bufsz = port->nframes * port->nchan * 2;
789 
790 		if (ddi_dma_alloc_handle(dev->dip, &dma_attr, DDI_DMA_DONTWAIT,
791 		    NULL, &port->dmah) != DDI_SUCCESS) {
792 			audio_dev_warn(adev, "ch%d: dma hdl alloc failed", i);
793 			return (DDI_FAILURE);
794 		}
795 		if (ddi_dma_mem_alloc(port->dmah, port->bufsz, &buf_attr,
796 		    DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, &port->kaddr,
797 		    &rlen, &port->acch) != DDI_SUCCESS) {
798 			audio_dev_warn(adev, "ch%d: dma mem allcoc failed", i);
799 			return (DDI_FAILURE);
800 		}
801 		bzero(port->kaddr, rlen);
802 
803 		if (ddi_dma_addr_bind_handle(port->dmah, NULL, port->kaddr,
804 		    rlen, dmaflags, DDI_DMA_DONTWAIT, NULL, &c, &ccnt) !=
805 		    DDI_DMA_MAPPED) {
806 			audio_dev_warn(adev, "ch%d: dma bind failed", i);
807 			return (DDI_FAILURE);
808 		}
809 		port->paddr = c.dmac_address;
810 
811 		port->engine = audio_engine_alloc(&cmpci_engine_ops, caps);
812 		if (port->engine == NULL) {
813 			audio_dev_warn(adev, "ch%d: alloc engine failed", i);
814 			return (DDI_FAILURE);
815 		}
816 		audio_engine_set_private(port->engine, port);
817 		audio_dev_add_engine(adev, port->engine);
818 	}
819 
820 	cmpci_add_controls(dev);
821 
822 	cmpci_reset(dev);
823 	cmpci_configure_mixer(dev);
824 
825 	if (audio_dev_register(adev) != DDI_SUCCESS) {
826 		audio_dev_warn(adev, "audio_dev_register failed");
827 		return (DDI_FAILURE);
828 	}
829 
830 	return (DDI_SUCCESS);
831 }
832 
833 void
834 cmpci_destroy(cmpci_dev_t *dev)
835 {
836 	mutex_destroy(&dev->mutex);
837 
838 	/* free up ports, including DMA resources for ports */
839 	for (int i = 0; i < PORT_MAX; i++) {
840 		cmpci_port_t	*port = &dev->port[i];
841 
842 		if (port->paddr != 0)
843 			(void) ddi_dma_unbind_handle(port->dmah);
844 		if (port->acch != NULL)
845 			ddi_dma_mem_free(&port->acch);
846 		if (port->dmah != NULL)
847 			ddi_dma_free_handle(&port->dmah);
848 
849 		if (port->engine != NULL) {
850 			audio_dev_remove_engine(dev->adev, port->engine);
851 			audio_engine_free(port->engine);
852 		}
853 	}
854 
855 	if (dev->acch != NULL) {
856 		ddi_regs_map_free(&dev->acch);
857 	}
858 
859 	cmpci_del_controls(dev);
860 
861 	if (dev->adev != NULL) {
862 		audio_dev_free(dev->adev);
863 	}
864 
865 	kmem_free(dev, sizeof (*dev));
866 }
867 
868 int
869 cmpci_attach(dev_info_t *dip)
870 {
871 	uint16_t		vendor, device;
872 	cmpci_dev_t		*dev;
873 	ddi_acc_handle_t	pcih;
874 	audio_dev_t		*adev;
875 	uint32_t		val;
876 
877 	if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
878 		audio_dev_warn(NULL, "pci_config_setup failed");
879 		return (DDI_FAILURE);
880 	}
881 
882 	vendor = pci_config_get16(pcih, PCI_CONF_VENID);
883 	device = pci_config_get16(pcih, PCI_CONF_DEVID);
884 
885 	if (vendor != CMEDIA_VENDOR_ID ||
886 	    ((device != CMEDIA_CM8738) && (device != CMEDIA_CM8338A) &&
887 	    (device != CMEDIA_CM8338B))) {
888 		pci_config_teardown(&pcih);
889 		audio_dev_warn(NULL, "device not recognized");
890 		return (DDI_FAILURE);
891 	}
892 
893 	/* enable IO and Master accesses */
894 	pci_config_put16(pcih, PCI_CONF_COMM,
895 	    pci_config_get16(pcih, PCI_CONF_COMM) |
896 	    PCI_COMM_MAE | PCI_COMM_IO);
897 
898 	pci_config_teardown(&pcih);
899 
900 	dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
901 	dev->dip = dip;
902 	mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, NULL);
903 
904 	ddi_set_driver_private(dip, dev);
905 
906 	if ((adev = audio_dev_alloc(dip, 0)) == NULL) {
907 		goto err_exit;
908 	}
909 	dev->adev = adev;
910 
911 	if (ddi_regs_map_setup(dip, 1, &dev->regs, 0, 0, &acc_attr,
912 	    &dev->acch) != DDI_SUCCESS) {
913 		audio_dev_warn(adev, "can't map registers");
914 		goto err_exit;
915 	}
916 
917 	/* setup some initial values */
918 	dev->maxch = 2;
919 	audio_dev_set_description(adev, "C-Media PCI Audio");
920 	switch (device) {
921 	case CMEDIA_CM8738:
922 		/*
923 		 * Crazy 8738 detection scheme.  Reviewing multiple
924 		 * different open sources gives multiple different
925 		 * answers here.  Its unclear how accurate this is.
926 		 * The approach taken here is a bit conservative in
927 		 * assigning multiple channel support, but for users
928 		 * with newer 8768 cards should offer the best
929 		 * capability.
930 		 */
931 		val = GET32(dev, REG_INTCTRL) & INTCTRL_MDL_MASK;
932 		if (val == 0) {
933 
934 			if (GET32(dev, REG_CHFORMAT & CHFORMAT_VER_MASK)) {
935 				audio_dev_set_version(adev, "CMI-8738-037");
936 				dev->maxch = 4;
937 			} else {
938 				audio_dev_set_version(adev, "CMI-8738-033");
939 			}
940 		} else if ((val & INTCTRL_MDL_068) == INTCTRL_MDL_068) {
941 			audio_dev_set_version(adev, "CMI-8768");
942 			dev->maxch = 8;
943 			dev->softvol = B_TRUE;	/* No hardware PCM volume */
944 		} else if ((val & INTCTRL_MDL_055) == INTCTRL_MDL_055) {
945 			audio_dev_set_version(adev, "CMI-8738-055");
946 			dev->maxch = 6;
947 		} else if ((val & INTCTRL_MDL_039) == INTCTRL_MDL_039) {
948 			audio_dev_set_version(adev, "CMI-8738-039");
949 			dev->maxch = 4;
950 		} else {
951 			audio_dev_set_version(adev, "CMI-8738");
952 		}
953 		break;
954 
955 	case CMEDIA_CM8338A:
956 		audio_dev_set_version(dev->adev, "CMI-8338");
957 		break;
958 
959 	case CMEDIA_CM8338B:
960 		audio_dev_set_version(dev->adev, "CMI-8338B");
961 		break;
962 	}
963 
964 	if (cmpci_init(dev) != DDI_SUCCESS) {
965 		audio_dev_warn(dev->adev, "can't init device");
966 		goto err_exit;
967 	}
968 
969 	return (DDI_SUCCESS);
970 
971 err_exit:
972 	cmpci_destroy(dev);
973 	return (DDI_FAILURE);
974 }
975 
976 static int
977 cmpci_resume(cmpci_dev_t *dev)
978 {
979 	mutex_enter(&dev->mutex);
980 	cmpci_reset(dev);
981 	/* wait one millisecond, to give reset a chance to get up */
982 	drv_usecwait(1000);
983 	mutex_exit(&dev->mutex);
984 
985 	audio_dev_resume(dev->adev);
986 
987 	return (DDI_SUCCESS);
988 }
989 
990 static int
991 cmpci_detach(cmpci_dev_t *dev)
992 {
993 	if (audio_dev_unregister(dev->adev) != DDI_SUCCESS)
994 		return (DDI_FAILURE);
995 
996 	mutex_enter(&dev->mutex);
997 
998 	/* disable channels */
999 	PUT32(dev, REG_FUNCTRL0, 0);
1000 
1001 	mutex_exit(&dev->mutex);
1002 
1003 	cmpci_destroy(dev);
1004 
1005 	return (DDI_SUCCESS);
1006 }
1007 
1008 static int
1009 cmpci_quiesce(dev_info_t *dip)
1010 {
1011 	cmpci_dev_t	*dev;
1012 
1013 	if ((dev = ddi_get_driver_private(dip)) == NULL) {
1014 		return (DDI_FAILURE);
1015 	}
1016 
1017 	/* disable channels */
1018 	PUT32(dev, REG_FUNCTRL0, 0);
1019 
1020 	return (DDI_SUCCESS);
1021 }
1022 
1023 static int
1024 cmpci_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1025 {
1026 	cmpci_dev_t *dev;
1027 
1028 	switch (cmd) {
1029 	case DDI_ATTACH:
1030 		return (cmpci_attach(dip));
1031 
1032 	case DDI_RESUME:
1033 		if ((dev = ddi_get_driver_private(dip)) == NULL) {
1034 			return (DDI_FAILURE);
1035 		}
1036 		return (cmpci_resume(dev));
1037 
1038 	default:
1039 		return (DDI_FAILURE);
1040 	}
1041 }
1042 
1043 static int
1044 cmpci_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1045 {
1046 	cmpci_dev_t *dev;
1047 
1048 	if ((dev = ddi_get_driver_private(dip)) == NULL) {
1049 		return (DDI_FAILURE);
1050 	}
1051 
1052 	switch (cmd) {
1053 	case DDI_DETACH:
1054 		return (cmpci_detach(dev));
1055 
1056 	case DDI_SUSPEND:
1057 		audio_dev_suspend(dev->adev);
1058 		return (DDI_SUCCESS);
1059 
1060 	default:
1061 		return (DDI_FAILURE);
1062 	}
1063 }
1064 
1065 static struct dev_ops cmpci_dev_ops = {
1066 	DEVO_REV,		/* rev */
1067 	0,			/* refcnt */
1068 	NULL,			/* getinfo */
1069 	nulldev,		/* identify */
1070 	nulldev,		/* probe */
1071 	cmpci_ddi_attach,	/* attach */
1072 	cmpci_ddi_detach,	/* detach */
1073 	nodev,			/* reset */
1074 	NULL,			/* cb_ops */
1075 	NULL,			/* bus_ops */
1076 	NULL,			/* power */
1077 	cmpci_quiesce,		/* quiesce */
1078 };
1079 
1080 static struct modldrv cmpci_modldrv = {
1081 	&mod_driverops,			/* drv_modops */
1082 	"C-Media PCI Audio",		/* linkinfo */
1083 	&cmpci_dev_ops,			/* dev_ops */
1084 };
1085 
1086 static struct modlinkage modlinkage = {
1087 	MODREV_1,
1088 	{ &cmpci_modldrv, NULL }
1089 };
1090 
1091 int
1092 _init(void)
1093 {
1094 	int	rv;
1095 
1096 	audio_init_ops(&cmpci_dev_ops, "audiocmi");
1097 	if ((rv = mod_install(&modlinkage)) != 0) {
1098 		audio_fini_ops(&cmpci_dev_ops);
1099 	}
1100 	return (rv);
1101 }
1102 
1103 int
1104 _fini(void)
1105 {
1106 	int	rv;
1107 	if ((rv = mod_remove(&modlinkage)) == 0) {
1108 		audio_fini_ops(&cmpci_dev_ops);
1109 	}
1110 	return (rv);
1111 }
1112 
1113 int
1114 _info(struct modinfo *modinfop)
1115 {
1116 	return (mod_info(&modlinkage, modinfop));
1117 }
1118