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 {
374 spi_write(devc, codec_id, AK4396_LchATTCtl | 0x20, mix_scale(left, 8));
375 spi_write(devc, codec_id, AK4396_RchATTCtl | 0x20, mix_scale(right, 8));
376 }
377
378 static void
xonar_d1_set_play_volume(cmediahd_devc_t * devc,int codec_id,int left,int right)379 xonar_d1_set_play_volume(cmediahd_devc_t *devc, int codec_id,
380 int left, int right)
381 {
382 switch (codec_id) {
383 case 0:
384 i2c_write(devc, XONAR_DX_FRONTDAC, CS4398_VOLA,
385 CS4398_VOL(left));
386 i2c_write(devc, XONAR_DX_FRONTDAC, CS4398_VOLB,
387 CS4398_VOL(right));
388 break;
389 case 1:
390 i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_1,
391 CS4362A_VOL(left));
392 i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_1,
393 CS4362A_VOL(right));
394 break;
395 case 2:
396 i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_2,
397 CS4362A_VOL(left));
398 i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_2,
399 CS4362A_VOL(right));
400 break;
401 case 3:
402 i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_3,
403 CS4362A_VOL(left));
404 i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_3,
405 CS4362A_VOL(right));
406 break;
407 }
408 }
409
410 static void
xonar_d2_set_play_volume(cmediahd_devc_t * devc,int codec_id,int left,int right)411 xonar_d2_set_play_volume(cmediahd_devc_t *devc, int codec_id,
412 int left, int right)
413 {
414 spi_write(devc, xd2_codec_map[codec_id], 16, mix_scale(left, 8));
415 spi_write(devc, xd2_codec_map[codec_id], 17, mix_scale(right, 8));
416 }
417
418 static void
xonar_stx_set_play_volume(cmediahd_devc_t * devc,int codec_id,int left,int right)419 xonar_stx_set_play_volume(cmediahd_devc_t *devc, int codec_id,
420 int left, int right)
421 {
422 if (codec_id == 0) {
423 i2c_write(devc, XONAR_STX_FRONTDAC, 16, mix_scale(left, 8));
424 i2c_write(devc, XONAR_STX_FRONTDAC, 17, mix_scale(right, 8));
425 }
426 }
427
428 static void
xonar_ds_set_play_volume(cmediahd_devc_t * devc,int codec_id,int left,int right)429 xonar_ds_set_play_volume(cmediahd_devc_t *devc, int codec_id,
430 int left, int right)
431 {
432 switch (codec_id) {
433 case 0: /* front */
434 spi_write(devc, XONAR_DS_FRONTDAC, 0,
435 mix_scale(left, 7) | 0x180);
436 spi_write(devc, XONAR_DS_FRONTDAC, 1,
437 mix_scale(right, 7) | 0x180);
438 spi_write(devc, XONAR_DS_FRONTDAC, 3,
439 mix_scale(left, 7) |0x180);
440 spi_write(devc, XONAR_DS_FRONTDAC, 4,
441 mix_scale(right, 7) | 0x180);
442 break;
443
444 case 1: /* side */
445 spi_write(devc, XONAR_DS_SURRDAC, 0,
446 mix_scale(left, 7) | 0x180);
447 spi_write(devc, XONAR_DS_SURRDAC, 1,
448 mix_scale(right, 7) | 0x180);
449 break;
450 case 2: /* rear */
451 spi_write(devc, XONAR_DS_SURRDAC, 4,
452 mix_scale(left, 7) | 0x180);
453 spi_write(devc, XONAR_DS_SURRDAC, 5,
454 mix_scale(right, 7) | 0x180);
455 break;
456 case 3: /* center */
457 spi_write(devc, XONAR_DS_SURRDAC, 6,
458 mix_scale(left, 7) | 0x180);
459 spi_write(devc, XONAR_DS_SURRDAC, 7,
460 mix_scale(right, 7) | 0x180);
461 break;
462 }
463 }
464
465 static void
cmediahd_set_rec_volume(cmediahd_devc_t * devc,int value)466 cmediahd_set_rec_volume(cmediahd_devc_t *devc, int value)
467 {
468 unsigned char left, right;
469
470 left = (value >> 8) & 0xff;
471 right = value & 0xff;
472
473 if (left > 100)
474 left = 100;
475 if (right > 100)
476 right = 100;
477
478 spi_write(devc, XONAR_DS_FRONTDAC, 0xe, mix_scale(left, 8));
479 spi_write(devc, XONAR_DS_FRONTDAC, 0xf, mix_scale(right, 8));
480 }
481
482 static void
cmediahd_set_play_volume(cmediahd_devc_t * devc,int codec_id,int value)483 cmediahd_set_play_volume(cmediahd_devc_t *devc, int codec_id, int value)
484 {
485 int left, right;
486
487 left = (value >> 8) & 0xFF;
488 right = (value & 0xFF);
489
490 if (left > 100)
491 left = 100;
492 if (right > 100)
493 right = 100;
494
495 switch (devc->model) {
496 case SUBID_XONAR_D1:
497 case SUBID_XONAR_DX:
498 xonar_d1_set_play_volume(devc, codec_id, left, right);
499 break;
500 case SUBID_XONAR_D2:
501 case SUBID_XONAR_D2X:
502 xonar_d2_set_play_volume(devc, codec_id, left, right);
503 break;
504 case SUBID_XONAR_STX:
505 xonar_stx_set_play_volume(devc, codec_id, left, right);
506 break;
507 case SUBID_XONAR_DS:
508 xonar_ds_set_play_volume(devc, codec_id, left, right);
509 break;
510 default:
511 cmediahd_generic_set_play_volume(devc, codec_id, left, right);
512 break;
513 }
514 }
515
516 /*
517 * Audio routines
518 */
519
520 int
cmediahd_open(void * arg,int flag,unsigned * nframesp,caddr_t * bufp)521 cmediahd_open(void *arg, int flag, unsigned *nframesp, caddr_t *bufp)
522 {
523 cmediahd_portc_t *portc = arg;
524
525 _NOTE(ARGUNUSED(flag));
526
527 portc->count = 0;
528
529 *nframesp = portc->nframes;
530 *bufp = portc->kaddr;
531
532 return (0);
533 }
534
535 void
cmediahd_close(void * arg)536 cmediahd_close(void *arg)
537 {
538 _NOTE(ARGUNUSED(arg));
539 }
540
541 int
cmediahd_start(void * arg)542 cmediahd_start(void *arg)
543 {
544 cmediahd_portc_t *portc = arg;
545 cmediahd_devc_t *devc = portc->devc;
546
547 mutex_enter(&devc->mutex);
548 portc->offset = 0;
549
550 cmediahd_reset_port(portc);
551
552 switch (portc->direction) {
553 case CMEDIAHD_PLAY:
554 /* enable the dma */
555 OUTW(devc, INW(devc, DMA_START) | 0x10, DMA_START);
556 break;
557
558 case CMEDIAHD_REC:
559 /* enable the channel */
560 OUTW(devc, INW(devc, DMA_START) | (1<<devc->rec_eng.chan),
561 DMA_START);
562 break;
563 }
564
565 mutex_exit(&devc->mutex);
566 return (0);
567 }
568
569 void
cmediahd_stop(void * arg)570 cmediahd_stop(void *arg)
571 {
572 cmediahd_portc_t *portc = arg;
573 cmediahd_devc_t *devc = portc->devc;
574
575 mutex_enter(&devc->mutex);
576 switch (portc->direction) {
577 case CMEDIAHD_PLAY:
578 /* disable dma */
579 OUTW(devc, INW(devc, DMA_START) & ~0x10, DMA_START);
580 break;
581
582 case CMEDIAHD_REC:
583 /* disable dma */
584 OUTW(devc, INW(devc, DMA_START) & ~(1<<devc->rec_eng.chan),
585 DMA_START);
586 break;
587 }
588 mutex_exit(&devc->mutex);
589 }
590
591 int
cmediahd_format(void * arg)592 cmediahd_format(void *arg)
593 {
594 _NOTE(ARGUNUSED(arg));
595
596 return (AUDIO_FORMAT_S16_LE);
597 }
598
599 int
cmediahd_channels(void * arg)600 cmediahd_channels(void *arg)
601 {
602 cmediahd_portc_t *portc = arg;
603
604 return (portc->chans);
605 }
606
607 int
cmediahd_rate(void * arg)608 cmediahd_rate(void *arg)
609 {
610 _NOTE(ARGUNUSED(arg));
611
612 return (48000);
613 }
614
615 void
cmediahd_sync(void * arg,unsigned nframes)616 cmediahd_sync(void *arg, unsigned nframes)
617 {
618 cmediahd_portc_t *portc = arg;
619 _NOTE(ARGUNUSED(nframes));
620
621 (void) ddi_dma_sync(portc->buf_dmah, 0, 0, portc->syncdir);
622 }
623
624 static void
cmediahd_chinfo(void * arg,int chan,unsigned * offset,unsigned * incr)625 cmediahd_chinfo(void *arg, int chan, unsigned *offset, unsigned *incr)
626 {
627 cmediahd_portc_t *portc = arg;
628 static const int map8ch[] = { 0, 1, 4, 5, 2, 3, 6, 7 };
629 static const int map4ch[] = { 0, 1, 2, 3 };
630
631 if (portc->chans <= 4) {
632 *offset = map4ch[chan];
633 } else {
634 *offset = map8ch[chan];
635 }
636 *incr = portc->chans;
637 }
638
639 uint64_t
cmediahd_count(void * arg)640 cmediahd_count(void *arg)
641 {
642 cmediahd_portc_t *portc = arg;
643 cmediahd_devc_t *devc = portc->devc;
644 uint64_t count;
645 uint32_t offset;
646
647 mutex_enter(&devc->mutex);
648
649 if (portc->direction == CMEDIAHD_PLAY)
650 offset = portc->bufsz/4 - INL(devc, MULTICH_SIZE) + 1;
651 else
652 offset = portc->bufsz/4 - INW(devc, devc->rec_eng.size) + 1;
653
654 /* check for wrap */
655 if (offset < portc->offset) {
656 count = ((portc->bufsz/4) - portc->offset) + offset;
657 } else {
658 count = offset - portc->offset;
659 }
660 portc->count += count;
661 portc->offset = offset;
662
663 /* convert from 16-bit stereo */
664 count = portc->count / (portc->chans/2);
665 mutex_exit(&devc->mutex);
666
667 return (count);
668 }
669
670 /* private implementation bits */
671
672
673 void
cmediahd_reset_port(cmediahd_portc_t * portc)674 cmediahd_reset_port(cmediahd_portc_t *portc)
675 {
676 cmediahd_devc_t *devc = portc->devc;
677 int channels;
678
679 if (devc->suspended)
680 return;
681
682 portc->offset = 0;
683
684 switch (portc->direction) {
685
686 case CMEDIAHD_PLAY:
687 /* reset channel */
688 OUTB(devc, INB(devc, CHAN_RESET)|0x10, CHAN_RESET);
689 drv_usecwait(10);
690 OUTB(devc, INB(devc, CHAN_RESET) & ~0x10, CHAN_RESET);
691 drv_usecwait(10);
692
693 OUTL(devc, portc->paddr, MULTICH_ADDR);
694 OUTL(devc, (portc->bufsz/4) - 1, MULTICH_SIZE);
695 OUTL(devc, (portc->bufsz/4) - 1, MULTICH_FRAG);
696
697 switch (portc->chans) {
698 case 2:
699 channels = 0;
700 break;
701 case 4:
702 channels = 1;
703 break;
704 case 6:
705 channels = 2;
706 break;
707 case 8:
708 channels = 3;
709 break;
710 }
711 OUTB(devc, (INB(devc, MULTICH_MODE) & ~0x3) | channels,
712 MULTICH_MODE);
713
714 /* set the format bits in play format register */
715 OUTB(devc, (INB(devc, PLAY_FORMAT) & ~0xC) | 0x0, PLAY_FORMAT);
716 break;
717
718 case CMEDIAHD_REC:
719 OUTB(devc, INB(devc, CHAN_RESET) | (1 << devc->rec_eng.chan),
720 CHAN_RESET);
721 drv_usecwait(10);
722 OUTB(devc, INB(devc, CHAN_RESET) & ~(1 << devc->rec_eng.chan),
723 CHAN_RESET);
724 drv_usecwait(10);
725
726 OUTL(devc, portc->paddr, devc->rec_eng.addr);
727 OUTW(devc, (portc->bufsz/4) - 1, devc->rec_eng.size);
728 OUTW(devc, (portc->bufsz/4) - 1, devc->rec_eng.frag);
729
730
731 switch (portc->chans) {
732 case 2:
733 channels = 0x0;
734 break;
735 case 4:
736 channels = 0x1;
737 break;
738 case 6:
739 channels = 0x2;
740 break;
741 case 8:
742 channels = 0x4;
743 break;
744 default:
745 /* Stereo - boomer only supports stereo */
746 channels = 0x0;
747 break;
748 }
749
750 OUTB(devc, (INB(devc, REC_MODE) & ~0x3) | channels, REC_MODE);
751 OUTB(devc, (INB(devc, REC_FORMAT) & ~0x3) | 0x0, REC_FORMAT);
752
753 }
754 }
755
756 int
cmediahd_alloc_port(cmediahd_devc_t * devc,int num)757 cmediahd_alloc_port(cmediahd_devc_t *devc, int num)
758 {
759 cmediahd_portc_t *portc;
760 size_t len;
761 ddi_dma_cookie_t cookie;
762 uint_t count;
763 int dir;
764 unsigned caps;
765 audio_dev_t *adev;
766
767 adev = devc->adev;
768 portc = kmem_zalloc(sizeof (*portc), KM_SLEEP);
769 devc->portc[num] = portc;
770 portc->devc = devc;
771 portc->direction = num;
772
773 switch (num) {
774 case CMEDIAHD_REC:
775 portc->syncdir = DDI_DMA_SYNC_FORKERNEL;
776 portc->chans = 2;
777 caps = ENGINE_INPUT_CAP;
778 dir = DDI_DMA_READ;
779 break;
780 case CMEDIAHD_PLAY:
781 portc->syncdir = DDI_DMA_SYNC_FORDEV;
782 portc->chans = 8;
783 caps = ENGINE_OUTPUT_CAP;
784 dir = DDI_DMA_WRITE;
785 break;
786 default:
787 return (DDI_FAILURE);
788 }
789
790 /*
791 * Calculate buffer size and frames
792 */
793 portc->nframes = 2048;
794 portc->bufsz = portc->nframes * portc->chans * 2;
795
796 /* Alloc buffers */
797 if (ddi_dma_alloc_handle(devc->dip, &dma_attr_buf, DDI_DMA_SLEEP, NULL,
798 &portc->buf_dmah) != DDI_SUCCESS) {
799 audio_dev_warn(adev, "failed to allocate BUF handle");
800 return (DDI_FAILURE);
801 }
802
803 if (ddi_dma_mem_alloc(portc->buf_dmah, CMEDIAHD_BUF_LEN,
804 &buf_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
805 &portc->kaddr, &len, &portc->buf_acch) != DDI_SUCCESS) {
806 audio_dev_warn(adev, "failed to allocate BUF memory");
807 return (DDI_FAILURE);
808 }
809
810 bzero(portc->kaddr, len);
811
812 if (ddi_dma_addr_bind_handle(portc->buf_dmah, NULL, portc->kaddr,
813 len, DDI_DMA_CONSISTENT | dir, DDI_DMA_SLEEP, NULL, &cookie,
814 &count) != DDI_SUCCESS) {
815 audio_dev_warn(adev, "failed binding BUF DMA handle");
816 return (DDI_FAILURE);
817 }
818 portc->paddr = cookie.dmac_address;
819
820 portc->engine = audio_engine_alloc(&cmediahd_engine_ops, caps);
821 if (portc->engine == NULL) {
822 audio_dev_warn(adev, "audio_engine_alloc failed");
823 return (DDI_FAILURE);
824 }
825
826 audio_engine_set_private(portc->engine, portc);
827 audio_dev_add_engine(adev, portc->engine);
828
829 return (DDI_SUCCESS);
830 }
831
832 void
cmediahd_destroy(cmediahd_devc_t * devc)833 cmediahd_destroy(cmediahd_devc_t *devc)
834 {
835 mutex_destroy(&devc->mutex);
836 mutex_destroy(&devc->low_mutex);
837
838 for (int i = 0; i < CMEDIAHD_NUM_PORTC; i++) {
839 cmediahd_portc_t *portc = devc->portc[i];
840 if (!portc)
841 continue;
842 if (portc->engine) {
843 audio_dev_remove_engine(devc->adev, portc->engine);
844 audio_engine_free(portc->engine);
845 }
846 if (portc->paddr) {
847 (void) ddi_dma_unbind_handle(portc->buf_dmah);
848 }
849 if (portc->buf_acch) {
850 ddi_dma_mem_free(&portc->buf_acch);
851 }
852 if (portc->buf_dmah) {
853 ddi_dma_free_handle(&portc->buf_dmah);
854 }
855 kmem_free(portc, sizeof (*portc));
856 }
857
858 if (devc->ac97) {
859 ac97_free(devc->ac97);
860 }
861
862 cmediahd_del_controls(devc);
863
864 if (devc->adev != NULL) {
865 audio_dev_free(devc->adev);
866 }
867 if (devc->regsh != NULL) {
868 ddi_regs_map_free(&devc->regsh);
869 }
870 if (devc->pcih != NULL) {
871 pci_config_teardown(&devc->pcih);
872 }
873 kmem_free(devc, sizeof (*devc));
874 }
875
876 void
cmediahd_ac97_hwinit(cmediahd_devc_t * devc)877 cmediahd_ac97_hwinit(cmediahd_devc_t *devc)
878 {
879 /* GPIO #0 programmed as output, set CMI9780 Reg0x70 */
880 cmediahd_write_ac97(devc, 0x70, 0x100);
881
882 /* LI2LI,MIC2MIC; let them always on, FOE on, ROE/BKOE/CBOE off */
883 cmediahd_write_ac97(devc, 0x62, 0x180F);
884
885 /* unmute Master Volume */
886 cmediahd_write_ac97(devc, 0x02, 0x0);
887
888 /* change PCBeep path, set Mix2FR on, option for quality issue */
889 cmediahd_write_ac97(devc, 0x64, 0x8043);
890
891 /* mute PCBeep, option for quality issues */
892 cmediahd_write_ac97(devc, 0x0A, 0x8000);
893
894 /* Record Select Control Register (Index 1Ah) */
895 cmediahd_write_ac97(devc, 0x1A, 0x0000);
896
897 /* set Mic Volume Register 0x0Eh umute and enable micboost */
898 cmediahd_write_ac97(devc, 0x0E, 0x0848);
899
900 /* set Line in Volume Register 0x10h mute */
901 cmediahd_write_ac97(devc, 0x10, 0x8808);
902
903 /* set CD Volume Register 0x12h mute */
904 cmediahd_write_ac97(devc, 0x12, 0x8808);
905
906 /* set AUX Volume Register 0x16h max */
907 cmediahd_write_ac97(devc, 0x16, 0x0808);
908
909 /* set record gain Register 0x1Ch to max */
910 cmediahd_write_ac97(devc, 0x1C, 0x0F0F);
911
912 /* GPIO status register enable GPO0 */
913 cmediahd_write_ac97(devc, 0x72, 0x0001);
914 }
915 void
cmediahd_hwinit(cmediahd_devc_t * devc)916 cmediahd_hwinit(cmediahd_devc_t *devc)
917 {
918
919 unsigned short sVal;
920 unsigned short i2s_fmt;
921 unsigned char bVal;
922 int i, count;
923
924 /* setup the default rec DMA engines to REC_A */
925 devc->rec_eng.addr = RECA_ADDR;
926 devc->rec_eng.size = RECA_SIZE;
927 devc->rec_eng.frag = RECA_FRAG;
928 devc->rec_eng.i2s = I2S_ADC1;
929 devc->rec_eng.chan = REC_A;
930
931 /* setup GPIOs to 0 */
932 devc->gpio_mic = 0;
933 devc->gpio_out = 0;
934 devc->gpio_codec = 0;
935 devc->gpio_alt = 0;
936
937 /* Init CMI Controller */
938 sVal = INW(devc, CTRL_VERSION);
939 if (!(sVal & 0x0008)) {
940 bVal = INB(devc, MISC_REG);
941 bVal |= 0x20;
942 OUTB(devc, bVal, MISC_REG);
943 }
944
945 bVal = INB(devc, FUNCTION);
946 bVal |= 0x02; /* Reset codec */
947 OUTB(devc, bVal, FUNCTION);
948
949 /* Cold reset onboard AC97 */
950 OUTW(devc, 0x1, AC97_CTRL);
951 count = 100;
952 while ((INW(devc, AC97_CTRL) & 0x2) && (count--)) {
953 OUTW(devc, (INW(devc, AC97_CTRL) & ~0x2) | 0x2, AC97_CTRL);
954 drv_usecwait(100);
955 }
956
957 if (!count)
958 audio_dev_warn(devc->adev, "CMI8788 AC97 not ready");
959
960 sVal = INW(devc, AC97_CTRL);
961 /* check if there's an onboard AC97 codec (CODEC 0) */
962 if (sVal & 0x10) {
963 /* disable CODEC0 OUTPUT */
964 OUTW(devc, INW(devc, AC97_OUT_CHAN_CONFIG) & ~0xFF00,
965 AC97_OUT_CHAN_CONFIG);
966
967 /* enable CODEC0 INPUT */
968 OUTW(devc, INW(devc, AC97_IN_CHAN_CONFIG) | 0x0300,
969 AC97_IN_CHAN_CONFIG);
970
971 devc->has_ac97 = 1;
972 }
973
974 /* check if there's an front panel AC97 codec (CODEC1) */
975 if (sVal & 0x20) {
976 /* enable CODEC1 OUTPUT */
977 OUTW(devc, INW(devc, AC97_OUT_CHAN_CONFIG) | 0x0033,
978 AC97_OUT_CHAN_CONFIG);
979 /* enable CODEC1 INPUT */
980 OUTW(devc, INW(devc, AC97_IN_CHAN_CONFIG) | 0x0033,
981 AC97_IN_CHAN_CONFIG);
982
983 devc->has_fp_ac97 = 1;
984 }
985
986 /* Disable AC97 interrupts and initialize AC97 */
987 OUTB(devc, 0x0, AC97_INTR_MASK);
988 OUTW(devc, INW(devc, IRQ_MASK) & ~0x4000, IRQ_MASK);
989
990 /* I2S to 16bit/48Khz/Master, see below. */
991 i2s_fmt = 0x011A;
992
993 /* Setup I2S to use 16bit instead of 24Bit */
994 OUTW(devc, i2s_fmt, I2S_MULTICH_DAC);
995 OUTW(devc, i2s_fmt, I2S_ADC1);
996 OUTW(devc, i2s_fmt, I2S_ADC2);
997 OUTW(devc, i2s_fmt, I2S_ADC3);
998
999 /* setup Routing regs (default vals) */
1000 OUTW(devc, 0xE400, PLAY_ROUTING);
1001 OUTB(devc, 0x00, REC_ROUTING); /* default routing set to I2S */
1002 OUTB(devc, 0x00, REC_MONITOR); /* monitor through MULTICH_PLAY */
1003 OUTB(devc, 0xE4, MONITOR_ROUTING); /* default monitor routing */
1004
1005
1006 /* Enable Xonar output */
1007 switch (devc->model) {
1008 case SUBID_XONAR_D1:
1009 case SUBID_XONAR_DX:
1010 /* GPIO8 = 0x100 controls mic/line-in */
1011 /* GPIO0 = 0x001controls output */
1012 /* GPIO2/3 = 0x00C codec output control */
1013
1014 devc->rec_eng.addr = RECB_ADDR;
1015 devc->rec_eng.size = RECB_SIZE;
1016 devc->rec_eng.frag = RECB_FRAG;
1017 devc->rec_eng.i2s = I2S_ADC2;
1018 devc->rec_eng.chan = REC_B;
1019
1020 /* disable AC97 mixer - not used */
1021 devc->has_ac97 = 0;
1022
1023 /* setup for 2wire communication mode */
1024 OUTB(devc, INB(devc, FUNCTION) | 0x40, FUNCTION);
1025
1026 /* setup GPIO direction */
1027 OUTW(devc, INW(devc, GPIO_CONTROL) | 0x10D, GPIO_CONTROL);
1028 /* setup GPIO pins */
1029 OUTW(devc, INW(devc, GPIO_DATA) | 0x101, GPIO_DATA);
1030
1031 /* init the front and rear dacs */
1032 cs4398_init(devc, XONAR_DX_FRONTDAC);
1033 cs4362a_init(devc, XONAR_DX_SURRDAC);
1034 break;
1035
1036 case SUBID_XONAR_D2:
1037 case SUBID_XONAR_D2X:
1038 /* GPIO7 = 0x0080 controls mic/line-in */
1039 /* GPIO8 = 0x0100 controls output */
1040 /* GPIO2/3 = 0x000C codec output control */
1041
1042 devc->rec_eng.addr = RECB_ADDR;
1043 devc->rec_eng.size = RECB_SIZE;
1044 devc->rec_eng.frag = RECB_FRAG;
1045 devc->rec_eng.i2s = I2S_ADC2;
1046 devc->rec_eng.chan = REC_B;
1047
1048 /* disable the AC97 mixer - it's not useful */
1049 devc->has_ac97 = 0;
1050
1051 /* setup for spi communication mode */
1052 OUTB(devc, (INB(devc, FUNCTION) & ~0x40) | 0x80, FUNCTION);
1053 /* setup the GPIO direction */
1054 OUTW(devc, INW(devc, GPIO_CONTROL) | 0x18c, GPIO_CONTROL);
1055
1056 /* setup GPIO Pins */
1057 OUTW(devc, INW(devc, GPIO_DATA) | 0x100, GPIO_DATA);
1058
1059 /* for all 4 codecs: unmute, set to 24Bit SPI */
1060 for (i = 0; i < 4; ++i) {
1061 /* left vol */
1062 spi_write(devc, i, 16, mix_scale(75, 8));
1063 /* right vol */
1064 spi_write(devc, i, 17, mix_scale(75, 8));
1065 /* unmute/24LSB/ATLD */
1066 spi_write(devc, i, 18, 0x30 | 0x80);
1067 }
1068 break;
1069
1070 case SUBID_XONAR_STX:
1071 devc->rec_eng.addr = RECB_ADDR;
1072 devc->rec_eng.size = RECB_SIZE;
1073 devc->rec_eng.frag = RECB_FRAG;
1074 devc->rec_eng.i2s = I2S_ADC2;
1075 devc->rec_eng.chan = REC_B;
1076
1077 /* disable the AC97 mixer - it's not useful */
1078 devc->has_ac97 = 0;
1079
1080 /* setup for spi communication mode */
1081 OUTB(devc, (INB(devc, FUNCTION) & ~0x40) | 0x80, FUNCTION);
1082 /* setup the GPIO direction */
1083 OUTW(devc, INW(devc, GPIO_CONTROL) | 0x18F, GPIO_CONTROL);
1084 /* setup GPIO Pins */
1085 OUTW(devc, INW(devc, GPIO_DATA) | 0x111, GPIO_DATA);
1086
1087 /* init front DAC */
1088 /* left vol */
1089 i2c_write(devc, XONAR_STX_FRONTDAC, 16, mix_scale(75, 8));
1090 /* right vol */
1091 i2c_write(devc, XONAR_STX_FRONTDAC, 17, mix_scale(75, 8));
1092 /* unmute/24LSB/ATLD */
1093 i2c_write(devc, XONAR_STX_FRONTDAC, 18, 0x30 | 0x80);
1094 i2c_write(devc, XONAR_STX_FRONTDAC, 19, 0); /* ATS1/FLT_SHARP */
1095 i2c_write(devc, XONAR_STX_FRONTDAC, 20, 0); /* OS_64 */
1096 i2c_write(devc, XONAR_STX_FRONTDAC, 21, 0);
1097 break;
1098
1099 case SUBID_XONAR_DS:
1100 /* GPIO 8 = 1 output enabled 0 mute */
1101 /* GPIO 7 = 1 lineout enabled 0 mute */
1102 /* GPIO 6 = 1 mic select 0 line-in select */
1103 /* GPIO 4 = 1 FP Headphone plugged in */
1104 /* GPIO 3 = 1 FP Mic plugged in */
1105
1106 devc->rec_eng.addr = RECA_ADDR;
1107 devc->rec_eng.size = RECA_SIZE;
1108 devc->rec_eng.frag = RECA_FRAG;
1109 devc->rec_eng.i2s = I2S_ADC1;
1110 devc->rec_eng.chan = REC_A;
1111
1112 /* disable the AC97 mixer - it's not useful */
1113 devc->has_ac97 = 0;
1114
1115 /* setup for spi communication mode */
1116 OUTB(devc, (INB(devc, FUNCTION) & ~0x40) | 0x80, FUNCTION);
1117 /* setup the GPIO direction */
1118 OUTW(devc, INW(devc, GPIO_CONTROL) | 0x1D0, GPIO_CONTROL);
1119 /* setup GPIO Pins */
1120 OUTW(devc, INW(devc, GPIO_DATA) | 0x1D0, GPIO_DATA);
1121 spi_write(devc, XONAR_DS_FRONTDAC, 0x17, 0x1); /* reset */
1122 spi_write(devc, XONAR_DS_FRONTDAC, 0x7, 0x90); /* dac control */
1123 spi_write(devc, XONAR_DS_FRONTDAC, 0x8, 0); /* unmute */
1124 /* powerdown hp */
1125 spi_write(devc, XONAR_DS_FRONTDAC, 0xC, 0x22);
1126 spi_write(devc, XONAR_DS_FRONTDAC, 0xD, 0x8); /* powerdown hp */
1127 spi_write(devc, XONAR_DS_FRONTDAC, 0xA, 0x1); /* LJust/16bit */
1128 spi_write(devc, XONAR_DS_FRONTDAC, 0xB, 0x1); /* LJust/16bit */
1129 spi_write(devc, XONAR_DS_SURRDAC, 0x1f, 1); /* reset */
1130 /* LJust/24bit */
1131 spi_write(devc, XONAR_DS_SURRDAC, 0x3, 0x1|0x20);
1132 break;
1133
1134
1135 default:
1136 /* SPI default for anything else, including the */
1137 OUTB(devc, (INB(devc, FUNCTION) & ~0x40) | 0x80, FUNCTION);
1138 OUTB(devc, 0x18, REC_ROUTING); /* default routing set to I2S */
1139 break;
1140 }
1141
1142 /* only initialize AC97 if not defined */
1143 if (devc->has_ac97)
1144 cmediahd_ac97_hwinit(devc);
1145 }
1146
1147 static int
cmediahd_set_control(void * arg,uint64_t val)1148 cmediahd_set_control(void *arg, uint64_t val)
1149 {
1150 cmediahd_ctrl_t *pc = arg;
1151 cmediahd_devc_t *devc = pc->devc;
1152
1153 mutex_enter(&devc->mutex);
1154
1155 pc->val = val;
1156
1157 switch (pc->num) {
1158
1159 case CTL_VOLUME:
1160 case CTL_FRONT:
1161 cmediahd_set_play_volume(devc, 0, val);
1162 break;
1163
1164 case CTL_REAR:
1165 cmediahd_set_play_volume(devc, 1, val);
1166 break;
1167
1168 case CTL_CENTER:
1169 val &= 0xff;
1170 val |= ((devc->controls[CTL_LFE].val) << 8);
1171 cmediahd_set_play_volume(devc, 2, val);
1172 break;
1173
1174 case CTL_LFE:
1175 val &= 0xff;
1176 val <<= 8;
1177 val |= (devc->controls[CTL_CENTER].val);
1178 cmediahd_set_play_volume(devc, 2, val);
1179 break;
1180
1181 case CTL_SURROUND:
1182 cmediahd_set_play_volume(devc, 3, val);
1183 break;
1184
1185 case CTL_MONITOR:
1186 /* enable recording monitor rec 1 and rec2 */
1187 if (val)
1188 OUTB(devc, INB(devc, REC_MONITOR) | 0xF, REC_MONITOR);
1189 else
1190 OUTB(devc, INB(devc, REC_MONITOR) & ~0xF, REC_MONITOR);
1191 break;
1192
1193 case CTL_RECSRC:
1194 switch (val) {
1195 case 1: /* Line */
1196 if (devc->model == SUBID_XONAR_DS)
1197 OUTW(devc, INW(devc, GPIO_DATA) & ~0x40,
1198 GPIO_DATA);
1199
1200 if (devc->model == SUBID_XONAR_D1 ||
1201 devc->model == SUBID_XONAR_DX)
1202 OUTW(devc, INW(devc, GPIO_DATA) &
1203 ~devc->gpio_mic, GPIO_DATA);
1204 cmediahd_write_ac97(devc, 0x72,
1205 cmediahd_read_ac97(devc, 0x72) & ~0x1);
1206 cmediahd_write_ac97(devc, 0x1A, 0x0404);
1207 break;
1208
1209 case 2: /* Mic */
1210 if (devc->model == SUBID_XONAR_DS)
1211 OUTW(devc, INW(devc, GPIO_DATA) | 0x40,
1212 GPIO_DATA);
1213
1214 if (devc->model == SUBID_XONAR_D1 ||
1215 devc->model == SUBID_XONAR_DX)
1216 OUTW(devc, INW(devc, GPIO_DATA) |
1217 devc->gpio_mic, GPIO_DATA);
1218 cmediahd_write_ac97(devc, 0x72,
1219 cmediahd_read_ac97(devc, 0x72) | 0x1);
1220 /* Unmute Mic */
1221 cmediahd_write_ac97(devc, 0xE,
1222 cmediahd_read_ac97(devc, 0xE) & ~0x8000);
1223 /* Mute AUX and Video */
1224 cmediahd_write_ac97(devc, 0x12,
1225 cmediahd_read_ac97(devc, 0x12) | 0x8000);
1226 cmediahd_write_ac97(devc, 0x16,
1227 cmediahd_read_ac97(devc, 0x16) | 0x8000);
1228 cmediahd_write_ac97(devc, 0x1A, 0x0000);
1229 break;
1230
1231 case 4: /* AUX */
1232 if (devc->model == SUBID_XONAR_D1 ||
1233 devc->model == SUBID_XONAR_DX)
1234 OUTW(devc, INW(devc, GPIO_DATA) |
1235 devc->gpio_mic, GPIO_DATA);
1236 cmediahd_write_ac97(devc, 0x72,
1237 cmediahd_read_ac97(devc, 0x72) | 0x1);
1238 /* Unmute AUX */
1239 cmediahd_write_ac97(devc, 0x16,
1240 cmediahd_read_ac97(devc, 0x16) & ~0x8000);
1241 /* Mute CD and Mic */
1242 cmediahd_write_ac97(devc, 0x14,
1243 cmediahd_read_ac97(devc, 0x14) | 0x8000);
1244 cmediahd_write_ac97(devc, 0x0E,
1245 cmediahd_read_ac97(devc, 0x0E) | 0x8000);
1246 cmediahd_write_ac97(devc, 0x1A, 0x0303);
1247 break;
1248
1249 case 8: /* Video (CD) */
1250 if (devc->model == SUBID_XONAR_D1 ||
1251 devc->model == SUBID_XONAR_DX)
1252 OUTW(devc, INW(devc, GPIO_DATA) |
1253 devc->gpio_mic, GPIO_DATA);
1254 cmediahd_write_ac97(devc, 0x72,
1255 cmediahd_read_ac97(devc, 0x72) | 0x1);
1256 /* Unmute Video (CD) */
1257 cmediahd_write_ac97(devc, 0x14,
1258 cmediahd_read_ac97(devc, 0x14) & ~0x8000);
1259 /* Mute AUX and Mic */
1260 cmediahd_write_ac97(devc, 0x16,
1261 cmediahd_read_ac97(devc, 0x16) | 0x8000);
1262 cmediahd_write_ac97(devc, 0x0E,
1263 cmediahd_read_ac97(devc, 0x0E) | 0x8000);
1264 /* set input to video */
1265 cmediahd_write_ac97(devc, 0x1A, 0x0202);
1266 break;
1267 }
1268 break;
1269
1270 case CTL_LOOP:
1271 if (val)
1272 OUTW(devc, INW(devc, GPIO_DATA) | devc->gpio_alt,
1273 GPIO_DATA);
1274 else
1275 OUTW(devc, (INW(devc, GPIO_DATA) & ~devc->gpio_alt),
1276 GPIO_DATA);
1277 break;
1278
1279 case CTL_SPREAD:
1280 if (val)
1281 OUTW(devc, INW(devc, PLAY_ROUTING) & 0x00FF,
1282 PLAY_ROUTING);
1283 else
1284 OUTW(devc, (INW(devc, PLAY_ROUTING) & 0x00FF) |
1285 0xE400, PLAY_ROUTING);
1286 break;
1287
1288 case CTL_RECGAIN:
1289 cmediahd_set_rec_volume(devc, val);
1290 break;
1291
1292 case CTL_MICVOL:
1293 if (val)
1294 cmediahd_write_ac97(devc, 0x0E,
1295 (0x40 | mix_scale(val, -5)) & ~0x8000);
1296 else
1297 cmediahd_write_ac97(devc, 0x0E, 0x8000);
1298 break;
1299
1300 case CTL_AUXVOL:
1301 if (val)
1302 cmediahd_write_ac97(devc, 0x16,
1303 mix_scale(val, -5) & ~0x8000);
1304 else
1305 cmediahd_write_ac97(devc, 0x16, 0x8000);
1306 break;
1307
1308
1309 case CTL_CDVOL:
1310 if (val)
1311 cmediahd_write_ac97(devc, 0x14,
1312 mix_scale(val, -5) & ~0x8000);
1313 else
1314 cmediahd_write_ac97(devc, 0x14, 0x8000);
1315 break;
1316 }
1317
1318 mutex_exit(&devc->mutex);
1319 return (0);
1320 }
1321
1322 static int
cmediahd_get_control(void * arg,uint64_t * val)1323 cmediahd_get_control(void *arg, uint64_t *val)
1324 {
1325 cmediahd_ctrl_t *pc = arg;
1326 cmediahd_devc_t *devc = pc->devc;
1327
1328 mutex_enter(&devc->mutex);
1329 *val = pc->val;
1330 mutex_exit(&devc->mutex);
1331 return (0);
1332 }
1333
1334 static void
cmediahd_alloc_ctrl(cmediahd_devc_t * devc,uint32_t num,uint64_t val)1335 cmediahd_alloc_ctrl(cmediahd_devc_t *devc, uint32_t num, uint64_t val)
1336 {
1337 audio_ctrl_desc_t desc;
1338 cmediahd_ctrl_t *pc;
1339
1340 bzero(&desc, sizeof (desc));
1341
1342 pc = &devc->controls[num];
1343 pc->num = num;
1344 pc->devc = devc;
1345
1346
1347 switch (num) {
1348
1349 case CTL_VOLUME:
1350 desc.acd_name = AUDIO_CTRL_ID_VOLUME;
1351 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1352 desc.acd_minvalue = 0;
1353 desc.acd_maxvalue = 100;
1354 desc.acd_flags = PCMVOL;
1355 break;
1356
1357 case CTL_FRONT:
1358 desc.acd_name = AUDIO_CTRL_ID_FRONT;
1359 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1360 desc.acd_minvalue = 0;
1361 desc.acd_maxvalue = 100;
1362 desc.acd_flags = PCMVOL;
1363 break;
1364
1365 case CTL_REAR:
1366 desc.acd_name = AUDIO_CTRL_ID_REAR;
1367 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1368 desc.acd_minvalue = 0;
1369 desc.acd_maxvalue = 100;
1370 desc.acd_flags = PCMVOL;
1371 break;
1372
1373 case CTL_SURROUND:
1374 desc.acd_name = AUDIO_CTRL_ID_SURROUND;
1375 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1376 desc.acd_minvalue = 0;
1377 desc.acd_maxvalue = 100;
1378 desc.acd_flags = PCMVOL;
1379 break;
1380
1381 case CTL_CENTER:
1382 desc.acd_name = AUDIO_CTRL_ID_CENTER;
1383 desc.acd_type = AUDIO_CTRL_TYPE_MONO;
1384 desc.acd_minvalue = 0;
1385 desc.acd_maxvalue = 100;
1386 desc.acd_flags = PCMVOL;
1387 break;
1388
1389 case CTL_LFE:
1390 desc.acd_name = AUDIO_CTRL_ID_LFE;
1391 desc.acd_type = AUDIO_CTRL_TYPE_MONO;
1392 desc.acd_minvalue = 0;
1393 desc.acd_maxvalue = 100;
1394 desc.acd_flags = PCMVOL;
1395 break;
1396
1397 case CTL_MONITOR:
1398 desc.acd_name = AUDIO_CTRL_ID_MONSRC;
1399 desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
1400 desc.acd_minvalue = 0;
1401 desc.acd_maxvalue = 1;
1402 desc.acd_flags = RECCTL;
1403 break;
1404
1405 case CTL_RECSRC:
1406 desc.acd_name = AUDIO_CTRL_ID_RECSRC;
1407 desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
1408 desc.acd_flags = RECCTL;
1409 desc.acd_enum[0] = AUDIO_PORT_LINEIN;
1410 desc.acd_enum[1] = AUDIO_PORT_MIC;
1411
1412 if (devc->model == SUBID_XONAR_D2 ||
1413 devc->model == SUBID_XONAR_D2X) {
1414 desc.acd_minvalue = 0xF;
1415 desc.acd_maxvalue = 0xF;
1416 desc.acd_enum[2] = AUDIO_PORT_AUX1IN;
1417 desc.acd_enum[3] = AUDIO_PORT_CD;
1418 } else {
1419 desc.acd_minvalue = 0x3;
1420 desc.acd_maxvalue = 0x3;
1421 }
1422 break;
1423
1424 case CTL_LOOP:
1425 desc.acd_name = AUDIO_CTRL_ID_LOOPBACK;
1426 desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
1427 desc.acd_minvalue = 0;
1428 desc.acd_maxvalue = 1;
1429 desc.acd_flags = RECCTL;
1430 break;
1431
1432 case CTL_SPREAD:
1433 desc.acd_name = AUDIO_CTRL_ID_SPREAD;
1434 desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
1435 desc.acd_minvalue = 0;
1436 desc.acd_maxvalue = 1;
1437 desc.acd_flags = PLAYCTL;
1438 break;
1439
1440 case CTL_RECGAIN:
1441 desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
1442 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1443 desc.acd_minvalue = 0;
1444 desc.acd_maxvalue = 100;
1445 desc.acd_flags = RECVOL;
1446 break;
1447
1448 case CTL_MICVOL:
1449 desc.acd_name = AUDIO_CTRL_ID_MIC;
1450 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1451 desc.acd_minvalue = 0;
1452 desc.acd_maxvalue = 100;
1453 desc.acd_flags = RECVOL;
1454 break;
1455
1456 case CTL_AUXVOL:
1457 desc.acd_name = AUDIO_CTRL_ID_AUX1IN;
1458 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1459 desc.acd_minvalue = 0;
1460 desc.acd_maxvalue = 100;
1461 desc.acd_flags = RECVOL;
1462 break;
1463 case CTL_CDVOL:
1464 desc.acd_name = AUDIO_CTRL_ID_CD;
1465 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1466 desc.acd_minvalue = 0;
1467 desc.acd_maxvalue = 100;
1468 desc.acd_flags = RECVOL;
1469 break;
1470
1471 }
1472
1473 pc->val = val;
1474 pc->ctrl = audio_dev_add_control(devc->adev, &desc,
1475 cmediahd_get_control, cmediahd_set_control, pc);
1476 }
1477
1478 static void
cmediahd_refresh_mixer(cmediahd_devc_t * devc)1479 cmediahd_refresh_mixer(cmediahd_devc_t *devc)
1480 {
1481 int ctl;
1482
1483 for (ctl = 0; ctl < CTL_NUM; ctl++) {
1484 if (devc->controls[ctl].ctrl == NULL)
1485 continue;
1486 (void) cmediahd_set_control(&devc->controls[ctl],
1487 devc->controls[ctl].val);
1488 }
1489 }
1490
1491 static void
cmediahd_add_controls(cmediahd_devc_t * devc)1492 cmediahd_add_controls(cmediahd_devc_t *devc)
1493 {
1494 cmediahd_alloc_ctrl(devc, CTL_VOLUME, 80 | (80 << 8));
1495 cmediahd_alloc_ctrl(devc, CTL_FRONT, 80 | (80<<8));
1496 cmediahd_alloc_ctrl(devc, CTL_REAR, 80 | (80<<8));
1497 cmediahd_alloc_ctrl(devc, CTL_CENTER, 80);
1498 cmediahd_alloc_ctrl(devc, CTL_LFE, 80);
1499 cmediahd_alloc_ctrl(devc, CTL_SURROUND, 80 | (80<<8));
1500 cmediahd_alloc_ctrl(devc, CTL_SPREAD, 0);
1501 cmediahd_alloc_ctrl(devc, CTL_MONITOR, 0);
1502 cmediahd_alloc_ctrl(devc, CTL_LOOP, 0);
1503 cmediahd_alloc_ctrl(devc, CTL_RECSRC, 2);
1504
1505 switch (devc->model) {
1506 case SUBID_XONAR_DS:
1507 cmediahd_alloc_ctrl(devc, CTL_RECGAIN, 80|80<<8);
1508 break;
1509 case SUBID_XONAR_D2:
1510 case SUBID_XONAR_D2X:
1511 cmediahd_alloc_ctrl(devc, CTL_MICVOL, 80|80<<8);
1512 cmediahd_alloc_ctrl(devc, CTL_AUXVOL, 80|80<<8);
1513 cmediahd_alloc_ctrl(devc, CTL_CDVOL, 80|80<<8);
1514 break;
1515 }
1516
1517 cmediahd_refresh_mixer(devc);
1518 }
1519
1520 void
cmediahd_del_controls(cmediahd_devc_t * dev)1521 cmediahd_del_controls(cmediahd_devc_t *dev)
1522 {
1523 for (int i = 0; i < CTL_NUM; i++) {
1524 if (dev->controls[i].ctrl) {
1525 audio_dev_del_control(dev->controls[i].ctrl);
1526 dev->controls[i].ctrl = NULL;
1527 }
1528 }
1529 }
1530
1531 int
cmediahd_attach(dev_info_t * dip)1532 cmediahd_attach(dev_info_t *dip)
1533 {
1534 uint16_t pci_command, vendor, device, subvendor, subdevice;
1535 cmediahd_devc_t *devc;
1536 ddi_acc_handle_t pcih;
1537
1538 devc = kmem_zalloc(sizeof (*devc), KM_SLEEP);
1539 devc->dip = dip;
1540 ddi_set_driver_private(dip, devc);
1541
1542 mutex_init(&devc->mutex, NULL, MUTEX_DRIVER, NULL);
1543 mutex_init(&devc->low_mutex, NULL, MUTEX_DRIVER, NULL);
1544
1545 if ((devc->adev = audio_dev_alloc(dip, 0)) == NULL) {
1546 cmn_err(CE_WARN, "audio_dev_alloc failed");
1547 goto error;
1548 }
1549
1550 if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
1551 audio_dev_warn(devc->adev, "pci_config_setup failed");
1552 goto error;
1553 }
1554 devc->pcih = pcih;
1555
1556 vendor = pci_config_get16(pcih, PCI_CONF_VENID);
1557 device = pci_config_get16(pcih, PCI_CONF_DEVID);
1558 subvendor = pci_config_get16(pcih, PCI_CONF_SUBVENID);
1559 subdevice = pci_config_get16(pcih, PCI_CONF_SUBSYSID);
1560 if (vendor != PCI_VENDOR_ID_CMEDIA ||
1561 device != PCI_DEVICE_ID_CMEDIAHD) {
1562 audio_dev_warn(devc->adev, "Hardware not recognized "
1563 "(vendor=%x, dev=%x)", vendor, device);
1564 goto error;
1565 }
1566
1567
1568 pci_command = pci_config_get16(pcih, PCI_CONF_COMM);
1569 pci_command |= PCI_COMM_ME | PCI_COMM_IO;
1570 pci_config_put16(pcih, PCI_CONF_COMM, pci_command);
1571
1572 if ((ddi_regs_map_setup(dip, 1, &devc->base, 0, 0, &dev_attr,
1573 &devc->regsh)) != DDI_SUCCESS) {
1574 audio_dev_warn(devc->adev, "failed to map registers");
1575 goto error;
1576 }
1577
1578 audio_dev_set_description(devc->adev, "CMedia 8788");
1579
1580 /* Detect Xonar device */
1581 if (subvendor == ASUS_VENDOR_ID) {
1582 switch (subdevice) {
1583 case SUBID_XONAR_D1:
1584 audio_dev_set_description(devc->adev,
1585 "Asus Xonar D1 (AV100)");
1586 break;
1587 case SUBID_XONAR_DX:
1588 audio_dev_set_description(devc->adev,
1589 "Asus Xonar DX (AV100)");
1590 break;
1591 case SUBID_XONAR_D2:
1592 audio_dev_set_description(devc->adev,
1593 "Asus Xonar D2 (AV200)");
1594 break;
1595 case SUBID_XONAR_D2X:
1596 audio_dev_set_description(devc->adev,
1597 "Asus Xonar D2X (AV200)");
1598 break;
1599 case SUBID_XONAR_STX:
1600 audio_dev_set_description(devc->adev,
1601 "Asus Xonar STX (AV100)");
1602 break;
1603 case SUBID_XONAR_DS:
1604 audio_dev_set_description(devc->adev,
1605 "Asus Xonar DS (AV66)");
1606 break;
1607 default:
1608 audio_dev_set_description(devc->adev,
1609 "Asus Xonar Unknown Model");
1610 subdevice = SUBID_GENERIC;
1611 break;
1612 }
1613 devc->model = subdevice;
1614 }
1615
1616 cmediahd_hwinit(devc);
1617
1618 if (cmediahd_alloc_port(devc, CMEDIAHD_PLAY) != DDI_SUCCESS)
1619 goto error;
1620 if (cmediahd_alloc_port(devc, CMEDIAHD_REC) != DDI_SUCCESS)
1621 goto error;
1622
1623 /* Add the AC97 Mixer if there is an onboard AC97 device */
1624 if (devc->has_ac97) {
1625 devc->ac97 = ac97_alloc(dip, cmediahd_read_ac97,
1626 cmediahd_write_ac97, devc);
1627 if (ac97_init(devc->ac97, devc->adev) != DDI_SUCCESS) {
1628 audio_dev_warn(devc->adev, "failed to init ac97");
1629 goto error;
1630 }
1631 }
1632 #if 0
1633 /* Add the front panel AC97 device if one exists */
1634 if (devc->has_fp_ac97) {
1635 devc->fp_ac97 = ac97_alloc(dip, cmediahd_read_fp_ac97,
1636 cmediahd_write_fp_ac97, devc);
1637 if (ac97_init(devc->fp_ac97, devc->adev) != DDI_SUCCESS) {
1638 audio_dev_warn(devc->adev, "failed to init fp_ac97");
1639 goto error;
1640 }
1641 }
1642 #endif
1643 /* Add the standard CMI8788 Mixer panel */
1644 cmediahd_add_controls(devc);
1645
1646 if (audio_dev_register(devc->adev) != DDI_SUCCESS) {
1647 audio_dev_warn(devc->adev, "unable to register with framework");
1648 goto error;
1649 }
1650
1651 ddi_report_dev(dip);
1652
1653 return (DDI_SUCCESS);
1654
1655 error:
1656 cmediahd_destroy(devc);
1657 return (DDI_FAILURE);
1658 }
1659
1660 int
cmediahd_resume(dev_info_t * dip)1661 cmediahd_resume(dev_info_t *dip)
1662 {
1663 cmediahd_devc_t *devc;
1664
1665 devc = ddi_get_driver_private(dip);
1666
1667 cmediahd_hwinit(devc);
1668
1669 if (devc->ac97)
1670 ac97_reset(devc->ac97);
1671
1672 cmediahd_refresh_mixer(devc);
1673
1674 audio_dev_resume(devc->adev);
1675
1676 return (DDI_SUCCESS);
1677 }
1678
1679 int
cmediahd_detach(cmediahd_devc_t * devc)1680 cmediahd_detach(cmediahd_devc_t *devc)
1681 {
1682 if (audio_dev_unregister(devc->adev) != DDI_SUCCESS)
1683 return (DDI_FAILURE);
1684
1685 cmediahd_destroy(devc);
1686 return (DDI_SUCCESS);
1687 }
1688
1689 int
cmediahd_suspend(cmediahd_devc_t * devc)1690 cmediahd_suspend(cmediahd_devc_t *devc)
1691 {
1692 audio_dev_suspend(devc->adev);
1693 return (DDI_SUCCESS);
1694 }
1695
1696 static int cmediahd_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
1697 static int cmediahd_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
1698 static int cmediahd_ddi_quiesce(dev_info_t *);
1699
1700 static struct dev_ops cmediahd_dev_ops = {
1701 DEVO_REV, /* rev */
1702 0, /* refcnt */
1703 NULL, /* getinfo */
1704 nulldev, /* identify */
1705 nulldev, /* probe */
1706 cmediahd_ddi_attach, /* attach */
1707 cmediahd_ddi_detach, /* detach */
1708 nodev, /* reset */
1709 NULL, /* cb_ops */
1710 NULL, /* bus_ops */
1711 NULL, /* power */
1712 cmediahd_ddi_quiesce, /* quiesce */
1713 };
1714
1715 static struct modldrv cmediahd_modldrv = {
1716 &mod_driverops, /* drv_modops */
1717 "CMedia 8788", /* linkinfo */
1718 &cmediahd_dev_ops, /* dev_ops */
1719 };
1720
1721 static struct modlinkage modlinkage = {
1722 MODREV_1,
1723 { &cmediahd_modldrv, NULL }
1724 };
1725
1726 int
_init(void)1727 _init(void)
1728 {
1729 int rv;
1730
1731 audio_init_ops(&cmediahd_dev_ops, CMEDIAHD_NAME);
1732 if ((rv = mod_install(&modlinkage)) != 0) {
1733 audio_fini_ops(&cmediahd_dev_ops);
1734 }
1735 return (rv);
1736 }
1737
1738 int
_fini(void)1739 _fini(void)
1740 {
1741 int rv;
1742
1743 if ((rv = mod_remove(&modlinkage)) == 0) {
1744 audio_fini_ops(&cmediahd_dev_ops);
1745 }
1746 return (rv);
1747 }
1748
1749 int
_info(struct modinfo * modinfop)1750 _info(struct modinfo *modinfop)
1751 {
1752 return (mod_info(&modlinkage, modinfop));
1753 }
1754
1755 int
cmediahd_ddi_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)1756 cmediahd_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1757 {
1758 switch (cmd) {
1759 case DDI_ATTACH:
1760 return (cmediahd_attach(dip));
1761
1762 case DDI_RESUME:
1763 return (cmediahd_resume(dip));
1764
1765 default:
1766 return (DDI_FAILURE);
1767 }
1768 }
1769
1770 int
cmediahd_ddi_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)1771 cmediahd_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1772 {
1773 cmediahd_devc_t *devc;
1774
1775 devc = ddi_get_driver_private(dip);
1776
1777 switch (cmd) {
1778 case DDI_DETACH:
1779 return (cmediahd_detach(devc));
1780
1781 case DDI_SUSPEND:
1782 return (cmediahd_suspend(devc));
1783
1784 default:
1785 return (DDI_FAILURE);
1786 }
1787 }
1788
1789 int
cmediahd_ddi_quiesce(dev_info_t * dip)1790 cmediahd_ddi_quiesce(dev_info_t *dip)
1791 {
1792 cmediahd_devc_t *devc;
1793
1794 devc = ddi_get_driver_private(dip);
1795
1796 OUTW(devc, 0x0, DMA_START);
1797
1798 /*
1799 * Turn off the hardware
1800 */
1801
1802
1803 return (DDI_SUCCESS);
1804 }
1805