1 /* $FreeBSD$ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5 * 6 * Copyright (c) 2000-2002 Hiroyuki Aizu <aizu@navi.org> 7 * Copyright (c) 2006 Hans Petter Selasky 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 32 #ifdef HAVE_KERNEL_OPTION_HEADERS 33 #include "opt_snd.h" 34 #endif 35 36 #include <dev/sound/pcm/sound.h> 37 #include <dev/sound/chip.h> 38 #include <dev/sound/usb/uaudio.h> 39 40 #include "mixer_if.h" 41 42 /************************************************************/ 43 static void * 44 ua_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 45 { 46 return (uaudio_chan_init(devinfo, b, c, dir)); 47 } 48 49 static int 50 ua_chan_free(kobj_t obj, void *data) 51 { 52 return (uaudio_chan_free(data)); 53 } 54 55 static int 56 ua_chan_setformat(kobj_t obj, void *data, uint32_t format) 57 { 58 /* 59 * At this point, no need to query as we 60 * shouldn't select an unsorted format 61 */ 62 return (uaudio_chan_set_param_format(data, format)); 63 } 64 65 static uint32_t 66 ua_chan_setspeed(kobj_t obj, void *data, uint32_t speed) 67 { 68 return (uaudio_chan_set_param_speed(data, speed)); 69 } 70 71 static uint32_t 72 ua_chan_setblocksize(kobj_t obj, void *data, uint32_t blocksize) 73 { 74 return (uaudio_chan_set_param_blocksize(data, blocksize)); 75 } 76 77 static int 78 ua_chan_setfragments(kobj_t obj, void *data, uint32_t blocksize, uint32_t blockcount) 79 { 80 return (uaudio_chan_set_param_fragments(data, blocksize, blockcount)); 81 } 82 83 static int 84 ua_chan_trigger(kobj_t obj, void *data, int go) 85 { 86 if (PCMTRIG_COMMON(go)) { 87 if (go == PCMTRIG_START) { 88 uaudio_chan_start(data); 89 } else { 90 uaudio_chan_stop(data); 91 } 92 } 93 return (0); 94 } 95 96 static uint32_t 97 ua_chan_getptr(kobj_t obj, void *data) 98 { 99 return (uaudio_chan_getptr(data)); 100 } 101 102 static struct pcmchan_caps * 103 ua_chan_getcaps(kobj_t obj, void *data) 104 { 105 return (uaudio_chan_getcaps(data)); 106 } 107 108 static struct pcmchan_matrix * 109 ua_chan_getmatrix(kobj_t obj, void *data, uint32_t format) 110 { 111 return (uaudio_chan_getmatrix(data, format)); 112 } 113 114 static kobj_method_t ua_chan_methods[] = { 115 KOBJMETHOD(channel_init, ua_chan_init), 116 KOBJMETHOD(channel_free, ua_chan_free), 117 KOBJMETHOD(channel_setformat, ua_chan_setformat), 118 KOBJMETHOD(channel_setspeed, ua_chan_setspeed), 119 KOBJMETHOD(channel_setblocksize, ua_chan_setblocksize), 120 KOBJMETHOD(channel_setfragments, ua_chan_setfragments), 121 KOBJMETHOD(channel_trigger, ua_chan_trigger), 122 KOBJMETHOD(channel_getptr, ua_chan_getptr), 123 KOBJMETHOD(channel_getcaps, ua_chan_getcaps), 124 KOBJMETHOD(channel_getmatrix, ua_chan_getmatrix), 125 KOBJMETHOD_END 126 }; 127 128 CHANNEL_DECLARE(ua_chan); 129 130 /************************************************************/ 131 static int 132 ua_mixer_init(struct snd_mixer *m) 133 { 134 return (uaudio_mixer_init_sub(mix_getdevinfo(m), m)); 135 } 136 137 static int 138 ua_mixer_set(struct snd_mixer *m, unsigned type, unsigned left, unsigned right) 139 { 140 struct mtx *mtx = mixer_get_lock(m); 141 uint8_t do_unlock; 142 143 if (mtx_owned(mtx)) { 144 do_unlock = 0; 145 } else { 146 do_unlock = 1; 147 mtx_lock(mtx); 148 } 149 uaudio_mixer_set(mix_getdevinfo(m), m, type, left, right); 150 if (do_unlock) { 151 mtx_unlock(mtx); 152 } 153 return (left | (right << 8)); 154 } 155 156 static uint32_t 157 ua_mixer_setrecsrc(struct snd_mixer *m, uint32_t src) 158 { 159 struct mtx *mtx = mixer_get_lock(m); 160 int retval; 161 uint8_t do_unlock; 162 163 if (mtx_owned(mtx)) { 164 do_unlock = 0; 165 } else { 166 do_unlock = 1; 167 mtx_lock(mtx); 168 } 169 retval = uaudio_mixer_setrecsrc(mix_getdevinfo(m), m, src); 170 if (do_unlock) { 171 mtx_unlock(mtx); 172 } 173 return (retval); 174 } 175 176 static int 177 ua_mixer_uninit(struct snd_mixer *m) 178 { 179 return (uaudio_mixer_uninit_sub(mix_getdevinfo(m), m)); 180 } 181 182 static kobj_method_t ua_mixer_methods[] = { 183 KOBJMETHOD(mixer_init, ua_mixer_init), 184 KOBJMETHOD(mixer_uninit, ua_mixer_uninit), 185 KOBJMETHOD(mixer_set, ua_mixer_set), 186 KOBJMETHOD(mixer_setrecsrc, ua_mixer_setrecsrc), 187 KOBJMETHOD_END 188 }; 189 190 MIXER_DECLARE(ua_mixer); 191 /************************************************************/ 192 193 194 static int 195 ua_probe(device_t dev) 196 { 197 struct sndcard_func *func; 198 199 /* the parent device has already been probed */ 200 201 func = device_get_ivars(dev); 202 203 if ((func == NULL) || 204 (func->func != SCF_PCM)) { 205 return (ENXIO); 206 } 207 device_set_desc(dev, "USB audio"); 208 209 return (BUS_PROBE_DEFAULT); 210 } 211 212 static int 213 ua_attach(device_t dev) 214 { 215 return (uaudio_attach_sub(dev, &ua_mixer_class, &ua_chan_class)); 216 } 217 218 static int 219 ua_detach(device_t dev) 220 { 221 return (uaudio_detach_sub(dev)); 222 } 223 224 /************************************************************/ 225 226 static device_method_t ua_pcm_methods[] = { 227 /* Device interface */ 228 DEVMETHOD(device_probe, ua_probe), 229 DEVMETHOD(device_attach, ua_attach), 230 DEVMETHOD(device_detach, ua_detach), 231 232 DEVMETHOD_END 233 }; 234 235 static driver_t ua_pcm_driver = { 236 "pcm", 237 ua_pcm_methods, 238 PCM_SOFTC_SIZE, 239 }; 240 241 DRIVER_MODULE(ua_pcm, uaudio, ua_pcm_driver, pcm_devclass, 0, 0); 242 MODULE_DEPEND(ua_pcm, uaudio, 1, 1, 1); 243 MODULE_DEPEND(ua_pcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 244 MODULE_VERSION(ua_pcm, 1); 245