1 /* $OpenBSD: cmpci.c,v 1.54 2024/05/24 06:02:53 jsg Exp $ */
2 /* $NetBSD: cmpci.c,v 1.25 2004/10/26 06:32:20 xtraeme Exp $ */
3
4 /*
5 * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Takuya SHIOZAKI <tshiozak@NetBSD.org> .
10 *
11 * This code is derived from software contributed to The NetBSD Foundation
12 * by ITOH Yasufumi.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 */
36
37 /*
38 * C-Media CMI8x38, CMI8768 Audio Chip Support.
39 *
40 * TODO:
41 * - Joystick support.
42 *
43 */
44
45 #if defined(AUDIO_DEBUG) || defined(DEBUG)
46 #define DPRINTF(x) if (cmpcidebug) printf x
47 int cmpcidebug = 0;
48 #else
49 #define DPRINTF(x)
50 #endif
51
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/malloc.h>
55 #include <sys/device.h>
56
57 #include <dev/pci/pcidevs.h>
58 #include <dev/pci/pcivar.h>
59
60 #include <sys/audioio.h>
61 #include <dev/audio_if.h>
62
63 #include <dev/pci/cmpcireg.h>
64 #include <dev/pci/cmpcivar.h>
65
66 #include <machine/bus.h>
67 #include <machine/intr.h>
68
69 /*
70 * Low-level HW interface
71 */
72 uint8_t cmpci_mixerreg_read(struct cmpci_softc *, uint8_t);
73 void cmpci_mixerreg_write(struct cmpci_softc *, uint8_t, uint8_t);
74 void cmpci_reg_partial_write_1(struct cmpci_softc *, int, int,
75 unsigned, unsigned);
76 void cmpci_reg_partial_write_4(struct cmpci_softc *, int, int,
77 uint32_t, uint32_t);
78 void cmpci_reg_set_1(struct cmpci_softc *, int, uint8_t);
79 void cmpci_reg_clear_1(struct cmpci_softc *, int, uint8_t);
80 void cmpci_reg_set_4(struct cmpci_softc *, int, uint32_t);
81 void cmpci_reg_clear_4(struct cmpci_softc *, int, uint32_t);
82 void cmpci_reg_set_reg_misc(struct cmpci_softc *, uint32_t);
83 void cmpci_reg_clear_reg_misc(struct cmpci_softc *, uint32_t);
84 int cmpci_rate_to_index(int);
85 int cmpci_index_to_rate(int);
86 int cmpci_index_to_divider(int);
87
88 int cmpci_adjust(int, int);
89 void cmpci_set_mixer_gain(struct cmpci_softc *, int);
90 void cmpci_set_out_ports(struct cmpci_softc *);
91 int cmpci_set_in_ports(struct cmpci_softc *);
92
93 void cmpci_resume(struct cmpci_softc *);
94
95 /*
96 * autoconf interface
97 */
98 int cmpci_match(struct device *, void *, void *);
99 void cmpci_attach(struct device *, struct device *, void *);
100 int cmpci_activate(struct device *, int);
101
102 struct cfdriver cmpci_cd = {
103 NULL, "cmpci", DV_DULL
104 };
105
106 const struct cfattach cmpci_ca = {
107 sizeof (struct cmpci_softc), cmpci_match, cmpci_attach, NULL,
108 cmpci_activate
109 };
110
111 /* interrupt */
112 int cmpci_intr(void *);
113
114 /*
115 * DMA stuff
116 */
117 int cmpci_alloc_dmamem(struct cmpci_softc *,
118 size_t, int,
119 int, caddr_t *);
120 int cmpci_free_dmamem(struct cmpci_softc *, caddr_t,
121 int);
122 struct cmpci_dmanode * cmpci_find_dmamem(struct cmpci_softc *,
123 caddr_t);
124
125 /*
126 * Interface to machine independent layer
127 */
128 int cmpci_open(void *, int);
129 void cmpci_close(void *);
130 int cmpci_set_params(void *, int, int,
131 struct audio_params *,
132 struct audio_params *);
133 int cmpci_round_blocksize(void *, int);
134 int cmpci_halt_output(void *);
135 int cmpci_halt_input(void *);
136 int cmpci_set_port(void *, mixer_ctrl_t *);
137 int cmpci_get_port(void *, mixer_ctrl_t *);
138 int cmpci_query_devinfo(void *, mixer_devinfo_t *);
139 void *cmpci_malloc(void *, int, size_t, int, int);
140 void cmpci_free(void *, void *, int);
141 size_t cmpci_round_buffersize(void *, int, size_t);
142 int cmpci_trigger_output(void *, void *, void *, int,
143 void (*)(void *), void *,
144 struct audio_params *);
145 int cmpci_trigger_input(void *, void *, void *, int,
146 void (*)(void *), void *,
147 struct audio_params *);
148
149 const struct audio_hw_if cmpci_hw_if = {
150 .open = cmpci_open,
151 .close = cmpci_close,
152 .set_params = cmpci_set_params,
153 .round_blocksize = cmpci_round_blocksize,
154 .halt_output = cmpci_halt_output,
155 .halt_input = cmpci_halt_input,
156 .set_port = cmpci_set_port,
157 .get_port = cmpci_get_port,
158 .query_devinfo = cmpci_query_devinfo,
159 .allocm = cmpci_malloc,
160 .freem = cmpci_free,
161 .round_buffersize = cmpci_round_buffersize,
162 .trigger_output = cmpci_trigger_output,
163 .trigger_input = cmpci_trigger_input,
164 };
165
166 /*
167 * Low-level HW interface
168 */
169
170 /* mixer register read/write */
171 uint8_t
cmpci_mixerreg_read(struct cmpci_softc * sc,uint8_t no)172 cmpci_mixerreg_read(struct cmpci_softc *sc, uint8_t no)
173 {
174 uint8_t ret;
175
176 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
177 delay(10);
178 ret = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA);
179 delay(10);
180 return ret;
181 }
182
183 void
cmpci_mixerreg_write(struct cmpci_softc * sc,uint8_t no,uint8_t val)184 cmpci_mixerreg_write(struct cmpci_softc *sc, uint8_t no, uint8_t val)
185 {
186 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
187 delay(10);
188 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA, val);
189 delay(10);
190 }
191
192 /* register partial write */
193 void
cmpci_reg_partial_write_1(struct cmpci_softc * sc,int no,int shift,unsigned mask,unsigned val)194 cmpci_reg_partial_write_1(struct cmpci_softc *sc, int no, int shift,
195 unsigned mask, unsigned val)
196 {
197 bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
198 (val<<shift) |
199 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift)));
200 delay(10);
201 }
202
203 void
cmpci_reg_partial_write_4(struct cmpci_softc * sc,int no,int shift,uint32_t mask,uint32_t val)204 cmpci_reg_partial_write_4(struct cmpci_softc *sc, int no, int shift,
205 uint32_t mask, uint32_t val)
206 {
207 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
208 (val<<shift) |
209 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift)));
210 delay(10);
211 }
212
213 /* register set/clear bit */
214 void
cmpci_reg_set_1(struct cmpci_softc * sc,int no,uint8_t mask)215 cmpci_reg_set_1(struct cmpci_softc *sc, int no, uint8_t mask)
216 {
217 bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
218 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) | mask));
219 delay(10);
220 }
221
222 void
cmpci_reg_clear_1(struct cmpci_softc * sc,int no,uint8_t mask)223 cmpci_reg_clear_1(struct cmpci_softc *sc, int no, uint8_t mask)
224 {
225 bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
226 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~mask));
227 delay(10);
228 }
229
230 void
cmpci_reg_set_4(struct cmpci_softc * sc,int no,uint32_t mask)231 cmpci_reg_set_4(struct cmpci_softc *sc, int no, uint32_t mask)
232 {
233 /* use cmpci_reg_set_reg_misc() for CMPCI_REG_MISC */
234 KDASSERT(no != CMPCI_REG_MISC);
235
236 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
237 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask));
238 delay(10);
239 }
240
241 void
cmpci_reg_clear_4(struct cmpci_softc * sc,int no,uint32_t mask)242 cmpci_reg_clear_4(struct cmpci_softc *sc, int no, uint32_t mask)
243 {
244 /* use cmpci_reg_clear_reg_misc() for CMPCI_REG_MISC */
245 KDASSERT(no != CMPCI_REG_MISC);
246
247 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
248 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask));
249 delay(10);
250 }
251
252 /*
253 * The CMPCI_REG_MISC register needs special handling, since one of
254 * its bits has different read/write values.
255 */
256 void
cmpci_reg_set_reg_misc(struct cmpci_softc * sc,uint32_t mask)257 cmpci_reg_set_reg_misc(struct cmpci_softc *sc, uint32_t mask)
258 {
259 sc->sc_reg_misc |= mask;
260 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC,
261 sc->sc_reg_misc);
262 delay(10);
263 }
264
265 void
cmpci_reg_clear_reg_misc(struct cmpci_softc * sc,uint32_t mask)266 cmpci_reg_clear_reg_misc(struct cmpci_softc *sc, uint32_t mask)
267 {
268 sc->sc_reg_misc &= ~mask;
269 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC,
270 sc->sc_reg_misc);
271 delay(10);
272 }
273
274 /* rate */
275 static const struct {
276 int rate;
277 int divider;
278 } cmpci_rate_table[CMPCI_REG_NUMRATE] = {
279 #define _RATE(n) { n, CMPCI_REG_RATE_ ## n }
280 _RATE(5512),
281 _RATE(8000),
282 _RATE(11025),
283 _RATE(16000),
284 _RATE(22050),
285 _RATE(32000),
286 _RATE(44100),
287 _RATE(48000)
288 #undef _RATE
289 };
290
291 int
cmpci_rate_to_index(int rate)292 cmpci_rate_to_index(int rate)
293 {
294 int i;
295
296 for (i = 0; i < CMPCI_REG_NUMRATE - 1; i++)
297 if (rate <=
298 (cmpci_rate_table[i].rate + cmpci_rate_table[i+1].rate) / 2)
299 return i;
300 return i; /* 48000 */
301 }
302
303 int
cmpci_index_to_rate(int index)304 cmpci_index_to_rate(int index)
305 {
306 return cmpci_rate_table[index].rate;
307 }
308
309 int
cmpci_index_to_divider(int index)310 cmpci_index_to_divider(int index)
311 {
312 return cmpci_rate_table[index].divider;
313 }
314
315 const struct pci_matchid cmpci_devices[] = {
316 { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8338A },
317 { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8338B },
318 { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8738 },
319 { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8738B }
320 };
321
322 /*
323 * interface to configure the device.
324 */
325
326 int
cmpci_match(struct device * parent,void * match,void * aux)327 cmpci_match(struct device *parent, void *match, void *aux)
328 {
329 return (pci_matchbyid((struct pci_attach_args *)aux, cmpci_devices,
330 nitems(cmpci_devices)));
331 }
332
333 void
cmpci_attach(struct device * parent,struct device * self,void * aux)334 cmpci_attach(struct device *parent, struct device *self, void *aux)
335 {
336 struct cmpci_softc *sc = (struct cmpci_softc *)self;
337 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
338 struct audio_attach_args aa;
339 pci_intr_handle_t ih;
340 char const *intrstr;
341 int i, v, d;
342
343 sc->sc_id = pa->pa_id;
344 sc->sc_class = pa->pa_class;
345 switch (PCI_PRODUCT(sc->sc_id)) {
346 case PCI_PRODUCT_CMI_CMI8338A:
347 /*FALLTHROUGH*/
348 case PCI_PRODUCT_CMI_CMI8338B:
349 sc->sc_capable = CMPCI_CAP_CMI8338;
350 break;
351 case PCI_PRODUCT_CMI_CMI8738:
352 /*FALLTHROUGH*/
353 case PCI_PRODUCT_CMI_CMI8738B:
354 sc->sc_capable = CMPCI_CAP_CMI8738;
355 break;
356 }
357
358 /* map I/O space */
359 if (pci_mapreg_map(pa, CMPCI_PCI_IOBASEREG, PCI_MAPREG_TYPE_IO, 0,
360 &sc->sc_iot, &sc->sc_ioh, NULL, NULL, 0)) {
361 printf(": can't map i/o space\n");
362 return;
363 }
364
365 /* interrupt */
366 if (pci_intr_map(pa, &ih)) {
367 printf(": can't map interrupt\n");
368 return;
369 }
370 intrstr = pci_intr_string(pa->pa_pc, ih);
371 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO | IPL_MPSAFE,
372 cmpci_intr, sc, sc->sc_dev.dv_xname);
373 if (sc->sc_ih == NULL) {
374 printf(": can't establish interrupt");
375 if (intrstr != NULL)
376 printf(" at %s", intrstr);
377 printf("\n");
378 return;
379 }
380 printf(": %s\n", intrstr);
381
382 sc->sc_dmat = pa->pa_dmat;
383
384 audio_attach_mi(&cmpci_hw_if, sc, NULL, &sc->sc_dev);
385
386 /* attach OPL device */
387 aa.type = AUDIODEV_TYPE_OPL;
388 aa.hwif = NULL;
389 aa.hdl = NULL;
390 (void)config_found(&sc->sc_dev, &aa, audioprint);
391
392 /* attach MPU-401 device */
393 aa.type = AUDIODEV_TYPE_MPU;
394 aa.hwif = NULL;
395 aa.hdl = NULL;
396 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh,
397 CMPCI_REG_MPU_BASE, CMPCI_REG_MPU_SIZE, &sc->sc_mpu_ioh) == 0)
398 sc->sc_mpudev = config_found(&sc->sc_dev, &aa, audioprint);
399
400 /* get initial value (this is 0 and may be omitted but just in case) */
401 sc->sc_reg_misc = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
402 CMPCI_REG_MISC) & ~CMPCI_REG_SPDIF48K;
403
404 /* extra capabilities check */
405 d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_INTR_CTRL) &
406 CMPCI_REG_CHIP_MASK2;
407 if (d) {
408 if (d & CMPCI_REG_CHIP_8768) {
409 sc->sc_version = 68;
410 sc->sc_capable |= CMPCI_CAP_4CH | CMPCI_CAP_6CH |
411 CMPCI_CAP_8CH;
412 } else if (d & CMPCI_REG_CHIP_055) {
413 sc->sc_version = 55;
414 sc->sc_capable |= CMPCI_CAP_4CH | CMPCI_CAP_6CH;
415 } else if (d & CMPCI_REG_CHIP_039) {
416 sc->sc_version = 39;
417 sc->sc_capable |= CMPCI_CAP_4CH |
418 ((d & CMPCI_REG_CHIP_039_6CH) ? CMPCI_CAP_6CH : 0);
419 } else {
420 /* unknown version */
421 sc->sc_version = 0;
422 }
423 } else {
424 d = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
425 CMPCI_REG_CHANNEL_FORMAT) & CMPCI_REG_CHIP_MASK1;
426 if (d)
427 sc->sc_version = 37;
428 else
429 sc->sc_version = 33;
430 }
431
432 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0);
433 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0);
434 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0);
435 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX,
436 CMPCI_SB16_SW_CD|CMPCI_SB16_SW_MIC|CMPCI_SB16_SW_LINE);
437 for (i = 0; i < CMPCI_NDEVS; i++) {
438 switch(i) {
439 /*
440 * CMI8738 defaults are
441 * master: 0xe0 (0x00 - 0xf8)
442 * FM, DAC: 0xc0 (0x00 - 0xf8)
443 * PC speaker: 0x80 (0x00 - 0xc0)
444 * others: 0
445 */
446 /* volume */
447 case CMPCI_MASTER_VOL:
448 v = 128; /* 224 */
449 break;
450 case CMPCI_FM_VOL:
451 case CMPCI_DAC_VOL:
452 v = 192;
453 break;
454 case CMPCI_PCSPEAKER:
455 v = 128;
456 break;
457
458 /* booleans, set to true */
459 case CMPCI_CD_MUTE:
460 case CMPCI_MIC_MUTE:
461 case CMPCI_LINE_IN_MUTE:
462 case CMPCI_AUX_IN_MUTE:
463 v = 1;
464 break;
465
466 /* volume with initial value 0 */
467 case CMPCI_CD_VOL:
468 case CMPCI_LINE_IN_VOL:
469 case CMPCI_AUX_IN_VOL:
470 case CMPCI_MIC_VOL:
471 case CMPCI_MIC_RECVOL:
472 /* FALLTHROUGH */
473
474 /* others are cleared */
475 case CMPCI_MIC_PREAMP:
476 case CMPCI_RECORD_SOURCE:
477 case CMPCI_PLAYBACK_MODE:
478 case CMPCI_SPDIF_IN_SELECT:
479 case CMPCI_SPDIF_IN_PHASE:
480 case CMPCI_SPDIF_LOOP:
481 case CMPCI_SPDIF_OUT_PLAYBACK:
482 case CMPCI_SPDIF_OUT_VOLTAGE:
483 case CMPCI_MONITOR_DAC:
484 case CMPCI_REAR:
485 case CMPCI_INDIVIDUAL:
486 case CMPCI_REVERSE:
487 case CMPCI_SURROUND:
488 default:
489 v = 0;
490 break;
491 }
492 sc->sc_gain[i][CMPCI_LEFT] = sc->sc_gain[i][CMPCI_RIGHT] = v;
493 cmpci_set_mixer_gain(sc, i);
494 }
495
496 sc->sc_play_channel = 0;
497 }
498
499 int
cmpci_activate(struct device * self,int act)500 cmpci_activate(struct device *self, int act)
501 {
502 struct cmpci_softc *sc = (struct cmpci_softc *)self;
503
504 switch (act) {
505 case DVACT_RESUME:
506 cmpci_resume(sc);
507 break;
508 default:
509 break;
510 }
511 return (config_activate_children(self, act));
512 }
513
514 void
cmpci_resume(struct cmpci_softc * sc)515 cmpci_resume(struct cmpci_softc *sc)
516 {
517 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0);
518 }
519
520 int
cmpci_intr(void * handle)521 cmpci_intr(void *handle)
522 {
523 struct cmpci_softc *sc = handle;
524 struct cmpci_channel *chan;
525 uint32_t intrstat;
526 uint16_t hwpos;
527
528 mtx_enter(&audio_lock);
529 intrstat = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
530 CMPCI_REG_INTR_STATUS);
531
532 if (!(intrstat & CMPCI_REG_ANY_INTR)) {
533 mtx_leave(&audio_lock);
534 return 0;
535 }
536
537 delay(10);
538
539 /* disable and reset intr */
540 if (intrstat & CMPCI_REG_CH0_INTR)
541 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
542 CMPCI_REG_CH0_INTR_ENABLE);
543 if (intrstat & CMPCI_REG_CH1_INTR)
544 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
545 CMPCI_REG_CH1_INTR_ENABLE);
546
547 if (intrstat & CMPCI_REG_CH0_INTR) {
548 chan = &sc->sc_ch0;
549 if (chan->intr != NULL) {
550 hwpos = bus_space_read_2(sc->sc_iot, sc->sc_ioh,
551 CMPCI_REG_DMA0_BYTES);
552 hwpos = hwpos * chan->bps / chan->blksize;
553 hwpos = chan->nblocks - hwpos - 1;
554 while (chan->swpos != hwpos) {
555 (*chan->intr)(chan->intr_arg);
556 chan->swpos++;
557 if (chan->swpos >= chan->nblocks)
558 chan->swpos = 0;
559 if (chan->swpos != hwpos) {
560 DPRINTF(("%s: DMA0 hwpos=%d swpos=%d\n",
561 __func__, hwpos, chan->swpos));
562 }
563 }
564 }
565 }
566 if (intrstat & CMPCI_REG_CH1_INTR) {
567 chan = &sc->sc_ch1;
568 if (chan->intr != NULL) {
569 hwpos = bus_space_read_2(sc->sc_iot, sc->sc_ioh,
570 CMPCI_REG_DMA1_BYTES);
571 hwpos = hwpos * chan->bps / chan->blksize;
572 hwpos = chan->nblocks - hwpos - 1;
573 while (chan->swpos != hwpos) {
574 (*chan->intr)(chan->intr_arg);
575 chan->swpos++;
576 if (chan->swpos >= chan->nblocks)
577 chan->swpos = 0;
578 if (chan->swpos != hwpos) {
579 DPRINTF(("%s: DMA1 hwpos=%d swpos=%d\n",
580 __func__, hwpos, chan->swpos));
581 }
582 }
583 }
584 }
585
586 /* enable intr */
587 if (intrstat & CMPCI_REG_CH0_INTR)
588 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
589 CMPCI_REG_CH0_INTR_ENABLE);
590 if (intrstat & CMPCI_REG_CH1_INTR)
591 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
592 CMPCI_REG_CH1_INTR_ENABLE);
593
594 #if 0
595 if (intrstat & CMPCI_REG_UART_INTR && sc->sc_mpudev != NULL)
596 mpu_intr(sc->sc_mpudev);
597 #endif
598
599 mtx_leave(&audio_lock);
600 return 1;
601 }
602
603 /* open/close */
604 int
cmpci_open(void * handle,int flags)605 cmpci_open(void *handle, int flags)
606 {
607 return 0;
608 }
609
610 void
cmpci_close(void * handle)611 cmpci_close(void *handle)
612 {
613 }
614
615 int
cmpci_set_params(void * handle,int setmode,int usemode,struct audio_params * play,struct audio_params * rec)616 cmpci_set_params(void *handle, int setmode, int usemode,
617 struct audio_params *play, struct audio_params *rec)
618 {
619 int i;
620 struct cmpci_softc *sc = handle;
621
622 for (i = 0; i < 2; i++) {
623 int md_format;
624 int md_divide;
625 int md_index;
626 int mode;
627 struct audio_params *p;
628
629 switch (i) {
630 case 0:
631 mode = AUMODE_PLAY;
632 p = play;
633 break;
634 case 1:
635 mode = AUMODE_RECORD;
636 p = rec;
637 break;
638 default:
639 return EINVAL;
640 }
641
642 if (!(setmode & mode))
643 continue;
644
645 if (setmode & AUMODE_RECORD) {
646 if (p->channels > 2)
647 p->channels = 2;
648 sc->sc_play_channel = 0;
649 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_ENDBDAC);
650 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_XCHGDAC);
651 } else {
652 sc->sc_play_channel = 1;
653 cmpci_reg_set_reg_misc(sc, CMPCI_REG_ENDBDAC);
654 cmpci_reg_set_reg_misc(sc, CMPCI_REG_XCHGDAC);
655 }
656
657 cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
658 CMPCI_REG_NXCHG);
659 if (sc->sc_capable & CMPCI_CAP_4CH)
660 cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT,
661 CMPCI_REG_CHB3D);
662 if (sc->sc_capable & CMPCI_CAP_6CH) {
663 cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT,
664 CMPCI_REG_CHB3D5C);
665 cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
666 CMPCI_REG_CHB3D6C);
667 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_ENCENTER);
668 }
669 if (sc->sc_capable & CMPCI_CAP_8CH)
670 cmpci_reg_clear_4(sc, CMPCI_REG_8768_MISC,
671 CMPCI_REG_CHB3D8C);
672
673 /* format */
674 switch (p->channels) {
675 case 1:
676 md_format = CMPCI_REG_FORMAT_MONO;
677 break;
678 case 2:
679 md_format = CMPCI_REG_FORMAT_STEREO;
680 break;
681 case 4:
682 if (mode & AUMODE_PLAY) {
683 if (sc->sc_capable & CMPCI_CAP_4CH) {
684 cmpci_reg_clear_reg_misc(sc,
685 CMPCI_REG_N4SPK3D);
686 cmpci_reg_set_4(sc,
687 CMPCI_REG_CHANNEL_FORMAT,
688 CMPCI_REG_CHB3D);
689 cmpci_reg_set_4(sc,
690 CMPCI_REG_LEGACY_CTRL,
691 CMPCI_REG_NXCHG);
692 } else
693 p->channels = 2;
694 }
695 md_format = CMPCI_REG_FORMAT_STEREO;
696 break;
697 case 6:
698 if (mode & AUMODE_PLAY) {
699 if (sc->sc_capable & CMPCI_CAP_6CH) {
700 cmpci_reg_clear_reg_misc(sc,
701 CMPCI_REG_N4SPK3D);
702 cmpci_reg_set_4(sc,
703 CMPCI_REG_CHANNEL_FORMAT,
704 CMPCI_REG_CHB3D5C);
705 cmpci_reg_set_4(sc,
706 CMPCI_REG_LEGACY_CTRL,
707 CMPCI_REG_CHB3D6C);
708 cmpci_reg_set_reg_misc(sc,
709 CMPCI_REG_ENCENTER);
710 cmpci_reg_set_4(sc,
711 CMPCI_REG_LEGACY_CTRL,
712 CMPCI_REG_NXCHG);
713 } else
714 p->channels = 2;
715 }
716 md_format = CMPCI_REG_FORMAT_STEREO;
717 break;
718 case 8:
719 if (mode & AUMODE_PLAY) {
720 if (sc->sc_capable & CMPCI_CAP_8CH) {
721 cmpci_reg_clear_reg_misc(sc,
722 CMPCI_REG_N4SPK3D);
723 cmpci_reg_set_4(sc,
724 CMPCI_REG_CHANNEL_FORMAT,
725 CMPCI_REG_CHB3D5C);
726 cmpci_reg_set_4(sc,
727 CMPCI_REG_LEGACY_CTRL,
728 CMPCI_REG_CHB3D6C);
729 cmpci_reg_set_reg_misc(sc,
730 CMPCI_REG_ENCENTER);
731 cmpci_reg_set_4(sc,
732 CMPCI_REG_8768_MISC,
733 CMPCI_REG_CHB3D8C);
734 cmpci_reg_set_4(sc,
735 CMPCI_REG_LEGACY_CTRL,
736 CMPCI_REG_NXCHG);
737 } else
738 p->channels = 2;
739 }
740 md_format = CMPCI_REG_FORMAT_STEREO;
741 break;
742 default:
743 return (EINVAL);
744 }
745 if (p->precision >= 16) {
746 p->precision = 16;
747 p->encoding = AUDIO_ENCODING_SLINEAR_LE;
748 md_format |= CMPCI_REG_FORMAT_16BIT;
749 } else {
750 p->precision = 8;
751 p->encoding = AUDIO_ENCODING_ULINEAR_LE;
752 md_format |= CMPCI_REG_FORMAT_8BIT;
753 }
754 p->bps = AUDIO_BPS(p->precision);
755 p->msb = 1;
756 if (mode & AUMODE_PLAY) {
757 if (sc->sc_play_channel == 1) {
758 cmpci_reg_partial_write_4(sc,
759 CMPCI_REG_CHANNEL_FORMAT,
760 CMPCI_REG_CH1_FORMAT_SHIFT,
761 CMPCI_REG_CH1_FORMAT_MASK, md_format);
762 } else {
763 cmpci_reg_partial_write_4(sc,
764 CMPCI_REG_CHANNEL_FORMAT,
765 CMPCI_REG_CH0_FORMAT_SHIFT,
766 CMPCI_REG_CH0_FORMAT_MASK, md_format);
767 }
768 } else {
769 cmpci_reg_partial_write_4(sc,
770 CMPCI_REG_CHANNEL_FORMAT,
771 CMPCI_REG_CH1_FORMAT_SHIFT,
772 CMPCI_REG_CH1_FORMAT_MASK, md_format);
773 }
774 /* sample rate */
775 md_index = cmpci_rate_to_index(p->sample_rate);
776 md_divide = cmpci_index_to_divider(md_index);
777 p->sample_rate = cmpci_index_to_rate(md_index);
778 DPRINTF(("%s: sample:%d, divider=%d\n",
779 sc->sc_dev.dv_xname, (int)p->sample_rate, md_divide));
780 if (mode & AUMODE_PLAY) {
781 if (sc->sc_play_channel == 1) {
782 cmpci_reg_partial_write_4(sc,
783 CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT,
784 CMPCI_REG_ADC_FS_MASK, md_divide);
785 sc->sc_ch1.md_divide = md_divide;
786 } else {
787 cmpci_reg_partial_write_4(sc,
788 CMPCI_REG_FUNC_1, CMPCI_REG_DAC_FS_SHIFT,
789 CMPCI_REG_DAC_FS_MASK, md_divide);
790 sc->sc_ch0.md_divide = md_divide;
791 }
792 } else {
793 cmpci_reg_partial_write_4(sc,
794 CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT,
795 CMPCI_REG_ADC_FS_MASK, md_divide);
796 sc->sc_ch1.md_divide = md_divide;
797 }
798 }
799
800 return 0;
801 }
802
803 int
cmpci_round_blocksize(void * handle,int block)804 cmpci_round_blocksize(void *handle, int block)
805 {
806 return ((block + 3) & -4);
807 }
808
809 int
cmpci_halt_output(void * handle)810 cmpci_halt_output(void *handle)
811 {
812 struct cmpci_softc *sc = handle;
813 uint32_t reg_intr, reg_enable, reg_reset;
814
815 mtx_enter(&audio_lock);
816 if (sc->sc_play_channel == 1) {
817 sc->sc_ch1.intr = NULL;
818 reg_intr = CMPCI_REG_CH1_INTR_ENABLE;
819 reg_enable = CMPCI_REG_CH1_ENABLE;
820 reg_reset = CMPCI_REG_CH1_RESET;
821 } else {
822 sc->sc_ch0.intr = NULL;
823 reg_intr = CMPCI_REG_CH0_INTR_ENABLE;
824 reg_enable = CMPCI_REG_CH0_ENABLE;
825 reg_reset = CMPCI_REG_CH0_RESET;
826 }
827 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, reg_intr);
828 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_enable);
829 /* wait for reset DMA */
830 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, reg_reset);
831 delay(10);
832 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_reset);
833 mtx_leave(&audio_lock);
834 return 0;
835 }
836
837 int
cmpci_halt_input(void * handle)838 cmpci_halt_input(void *handle)
839 {
840 struct cmpci_softc *sc = handle;
841
842 mtx_enter(&audio_lock);
843 sc->sc_ch1.intr = NULL;
844 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
845 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
846 /* wait for reset DMA */
847 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
848 delay(10);
849 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
850 mtx_leave(&audio_lock);
851 return 0;
852 }
853
854 /* mixer device information */
855 int
cmpci_query_devinfo(void * handle,mixer_devinfo_t * dip)856 cmpci_query_devinfo(void *handle, mixer_devinfo_t *dip)
857 {
858 static const char *const mixer_port_names[] = {
859 AudioNdac, AudioNfmsynth, AudioNcd, AudioNline, AudioNaux,
860 AudioNmicrophone
861 };
862 static const char *const mixer_classes[] = {
863 AudioCinputs, AudioCoutputs, AudioCrecord, CmpciCplayback,
864 CmpciCspdif
865 };
866 struct cmpci_softc *sc = handle;
867 int i;
868
869 dip->prev = dip->next = AUDIO_MIXER_LAST;
870
871 switch (dip->index) {
872 case CMPCI_INPUT_CLASS:
873 case CMPCI_OUTPUT_CLASS:
874 case CMPCI_RECORD_CLASS:
875 case CMPCI_PLAYBACK_CLASS:
876 case CMPCI_SPDIF_CLASS:
877 dip->type = AUDIO_MIXER_CLASS;
878 dip->mixer_class = dip->index;
879 strlcpy(dip->label.name,
880 mixer_classes[dip->index - CMPCI_INPUT_CLASS],
881 sizeof dip->label.name);
882 return 0;
883
884 case CMPCI_AUX_IN_VOL:
885 dip->un.v.delta = 1 << (8 - CMPCI_REG_AUX_VALBITS);
886 goto vol1;
887 case CMPCI_DAC_VOL:
888 case CMPCI_FM_VOL:
889 case CMPCI_CD_VOL:
890 case CMPCI_LINE_IN_VOL:
891 case CMPCI_MIC_VOL:
892 dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_VALBITS);
893 vol1: dip->mixer_class = CMPCI_INPUT_CLASS;
894 dip->next = dip->index + 6; /* CMPCI_xxx_MUTE */
895 strlcpy(dip->label.name, mixer_port_names[dip->index],
896 sizeof dip->label.name);
897 dip->un.v.num_channels = (dip->index == CMPCI_MIC_VOL ? 1 : 2);
898 vol:
899 dip->type = AUDIO_MIXER_VALUE;
900 strlcpy(dip->un.v.units.name, AudioNvolume,
901 sizeof dip->un.v.units.name);
902 return 0;
903
904 case CMPCI_MIC_MUTE:
905 dip->next = CMPCI_MIC_PREAMP;
906 /* FALLTHROUGH */
907 case CMPCI_DAC_MUTE:
908 case CMPCI_FM_MUTE:
909 case CMPCI_CD_MUTE:
910 case CMPCI_LINE_IN_MUTE:
911 case CMPCI_AUX_IN_MUTE:
912 dip->prev = dip->index - 6; /* CMPCI_xxx_VOL */
913 dip->mixer_class = CMPCI_INPUT_CLASS;
914 strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
915 goto on_off;
916 on_off:
917 dip->type = AUDIO_MIXER_ENUM;
918 dip->un.e.num_mem = 2;
919 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
920 sizeof dip->un.e.member[0].label.name);
921 dip->un.e.member[0].ord = 0;
922 strlcpy(dip->un.e.member[1].label.name, AudioNon,
923 sizeof dip->un.e.member[1].label.name);
924 dip->un.e.member[1].ord = 1;
925 return 0;
926
927 case CMPCI_MIC_PREAMP:
928 dip->mixer_class = CMPCI_INPUT_CLASS;
929 dip->prev = CMPCI_MIC_MUTE;
930 strlcpy(dip->label.name, AudioNpreamp, sizeof dip->label.name);
931 goto on_off;
932 case CMPCI_PCSPEAKER:
933 dip->mixer_class = CMPCI_INPUT_CLASS;
934 strlcpy(dip->label.name, AudioNspeaker, sizeof dip->label.name);
935 dip->un.v.num_channels = 1;
936 dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_SPEAKER_VALBITS);
937 goto vol;
938 case CMPCI_RECORD_SOURCE:
939 dip->mixer_class = CMPCI_RECORD_CLASS;
940 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
941 dip->type = AUDIO_MIXER_SET;
942 dip->un.s.num_mem = 7;
943 strlcpy(dip->un.s.member[0].label.name, AudioNmicrophone,
944 sizeof dip->un.s.member[0].label.name);
945 dip->un.s.member[0].mask = CMPCI_RECORD_SOURCE_MIC;
946 strlcpy(dip->un.s.member[1].label.name, AudioNcd,
947 sizeof dip->un.s.member[1].label.name);
948 dip->un.s.member[1].mask = CMPCI_RECORD_SOURCE_CD;
949 strlcpy(dip->un.s.member[2].label.name, AudioNline,
950 sizeof dip->un.s.member[2].label.name);
951 dip->un.s.member[2].mask = CMPCI_RECORD_SOURCE_LINE_IN;
952 strlcpy(dip->un.s.member[3].label.name, AudioNaux,
953 sizeof dip->un.s.member[3].label.name);
954 dip->un.s.member[3].mask = CMPCI_RECORD_SOURCE_AUX_IN;
955 strlcpy(dip->un.s.member[4].label.name, AudioNwave,
956 sizeof dip->un.s.member[4].label.name);
957 dip->un.s.member[4].mask = CMPCI_RECORD_SOURCE_WAVE;
958 strlcpy(dip->un.s.member[5].label.name, AudioNfmsynth,
959 sizeof dip->un.s.member[5].label.name);
960 dip->un.s.member[5].mask = CMPCI_RECORD_SOURCE_FM;
961 strlcpy(dip->un.s.member[6].label.name, CmpciNspdif,
962 sizeof dip->un.s.member[6].label.name);
963 dip->un.s.member[6].mask = CMPCI_RECORD_SOURCE_SPDIF;
964 return 0;
965 case CMPCI_MIC_RECVOL:
966 dip->mixer_class = CMPCI_RECORD_CLASS;
967 strlcpy(dip->label.name, AudioNmicrophone, sizeof dip->label.name);
968 dip->un.v.num_channels = 1;
969 dip->un.v.delta = 1 << (8 - CMPCI_REG_ADMIC_VALBITS);
970 goto vol;
971
972 case CMPCI_PLAYBACK_MODE:
973 dip->mixer_class = CMPCI_PLAYBACK_CLASS;
974 dip->type = AUDIO_MIXER_ENUM;
975 strlcpy(dip->label.name, AudioNmode, sizeof dip->label.name);
976 dip->un.e.num_mem = 2;
977 strlcpy(dip->un.e.member[0].label.name, AudioNdac,
978 sizeof dip->un.e.member[0].label.name);
979 dip->un.e.member[0].ord = CMPCI_PLAYBACK_MODE_WAVE;
980 strlcpy(dip->un.e.member[1].label.name, CmpciNspdif,
981 sizeof dip->un.e.member[1].label.name);
982 dip->un.e.member[1].ord = CMPCI_PLAYBACK_MODE_SPDIF;
983 return 0;
984 case CMPCI_SPDIF_IN_SELECT:
985 dip->mixer_class = CMPCI_SPDIF_CLASS;
986 dip->type = AUDIO_MIXER_ENUM;
987 dip->next = CMPCI_SPDIF_IN_PHASE;
988 strlcpy(dip->label.name, AudioNinput, sizeof dip->label.name);
989 i = 0;
990 strlcpy(dip->un.e.member[i].label.name, CmpciNspdin1,
991 sizeof dip->un.e.member[i].label.name);
992 dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDIN1;
993 if (CMPCI_ISCAP(sc, 2ND_SPDIN)) {
994 strlcpy(dip->un.e.member[i].label.name, CmpciNspdin2,
995 sizeof dip->un.e.member[i].label.name);
996 dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDIN2;
997 }
998 strlcpy(dip->un.e.member[i].label.name, CmpciNspdout,
999 sizeof dip->un.e.member[i].label.name);
1000 dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDOUT;
1001 dip->un.e.num_mem = i;
1002 return 0;
1003 case CMPCI_SPDIF_IN_PHASE:
1004 dip->mixer_class = CMPCI_SPDIF_CLASS;
1005 dip->prev = CMPCI_SPDIF_IN_SELECT;
1006 strlcpy(dip->label.name, CmpciNphase, sizeof dip->label.name);
1007 dip->type = AUDIO_MIXER_ENUM;
1008 dip->un.e.num_mem = 2;
1009 strlcpy(dip->un.e.member[0].label.name, CmpciNpositive,
1010 sizeof dip->un.e.member[0].label.name);
1011 dip->un.e.member[0].ord = CMPCI_SPDIF_IN_PHASE_POSITIVE;
1012 strlcpy(dip->un.e.member[1].label.name, CmpciNnegative,
1013 sizeof dip->un.e.member[1].label.name);
1014 dip->un.e.member[1].ord = CMPCI_SPDIF_IN_PHASE_NEGATIVE;
1015 return 0;
1016 case CMPCI_SPDIF_LOOP:
1017 dip->mixer_class = CMPCI_SPDIF_CLASS;
1018 dip->next = CMPCI_SPDIF_OUT_PLAYBACK;
1019 strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
1020 dip->type = AUDIO_MIXER_ENUM;
1021 dip->un.e.num_mem = 2;
1022 strlcpy(dip->un.e.member[0].label.name, CmpciNplayback,
1023 sizeof dip->un.e.member[0].label.name);
1024 dip->un.e.member[0].ord = CMPCI_SPDIF_LOOP_OFF;
1025 strlcpy(dip->un.e.member[1].label.name, CmpciNspdin,
1026 sizeof dip->un.e.member[1].label.name);
1027 dip->un.e.member[1].ord = CMPCI_SPDIF_LOOP_ON;
1028 return 0;
1029 case CMPCI_SPDIF_OUT_PLAYBACK:
1030 dip->mixer_class = CMPCI_SPDIF_CLASS;
1031 dip->prev = CMPCI_SPDIF_LOOP;
1032 dip->next = CMPCI_SPDIF_OUT_VOLTAGE;
1033 strlcpy(dip->label.name, CmpciNplayback, sizeof dip->label.name);
1034 dip->type = AUDIO_MIXER_ENUM;
1035 dip->un.e.num_mem = 2;
1036 strlcpy(dip->un.e.member[0].label.name, AudioNwave,
1037 sizeof dip->un.e.member[0].label.name);
1038 dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_PLAYBACK_WAVE;
1039 strlcpy(dip->un.e.member[1].label.name, CmpciNlegacy,
1040 sizeof dip->un.e.member[1].label.name);
1041 dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_PLAYBACK_LEGACY;
1042 return 0;
1043 case CMPCI_SPDIF_OUT_VOLTAGE:
1044 dip->mixer_class = CMPCI_SPDIF_CLASS;
1045 dip->prev = CMPCI_SPDIF_OUT_PLAYBACK;
1046 strlcpy(dip->label.name, CmpciNvoltage, sizeof dip->label.name);
1047 dip->type = AUDIO_MIXER_ENUM;
1048 dip->un.e.num_mem = 2;
1049 strlcpy(dip->un.e.member[0].label.name, CmpciNhigh_v,
1050 sizeof dip->un.e.member[0].label.name);
1051 dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_VOLTAGE_HIGH;
1052 strlcpy(dip->un.e.member[1].label.name, CmpciNlow_v,
1053 sizeof dip->un.e.member[1].label.name);
1054 dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_VOLTAGE_LOW;
1055 return 0;
1056 case CMPCI_MONITOR_DAC:
1057 dip->mixer_class = CMPCI_SPDIF_CLASS;
1058 strlcpy(dip->label.name, AudioNmonitor, sizeof dip->label.name);
1059 dip->type = AUDIO_MIXER_ENUM;
1060 dip->un.e.num_mem = 3;
1061 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
1062 sizeof dip->un.e.member[0].label.name);
1063 dip->un.e.member[0].ord = CMPCI_MONITOR_DAC_OFF;
1064 strlcpy(dip->un.e.member[1].label.name, CmpciNspdin,
1065 sizeof dip->un.e.member[1].label.name);
1066 dip->un.e.member[1].ord = CMPCI_MONITOR_DAC_SPDIN;
1067 strlcpy(dip->un.e.member[2].label.name, CmpciNspdout,
1068 sizeof dip->un.e.member[2].label.name);
1069 dip->un.e.member[2].ord = CMPCI_MONITOR_DAC_SPDOUT;
1070 return 0;
1071
1072 case CMPCI_MASTER_VOL:
1073 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1074 strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
1075 dip->un.v.num_channels = 2;
1076 dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_VALBITS);
1077 goto vol;
1078 case CMPCI_REAR:
1079 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1080 dip->next = CMPCI_INDIVIDUAL;
1081 strlcpy(dip->label.name, CmpciNrear, sizeof dip->label.name);
1082 goto on_off;
1083 case CMPCI_INDIVIDUAL:
1084 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1085 dip->prev = CMPCI_REAR;
1086 dip->next = CMPCI_REVERSE;
1087 strlcpy(dip->label.name, CmpciNindividual, sizeof dip->label.name);
1088 goto on_off;
1089 case CMPCI_REVERSE:
1090 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1091 dip->prev = CMPCI_INDIVIDUAL;
1092 strlcpy(dip->label.name, CmpciNreverse, sizeof dip->label.name);
1093 goto on_off;
1094 case CMPCI_SURROUND:
1095 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1096 strlcpy(dip->label.name, CmpciNsurround, sizeof dip->label.name);
1097 goto on_off;
1098 }
1099
1100 return ENXIO;
1101 }
1102
1103 int
cmpci_alloc_dmamem(struct cmpci_softc * sc,size_t size,int type,int flags,caddr_t * r_addr)1104 cmpci_alloc_dmamem(struct cmpci_softc *sc, size_t size, int type, int flags,
1105 caddr_t *r_addr)
1106 {
1107 int error = 0;
1108 struct cmpci_dmanode *n;
1109 int w;
1110
1111 n = malloc(sizeof(struct cmpci_dmanode), type, flags);
1112 if (n == NULL) {
1113 error = ENOMEM;
1114 goto quit;
1115 }
1116
1117 w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
1118 #define CMPCI_DMABUF_ALIGN 0x4
1119 #define CMPCI_DMABUF_BOUNDARY 0x0
1120 n->cd_tag = sc->sc_dmat;
1121 n->cd_size = size;
1122 error = bus_dmamem_alloc(n->cd_tag, n->cd_size,
1123 CMPCI_DMABUF_ALIGN, CMPCI_DMABUF_BOUNDARY, n->cd_segs,
1124 nitems(n->cd_segs), &n->cd_nsegs, w);
1125 if (error)
1126 goto mfree;
1127 error = bus_dmamem_map(n->cd_tag, n->cd_segs, n->cd_nsegs, n->cd_size,
1128 &n->cd_addr, w | BUS_DMA_COHERENT);
1129 if (error)
1130 goto dmafree;
1131 error = bus_dmamap_create(n->cd_tag, n->cd_size, 1, n->cd_size, 0,
1132 w, &n->cd_map);
1133 if (error)
1134 goto unmap;
1135 error = bus_dmamap_load(n->cd_tag, n->cd_map, n->cd_addr, n->cd_size,
1136 NULL, w);
1137 if (error)
1138 goto destroy;
1139
1140 n->cd_next = sc->sc_dmap;
1141 sc->sc_dmap = n;
1142 *r_addr = KVADDR(n);
1143 return 0;
1144
1145 destroy:
1146 bus_dmamap_destroy(n->cd_tag, n->cd_map);
1147 unmap:
1148 bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
1149 dmafree:
1150 bus_dmamem_free(n->cd_tag,
1151 n->cd_segs, nitems(n->cd_segs));
1152 mfree:
1153 free(n, type, 0);
1154 quit:
1155 return error;
1156 }
1157
1158 int
cmpci_free_dmamem(struct cmpci_softc * sc,caddr_t addr,int type)1159 cmpci_free_dmamem(struct cmpci_softc *sc, caddr_t addr, int type)
1160 {
1161 struct cmpci_dmanode **nnp;
1162
1163 for (nnp = &sc->sc_dmap; *nnp; nnp = &(*nnp)->cd_next) {
1164 if ((*nnp)->cd_addr == addr) {
1165 struct cmpci_dmanode *n = *nnp;
1166 bus_dmamap_unload(n->cd_tag, n->cd_map);
1167 bus_dmamap_destroy(n->cd_tag, n->cd_map);
1168 bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
1169 bus_dmamem_free(n->cd_tag, n->cd_segs,
1170 nitems(n->cd_segs));
1171 free(n, type, 0);
1172 return 0;
1173 }
1174 }
1175 return -1;
1176 }
1177
1178 struct cmpci_dmanode *
cmpci_find_dmamem(struct cmpci_softc * sc,caddr_t addr)1179 cmpci_find_dmamem(struct cmpci_softc *sc, caddr_t addr)
1180 {
1181 struct cmpci_dmanode *p;
1182
1183 for (p = sc->sc_dmap; p; p = p->cd_next) {
1184 if (KVADDR(p) == (void *)addr)
1185 break;
1186 }
1187 return p;
1188 }
1189
1190 #if 0
1191 void cmpci_print_dmamem(struct cmpci_dmanode *p);
1192
1193 void
1194 cmpci_print_dmamem(struct cmpci_dmanode *p)
1195 {
1196 DPRINTF(("DMA at virt:%p, dmaseg:%p, mapseg:%p, size:%p\n",
1197 (void *)p->cd_addr, (void *)p->cd_segs[0].ds_addr,
1198 (void *)DMAADDR(p), (void *)p->cd_size));
1199 }
1200 #endif /* DEBUG */
1201
1202 void *
cmpci_malloc(void * handle,int direction,size_t size,int type,int flags)1203 cmpci_malloc(void *handle, int direction, size_t size, int type,
1204 int flags)
1205 {
1206 caddr_t addr;
1207
1208 if (cmpci_alloc_dmamem(handle, size, type, flags, &addr))
1209 return NULL;
1210 return addr;
1211 }
1212
1213 void
cmpci_free(void * handle,void * addr,int type)1214 cmpci_free(void *handle, void *addr, int type)
1215 {
1216 cmpci_free_dmamem(handle, addr, type);
1217 }
1218
1219 #define MAXVAL 256
1220 int
cmpci_adjust(int val,int mask)1221 cmpci_adjust(int val, int mask)
1222 {
1223 val += (MAXVAL - mask) >> 1;
1224 if (val >= MAXVAL)
1225 val = MAXVAL-1;
1226 return val & mask;
1227 }
1228
1229 void
cmpci_set_mixer_gain(struct cmpci_softc * sc,int port)1230 cmpci_set_mixer_gain(struct cmpci_softc *sc, int port)
1231 {
1232 int src;
1233 int bits, mask;
1234
1235 switch (port) {
1236 case CMPCI_MIC_VOL:
1237 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_MIC,
1238 CMPCI_ADJUST_MIC_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
1239 return;
1240 case CMPCI_MASTER_VOL:
1241 src = CMPCI_SB16_MIXER_MASTER_L;
1242 break;
1243 case CMPCI_LINE_IN_VOL:
1244 src = CMPCI_SB16_MIXER_LINE_L;
1245 break;
1246 case CMPCI_AUX_IN_VOL:
1247 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MIXER_AUX,
1248 CMPCI_ADJUST_AUX_GAIN(sc, sc->sc_gain[port][CMPCI_LEFT],
1249 sc->sc_gain[port][CMPCI_RIGHT]));
1250 return;
1251 case CMPCI_MIC_RECVOL:
1252 cmpci_reg_partial_write_1(sc, CMPCI_REG_MIXER25,
1253 CMPCI_REG_ADMIC_SHIFT, CMPCI_REG_ADMIC_MASK,
1254 CMPCI_ADJUST_ADMIC_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
1255 return;
1256 case CMPCI_DAC_VOL:
1257 src = CMPCI_SB16_MIXER_VOICE_L;
1258 break;
1259 case CMPCI_FM_VOL:
1260 src = CMPCI_SB16_MIXER_FM_L;
1261 break;
1262 case CMPCI_CD_VOL:
1263 src = CMPCI_SB16_MIXER_CDDA_L;
1264 break;
1265 case CMPCI_PCSPEAKER:
1266 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_SPEAKER,
1267 CMPCI_ADJUST_2_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
1268 return;
1269 case CMPCI_MIC_PREAMP:
1270 if (sc->sc_gain[port][CMPCI_LR])
1271 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
1272 CMPCI_REG_MICGAINZ);
1273 else
1274 cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
1275 CMPCI_REG_MICGAINZ);
1276 return;
1277
1278 case CMPCI_DAC_MUTE:
1279 if (sc->sc_gain[port][CMPCI_LR])
1280 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1281 CMPCI_REG_WSMUTE);
1282 else
1283 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1284 CMPCI_REG_WSMUTE);
1285 return;
1286 case CMPCI_FM_MUTE:
1287 if (sc->sc_gain[port][CMPCI_LR])
1288 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1289 CMPCI_REG_FMMUTE);
1290 else
1291 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1292 CMPCI_REG_FMMUTE);
1293 return;
1294 case CMPCI_AUX_IN_MUTE:
1295 if (sc->sc_gain[port][CMPCI_LR])
1296 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
1297 CMPCI_REG_VAUXRM|CMPCI_REG_VAUXLM);
1298 else
1299 cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
1300 CMPCI_REG_VAUXRM|CMPCI_REG_VAUXLM);
1301 return;
1302 case CMPCI_CD_MUTE:
1303 mask = CMPCI_SB16_SW_CD;
1304 goto sbmute;
1305 case CMPCI_MIC_MUTE:
1306 mask = CMPCI_SB16_SW_MIC;
1307 goto sbmute;
1308 case CMPCI_LINE_IN_MUTE:
1309 mask = CMPCI_SB16_SW_LINE;
1310 sbmute:
1311 bits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_OUTMIX);
1312 if (sc->sc_gain[port][CMPCI_LR])
1313 bits = bits & ~mask;
1314 else
1315 bits = bits | mask;
1316 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, bits);
1317 return;
1318
1319 case CMPCI_SPDIF_IN_SELECT:
1320 case CMPCI_MONITOR_DAC:
1321 case CMPCI_PLAYBACK_MODE:
1322 case CMPCI_SPDIF_LOOP:
1323 case CMPCI_SPDIF_OUT_PLAYBACK:
1324 cmpci_set_out_ports(sc);
1325 return;
1326 case CMPCI_SPDIF_OUT_VOLTAGE:
1327 if (CMPCI_ISCAP(sc, SPDOUT_VOLTAGE)) {
1328 if (sc->sc_gain[CMPCI_SPDIF_OUT_VOLTAGE][CMPCI_LR]
1329 == CMPCI_SPDIF_OUT_VOLTAGE_HIGH)
1330 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_5V);
1331 else
1332 cmpci_reg_set_reg_misc(sc, CMPCI_REG_5V);
1333 }
1334 return;
1335 case CMPCI_SURROUND:
1336 if (CMPCI_ISCAP(sc, SURROUND)) {
1337 if (sc->sc_gain[CMPCI_SURROUND][CMPCI_LR])
1338 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1339 CMPCI_REG_SURROUND);
1340 else
1341 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1342 CMPCI_REG_SURROUND);
1343 }
1344 return;
1345 case CMPCI_REAR:
1346 if (CMPCI_ISCAP(sc, REAR)) {
1347 if (sc->sc_gain[CMPCI_REAR][CMPCI_LR])
1348 cmpci_reg_set_reg_misc(sc, CMPCI_REG_N4SPK3D);
1349 else
1350 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_N4SPK3D);
1351 }
1352 return;
1353 case CMPCI_INDIVIDUAL:
1354 if (CMPCI_ISCAP(sc, INDIVIDUAL_REAR)) {
1355 if (sc->sc_gain[CMPCI_REAR][CMPCI_LR])
1356 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1357 CMPCI_REG_INDIVIDUAL);
1358 else
1359 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1360 CMPCI_REG_INDIVIDUAL);
1361 }
1362 return;
1363 case CMPCI_REVERSE:
1364 if (CMPCI_ISCAP(sc, REVERSE_FR)) {
1365 if (sc->sc_gain[CMPCI_REVERSE][CMPCI_LR])
1366 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1367 CMPCI_REG_REVERSE_FR);
1368 else
1369 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1370 CMPCI_REG_REVERSE_FR);
1371 }
1372 return;
1373 case CMPCI_SPDIF_IN_PHASE:
1374 if (CMPCI_ISCAP(sc, SPDIN_PHASE)) {
1375 if (sc->sc_gain[CMPCI_SPDIF_IN_PHASE][CMPCI_LR]
1376 == CMPCI_SPDIF_IN_PHASE_POSITIVE)
1377 cmpci_reg_clear_1(sc, CMPCI_REG_CHANNEL_FORMAT,
1378 CMPCI_REG_SPDIN_PHASE);
1379 else
1380 cmpci_reg_set_1(sc, CMPCI_REG_CHANNEL_FORMAT,
1381 CMPCI_REG_SPDIN_PHASE);
1382 }
1383 return;
1384 default:
1385 return;
1386 }
1387
1388 cmpci_mixerreg_write(sc, src,
1389 CMPCI_ADJUST_GAIN(sc, sc->sc_gain[port][CMPCI_LEFT]));
1390 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_L_TO_R(src),
1391 CMPCI_ADJUST_GAIN(sc, sc->sc_gain[port][CMPCI_RIGHT]));
1392 }
1393
1394 void
cmpci_set_out_ports(struct cmpci_softc * sc)1395 cmpci_set_out_ports(struct cmpci_softc *sc)
1396 {
1397 struct cmpci_channel *chan;
1398 u_int8_t v;
1399 int enspdout = 0;
1400
1401 if (!CMPCI_ISCAP(sc, SPDLOOP))
1402 return;
1403
1404 /* SPDIF/out select */
1405 if (sc->sc_gain[CMPCI_SPDIF_LOOP][CMPCI_LR] == CMPCI_SPDIF_LOOP_OFF) {
1406 /* playback */
1407 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP);
1408 } else {
1409 /* monitor SPDIF/in */
1410 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP);
1411 }
1412
1413 /* SPDIF in select */
1414 v = sc->sc_gain[CMPCI_SPDIF_IN_SELECT][CMPCI_LR];
1415 if (v & CMPCI_SPDIFIN_SPDIFIN2)
1416 cmpci_reg_set_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN);
1417 else
1418 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN);
1419 if (v & CMPCI_SPDIFIN_SPDIFOUT)
1420 cmpci_reg_set_reg_misc(sc, CMPCI_REG_SPDFLOOPI);
1421 else
1422 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_SPDFLOOPI);
1423
1424 if (sc->sc_play_channel == 1)
1425 chan = &sc->sc_ch1;
1426 else
1427 chan = &sc->sc_ch0;
1428
1429 /* disable ac3 and 24 and 32 bit s/pdif modes */
1430 cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT, CMPCI_REG_AC3EN1);
1431 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_AC3EN2);
1432 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_SPD32SEL);
1433 cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT, CMPCI_REG_SPDIF_24);
1434
1435 /* playback to ... */
1436 if (CMPCI_ISCAP(sc, SPDOUT) &&
1437 sc->sc_gain[CMPCI_PLAYBACK_MODE][CMPCI_LR]
1438 == CMPCI_PLAYBACK_MODE_SPDIF &&
1439 (chan->md_divide == CMPCI_REG_RATE_44100 ||
1440 (CMPCI_ISCAP(sc, SPDOUT_48K) &&
1441 chan->md_divide == CMPCI_REG_RATE_48000))) {
1442 /* playback to SPDIF */
1443 if (sc->sc_play_channel == 0)
1444 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
1445 CMPCI_REG_SPDIF0_ENABLE);
1446 else
1447 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
1448 CMPCI_REG_SPDIF1_ENABLE);
1449 enspdout = 1;
1450 if (chan->md_divide == CMPCI_REG_RATE_48000)
1451 cmpci_reg_set_reg_misc(sc,
1452 CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
1453 else
1454 cmpci_reg_clear_reg_misc(sc,
1455 CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
1456 /* XXX assume sample rate <= 48kHz */
1457 cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT,
1458 CMPCI_REG_DBL_SPD_RATE);
1459 } else {
1460 /* playback to DAC */
1461 if (sc->sc_play_channel == 0)
1462 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
1463 CMPCI_REG_SPDIF0_ENABLE);
1464 else
1465 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
1466 CMPCI_REG_SPDIF1_ENABLE);
1467 if (CMPCI_ISCAP(sc, SPDOUT_48K))
1468 cmpci_reg_clear_reg_misc(sc,
1469 CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
1470 }
1471
1472 /* legacy to SPDIF/out or not */
1473 if (CMPCI_ISCAP(sc, SPDLEGACY)) {
1474 if (sc->sc_gain[CMPCI_SPDIF_OUT_PLAYBACK][CMPCI_LR]
1475 == CMPCI_SPDIF_OUT_PLAYBACK_WAVE)
1476 cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
1477 CMPCI_REG_LEGACY_SPDIF_ENABLE);
1478 else {
1479 cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL,
1480 CMPCI_REG_LEGACY_SPDIF_ENABLE);
1481 enspdout = 1;
1482 }
1483 }
1484
1485 /* enable/disable SPDIF/out */
1486 if (CMPCI_ISCAP(sc, XSPDOUT) && enspdout)
1487 cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL,
1488 CMPCI_REG_XSPDIF_ENABLE);
1489 else
1490 cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
1491 CMPCI_REG_XSPDIF_ENABLE);
1492
1493 /* SPDIF monitor (digital to analog output) */
1494 if (CMPCI_ISCAP(sc, SPDIN_MONITOR)) {
1495 v = sc->sc_gain[CMPCI_MONITOR_DAC][CMPCI_LR];
1496 if (!(v & CMPCI_MONDAC_ENABLE))
1497 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1498 CMPCI_REG_SPDIN_MONITOR);
1499 if (v & CMPCI_MONDAC_SPDOUT)
1500 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
1501 CMPCI_REG_SPDIFOUT_DAC);
1502 else
1503 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
1504 CMPCI_REG_SPDIFOUT_DAC);
1505 if (v & CMPCI_MONDAC_ENABLE)
1506 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1507 CMPCI_REG_SPDIN_MONITOR);
1508 }
1509 }
1510
1511 int
cmpci_set_in_ports(struct cmpci_softc * sc)1512 cmpci_set_in_ports(struct cmpci_softc *sc)
1513 {
1514 int mask;
1515 int bitsl, bitsr;
1516
1517 mask = sc->sc_in_mask;
1518
1519 /*
1520 * Note CMPCI_RECORD_SOURCE_CD, CMPCI_RECORD_SOURCE_LINE_IN and
1521 * CMPCI_RECORD_SOURCE_FM are defined to the corresponding bit
1522 * of the mixer register.
1523 */
1524 bitsr = mask & (CMPCI_RECORD_SOURCE_CD | CMPCI_RECORD_SOURCE_LINE_IN |
1525 CMPCI_RECORD_SOURCE_FM);
1526
1527 bitsl = CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr);
1528 if (mask & CMPCI_RECORD_SOURCE_MIC) {
1529 bitsl |= CMPCI_SB16_MIXER_MIC_SRC;
1530 bitsr |= CMPCI_SB16_MIXER_MIC_SRC;
1531 }
1532 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, bitsl);
1533 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, bitsr);
1534
1535 if (mask & CMPCI_RECORD_SOURCE_AUX_IN)
1536 cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
1537 CMPCI_REG_RAUXREN | CMPCI_REG_RAUXLEN);
1538 else
1539 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
1540 CMPCI_REG_RAUXREN | CMPCI_REG_RAUXLEN);
1541
1542 if (mask & CMPCI_RECORD_SOURCE_WAVE)
1543 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1544 CMPCI_REG_WAVEINL | CMPCI_REG_WAVEINR);
1545 else
1546 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1547 CMPCI_REG_WAVEINL | CMPCI_REG_WAVEINR);
1548
1549 if (CMPCI_ISCAP(sc, SPDIN) &&
1550 (sc->sc_ch1.md_divide == CMPCI_REG_RATE_44100 ||
1551 (CMPCI_ISCAP(sc, SPDOUT_48K) &&
1552 sc->sc_ch1.md_divide == CMPCI_REG_RATE_48000/* XXX? */))) {
1553 if (mask & CMPCI_RECORD_SOURCE_SPDIF) {
1554 /* enable SPDIF/in */
1555 cmpci_reg_set_4(sc,
1556 CMPCI_REG_FUNC_1,
1557 CMPCI_REG_SPDIF1_ENABLE);
1558 } else {
1559 cmpci_reg_clear_4(sc,
1560 CMPCI_REG_FUNC_1,
1561 CMPCI_REG_SPDIF1_ENABLE);
1562 }
1563 }
1564
1565 return 0;
1566 }
1567
1568 int
cmpci_set_port(void * handle,mixer_ctrl_t * cp)1569 cmpci_set_port(void *handle, mixer_ctrl_t *cp)
1570 {
1571 struct cmpci_softc *sc = handle;
1572 int lgain, rgain;
1573
1574 switch (cp->dev) {
1575 case CMPCI_MIC_VOL:
1576 case CMPCI_PCSPEAKER:
1577 case CMPCI_MIC_RECVOL:
1578 if (cp->un.value.num_channels != 1)
1579 return EINVAL;
1580 /* FALLTHROUGH */
1581 case CMPCI_DAC_VOL:
1582 case CMPCI_FM_VOL:
1583 case CMPCI_CD_VOL:
1584 case CMPCI_LINE_IN_VOL:
1585 case CMPCI_AUX_IN_VOL:
1586 case CMPCI_MASTER_VOL:
1587 if (cp->type != AUDIO_MIXER_VALUE)
1588 return EINVAL;
1589 switch (cp->un.value.num_channels) {
1590 case 1:
1591 lgain = rgain =
1592 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
1593 break;
1594 case 2:
1595 lgain = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1596 rgain = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1597 break;
1598 default:
1599 return EINVAL;
1600 }
1601 sc->sc_gain[cp->dev][CMPCI_LEFT] = lgain;
1602 sc->sc_gain[cp->dev][CMPCI_RIGHT] = rgain;
1603
1604 cmpci_set_mixer_gain(sc, cp->dev);
1605 break;
1606
1607 case CMPCI_RECORD_SOURCE:
1608 if (cp->type != AUDIO_MIXER_SET)
1609 return EINVAL;
1610
1611 if (cp->un.mask & ~(CMPCI_RECORD_SOURCE_MIC |
1612 CMPCI_RECORD_SOURCE_CD | CMPCI_RECORD_SOURCE_LINE_IN |
1613 CMPCI_RECORD_SOURCE_AUX_IN | CMPCI_RECORD_SOURCE_WAVE |
1614 CMPCI_RECORD_SOURCE_FM | CMPCI_RECORD_SOURCE_SPDIF))
1615 return EINVAL;
1616
1617 if (cp->un.mask & CMPCI_RECORD_SOURCE_SPDIF)
1618 cp->un.mask = CMPCI_RECORD_SOURCE_SPDIF;
1619
1620 sc->sc_in_mask = cp->un.mask;
1621 return cmpci_set_in_ports(sc);
1622
1623 /* boolean */
1624 case CMPCI_DAC_MUTE:
1625 case CMPCI_FM_MUTE:
1626 case CMPCI_CD_MUTE:
1627 case CMPCI_LINE_IN_MUTE:
1628 case CMPCI_AUX_IN_MUTE:
1629 case CMPCI_MIC_MUTE:
1630 case CMPCI_MIC_PREAMP:
1631 case CMPCI_PLAYBACK_MODE:
1632 case CMPCI_SPDIF_IN_PHASE:
1633 case CMPCI_SPDIF_LOOP:
1634 case CMPCI_SPDIF_OUT_PLAYBACK:
1635 case CMPCI_SPDIF_OUT_VOLTAGE:
1636 case CMPCI_REAR:
1637 case CMPCI_INDIVIDUAL:
1638 case CMPCI_REVERSE:
1639 case CMPCI_SURROUND:
1640 if (cp->type != AUDIO_MIXER_ENUM)
1641 return EINVAL;
1642 sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
1643 cmpci_set_mixer_gain(sc, cp->dev);
1644 break;
1645
1646 case CMPCI_SPDIF_IN_SELECT:
1647 switch (cp->un.ord) {
1648 case CMPCI_SPDIF_IN_SPDIN1:
1649 case CMPCI_SPDIF_IN_SPDIN2:
1650 case CMPCI_SPDIF_IN_SPDOUT:
1651 break;
1652 default:
1653 return EINVAL;
1654 }
1655 goto xenum;
1656 case CMPCI_MONITOR_DAC:
1657 switch (cp->un.ord) {
1658 case CMPCI_MONITOR_DAC_OFF:
1659 case CMPCI_MONITOR_DAC_SPDIN:
1660 case CMPCI_MONITOR_DAC_SPDOUT:
1661 break;
1662 default:
1663 return EINVAL;
1664 }
1665 xenum:
1666 if (cp->type != AUDIO_MIXER_ENUM)
1667 return EINVAL;
1668 sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord;
1669 cmpci_set_mixer_gain(sc, cp->dev);
1670 break;
1671
1672 default:
1673 return EINVAL;
1674 }
1675
1676 return 0;
1677 }
1678
1679 int
cmpci_get_port(void * handle,mixer_ctrl_t * cp)1680 cmpci_get_port(void *handle, mixer_ctrl_t *cp)
1681 {
1682 struct cmpci_softc *sc = handle;
1683
1684 switch (cp->dev) {
1685 case CMPCI_MIC_VOL:
1686 case CMPCI_PCSPEAKER:
1687 case CMPCI_MIC_RECVOL:
1688 if (cp->un.value.num_channels != 1)
1689 return EINVAL;
1690 /*FALLTHROUGH*/
1691 case CMPCI_DAC_VOL:
1692 case CMPCI_FM_VOL:
1693 case CMPCI_CD_VOL:
1694 case CMPCI_LINE_IN_VOL:
1695 case CMPCI_AUX_IN_VOL:
1696 case CMPCI_MASTER_VOL:
1697 switch (cp->un.value.num_channels) {
1698 case 1:
1699 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1700 sc->sc_gain[cp->dev][CMPCI_LEFT];
1701 break;
1702 case 2:
1703 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1704 sc->sc_gain[cp->dev][CMPCI_LEFT];
1705 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1706 sc->sc_gain[cp->dev][CMPCI_RIGHT];
1707 break;
1708 default:
1709 return EINVAL;
1710 }
1711 break;
1712
1713 case CMPCI_RECORD_SOURCE:
1714 cp->un.mask = sc->sc_in_mask;
1715 break;
1716
1717 case CMPCI_DAC_MUTE:
1718 case CMPCI_FM_MUTE:
1719 case CMPCI_CD_MUTE:
1720 case CMPCI_LINE_IN_MUTE:
1721 case CMPCI_AUX_IN_MUTE:
1722 case CMPCI_MIC_MUTE:
1723 case CMPCI_MIC_PREAMP:
1724 case CMPCI_PLAYBACK_MODE:
1725 case CMPCI_SPDIF_IN_SELECT:
1726 case CMPCI_SPDIF_IN_PHASE:
1727 case CMPCI_SPDIF_LOOP:
1728 case CMPCI_SPDIF_OUT_PLAYBACK:
1729 case CMPCI_SPDIF_OUT_VOLTAGE:
1730 case CMPCI_MONITOR_DAC:
1731 case CMPCI_REAR:
1732 case CMPCI_INDIVIDUAL:
1733 case CMPCI_REVERSE:
1734 case CMPCI_SURROUND:
1735 cp->un.ord = sc->sc_gain[cp->dev][CMPCI_LR];
1736 break;
1737
1738 default:
1739 return EINVAL;
1740 }
1741
1742 return 0;
1743 }
1744
1745 size_t
cmpci_round_buffersize(void * handle,int direction,size_t bufsize)1746 cmpci_round_buffersize(void *handle, int direction, size_t bufsize)
1747 {
1748 if (bufsize > 0x10000)
1749 bufsize = 0x10000;
1750
1751 return bufsize;
1752 }
1753
1754 int
cmpci_trigger_output(void * handle,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)1755 cmpci_trigger_output(void *handle, void *start, void *end, int blksize,
1756 void (*intr)(void *), void *arg, struct audio_params *param)
1757 {
1758 struct cmpci_softc *sc = handle;
1759 struct cmpci_dmanode *p;
1760 struct cmpci_channel *chan;
1761 uint32_t reg_dma_base, reg_dma_bytes, reg_dma_samples, reg_dir,
1762 reg_intr_enable, reg_enable;
1763 uint32_t length;
1764 size_t buffer_size = (caddr_t)end - (caddr_t)start;
1765
1766 cmpci_set_out_ports(sc);
1767
1768 if (sc->sc_play_channel == 1) {
1769 chan = &sc->sc_ch1;
1770 reg_dma_base = CMPCI_REG_DMA1_BASE;
1771 reg_dma_bytes = CMPCI_REG_DMA1_BYTES;
1772 reg_dma_samples = CMPCI_REG_DMA1_SAMPLES;
1773 reg_dir = CMPCI_REG_CH1_DIR;
1774 reg_intr_enable = CMPCI_REG_CH1_INTR_ENABLE;
1775 reg_enable = CMPCI_REG_CH1_ENABLE;
1776 } else {
1777 chan = &sc->sc_ch0;
1778 reg_dma_base = CMPCI_REG_DMA0_BASE;
1779 reg_dma_bytes = CMPCI_REG_DMA0_BYTES;
1780 reg_dma_samples = CMPCI_REG_DMA0_SAMPLES;
1781 reg_dir = CMPCI_REG_CH0_DIR;
1782 reg_intr_enable = CMPCI_REG_CH0_INTR_ENABLE;
1783 reg_enable = CMPCI_REG_CH0_ENABLE;
1784 }
1785
1786 chan->bps = (param->channels > 1 ? 2 : 1) * param->bps;
1787 if (!chan->bps)
1788 return EINVAL;
1789
1790 chan->intr = intr;
1791 chan->intr_arg = arg;
1792 chan->blksize = blksize;
1793 chan->nblocks = buffer_size / chan->blksize;
1794 chan->swpos = 0;
1795
1796 /* set DMA frame */
1797 if (!(p = cmpci_find_dmamem(sc, start)))
1798 return EINVAL;
1799 bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg_dma_base,
1800 DMAADDR(p));
1801 delay(10);
1802 length = (buffer_size + 1) / chan->bps - 1;
1803 bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg_dma_bytes, length);
1804 delay(10);
1805
1806 /* set interrupt count */
1807 length = (chan->blksize + chan->bps - 1) / chan->bps - 1;
1808 bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg_dma_samples, length);
1809 delay(10);
1810
1811 /* start DMA */
1812 mtx_enter(&audio_lock);
1813 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_dir); /* PLAY */
1814 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, reg_intr_enable);
1815 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, reg_enable);
1816 mtx_leave(&audio_lock);
1817 return 0;
1818 }
1819
1820 int
cmpci_trigger_input(void * handle,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)1821 cmpci_trigger_input(void *handle, void *start, void *end, int blksize,
1822 void (*intr)(void *), void *arg, struct audio_params *param)
1823 {
1824 struct cmpci_softc *sc = handle;
1825 struct cmpci_dmanode *p;
1826 struct cmpci_channel *chan = &sc->sc_ch1;
1827 size_t buffer_size = (caddr_t)end - (caddr_t)start;
1828
1829 cmpci_set_in_ports(sc);
1830
1831 chan->bps = param->channels * param->bps;
1832 if (!chan->bps)
1833 return EINVAL;
1834
1835 chan->intr = intr;
1836 chan->intr_arg = arg;
1837 chan->blksize = blksize;
1838 chan->nblocks = buffer_size / chan->blksize;
1839 chan->swpos = 0;
1840
1841 /* set DMA frame */
1842 if (!(p = cmpci_find_dmamem(sc, start)))
1843 return EINVAL;
1844 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BASE,
1845 DMAADDR(p));
1846 delay(10);
1847 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BYTES,
1848 (buffer_size + 1) / chan->bps - 1);
1849 delay(10);
1850
1851 /* set interrupt count */
1852 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_SAMPLES,
1853 (chan->blksize + chan->bps - 1) / chan->bps - 1);
1854 delay(10);
1855
1856 /* start DMA */
1857 mtx_enter(&audio_lock);
1858 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* REC */
1859 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
1860 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
1861 mtx_leave(&audio_lock);
1862 return 0;
1863 }
1864
1865 /* end of file */
1866