1 /* $FreeBSD$ */ 2 3 /*- 4 * Copyright (c) 2000-2002 Hiroyuki Aizu <aizu@navi.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 29 #include <sys/soundcard.h> 30 #include <dev/sound/pcm/sound.h> 31 #include <dev/sound/chip.h> 32 33 #include <dev/sound/usb/uaudio.h> 34 35 #include "mixer_if.h" 36 37 struct ua_info; 38 39 struct ua_chinfo { 40 struct ua_info *parent; 41 struct pcm_channel *channel; 42 struct snd_dbuf *buffer; 43 u_char *buf; 44 int dir, hwch; 45 u_int32_t fmt, spd, blksz; /* XXXXX */ 46 }; 47 48 struct ua_info { 49 device_t sc_dev; 50 u_int32_t bufsz; 51 struct ua_chinfo pch, rch; 52 }; 53 54 static u_int32_t ua_playfmt[8*2+1]; /* 8 format * (stereo or mono) + endptr */ 55 56 static struct pcmchan_caps ua_playcaps = {8000, 48000, ua_playfmt, 0}; 57 58 static u_int32_t ua_recfmt[8*2+1]; /* 8 format * (stereo or mono) + endptr */ 59 60 static struct pcmchan_caps ua_reccaps = {8000, 48000, ua_recfmt, 0}; 61 62 #define UAUDIO_DEFAULT_BUFSZ 16*1024 63 64 /************************************************************/ 65 static void * 66 ua_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 67 { 68 device_t pa_dev; 69 70 struct ua_info *sc = devinfo; 71 struct ua_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; 72 73 ch->parent = sc; 74 ch->channel = c; 75 ch->buffer = b; 76 ch->dir = dir; 77 78 pa_dev = device_get_parent(sc->sc_dev); 79 /* Create ua_playfmt[] & ua_recfmt[] */ 80 uaudio_query_formats(pa_dev, (u_int32_t *)&ua_playfmt, (u_int32_t *)&ua_recfmt); 81 if (dir == PCMDIR_PLAY) { 82 if (ua_playfmt[0] == 0) { 83 printf("play channel supported format list invalid\n"); 84 return NULL; 85 } 86 } else { 87 if (ua_recfmt[0] == 0) { 88 printf("record channel supported format list invalid\n"); 89 return NULL; 90 } 91 92 } 93 94 ch->buf = malloc(sc->bufsz, M_DEVBUF, M_NOWAIT); 95 if (ch->buf == NULL) 96 return NULL; 97 if (sndbuf_setup(b, ch->buf, sc->bufsz) != 0) { 98 free(ch->buf, M_DEVBUF); 99 return NULL; 100 } 101 uaudio_chan_set_param_pcm_dma_buff(pa_dev, ch->buf, ch->buf+sc->bufsz, ch->channel, dir); 102 if (bootverbose) 103 device_printf(pa_dev, "%s buf %p\n", (dir == PCMDIR_PLAY)? 104 "play" : "rec", sndbuf_getbuf(ch->buffer)); 105 106 ch->dir = dir; 107 #ifndef NO_RECORDING 108 ch->hwch = 1; 109 if (dir == PCMDIR_PLAY) 110 ch->hwch = 2; 111 #else 112 ch->hwch = 2; 113 #endif 114 115 return ch; 116 } 117 118 static int 119 ua_chan_free(kobj_t obj, void *data) 120 { 121 struct ua_chinfo *ua = data; 122 123 if (ua->buf != NULL) 124 free(ua->buf, M_DEVBUF); 125 return 0; 126 } 127 128 static int 129 ua_chan_setformat(kobj_t obj, void *data, u_int32_t format) 130 { 131 device_t pa_dev; 132 struct ua_info *ua; 133 134 struct ua_chinfo *ch = data; 135 136 ua = ch->parent; 137 pa_dev = device_get_parent(ua->sc_dev); 138 uaudio_chan_set_param_format(pa_dev, format, ch->dir); 139 140 ch->fmt = format; 141 return 0; 142 } 143 144 static int 145 ua_chan_setspeed(kobj_t obj, void *data, u_int32_t speed) 146 { 147 device_t pa_dev; 148 struct ua_info *ua; 149 150 struct ua_chinfo *ch = data; 151 ch->spd = speed; 152 153 ua = ch->parent; 154 pa_dev = device_get_parent(ua->sc_dev); 155 uaudio_chan_set_param_speed(pa_dev, speed, ch->dir); 156 157 return ch->spd; 158 } 159 160 static int 161 ua_chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 162 { 163 device_t pa_dev; 164 struct ua_chinfo *ch = data; 165 struct ua_info *ua = ch->parent; 166 167 if (blocksize) { 168 RANGE(blocksize, 128, ua->bufsz / 2); 169 if (sndbuf_resize(ch->buffer, ua->bufsz/blocksize, blocksize) != 0) { 170 ch->blksz = blocksize; 171 } 172 } 173 pa_dev = device_get_parent(ua->sc_dev); 174 uaudio_chan_set_param_blocksize(pa_dev, blocksize, ch->dir); 175 176 return ch->blksz; 177 } 178 179 static int 180 ua_chan_trigger(kobj_t obj, void *data, int go) 181 { 182 device_t pa_dev; 183 struct ua_info *ua; 184 struct ua_chinfo *ch = data; 185 186 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 187 return 0; 188 189 ua = ch->parent; 190 pa_dev = device_get_parent(ua->sc_dev); 191 192 /* XXXXX */ 193 if (ch->dir == PCMDIR_PLAY) { 194 if (go == PCMTRIG_START) { 195 uaudio_trigger_output(pa_dev); 196 } else { 197 uaudio_halt_out_dma(pa_dev); 198 } 199 } else { 200 #ifndef NO_RECORDING 201 if (go == PCMTRIG_START) 202 uaudio_trigger_input(pa_dev); 203 else 204 uaudio_halt_in_dma(pa_dev); 205 #endif 206 } 207 208 return 0; 209 } 210 211 static int 212 ua_chan_getptr(kobj_t obj, void *data) 213 { 214 device_t pa_dev; 215 struct ua_info *ua; 216 struct ua_chinfo *ch = data; 217 218 ua = ch->parent; 219 pa_dev = device_get_parent(ua->sc_dev); 220 221 return uaudio_chan_getptr(pa_dev, ch->dir); 222 } 223 224 static struct pcmchan_caps * 225 ua_chan_getcaps(kobj_t obj, void *data) 226 { 227 struct ua_chinfo *ch = data; 228 229 return (ch->dir == PCMDIR_PLAY) ? &ua_playcaps : & ua_reccaps; 230 } 231 232 static kobj_method_t ua_chan_methods[] = { 233 KOBJMETHOD(channel_init, ua_chan_init), 234 KOBJMETHOD(channel_free, ua_chan_free), 235 KOBJMETHOD(channel_setformat, ua_chan_setformat), 236 KOBJMETHOD(channel_setspeed, ua_chan_setspeed), 237 KOBJMETHOD(channel_setblocksize, ua_chan_setblocksize), 238 KOBJMETHOD(channel_trigger, ua_chan_trigger), 239 KOBJMETHOD(channel_getptr, ua_chan_getptr), 240 KOBJMETHOD(channel_getcaps, ua_chan_getcaps), 241 { 0, 0 } 242 }; 243 244 CHANNEL_DECLARE(ua_chan); 245 246 /************************************************************/ 247 static int 248 ua_mixer_init(struct snd_mixer *m) 249 { 250 u_int32_t mask; 251 device_t pa_dev; 252 struct ua_info *ua = mix_getdevinfo(m); 253 254 pa_dev = device_get_parent(ua->sc_dev); 255 256 mask = uaudio_query_mix_info(pa_dev); 257 mix_setdevs(m, mask); 258 259 mask = uaudio_query_recsrc_info(pa_dev); 260 mix_setrecdevs(m, mask); 261 262 return 0; 263 } 264 265 static int 266 ua_mixer_set(struct snd_mixer *m, unsigned type, unsigned left, unsigned right) 267 { 268 device_t pa_dev; 269 struct ua_info *ua = mix_getdevinfo(m); 270 271 pa_dev = device_get_parent(ua->sc_dev); 272 uaudio_mixer_set(pa_dev, type, left, right); 273 274 return left | (right << 8); 275 } 276 277 static int 278 ua_mixer_setrecsrc(struct snd_mixer *m, u_int32_t src) 279 { 280 device_t pa_dev; 281 struct ua_info *ua = mix_getdevinfo(m); 282 283 pa_dev = device_get_parent(ua->sc_dev); 284 return uaudio_mixer_setrecsrc(pa_dev, src); 285 } 286 287 static kobj_method_t ua_mixer_methods[] = { 288 KOBJMETHOD(mixer_init, ua_mixer_init), 289 KOBJMETHOD(mixer_set, ua_mixer_set), 290 KOBJMETHOD(mixer_setrecsrc, ua_mixer_setrecsrc), 291 292 { 0, 0 } 293 }; 294 MIXER_DECLARE(ua_mixer); 295 /************************************************************/ 296 297 298 static int 299 ua_probe(device_t dev) 300 { 301 char *s; 302 struct sndcard_func *func; 303 304 /* The parent device has already been probed. */ 305 306 func = device_get_ivars(dev); 307 if (func == NULL || func->func != SCF_PCM) 308 return (ENXIO); 309 310 s = "USB Audio"; 311 312 device_set_desc(dev, s); 313 return BUS_PROBE_DEFAULT; 314 } 315 316 static int 317 ua_attach(device_t dev) 318 { 319 struct ua_info *ua; 320 char status[SND_STATUSLEN]; 321 322 ua = (struct ua_info *)malloc(sizeof *ua, M_DEVBUF, M_NOWAIT); 323 if (!ua) 324 return ENXIO; 325 bzero(ua, sizeof *ua); 326 327 ua->sc_dev = dev; 328 329 ua->bufsz = pcm_getbuffersize(dev, 4096, UAUDIO_DEFAULT_BUFSZ, 65536); 330 if (bootverbose) 331 device_printf(dev, "using a default buffer size of %jd\n", (intmax_t)ua->bufsz); 332 333 if (mixer_init(dev, &ua_mixer_class, ua)) { 334 return(ENXIO); 335 } 336 337 snprintf(status, SND_STATUSLEN, "at addr ?"); 338 339 #ifndef NO_RECORDING 340 if (pcm_register(dev, ua, 1, 1)) { 341 #else 342 if (pcm_register(dev, ua, 1, 0)) { 343 #endif 344 return(ENXIO); 345 } 346 347 pcm_addchan(dev, PCMDIR_PLAY, &ua_chan_class, ua); 348 #ifndef NO_RECORDING 349 pcm_addchan(dev, PCMDIR_REC, &ua_chan_class, ua); 350 #endif 351 pcm_setstatus(dev, status); 352 353 return 0; 354 } 355 356 static int 357 ua_detach(device_t dev) 358 { 359 int r; 360 struct ua_info *sc; 361 362 r = pcm_unregister(dev); 363 if (r) 364 return r; 365 366 sc = pcm_getdevinfo(dev); 367 free(sc, M_DEVBUF); 368 369 return 0; 370 } 371 372 /************************************************************/ 373 374 static device_method_t ua_pcm_methods[] = { 375 /* Device interface */ 376 DEVMETHOD(device_probe, ua_probe), 377 DEVMETHOD(device_attach, ua_attach), 378 DEVMETHOD(device_detach, ua_detach), 379 380 { 0, 0 } 381 }; 382 383 static driver_t ua_pcm_driver = { 384 "pcm", 385 ua_pcm_methods, 386 PCM_SOFTC_SIZE, 387 }; 388 389 390 DRIVER_MODULE(ua_pcm, uaudio, ua_pcm_driver, pcm_devclass, 0, 0); 391 MODULE_DEPEND(ua_pcm, uaudio, 1, 1, 1); 392 MODULE_DEPEND(ua_pcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 393 MODULE_VERSION(ua_pcm, 1); 394