Lines Matching +full:pcm +full:- +full:clock +full:- +full:mode

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2012-2016 Ruslan Bukin <br@bsdpad.com>
5 * Copyright (c) 2023-2024 Florian Walpen <dev@submerge.ch>
38 #include <dev/sound/pcm/sound.h>
52 &hdsp_unified_pcm, 0, "Combine physical ports in one unified pcm device");
112 snd_mtxlock(sc->lock); in hdsp_intr()
116 if ((err = device_get_children(sc->dev, &devlist, &devcount)) != 0) in hdsp_intr()
121 if (scp->ih != NULL) in hdsp_intr()
122 scp->ih(scp); in hdsp_intr()
129 snd_mtxunlock(sc->lock); in hdsp_intr()
136 device_printf(sc->dev, "hdsp_dmapsetmap()\n"); in hdsp_dmapsetmap()
145 sc->csid = PCIR_BAR(0); in hdsp_alloc_resources()
146 sc->cs = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, in hdsp_alloc_resources()
147 &sc->csid, RF_ACTIVE); in hdsp_alloc_resources()
149 if (!sc->cs) { in hdsp_alloc_resources()
150 device_printf(sc->dev, "Unable to map SYS_RES_MEMORY.\n"); in hdsp_alloc_resources()
154 sc->cst = rman_get_bustag(sc->cs); in hdsp_alloc_resources()
155 sc->csh = rman_get_bushandle(sc->cs); in hdsp_alloc_resources()
158 sc->irqid = 0; in hdsp_alloc_resources()
159 sc->irq = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &sc->irqid, in hdsp_alloc_resources()
162 if (!sc->irq || in hdsp_alloc_resources()
163 bus_setup_intr(sc->dev, sc->irq, INTR_MPSAFE | INTR_TYPE_AV, in hdsp_alloc_resources()
164 NULL, hdsp_intr, sc, &sc->ih)) { in hdsp_alloc_resources()
165 device_printf(sc->dev, "Unable to alloc interrupt resource.\n"); in hdsp_alloc_resources()
170 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev), in hdsp_alloc_resources()
183 /*dmatag*/&sc->dmat) != 0) { in hdsp_alloc_resources()
184 device_printf(sc->dev, "Unable to create dma tag.\n"); in hdsp_alloc_resources()
188 sc->bufsize = HDSP_DMASEGSIZE; in hdsp_alloc_resources()
191 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_WAITOK, in hdsp_alloc_resources()
192 &sc->pmap)) { in hdsp_alloc_resources()
193 device_printf(sc->dev, "Can't alloc pbuf.\n"); in hdsp_alloc_resources()
197 if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->bufsize, in hdsp_alloc_resources()
199 device_printf(sc->dev, "Can't load pbuf.\n"); in hdsp_alloc_resources()
204 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_WAITOK, in hdsp_alloc_resources()
205 &sc->rmap)) { in hdsp_alloc_resources()
206 device_printf(sc->dev, "Can't alloc rbuf.\n"); in hdsp_alloc_resources()
210 if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->bufsize, in hdsp_alloc_resources()
212 device_printf(sc->dev, "Can't load rbuf.\n"); in hdsp_alloc_resources()
216 bzero(sc->pbuf, sc->bufsize); in hdsp_alloc_resources()
217 bzero(sc->rbuf, sc->bufsize); in hdsp_alloc_resources()
227 paddr = vtophys(sc->pbuf); in hdsp_map_dmabuf()
228 raddr = vtophys(sc->rbuf); in hdsp_map_dmabuf()
243 return ("-10dBV"); in hdsp_control_input_level()
258 sc = oidp->oid_arg1; in hdsp_sysctl_input_level()
261 if (sc->type != HDSP_9632) in hdsp_sysctl_input_level()
265 control = sc->ctrl_register & HDSP_INPUT_LEVEL_MASK; in hdsp_sysctl_input_level()
272 if (error != 0 || req->newptr == NULL) in hdsp_sysctl_input_level()
288 if (control != (sc->ctrl_register & HDSP_INPUT_LEVEL_MASK)) { in hdsp_sysctl_input_level()
289 snd_mtxlock(sc->lock); in hdsp_sysctl_input_level()
290 sc->ctrl_register &= ~HDSP_INPUT_LEVEL_MASK; in hdsp_sysctl_input_level()
291 sc->ctrl_register |= control; in hdsp_sysctl_input_level()
292 hdsp_write_4(sc, HDSP_CONTROL_REG, sc->ctrl_register); in hdsp_sysctl_input_level()
293 snd_mtxunlock(sc->lock); in hdsp_sysctl_input_level()
303 return ("-10dBV"); in hdsp_control_output_level()
322 sc = oidp->oid_arg1; in hdsp_sysctl_output_level()
325 if (sc->type != HDSP_9632) in hdsp_sysctl_output_level()
329 control = sc->ctrl_register & HDSP_OUTPUT_LEVEL_MASK; in hdsp_sysctl_output_level()
336 if (error != 0 || req->newptr == NULL) in hdsp_sysctl_output_level()
352 if (control != (sc->ctrl_register & HDSP_OUTPUT_LEVEL_MASK)) { in hdsp_sysctl_output_level()
353 snd_mtxlock(sc->lock); in hdsp_sysctl_output_level()
354 sc->ctrl_register &= ~HDSP_OUTPUT_LEVEL_MASK; in hdsp_sysctl_output_level()
355 sc->ctrl_register |= control; in hdsp_sysctl_output_level()
356 hdsp_write_4(sc, HDSP_CONTROL_REG, sc->ctrl_register); in hdsp_sysctl_output_level()
357 snd_mtxunlock(sc->lock); in hdsp_sysctl_output_level()
367 return ("-12dB"); in hdsp_control_phones_level()
369 return ("-6dB"); in hdsp_control_phones_level()
386 sc = oidp->oid_arg1; in hdsp_sysctl_phones_level()
389 if (sc->type != HDSP_9632) in hdsp_sysctl_phones_level()
393 control = sc->ctrl_register & HDSP_PHONES_LEVEL_MASK; in hdsp_sysctl_phones_level()
400 if (error != 0 || req->newptr == NULL) in hdsp_sysctl_phones_level()
416 if (control != (sc->ctrl_register & HDSP_PHONES_LEVEL_MASK)) { in hdsp_sysctl_phones_level()
417 snd_mtxlock(sc->lock); in hdsp_sysctl_phones_level()
418 sc->ctrl_register &= ~HDSP_PHONES_LEVEL_MASK; in hdsp_sysctl_phones_level()
419 sc->ctrl_register |= control; in hdsp_sysctl_phones_level()
420 hdsp_write_4(sc, HDSP_CONTROL_REG, sc->ctrl_register); in hdsp_sysctl_phones_level()
421 snd_mtxunlock(sc->lock); in hdsp_sysctl_phones_level()
429 struct sc_info *sc = oidp->oid_arg1; in hdsp_sysctl_sample_rate()
433 speed = sc->force_speed; in hdsp_sysctl_sample_rate()
437 if (error != 0 || req->newptr == NULL) in hdsp_sysctl_sample_rate()
440 /* Speed from 32000 to 192000, 0 falls back to pcm speed setting. */ in hdsp_sysctl_sample_rate()
441 sc->force_speed = 0; in hdsp_sysctl_sample_rate()
444 if ((speed > (96000 + 128000) / 2) && sc->type == HDSP_9632) in hdsp_sysctl_sample_rate()
450 sc->force_speed = 32000 * multiplier; in hdsp_sysctl_sample_rate()
452 sc->force_speed = 44100 * multiplier; in hdsp_sysctl_sample_rate()
454 sc->force_speed = 48000 * multiplier; in hdsp_sysctl_sample_rate()
464 struct sc_info *sc = oidp->oid_arg1; in hdsp_sysctl_period()
468 period = sc->force_period; in hdsp_sysctl_period()
472 if (error != 0 || req->newptr == NULL) in hdsp_sysctl_period()
475 /* Period is from 2^5 to 2^14, 0 falls back to pcm latency settings. */ in hdsp_sysctl_period()
476 sc->force_period = 0; in hdsp_sysctl_period()
478 sc->force_period = 32; in hdsp_sysctl_period()
479 while (sc->force_period < period && sc->force_period < 4096) in hdsp_sysctl_period()
480 sc->force_period <<= 1; in hdsp_sysctl_period()
513 struct hdsp_clock_source *clock_table, *clock; in hdsp_sysctl_clock_preference() local
518 sc = oidp->oid_arg1; in hdsp_sysctl_clock_preference()
521 if (sc->type == HDSP_9632) in hdsp_sysctl_clock_preference()
523 else if (sc->type == HDSP_9652) in hdsp_sysctl_clock_preference()
528 /* Extract preferred clock source from control register. */ in hdsp_sysctl_clock_preference()
529 control = sc->ctrl_register & HDSP_CONTROL_CLOCK_MASK; in hdsp_sysctl_clock_preference()
530 for (clock = clock_table; clock->name != NULL; ++clock) { in hdsp_sysctl_clock_preference()
531 if (hdsp_control_clock_preference(clock->type) == control) in hdsp_sysctl_clock_preference()
534 if (clock->name != NULL) in hdsp_sysctl_clock_preference()
535 strlcpy(buf, clock->name, sizeof(buf)); in hdsp_sysctl_clock_preference()
539 if (error != 0 || req->newptr == NULL) in hdsp_sysctl_clock_preference()
542 /* Find clock source matching the sysctl string. */ in hdsp_sysctl_clock_preference()
543 for (clock = clock_table; clock->name != NULL; ++clock) { in hdsp_sysctl_clock_preference()
544 if (strncasecmp(buf, clock->name, sizeof(buf)) == 0) in hdsp_sysctl_clock_preference()
548 /* Set preferred clock source in control register. */ in hdsp_sysctl_clock_preference()
549 if (clock->name != NULL) { in hdsp_sysctl_clock_preference()
550 control = hdsp_control_clock_preference(clock->type); in hdsp_sysctl_clock_preference()
552 snd_mtxlock(sc->lock); in hdsp_sysctl_clock_preference()
553 sc->ctrl_register &= ~HDSP_CONTROL_CLOCK_MASK; in hdsp_sysctl_clock_preference()
554 sc->ctrl_register |= control; in hdsp_sysctl_clock_preference()
555 hdsp_write_4(sc, HDSP_CONTROL_REG, sc->ctrl_register); in hdsp_sysctl_clock_preference()
556 snd_mtxunlock(sc->lock); in hdsp_sysctl_clock_preference()
588 struct hdsp_clock_source *clock_table, *clock; in hdsp_sysctl_clock_source() local
592 sc = oidp->oid_arg1; in hdsp_sysctl_clock_source()
595 if (sc->type == HDSP_9632) in hdsp_sysctl_clock_source()
597 else if (sc->type == HDSP_9652) in hdsp_sysctl_clock_source()
602 /* Read current (autosync) clock source from status2 register. */ in hdsp_sysctl_clock_source()
603 snd_mtxlock(sc->lock); in hdsp_sysctl_clock_source()
606 snd_mtxunlock(sc->lock); in hdsp_sysctl_clock_source()
608 /* Translate status2 register value to clock source. */ in hdsp_sysctl_clock_source()
609 for (clock = clock_table; clock->name != NULL; ++clock) { in hdsp_sysctl_clock_source()
610 /* In clock master mode, override with internal clock source. */ in hdsp_sysctl_clock_source()
611 if (sc->ctrl_register & HDSP_CONTROL_MASTER) { in hdsp_sysctl_clock_source()
612 if (clock->type == HDSP_CLOCK_INTERNAL) in hdsp_sysctl_clock_source()
614 } else if (hdsp_status2_clock_source(clock->type) == status2) in hdsp_sysctl_clock_source()
619 if (clock->name != NULL) in hdsp_sysctl_clock_source()
620 strlcpy(buf, clock->name, sizeof(buf)); in hdsp_sysctl_clock_source()
628 struct hdsp_clock_source *clock_table, *clock; in hdsp_sysctl_clock_list() local
632 sc = oidp->oid_arg1; in hdsp_sysctl_clock_list()
635 /* Select clock source table for device type. */ in hdsp_sysctl_clock_list()
636 if (sc->type == HDSP_9632) in hdsp_sysctl_clock_list()
638 else if (sc->type == HDSP_9652) in hdsp_sysctl_clock_list()
643 /* List available clock sources. */ in hdsp_sysctl_clock_list()
645 for (clock = clock_table; clock->name != NULL; ++clock) { in hdsp_sysctl_clock_list()
647 n += strlcpy(buf + n, ",", sizeof(buf) - n); in hdsp_sysctl_clock_list()
648 n += strlcpy(buf + n, clock->name, sizeof(buf) - n); in hdsp_sysctl_clock_list()
705 struct hdsp_clock_source *clock_table, *clock; in hdsp_sysctl_sync_status() local
711 sc = oidp->oid_arg1; in hdsp_sysctl_sync_status()
715 if (sc->type == HDSP_9632) in hdsp_sysctl_sync_status()
717 else if (sc->type == HDSP_9652) in hdsp_sysctl_sync_status()
723 snd_mtxlock(sc->lock); in hdsp_sysctl_sync_status()
726 snd_mtxunlock(sc->lock); in hdsp_sysctl_sync_status()
728 /* List clock sources with lock and sync state. */ in hdsp_sysctl_sync_status()
729 for (clock = clock_table; clock->name != NULL; ++clock) { in hdsp_sysctl_sync_status()
730 if (clock->type == HDSP_CLOCK_INTERNAL) in hdsp_sysctl_sync_status()
733 n += strlcpy(buf + n, ",", sizeof(buf) - n); in hdsp_sysctl_sync_status()
735 if (hdsp_clock_source_locked(clock->type, status, status2)) { in hdsp_sysctl_sync_status()
736 if (hdsp_clock_source_synced(clock->type, status, in hdsp_sysctl_sync_status()
742 n += snprintf(buf + n, sizeof(buf) - n, "%s(%s)", in hdsp_sysctl_sync_status()
743 clock->name, state); in hdsp_sysctl_sync_status()
775 sc->period = 256; in hdsp_init()
777 * The pcm channel latency settings propagate unreliable blocksizes, in hdsp_init()
782 sc->force_period = 256; in hdsp_init()
783 sc->ctrl_register = hdsp_encode_latency(2); in hdsp_init()
786 sc->speed = HDSP_SPEED_DEFAULT; in hdsp_init()
787 sc->force_speed = 0; in hdsp_init()
788 sc->ctrl_register &= ~HDSP_FREQ_MASK; in hdsp_init()
789 sc->ctrl_register |= HDSP_FREQ_MASK_DEFAULT; in hdsp_init()
791 /* Set internal clock source (master). */ in hdsp_init()
792 sc->ctrl_register &= ~HDSP_CONTROL_CLOCK_MASK; in hdsp_init()
793 sc->ctrl_register |= HDSP_CONTROL_MASTER; in hdsp_init()
796 sc->ctrl_register &= ~HDSP_CONTROL_SPDIF_COAX; in hdsp_init()
797 sc->ctrl_register |= HDSP_CONTROL_SPDIF_COAX; in hdsp_init()
798 sc->ctrl_register &= ~HDSP_CONTROL_LINE_OUT; in hdsp_init()
799 sc->ctrl_register |= HDSP_CONTROL_LINE_OUT; in hdsp_init()
802 sc->ctrl_register &= ~HDSP_INPUT_LEVEL_MASK; in hdsp_init()
803 sc->ctrl_register |= HDSP_INPUT_LEVEL_LOWGAIN; in hdsp_init()
804 sc->ctrl_register &= ~HDSP_OUTPUT_LEVEL_MASK; in hdsp_init()
805 sc->ctrl_register |= HDSP_OUTPUT_LEVEL_MINUS10DBV; in hdsp_init()
806 sc->ctrl_register &= ~HDSP_PHONES_LEVEL_MASK; in hdsp_init()
807 sc->ctrl_register |= HDSP_PHONES_LEVEL_MINUS12DB; in hdsp_init()
809 hdsp_write_4(sc, HDSP_CONTROL_REG, sc->ctrl_register); in hdsp_init()
811 if (sc->type == HDSP_9652) in hdsp_init()
816 switch (sc->type) { in hdsp_init()
838 if (sc->type == HDSP_9632) { in hdsp_init()
840 hdsp_write_4(sc, HDSP_FREQ_REG, hdsp_freq_reg_value(sc->speed)); in hdsp_init()
860 sc->lock = snd_mtxcreate(device_get_nameunit(dev), in hdsp_attach()
862 sc->dev = dev; in hdsp_attach()
868 sc->type = HDSP_9632; in hdsp_attach()
872 sc->type = HDSP_9652; in hdsp_attach()
891 scp->hc = &chan_map[i]; in hdsp_attach()
892 scp->sc = sc; in hdsp_attach()
893 scp->dev = device_add_child(dev, "pcm", -1); in hdsp_attach()
894 device_set_ivars(scp->dev, scp); in hdsp_attach()
903 "List clock source signal lock and sync status"); in hdsp_attach()
909 "Currently effective clock source"); in hdsp_attach()
915 "Set 'internal' (master) or preferred autosync clock source"); in hdsp_attach()
921 "List of supported clock sources"); in hdsp_attach()
935 if (sc->type == HDSP_9632) { in hdsp_attach()
940 "Phones output level ('0dB', '-6dB', '-12dB')"); in hdsp_attach()
946 "Analog output level ('HighGain', '+4dBU', '-10dBV')"); in hdsp_attach()
952 "Analog input level ('LowGain', '+4dBU', '-10dBV')"); in hdsp_attach()
969 bus_dmamap_unload(sc->dmat, sc->rmap); in hdsp_dmafree()
970 bus_dmamap_unload(sc->dmat, sc->pmap); in hdsp_dmafree()
971 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap); in hdsp_dmafree()
972 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap); in hdsp_dmafree()
973 sc->rbuf = sc->pbuf = NULL; in hdsp_dmafree()
994 if (sc->ih) in hdsp_detach()
995 bus_teardown_intr(dev, sc->irq, sc->ih); in hdsp_detach()
996 if (sc->dmat) in hdsp_detach()
997 bus_dma_tag_destroy(sc->dmat); in hdsp_detach()
998 if (sc->irq) in hdsp_detach()
999 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); in hdsp_detach()
1000 if (sc->cs) in hdsp_detach()
1001 bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), sc->cs); in hdsp_detach()
1002 if (sc->lock) in hdsp_detach()
1003 snd_mtxfree(sc->lock); in hdsp_detach()