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