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