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