Lines Matching +full:pcm +full:- +full:interface +full:- +full:rate

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2012-2021 Ruslan Bukin <br@bsdpad.com>
5 * Copyright (c) 2023-2024 Florian Walpen <dev@submerge.ch>
31 * RME HDSP driver for FreeBSD (pcm-part).
37 #include <dev/sound/pcm/sound.h>
88 /* ADAT slot bitmap depends on sample rate. */ in hdsp_adat_slot_map()
130 return (slots & (~(slots - 1))); /* Extract first bit set. */ in hdsp_slot_first()
141 return (slots & (ends ^ (ends - 1))); in hdsp_slot_first_row()
150 --n; in hdsp_slot_first_n()
166 return (hdsp_slot_count(hdsp_slot_first(slots) - 1)); in hdsp_slot_offset()
177 preceding = slots & (hdsp_slot_first(subset) - 1); in hdsp_slot_channel_offset()
185 return (ports & (~(ports - 1))); /* Extract first bit set. */ in hdsp_port_first()
203 return (hc->ports & (HDSP_CHAN_9632_ALL | HDSP_CHAN_9652_ALL)); in hdsp_channel_play_ports()
209 return (hc->ports & (HDSP_CHAN_9632_ALL | HDSP_CHAN_9652_ALL)); in hdsp_channel_rec_ports()
221 scp = ch->parent; in hdsp_hw_mixer()
222 sc = scp->sc; in hdsp_hw_mixer()
227 if (ch->dir != PCMDIR_PLAY) in hdsp_hw_mixer()
230 switch (sc->type) { in hdsp_hw_mixer()
255 offset -= 1; in hdsp_hw_mixer()
273 ports = ch->ports; in hdspchan_setgain()
285 volume = ch->lvol * HDSP_MAX_GAIN / 100; in hdspchan_setgain()
294 volume = ch->rvol * HDSP_MAX_GAIN / 100; in hdspchan_setgain()
312 sc = scp->sc; in hdspmixer_init()
314 return (-1); in hdspmixer_init()
318 if (hdsp_channel_play_ports(scp->hc)) in hdspmixer_init()
321 if (hdsp_channel_rec_ports(scp->hc)) in hdspmixer_init()
324 snd_mtxlock(sc->lock); in hdspmixer_init()
325 pcm_setflags(scp->dev, pcm_getflags(scp->dev) | SD_F_SOFTPCMVOL); in hdspmixer_init()
327 snd_mtxunlock(sc->lock); in hdspmixer_init()
343 device_printf(scp->dev, "hdspmixer_set() %d %d\n", in hdspmixer_set()
347 for (i = 0; i < scp->chnum; i++) { in hdspmixer_set()
348 ch = &scp->chan[i]; in hdspmixer_set()
349 if ((dev == SOUND_MIXER_VOLUME && ch->dir == PCMDIR_PLAY) || in hdspmixer_set()
350 (dev == SOUND_MIXER_RECLEV && ch->dir == PCMDIR_REC)) { in hdspmixer_set()
351 ch->lvol = left; in hdspmixer_set()
352 ch->rvol = right; in hdspmixer_set()
353 if (ch->run) in hdspmixer_set()
377 scp = ch->parent; in hdspchan_enable()
378 sc = scp->sc; in hdspchan_enable()
380 if (ch->dir == PCMDIR_PLAY) in hdspchan_enable()
385 ch->run = value; in hdspchan_enable()
388 slots = hdsp_port_slot_map(ch->ports, sc->speed); in hdspchan_enable()
415 if (device_get_children(sc->dev, &devlist, &devcount) != 0) in hdsp_running()
420 for (j = 0; j < scp->chnum; j++) { in hdsp_running()
421 ch = &scp->chan[j]; in hdsp_running()
422 if (ch->run) { in hdsp_running()
431 device_printf(sc->dev, "hdsp is running\n"); in hdsp_running()
443 sc->ctrl_register |= (HDSP_AUDIO_INT_ENABLE | HDSP_ENABLE); in hdsp_start_audio()
444 hdsp_write_4(sc, HDSP_CONTROL_REG, sc->ctrl_register); in hdsp_start_audio()
454 sc->ctrl_register &= ~(HDSP_AUDIO_INT_ENABLE | HDSP_ENABLE); in hdsp_stop_audio()
455 hdsp_write_4(sc, HDSP_CONTROL_REG, sc->ctrl_register); in hdsp_stop_audio()
459 buffer_mux_write(uint32_t *dma, uint32_t *pcm, unsigned int pos, in buffer_mux_write() argument
467 pcm[pos * channels + slot]; in buffer_mux_write()
473 buffer_mux_port(uint32_t *dma, uint32_t *pcm, uint32_t subset, uint32_t slots, in buffer_mux_port() argument
485 pcm += chan_pos; in buffer_mux_port()
487 /* Only copy channels supported by both hardware and pcm format. */ in buffer_mux_port()
492 buffer_mux_write(dma, pcm, pos, pos + samples, 1, channels); in buffer_mux_port()
494 buffer_mux_write(dma, pcm, pos, pos + samples, 2, channels); in buffer_mux_port()
496 buffer_mux_write(dma, pcm, pos, pos + samples, 4, channels); in buffer_mux_port()
498 buffer_mux_write(dma, pcm, pos, pos + samples, 8, channels); in buffer_mux_port()
500 buffer_mux_write(dma, pcm, pos, pos + samples, width, channels); in buffer_mux_port()
504 buffer_demux_read(uint32_t *dma, uint32_t *pcm, unsigned int pos, in buffer_demux_read() argument
511 pcm[pos * channels + slot] = in buffer_demux_read()
518 buffer_demux_port(uint32_t *dma, uint32_t *pcm, uint32_t subset, uint32_t slots, in buffer_demux_port() argument
530 pcm += chan_pos; in buffer_demux_port()
532 /* Only copy channels supported by both hardware and pcm format. */ in buffer_demux_port()
537 buffer_demux_read(dma, pcm, pos, pos + samples, 1, channels); in buffer_demux_port()
539 buffer_demux_read(dma, pcm, pos, pos + samples, 2, channels); in buffer_demux_port()
541 buffer_demux_read(dma, pcm, pos, pos + samples, 4, channels); in buffer_demux_port()
543 buffer_demux_read(dma, pcm, pos, pos + samples, 8, channels); in buffer_demux_port()
545 buffer_demux_read(dma, pcm, pos, pos + samples, width, channels); in buffer_demux_port()
549 /* Copy data between DMA and PCM buffers. */
560 scp = ch->parent; in buffer_copy()
561 sc = scp->sc; in buffer_copy()
563 channels = AFMT_CHANNEL(ch->format); /* Number of PCM channels. */ in buffer_copy()
566 buffer_size = 2 * sc->period * sizeof(uint32_t); in buffer_copy()
569 if (ch->dir == PCMDIR_PLAY) { in buffer_copy()
571 pos = sndbuf_getreadyptr(ch->buffer) / channels; in buffer_copy()
572 length = sndbuf_getready(ch->buffer) / channels; in buffer_copy()
577 offset = (ch->position + buffer_size) - pos; in buffer_copy()
581 length -= offset; in buffer_copy()
585 pos = sndbuf_getfreeptr(ch->buffer) / channels; in buffer_copy()
591 length = (dma_pos + buffer_size) - pos; in buffer_copy()
603 remainder = (pos + length) - buffer_size; in buffer_copy()
606 slots = hdsp_port_slot_map(ch->ports, sc->speed); in buffer_copy()
611 if (ch->dir == PCMDIR_PLAY) { in buffer_copy()
612 buffer_mux_port(sc->pbuf, ch->data, row, slots, pos, in buffer_copy()
613 length - remainder, channels); in buffer_copy()
614 buffer_mux_port(sc->pbuf, ch->data, row, slots, 0, in buffer_copy()
617 buffer_demux_port(sc->rbuf, ch->data, row, slots, pos, in buffer_copy()
618 length - remainder, channels); in buffer_copy()
619 buffer_demux_port(sc->rbuf, ch->data, row, slots, 0, in buffer_copy()
627 ch->position = ((pos + length) * 4) % buffer_size; in buffer_copy()
639 scp = ch->parent; in clean()
640 sc = scp->sc; in clean()
641 buf = sc->rbuf; in clean()
643 if (ch->dir == PCMDIR_PLAY) in clean()
644 buf = sc->pbuf; in clean()
647 slots = hdsp_port_slot_map(ch->ports, sc->speed); in clean()
658 ch->position = 0; in clean()
663 /* Channel interface. */
672 scp = ch->parent; in hdspchan_free()
673 sc = scp->sc; in hdspchan_free()
676 device_printf(scp->dev, "hdspchan_free()\n"); in hdspchan_free()
679 snd_mtxlock(sc->lock); in hdspchan_free()
680 if (ch->data != NULL) { in hdspchan_free()
681 free(ch->data, M_HDSP); in hdspchan_free()
682 ch->data = NULL; in hdspchan_free()
684 if (ch->caps != NULL) { in hdspchan_free()
685 free(ch->caps, M_HDSP); in hdspchan_free()
686 ch->caps = NULL; in hdspchan_free()
688 snd_mtxunlock(sc->lock); in hdspchan_free()
703 sc = scp->sc; in hdspchan_init()
705 snd_mtxlock(sc->lock); in hdspchan_init()
706 num = scp->chnum; in hdspchan_init()
708 ch = &scp->chan[num]; in hdspchan_init()
711 ch->ports = hdsp_channel_play_ports(scp->hc); in hdspchan_init()
713 ch->ports = hdsp_channel_rec_ports(scp->hc); in hdspchan_init()
715 ch->run = 0; in hdspchan_init()
716 ch->lvol = 0; in hdspchan_init()
717 ch->rvol = 0; in hdspchan_init()
720 ch->cap_fmts[0] = in hdspchan_init()
721 SND_FORMAT(AFMT_S32_LE, hdsp_port_slot_count(ch->ports, 48000), 0); in hdspchan_init()
722 ch->cap_fmts[1] = in hdspchan_init()
723 SND_FORMAT(AFMT_S32_LE, hdsp_port_slot_count(ch->ports, 96000), 0); in hdspchan_init()
724 ch->cap_fmts[2] = in hdspchan_init()
725 SND_FORMAT(AFMT_S32_LE, hdsp_port_slot_count(ch->ports, 192000), 0); in hdspchan_init()
726 ch->cap_fmts[3] = 0; in hdspchan_init()
728 ch->caps = malloc(sizeof(struct pcmchan_caps), M_HDSP, M_NOWAIT); in hdspchan_init()
729 *(ch->caps) = (struct pcmchan_caps) {32000, 192000, ch->cap_fmts, 0}; in hdspchan_init()
732 if (sc->type == HDSP_9652) { in hdspchan_init()
733 ch->cap_fmts[2] = SND_FORMAT(AFMT_S32_LE, 2, 0); in hdspchan_init()
734 ch->caps->maxspeed = 96000; in hdspchan_init()
738 ch->size = HDSP_CHANBUF_SIZE * hdsp_port_slot_count_max(ch->ports); in hdspchan_init()
739 ch->data = malloc(ch->size, M_HDSP, M_NOWAIT); in hdspchan_init()
740 ch->position = 0; in hdspchan_init()
742 ch->buffer = b; in hdspchan_init()
743 ch->channel = c; in hdspchan_init()
744 ch->parent = scp; in hdspchan_init()
746 ch->dir = dir; in hdspchan_init()
748 snd_mtxunlock(sc->lock); in hdspchan_init()
750 if (sndbuf_setup(ch->buffer, ch->data, ch->size) != 0) { in hdspchan_init()
751 device_printf(scp->dev, "Can't setup sndbuf.\n"); in hdspchan_init()
767 scp = ch->parent; in hdspchan_trigger()
768 sc = scp->sc; in hdspchan_trigger()
770 snd_mtxlock(sc->lock); in hdspchan_trigger()
774 device_printf(scp->dev, "hdspchan_trigger(): start\n"); in hdspchan_trigger()
784 device_printf(scp->dev, "hdspchan_trigger(): stop or abort\n"); in hdspchan_trigger()
793 if(ch->run) in hdspchan_trigger()
798 snd_mtxunlock(sc->lock); in hdspchan_trigger()
812 scp = ch->parent; in hdspchan_getptr()
813 sc = scp->sc; in hdspchan_getptr()
815 snd_mtxlock(sc->lock); in hdspchan_getptr()
817 snd_mtxunlock(sc->lock); in hdspchan_getptr()
820 pos %= (2 * sc->period * sizeof(uint32_t)); /* Double buffer. */ in hdspchan_getptr()
821 pos *= AFMT_CHANNEL(ch->format); /* Hardbuf with multiple channels. */ in hdspchan_getptr()
834 struct sc_pcminfo *scp = ch->parent; in hdspchan_setformat()
835 device_printf(scp->dev, "hdspchan_setformat(%d)\n", format); in hdspchan_setformat()
838 ch->format = format; in hdspchan_setformat()
854 scp = ch->parent; in hdspchan_setspeed()
855 sc = scp->sc; in hdspchan_setspeed()
859 device_printf(scp->dev, "hdspchan_setspeed(%d)\n", speed); in hdspchan_setspeed()
866 if (sc->type == HDSP_9652 && speed > 96000) in hdspchan_setspeed()
869 if (sc->force_speed > 0) in hdspchan_setspeed()
870 speed = sc->force_speed; in hdspchan_setspeed()
882 threshold = hr->speed + ((rate_map[i + 1].speed != 0) ? in hdspchan_setspeed()
883 ((rate_map[i + 1].speed - hr->speed) >> 1) : 0); in hdspchan_setspeed()
890 sc->ctrl_register &= ~HDSP_FREQ_MASK; in hdspchan_setspeed()
891 sc->ctrl_register |= hr->reg; in hdspchan_setspeed()
892 hdsp_write_4(sc, HDSP_CONTROL_REG, sc->ctrl_register); in hdspchan_setspeed()
894 if (sc->type == HDSP_9632) { in hdspchan_setspeed()
896 hdsp_write_4(sc, HDSP_FREQ_REG, hdsp_freq_reg_value(hr->speed)); in hdspchan_setspeed()
899 sc->speed = hr->speed; in hdspchan_setspeed()
902 return (sc->speed); in hdspchan_setspeed()
916 scp = ch->parent; in hdspchan_setblocksize()
917 sc = scp->sc; in hdspchan_setblocksize()
921 device_printf(scp->dev, "hdspchan_setblocksize(%d)\n", blocksize); in hdspchan_setblocksize()
934 if (sc->force_period > 0) in hdspchan_setblocksize()
935 blocksize = sc->force_period; in hdspchan_setblocksize()
947 threshold = hl->period + ((latency_map[i + 1].period != 0) ? in hdspchan_setblocksize()
948 ((latency_map[i + 1].period - hl->period) >> 1) : 0); in hdspchan_setblocksize()
954 snd_mtxlock(sc->lock); in hdspchan_setblocksize()
955 sc->ctrl_register &= ~HDSP_LAT_MASK; in hdspchan_setblocksize()
956 sc->ctrl_register |= hdsp_encode_latency(hl->n); in hdspchan_setblocksize()
957 hdsp_write_4(sc, HDSP_CONTROL_REG, sc->ctrl_register); in hdspchan_setblocksize()
958 sc->period = hl->period; in hdspchan_setblocksize()
959 snd_mtxunlock(sc->lock); in hdspchan_setblocksize()
962 device_printf(scp->dev, "New period=%d\n", sc->period); in hdspchan_setblocksize()
965 sndbuf_resize(ch->buffer, 2, in hdspchan_setblocksize()
966 (sc->period * AFMT_CHANNEL(ch->format) * sizeof(uint32_t))); in hdspchan_setblocksize()
970 if (sc->type == HDSP_9632) in hdspchan_setblocksize()
971 hdsp_write_4(sc, HDSP_FREQ_REG, hdsp_freq_reg_value(sc->speed)); in hdspchan_setblocksize()
974 return (sndbuf_getblksz(ch->buffer)); in hdspchan_setblocksize()
993 device_printf(ch->parent->dev, "hdspchan_getcaps()\n"); in hdspchan_getcaps()
996 if (ch->caps != NULL) in hdspchan_getcaps()
997 return (ch->caps); in hdspchan_getcaps()
1033 sc = scp->sc; in hdsp_pcm_intr()
1035 for (i = 0; i < scp->chnum; i++) { in hdsp_pcm_intr()
1036 ch = &scp->chan[i]; in hdsp_pcm_intr()
1037 snd_mtxunlock(sc->lock); in hdsp_pcm_intr()
1038 chn_intr(ch->channel); in hdsp_pcm_intr()
1039 snd_mtxlock(sc->lock); in hdsp_pcm_intr()
1056 scp->ih = &hdsp_pcm_intr; in hdsp_pcm_attach()
1058 if (scp->hc->ports & HDSP_CHAN_9632_ALL) in hdsp_pcm_attach()
1060 else if (scp->hc->ports & HDSP_CHAN_9652_ALL) in hdsp_pcm_attach()
1064 device_set_descf(dev, "HDSP %s [%s]", buf, scp->hc->descr); in hdsp_pcm_attach()
1068 * in pcm device. Mark pcm device as MPSAFE manually. in hdsp_pcm_attach()
1071 if (hdsp_port_slot_count_max(scp->hc->ports) > HDSP_MATRIX_MAX) in hdsp_pcm_attach()
1078 play = (hdsp_channel_play_ports(scp->hc)) ? 1 : 0; in hdsp_pcm_attach()
1079 rec = (hdsp_channel_rec_ports(scp->hc)) ? 1 : 0; in hdsp_pcm_attach()
1081 scp->chnum = 0; in hdsp_pcm_attach()
1084 scp->chnum++; in hdsp_pcm_attach()
1089 scp->chnum++; in hdsp_pcm_attach()
1093 rman_get_start(scp->sc->cs), in hdsp_pcm_attach()
1094 rman_get_start(scp->sc->irq), in hdsp_pcm_attach()
1098 device_printf(dev, "Can't register pcm.\n"); in hdsp_pcm_attach()
1129 "pcm",