harmony.c revision 1.2.4.3 1 /* $NetBSD: harmony.c,v 1.2.4.3 2017/12/03 11:36:16 jdolecek Exp $ */
2
3 /* $OpenBSD: harmony.c,v 1.23 2004/02/13 21:28:19 mickey Exp $ */
4
5 /*-
6 * Copyright (c) 2009 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Matt Fleming.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Copyright (c) 2003 Jason L. Wright (jason (at) thought.net)
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
50 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
51 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
53 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
55 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
56 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 * POSSIBILITY OF SUCH DAMAGE.
58 */
59
60 /*
61 * Harmony (CS4215/AD1849 LASI) audio interface.
62 */
63
64
65
66 #include <sys/param.h>
67 #include <sys/kernel.h>
68 #include <sys/systm.h>
69 #include <sys/errno.h>
70 #include <sys/ioctl.h>
71 #include <sys/device.h>
72 #include <sys/proc.h>
73 #include <sys/kmem.h>
74 #include <uvm/uvm_extern.h>
75
76 #include <sys/rndsource.h>
77
78 #include <sys/audioio.h>
79 #include <dev/audio_if.h>
80 #include <dev/auconv.h>
81
82 #include <machine/cpu.h>
83 #include <machine/intr.h>
84 #include <machine/iomod.h>
85 #include <machine/autoconf.h>
86 #include <sys/bus.h>
87
88 #include <hppa/dev/cpudevs.h>
89 #include <hppa/gsc/gscbusvar.h>
90 #include <hppa/gsc/harmonyreg.h>
91 #include <hppa/gsc/harmonyvar.h>
92
93 int harmony_open(void *, int);
94 void harmony_close(void *);
95 int harmony_query_encoding(void *, struct audio_encoding *);
96 int harmony_set_params(void *, int, int, audio_params_t *,
97 audio_params_t *, stream_filter_list_t *, stream_filter_list_t *);
98 int harmony_round_blocksize(void *, int, int, const audio_params_t *);
99
100 int harmony_control_wait(struct harmony_softc *);
101 int harmony_commit_settings(void *);
102
103 int harmony_halt_output(void *);
104 int harmony_halt_input(void *);
105 int harmony_getdev(void *, struct audio_device *);
106 int harmony_set_port(void *, mixer_ctrl_t *);
107 int harmony_get_port(void *, mixer_ctrl_t *);
108 int harmony_query_devinfo(void *, mixer_devinfo_t *);
109 void * harmony_allocm(void *, int, size_t);
110 void harmony_freem(void *, void *, size_t);
111 size_t harmony_round_buffersize(void *, int, size_t);
112 int harmony_get_props(void *);
113 int harmony_trigger_output(void *, void *, void *, int,
114 void (*)(void *), void *, const audio_params_t *);
115 int harmony_trigger_input(void *, void *, void *, int,
116 void (*)(void *), void *, const audio_params_t *);
117 void harmony_get_locks(void *, kmutex_t **, kmutex_t **);
118
119 const struct audio_hw_if harmony_sa_hw_if = {
120 harmony_open,
121 harmony_close,
122 NULL,
123 harmony_query_encoding,
124 harmony_set_params,
125 harmony_round_blocksize,
126 harmony_commit_settings,
127 NULL,
128 NULL,
129 NULL,
130 NULL,
131 harmony_halt_output,
132 harmony_halt_input,
133 NULL,
134 harmony_getdev,
135 NULL,
136 harmony_set_port,
137 harmony_get_port,
138 harmony_query_devinfo,
139 harmony_allocm,
140 harmony_freem,
141 harmony_round_buffersize,
142 NULL,
143 harmony_get_props,
144 harmony_trigger_output,
145 harmony_trigger_input,
146 NULL,
147 harmony_get_locks,
148 };
149
150 int harmony_match(device_t, struct cfdata *, void *);
151 void harmony_attach(device_t, device_t, void *);
152
153
154 CFATTACH_DECL_NEW(harmony, sizeof(struct harmony_softc),
155 harmony_match, harmony_attach, NULL, NULL);
156
157 int harmony_intr(void *);
158 void harmony_intr_enable(struct harmony_softc *);
159 void harmony_intr_disable(struct harmony_softc *);
160 uint32_t harmony_speed_bits(struct harmony_softc *, u_int *);
161 int harmony_set_gainctl(struct harmony_softc *);
162 void harmony_reset_codec(struct harmony_softc *);
163 void harmony_start_cp(struct harmony_softc *, int);
164 void harmony_start_pp(struct harmony_softc *, int);
165 void harmony_tick_pb(void *);
166 void harmony_tick_cp(void *);
167 void harmony_try_more(struct harmony_softc *, int, int,
168 struct harmony_channel *);
169 static void harmony_empty_input(struct harmony_softc *);
170 static void harmony_empty_output(struct harmony_softc *);
171
172 void harmony_acc_tmo(void *);
173 #define ADD_CLKALLICA(sc) do { \
174 (sc)->sc_acc <<= 1; \
175 (sc)->sc_acc |= READ_REG((sc), HARMONY_DIAG) & DIAG_CO; \
176 if ((sc)->sc_acc_cnt++ && !((sc)->sc_acc_cnt % 32)) \
177 rnd_add_uint32(&(sc)->sc_rnd_source, \
178 (sc)->sc_acc_num ^= (sc)->sc_acc); \
179 } while(0)
180
181 int
182 harmony_match(device_t parent, struct cfdata *match, void *aux)
183 {
184 struct gsc_attach_args *ga;
185
186 ga = aux;
187 if (ga->ga_type.iodc_type == HPPA_TYPE_FIO) {
188 if (ga->ga_type.iodc_sv_model == HPPA_FIO_A1 ||
189 ga->ga_type.iodc_sv_model == HPPA_FIO_A2NB ||
190 ga->ga_type.iodc_sv_model == HPPA_FIO_A1NB ||
191 ga->ga_type.iodc_sv_model == HPPA_FIO_A2)
192 return 1;
193 }
194 return 0;
195 }
196
197 void
198 harmony_attach(device_t parent, device_t self, void *aux)
199 {
200 struct harmony_softc *sc = device_private(self);
201 struct gsc_attach_args *ga;
202 uint8_t rev;
203 uint32_t cntl;
204 int i;
205
206 sc->sc_dv = self;
207 ga = aux;
208 sc->sc_bt = ga->ga_iot;
209 sc->sc_dmat = ga->ga_dmatag;
210
211 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
212 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
213
214 if (bus_space_map(sc->sc_bt, ga->ga_hpa, HARMONY_NREGS, 0,
215 &sc->sc_bh) != 0) {
216 aprint_error(": couldn't map registers\n");
217 return;
218 }
219
220 cntl = READ_REG(sc, HARMONY_ID);
221 switch ((cntl & ID_REV_MASK)) {
222 case ID_REV_TS:
223 sc->sc_teleshare = 1;
224 case ID_REV_NOTS:
225 break;
226 default:
227 aprint_error(": unknown id == 0x%02x\n",
228 (cntl & ID_REV_MASK) >> ID_REV_SHIFT);
229 bus_space_unmap(sc->sc_bt, sc->sc_bh, HARMONY_NREGS);
230 return;
231 }
232
233 if (bus_dmamem_alloc(sc->sc_dmat, sizeof(struct harmony_empty),
234 PAGE_SIZE, 0, &sc->sc_empty_seg, 1, &sc->sc_empty_rseg,
235 BUS_DMA_WAITOK) != 0) {
236 aprint_error(": could not alloc DMA memory\n");
237 bus_space_unmap(sc->sc_bt, sc->sc_bh, HARMONY_NREGS);
238 return;
239 }
240 if (bus_dmamem_map(sc->sc_dmat, &sc->sc_empty_seg, 1,
241 sizeof(struct harmony_empty), (void **)&sc->sc_empty_kva,
242 BUS_DMA_WAITOK) != 0) {
243 aprint_error(": couldn't map DMA memory\n");
244 bus_dmamem_free(sc->sc_dmat, &sc->sc_empty_seg,
245 sc->sc_empty_rseg);
246 bus_space_unmap(sc->sc_bt, sc->sc_bh, HARMONY_NREGS);
247 return;
248 }
249 if (bus_dmamap_create(sc->sc_dmat, sizeof(struct harmony_empty), 1,
250 sizeof(struct harmony_empty), 0, BUS_DMA_WAITOK,
251 &sc->sc_empty_map) != 0) {
252 aprint_error(": can't create DMA map\n");
253 bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_empty_kva,
254 sizeof(struct harmony_empty));
255 bus_dmamem_free(sc->sc_dmat, &sc->sc_empty_seg,
256 sc->sc_empty_rseg);
257 bus_space_unmap(sc->sc_bt, sc->sc_bh, HARMONY_NREGS);
258 return;
259 }
260 if (bus_dmamap_load(sc->sc_dmat, sc->sc_empty_map, sc->sc_empty_kva,
261 sizeof(struct harmony_empty), NULL, BUS_DMA_WAITOK) != 0) {
262 aprint_error(": can't load DMA map\n");
263 bus_dmamap_destroy(sc->sc_dmat, sc->sc_empty_map);
264 bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_empty_kva,
265 sizeof(struct harmony_empty));
266 bus_dmamem_free(sc->sc_dmat, &sc->sc_empty_seg,
267 sc->sc_empty_rseg);
268 bus_space_unmap(sc->sc_bt, sc->sc_bh, HARMONY_NREGS);
269 return;
270 }
271
272 sc->sc_playback_empty = 0;
273 for (i = 0; i < PLAYBACK_EMPTYS; i++)
274 sc->sc_playback_paddrs[i] =
275 sc->sc_empty_map->dm_segs[0].ds_addr +
276 offsetof(struct harmony_empty, playback[i][0]);
277
278 sc->sc_capture_empty = 0;
279 for (i = 0; i < CAPTURE_EMPTYS; i++)
280 sc->sc_capture_paddrs[i] =
281 sc->sc_empty_map->dm_segs[0].ds_addr +
282 offsetof(struct harmony_empty, capture[i][0]);
283
284 bus_dmamap_sync(sc->sc_dmat, sc->sc_empty_map,
285 offsetof(struct harmony_empty, playback[0][0]),
286 PLAYBACK_EMPTYS * HARMONY_BUFSIZE, BUS_DMASYNC_PREWRITE);
287
288 (void) hppa_intr_establish(IPL_AUDIO, harmony_intr, sc, ga->ga_ir,
289 ga->ga_irq);
290
291 /* set defaults */
292 sc->sc_in_port = HARMONY_IN_LINE;
293 sc->sc_out_port = HARMONY_OUT_SPEAKER;
294 sc->sc_input_lvl.left = sc->sc_input_lvl.right = 240;
295 sc->sc_output_lvl.left = sc->sc_output_lvl.right = 244;
296 sc->sc_monitor_lvl.left = sc->sc_monitor_lvl.right = 208;
297 sc->sc_outputgain = 0;
298
299 /* reset chip, and push default gain controls */
300 harmony_reset_codec(sc);
301
302 cntl = READ_REG(sc, HARMONY_CNTL);
303 rev = (cntl & CNTL_CODEC_REV_MASK) >> CNTL_CODEC_REV_SHIFT;
304 aprint_normal(": rev %u", rev);
305
306 if (sc->sc_teleshare)
307 printf(", teleshare");
308 aprint_normal("\n");
309
310 if ((rev & CS4215_REV_VER) >= CS4215_REV_VER_E)
311 sc->sc_hasulinear8 = 1;
312
313 strlcpy(sc->sc_audev.name, ga->ga_name, sizeof(sc->sc_audev.name));
314 snprintf(sc->sc_audev.version, sizeof sc->sc_audev.version,
315 "%u.%u;%u", ga->ga_type.iodc_sv_rev,
316 ga->ga_type.iodc_model, ga->ga_type.iodc_revision);
317 strlcpy(sc->sc_audev.config, device_xname(sc->sc_dv),
318 sizeof(sc->sc_audev.config));
319
320 audio_attach_mi(&harmony_sa_hw_if, sc, sc->sc_dv);
321
322 rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dv),
323 RND_TYPE_UNKNOWN, RND_FLAG_DEFAULT);
324
325 callout_init(&sc->sc_acc_tmo, 0);
326 callout_setfunc(&sc->sc_acc_tmo, harmony_acc_tmo, sc);
327 sc->sc_acc_num = 0xa5a5a5a5;
328 }
329
330 void
331 harmony_reset_codec(struct harmony_softc *sc)
332 {
333
334 /* silence */
335 WRITE_REG(sc, HARMONY_GAINCTL, GAINCTL_OUTPUT_LEFT_M |
336 GAINCTL_OUTPUT_RIGHT_M | GAINCTL_MONITOR_M);
337
338 /* start reset */
339 WRITE_REG(sc, HARMONY_RESET, RESET_RST);
340
341 DELAY(100000); /* wait at least 0.05 sec */
342
343 harmony_set_gainctl(sc);
344 WRITE_REG(sc, HARMONY_RESET, 0);
345 }
346
347 void
348 harmony_acc_tmo(void *v)
349 {
350 struct harmony_softc *sc;
351
352 sc = v;
353 ADD_CLKALLICA(sc);
354 callout_schedule(&sc->sc_acc_tmo, 1);
355 }
356
357 /*
358 * interrupt handler
359 */
360 int
361 harmony_intr(void *vsc)
362 {
363 struct harmony_softc *sc;
364 uint32_t dstatus;
365 int r;
366
367 sc = vsc;
368 r = 0;
369 ADD_CLKALLICA(sc);
370
371 mutex_spin_enter(&sc->sc_intr_lock);
372
373 harmony_intr_disable(sc);
374
375 dstatus = READ_REG(sc, HARMONY_DSTATUS);
376
377 if (dstatus & DSTATUS_PN) {
378 r = 1;
379 harmony_start_pp(sc, 0);
380 }
381
382 if (dstatus & DSTATUS_RN) {
383 r = 1;
384 harmony_start_cp(sc, 0);
385 }
386
387 if (READ_REG(sc, HARMONY_OV) & OV_OV) {
388 sc->sc_ov = 1;
389 WRITE_REG(sc, HARMONY_OV, 0);
390 } else
391 sc->sc_ov = 0;
392
393 harmony_intr_enable(sc);
394
395 mutex_spin_exit(&sc->sc_intr_lock);
396
397 return r;
398 }
399
400 void
401 harmony_intr_enable(struct harmony_softc *sc)
402 {
403
404 WRITE_REG(sc, HARMONY_DSTATUS, DSTATUS_IE);
405 SYNC_REG(sc, HARMONY_DSTATUS, BUS_SPACE_BARRIER_WRITE);
406 }
407
408 void
409 harmony_intr_disable(struct harmony_softc *sc)
410 {
411
412 WRITE_REG(sc, HARMONY_DSTATUS, 0);
413 SYNC_REG(sc, HARMONY_DSTATUS, BUS_SPACE_BARRIER_WRITE);
414 }
415
416 int
417 harmony_open(void *vsc, int flags)
418 {
419 struct harmony_softc *sc;
420
421 sc = vsc;
422 if (sc->sc_open)
423 return EBUSY;
424 sc->sc_open = 1;
425 return 0;
426 }
427
428 void
429 harmony_close(void *vsc)
430 {
431 struct harmony_softc *sc;
432
433 sc = vsc;
434 harmony_halt_input(sc);
435 harmony_halt_output(sc);
436 harmony_intr_disable(sc);
437 sc->sc_open = 0;
438 }
439
440 int
441 harmony_query_encoding(void *vsc, struct audio_encoding *fp)
442 {
443 struct harmony_softc *sc;
444 int err;
445
446 sc = vsc;
447 err = 0;
448 switch (fp->index) {
449 case 0:
450 strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
451 fp->encoding = AUDIO_ENCODING_ULAW;
452 fp->precision = 8;
453 fp->flags = 0;
454 break;
455 case 1:
456 strlcpy(fp->name, AudioEalaw, sizeof fp->name);
457 fp->encoding = AUDIO_ENCODING_ALAW;
458 fp->precision = 8;
459 fp->flags = 0;
460 break;
461 case 2:
462 strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
463 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
464 fp->precision = 16;
465 fp->flags = 0;
466 break;
467 case 3:
468 strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
469 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
470 fp->precision = 16;
471 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
472 break;
473 case 4:
474 strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
475 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
476 fp->precision = 16;
477 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
478 break;
479 case 5:
480 strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
481 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
482 fp->precision = 16;
483 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
484 break;
485 case 6:
486 if (sc->sc_hasulinear8) {
487 strlcpy(fp->name, AudioEulinear, sizeof fp->name);
488 fp->encoding = AUDIO_ENCODING_ULINEAR;
489 fp->precision = 8;
490 fp->flags = 0;
491 break;
492 }
493 /*FALLTHROUGH*/
494 case 7:
495 if (sc->sc_hasulinear8) {
496 strlcpy(fp->name, AudioEslinear, sizeof fp->name);
497 fp->encoding = AUDIO_ENCODING_SLINEAR;
498 fp->precision = 8;
499 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
500 break;
501 }
502 /*FALLTHROUGH*/
503 default:
504 err = EINVAL;
505 }
506 return err;
507 }
508
509 int
510 harmony_set_params(void *vsc, int setmode, int usemode,
511 audio_params_t *p, audio_params_t *r,
512 stream_filter_list_t *pfil, stream_filter_list_t *rfil)
513 {
514 audio_params_t hw;
515 struct harmony_softc *sc;
516 uint32_t bits;
517 stream_filter_factory_t *pswcode = NULL;
518 stream_filter_factory_t *rswcode = NULL;
519
520 sc = vsc;
521 /* assume p.equals(r) */
522 hw = *p;
523 switch (p->encoding) {
524 case AUDIO_ENCODING_ULAW:
525 if (p->precision != 8)
526 return EINVAL;
527 bits = CNTL_FORMAT_ULAW;
528 break;
529 case AUDIO_ENCODING_ALAW:
530 if (p->precision != 8)
531 return EINVAL;
532 bits = CNTL_FORMAT_ALAW;
533 break;
534 case AUDIO_ENCODING_SLINEAR_BE:
535 if (p->precision == 8) {
536 bits = CNTL_FORMAT_ULINEAR8;
537 hw.encoding = AUDIO_ENCODING_ULINEAR_LE;
538 rswcode = pswcode = change_sign8;
539 break;
540 }
541 if (p->precision == 16) {
542 bits = CNTL_FORMAT_SLINEAR16BE;
543 break;
544 }
545 return EINVAL;
546 case AUDIO_ENCODING_ULINEAR:
547 if (p->precision != 8)
548 return EINVAL;
549 bits = CNTL_FORMAT_ULINEAR8;
550 break;
551 case AUDIO_ENCODING_SLINEAR:
552 if (p->precision != 8)
553 return EINVAL;
554 bits = CNTL_FORMAT_ULINEAR8;
555 hw.encoding = AUDIO_ENCODING_ULINEAR_LE;
556 rswcode = pswcode = change_sign8;
557 break;
558 case AUDIO_ENCODING_SLINEAR_LE:
559 if (p->precision == 8) {
560 bits = CNTL_FORMAT_ULINEAR8;
561 hw.encoding = AUDIO_ENCODING_ULINEAR_LE;
562 rswcode = pswcode = change_sign8;
563 break;
564 }
565 if (p->precision == 16) {
566 bits = CNTL_FORMAT_SLINEAR16BE;
567 hw.encoding = AUDIO_ENCODING_SLINEAR_BE;
568 rswcode = pswcode = swap_bytes;
569 break;
570 }
571 return EINVAL;
572 case AUDIO_ENCODING_ULINEAR_BE:
573 if (p->precision == 8) {
574 bits = CNTL_FORMAT_ULINEAR8;
575 break;
576 }
577 if (p->precision == 16) {
578 bits = CNTL_FORMAT_SLINEAR16BE;
579 rswcode = pswcode = change_sign16;
580 break;
581 }
582 return EINVAL;
583 case AUDIO_ENCODING_ULINEAR_LE:
584 if (p->precision == 8) {
585 bits = CNTL_FORMAT_ULINEAR8;
586 break;
587 }
588 if (p->precision == 16) {
589 bits = CNTL_FORMAT_SLINEAR16BE;
590 hw.encoding = AUDIO_ENCODING_SLINEAR_BE;
591 rswcode = pswcode = swap_bytes_change_sign16;
592 break;
593 }
594 return EINVAL;
595 default:
596 return EINVAL;
597 }
598
599 if (sc->sc_outputgain)
600 bits |= CNTL_OLB;
601
602 if (p->channels == 1)
603 bits |= CNTL_CHANS_MONO;
604 else if (p->channels == 2)
605 bits |= CNTL_CHANS_STEREO;
606 else
607 return EINVAL;
608
609 bits |= harmony_speed_bits(sc, &p->sample_rate);
610 if (pswcode != NULL)
611 pfil->append(pfil, pswcode, &hw);
612 if (rswcode != NULL)
613 rfil->append(rfil, rswcode, &hw);
614 sc->sc_cntlbits = bits;
615 sc->sc_need_commit = 1;
616
617 return 0;
618 }
619
620 int
621 harmony_round_blocksize(void *vsc, int blk,
622 int mode, const audio_params_t *param)
623 {
624
625 return HARMONY_BUFSIZE;
626 }
627
628 int
629 harmony_control_wait(struct harmony_softc *sc)
630 {
631 uint32_t reg;
632 int j = 0;
633
634 while (j < 10) {
635 /* Wait for it to come out of control mode */
636 reg = READ_REG(sc, HARMONY_CNTL);
637 if ((reg & CNTL_C) == 0)
638 return 0;
639 DELAY(50000); /* wait 0.05 */
640 j++;
641 }
642
643 return 1;
644 }
645
646 int
647 harmony_commit_settings(void *vsc)
648 {
649 struct harmony_softc *sc;
650 uint32_t reg;
651 uint8_t quietchar;
652 int i;
653
654 sc = vsc;
655 if (sc->sc_need_commit == 0)
656 return 0;
657
658 harmony_intr_disable(sc);
659
660 for (;;) {
661 reg = READ_REG(sc, HARMONY_DSTATUS);
662 if ((reg & (DSTATUS_PC | DSTATUS_RC)) == 0)
663 break;
664 }
665
666 /* Setting some bits in gainctl requires a reset */
667 harmony_reset_codec(sc);
668
669 /* set the silence character based on the encoding type */
670 bus_dmamap_sync(sc->sc_dmat, sc->sc_empty_map,
671 offsetof(struct harmony_empty, playback[0][0]),
672 PLAYBACK_EMPTYS * HARMONY_BUFSIZE, BUS_DMASYNC_POSTWRITE);
673 switch (sc->sc_cntlbits & CNTL_FORMAT_MASK) {
674 case CNTL_FORMAT_ULAW:
675 quietchar = 0x7f;
676 break;
677 case CNTL_FORMAT_ALAW:
678 quietchar = 0x55;
679 break;
680 case CNTL_FORMAT_SLINEAR16BE:
681 case CNTL_FORMAT_ULINEAR8:
682 default:
683 quietchar = 0;
684 break;
685 }
686 for (i = 0; i < PLAYBACK_EMPTYS; i++)
687 memset(&sc->sc_empty_kva->playback[i][0],
688 quietchar, HARMONY_BUFSIZE);
689 bus_dmamap_sync(sc->sc_dmat, sc->sc_empty_map,
690 offsetof(struct harmony_empty, playback[0][0]),
691 PLAYBACK_EMPTYS * HARMONY_BUFSIZE, BUS_DMASYNC_PREWRITE);
692
693 harmony_control_wait(sc);
694
695 bus_space_write_4(sc->sc_bt, sc->sc_bh, HARMONY_CNTL,
696 sc->sc_cntlbits | CNTL_C);
697
698 harmony_control_wait(sc);
699
700 sc->sc_need_commit = 0;
701
702 if (sc->sc_playing || sc->sc_capturing)
703 harmony_intr_enable(sc);
704
705 return 0;
706 }
707
708 static void
709 harmony_empty_output(struct harmony_softc *sc)
710 {
711
712 WRITE_REG(sc, HARMONY_PNXTADD,
713 sc->sc_playback_paddrs[sc->sc_playback_empty]);
714 SYNC_REG(sc, HARMONY_PNXTADD, BUS_SPACE_BARRIER_WRITE);
715
716 if (++sc->sc_playback_empty == PLAYBACK_EMPTYS)
717 sc->sc_playback_empty = 0;
718 }
719
720 int
721 harmony_halt_output(void *vsc)
722 {
723 struct harmony_softc *sc;
724
725 sc = vsc;
726 sc->sc_playing = 0;
727
728 harmony_empty_output(sc);
729 return 0;
730 }
731
732 static void
733 harmony_empty_input(struct harmony_softc *sc)
734 {
735
736 WRITE_REG(sc, HARMONY_RNXTADD,
737 sc->sc_capture_paddrs[sc->sc_capture_empty]);
738 SYNC_REG(sc, HARMONY_RNXTADD, BUS_SPACE_BARRIER_WRITE);
739
740 if (++sc->sc_capture_empty == CAPTURE_EMPTYS)
741 sc->sc_capture_empty = 0;
742 }
743
744 int
745 harmony_halt_input(void *vsc)
746 {
747 struct harmony_softc *sc;
748
749 sc = vsc;
750 sc->sc_capturing = 0;
751
752 harmony_empty_input(sc);
753 return 0;
754 }
755
756 int
757 harmony_getdev(void *vsc, struct audio_device *retp)
758 {
759 struct harmony_softc *sc;
760
761 sc = vsc;
762 *retp = sc->sc_audev;
763 return 0;
764 }
765
766 int
767 harmony_set_port(void *vsc, mixer_ctrl_t *cp)
768 {
769 struct harmony_softc *sc;
770 int err;
771
772 sc = vsc;
773 err = EINVAL;
774 switch (cp->dev) {
775 case HARMONY_PORT_INPUT_LVL:
776 if (cp->type != AUDIO_MIXER_VALUE)
777 break;
778 if (cp->un.value.num_channels == 1)
779 sc->sc_input_lvl.left = sc->sc_input_lvl.right =
780 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
781 else if (cp->un.value.num_channels == 2) {
782 sc->sc_input_lvl.left =
783 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
784 sc->sc_input_lvl.right =
785 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
786 } else
787 break;
788 sc->sc_need_commit = 1;
789 err = 0;
790 break;
791 case HARMONY_PORT_OUTPUT_LVL:
792 if (cp->type != AUDIO_MIXER_VALUE)
793 break;
794 if (cp->un.value.num_channels == 1)
795 sc->sc_output_lvl.left = sc->sc_output_lvl.right =
796 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
797 else if (cp->un.value.num_channels == 2) {
798 sc->sc_output_lvl.left =
799 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
800 sc->sc_output_lvl.right =
801 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
802 } else
803 break;
804 sc->sc_need_commit = 1;
805 err = 0;
806 break;
807 case HARMONY_PORT_OUTPUT_GAIN:
808 if (cp->type != AUDIO_MIXER_ENUM)
809 break;
810 sc->sc_outputgain = cp->un.ord ? 1 : 0;
811 err = 0;
812 break;
813 case HARMONY_PORT_MONITOR_LVL:
814 if (cp->type != AUDIO_MIXER_VALUE)
815 break;
816 if (cp->un.value.num_channels != 1)
817 break;
818 sc->sc_monitor_lvl.left = sc->sc_input_lvl.right =
819 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
820 sc->sc_need_commit = 1;
821 err = 0;
822 break;
823 case HARMONY_PORT_RECORD_SOURCE:
824 if (cp->type != AUDIO_MIXER_ENUM)
825 break;
826 if (cp->un.ord != HARMONY_IN_LINE &&
827 cp->un.ord != HARMONY_IN_MIC)
828 break;
829 sc->sc_in_port = cp->un.ord;
830 err = 0;
831 sc->sc_need_commit = 1;
832 break;
833 case HARMONY_PORT_OUTPUT_SOURCE:
834 if (cp->type != AUDIO_MIXER_ENUM)
835 break;
836 if (cp->un.ord != HARMONY_OUT_LINE &&
837 cp->un.ord != HARMONY_OUT_SPEAKER &&
838 cp->un.ord != HARMONY_OUT_HEADPHONE)
839 break;
840 sc->sc_out_port = cp->un.ord;
841 err = 0;
842 sc->sc_need_commit = 1;
843 break;
844 }
845
846 return err;
847 }
848
849 int
850 harmony_get_port(void *vsc, mixer_ctrl_t *cp)
851 {
852 struct harmony_softc *sc;
853 int err;
854
855 sc = vsc;
856 err = EINVAL;
857 switch (cp->dev) {
858 case HARMONY_PORT_INPUT_LVL:
859 if (cp->type != AUDIO_MIXER_VALUE)
860 break;
861 if (cp->un.value.num_channels == 1) {
862 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
863 sc->sc_input_lvl.left;
864 } else if (cp->un.value.num_channels == 2) {
865 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
866 sc->sc_input_lvl.left;
867 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
868 sc->sc_input_lvl.right;
869 } else
870 break;
871 err = 0;
872 break;
873 case HARMONY_PORT_INPUT_OV:
874 if (cp->type != AUDIO_MIXER_ENUM)
875 break;
876 cp->un.ord = sc->sc_ov ? 1 : 0;
877 err = 0;
878 break;
879 case HARMONY_PORT_OUTPUT_LVL:
880 if (cp->type != AUDIO_MIXER_VALUE)
881 break;
882 if (cp->un.value.num_channels == 1) {
883 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
884 sc->sc_output_lvl.left;
885 } else if (cp->un.value.num_channels == 2) {
886 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
887 sc->sc_output_lvl.left;
888 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
889 sc->sc_output_lvl.right;
890 } else
891 break;
892 err = 0;
893 break;
894 case HARMONY_PORT_OUTPUT_GAIN:
895 if (cp->type != AUDIO_MIXER_ENUM)
896 break;
897 cp->un.ord = sc->sc_outputgain ? 1 : 0;
898 err = 0;
899 break;
900 case HARMONY_PORT_MONITOR_LVL:
901 if (cp->type != AUDIO_MIXER_VALUE)
902 break;
903 if (cp->un.value.num_channels != 1)
904 break;
905 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
906 sc->sc_monitor_lvl.left;
907 err = 0;
908 break;
909 case HARMONY_PORT_RECORD_SOURCE:
910 if (cp->type != AUDIO_MIXER_ENUM)
911 break;
912 cp->un.ord = sc->sc_in_port;
913 err = 0;
914 break;
915 case HARMONY_PORT_OUTPUT_SOURCE:
916 if (cp->type != AUDIO_MIXER_ENUM)
917 break;
918 cp->un.ord = sc->sc_out_port;
919 err = 0;
920 break;
921 }
922 return err;
923 }
924
925 int
926 harmony_query_devinfo(void *vsc, mixer_devinfo_t *dip)
927 {
928 int err;
929
930 err = 0;
931 switch (dip->index) {
932 case HARMONY_PORT_INPUT_LVL:
933 dip->type = AUDIO_MIXER_VALUE;
934 dip->mixer_class = HARMONY_PORT_INPUT_CLASS;
935 dip->prev = dip->next = AUDIO_MIXER_LAST;
936 strlcpy(dip->label.name, AudioNinput, sizeof dip->label.name);
937 dip->un.v.num_channels = 2;
938 strlcpy(dip->un.v.units.name, AudioNvolume,
939 sizeof dip->un.v.units.name);
940 break;
941 case HARMONY_PORT_INPUT_OV:
942 dip->type = AUDIO_MIXER_ENUM;
943 dip->mixer_class = HARMONY_PORT_INPUT_CLASS;
944 dip->prev = dip->next = AUDIO_MIXER_LAST;
945 strlcpy(dip->label.name, "overrange", sizeof dip->label.name);
946 dip->un.e.num_mem = 2;
947 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
948 sizeof dip->un.e.member[0].label.name);
949 dip->un.e.member[0].ord = 0;
950 strlcpy(dip->un.e.member[1].label.name, AudioNon,
951 sizeof dip->un.e.member[1].label.name);
952 dip->un.e.member[1].ord = 1;
953 break;
954 case HARMONY_PORT_OUTPUT_LVL:
955 dip->type = AUDIO_MIXER_VALUE;
956 dip->mixer_class = HARMONY_PORT_OUTPUT_CLASS;
957 dip->prev = dip->next = AUDIO_MIXER_LAST;
958 strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
959 dip->un.v.num_channels = 2;
960 strlcpy(dip->un.v.units.name, AudioNvolume,
961 sizeof dip->un.v.units.name);
962 break;
963 case HARMONY_PORT_OUTPUT_GAIN:
964 dip->type = AUDIO_MIXER_ENUM;
965 dip->mixer_class = HARMONY_PORT_OUTPUT_CLASS;
966 dip->prev = dip->next = AUDIO_MIXER_LAST;
967 strlcpy(dip->label.name, "gain", sizeof dip->label.name);
968 dip->un.e.num_mem = 2;
969 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
970 sizeof dip->un.e.member[0].label.name);
971 dip->un.e.member[0].ord = 0;
972 strlcpy(dip->un.e.member[1].label.name, AudioNon,
973 sizeof dip->un.e.member[1].label.name);
974 dip->un.e.member[1].ord = 1;
975 break;
976 case HARMONY_PORT_MONITOR_LVL:
977 dip->type = AUDIO_MIXER_VALUE;
978 dip->mixer_class = HARMONY_PORT_MONITOR_CLASS;
979 dip->prev = dip->next = AUDIO_MIXER_LAST;
980 strlcpy(dip->label.name, AudioNmonitor, sizeof dip->label.name);
981 dip->un.v.num_channels = 1;
982 strlcpy(dip->un.v.units.name, AudioNvolume,
983 sizeof dip->un.v.units.name);
984 break;
985 case HARMONY_PORT_RECORD_SOURCE:
986 dip->type = AUDIO_MIXER_ENUM;
987 dip->mixer_class = HARMONY_PORT_RECORD_CLASS;
988 dip->prev = dip->next = AUDIO_MIXER_LAST;
989 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
990 dip->un.e.num_mem = 2;
991 strlcpy(dip->un.e.member[0].label.name, AudioNmicrophone,
992 sizeof dip->un.e.member[0].label.name);
993 dip->un.e.member[0].ord = HARMONY_IN_MIC;
994 strlcpy(dip->un.e.member[1].label.name, AudioNline,
995 sizeof dip->un.e.member[1].label.name);
996 dip->un.e.member[1].ord = HARMONY_IN_LINE;
997 break;
998 case HARMONY_PORT_OUTPUT_SOURCE:
999 dip->type = AUDIO_MIXER_ENUM;
1000 dip->mixer_class = HARMONY_PORT_MONITOR_CLASS;
1001 dip->prev = dip->next = AUDIO_MIXER_LAST;
1002 strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
1003 dip->un.e.num_mem = 3;
1004 strlcpy(dip->un.e.member[0].label.name, AudioNline,
1005 sizeof dip->un.e.member[0].label.name);
1006 dip->un.e.member[0].ord = HARMONY_OUT_LINE;
1007 strlcpy(dip->un.e.member[1].label.name, AudioNspeaker,
1008 sizeof dip->un.e.member[1].label.name);
1009 dip->un.e.member[1].ord = HARMONY_OUT_SPEAKER;
1010 strlcpy(dip->un.e.member[2].label.name, AudioNheadphone,
1011 sizeof dip->un.e.member[2].label.name);
1012 dip->un.e.member[2].ord = HARMONY_OUT_HEADPHONE;
1013 break;
1014 case HARMONY_PORT_INPUT_CLASS:
1015 dip->type = AUDIO_MIXER_CLASS;
1016 dip->mixer_class = HARMONY_PORT_INPUT_CLASS;
1017 dip->prev = dip->next = AUDIO_MIXER_LAST;
1018 strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
1019 break;
1020 case HARMONY_PORT_OUTPUT_CLASS:
1021 dip->type = AUDIO_MIXER_CLASS;
1022 dip->mixer_class = HARMONY_PORT_INPUT_CLASS;
1023 dip->prev = dip->next = AUDIO_MIXER_LAST;
1024 strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
1025 break;
1026 case HARMONY_PORT_MONITOR_CLASS:
1027 dip->type = AUDIO_MIXER_CLASS;
1028 dip->mixer_class = HARMONY_PORT_INPUT_CLASS;
1029 dip->prev = dip->next = AUDIO_MIXER_LAST;
1030 strlcpy(dip->label.name, AudioCmonitor, sizeof dip->label.name);
1031 break;
1032 case HARMONY_PORT_RECORD_CLASS:
1033 dip->type = AUDIO_MIXER_CLASS;
1034 dip->mixer_class = HARMONY_PORT_RECORD_CLASS;
1035 dip->prev = dip->next = AUDIO_MIXER_LAST;
1036 strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
1037 break;
1038 default:
1039 err = ENXIO;
1040 break;
1041 }
1042
1043 return err;
1044 }
1045
1046 void *
1047 harmony_allocm(void *vsc, int dir, size_t size)
1048 {
1049 struct harmony_softc *sc;
1050 struct harmony_dma *d;
1051 int rseg;
1052
1053 sc = vsc;
1054 d = kmem_alloc(sizeof(*d), KM_SLEEP);
1055
1056 if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, BUS_DMA_WAITOK,
1057 &d->d_map) != 0)
1058 goto fail1;
1059
1060 if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &d->d_seg, 1,
1061 &rseg, BUS_DMA_WAITOK) != 0)
1062 goto fail2;
1063
1064 if (bus_dmamem_map(sc->sc_dmat, &d->d_seg, 1, size, &d->d_kva,
1065 BUS_DMA_WAITOK) != 0)
1066 goto fail3;
1067
1068 if (bus_dmamap_load(sc->sc_dmat, d->d_map, d->d_kva, size, NULL,
1069 BUS_DMA_WAITOK) != 0)
1070 goto fail4;
1071
1072 d->d_next = sc->sc_dmas;
1073 sc->sc_dmas = d;
1074 d->d_size = size;
1075 return (d->d_kva);
1076
1077 fail4:
1078 bus_dmamem_unmap(sc->sc_dmat, d->d_kva, size);
1079 fail3:
1080 bus_dmamem_free(sc->sc_dmat, &d->d_seg, 1);
1081 fail2:
1082 bus_dmamap_destroy(sc->sc_dmat, d->d_map);
1083 fail1:
1084 kmem_free(d, sizeof(*d));
1085 return (NULL);
1086 }
1087
1088 void
1089 harmony_freem(void *vsc, void *ptr, size_t size)
1090 {
1091 struct harmony_softc *sc;
1092 struct harmony_dma *d, **dd;
1093
1094 sc = vsc;
1095 for (dd = &sc->sc_dmas; (d = *dd) != NULL; dd = &(*dd)->d_next) {
1096 if (d->d_kva != ptr)
1097 continue;
1098 bus_dmamap_unload(sc->sc_dmat, d->d_map);
1099 bus_dmamem_unmap(sc->sc_dmat, d->d_kva, d->d_size);
1100 bus_dmamem_free(sc->sc_dmat, &d->d_seg, 1);
1101 bus_dmamap_destroy(sc->sc_dmat, d->d_map);
1102 kmem_free(d, sizeof(*d));
1103 return;
1104 }
1105 printf("%s: free rogue pointer\n", device_xname(sc->sc_dv));
1106 }
1107
1108 size_t
1109 harmony_round_buffersize(void *vsc, int direction, size_t size)
1110 {
1111
1112 return ((size + HARMONY_BUFSIZE - 1) & (size_t)(-HARMONY_BUFSIZE));
1113 }
1114
1115 int
1116 harmony_get_props(void *vsc)
1117 {
1118
1119 return AUDIO_PROP_FULLDUPLEX;
1120 }
1121
1122 void
1123 harmony_get_locks(void *vsc, kmutex_t **intr, kmutex_t **thread)
1124 {
1125 struct harmony_softc *sc;
1126
1127 sc = vsc;
1128 *intr = &sc->sc_intr_lock;
1129 *thread = &sc->sc_lock;
1130 }
1131
1132 int
1133 harmony_trigger_output(void *vsc, void *start, void *end, int blksize,
1134 void (*intr)(void *), void *intrarg, const audio_params_t *param)
1135 {
1136 struct harmony_softc *sc;
1137 struct harmony_channel *c;
1138 struct harmony_dma *d;
1139
1140 sc = vsc;
1141 c = &sc->sc_playback;
1142 for (d = sc->sc_dmas; d->d_kva != start; d = d->d_next)
1143 continue;
1144 if (d == NULL) {
1145 printf("%s: trigger_output: bad addr: %p\n",
1146 device_xname(sc->sc_dv), start);
1147 return EINVAL;
1148 }
1149
1150 mutex_spin_enter(&sc->sc_intr_lock);
1151
1152 c->c_intr = intr;
1153 c->c_intrarg = intrarg;
1154 c->c_blksz = blksize;
1155 c->c_current = d;
1156 c->c_segsz = (char *)end - (char *)start;
1157 c->c_cnt = 0;
1158 c->c_lastaddr = d->d_map->dm_segs[0].ds_addr;
1159
1160 sc->sc_playing = 1;
1161
1162 harmony_start_pp(sc, 1);
1163 harmony_start_cp(sc, 0);
1164 harmony_intr_enable(sc);
1165
1166 mutex_spin_exit(&sc->sc_intr_lock);
1167
1168 return 0;
1169 }
1170
1171 void
1172 harmony_start_cp(struct harmony_softc *sc, int start)
1173 {
1174 struct harmony_channel *c;
1175 struct harmony_dma *d;
1176 bus_addr_t nextaddr;
1177 bus_size_t togo;
1178
1179 KASSERT(mutex_owned(&sc->sc_intr_lock));
1180
1181 c = &sc->sc_capture;
1182 if (sc->sc_capturing == 0)
1183 harmony_empty_input(sc);
1184 else {
1185 d = c->c_current;
1186 togo = c->c_segsz - c->c_cnt;
1187 if (togo == 0) {
1188 nextaddr = d->d_map->dm_segs[0].ds_addr;
1189 c->c_cnt = togo = c->c_blksz;
1190 } else {
1191 nextaddr = c->c_lastaddr;
1192 if (togo > c->c_blksz)
1193 togo = c->c_blksz;
1194 c->c_cnt += togo;
1195 }
1196
1197 bus_dmamap_sync(sc->sc_dmat, d->d_map,
1198 nextaddr - d->d_map->dm_segs[0].ds_addr,
1199 c->c_blksz, BUS_DMASYNC_PREWRITE);
1200
1201 WRITE_REG(sc, HARMONY_RNXTADD, nextaddr);
1202 if (start)
1203 c->c_theaddr = nextaddr;
1204 SYNC_REG(sc, HARMONY_RNXTADD, BUS_SPACE_BARRIER_WRITE);
1205 c->c_lastaddr = nextaddr + togo;
1206
1207 harmony_try_more(sc, HARMONY_RCURADD,
1208 RCURADD_BUFMASK, &sc->sc_capture);
1209 }
1210
1211 callout_schedule(&sc->sc_acc_tmo, 1);
1212 }
1213
1214 void
1215 harmony_start_pp(struct harmony_softc *sc, int start)
1216 {
1217 struct harmony_channel *c;
1218 struct harmony_dma *d;
1219 bus_addr_t nextaddr;
1220 bus_size_t togo;
1221
1222 KASSERT(mutex_owned(&sc->sc_intr_lock));
1223
1224 c = &sc->sc_playback;
1225 if (sc->sc_playing == 0)
1226 harmony_empty_output(sc);
1227 else {
1228 d = c->c_current;
1229 togo = c->c_segsz - c->c_cnt;
1230 if (togo == 0) {
1231 nextaddr = d->d_map->dm_segs[0].ds_addr;
1232 c->c_cnt = togo = c->c_blksz;
1233 } else {
1234 nextaddr = c->c_lastaddr;
1235 if (togo > c->c_blksz)
1236 togo = c->c_blksz;
1237 c->c_cnt += togo;
1238 }
1239
1240 bus_dmamap_sync(sc->sc_dmat, d->d_map,
1241 nextaddr - d->d_map->dm_segs[0].ds_addr,
1242 c->c_blksz, BUS_DMASYNC_PREWRITE);
1243
1244 WRITE_REG(sc, HARMONY_PNXTADD, nextaddr);
1245 if (start)
1246 c->c_theaddr = nextaddr;
1247 SYNC_REG(sc, HARMONY_PNXTADD, BUS_SPACE_BARRIER_WRITE);
1248 c->c_lastaddr = nextaddr + togo;
1249
1250 harmony_try_more(sc, HARMONY_PCURADD,
1251 PCURADD_BUFMASK, &sc->sc_playback);
1252 }
1253 }
1254
1255 int
1256 harmony_trigger_input(void *vsc, void *start, void *end, int blksize,
1257 void (*intr)(void *), void *intrarg, const audio_params_t *param)
1258 {
1259 struct harmony_softc *sc = vsc;
1260 struct harmony_channel *c = &sc->sc_capture;
1261 struct harmony_dma *d;
1262
1263 KASSERT(mutex_owned(&sc->sc_intr_lock));
1264
1265 for (d = sc->sc_dmas; d->d_kva != start; d = d->d_next)
1266 continue;
1267 if (d == NULL) {
1268 printf("%s: trigger_input: bad addr: %p\n",
1269 device_xname(sc->sc_dv), start);
1270 return EINVAL;
1271 }
1272
1273 c->c_intr = intr;
1274 c->c_intrarg = intrarg;
1275 c->c_blksz = blksize;
1276 c->c_current = d;
1277 c->c_segsz = (char *)end - (char *)start;
1278 c->c_cnt = 0;
1279 c->c_lastaddr = d->d_map->dm_segs[0].ds_addr;
1280
1281 sc->sc_capturing = 1;
1282
1283 harmony_start_cp(sc, 1);
1284 harmony_intr_enable(sc);
1285
1286 return 0;
1287 }
1288
1289 static const struct speed_struct {
1290 uint32_t speed;
1291 uint32_t bits;
1292 } harmony_speeds[] = {
1293 { 5125, CNTL_RATE_5125 },
1294 { 6615, CNTL_RATE_6615 },
1295 { 8000, CNTL_RATE_8000 },
1296 { 9600, CNTL_RATE_9600 },
1297 { 11025, CNTL_RATE_11025 },
1298 { 16000, CNTL_RATE_16000 },
1299 { 18900, CNTL_RATE_18900 },
1300 { 22050, CNTL_RATE_22050 },
1301 { 27428, CNTL_RATE_27428 },
1302 { 32000, CNTL_RATE_32000 },
1303 { 33075, CNTL_RATE_33075 },
1304 { 37800, CNTL_RATE_37800 },
1305 { 44100, CNTL_RATE_44100 },
1306 { 48000, CNTL_RATE_48000 },
1307 };
1308
1309 uint32_t
1310 harmony_speed_bits(struct harmony_softc *sc, u_int *speedp)
1311 {
1312 int i, n, selected;
1313
1314 selected = -1;
1315 n = sizeof(harmony_speeds) / sizeof(harmony_speeds[0]);
1316
1317 if ((*speedp) <= harmony_speeds[0].speed)
1318 selected = 0;
1319 else if ((*speedp) >= harmony_speeds[n - 1].speed)
1320 selected = n - 1;
1321 else {
1322 for (i = 1; selected == -1 && i < n; i++) {
1323 if ((*speedp) == harmony_speeds[i].speed)
1324 selected = i;
1325 else if ((*speedp) < harmony_speeds[i].speed) {
1326 int diff1, diff2;
1327
1328 diff1 = (*speedp) - harmony_speeds[i - 1].speed;
1329 diff2 = harmony_speeds[i].speed - (*speedp);
1330 if (diff1 < diff2)
1331 selected = i - 1;
1332 else
1333 selected = i;
1334 }
1335 }
1336 }
1337
1338 if (selected == -1)
1339 selected = 2;
1340
1341 *speedp = harmony_speeds[selected].speed;
1342 return harmony_speeds[selected].bits;
1343 }
1344
1345 int
1346 harmony_set_gainctl(struct harmony_softc *sc)
1347 {
1348 uint32_t bits, mask, val, old;
1349
1350 /* XXX leave these bits alone or the chip will not come out of CNTL */
1351 bits = GAINCTL_LE | GAINCTL_HE | GAINCTL_SE | GAINCTL_IS_MASK;
1352
1353 /* input level */
1354 bits |= ((sc->sc_input_lvl.left >> (8 - GAINCTL_INPUT_BITS)) <<
1355 GAINCTL_INPUT_LEFT_S) & GAINCTL_INPUT_LEFT_M;
1356 bits |= ((sc->sc_input_lvl.right >> (8 - GAINCTL_INPUT_BITS)) <<
1357 GAINCTL_INPUT_RIGHT_S) & GAINCTL_INPUT_RIGHT_M;
1358
1359 /* output level (inverted) */
1360 mask = (1 << GAINCTL_OUTPUT_BITS) - 1;
1361 val = mask - (sc->sc_output_lvl.left >> (8 - GAINCTL_OUTPUT_BITS));
1362 bits |= (val << GAINCTL_OUTPUT_LEFT_S) & GAINCTL_OUTPUT_LEFT_M;
1363 val = mask - (sc->sc_output_lvl.right >> (8 - GAINCTL_OUTPUT_BITS));
1364 bits |= (val << GAINCTL_OUTPUT_RIGHT_S) & GAINCTL_OUTPUT_RIGHT_M;
1365
1366 /* monitor level (inverted) */
1367 mask = (1 << GAINCTL_MONITOR_BITS) - 1;
1368 val = mask - (sc->sc_monitor_lvl.left >> (8 - GAINCTL_MONITOR_BITS));
1369 bits |= (val << GAINCTL_MONITOR_S) & GAINCTL_MONITOR_M;
1370
1371 /* XXX messing with these causes CNTL_C to get stuck... grr. */
1372 bits &= ~GAINCTL_IS_MASK;
1373 if (sc->sc_in_port == HARMONY_IN_MIC)
1374 bits |= GAINCTL_IS_LINE;
1375 else
1376 bits |= GAINCTL_IS_MICROPHONE;
1377
1378 /* XXX messing with these causes CNTL_C to get stuck... grr. */
1379 bits &= ~(GAINCTL_LE | GAINCTL_HE | GAINCTL_SE);
1380 if (sc->sc_out_port == HARMONY_OUT_LINE)
1381 bits |= GAINCTL_LE;
1382 else if (sc->sc_out_port == HARMONY_OUT_SPEAKER)
1383 bits |= GAINCTL_SE;
1384 else
1385 bits |= GAINCTL_HE;
1386
1387 mask = GAINCTL_LE | GAINCTL_HE | GAINCTL_SE | GAINCTL_IS_MASK;
1388 old = bus_space_read_4(sc->sc_bt, sc->sc_bh, HARMONY_GAINCTL);
1389 bus_space_write_4(sc->sc_bt, sc->sc_bh, HARMONY_GAINCTL, bits);
1390 if ((old & mask) != (bits & mask))
1391 return 1;
1392 return 0;
1393 }
1394
1395 void
1396 harmony_try_more(struct harmony_softc *sc, int curadd, int bufmask,
1397 struct harmony_channel *c)
1398 {
1399 struct harmony_dma *d;
1400 uint32_t cur;
1401 int i, nsegs;
1402
1403 d = c->c_current;
1404 cur = bus_space_read_4(sc->sc_bt, sc->sc_bh, curadd);
1405 cur &= bufmask;
1406 nsegs = 0;
1407
1408 #ifdef DIAGNOSTIC
1409 if (cur < d->d_map->dm_segs[0].ds_addr ||
1410 cur >= (d->d_map->dm_segs[0].ds_addr + c->c_segsz))
1411 panic("%s: bad current %x < %lx || %x > %lx",
1412 device_xname(sc->sc_dv), cur,
1413 d->d_map->dm_segs[0].ds_addr, cur,
1414 d->d_map->dm_segs[0].ds_addr + c->c_segsz);
1415 #endif /* DIAGNOSTIC */
1416
1417 if (cur > c->c_theaddr) {
1418 nsegs = (cur - c->c_theaddr) / HARMONY_BUFSIZE;
1419 } else if (cur < c->c_theaddr) {
1420 nsegs = (d->d_map->dm_segs[0].ds_addr + c->c_segsz -
1421 c->c_theaddr) / HARMONY_BUFSIZE;
1422 nsegs += (cur - d->d_map->dm_segs[0].ds_addr) /
1423 HARMONY_BUFSIZE;
1424 }
1425
1426 if (nsegs != 0 && c->c_intr != NULL) {
1427 for (i = 0; i < nsegs; i++)
1428 (*c->c_intr)(c->c_intrarg);
1429 c->c_theaddr = cur;
1430 }
1431 }
1432