uaudio_pcm.c revision 184610
1/* $FreeBSD: head/sys/dev/usb2/sound/uaudio2_pcm.c 184610 2008-11-04 02:31:03Z alfred $ */ 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#include <sys/soundcard.h> 31#include <dev/sound/pcm/sound.h> 32#include <dev/sound/chip.h> 33 34#include <dev/usb2/sound/uaudio2.h> 35 36#include "mixer_if.h" 37 38/************************************************************/ 39static void * 40ua_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 41{ 42 return (uaudio_chan_init(devinfo, b, c, dir)); 43} 44 45static int 46ua_chan_free(kobj_t obj, void *data) 47{ 48 return (uaudio_chan_free(data)); 49} 50 51static int 52ua_chan_setformat(kobj_t obj, void *data, uint32_t format) 53{ 54 /* 55 * At this point, no need to query as we 56 * shouldn't select an unsorted format 57 */ 58 return (uaudio_chan_set_param_format(data, format)); 59} 60 61static int 62ua_chan_setspeed(kobj_t obj, void *data, uint32_t speed) 63{ 64 return (uaudio_chan_set_param_speed(data, speed)); 65} 66 67static int 68ua_chan_setblocksize(kobj_t obj, void *data, uint32_t blocksize) 69{ 70 return (uaudio_chan_set_param_blocksize(data, blocksize)); 71} 72 73static int 74ua_chan_setfragments(kobj_t obj, void *data, uint32_t blocksize, uint32_t blockcount) 75{ 76 return (uaudio_chan_set_param_fragments(data, blocksize, blockcount)); 77} 78 79static int 80ua_chan_trigger(kobj_t obj, void *data, int go) 81{ 82 if (!PCMTRIG_COMMON(go)) { 83 return (0); 84 } 85 if (go == PCMTRIG_START) { 86 return (uaudio_chan_start(data)); 87 } else { 88 return (uaudio_chan_stop(data)); 89 } 90} 91 92static int 93ua_chan_getptr(kobj_t obj, void *data) 94{ 95 return (uaudio_chan_getptr(data)); 96} 97 98static struct pcmchan_caps * 99ua_chan_getcaps(kobj_t obj, void *data) 100{ 101 return (uaudio_chan_getcaps(data)); 102} 103 104static kobj_method_t ua_chan_methods[] = { 105 KOBJMETHOD(channel_init, ua_chan_init), 106 KOBJMETHOD(channel_free, ua_chan_free), 107 KOBJMETHOD(channel_setformat, ua_chan_setformat), 108 KOBJMETHOD(channel_setspeed, ua_chan_setspeed), 109 KOBJMETHOD(channel_setblocksize, ua_chan_setblocksize), 110 KOBJMETHOD(channel_setfragments, ua_chan_setfragments), 111 KOBJMETHOD(channel_trigger, ua_chan_trigger), 112 KOBJMETHOD(channel_getptr, ua_chan_getptr), 113 KOBJMETHOD(channel_getcaps, ua_chan_getcaps), 114 {0, 0} 115}; 116 117CHANNEL_DECLARE(ua_chan); 118 119/************************************************************/ 120static int 121ua_mixer_init(struct snd_mixer *m) 122{ 123 return (uaudio_mixer_init_sub(mix_getdevinfo(m), m)); 124} 125 126static int 127ua_mixer_set(struct snd_mixer *m, unsigned type, unsigned left, unsigned right) 128{ 129 struct mtx *mtx = mixer_get_lock(m); 130 uint8_t do_unlock; 131 132 if (mtx_owned(mtx)) { 133 do_unlock = 0; 134 } else { 135 do_unlock = 1; 136 mtx_lock(mtx); 137 } 138 uaudio_mixer_set(mix_getdevinfo(m), type, left, right); 139 if (do_unlock) { 140 mtx_unlock(mtx); 141 } 142 return (left | (right << 8)); 143} 144 145static int 146ua_mixer_setrecsrc(struct snd_mixer *m, uint32_t src) 147{ 148 struct mtx *mtx = mixer_get_lock(m); 149 int retval; 150 uint8_t do_unlock; 151 152 if (mtx_owned(mtx)) { 153 do_unlock = 0; 154 } else { 155 do_unlock = 1; 156 mtx_lock(mtx); 157 } 158 retval = uaudio_mixer_setrecsrc(mix_getdevinfo(m), src); 159 if (do_unlock) { 160 mtx_unlock(mtx); 161 } 162 return (retval); 163} 164 165static int 166ua_mixer_uninit(struct snd_mixer *m) 167{ 168 return (uaudio_mixer_uninit_sub(mix_getdevinfo(m))); 169} 170 171static kobj_method_t ua_mixer_methods[] = { 172 KOBJMETHOD(mixer_init, ua_mixer_init), 173 KOBJMETHOD(mixer_uninit, ua_mixer_uninit), 174 KOBJMETHOD(mixer_set, ua_mixer_set), 175 KOBJMETHOD(mixer_setrecsrc, ua_mixer_setrecsrc), 176 177 {0, 0} 178}; 179 180MIXER_DECLARE(ua_mixer); 181/************************************************************/ 182 183 184static int 185ua_probe(device_t dev) 186{ 187 struct sndcard_func *func; 188 189 /* the parent device has already been probed */ 190 191 func = device_get_ivars(dev); 192 193 if ((func == NULL) || 194 (func->func != SCF_PCM)) { 195 return (ENXIO); 196 } 197 device_set_desc(dev, "USB audio"); 198 199 return (BUS_PROBE_DEFAULT); 200} 201 202static int 203ua_attach(device_t dev) 204{ 205 return (uaudio_attach_sub(dev, &ua_mixer_class, &ua_chan_class)); 206} 207 208static int 209ua_detach(device_t dev) 210{ 211 return (uaudio_detach_sub(dev)); 212} 213 214/************************************************************/ 215 216static device_method_t ua_pcm_methods[] = { 217 /* Device interface */ 218 DEVMETHOD(device_probe, ua_probe), 219 DEVMETHOD(device_attach, ua_attach), 220 DEVMETHOD(device_detach, ua_detach), 221 222 {0, 0} 223}; 224 225static driver_t ua_pcm_driver = { 226 "pcm", 227 ua_pcm_methods, 228 PCM_SOFTC_SIZE, 229}; 230 231DRIVER_MODULE(ua_pcm, uaudio, ua_pcm_driver, pcm_devclass, 0, 0); 232MODULE_DEPEND(ua_pcm, uaudio, 1, 1, 1); 233MODULE_DEPEND(ua_pcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 234MODULE_VERSION(ua_pcm, 1); 235