bwdsp.c revision 1.1
11.1Sjmcneill/* $NetBSD: bwdsp.c,v 1.1 2026/01/09 22:54:29 jmcneill Exp $ */ 21.1Sjmcneill 31.1Sjmcneill/*- 41.1Sjmcneill * Copyright (c) 2024 Jared McNeill <jmcneill@invisible.ca> 51.1Sjmcneill * All rights reserved. 61.1Sjmcneill * 71.1Sjmcneill * Redistribution and use in source and binary forms, with or without 81.1Sjmcneill * modification, are permitted provided that the following conditions 91.1Sjmcneill * are met: 101.1Sjmcneill * 1. Redistributions of source code must retain the above copyright 111.1Sjmcneill * notice, this list of conditions and the following disclaimer. 121.1Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright 131.1Sjmcneill * notice, this list of conditions and the following disclaimer in the 141.1Sjmcneill * documentation and/or other materials provided with the distribution. 151.1Sjmcneill * 161.1Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 171.1Sjmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 181.1Sjmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 191.1Sjmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 201.1Sjmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 211.1Sjmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 221.1Sjmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 231.1Sjmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 241.1Sjmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 251.1Sjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261.1Sjmcneill * SUCH DAMAGE. 271.1Sjmcneill */ 281.1Sjmcneill 291.1Sjmcneill#include <sys/cdefs.h> 301.1Sjmcneill__KERNEL_RCSID(0, "$NetBSD: bwdsp.c,v 1.1 2026/01/09 22:54:29 jmcneill Exp $"); 311.1Sjmcneill 321.1Sjmcneill#include <sys/param.h> 331.1Sjmcneill#include <sys/bus.h> 341.1Sjmcneill#include <sys/cpu.h> 351.1Sjmcneill#include <sys/device.h> 361.1Sjmcneill#include <sys/kmem.h> 371.1Sjmcneill 381.1Sjmcneill#include <sys/audioio.h> 391.1Sjmcneill#include <dev/audio/audio_if.h> 401.1Sjmcneill#include <dev/audio/audio_dai.h> 411.1Sjmcneill 421.1Sjmcneill#include <machine/wiiu.h> 431.1Sjmcneill#include <machine/pio.h> 441.1Sjmcneill 451.1Sjmcneill#include "mainbus.h" 461.1Sjmcneill#include "bwai.h" 471.1Sjmcneill 481.1Sjmcneill#define BWDSP_MAP_FLAGS BUS_DMA_NOCACHE 491.1Sjmcneill 501.1Sjmcneill#define DSP_DMA_START_ADDR_H 0x30 511.1Sjmcneill#define DSP_DMA_START_ADDR_L 0x32 521.1Sjmcneill#define DSP_DMA_CONTROL_LENGTH 0x36 531.1Sjmcneill#define DSP_DMA_CONTROL_LENGTH_CTRL __BIT(15) 541.1Sjmcneill#define DSP_DMA_CONTROL_LENGTH_NUM_CLS __BITS(14,0) 551.1Sjmcneill 561.1Sjmcneill#define DSP_DMA_ALIGN 32 571.1Sjmcneill#define DSP_DMA_MAX_BUFSIZE (DSP_DMA_CONTROL_LENGTH_NUM_CLS * 32) 581.1Sjmcneill 591.1Sjmcneillextern struct powerpc_bus_dma_tag wii_mem2_bus_dma_tag; 601.1Sjmcneill 611.1Sjmcneillstruct bwdsp_dma { 621.1Sjmcneill LIST_ENTRY(bwdsp_dma) dma_list; 631.1Sjmcneill bus_dmamap_t dma_map; 641.1Sjmcneill void *dma_addr; 651.1Sjmcneill size_t dma_size; 661.1Sjmcneill bus_dma_segment_t dma_segs[1]; 671.1Sjmcneill int dma_nsegs; 681.1Sjmcneill}; 691.1Sjmcneill 701.1Sjmcneillstruct bwdsp_softc { 711.1Sjmcneill device_t sc_dev; 721.1Sjmcneill bus_space_tag_t sc_bst; 731.1Sjmcneill bus_space_handle_t sc_bsh; 741.1Sjmcneill bus_dma_tag_t sc_dmat; 751.1Sjmcneill 761.1Sjmcneill LIST_HEAD(, bwdsp_dma) sc_dmalist; 771.1Sjmcneill 781.1Sjmcneill kmutex_t sc_lock; 791.1Sjmcneill kmutex_t sc_intr_lock; 801.1Sjmcneill 811.1Sjmcneill struct audio_format sc_format; 821.1Sjmcneill 831.1Sjmcneill audio_dai_tag_t sc_dai; 841.1Sjmcneill 851.1Sjmcneill /* Register offsets */ 861.1Sjmcneill uint32_t sc_dma_start_addr_h; 871.1Sjmcneill uint32_t sc_dma_start_addr_l; 881.1Sjmcneill uint32_t sc_dma_control_length; 891.1Sjmcneill}; 901.1Sjmcneill 911.1Sjmcneill#define WR2(sc, reg, val) \ 921.1Sjmcneill bus_space_write_2((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 931.1Sjmcneill 941.1Sjmcneillstatic int 951.1Sjmcneillbwdsp_allocdma(struct bwdsp_softc *sc, size_t size, 961.1Sjmcneill size_t align, struct bwdsp_dma *dma) 971.1Sjmcneill{ 981.1Sjmcneill int error; 991.1Sjmcneill 1001.1Sjmcneill dma->dma_size = size; 1011.1Sjmcneill error = bus_dmamem_alloc(sc->sc_dmat, dma->dma_size, align, 0, 1021.1Sjmcneill dma->dma_segs, 1, &dma->dma_nsegs, BUS_DMA_WAITOK); 1031.1Sjmcneill if (error) 1041.1Sjmcneill return error; 1051.1Sjmcneill 1061.1Sjmcneill error = bus_dmamem_map(sc->sc_dmat, dma->dma_segs, dma->dma_nsegs, 1071.1Sjmcneill dma->dma_size, &dma->dma_addr, BUS_DMA_WAITOK | BWDSP_MAP_FLAGS); 1081.1Sjmcneill if (error) 1091.1Sjmcneill goto free; 1101.1Sjmcneill 1111.1Sjmcneill error = bus_dmamap_create(sc->sc_dmat, dma->dma_size, dma->dma_nsegs, 1121.1Sjmcneill dma->dma_size, 0, BUS_DMA_WAITOK, &dma->dma_map); 1131.1Sjmcneill if (error) 1141.1Sjmcneill goto unmap; 1151.1Sjmcneill 1161.1Sjmcneill error = bus_dmamap_load(sc->sc_dmat, dma->dma_map, dma->dma_addr, 1171.1Sjmcneill dma->dma_size, NULL, BUS_DMA_WAITOK); 1181.1Sjmcneill if (error) 1191.1Sjmcneill goto destroy; 1201.1Sjmcneill 1211.1Sjmcneill return 0; 1221.1Sjmcneill 1231.1Sjmcneilldestroy: 1241.1Sjmcneill bus_dmamap_destroy(sc->sc_dmat, dma->dma_map); 1251.1Sjmcneillunmap: 1261.1Sjmcneill bus_dmamem_unmap(sc->sc_dmat, dma->dma_addr, dma->dma_size); 1271.1Sjmcneillfree: 1281.1Sjmcneill bus_dmamem_free(sc->sc_dmat, dma->dma_segs, dma->dma_nsegs); 1291.1Sjmcneill 1301.1Sjmcneill return error; 1311.1Sjmcneill} 1321.1Sjmcneill 1331.1Sjmcneillstatic void 1341.1Sjmcneillbwdsp_freedma(struct bwdsp_softc *sc, struct bwdsp_dma *dma) 1351.1Sjmcneill{ 1361.1Sjmcneill bus_dmamap_unload(sc->sc_dmat, dma->dma_map); 1371.1Sjmcneill bus_dmamap_destroy(sc->sc_dmat, dma->dma_map); 1381.1Sjmcneill bus_dmamem_unmap(sc->sc_dmat, dma->dma_addr, dma->dma_size); 1391.1Sjmcneill bus_dmamem_free(sc->sc_dmat, dma->dma_segs, dma->dma_nsegs); 1401.1Sjmcneill} 1411.1Sjmcneill 1421.1Sjmcneillstatic int 1431.1Sjmcneillbwdsp_query_format(void *priv, audio_format_query_t *afp) 1441.1Sjmcneill{ 1451.1Sjmcneill struct bwdsp_softc * const sc = priv; 1461.1Sjmcneill 1471.1Sjmcneill return audio_query_format(&sc->sc_format, 1, afp); 1481.1Sjmcneill} 1491.1Sjmcneill 1501.1Sjmcneillstatic int 1511.1Sjmcneillbwdsp_set_format(void *priv, int setmode, 1521.1Sjmcneill const audio_params_t *play, const audio_params_t *rec, 1531.1Sjmcneill audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 1541.1Sjmcneill{ 1551.1Sjmcneill struct bwdsp_softc * const sc = priv; 1561.1Sjmcneill 1571.1Sjmcneill return audio_dai_mi_set_format(sc->sc_dai, setmode, play, rec, 1581.1Sjmcneill pfil, rfil); 1591.1Sjmcneill} 1601.1Sjmcneill 1611.1Sjmcneillstatic int 1621.1Sjmcneillbwdsp_set_port(void *priv, mixer_ctrl_t *mc) 1631.1Sjmcneill{ 1641.1Sjmcneill struct bwdsp_softc * const sc = priv; 1651.1Sjmcneill 1661.1Sjmcneill return audio_dai_set_port(sc->sc_dai, mc); 1671.1Sjmcneill} 1681.1Sjmcneill 1691.1Sjmcneillstatic int 1701.1Sjmcneillbwdsp_get_port(void *priv, mixer_ctrl_t *mc) 1711.1Sjmcneill{ 1721.1Sjmcneill struct bwdsp_softc * const sc = priv; 1731.1Sjmcneill 1741.1Sjmcneill return audio_dai_get_port(sc->sc_dai, mc); 1751.1Sjmcneill} 1761.1Sjmcneill 1771.1Sjmcneillstatic int 1781.1Sjmcneillbwdsp_query_devinfo(void *priv, mixer_devinfo_t *di) 1791.1Sjmcneill{ 1801.1Sjmcneill struct bwdsp_softc * const sc = priv; 1811.1Sjmcneill 1821.1Sjmcneill return audio_dai_query_devinfo(sc->sc_dai, di); 1831.1Sjmcneill} 1841.1Sjmcneill 1851.1Sjmcneillstatic void * 1861.1Sjmcneillbwdsp_allocm(void *priv, int dir, size_t size) 1871.1Sjmcneill{ 1881.1Sjmcneill struct bwdsp_softc * const sc = priv; 1891.1Sjmcneill struct bwdsp_dma *dma; 1901.1Sjmcneill int error; 1911.1Sjmcneill 1921.1Sjmcneill dma = kmem_alloc(sizeof(*dma), KM_SLEEP); 1931.1Sjmcneill 1941.1Sjmcneill error = bwdsp_allocdma(sc, size, DSP_DMA_ALIGN, dma); 1951.1Sjmcneill if (error) { 1961.1Sjmcneill kmem_free(dma, sizeof(*dma)); 1971.1Sjmcneill device_printf(sc->sc_dev, "couldn't allocate DMA memory (%d)\n", 1981.1Sjmcneill error); 1991.1Sjmcneill return NULL; 2001.1Sjmcneill } 2011.1Sjmcneill 2021.1Sjmcneill LIST_INSERT_HEAD(&sc->sc_dmalist, dma, dma_list); 2031.1Sjmcneill 2041.1Sjmcneill return dma->dma_addr; 2051.1Sjmcneill} 2061.1Sjmcneill 2071.1Sjmcneillstatic void 2081.1Sjmcneillbwdsp_freem(void *priv, void *addr, size_t size) 2091.1Sjmcneill{ 2101.1Sjmcneill struct bwdsp_softc * const sc = priv; 2111.1Sjmcneill struct bwdsp_dma *dma; 2121.1Sjmcneill 2131.1Sjmcneill LIST_FOREACH(dma, &sc->sc_dmalist, dma_list) 2141.1Sjmcneill if (dma->dma_addr == addr) { 2151.1Sjmcneill bwdsp_freedma(sc, dma); 2161.1Sjmcneill LIST_REMOVE(dma, dma_list); 2171.1Sjmcneill kmem_free(dma, sizeof(*dma)); 2181.1Sjmcneill break; 2191.1Sjmcneill } 2201.1Sjmcneill} 2211.1Sjmcneill 2221.1Sjmcneillstatic int 2231.1Sjmcneillbwdsp_getdev(void *priv, struct audio_device *adev) 2241.1Sjmcneill{ 2251.1Sjmcneill if (wiiu_plat) { 2261.1Sjmcneill snprintf(adev->name, sizeof(adev->name), "Latte DSP"); 2271.1Sjmcneill } else { 2281.1Sjmcneill snprintf(adev->name, sizeof(adev->name), "Hollywood DSP"); 2291.1Sjmcneill } 2301.1Sjmcneill snprintf(adev->version, sizeof(adev->version), ""); 2311.1Sjmcneill snprintf(adev->config, sizeof(adev->config), "bwdsp"); 2321.1Sjmcneill 2331.1Sjmcneill return 0; 2341.1Sjmcneill} 2351.1Sjmcneill 2361.1Sjmcneillstatic int 2371.1Sjmcneillbwdsp_get_props(void *priv) 2381.1Sjmcneill{ 2391.1Sjmcneill return AUDIO_PROP_PLAYBACK; 2401.1Sjmcneill} 2411.1Sjmcneill 2421.1Sjmcneillstatic int 2431.1Sjmcneillbwdsp_round_blocksize(void *priv, int bs, int mode, 2441.1Sjmcneill const audio_params_t *params) 2451.1Sjmcneill{ 2461.1Sjmcneill bs = roundup(bs, DSP_DMA_ALIGN); 2471.1Sjmcneill if (bs > DSP_DMA_MAX_BUFSIZE) { 2481.1Sjmcneill bs = DSP_DMA_MAX_BUFSIZE; 2491.1Sjmcneill } 2501.1Sjmcneill return bs; 2511.1Sjmcneill} 2521.1Sjmcneill 2531.1Sjmcneillstatic size_t 2541.1Sjmcneillbwdsp_round_buffersize(void *priv, int dir, size_t bufsize) 2551.1Sjmcneill{ 2561.1Sjmcneill if (bufsize > DSP_DMA_MAX_BUFSIZE) { 2571.1Sjmcneill bufsize = DSP_DMA_MAX_BUFSIZE; 2581.1Sjmcneill } 2591.1Sjmcneill return bufsize; 2601.1Sjmcneill} 2611.1Sjmcneill 2621.1Sjmcneillstatic void 2631.1Sjmcneillbwdsp_transfer(struct bwdsp_softc *sc, uint32_t phys_addr, size_t bufsize) 2641.1Sjmcneill{ 2651.1Sjmcneill if (bufsize != 0) { 2661.1Sjmcneill WR2(sc, sc->sc_dma_start_addr_h, phys_addr >> 16); 2671.1Sjmcneill WR2(sc, sc->sc_dma_start_addr_l, phys_addr & 0xffff); 2681.1Sjmcneill WR2(sc, sc->sc_dma_control_length, 2691.1Sjmcneill DSP_DMA_CONTROL_LENGTH_CTRL | (bufsize / 32)); 2701.1Sjmcneill } else { 2711.1Sjmcneill WR2(sc, sc->sc_dma_control_length, 0); 2721.1Sjmcneill } 2731.1Sjmcneill} 2741.1Sjmcneill 2751.1Sjmcneillstatic int 2761.1Sjmcneillbwdsp_trigger_output(void *priv, void *start, void *end, int blksize, 2771.1Sjmcneill void (*intr)(void *), void *intrarg, const audio_params_t *params) 2781.1Sjmcneill{ 2791.1Sjmcneill struct bwdsp_softc * const sc = priv; 2801.1Sjmcneill struct bwdsp_dma *dma; 2811.1Sjmcneill bus_addr_t pstart; 2821.1Sjmcneill bus_size_t psize; 2831.1Sjmcneill int error; 2841.1Sjmcneill 2851.1Sjmcneill pstart = 0; 2861.1Sjmcneill psize = (uintptr_t)end - (uintptr_t)start; 2871.1Sjmcneill 2881.1Sjmcneill LIST_FOREACH(dma, &sc->sc_dmalist, dma_list) 2891.1Sjmcneill if (dma->dma_addr == start) { 2901.1Sjmcneill pstart = dma->dma_map->dm_segs[0].ds_addr; 2911.1Sjmcneill break; 2921.1Sjmcneill } 2931.1Sjmcneill if (pstart == 0) { 2941.1Sjmcneill device_printf(sc->sc_dev, "bad addr %p\n", start); 2951.1Sjmcneill return EINVAL; 2961.1Sjmcneill } 2971.1Sjmcneill 2981.1Sjmcneill error = audio_dai_trigger(sc->sc_dai, start, end, blksize, 2991.1Sjmcneill intr, intrarg, params, AUMODE_PLAY); 3001.1Sjmcneill if (error != 0) { 3011.1Sjmcneill return error; 3021.1Sjmcneill } 3031.1Sjmcneill 3041.1Sjmcneill /* Start DMA transfer */ 3051.1Sjmcneill bwdsp_transfer(sc, pstart, psize); 3061.1Sjmcneill 3071.1Sjmcneill return 0; 3081.1Sjmcneill} 3091.1Sjmcneill 3101.1Sjmcneillstatic int 3111.1Sjmcneillbwdsp_halt_output(void *priv) 3121.1Sjmcneill{ 3131.1Sjmcneill struct bwdsp_softc * const sc = priv; 3141.1Sjmcneill 3151.1Sjmcneill /* Stop DMA transfer */ 3161.1Sjmcneill bwdsp_transfer(sc, 0, 0); 3171.1Sjmcneill 3181.1Sjmcneill return audio_dai_halt(sc->sc_dai, AUMODE_PLAY); 3191.1Sjmcneill} 3201.1Sjmcneill 3211.1Sjmcneillstatic void 3221.1Sjmcneillbwdsp_get_locks(void *priv, kmutex_t **intr, kmutex_t **thread) 3231.1Sjmcneill{ 3241.1Sjmcneill struct bwdsp_softc * const sc = priv; 3251.1Sjmcneill 3261.1Sjmcneill *intr = &sc->sc_intr_lock; 3271.1Sjmcneill *thread = &sc->sc_lock; 3281.1Sjmcneill} 3291.1Sjmcneill 3301.1Sjmcneillstatic const struct audio_hw_if bwdsp_hw_if = { 3311.1Sjmcneill .query_format = bwdsp_query_format, 3321.1Sjmcneill .set_format = bwdsp_set_format, 3331.1Sjmcneill .allocm = bwdsp_allocm, 3341.1Sjmcneill .freem = bwdsp_freem, 3351.1Sjmcneill .getdev = bwdsp_getdev, 3361.1Sjmcneill .set_port = bwdsp_set_port, 3371.1Sjmcneill .get_port = bwdsp_get_port, 3381.1Sjmcneill .query_devinfo = bwdsp_query_devinfo, 3391.1Sjmcneill .get_props = bwdsp_get_props, 3401.1Sjmcneill .round_blocksize = bwdsp_round_blocksize, 3411.1Sjmcneill .round_buffersize = bwdsp_round_buffersize, 3421.1Sjmcneill .trigger_output = bwdsp_trigger_output, 3431.1Sjmcneill .halt_output = bwdsp_halt_output, 3441.1Sjmcneill .get_locks = bwdsp_get_locks, 3451.1Sjmcneill}; 3461.1Sjmcneill 3471.1Sjmcneillstatic void 3481.1Sjmcneillbwdsp_late_attach(device_t dev) 3491.1Sjmcneill{ 3501.1Sjmcneill struct bwdsp_softc * const sc = device_private(dev); 3511.1Sjmcneill 3521.1Sjmcneill sc->sc_dai = bwai_dsp_init(&sc->sc_intr_lock); 3531.1Sjmcneill if (sc->sc_dai == NULL) { 3541.1Sjmcneill aprint_error_dev(dev, "can't find bwai device\n"); 3551.1Sjmcneill return; 3561.1Sjmcneill } 3571.1Sjmcneill 3581.1Sjmcneill audio_attach_mi(&bwdsp_hw_if, sc, dev); 3591.1Sjmcneill} 3601.1Sjmcneill 3611.1Sjmcneillstatic int 3621.1Sjmcneillbwdsp_match(device_t parent, cfdata_t cf, void *aux) 3631.1Sjmcneill{ 3641.1Sjmcneill struct mainbus_attach_args * const maa = aux; 3651.1Sjmcneill 3661.1Sjmcneill return strcmp(maa->maa_name, "bwdsp") == 0; 3671.1Sjmcneill} 3681.1Sjmcneill 3691.1Sjmcneillstatic void 3701.1Sjmcneillbwdsp_attach(device_t parent, device_t self, void *aux) 3711.1Sjmcneill{ 3721.1Sjmcneill struct bwdsp_softc * const sc = device_private(self); 3731.1Sjmcneill struct mainbus_attach_args * const maa = aux; 3741.1Sjmcneill bus_addr_t addr = maa->maa_addr; 3751.1Sjmcneill bus_size_t size = 0x200; 3761.1Sjmcneill const uint32_t dma_reg_off = wiiu_native ? 0x10 : 0; 3771.1Sjmcneill 3781.1Sjmcneill sc->sc_dev = self; 3791.1Sjmcneill sc->sc_bst = maa->maa_bst; 3801.1Sjmcneill if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 3811.1Sjmcneill aprint_error(": couldn't map registers\n"); 3821.1Sjmcneill return; 3831.1Sjmcneill } 3841.1Sjmcneill sc->sc_dmat = &wii_mem2_bus_dma_tag; 3851.1Sjmcneill LIST_INIT(&sc->sc_dmalist); 3861.1Sjmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 3871.1Sjmcneill mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED); 3881.1Sjmcneill 3891.1Sjmcneill sc->sc_dma_start_addr_h = DSP_DMA_START_ADDR_H + dma_reg_off; 3901.1Sjmcneill sc->sc_dma_start_addr_l = DSP_DMA_START_ADDR_L + dma_reg_off; 3911.1Sjmcneill sc->sc_dma_control_length = DSP_DMA_CONTROL_LENGTH + dma_reg_off; 3921.1Sjmcneill 3931.1Sjmcneill aprint_naive("\n"); 3941.1Sjmcneill aprint_normal(": DSP\n"); 3951.1Sjmcneill 3961.1Sjmcneill out32(HW_RESETS, in32(HW_RESETS) | RSTB_DSP); 3971.1Sjmcneill 3981.1Sjmcneill sc->sc_format.mode = AUMODE_PLAY; 3991.1Sjmcneill sc->sc_format.encoding = AUDIO_ENCODING_SLINEAR_BE; 4001.1Sjmcneill sc->sc_format.validbits = 16; 4011.1Sjmcneill sc->sc_format.precision = 16; 4021.1Sjmcneill sc->sc_format.channels = 2; 4031.1Sjmcneill sc->sc_format.channel_mask = AUFMT_STEREO; 4041.1Sjmcneill sc->sc_format.frequency_type = 1; 4051.1Sjmcneill sc->sc_format.frequency[0] = 48000; 4061.1Sjmcneill 4071.1Sjmcneill config_defer(self, bwdsp_late_attach); 4081.1Sjmcneill} 4091.1Sjmcneill 4101.1SjmcneillCFATTACH_DECL_NEW(bwdsp, sizeof(struct bwdsp_softc), 4111.1Sjmcneill bwdsp_match, bwdsp_attach, NULL, NULL); 412