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