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