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