1 /* $FreeBSD: head/sys/dev/sound/usb/uaudio_pcm.c 246128 2013-01-30 18:01:20Z sbz $ */ 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 "opt_snd.h" 31 32 #include <dev/sound/pcm/sound.h> 33 #include <dev/sound/chip.h> 34 #include <bus/u4b/audio/uaudio.h> 35 36 #include "mixer_if.h" 37 38 /************************************************************/ 39 static void * 40 ua_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 45 static int 46 ua_chan_free(kobj_t obj, void *data) 47 { 48 return (uaudio_chan_free(data)); 49 } 50 51 static int 52 ua_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 61 static uint32_t 62 ua_chan_setspeed(kobj_t obj, void *data, uint32_t speed) 63 { 64 return (uaudio_chan_set_param_speed(data, speed)); 65 } 66 67 static uint32_t 68 ua_chan_setblocksize(kobj_t obj, void *data, uint32_t blocksize) 69 { 70 return (uaudio_chan_set_param_blocksize(data, blocksize)); 71 } 72 73 static int 74 ua_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 79 static int 80 ua_chan_trigger(kobj_t obj, void *data, int go) 81 { 82 if (PCMTRIG_COMMON(go)) { 83 if (go == PCMTRIG_START) { 84 uaudio_chan_start(data); 85 } else { 86 uaudio_chan_stop(data); 87 } 88 } 89 return (0); 90 } 91 92 static uint32_t 93 ua_chan_getptr(kobj_t obj, void *data) 94 { 95 return (uaudio_chan_getptr(data)); 96 } 97 98 static struct pcmchan_caps * 99 ua_chan_getcaps(kobj_t obj, void *data) 100 { 101 return (uaudio_chan_getcaps(data)); 102 } 103 104 static struct pcmchan_matrix * 105 ua_chan_getmatrix(kobj_t obj, void *data, uint32_t format) 106 { 107 return (uaudio_chan_getmatrix(data, format)); 108 } 109 110 static kobj_method_t ua_chan_methods[] = { 111 KOBJMETHOD(channel_init, ua_chan_init), 112 KOBJMETHOD(channel_free, ua_chan_free), 113 KOBJMETHOD(channel_setformat, ua_chan_setformat), 114 KOBJMETHOD(channel_setspeed, ua_chan_setspeed), 115 KOBJMETHOD(channel_setblocksize, ua_chan_setblocksize), 116 KOBJMETHOD(channel_setfragments, ua_chan_setfragments), 117 KOBJMETHOD(channel_trigger, ua_chan_trigger), 118 KOBJMETHOD(channel_getptr, ua_chan_getptr), 119 KOBJMETHOD(channel_getcaps, ua_chan_getcaps), 120 KOBJMETHOD(channel_getmatrix, ua_chan_getmatrix), 121 KOBJMETHOD_END 122 }; 123 124 CHANNEL_DECLARE(ua_chan); 125 126 /************************************************************/ 127 static int 128 ua_mixer_init(struct snd_mixer *m) 129 { 130 return (uaudio_mixer_init_sub(mix_getdevinfo(m), m)); 131 } 132 133 static int 134 ua_mixer_set(struct snd_mixer *m, unsigned type, unsigned left, unsigned right) 135 { 136 struct lock *lock = mixer_get_lock(m); 137 uint8_t do_unlock; 138 139 if (lockowned(lock)) { 140 do_unlock = 0; 141 } else { 142 do_unlock = 1; 143 lockmgr(lock, LK_EXCLUSIVE); 144 } 145 uaudio_mixer_set(mix_getdevinfo(m), type, left, right); 146 if (do_unlock) { 147 lockmgr(lock, LK_RELEASE); 148 } 149 return (left | (right << 8)); 150 } 151 152 static uint32_t 153 ua_mixer_setrecsrc(struct snd_mixer *m, uint32_t src) 154 { 155 struct lock *lock = mixer_get_lock(m); 156 int retval; 157 uint8_t do_unlock; 158 159 if (lockowned(lock)) { 160 do_unlock = 0; 161 } else { 162 do_unlock = 1; 163 lockmgr(lock, LK_EXCLUSIVE); 164 } 165 retval = uaudio_mixer_setrecsrc(mix_getdevinfo(m), src); 166 if (do_unlock) { 167 lockmgr(lock, LK_RELEASE); 168 } 169 return (retval); 170 } 171 172 static int 173 ua_mixer_uninit(struct snd_mixer *m) 174 { 175 return (uaudio_mixer_uninit_sub(mix_getdevinfo(m))); 176 } 177 178 static kobj_method_t ua_mixer_methods[] = { 179 KOBJMETHOD(mixer_init, ua_mixer_init), 180 KOBJMETHOD(mixer_uninit, ua_mixer_uninit), 181 KOBJMETHOD(mixer_set, ua_mixer_set), 182 KOBJMETHOD(mixer_setrecsrc, ua_mixer_setrecsrc), 183 KOBJMETHOD_END 184 }; 185 186 MIXER_DECLARE(ua_mixer); 187 /************************************************************/ 188 189 190 static int 191 ua_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 device_set_desc(dev, "USB audio"); 204 205 return (BUS_PROBE_DEFAULT); 206 } 207 208 static int 209 ua_attach(device_t dev) 210 { 211 return (uaudio_attach_sub(dev, &ua_mixer_class, &ua_chan_class)); 212 } 213 214 static int 215 ua_detach(device_t dev) 216 { 217 return (uaudio_detach_sub(dev)); 218 } 219 220 /************************************************************/ 221 222 static device_method_t ua_pcm_methods[] = { 223 /* Device interface */ 224 DEVMETHOD(device_probe, ua_probe), 225 DEVMETHOD(device_attach, ua_attach), 226 DEVMETHOD(device_detach, ua_detach), 227 228 DEVMETHOD_END 229 }; 230 231 static driver_t ua_pcm_driver = { 232 "pcm", 233 ua_pcm_methods, 234 PCM_SOFTC_SIZE, 235 }; 236 237 DRIVER_MODULE(ua_pcm, uaudio, ua_pcm_driver, pcm_devclass, NULL, NULL); 238 MODULE_DEPEND(ua_pcm, uaudio, 1, 1, 1); 239 MODULE_DEPEND(ua_pcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 240 MODULE_VERSION(ua_pcm, 1); 241