xref: /freebsd/sys/dev/sound/usb/uaudio_pcm.c (revision 7660b554bc59a07be0431c17e0e33815818baa69)
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 	int dir, hwch;
44 	u_int32_t fmt, spd, blksz;	/* XXXXX */
45 };
46 
47 struct ua_info {
48 	device_t sc_dev;
49 	struct ua_chinfo pch, rch;
50 	bus_dma_tag_t	parent_dmat;
51 };
52 
53 static u_int32_t ua_playfmt[8*2+1]; /* 8 format * (stereo or mono) + endptr */
54 
55 static struct pcmchan_caps ua_playcaps = {8000, 48000, ua_playfmt, 0};
56 
57 static u_int32_t ua_recfmt[8*2+1]; /* 8 format * (stereo or mono) + endptr */
58 
59 static struct pcmchan_caps ua_reccaps = {8000, 48000, ua_recfmt, 0};
60 
61 #define UAUDIO_PCM_BUFF_SIZE	16*1024
62 
63 /************************************************************/
64 static void *
65 ua_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
66 {
67 	device_t pa_dev;
68 	u_char *buf,*end;
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 
77 	pa_dev = device_get_parent(sc->sc_dev);
78      	/* Create ua_playfmt[] & ua_recfmt[] */
79 	uaudio_query_formats(pa_dev, (u_int32_t *)&ua_playfmt, (u_int32_t *)&ua_recfmt);
80 	if (ua_playfmt[0] == 0) {
81 		printf("%s channel supported format list invalid\n", dir == PCMDIR_PLAY? "play" : "record");
82 		return NULL;
83 	}
84 
85 	/* allocate PCM side DMA buffer */
86 	if (sndbuf_alloc(ch->buffer, sc->parent_dmat, UAUDIO_PCM_BUFF_SIZE) != 0) {
87 	    return NULL;
88         }
89 
90 	buf = end = sndbuf_getbuf(b);
91 	end += sndbuf_getsize(b);
92 	uaudio_chan_set_param_pcm_dma_buff(pa_dev, buf, end, ch->channel);
93 
94 	ch->dir = dir;
95 #ifndef NO_RECORDING
96 	ch->hwch = 1;
97 	if (dir == PCMDIR_PLAY)
98 		ch->hwch = 2;
99 #else
100 	ch->hwch = 2;
101 #endif
102 
103 	return ch;
104 }
105 
106 static int
107 ua_chan_setformat(kobj_t obj, void *data, u_int32_t format)
108 {
109 	device_t pa_dev;
110 	struct ua_info *ua;
111 
112 	struct ua_chinfo *ch = data;
113 
114 	ua = ch->parent;
115 	pa_dev = device_get_parent(ua->sc_dev);
116 	uaudio_chan_set_param_format(pa_dev, format);
117 
118 	ch->fmt = format;
119 	return 0;
120 }
121 
122 static int
123 ua_chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
124 {
125 	device_t pa_dev;
126 	struct ua_info *ua;
127 
128 	struct ua_chinfo *ch = data;
129 	ch->spd = speed;
130 
131 	ua = ch->parent;
132 	pa_dev = device_get_parent(ua->sc_dev);
133 	uaudio_chan_set_param_speed(pa_dev, speed);
134 
135 	return ch->spd;
136 }
137 
138 static int
139 ua_chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
140 {
141 	device_t pa_dev;
142 	struct ua_info *ua;
143 	struct ua_chinfo *ch = data;
144 	/* ch->blksz = blocksize; */
145 	if (blocksize) {
146 		ch->blksz = blocksize;
147 	} else {
148 		ch->blksz = UAUDIO_PCM_BUFF_SIZE/2;
149 	}
150 
151 	/* XXXXX */
152 	ua = ch->parent;
153 	pa_dev = device_get_parent(ua->sc_dev);
154 	uaudio_chan_set_param_blocksize(pa_dev, blocksize);
155 
156 	return ch->blksz;
157 }
158 
159 static int
160 ua_chan_trigger(kobj_t obj, void *data, int go)
161 {
162 	device_t pa_dev;
163 	struct ua_info *ua;
164 	struct ua_chinfo *ch = data;
165 
166 	if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
167 		return 0;
168 
169 	ua = ch->parent;
170 	pa_dev = device_get_parent(ua->sc_dev);
171 
172 	/* XXXXX */
173 	if (ch->dir == PCMDIR_PLAY) {
174 		if (go == PCMTRIG_START) {
175 			uaudio_trigger_output(pa_dev);
176 		} else {
177 			uaudio_halt_out_dma(pa_dev);
178 		}
179 	} else {
180 #ifndef NO_RECORDING
181 		if (go == PCMTRIG_START)
182 			uaudio_trigger_input(pa_dev);
183 		else
184 			uaudio_halt_in_dma(pa_dev);
185 #endif
186 	}
187 
188 	return 0;
189 }
190 
191 static int
192 ua_chan_getptr(kobj_t obj, void *data)
193 {
194 	device_t pa_dev;
195 	struct ua_info *ua;
196 	struct ua_chinfo *ch = data;
197 
198 	ua = ch->parent;
199 	pa_dev = device_get_parent(ua->sc_dev);
200 
201 	return uaudio_chan_getptr(pa_dev);
202 }
203 
204 static struct pcmchan_caps *
205 ua_chan_getcaps(kobj_t obj, void *data)
206 {
207 	struct ua_chinfo *ch = data;
208 
209 	return (ch->dir == PCMDIR_PLAY) ? &ua_playcaps : & ua_reccaps;
210 }
211 
212 static kobj_method_t ua_chan_methods[] = {
213 	KOBJMETHOD(channel_init,		ua_chan_init),
214 	KOBJMETHOD(channel_setformat,		ua_chan_setformat),
215 	KOBJMETHOD(channel_setspeed,		ua_chan_setspeed),
216 	KOBJMETHOD(channel_setblocksize,	ua_chan_setblocksize),
217 	KOBJMETHOD(channel_trigger,		ua_chan_trigger),
218 	KOBJMETHOD(channel_getptr,		ua_chan_getptr),
219 	KOBJMETHOD(channel_getcaps,		ua_chan_getcaps),
220 	{ 0, 0 }
221 };
222 
223 CHANNEL_DECLARE(ua_chan);
224 
225 /************************************************************/
226 static int
227 ua_mixer_init(struct snd_mixer *m)
228 {
229 	u_int32_t mask;
230 	device_t pa_dev;
231 	struct ua_info *ua = mix_getdevinfo(m);
232 
233 	pa_dev = device_get_parent(ua->sc_dev);
234 
235 	mask = uaudio_query_mix_info(pa_dev);
236 	mix_setdevs(m,	mask);
237 
238 	return 0;
239 }
240 
241 static int
242 ua_mixer_set(struct snd_mixer *m, unsigned type, unsigned left, unsigned right)
243 {
244 	device_t pa_dev;
245 	struct ua_info *ua = mix_getdevinfo(m);
246 
247 	pa_dev = device_get_parent(ua->sc_dev);
248 	uaudio_mixer_set(pa_dev, type, left, right);
249 
250 	return left | (right << 8);
251 }
252 
253 static int
254 ua_mixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
255 {
256 	return src;
257 }
258 
259 static kobj_method_t ua_mixer_methods[] = {
260 	KOBJMETHOD(mixer_init,		ua_mixer_init),
261 	KOBJMETHOD(mixer_set,		ua_mixer_set),
262 	KOBJMETHOD(mixer_setrecsrc,	ua_mixer_setrecsrc),
263 
264 	{ 0, 0 }
265 };
266 MIXER_DECLARE(ua_mixer);
267 /************************************************************/
268 
269 
270 static int
271 ua_probe(device_t dev)
272 {
273 	char *s;
274 	struct sndcard_func *func;
275 
276 	/* The parent device has already been probed. */
277 
278 	func = device_get_ivars(dev);
279 	if (func == NULL || func->func != SCF_PCM)
280 		return (ENXIO);
281 
282 	s = "USB Audio";
283 
284 	device_set_desc(dev, s);
285 	return 0;
286 }
287 
288 static int
289 ua_attach(device_t dev)
290 {
291 	struct ua_info *ua;
292 	char status[SND_STATUSLEN];
293 	unsigned int bufsz;
294 
295 	ua = (struct ua_info *)malloc(sizeof *ua, M_DEVBUF, M_NOWAIT);
296 	if (!ua)
297 		return ENXIO;
298 	bzero(ua, sizeof *ua);
299 
300 	ua->sc_dev = dev;
301 
302 	bufsz = pcm_getbuffersize(dev, 4096, UAUDIO_PCM_BUFF_SIZE, 65536);
303 
304 	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
305 				/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
306 				/*highaddr*/BUS_SPACE_MAXADDR,
307 				/*filter*/NULL, /*filterarg*/NULL,
308 				/*maxsize*/bufsz, /*nsegments*/1,
309 				/*maxsegz*/0x3fff, /*flags*/0,
310 				/*lockfunc*/busdma_lock_mutex,
311 				/*lockarg*/&Giant,
312 				&ua->parent_dmat) != 0) {
313 		device_printf(dev, "unable to create dma tag\n");
314 		goto bad;
315 	}
316 
317 	if (mixer_init(dev, &ua_mixer_class, ua)) {
318 		return(ENXIO);
319 	}
320 
321 	snprintf(status, SND_STATUSLEN, "at addr ?");
322 
323 	if (pcm_register(dev, ua, 1, 0)) {
324 		return(ENXIO);
325 	}
326 
327 	pcm_addchan(dev, PCMDIR_PLAY, &ua_chan_class, ua);
328 #ifndef NO_RECORDING
329 	pcm_addchan(dev, PCMDIR_REC, &ua_chan_class, ua);
330 #endif
331 	pcm_setstatus(dev, status);
332 
333 	return 0;
334 bad:
335 	if (ua->parent_dmat)
336 		bus_dma_tag_destroy(ua->parent_dmat);
337 	free(ua, M_DEVBUF);
338 
339 	return ENXIO;
340 }
341 
342 static int
343 ua_detach(device_t dev)
344 {
345 	int r;
346 	struct ua_info *sc;
347 
348 	r = pcm_unregister(dev);
349 	if (r)
350 		return r;
351 
352 	sc = pcm_getdevinfo(dev);
353 	bus_dma_tag_destroy(sc->parent_dmat);
354 	free(sc, M_DEVBUF);
355 
356 	return 0;
357 }
358 
359 /************************************************************/
360 
361 static device_method_t ua_pcm_methods[] = {
362 	/* Device interface */
363 	DEVMETHOD(device_probe,		ua_probe),
364 	DEVMETHOD(device_attach,	ua_attach),
365 	DEVMETHOD(device_detach,	ua_detach),
366 
367 	{ 0, 0 }
368 };
369 
370 static driver_t ua_pcm_driver = {
371 	"pcm",
372 	ua_pcm_methods,
373 	PCM_SOFTC_SIZE,
374 };
375 
376 static devclass_t pcm_devclass;
377 
378 DRIVER_MODULE(ua_pcm, uaudio, ua_pcm_driver, pcm_devclass, 0, 0);
379 MODULE_DEPEND(ua_pcm, uaudio, 1, 1, 1);
380 MODULE_DEPEND(ua_pcm, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
381 MODULE_VERSION(ua_pcm, 1);
382