xref: /freebsd/sys/dev/sound/usb/uaudio_pcm.c (revision ebccf1e3a6b11b97cbf5f813dd76636e892a9035)
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