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 #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 <bus/u4b/audio/uaudio.h> 37 38 #include "mixer_if.h" 39 40 /************************************************************/ 41 static void * 42 ua_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 47 static int 48 ua_chan_free(kobj_t obj, void *data) 49 { 50 return (uaudio_chan_free(data)); 51 } 52 53 static int 54 ua_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 63 static uint32_t 64 ua_chan_setspeed(kobj_t obj, void *data, uint32_t speed) 65 { 66 return (uaudio_chan_set_param_speed(data, speed)); 67 } 68 69 static uint32_t 70 ua_chan_setblocksize(kobj_t obj, void *data, uint32_t blocksize) 71 { 72 return (uaudio_chan_set_param_blocksize(data, blocksize)); 73 } 74 75 #if 0 76 static int 77 ua_chan_setfragments(kobj_t obj, void *data, uint32_t blocksize, uint32_t blockcount) 78 { 79 return (uaudio_chan_set_param_fragments(data, blocksize, blockcount)); 80 } 81 #endif 82 83 static int 84 ua_chan_trigger(kobj_t obj, void *data, int go) 85 { 86 if (!PCMTRIG_COMMON(go)) { 87 return (0); 88 } 89 if (go == PCMTRIG_START) { 90 return (uaudio_chan_start(data)); 91 } else { 92 return (uaudio_chan_stop(data)); 93 } 94 } 95 96 static uint32_t 97 ua_chan_getptr(kobj_t obj, void *data) 98 { 99 return (uaudio_chan_getptr(data)); 100 } 101 102 static struct pcmchan_caps * 103 ua_chan_getcaps(kobj_t obj, void *data) 104 { 105 return (uaudio_chan_getcaps(data)); 106 } 107 108 #if 0 109 static struct pcmchan_matrix * 110 ua_chan_getmatrix(kobj_t obj, void *data, uint32_t format) 111 { 112 return (uaudio_chan_getmatrix(data, format)); 113 } 114 #endif 115 116 static kobj_method_t ua_chan_methods[] = { 117 KOBJMETHOD(channel_init, ua_chan_init), 118 KOBJMETHOD(channel_free, ua_chan_free), 119 KOBJMETHOD(channel_setformat, ua_chan_setformat), 120 KOBJMETHOD(channel_setspeed, ua_chan_setspeed), 121 KOBJMETHOD(channel_setblocksize, ua_chan_setblocksize), 122 #if 0 123 KOBJMETHOD(channel_setfragments, ua_chan_setfragments), 124 #endif 125 KOBJMETHOD(channel_trigger, ua_chan_trigger), 126 KOBJMETHOD(channel_getptr, ua_chan_getptr), 127 KOBJMETHOD(channel_getcaps, ua_chan_getcaps), 128 #if 0 129 KOBJMETHOD(channel_getmatrix, ua_chan_getmatrix), 130 #endif 131 KOBJMETHOD_END 132 }; 133 134 CHANNEL_DECLARE(ua_chan); 135 136 /************************************************************/ 137 static int 138 ua_mixer_init(struct snd_mixer *m) 139 { 140 return (uaudio_mixer_init_sub(mix_getdevinfo(m), m)); 141 } 142 143 static int 144 ua_mixer_set(struct snd_mixer *m, unsigned type, unsigned left, unsigned right) 145 { 146 sndlock_t lock = uaudio_mixer_lock(m); 147 snd_mtxlock(lock); 148 uaudio_mixer_set(mix_getdevinfo(m), type, left, right); 149 snd_mtxunlock(lock); 150 return (left | (right << 8)); 151 } 152 153 static uint32_t 154 ua_mixer_setrecsrc(struct snd_mixer *m, uint32_t src) 155 { 156 int retval; 157 sndlock_t lock = uaudio_mixer_lock(m); 158 snd_mtxlock(lock); 159 retval = uaudio_mixer_setrecsrc(mix_getdevinfo(m), src); 160 snd_mtxunlock(lock); 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 KOBJMETHOD_END 176 }; 177 178 MIXER_DECLARE(ua_mixer); 179 /************************************************************/ 180 181 182 static int 183 ua_probe(device_t dev) 184 { 185 struct sndcard_func *func; 186 187 /* the parent device has already been probed */ 188 189 func = device_get_ivars(dev); 190 191 if ((func == NULL) || 192 (func->func != SCF_PCM)) { 193 return (ENXIO); 194 } 195 device_set_desc(dev, "USB audio"); 196 197 return (BUS_PROBE_DEFAULT); 198 } 199 200 static int 201 ua_attach(device_t dev) 202 { 203 return (uaudio_attach_sub(dev, &ua_mixer_class, &ua_chan_class)); 204 } 205 206 static int 207 ua_detach(device_t dev) 208 { 209 return (uaudio_detach_sub(dev)); 210 } 211 212 /************************************************************/ 213 214 static device_method_t ua_pcm_methods[] = { 215 /* Device interface */ 216 DEVMETHOD(device_probe, ua_probe), 217 DEVMETHOD(device_attach, ua_attach), 218 DEVMETHOD(device_detach, ua_detach), 219 220 DEVMETHOD_END 221 }; 222 223 static driver_t ua_pcm_driver = { 224 "pcm", 225 ua_pcm_methods, 226 PCM_SOFTC_SIZE, 227 }; 228 229 DRIVER_MODULE(ua_pcm, uaudio, ua_pcm_driver, pcm_devclass, NULL, NULL); 230 MODULE_DEPEND(ua_pcm, uaudio, 1, 1, 1); 231 MODULE_DEPEND(ua_pcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 232 MODULE_VERSION(ua_pcm, 1); 233