1184610Salfred/* $FreeBSD: stable/11/sys/dev/sound/usb/uaudio_pcm.c 359889 2020-04-13 16:33:45Z hselasky $ */ 2184610Salfred 3184610Salfred/*- 4184610Salfred * Copyright (c) 2000-2002 Hiroyuki Aizu <aizu@navi.org> 5184610Salfred * Copyright (c) 2006 Hans Petter Selasky 6184610Salfred * 7184610Salfred * Redistribution and use in source and binary forms, with or without 8184610Salfred * modification, are permitted provided that the following conditions 9184610Salfred * are met: 10184610Salfred * 1. Redistributions of source code must retain the above copyright 11184610Salfred * notice, this list of conditions and the following disclaimer. 12184610Salfred * 2. Redistributions in binary form must reproduce the above copyright 13184610Salfred * notice, this list of conditions and the following disclaimer in the 14184610Salfred * documentation and/or other materials provided with the distribution. 15184610Salfred * 16184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19184610Salfred * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20184610Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21184610Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22184610Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23184610Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24184610Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25184610Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26184610Salfred * SUCH DAMAGE. 27184610Salfred */ 28184610Salfred 29184610Salfred 30193640Sariff#ifdef HAVE_KERNEL_OPTION_HEADERS 31193640Sariff#include "opt_snd.h" 32193640Sariff#endif 33193640Sariff 34184610Salfred#include <dev/sound/pcm/sound.h> 35184610Salfred#include <dev/sound/chip.h> 36188957Sthompsa#include <dev/sound/usb/uaudio.h> 37184610Salfred 38184610Salfred#include "mixer_if.h" 39184610Salfred 40184610Salfred/************************************************************/ 41184610Salfredstatic void * 42184610Salfredua_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 43184610Salfred{ 44184610Salfred return (uaudio_chan_init(devinfo, b, c, dir)); 45184610Salfred} 46184610Salfred 47184610Salfredstatic int 48184610Salfredua_chan_free(kobj_t obj, void *data) 49184610Salfred{ 50184610Salfred return (uaudio_chan_free(data)); 51184610Salfred} 52184610Salfred 53184610Salfredstatic int 54184610Salfredua_chan_setformat(kobj_t obj, void *data, uint32_t format) 55184610Salfred{ 56184610Salfred /* 57184610Salfred * At this point, no need to query as we 58184610Salfred * shouldn't select an unsorted format 59184610Salfred */ 60184610Salfred return (uaudio_chan_set_param_format(data, format)); 61184610Salfred} 62184610Salfred 63193640Sariffstatic uint32_t 64184610Salfredua_chan_setspeed(kobj_t obj, void *data, uint32_t speed) 65184610Salfred{ 66184610Salfred return (uaudio_chan_set_param_speed(data, speed)); 67184610Salfred} 68184610Salfred 69193640Sariffstatic uint32_t 70184610Salfredua_chan_setblocksize(kobj_t obj, void *data, uint32_t blocksize) 71184610Salfred{ 72184610Salfred return (uaudio_chan_set_param_blocksize(data, blocksize)); 73184610Salfred} 74184610Salfred 75184610Salfredstatic int 76184610Salfredua_chan_setfragments(kobj_t obj, void *data, uint32_t blocksize, uint32_t blockcount) 77184610Salfred{ 78184610Salfred return (uaudio_chan_set_param_fragments(data, blocksize, blockcount)); 79184610Salfred} 80184610Salfred 81184610Salfredstatic int 82184610Salfredua_chan_trigger(kobj_t obj, void *data, int go) 83184610Salfred{ 84280322Shselasky if (PCMTRIG_COMMON(go)) { 85280322Shselasky if (go == PCMTRIG_START) { 86280322Shselasky uaudio_chan_start(data); 87280322Shselasky } else { 88280322Shselasky uaudio_chan_stop(data); 89280322Shselasky } 90184610Salfred } 91280322Shselasky return (0); 92184610Salfred} 93184610Salfred 94193640Sariffstatic uint32_t 95184610Salfredua_chan_getptr(kobj_t obj, void *data) 96184610Salfred{ 97184610Salfred return (uaudio_chan_getptr(data)); 98184610Salfred} 99184610Salfred 100184610Salfredstatic struct pcmchan_caps * 101184610Salfredua_chan_getcaps(kobj_t obj, void *data) 102184610Salfred{ 103184610Salfred return (uaudio_chan_getcaps(data)); 104184610Salfred} 105184610Salfred 106193640Sariffstatic struct pcmchan_matrix * 107193640Sariffua_chan_getmatrix(kobj_t obj, void *data, uint32_t format) 108193640Sariff{ 109193640Sariff return (uaudio_chan_getmatrix(data, format)); 110193640Sariff} 111193640Sariff 112184610Salfredstatic kobj_method_t ua_chan_methods[] = { 113184610Salfred KOBJMETHOD(channel_init, ua_chan_init), 114184610Salfred KOBJMETHOD(channel_free, ua_chan_free), 115184610Salfred KOBJMETHOD(channel_setformat, ua_chan_setformat), 116184610Salfred KOBJMETHOD(channel_setspeed, ua_chan_setspeed), 117184610Salfred KOBJMETHOD(channel_setblocksize, ua_chan_setblocksize), 118184610Salfred KOBJMETHOD(channel_setfragments, ua_chan_setfragments), 119184610Salfred KOBJMETHOD(channel_trigger, ua_chan_trigger), 120184610Salfred KOBJMETHOD(channel_getptr, ua_chan_getptr), 121184610Salfred KOBJMETHOD(channel_getcaps, ua_chan_getcaps), 122193640Sariff KOBJMETHOD(channel_getmatrix, ua_chan_getmatrix), 123193640Sariff KOBJMETHOD_END 124184610Salfred}; 125184610Salfred 126184610SalfredCHANNEL_DECLARE(ua_chan); 127184610Salfred 128184610Salfred/************************************************************/ 129184610Salfredstatic int 130184610Salfredua_mixer_init(struct snd_mixer *m) 131184610Salfred{ 132184610Salfred return (uaudio_mixer_init_sub(mix_getdevinfo(m), m)); 133184610Salfred} 134184610Salfred 135184610Salfredstatic int 136184610Salfredua_mixer_set(struct snd_mixer *m, unsigned type, unsigned left, unsigned right) 137184610Salfred{ 138184610Salfred struct mtx *mtx = mixer_get_lock(m); 139184610Salfred uint8_t do_unlock; 140184610Salfred 141184610Salfred if (mtx_owned(mtx)) { 142184610Salfred do_unlock = 0; 143184610Salfred } else { 144184610Salfred do_unlock = 1; 145184610Salfred mtx_lock(mtx); 146184610Salfred } 147359889Shselasky uaudio_mixer_set(mix_getdevinfo(m), m, type, left, right); 148184610Salfred if (do_unlock) { 149184610Salfred mtx_unlock(mtx); 150184610Salfred } 151184610Salfred return (left | (right << 8)); 152184610Salfred} 153184610Salfred 154193640Sariffstatic uint32_t 155184610Salfredua_mixer_setrecsrc(struct snd_mixer *m, uint32_t src) 156184610Salfred{ 157184610Salfred struct mtx *mtx = mixer_get_lock(m); 158184610Salfred int retval; 159184610Salfred uint8_t do_unlock; 160184610Salfred 161184610Salfred if (mtx_owned(mtx)) { 162184610Salfred do_unlock = 0; 163184610Salfred } else { 164184610Salfred do_unlock = 1; 165184610Salfred mtx_lock(mtx); 166184610Salfred } 167359889Shselasky retval = uaudio_mixer_setrecsrc(mix_getdevinfo(m), m, src); 168184610Salfred if (do_unlock) { 169184610Salfred mtx_unlock(mtx); 170184610Salfred } 171184610Salfred return (retval); 172184610Salfred} 173184610Salfred 174184610Salfredstatic int 175184610Salfredua_mixer_uninit(struct snd_mixer *m) 176184610Salfred{ 177359889Shselasky return (uaudio_mixer_uninit_sub(mix_getdevinfo(m), m)); 178184610Salfred} 179184610Salfred 180184610Salfredstatic kobj_method_t ua_mixer_methods[] = { 181184610Salfred KOBJMETHOD(mixer_init, ua_mixer_init), 182184610Salfred KOBJMETHOD(mixer_uninit, ua_mixer_uninit), 183184610Salfred KOBJMETHOD(mixer_set, ua_mixer_set), 184184610Salfred KOBJMETHOD(mixer_setrecsrc, ua_mixer_setrecsrc), 185193640Sariff KOBJMETHOD_END 186184610Salfred}; 187184610Salfred 188184610SalfredMIXER_DECLARE(ua_mixer); 189184610Salfred/************************************************************/ 190184610Salfred 191184610Salfred 192184610Salfredstatic int 193184610Salfredua_probe(device_t dev) 194184610Salfred{ 195184610Salfred struct sndcard_func *func; 196184610Salfred 197184610Salfred /* the parent device has already been probed */ 198184610Salfred 199184610Salfred func = device_get_ivars(dev); 200184610Salfred 201184610Salfred if ((func == NULL) || 202184610Salfred (func->func != SCF_PCM)) { 203184610Salfred return (ENXIO); 204184610Salfred } 205184610Salfred device_set_desc(dev, "USB audio"); 206184610Salfred 207184610Salfred return (BUS_PROBE_DEFAULT); 208184610Salfred} 209184610Salfred 210184610Salfredstatic int 211184610Salfredua_attach(device_t dev) 212184610Salfred{ 213184610Salfred return (uaudio_attach_sub(dev, &ua_mixer_class, &ua_chan_class)); 214184610Salfred} 215184610Salfred 216184610Salfredstatic int 217184610Salfredua_detach(device_t dev) 218184610Salfred{ 219184610Salfred return (uaudio_detach_sub(dev)); 220184610Salfred} 221184610Salfred 222184610Salfred/************************************************************/ 223184610Salfred 224184610Salfredstatic device_method_t ua_pcm_methods[] = { 225184610Salfred /* Device interface */ 226184610Salfred DEVMETHOD(device_probe, ua_probe), 227184610Salfred DEVMETHOD(device_attach, ua_attach), 228184610Salfred DEVMETHOD(device_detach, ua_detach), 229184610Salfred 230246128Ssbz DEVMETHOD_END 231184610Salfred}; 232184610Salfred 233184610Salfredstatic driver_t ua_pcm_driver = { 234184610Salfred "pcm", 235184610Salfred ua_pcm_methods, 236184610Salfred PCM_SOFTC_SIZE, 237184610Salfred}; 238184610Salfred 239184610SalfredDRIVER_MODULE(ua_pcm, uaudio, ua_pcm_driver, pcm_devclass, 0, 0); 240184610SalfredMODULE_DEPEND(ua_pcm, uaudio, 1, 1, 1); 241184610SalfredMODULE_DEPEND(ua_pcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 242184610SalfredMODULE_VERSION(ua_pcm, 1); 243