1 /* $FreeBSD: releng/5.2/sys/dev/sound/usb/uaudio_pcm.c 117126 2003-07-01 15:52:06Z scottl $ */
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);
Cache object: b69d78202d76933ad4fcd1747b92b8f4
|