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 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Purpose: Driver for the CMedia 8788 sound card
29 */
30 /*
31 *
32 * Copyright (C) 4Front Technologies 1996-2011.
33 *
34 * This software is released under CDDL 1.0 source license.
35 * See the COPYING file included in the main directory of this source
36 * distribution for the license terms and conditions.
37 */
38
39 #include <sys/types.h>
40 #include <sys/modctl.h>
41 #include <sys/kmem.h>
42 #include <sys/conf.h>
43 #include <sys/ddi.h>
44 #include <sys/sunddi.h>
45 #include <sys/pci.h>
46 #include <sys/sysmacros.h>
47 #include <sys/note.h>
48 #include <sys/audio/audio_driver.h>
49 #include <sys/audio/ac97.h>
50
51 #include "audiocmihd.h"
52
53 static struct ddi_device_acc_attr dev_attr = {
54 DDI_DEVICE_ATTR_V0,
55 DDI_STRUCTURE_LE_ACC,
56 DDI_STRICTORDER_ACC
57 };
58
59 static struct ddi_device_acc_attr buf_attr = {
60 DDI_DEVICE_ATTR_V0,
61 DDI_NEVERSWAP_ACC,
62 DDI_STRICTORDER_ACC
63 };
64
65 static ddi_dma_attr_t dma_attr_buf = {
66 DMA_ATTR_V0, /* version number */
67 0x0, /* dma_attr_addr_lo */
68 0xffffffffU, /* dma_attr_addr_hi */
69 0x3ffff, /* dma_attr_count_max */
70 0x8, /* dma_attr_align */
71 0x7f, /* dma_attr_burstsizes */
72 0x1, /* dma_attr_minxfer */
73 0x3ffff, /* dma_attr_maxxfer */
74 0x3ffff, /* dma_attr_seg */
75 0x1, /* dma_attr_sgllen */
76 0x1, /* dma_attr_granular */
77 0 /* dma_attr_flags */
78 };
79
80
81 static int cmediahd_attach(dev_info_t *);
82 static int cmediahd_resume(dev_info_t *);
83 static int cmediahd_detach(cmediahd_devc_t *);
84 static int cmediahd_suspend(cmediahd_devc_t *);
85
86 static int cmediahd_open(void *, int, unsigned *, caddr_t *);
87 static void cmediahd_close(void *);
88 static int cmediahd_start(void *);
89 static void cmediahd_stop(void *);
90 static int cmediahd_format(void *);
91 static int cmediahd_channels(void *);
92 static int cmediahd_rate(void *);
93 static uint64_t cmediahd_count(void *);
94 static void cmediahd_sync(void *, unsigned);
95 static void cmediahd_chinfo(void *, int, unsigned *, unsigned *);
96
97
98 static uint16_t cmediahd_read_ac97(void *, uint8_t);
99 static void cmediahd_write_ac97(void *, uint8_t, uint16_t);
100 static int cmediahd_alloc_port(cmediahd_devc_t *, int);
101 static void cmediahd_reset_port(cmediahd_portc_t *);
102 static void cmediahd_destroy(cmediahd_devc_t *);
103 static void cmediahd_hwinit(cmediahd_devc_t *);
104 static void cmediahd_refresh_mixer(cmediahd_devc_t *devc);
105 static uint32_t mix_scale(uint32_t, int8_t);
106 static void cmediahd_ac97_hwinit(cmediahd_devc_t *);
107 static void cmediahd_del_controls(cmediahd_devc_t *);
108
109
110 static audio_engine_ops_t cmediahd_engine_ops = {
111 AUDIO_ENGINE_VERSION,
112 cmediahd_open,
113 cmediahd_close,
114 cmediahd_start,
115 cmediahd_stop,
116 cmediahd_count,
117 cmediahd_format,
118 cmediahd_channels,
119 cmediahd_rate,
120 cmediahd_sync,
121 NULL, /* qlen */
122 cmediahd_chinfo,
123 NULL /* playahead */
124 };
125
126 #define PLAYCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_PLAY)
127 #define RECCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC)
128 #define MONCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_MONITOR)
129 #define PCMVOL (PLAYCTL | AUDIO_CTRL_FLAG_PCMVOL)
130 #define MAINVOL (PLAYCTL | AUDIO_CTRL_FLAG_MAINVOL)
131 #define RECVOL (RECCTL | AUDIO_CTRL_FLAG_RECVOL)
132
133 static const char mix_cvt[101] = {
134 0, 0, 3, 7, 10, 13, 16, 19,
135 21, 23, 26, 28, 30, 32, 34, 35,
136 37, 39, 40, 42, 43, 45, 46, 47,
137 49, 50, 51, 52, 53, 55, 56, 57,
138 58, 59, 60, 61, 62, 63, 64, 65,
139 65, 66, 67, 68, 69, 70, 70, 71,
140 72, 73, 73, 74, 75, 75, 76, 77,
141 77, 78, 79, 79, 80, 81, 81, 82,
142 82, 83, 84, 84, 85, 85, 86, 86,
143 87, 87, 88, 88, 89, 89, 90, 90,
144 91, 91, 92, 92, 93, 93, 94, 94,
145 95, 95, 96, 96, 96, 97, 97, 98,
146 98, 98, 99, 99, 100
147 };
148
149 static uint32_t
mix_scale(uint32_t vol,int8_t bits)150 mix_scale(uint32_t vol, int8_t bits)
151 {
152 vol = mix_cvt[vol];
153 vol = (vol * ((1 << bits) - 1)) / 100;
154 return (vol);
155 }
156
157 static uint16_t
cmediahd_read_ac97(void * arg,uint8_t reg)158 cmediahd_read_ac97(void *arg, uint8_t reg)
159 {
160 cmediahd_devc_t *devc = arg;
161 uint32_t val;
162 uint16_t data;
163
164 mutex_enter(&devc->low_mutex);
165 val = 0L;
166 val |= reg << 16;
167 val |= 0 << 24; /* codec 0 or codec 1 */
168 val |= 1 << 23; /* ac97 read the reg address */
169 OUTL(devc, val, AC97_CMD_DATA);
170 drv_usecwait(100);
171 data = INL(devc, AC97_CMD_DATA) & 0xFFFF;
172 mutex_exit(&devc->low_mutex);
173 return (data);
174 }
175
176 static void
cmediahd_write_ac97(void * arg,uint8_t reg,uint16_t data)177 cmediahd_write_ac97(void *arg, uint8_t reg, uint16_t data)
178 {
179 cmediahd_devc_t *devc = arg;
180 uint32_t val;
181
182 mutex_enter(&devc->low_mutex);
183 val = 0L;
184 val |= reg << 16;
185 val |= data & 0xFFFF;
186 val |= 0 << 24; /* on board codec or frontpanel */
187 val |= 0 << 23; /* ac97 write operation */
188 OUTL(devc, val, AC97_CMD_DATA);
189 drv_usecwait(100);
190 mutex_exit(&devc->low_mutex);
191 }
192
193 #if 0 /* Front Panel AC'97 not supported yet */
194 static uint16_t
195 cmediahd_read_fp_ac97(void *arg, uint8_t reg)
196 {
197 cmediahd_devc_t *devc = arg;
198 uint32_t val;
199 uint16_t data;
200
201 mutex_enter(&devc->low_mutex);
202 val = 0L;
203 val |= 1 << 24; /* front panel */
204 val |= 1 << 23; /* ac97 read the reg address */
205 val |= reg << 16;
206 OUTL(devc, val, AC97_CMD_DATA);
207 drv_usecwait(100);
208 data = INL(devc, AC97_CMD_DATA) & 0xFFFF;
209 mutex_exit(&devc->low_mutex);
210
211 return (data);
212 }
213
214 static void
215 cmediahd_write_fp_ac97(void *arg, uint8_t reg, uint16_t data)
216 {
217 cmediahd_devc_t *devc = arg;
218 uint32_t val;
219
220 mutex_enter(&devc->low_mutex);
221 val = 0L;
222 val |= 1 << 24; /* frontpanel */
223 val |= 0 << 23; /* ac97 write operation */
224 val |= reg << 16;
225 val |= data & 0xFFFF;
226 OUTL(devc, val, AC97_CMD_DATA);
227 drv_usecwait(100);
228 mutex_exit(&devc->low_mutex);
229 }
230 #endif
231
232 static void
spi_write(void * arg,int codec_num,unsigned char reg,int val)233 spi_write(void *arg, int codec_num, unsigned char reg, int val)
234 {
235 cmediahd_devc_t *devc = arg;
236 unsigned int tmp;
237 int latch, shift, count;
238
239 mutex_enter(&devc->low_mutex);
240
241 /* check if SPI is busy */
242 count = 10;
243 while ((INB(devc, SPI_CONTROL) & 0x1) && count-- > 0) {
244 drv_usecwait(10);
245 }
246
247 if (devc->model == SUBID_XONAR_DS) {
248 shift = 9;
249 latch = 0;
250 } else {
251 shift = 8;
252 latch = 0x80;
253 }
254
255 /* 2 byte data/reg info to be written */
256 tmp = val;
257 tmp |= (reg << shift);
258
259 /* write 2-byte data values */
260 OUTB(devc, tmp & 0xff, SPI_DATA + 0);
261 OUTB(devc, (tmp >> 8) & 0xff, SPI_DATA + 1);
262
263 /* Latch high, clock=160, Len=2byte, mode=write */
264 tmp = (INB(devc, SPI_CONTROL) & ~0x7E) | latch | 0x1;
265
266 /* now address which codec you want to send the data to */
267 tmp |= (codec_num << 4);
268
269 /* send the command to write the data */
270 OUTB(devc, tmp, SPI_CONTROL);
271
272 mutex_exit(&devc->low_mutex);
273 }
274
275 static void
i2c_write(void * arg,unsigned char codec_num,unsigned char reg,unsigned char data)276 i2c_write(void *arg, unsigned char codec_num, unsigned char reg,
277 unsigned char data)
278 {
279 cmediahd_devc_t *devc = arg;
280 int count = 50;
281
282 /* Wait for it to stop being busy */
283 mutex_enter(&devc->low_mutex);
284 while ((INW(devc, TWO_WIRE_CTRL) & 0x1) && (count > 0)) {
285 drv_usecwait(10);
286 count--;
287 }
288
289 if (count == 0) {
290 audio_dev_warn(devc->adev, "Time out on Two-Wire interface");
291 mutex_exit(&devc->low_mutex);
292 return;
293 }
294
295 /* first write the Register Address into the MAP register */
296 OUTB(devc, reg, TWO_WIRE_MAP);
297
298 /* now write the data */
299 OUTB(devc, data, TWO_WIRE_DATA);
300
301 /* select the codec number to address */
302 OUTB(devc, codec_num, TWO_WIRE_ADDR);
303
304 mutex_exit(&devc->low_mutex);
305 }
306
307 static void
cs4398_init(void * arg,int codec)308 cs4398_init(void *arg, int codec)
309 {
310 cmediahd_devc_t *devc = arg;
311
312 /* Fast Two-Wire. Reduces the wire ready time. */
313 OUTW(devc, 0x0100, TWO_WIRE_CTRL);
314
315 /* Power down, enable control mode. */
316 i2c_write(devc, codec, CS4398_MISC_CTRL,
317 CS4398_CPEN | CS4398_POWER_DOWN);
318 /*
319 * Left justified PCM (DAC and 8788 support I2S, but doesn't work.
320 * Setting it introduces clipping like hell).
321 */
322 i2c_write(devc, codec, CS4398_MODE_CTRL, 0x00);
323 i2c_write(devc, codec, 3, 0x09);
324 i2c_write(devc, codec, 4, 0x82); /* PCM Automute */
325 i2c_write(devc, codec, 5, 0x80); /* Vol A+B to -64dB */
326 i2c_write(devc, codec, 6, 0x80);
327 i2c_write(devc, codec, 7, 0xf0); /* soft ramping on */
328
329 /* remove the powerdown flag */
330 i2c_write(devc, codec, CS4398_MISC_CTRL, CS4398_CPEN);
331 }
332
333
334 static void
cs4362a_init(void * arg,int codec)335 cs4362a_init(void *arg, int codec)
336 {
337
338 cmediahd_devc_t *devc = arg;
339
340 OUTW(devc, 0x0100, TWO_WIRE_CTRL);
341
342 /* Power down and enable control port. */
343 i2c_write(devc, codec, CS4362A_MODE1_CTRL,
344 CS4362A_CPEN | CS4362A_POWER_DOWN);
345 /* Left-justified PCM */
346 i2c_write(devc, codec, CS4362A_MODE2_CTRL, CS4362A_DIF_LJUST);
347 /* Ramp & Automute, re-set DAC defaults. */
348 i2c_write(devc, codec, CS4362A_MODE3_CTRL, 0x84);
349 /* Filter control, DAC defs. */
350 i2c_write(devc, codec, CS4362A_FILTER_CTRL, 0);
351 /* Invert control, DAC defs. */
352 i2c_write(devc, codec, CS4362A_INVERT_CTRL, 0);
353 /* Mixing control, DAC defs. */
354 i2c_write(devc, codec, CS4362A_MIX1_CTRL, 0x24);
355 i2c_write(devc, codec, CS4362A_MIX2_CTRL, 0x24);
356 i2c_write(devc, codec, CS4362A_MIX3_CTRL, 0x24);
357 /* Volume to -64dB. */
358 i2c_write(devc, codec, CS4362A_VOLA_1, 0x40);
359 i2c_write(devc, codec, CS4362A_VOLB_1, 0x40);
360 i2c_write(devc, codec, CS4362A_VOLA_2, 0x40);
361 i2c_write(devc, codec, CS4362A_VOLB_2, 0x40);
362 i2c_write(devc, codec, CS4362A_VOLA_3, 0x40);
363 i2c_write(devc, codec, CS4362A_VOLB_3, 0x40);
364 /* Power up. */
365 i2c_write(devc, codec, CS4362A_MODE1_CTRL, CS4362A_CPEN);
366 }
367
368
369 static void
cmediahd_generic_set_play_volume(cmediahd_devc_t * devc,int codec_id,int left,int right)370 cmediahd_generic_set_play_volume(cmediahd_devc_t *devc, int codec_id,
371 int left, int right)
372 {
373 spi_write(devc, codec_id, AK4396_LchATTCtl | 0x20, mix_scale(left, 8));
374 spi_write(devc, codec_id, AK4396_RchATTCtl | 0x20, mix_scale(right, 8));
375 }
376
377 static void
xonar_d1_set_play_volume(cmediahd_devc_t * devc,int codec_id,int left,int right)378 xonar_d1_set_play_volume(cmediahd_devc_t *devc, int codec_id,
379 int left, int right)
380 {
381 switch (codec_id) {
382 case 0:
383 i2c_write(devc, XONAR_DX_FRONTDAC, CS4398_VOLA,
384 CS4398_VOL(left));
385 i2c_write(devc, XONAR_DX_FRONTDAC, CS4398_VOLB,
386 CS4398_VOL(right));
387 break;
388 case 1:
389 i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_1,
390 CS4362A_VOL(left));
391 i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_1,
392 CS4362A_VOL(right));
393 break;
394 case 2:
395 i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_2,
396 CS4362A_VOL(left));
397 i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_2,
398 CS4362A_VOL(right));
399 break;
400 case 3:
401 i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_3,
402 CS4362A_VOL(left));
403 i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_3,
404 CS4362A_VOL(right));
405 break;
406 }
407 }
408
409 static void
xonar_d2_set_play_volume(cmediahd_devc_t * devc,int codec_id,int left,int right)410 xonar_d2_set_play_volume(cmediahd_devc_t *devc, int codec_id,
411 int left, int right)
412 {
413 spi_write(devc, xd2_codec_map[codec_id], 16, mix_scale(left, 8));
414 spi_write(devc, xd2_codec_map[codec_id], 17, mix_scale(right, 8));
415 }
416
417 static void
xonar_stx_set_play_volume(cmediahd_devc_t * devc,int codec_id,int left,int right)418 xonar_stx_set_play_volume(cmediahd_devc_t *devc, int codec_id,
419 int left, int right)
420 {
421 if (codec_id == 0) {
422 i2c_write(devc, XONAR_STX_FRONTDAC, 16, mix_scale(left, 8));
423 i2c_write(devc, XONAR_STX_FRONTDAC, 17, mix_scale(right, 8));
424 }
425 }
426
427 static void
xonar_ds_set_play_volume(cmediahd_devc_t * devc,int codec_id,int left,int right)428 xonar_ds_set_play_volume(cmediahd_devc_t *devc, int codec_id,
429 int left, int right)
430 {
431 switch (codec_id) {
432 case 0: /* front */
433 spi_write(devc, XONAR_DS_FRONTDAC, 0,
434 mix_scale(left, 7) | 0x180);
435 spi_write(devc, XONAR_DS_FRONTDAC, 1,
436 mix_scale(right, 7) | 0x180);
437 spi_write(devc, XONAR_DS_FRONTDAC, 3,
438 mix_scale(left, 7) |0x180);
439 spi_write(devc, XONAR_DS_FRONTDAC, 4,
440 mix_scale(right, 7) | 0x180);
441 break;
442
443 case 1: /* side */
444 spi_write(devc, XONAR_DS_SURRDAC, 0,
445 mix_scale(left, 7) | 0x180);
446 spi_write(devc, XONAR_DS_SURRDAC, 1,
447 mix_scale(right, 7) | 0x180);
448 break;
449 case 2: /* rear */
450 spi_write(devc, XONAR_DS_SURRDAC, 4,
451 mix_scale(left, 7) | 0x180);
452 spi_write(devc, XONAR_DS_SURRDAC, 5,
453 mix_scale(right, 7) | 0x180);
454 break;
455 case 3: /* center */
456 spi_write(devc, XONAR_DS_SURRDAC, 6,
457 mix_scale(left, 7) | 0x180);
458 spi_write(devc, XONAR_DS_SURRDAC, 7,
459 mix_scale(right, 7) | 0x180);
460 break;
461 }
462 }
463
464 static void
cmediahd_set_rec_volume(cmediahd_devc_t * devc,int value)465 cmediahd_set_rec_volume(cmediahd_devc_t *devc, int value)
466 {
467 unsigned char left, right;
468
469 left = (value >> 8) & 0xff;
470 right = value & 0xff;
471
472 if (left > 100)
473 left = 100;
474 if (right > 100)
475 right = 100;
476
477 spi_write(devc, XONAR_DS_FRONTDAC, 0xe, mix_scale(left, 8));
478 spi_write(devc, XONAR_DS_FRONTDAC, 0xf, mix_scale(right, 8));
479 }
480
481 static void
cmediahd_set_play_volume(cmediahd_devc_t * devc,int codec_id,int value)482 cmediahd_set_play_volume(cmediahd_devc_t *devc, int codec_id, int value)
483 {
484 int left, right;
485
486 left = (value >> 8) & 0xFF;
487 right = (value & 0xFF);
488
489 if (left > 100)
490 left = 100;
491 if (right > 100)
492 right = 100;
493
494 switch (devc->model) {
495 case SUBID_XONAR_D1:
496 case SUBID_XONAR_DX:
497 xonar_d1_set_play_volume(devc, codec_id, left, right);
498 break;
499 case SUBID_XONAR_D2:
500 case SUBID_XONAR_D2X:
501 xonar_d2_set_play_volume(devc, codec_id, left, right);
502 break;
503 case SUBID_XONAR_STX:
504 xonar_stx_set_play_volume(devc, codec_id, left, right);
505 break;
506 case SUBID_XONAR_DS:
507 xonar_ds_set_play_volume(devc, codec_id, left, right);
508 break;
509 default:
510 cmediahd_generic_set_play_volume(devc, codec_id, left, right);
511 break;
512 }
513 }
514
515 /*
516 * Audio routines
517 */
518
519 int
cmediahd_open(void * arg,int flag,unsigned * nframesp,caddr_t * bufp)520 cmediahd_open(void *arg, int flag, unsigned *nframesp, caddr_t *bufp)
521 {
522 cmediahd_portc_t *portc = arg;
523
524 _NOTE(ARGUNUSED(flag));
525
526 portc->count = 0;
527
528 *nframesp = portc->nframes;
529 *bufp = portc->kaddr;
530
531 return (0);
532 }
533
534 void
cmediahd_close(void * arg)535 cmediahd_close(void *arg)
536 {
537 _NOTE(ARGUNUSED(arg));
538 }
539
540 int
cmediahd_start(void * arg)541 cmediahd_start(void *arg)
542 {
543 cmediahd_portc_t *portc = arg;
544 cmediahd_devc_t *devc = portc->devc;
545
546 mutex_enter(&devc->mutex);
547 portc->offset = 0;
548
549 cmediahd_reset_port(portc);
550
551 switch (portc->direction) {
552 case CMEDIAHD_PLAY:
553 /* enable the dma */
554 OUTW(devc, INW(devc, DMA_START) | 0x10, DMA_START);
555 break;
556
557 case CMEDIAHD_REC:
558 /* enable the channel */
559 OUTW(devc, INW(devc, DMA_START) | (1<<devc->rec_eng.chan),
560 DMA_START);
561 break;
562 }
563
564 mutex_exit(&devc->mutex);
565 return (0);
566 }
567
568 void
cmediahd_stop(void * arg)569 cmediahd_stop(void *arg)
570 {
571 cmediahd_portc_t *portc = arg;
572 cmediahd_devc_t *devc = portc->devc;
573
574 mutex_enter(&devc->mutex);
575 switch (portc->direction) {
576 case CMEDIAHD_PLAY:
577 /* disable dma */
578 OUTW(devc, INW(devc, DMA_START) & ~0x10, DMA_START);
579 break;
580
581 case CMEDIAHD_REC:
582 /* disable dma */
583 OUTW(devc, INW(devc, DMA_START) & ~(1<<devc->rec_eng.chan),
584 DMA_START);
585 break;
586 }
587 mutex_exit(&devc->mutex);
588 }
589
590 int
cmediahd_format(void * arg)591 cmediahd_format(void *arg)
592 {
593 _NOTE(ARGUNUSED(arg));
594
595 return (AUDIO_FORMAT_S16_LE);
596 }
597
598 int
cmediahd_channels(void * arg)599 cmediahd_channels(void *arg)
600 {
601 cmediahd_portc_t *portc = arg;
602
603 return (portc->chans);
604 }
605
606 int
cmediahd_rate(void * arg)607 cmediahd_rate(void *arg)
608 {
609 _NOTE(ARGUNUSED(arg));
610
611 return (48000);
612 }
613
614 void
cmediahd_sync(void * arg,unsigned nframes)615 cmediahd_sync(void *arg, unsigned nframes)
616 {
617 cmediahd_portc_t *portc = arg;
618 _NOTE(ARGUNUSED(nframes));
619
620 (void) ddi_dma_sync(portc->buf_dmah, 0, 0, portc->syncdir);
621 }
622
623 static void
cmediahd_chinfo(void * arg,int chan,unsigned * offset,unsigned * incr)624 cmediahd_chinfo(void *arg, int chan, unsigned *offset, unsigned *incr)
625 {
626 cmediahd_portc_t *portc = arg;
627 static const int map8ch[] = { 0, 1, 4, 5, 2, 3, 6, 7 };
628 static const int map4ch[] = { 0, 1, 2, 3 };
629
630 if (portc->chans <= 4) {
631 *offset = map4ch[chan];
632 } else {
633 *offset = map8ch[chan];
634 }
635 *incr = portc->chans;
636 }
637
638 uint64_t
cmediahd_count(void * arg)639 cmediahd_count(void *arg)
640 {
641 cmediahd_portc_t *portc = arg;
642 cmediahd_devc_t *devc = portc->devc;
643 uint64_t count;
644 uint32_t offset;
645
646 mutex_enter(&devc->mutex);
647
648 if (portc->direction == CMEDIAHD_PLAY)
649 offset = portc->bufsz/4 - INL(devc, MULTICH_SIZE) + 1;
650 else
651 offset = portc->bufsz/4 - INW(devc, devc->rec_eng.size) + 1;
652
653 /* check for wrap */
654 if (offset < portc->offset) {
655 count = ((portc->bufsz/4) - portc->offset) + offset;
656 } else {
657 count = offset - portc->offset;
658 }
659 portc->count += count;
660 portc->offset = offset;
661
662 /* convert from 16-bit stereo */
663 count = portc->count / (portc->chans/2);
664 mutex_exit(&devc->mutex);
665
666 return (count);
667 }
668
669 /* private implementation bits */
670
671
672 void
cmediahd_reset_port(cmediahd_portc_t * portc)673 cmediahd_reset_port(cmediahd_portc_t *portc)
674 {
675 cmediahd_devc_t *devc = portc->devc;
676 int channels;
677
678 if (devc->suspended)
679 return;
680
681 portc->offset = 0;
682
683 switch (portc->direction) {
684
685 case CMEDIAHD_PLAY:
686 /* reset channel */
687 OUTB(devc, INB(devc, CHAN_RESET)|0x10, CHAN_RESET);
688 drv_usecwait(10);
689 OUTB(devc, INB(devc, CHAN_RESET) & ~0x10, CHAN_RESET);
690 drv_usecwait(10);
691
692 OUTL(devc, portc->paddr, MULTICH_ADDR);
693 OUTL(devc, (portc->bufsz/4) - 1, MULTICH_SIZE);
694 OUTL(devc, (portc->bufsz/4) - 1, MULTICH_FRAG);
695
696 switch (portc->chans) {
697 case 2:
698 channels = 0;
699 break;
700 case 4:
701 channels = 1;
702 break;
703 case 6:
704 channels = 2;
705 break;
706 case 8:
707 channels = 3;
708 break;
709 default:
710 channels = 0x0;
711 break;
712 }
713 OUTB(devc, (INB(devc, MULTICH_MODE) & ~0x3) | channels,
714 MULTICH_MODE);
715
716 /* set the format bits in play format register */
717 OUTB(devc, (INB(devc, PLAY_FORMAT) & ~0xC) | 0x0, PLAY_FORMAT);
718 break;
719
720 case CMEDIAHD_REC:
721 OUTB(devc, INB(devc, CHAN_RESET) | (1 << devc->rec_eng.chan),
722 CHAN_RESET);
723 drv_usecwait(10);
724 OUTB(devc, INB(devc, CHAN_RESET) & ~(1 << devc->rec_eng.chan),
725 CHAN_RESET);
726 drv_usecwait(10);
727
728 OUTL(devc, portc->paddr, devc->rec_eng.addr);
729 OUTW(devc, (portc->bufsz/4) - 1, devc->rec_eng.size);
730 OUTW(devc, (portc->bufsz/4) - 1, devc->rec_eng.frag);
731
732
733 switch (portc->chans) {
734 case 2:
735 channels = 0x0;
736 break;
737 case 4:
738 channels = 0x1;
739 break;
740 case 6:
741 channels = 0x2;
742 break;
743 case 8:
744 channels = 0x4;
745 break;
746 default:
747 /* Stereo - boomer only supports stereo */
748 channels = 0x0;
749 break;
750 }
751
752 OUTB(devc, (INB(devc, REC_MODE) & ~0x3) | channels, REC_MODE);
753 OUTB(devc, (INB(devc, REC_FORMAT) & ~0x3) | 0x0, REC_FORMAT);
754
755 }
756 }
757
758 int
cmediahd_alloc_port(cmediahd_devc_t * devc,int num)759 cmediahd_alloc_port(cmediahd_devc_t *devc, int num)
760 {
761 cmediahd_portc_t *portc;
762 size_t len;
763 ddi_dma_cookie_t cookie;
764 uint_t count;
765 int dir;
766 unsigned caps;
767 audio_dev_t *adev;
768
769 adev = devc->adev;
770 portc = kmem_zalloc(sizeof (*portc), KM_SLEEP);
771 devc->portc[num] = portc;
772 portc->devc = devc;
773 portc->direction = num;
774
775 switch (num) {
776 case CMEDIAHD_REC:
777 portc->syncdir = DDI_DMA_SYNC_FORKERNEL;
778 portc->chans = 2;
779 caps = ENGINE_INPUT_CAP;
780 dir = DDI_DMA_READ;
781 break;
782 case CMEDIAHD_PLAY:
783 portc->syncdir = DDI_DMA_SYNC_FORDEV;
784 portc->chans = 8;
785 caps = ENGINE_OUTPUT_CAP;
786 dir = DDI_DMA_WRITE;
787 break;
788 default:
789 return (DDI_FAILURE);
790 }
791
792 /*
793 * Calculate buffer size and frames
794 */
795 portc->nframes = 2048;
796 portc->bufsz = portc->nframes * portc->chans * 2;
797
798 /* Alloc buffers */
799 if (ddi_dma_alloc_handle(devc->dip, &dma_attr_buf, DDI_DMA_SLEEP, NULL,
800 &portc->buf_dmah) != DDI_SUCCESS) {
801 audio_dev_warn(adev, "failed to allocate BUF handle");
802 return (DDI_FAILURE);
803 }
804
805 if (ddi_dma_mem_alloc(portc->buf_dmah, CMEDIAHD_BUF_LEN,
806 &buf_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
807 &portc->kaddr, &len, &portc->buf_acch) != DDI_SUCCESS) {
808 audio_dev_warn(adev, "failed to allocate BUF memory");
809 return (DDI_FAILURE);
810 }
811
812 bzero(portc->kaddr, len);
813
814 if (ddi_dma_addr_bind_handle(portc->buf_dmah, NULL, portc->kaddr,
815 len, DDI_DMA_CONSISTENT | dir, DDI_DMA_SLEEP, NULL, &cookie,
816 &count) != DDI_SUCCESS) {
817 audio_dev_warn(adev, "failed binding BUF DMA handle");
818 return (DDI_FAILURE);
819 }
820 portc->paddr = cookie.dmac_address;
821
822 portc->engine = audio_engine_alloc(&cmediahd_engine_ops, caps);
823 if (portc->engine == NULL) {
824 audio_dev_warn(adev, "audio_engine_alloc failed");
825 return (DDI_FAILURE);
826 }
827
828 audio_engine_set_private(portc->engine, portc);
829 audio_dev_add_engine(adev, portc->engine);
830
831 return (DDI_SUCCESS);
832 }
833
834 void
cmediahd_destroy(cmediahd_devc_t * devc)835 cmediahd_destroy(cmediahd_devc_t *devc)
836 {
837 mutex_destroy(&devc->mutex);
838 mutex_destroy(&devc->low_mutex);
839
840 for (int i = 0; i < CMEDIAHD_NUM_PORTC; i++) {
841 cmediahd_portc_t *portc = devc->portc[i];
842 if (!portc)
843 continue;
844 if (portc->engine) {
845 audio_dev_remove_engine(devc->adev, portc->engine);
846 audio_engine_free(portc->engine);
847 }
848 if (portc->paddr) {
849 (void) ddi_dma_unbind_handle(portc->buf_dmah);
850 }
851 if (portc->buf_acch) {
852 ddi_dma_mem_free(&portc->buf_acch);
853 }
854 if (portc->buf_dmah) {
855 ddi_dma_free_handle(&portc->buf_dmah);
856 }
857 kmem_free(portc, sizeof (*portc));
858 }
859
860 if (devc->ac97) {
861 ac97_free(devc->ac97);
862 }
863
864 cmediahd_del_controls(devc);
865
866 if (devc->adev != NULL) {
867 audio_dev_free(devc->adev);
868 }
869 if (devc->regsh != NULL) {
870 ddi_regs_map_free(&devc->regsh);
871 }
872 if (devc->pcih != NULL) {
873 pci_config_teardown(&devc->pcih);
874 }
875 kmem_free(devc, sizeof (*devc));
876 }
877
878 void
cmediahd_ac97_hwinit(cmediahd_devc_t * devc)879 cmediahd_ac97_hwinit(cmediahd_devc_t *devc)
880 {
881 /* GPIO #0 programmed as output, set CMI9780 Reg0x70 */
882 cmediahd_write_ac97(devc, 0x70, 0x100);
883
884 /* LI2LI,MIC2MIC; let them always on, FOE on, ROE/BKOE/CBOE off */
885 cmediahd_write_ac97(devc, 0x62, 0x180F);
886
887 /* unmute Master Volume */
888 cmediahd_write_ac97(devc, 0x02, 0x0);
889
890 /* change PCBeep path, set Mix2FR on, option for quality issue */
891 cmediahd_write_ac97(devc, 0x64, 0x8043);
892
893 /* mute PCBeep, option for quality issues */
894 cmediahd_write_ac97(devc, 0x0A, 0x8000);
895
896 /* Record Select Control Register (Index 1Ah) */
897 cmediahd_write_ac97(devc, 0x1A, 0x0000);
898
899 /* set Mic Volume Register 0x0Eh umute and enable micboost */
900 cmediahd_write_ac97(devc, 0x0E, 0x0848);
901
902 /* set Line in Volume Register 0x10h mute */
903 cmediahd_write_ac97(devc, 0x10, 0x8808);
904
905 /* set CD Volume Register 0x12h mute */
906 cmediahd_write_ac97(devc, 0x12, 0x8808);
907
908 /* set AUX Volume Register 0x16h max */
909 cmediahd_write_ac97(devc, 0x16, 0x0808);
910
911 /* set record gain Register 0x1Ch to max */
912 cmediahd_write_ac97(devc, 0x1C, 0x0F0F);
913
914 /* GPIO status register enable GPO0 */
915 cmediahd_write_ac97(devc, 0x72, 0x0001);
916 }
917 void
cmediahd_hwinit(cmediahd_devc_t * devc)918 cmediahd_hwinit(cmediahd_devc_t *devc)
919 {
920
921 unsigned short sVal;
922 unsigned short i2s_fmt;
923 unsigned char bVal;
924 int i, count;
925
926 /* setup the default rec DMA engines to REC_A */
927 devc->rec_eng.addr = RECA_ADDR;
928 devc->rec_eng.size = RECA_SIZE;
929 devc->rec_eng.frag = RECA_FRAG;
930 devc->rec_eng.i2s = I2S_ADC1;
931 devc->rec_eng.chan = REC_A;
932
933 /* setup GPIOs to 0 */
934 devc->gpio_mic = 0;
935 devc->gpio_out = 0;
936 devc->gpio_codec = 0;
937 devc->gpio_alt = 0;
938
939 /* Init CMI Controller */
940 sVal = INW(devc, CTRL_VERSION);
941 if (!(sVal & 0x0008)) {
942 bVal = INB(devc, MISC_REG);
943 bVal |= 0x20;
944 OUTB(devc, bVal, MISC_REG);
945 }
946
947 bVal = INB(devc, FUNCTION);
948 bVal |= 0x02; /* Reset codec */
949 OUTB(devc, bVal, FUNCTION);
950
951 /* Cold reset onboard AC97 */
952 OUTW(devc, 0x1, AC97_CTRL);
953 count = 100;
954 while ((INW(devc, AC97_CTRL) & 0x2) && (count--)) {
955 OUTW(devc, (INW(devc, AC97_CTRL) & ~0x2) | 0x2, AC97_CTRL);
956 drv_usecwait(100);
957 }
958
959 if (!count)
960 audio_dev_warn(devc->adev, "CMI8788 AC97 not ready");
961
962 sVal = INW(devc, AC97_CTRL);
963 /* check if there's an onboard AC97 codec (CODEC 0) */
964 if (sVal & 0x10) {
965 /* disable CODEC0 OUTPUT */
966 OUTW(devc, INW(devc, AC97_OUT_CHAN_CONFIG) & ~0xFF00,
967 AC97_OUT_CHAN_CONFIG);
968
969 /* enable CODEC0 INPUT */
970 OUTW(devc, INW(devc, AC97_IN_CHAN_CONFIG) | 0x0300,
971 AC97_IN_CHAN_CONFIG);
972
973 devc->has_ac97 = 1;
974 }
975
976 /* check if there's an front panel AC97 codec (CODEC1) */
977 if (sVal & 0x20) {
978 /* enable CODEC1 OUTPUT */
979 OUTW(devc, INW(devc, AC97_OUT_CHAN_CONFIG) | 0x0033,
980 AC97_OUT_CHAN_CONFIG);
981 /* enable CODEC1 INPUT */
982 OUTW(devc, INW(devc, AC97_IN_CHAN_CONFIG) | 0x0033,
983 AC97_IN_CHAN_CONFIG);
984
985 devc->has_fp_ac97 = 1;
986 }
987
988 /* Disable AC97 interrupts and initialize AC97 */
989 OUTB(devc, 0x0, AC97_INTR_MASK);
990 OUTW(devc, INW(devc, IRQ_MASK) & ~0x4000, IRQ_MASK);
991
992 /* I2S to 16bit/48Khz/Master, see below. */
993 i2s_fmt = 0x011A;
994
995 /* Setup I2S to use 16bit instead of 24Bit */
996 OUTW(devc, i2s_fmt, I2S_MULTICH_DAC);
997 OUTW(devc, i2s_fmt, I2S_ADC1);
998 OUTW(devc, i2s_fmt, I2S_ADC2);
999 OUTW(devc, i2s_fmt, I2S_ADC3);
1000
1001 /* setup Routing regs (default vals) */
1002 OUTW(devc, 0xE400, PLAY_ROUTING);
1003 OUTB(devc, 0x00, REC_ROUTING); /* default routing set to I2S */
1004 OUTB(devc, 0x00, REC_MONITOR); /* monitor through MULTICH_PLAY */
1005 OUTB(devc, 0xE4, MONITOR_ROUTING); /* default monitor routing */
1006
1007
1008 /* Enable Xonar output */
1009 switch (devc->model) {
1010 case SUBID_XONAR_D1:
1011 case SUBID_XONAR_DX:
1012 /* GPIO8 = 0x100 controls mic/line-in */
1013 /* GPIO0 = 0x001controls output */
1014 /* GPIO2/3 = 0x00C codec output control */
1015
1016 devc->rec_eng.addr = RECB_ADDR;
1017 devc->rec_eng.size = RECB_SIZE;
1018 devc->rec_eng.frag = RECB_FRAG;
1019 devc->rec_eng.i2s = I2S_ADC2;
1020 devc->rec_eng.chan = REC_B;
1021
1022 /* disable AC97 mixer - not used */
1023 devc->has_ac97 = 0;
1024
1025 /* setup for 2wire communication mode */
1026 OUTB(devc, INB(devc, FUNCTION) | 0x40, FUNCTION);
1027
1028 /* setup GPIO direction */
1029 OUTW(devc, INW(devc, GPIO_CONTROL) | 0x10D, GPIO_CONTROL);
1030 /* setup GPIO pins */
1031 OUTW(devc, INW(devc, GPIO_DATA) | 0x101, GPIO_DATA);
1032
1033 /* init the front and rear dacs */
1034 cs4398_init(devc, XONAR_DX_FRONTDAC);
1035 cs4362a_init(devc, XONAR_DX_SURRDAC);
1036 break;
1037
1038 case SUBID_XONAR_D2:
1039 case SUBID_XONAR_D2X:
1040 /* GPIO7 = 0x0080 controls mic/line-in */
1041 /* GPIO8 = 0x0100 controls output */
1042 /* GPIO2/3 = 0x000C codec output control */
1043
1044 devc->rec_eng.addr = RECB_ADDR;
1045 devc->rec_eng.size = RECB_SIZE;
1046 devc->rec_eng.frag = RECB_FRAG;
1047 devc->rec_eng.i2s = I2S_ADC2;
1048 devc->rec_eng.chan = REC_B;
1049
1050 /* disable the AC97 mixer - it's not useful */
1051 devc->has_ac97 = 0;
1052
1053 /* setup for spi communication mode */
1054 OUTB(devc, (INB(devc, FUNCTION) & ~0x40) | 0x80, FUNCTION);
1055 /* setup the GPIO direction */
1056 OUTW(devc, INW(devc, GPIO_CONTROL) | 0x18c, GPIO_CONTROL);
1057
1058 /* setup GPIO Pins */
1059 OUTW(devc, INW(devc, GPIO_DATA) | 0x100, GPIO_DATA);
1060
1061 /* for all 4 codecs: unmute, set to 24Bit SPI */
1062 for (i = 0; i < 4; ++i) {
1063 /* left vol */
1064 spi_write(devc, i, 16, mix_scale(75, 8));
1065 /* right vol */
1066 spi_write(devc, i, 17, mix_scale(75, 8));
1067 /* unmute/24LSB/ATLD */
1068 spi_write(devc, i, 18, 0x30 | 0x80);
1069 }
1070 break;
1071
1072 case SUBID_XONAR_STX:
1073 devc->rec_eng.addr = RECB_ADDR;
1074 devc->rec_eng.size = RECB_SIZE;
1075 devc->rec_eng.frag = RECB_FRAG;
1076 devc->rec_eng.i2s = I2S_ADC2;
1077 devc->rec_eng.chan = REC_B;
1078
1079 /* disable the AC97 mixer - it's not useful */
1080 devc->has_ac97 = 0;
1081
1082 /* setup for spi communication mode */
1083 OUTB(devc, (INB(devc, FUNCTION) & ~0x40) | 0x80, FUNCTION);
1084 /* setup the GPIO direction */
1085 OUTW(devc, INW(devc, GPIO_CONTROL) | 0x18F, GPIO_CONTROL);
1086 /* setup GPIO Pins */
1087 OUTW(devc, INW(devc, GPIO_DATA) | 0x111, GPIO_DATA);
1088
1089 /* init front DAC */
1090 /* left vol */
1091 i2c_write(devc, XONAR_STX_FRONTDAC, 16, mix_scale(75, 8));
1092 /* right vol */
1093 i2c_write(devc, XONAR_STX_FRONTDAC, 17, mix_scale(75, 8));
1094 /* unmute/24LSB/ATLD */
1095 i2c_write(devc, XONAR_STX_FRONTDAC, 18, 0x30 | 0x80);
1096 i2c_write(devc, XONAR_STX_FRONTDAC, 19, 0); /* ATS1/FLT_SHARP */
1097 i2c_write(devc, XONAR_STX_FRONTDAC, 20, 0); /* OS_64 */
1098 i2c_write(devc, XONAR_STX_FRONTDAC, 21, 0);
1099 break;
1100
1101 case SUBID_XONAR_DS:
1102 /* GPIO 8 = 1 output enabled 0 mute */
1103 /* GPIO 7 = 1 lineout enabled 0 mute */
1104 /* GPIO 6 = 1 mic select 0 line-in select */
1105 /* GPIO 4 = 1 FP Headphone plugged in */
1106 /* GPIO 3 = 1 FP Mic plugged in */
1107
1108 devc->rec_eng.addr = RECA_ADDR;
1109 devc->rec_eng.size = RECA_SIZE;
1110 devc->rec_eng.frag = RECA_FRAG;
1111 devc->rec_eng.i2s = I2S_ADC1;
1112 devc->rec_eng.chan = REC_A;
1113
1114 /* disable the AC97 mixer - it's not useful */
1115 devc->has_ac97 = 0;
1116
1117 /* setup for spi communication mode */
1118 OUTB(devc, (INB(devc, FUNCTION) & ~0x40) | 0x80, FUNCTION);
1119 /* setup the GPIO direction */
1120 OUTW(devc, INW(devc, GPIO_CONTROL) | 0x1D0, GPIO_CONTROL);
1121 /* setup GPIO Pins */
1122 OUTW(devc, INW(devc, GPIO_DATA) | 0x1D0, GPIO_DATA);
1123 spi_write(devc, XONAR_DS_FRONTDAC, 0x17, 0x1); /* reset */
1124 spi_write(devc, XONAR_DS_FRONTDAC, 0x7, 0x90); /* dac control */
1125 spi_write(devc, XONAR_DS_FRONTDAC, 0x8, 0); /* unmute */
1126 /* powerdown hp */
1127 spi_write(devc, XONAR_DS_FRONTDAC, 0xC, 0x22);
1128 spi_write(devc, XONAR_DS_FRONTDAC, 0xD, 0x8); /* powerdown hp */
1129 spi_write(devc, XONAR_DS_FRONTDAC, 0xA, 0x1); /* LJust/16bit */
1130 spi_write(devc, XONAR_DS_FRONTDAC, 0xB, 0x1); /* LJust/16bit */
1131 spi_write(devc, XONAR_DS_SURRDAC, 0x1f, 1); /* reset */
1132 /* LJust/24bit */
1133 spi_write(devc, XONAR_DS_SURRDAC, 0x3, 0x1|0x20);
1134 break;
1135
1136
1137 default:
1138 /* SPI default for anything else, including the */
1139 OUTB(devc, (INB(devc, FUNCTION) & ~0x40) | 0x80, FUNCTION);
1140 OUTB(devc, 0x18, REC_ROUTING); /* default routing set to I2S */
1141 break;
1142 }
1143
1144 /* only initialize AC97 if not defined */
1145 if (devc->has_ac97)
1146 cmediahd_ac97_hwinit(devc);
1147 }
1148
1149 static int
cmediahd_set_control(void * arg,uint64_t val)1150 cmediahd_set_control(void *arg, uint64_t val)
1151 {
1152 cmediahd_ctrl_t *pc = arg;
1153 cmediahd_devc_t *devc = pc->devc;
1154
1155 mutex_enter(&devc->mutex);
1156
1157 pc->val = val;
1158
1159 switch (pc->num) {
1160
1161 case CTL_VOLUME:
1162 case CTL_FRONT:
1163 cmediahd_set_play_volume(devc, 0, val);
1164 break;
1165
1166 case CTL_REAR:
1167 cmediahd_set_play_volume(devc, 1, val);
1168 break;
1169
1170 case CTL_CENTER:
1171 val &= 0xff;
1172 val |= ((devc->controls[CTL_LFE].val) << 8);
1173 cmediahd_set_play_volume(devc, 2, val);
1174 break;
1175
1176 case CTL_LFE:
1177 val &= 0xff;
1178 val <<= 8;
1179 val |= (devc->controls[CTL_CENTER].val);
1180 cmediahd_set_play_volume(devc, 2, val);
1181 break;
1182
1183 case CTL_SURROUND:
1184 cmediahd_set_play_volume(devc, 3, val);
1185 break;
1186
1187 case CTL_MONITOR:
1188 /* enable recording monitor rec 1 and rec2 */
1189 if (val)
1190 OUTB(devc, INB(devc, REC_MONITOR) | 0xF, REC_MONITOR);
1191 else
1192 OUTB(devc, INB(devc, REC_MONITOR) & ~0xF, REC_MONITOR);
1193 break;
1194
1195 case CTL_RECSRC:
1196 switch (val) {
1197 case 1: /* Line */
1198 if (devc->model == SUBID_XONAR_DS)
1199 OUTW(devc, INW(devc, GPIO_DATA) & ~0x40,
1200 GPIO_DATA);
1201
1202 if (devc->model == SUBID_XONAR_D1 ||
1203 devc->model == SUBID_XONAR_DX)
1204 OUTW(devc, INW(devc, GPIO_DATA) &
1205 ~devc->gpio_mic, GPIO_DATA);
1206 cmediahd_write_ac97(devc, 0x72,
1207 cmediahd_read_ac97(devc, 0x72) & ~0x1);
1208 cmediahd_write_ac97(devc, 0x1A, 0x0404);
1209 break;
1210
1211 case 2: /* Mic */
1212 if (devc->model == SUBID_XONAR_DS)
1213 OUTW(devc, INW(devc, GPIO_DATA) | 0x40,
1214 GPIO_DATA);
1215
1216 if (devc->model == SUBID_XONAR_D1 ||
1217 devc->model == SUBID_XONAR_DX)
1218 OUTW(devc, INW(devc, GPIO_DATA) |
1219 devc->gpio_mic, GPIO_DATA);
1220 cmediahd_write_ac97(devc, 0x72,
1221 cmediahd_read_ac97(devc, 0x72) | 0x1);
1222 /* Unmute Mic */
1223 cmediahd_write_ac97(devc, 0xE,
1224 cmediahd_read_ac97(devc, 0xE) & ~0x8000);
1225 /* Mute AUX and Video */
1226 cmediahd_write_ac97(devc, 0x12,
1227 cmediahd_read_ac97(devc, 0x12) | 0x8000);
1228 cmediahd_write_ac97(devc, 0x16,
1229 cmediahd_read_ac97(devc, 0x16) | 0x8000);
1230 cmediahd_write_ac97(devc, 0x1A, 0x0000);
1231 break;
1232
1233 case 4: /* AUX */
1234 if (devc->model == SUBID_XONAR_D1 ||
1235 devc->model == SUBID_XONAR_DX)
1236 OUTW(devc, INW(devc, GPIO_DATA) |
1237 devc->gpio_mic, GPIO_DATA);
1238 cmediahd_write_ac97(devc, 0x72,
1239 cmediahd_read_ac97(devc, 0x72) | 0x1);
1240 /* Unmute AUX */
1241 cmediahd_write_ac97(devc, 0x16,
1242 cmediahd_read_ac97(devc, 0x16) & ~0x8000);
1243 /* Mute CD and Mic */
1244 cmediahd_write_ac97(devc, 0x14,
1245 cmediahd_read_ac97(devc, 0x14) | 0x8000);
1246 cmediahd_write_ac97(devc, 0x0E,
1247 cmediahd_read_ac97(devc, 0x0E) | 0x8000);
1248 cmediahd_write_ac97(devc, 0x1A, 0x0303);
1249 break;
1250
1251 case 8: /* Video (CD) */
1252 if (devc->model == SUBID_XONAR_D1 ||
1253 devc->model == SUBID_XONAR_DX)
1254 OUTW(devc, INW(devc, GPIO_DATA) |
1255 devc->gpio_mic, GPIO_DATA);
1256 cmediahd_write_ac97(devc, 0x72,
1257 cmediahd_read_ac97(devc, 0x72) | 0x1);
1258 /* Unmute Video (CD) */
1259 cmediahd_write_ac97(devc, 0x14,
1260 cmediahd_read_ac97(devc, 0x14) & ~0x8000);
1261 /* Mute AUX and Mic */
1262 cmediahd_write_ac97(devc, 0x16,
1263 cmediahd_read_ac97(devc, 0x16) | 0x8000);
1264 cmediahd_write_ac97(devc, 0x0E,
1265 cmediahd_read_ac97(devc, 0x0E) | 0x8000);
1266 /* set input to video */
1267 cmediahd_write_ac97(devc, 0x1A, 0x0202);
1268 break;
1269 }
1270 break;
1271
1272 case CTL_LOOP:
1273 if (val)
1274 OUTW(devc, INW(devc, GPIO_DATA) | devc->gpio_alt,
1275 GPIO_DATA);
1276 else
1277 OUTW(devc, (INW(devc, GPIO_DATA) & ~devc->gpio_alt),
1278 GPIO_DATA);
1279 break;
1280
1281 case CTL_SPREAD:
1282 if (val)
1283 OUTW(devc, INW(devc, PLAY_ROUTING) & 0x00FF,
1284 PLAY_ROUTING);
1285 else
1286 OUTW(devc, (INW(devc, PLAY_ROUTING) & 0x00FF) |
1287 0xE400, PLAY_ROUTING);
1288 break;
1289
1290 case CTL_RECGAIN:
1291 cmediahd_set_rec_volume(devc, val);
1292 break;
1293
1294 case CTL_MICVOL:
1295 if (val)
1296 cmediahd_write_ac97(devc, 0x0E,
1297 (0x40 | mix_scale(val, -5)) & ~0x8000);
1298 else
1299 cmediahd_write_ac97(devc, 0x0E, 0x8000);
1300 break;
1301
1302 case CTL_AUXVOL:
1303 if (val)
1304 cmediahd_write_ac97(devc, 0x16,
1305 mix_scale(val, -5) & ~0x8000);
1306 else
1307 cmediahd_write_ac97(devc, 0x16, 0x8000);
1308 break;
1309
1310
1311 case CTL_CDVOL:
1312 if (val)
1313 cmediahd_write_ac97(devc, 0x14,
1314 mix_scale(val, -5) & ~0x8000);
1315 else
1316 cmediahd_write_ac97(devc, 0x14, 0x8000);
1317 break;
1318 }
1319
1320 mutex_exit(&devc->mutex);
1321 return (0);
1322 }
1323
1324 static int
cmediahd_get_control(void * arg,uint64_t * val)1325 cmediahd_get_control(void *arg, uint64_t *val)
1326 {
1327 cmediahd_ctrl_t *pc = arg;
1328 cmediahd_devc_t *devc = pc->devc;
1329
1330 mutex_enter(&devc->mutex);
1331 *val = pc->val;
1332 mutex_exit(&devc->mutex);
1333 return (0);
1334 }
1335
1336 static void
cmediahd_alloc_ctrl(cmediahd_devc_t * devc,uint32_t num,uint64_t val)1337 cmediahd_alloc_ctrl(cmediahd_devc_t *devc, uint32_t num, uint64_t val)
1338 {
1339 audio_ctrl_desc_t desc;
1340 cmediahd_ctrl_t *pc;
1341
1342 bzero(&desc, sizeof (desc));
1343
1344 pc = &devc->controls[num];
1345 pc->num = num;
1346 pc->devc = devc;
1347
1348
1349 switch (num) {
1350
1351 case CTL_VOLUME:
1352 desc.acd_name = AUDIO_CTRL_ID_VOLUME;
1353 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1354 desc.acd_minvalue = 0;
1355 desc.acd_maxvalue = 100;
1356 desc.acd_flags = PCMVOL;
1357 break;
1358
1359 case CTL_FRONT:
1360 desc.acd_name = AUDIO_CTRL_ID_FRONT;
1361 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1362 desc.acd_minvalue = 0;
1363 desc.acd_maxvalue = 100;
1364 desc.acd_flags = PCMVOL;
1365 break;
1366
1367 case CTL_REAR:
1368 desc.acd_name = AUDIO_CTRL_ID_REAR;
1369 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1370 desc.acd_minvalue = 0;
1371 desc.acd_maxvalue = 100;
1372 desc.acd_flags = PCMVOL;
1373 break;
1374
1375 case CTL_SURROUND:
1376 desc.acd_name = AUDIO_CTRL_ID_SURROUND;
1377 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1378 desc.acd_minvalue = 0;
1379 desc.acd_maxvalue = 100;
1380 desc.acd_flags = PCMVOL;
1381 break;
1382
1383 case CTL_CENTER:
1384 desc.acd_name = AUDIO_CTRL_ID_CENTER;
1385 desc.acd_type = AUDIO_CTRL_TYPE_MONO;
1386 desc.acd_minvalue = 0;
1387 desc.acd_maxvalue = 100;
1388 desc.acd_flags = PCMVOL;
1389 break;
1390
1391 case CTL_LFE:
1392 desc.acd_name = AUDIO_CTRL_ID_LFE;
1393 desc.acd_type = AUDIO_CTRL_TYPE_MONO;
1394 desc.acd_minvalue = 0;
1395 desc.acd_maxvalue = 100;
1396 desc.acd_flags = PCMVOL;
1397 break;
1398
1399 case CTL_MONITOR:
1400 desc.acd_name = AUDIO_CTRL_ID_MONSRC;
1401 desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
1402 desc.acd_minvalue = 0;
1403 desc.acd_maxvalue = 1;
1404 desc.acd_flags = RECCTL;
1405 break;
1406
1407 case CTL_RECSRC:
1408 desc.acd_name = AUDIO_CTRL_ID_RECSRC;
1409 desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
1410 desc.acd_flags = RECCTL;
1411 desc.acd_enum[0] = AUDIO_PORT_LINEIN;
1412 desc.acd_enum[1] = AUDIO_PORT_MIC;
1413
1414 if (devc->model == SUBID_XONAR_D2 ||
1415 devc->model == SUBID_XONAR_D2X) {
1416 desc.acd_minvalue = 0xF;
1417 desc.acd_maxvalue = 0xF;
1418 desc.acd_enum[2] = AUDIO_PORT_AUX1IN;
1419 desc.acd_enum[3] = AUDIO_PORT_CD;
1420 } else {
1421 desc.acd_minvalue = 0x3;
1422 desc.acd_maxvalue = 0x3;
1423 }
1424 break;
1425
1426 case CTL_LOOP:
1427 desc.acd_name = AUDIO_CTRL_ID_LOOPBACK;
1428 desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
1429 desc.acd_minvalue = 0;
1430 desc.acd_maxvalue = 1;
1431 desc.acd_flags = RECCTL;
1432 break;
1433
1434 case CTL_SPREAD:
1435 desc.acd_name = AUDIO_CTRL_ID_SPREAD;
1436 desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
1437 desc.acd_minvalue = 0;
1438 desc.acd_maxvalue = 1;
1439 desc.acd_flags = PLAYCTL;
1440 break;
1441
1442 case CTL_RECGAIN:
1443 desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
1444 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1445 desc.acd_minvalue = 0;
1446 desc.acd_maxvalue = 100;
1447 desc.acd_flags = RECVOL;
1448 break;
1449
1450 case CTL_MICVOL:
1451 desc.acd_name = AUDIO_CTRL_ID_MIC;
1452 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1453 desc.acd_minvalue = 0;
1454 desc.acd_maxvalue = 100;
1455 desc.acd_flags = RECVOL;
1456 break;
1457
1458 case CTL_AUXVOL:
1459 desc.acd_name = AUDIO_CTRL_ID_AUX1IN;
1460 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1461 desc.acd_minvalue = 0;
1462 desc.acd_maxvalue = 100;
1463 desc.acd_flags = RECVOL;
1464 break;
1465 case CTL_CDVOL:
1466 desc.acd_name = AUDIO_CTRL_ID_CD;
1467 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1468 desc.acd_minvalue = 0;
1469 desc.acd_maxvalue = 100;
1470 desc.acd_flags = RECVOL;
1471 break;
1472
1473 }
1474
1475 pc->val = val;
1476 pc->ctrl = audio_dev_add_control(devc->adev, &desc,
1477 cmediahd_get_control, cmediahd_set_control, pc);
1478 }
1479
1480 static void
cmediahd_refresh_mixer(cmediahd_devc_t * devc)1481 cmediahd_refresh_mixer(cmediahd_devc_t *devc)
1482 {
1483 int ctl;
1484
1485 for (ctl = 0; ctl < CTL_NUM; ctl++) {
1486 if (devc->controls[ctl].ctrl == NULL)
1487 continue;
1488 (void) cmediahd_set_control(&devc->controls[ctl],
1489 devc->controls[ctl].val);
1490 }
1491 }
1492
1493 static void
cmediahd_add_controls(cmediahd_devc_t * devc)1494 cmediahd_add_controls(cmediahd_devc_t *devc)
1495 {
1496 cmediahd_alloc_ctrl(devc, CTL_VOLUME, 80 | (80 << 8));
1497 cmediahd_alloc_ctrl(devc, CTL_FRONT, 80 | (80<<8));
1498 cmediahd_alloc_ctrl(devc, CTL_REAR, 80 | (80<<8));
1499 cmediahd_alloc_ctrl(devc, CTL_CENTER, 80);
1500 cmediahd_alloc_ctrl(devc, CTL_LFE, 80);
1501 cmediahd_alloc_ctrl(devc, CTL_SURROUND, 80 | (80<<8));
1502 cmediahd_alloc_ctrl(devc, CTL_SPREAD, 0);
1503 cmediahd_alloc_ctrl(devc, CTL_MONITOR, 0);
1504 cmediahd_alloc_ctrl(devc, CTL_LOOP, 0);
1505 cmediahd_alloc_ctrl(devc, CTL_RECSRC, 2);
1506
1507 switch (devc->model) {
1508 case SUBID_XONAR_DS:
1509 cmediahd_alloc_ctrl(devc, CTL_RECGAIN, 80|80<<8);
1510 break;
1511 case SUBID_XONAR_D2:
1512 case SUBID_XONAR_D2X:
1513 cmediahd_alloc_ctrl(devc, CTL_MICVOL, 80|80<<8);
1514 cmediahd_alloc_ctrl(devc, CTL_AUXVOL, 80|80<<8);
1515 cmediahd_alloc_ctrl(devc, CTL_CDVOL, 80|80<<8);
1516 break;
1517 }
1518
1519 cmediahd_refresh_mixer(devc);
1520 }
1521
1522 void
cmediahd_del_controls(cmediahd_devc_t * dev)1523 cmediahd_del_controls(cmediahd_devc_t *dev)
1524 {
1525 for (int i = 0; i < CTL_NUM; i++) {
1526 if (dev->controls[i].ctrl) {
1527 audio_dev_del_control(dev->controls[i].ctrl);
1528 dev->controls[i].ctrl = NULL;
1529 }
1530 }
1531 }
1532
1533 int
cmediahd_attach(dev_info_t * dip)1534 cmediahd_attach(dev_info_t *dip)
1535 {
1536 uint16_t pci_command, vendor, device, subvendor, subdevice;
1537 cmediahd_devc_t *devc;
1538 ddi_acc_handle_t pcih;
1539
1540 devc = kmem_zalloc(sizeof (*devc), KM_SLEEP);
1541 devc->dip = dip;
1542 ddi_set_driver_private(dip, devc);
1543
1544 mutex_init(&devc->mutex, NULL, MUTEX_DRIVER, NULL);
1545 mutex_init(&devc->low_mutex, NULL, MUTEX_DRIVER, NULL);
1546
1547 if ((devc->adev = audio_dev_alloc(dip, 0)) == NULL) {
1548 cmn_err(CE_WARN, "audio_dev_alloc failed");
1549 goto error;
1550 }
1551
1552 if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
1553 audio_dev_warn(devc->adev, "pci_config_setup failed");
1554 goto error;
1555 }
1556 devc->pcih = pcih;
1557
1558 vendor = pci_config_get16(pcih, PCI_CONF_VENID);
1559 device = pci_config_get16(pcih, PCI_CONF_DEVID);
1560 subvendor = pci_config_get16(pcih, PCI_CONF_SUBVENID);
1561 subdevice = pci_config_get16(pcih, PCI_CONF_SUBSYSID);
1562 if (vendor != PCI_VENDOR_ID_CMEDIA ||
1563 device != PCI_DEVICE_ID_CMEDIAHD) {
1564 audio_dev_warn(devc->adev, "Hardware not recognized "
1565 "(vendor=%x, dev=%x)", vendor, device);
1566 goto error;
1567 }
1568
1569
1570 pci_command = pci_config_get16(pcih, PCI_CONF_COMM);
1571 pci_command |= PCI_COMM_ME | PCI_COMM_IO;
1572 pci_config_put16(pcih, PCI_CONF_COMM, pci_command);
1573
1574 if ((ddi_regs_map_setup(dip, 1, &devc->base, 0, 0, &dev_attr,
1575 &devc->regsh)) != DDI_SUCCESS) {
1576 audio_dev_warn(devc->adev, "failed to map registers");
1577 goto error;
1578 }
1579
1580 audio_dev_set_description(devc->adev, "CMedia 8788");
1581
1582 /* Detect Xonar device */
1583 if (subvendor == ASUS_VENDOR_ID) {
1584 switch (subdevice) {
1585 case SUBID_XONAR_D1:
1586 audio_dev_set_description(devc->adev,
1587 "Asus Xonar D1 (AV100)");
1588 break;
1589 case SUBID_XONAR_DX:
1590 audio_dev_set_description(devc->adev,
1591 "Asus Xonar DX (AV100)");
1592 break;
1593 case SUBID_XONAR_D2:
1594 audio_dev_set_description(devc->adev,
1595 "Asus Xonar D2 (AV200)");
1596 break;
1597 case SUBID_XONAR_D2X:
1598 audio_dev_set_description(devc->adev,
1599 "Asus Xonar D2X (AV200)");
1600 break;
1601 case SUBID_XONAR_STX:
1602 audio_dev_set_description(devc->adev,
1603 "Asus Xonar STX (AV100)");
1604 break;
1605 case SUBID_XONAR_DS:
1606 audio_dev_set_description(devc->adev,
1607 "Asus Xonar DS (AV66)");
1608 break;
1609 default:
1610 audio_dev_set_description(devc->adev,
1611 "Asus Xonar Unknown Model");
1612 subdevice = SUBID_GENERIC;
1613 break;
1614 }
1615 devc->model = subdevice;
1616 }
1617
1618 cmediahd_hwinit(devc);
1619
1620 if (cmediahd_alloc_port(devc, CMEDIAHD_PLAY) != DDI_SUCCESS)
1621 goto error;
1622 if (cmediahd_alloc_port(devc, CMEDIAHD_REC) != DDI_SUCCESS)
1623 goto error;
1624
1625 /* Add the AC97 Mixer if there is an onboard AC97 device */
1626 if (devc->has_ac97) {
1627 devc->ac97 = ac97_alloc(dip, cmediahd_read_ac97,
1628 cmediahd_write_ac97, devc);
1629 if (ac97_init(devc->ac97, devc->adev) != DDI_SUCCESS) {
1630 audio_dev_warn(devc->adev, "failed to init ac97");
1631 goto error;
1632 }
1633 }
1634 #if 0
1635 /* Add the front panel AC97 device if one exists */
1636 if (devc->has_fp_ac97) {
1637 devc->fp_ac97 = ac97_alloc(dip, cmediahd_read_fp_ac97,
1638 cmediahd_write_fp_ac97, devc);
1639 if (ac97_init(devc->fp_ac97, devc->adev) != DDI_SUCCESS) {
1640 audio_dev_warn(devc->adev, "failed to init fp_ac97");
1641 goto error;
1642 }
1643 }
1644 #endif
1645 /* Add the standard CMI8788 Mixer panel */
1646 cmediahd_add_controls(devc);
1647
1648 if (audio_dev_register(devc->adev) != DDI_SUCCESS) {
1649 audio_dev_warn(devc->adev, "unable to register with framework");
1650 goto error;
1651 }
1652
1653 ddi_report_dev(dip);
1654
1655 return (DDI_SUCCESS);
1656
1657 error:
1658 cmediahd_destroy(devc);
1659 return (DDI_FAILURE);
1660 }
1661
1662 int
cmediahd_resume(dev_info_t * dip)1663 cmediahd_resume(dev_info_t *dip)
1664 {
1665 cmediahd_devc_t *devc;
1666
1667 devc = ddi_get_driver_private(dip);
1668
1669 cmediahd_hwinit(devc);
1670
1671 if (devc->ac97)
1672 ac97_reset(devc->ac97);
1673
1674 cmediahd_refresh_mixer(devc);
1675
1676 audio_dev_resume(devc->adev);
1677
1678 return (DDI_SUCCESS);
1679 }
1680
1681 int
cmediahd_detach(cmediahd_devc_t * devc)1682 cmediahd_detach(cmediahd_devc_t *devc)
1683 {
1684 if (audio_dev_unregister(devc->adev) != DDI_SUCCESS)
1685 return (DDI_FAILURE);
1686
1687 cmediahd_destroy(devc);
1688 return (DDI_SUCCESS);
1689 }
1690
1691 int
cmediahd_suspend(cmediahd_devc_t * devc)1692 cmediahd_suspend(cmediahd_devc_t *devc)
1693 {
1694 audio_dev_suspend(devc->adev);
1695 return (DDI_SUCCESS);
1696 }
1697
1698 static int cmediahd_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
1699 static int cmediahd_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
1700 static int cmediahd_ddi_quiesce(dev_info_t *);
1701
1702 static struct dev_ops cmediahd_dev_ops = {
1703 DEVO_REV, /* rev */
1704 0, /* refcnt */
1705 NULL, /* getinfo */
1706 nulldev, /* identify */
1707 nulldev, /* probe */
1708 cmediahd_ddi_attach, /* attach */
1709 cmediahd_ddi_detach, /* detach */
1710 nodev, /* reset */
1711 NULL, /* cb_ops */
1712 NULL, /* bus_ops */
1713 NULL, /* power */
1714 cmediahd_ddi_quiesce, /* quiesce */
1715 };
1716
1717 static struct modldrv cmediahd_modldrv = {
1718 &mod_driverops, /* drv_modops */
1719 "CMedia 8788", /* linkinfo */
1720 &cmediahd_dev_ops, /* dev_ops */
1721 };
1722
1723 static struct modlinkage modlinkage = {
1724 MODREV_1,
1725 { &cmediahd_modldrv, NULL }
1726 };
1727
1728 int
_init(void)1729 _init(void)
1730 {
1731 int rv;
1732
1733 audio_init_ops(&cmediahd_dev_ops, CMEDIAHD_NAME);
1734 if ((rv = mod_install(&modlinkage)) != 0) {
1735 audio_fini_ops(&cmediahd_dev_ops);
1736 }
1737 return (rv);
1738 }
1739
1740 int
_fini(void)1741 _fini(void)
1742 {
1743 int rv;
1744
1745 if ((rv = mod_remove(&modlinkage)) == 0) {
1746 audio_fini_ops(&cmediahd_dev_ops);
1747 }
1748 return (rv);
1749 }
1750
1751 int
_info(struct modinfo * modinfop)1752 _info(struct modinfo *modinfop)
1753 {
1754 return (mod_info(&modlinkage, modinfop));
1755 }
1756
1757 int
cmediahd_ddi_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)1758 cmediahd_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1759 {
1760 switch (cmd) {
1761 case DDI_ATTACH:
1762 return (cmediahd_attach(dip));
1763
1764 case DDI_RESUME:
1765 return (cmediahd_resume(dip));
1766
1767 default:
1768 return (DDI_FAILURE);
1769 }
1770 }
1771
1772 int
cmediahd_ddi_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)1773 cmediahd_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1774 {
1775 cmediahd_devc_t *devc;
1776
1777 devc = ddi_get_driver_private(dip);
1778
1779 switch (cmd) {
1780 case DDI_DETACH:
1781 return (cmediahd_detach(devc));
1782
1783 case DDI_SUSPEND:
1784 return (cmediahd_suspend(devc));
1785
1786 default:
1787 return (DDI_FAILURE);
1788 }
1789 }
1790
1791 int
cmediahd_ddi_quiesce(dev_info_t * dip)1792 cmediahd_ddi_quiesce(dev_info_t *dip)
1793 {
1794 cmediahd_devc_t *devc;
1795
1796 devc = ddi_get_driver_private(dip);
1797
1798 OUTW(devc, 0x0, DMA_START);
1799
1800 /*
1801 * Turn off the hardware
1802 */
1803
1804
1805 return (DDI_SUCCESS);
1806 }
1807