FreeBSD kernel sound device code
audio_soc.c
Go to the documentation of this file.
1/*-
2 * Copyright (c) 2019 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 */
25
26#include <sys/cdefs.h>
27__FBSDID("$FreeBSD$");
28
29#include "opt_platform.h"
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/bus.h>
34#include <sys/clock.h>
35#include <sys/kernel.h>
36#include <sys/lock.h>
37#include <sys/module.h>
38#include <sys/endian.h>
39
40#include <dev/ofw/ofw_bus.h>
41#include <dev/ofw/ofw_bus_subr.h>
42
44#include <dev/sound/pcm/sound.h>
45#include "audio_dai_if.h"
46
47#define AUDIO_BUFFER_SIZE 48000 * 4
48
50 SLIST_ENTRY(audio_soc_aux_node) link;
51 device_t dev;
52};
53
55 struct audio_soc_softc *sc; /* parent device's softc */
56 struct pcm_channel *pcm; /* PCM channel */
57 struct snd_dbuf *buf; /* PCM buffer */
58 int dir; /* direction */
59};
60
62 /*
63 * pcm_register assumes that sc is snddev_info,
64 * so this has to be first structure member for "compatibility"
65 */
67 device_t dev;
68 char *name;
69 struct intr_config_hook init_hook;
70 device_t cpu_dev;
71 device_t codec_dev;
73 unsigned int mclk_fs;
74 struct audio_soc_channel play_channel;
75 struct audio_soc_channel rec_channel;
76 /*
77 * The format is from the CPU node, for CODEC node clock roles
78 * need to be reversed.
79 */
80 uint32_t format;
81 uint32_t link_mclk_fs;
82};
83
84static struct ofw_compat_data compat_data[] = {
85 {"simple-audio-card", 1},
86 {NULL, 0},
87};
88
89static struct {
90 const char *name;
91 unsigned int fmt;
93 { "i2s", AUDIO_DAI_FORMAT_I2S },
94 { "right_j", AUDIO_DAI_FORMAT_RJ },
95 { "left_j", AUDIO_DAI_FORMAT_LJ },
96 { "dsp_a", AUDIO_DAI_FORMAT_DSPA },
97 { "dsp_b", AUDIO_DAI_FORMAT_DSPB },
98 { "ac97", AUDIO_DAI_FORMAT_AC97 },
99 { "pdm", AUDIO_DAI_FORMAT_PDM },
101
102static int audio_soc_probe(device_t dev);
103static int audio_soc_attach(device_t dev);
104static int audio_soc_detach(device_t dev);
105
106/*
107 * Invert master/slave roles for CODEC side of the node
108 */
109static uint32_t
111{
112 int fmt, pol, clk;
113
117
118 switch (clk) {
121 break;
124 break;
127 break;
130 break;
131 }
132
133 return AUDIO_DAI_FORMAT(fmt, pol, clk);
134}
135
136static uint32_t
137audio_soc_chan_setblocksize(kobj_t obj, void *data, uint32_t blocksz)
138{
139
140 return (blocksz);
141}
142
143static int
144audio_soc_chan_setformat(kobj_t obj, void *data, uint32_t format)
145{
146
147 struct audio_soc_softc *sc;
148 struct audio_soc_channel *ausoc_chan;
149
150 ausoc_chan = data;
151 sc = ausoc_chan->sc;
152
153 return AUDIO_DAI_SET_CHANFORMAT(sc->cpu_dev, format);
154}
155
156static uint32_t
157audio_soc_chan_setspeed(kobj_t obj, void *data, uint32_t speed)
158{
159
160 struct audio_soc_softc *sc;
161 struct audio_soc_channel *ausoc_chan;
162 uint32_t rate;
163 struct audio_soc_aux_node *aux_node;
164
165 ausoc_chan = data;
166 sc = ausoc_chan->sc;
167
168 if (sc->link_mclk_fs) {
169 rate = speed * sc->link_mclk_fs;
170 if (AUDIO_DAI_SET_SYSCLK(sc->cpu_dev, rate, AUDIO_DAI_CLOCK_IN))
171 device_printf(sc->dev, "failed to set sysclk for CPU node\n");
172
173 if (AUDIO_DAI_SET_SYSCLK(sc->codec_dev, rate, AUDIO_DAI_CLOCK_OUT))
174 device_printf(sc->dev, "failed to set sysclk for codec node\n");
175
176 SLIST_FOREACH(aux_node, &sc->aux_devs, link) {
177 if (AUDIO_DAI_SET_SYSCLK(aux_node->dev, rate, AUDIO_DAI_CLOCK_OUT))
178 device_printf(sc->dev, "failed to set sysclk for aux node\n");
179 }
180 }
181
182 /*
183 * Let CPU node determine speed
184 */
185 speed = AUDIO_DAI_SET_CHANSPEED(sc->cpu_dev, speed);
186 AUDIO_DAI_SET_CHANSPEED(sc->codec_dev, speed);
187 SLIST_FOREACH(aux_node, &sc->aux_devs, link) {
188 AUDIO_DAI_SET_CHANSPEED(aux_node->dev, speed);
189 }
190
191 return (speed);
192}
193
194static uint32_t
195audio_soc_chan_getptr(kobj_t obj, void *data)
196{
197 struct audio_soc_softc *sc;
198 struct audio_soc_channel *ausoc_chan;
199
200 ausoc_chan = data;
201 sc = ausoc_chan->sc;
202
203 return AUDIO_DAI_GET_PTR(sc->cpu_dev, ausoc_chan->dir);
204}
205
206static void *
207audio_soc_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
208 struct pcm_channel *c, int dir)
209{
210 struct audio_soc_channel *ausoc_chan;
211 void *buffer;
212
213 ausoc_chan = devinfo;
214 buffer = malloc(AUDIO_BUFFER_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
215
217 free(buffer, M_DEVBUF);
218 return NULL;
219 }
220
221 ausoc_chan->dir = dir;
222 ausoc_chan->buf = b;
223 ausoc_chan->pcm = c;
224
225 return (devinfo);
226}
227
228static int
229audio_soc_chan_trigger(kobj_t obj, void *data, int go)
230{
231 struct audio_soc_softc *sc;
232 struct audio_soc_channel *ausoc_chan;
233 struct audio_soc_aux_node *aux_node;
234
235 ausoc_chan = (struct audio_soc_channel *)data;
236 sc = ausoc_chan->sc;
237 AUDIO_DAI_TRIGGER(sc->codec_dev, go, ausoc_chan->dir);
238 SLIST_FOREACH(aux_node, &sc->aux_devs, link) {
239 AUDIO_DAI_TRIGGER(aux_node->dev, go, ausoc_chan->dir);
240 }
241
242 return AUDIO_DAI_TRIGGER(sc->cpu_dev, go, ausoc_chan->dir);
243}
244
245static int
246audio_soc_chan_free(kobj_t obj, void *data)
247{
248
249 struct audio_soc_channel *ausoc_chan;
250 void *buffer;
251
252 ausoc_chan = (struct audio_soc_channel *)data;
253
254 buffer = sndbuf_getbuf(ausoc_chan->buf);
255 if (buffer)
256 free(buffer, M_DEVBUF);
257
258 return (0);
259}
260
261static struct pcmchan_caps *
262audio_soc_chan_getcaps(kobj_t obj, void *data)
263{
264 struct audio_soc_softc *sc;
265 struct audio_soc_channel *ausoc_chan;
266
267 ausoc_chan = data;
268 sc = ausoc_chan->sc;
269
270 return AUDIO_DAI_GET_CAPS(sc->cpu_dev);
271}
272
273static kobj_method_t audio_soc_chan_methods[] = {
274 KOBJMETHOD(channel_init, audio_soc_chan_init),
275 KOBJMETHOD(channel_free, audio_soc_chan_free),
276 KOBJMETHOD(channel_setformat, audio_soc_chan_setformat),
277 KOBJMETHOD(channel_setspeed, audio_soc_chan_setspeed),
278 KOBJMETHOD(channel_setblocksize,audio_soc_chan_setblocksize),
279 KOBJMETHOD(channel_trigger, audio_soc_chan_trigger),
280 KOBJMETHOD(channel_getptr, audio_soc_chan_getptr),
281 KOBJMETHOD(channel_getcaps, audio_soc_chan_getcaps),
283};
284CHANNEL_DECLARE(audio_soc_chan);
285
286static void
288{
289 struct audio_soc_softc *sc;
290 int channel_intr_required;
291
292 sc = (struct audio_soc_softc *)arg;
293 channel_intr_required = AUDIO_DAI_INTR(sc->cpu_dev, sc->play_channel.buf, sc->rec_channel.buf);
294 if (channel_intr_required & AUDIO_DAI_PLAY_INTR)
295 chn_intr(sc->play_channel.pcm);
296 if (channel_intr_required & AUDIO_DAI_REC_INTR)
297 chn_intr(sc->rec_channel.pcm);
298}
299
300static int
302{
303
304 if (!ofw_bus_status_okay(dev))
305 return (ENXIO);
306
307 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
308 device_set_desc(dev, "simple-audio-card");
309 return (BUS_PROBE_DEFAULT);
310 }
311
312 return (ENXIO);
313}
314
315static void
317{
318 struct audio_soc_softc *sc;
319 phandle_t node, child;
320 device_t daidev, auxdev;
321 uint32_t xref;
322 uint32_t *aux_devs;
323 int ncells, i;
324 struct audio_soc_aux_node *aux_node;
325
326 sc = (struct audio_soc_softc *)arg;
327 config_intrhook_disestablish(&sc->init_hook);
328
329 node = ofw_bus_get_node(sc->dev);
330 /* TODO: handle multi-link nodes */
331 child = ofw_bus_find_child(node, "simple-audio-card,cpu");
332 if (child == 0) {
333 device_printf(sc->dev, "cpu node is missing\n");
334 return;
335 }
336 if ((OF_getencprop(child, "sound-dai", &xref, sizeof(xref))) <= 0) {
337 device_printf(sc->dev, "missing sound-dai property in cpu node\n");
338 return;
339 }
340 daidev = OF_device_from_xref(xref);
341 if (daidev == NULL) {
342 device_printf(sc->dev, "no driver attached to cpu node\n");
343 return;
344 }
345 sc->cpu_dev = daidev;
346
347 child = ofw_bus_find_child(node, "simple-audio-card,codec");
348 if (child == 0) {
349 device_printf(sc->dev, "codec node is missing\n");
350 return;
351 }
352 if ((OF_getencprop(child, "sound-dai", &xref, sizeof(xref))) <= 0) {
353 device_printf(sc->dev, "missing sound-dai property in codec node\n");
354 return;
355 }
356 daidev = OF_device_from_xref(xref);
357 if (daidev == NULL) {
358 device_printf(sc->dev, "no driver attached to codec node\n");
359 return;
360 }
361 sc->codec_dev = daidev;
362
363 /* Add AUX devices */
364 aux_devs = NULL;
365 ncells = OF_getencprop_alloc_multi(node, "simple-audio-card,aux-devs", sizeof(*aux_devs),
366 (void **)&aux_devs);
367
368 for (i = 0; i < ncells; i++) {
369 auxdev = OF_device_from_xref(aux_devs[i]);
370 if (auxdev == NULL)
371 device_printf(sc->dev, "warning: no driver attached to aux node\n");
372 aux_node = (struct audio_soc_aux_node *)malloc(sizeof(*aux_node), M_DEVBUF, M_NOWAIT);
373 if (aux_node == NULL) {
374 device_printf(sc->dev, "failed to allocate aux node struct\n");
375 return;
376 }
377 aux_node->dev = auxdev;
378 SLIST_INSERT_HEAD(&sc->aux_devs, aux_node, link);
379 }
380
381 if (aux_devs)
382 OF_prop_free(aux_devs);
383
384 if (AUDIO_DAI_INIT(sc->cpu_dev, sc->format)) {
385 device_printf(sc->dev, "failed to initialize cpu node\n");
386 return;
387 }
388
389 /* Reverse clock roles for CODEC */
390 if (AUDIO_DAI_INIT(sc->codec_dev, audio_soc_reverse_clocks(sc->format))) {
391 device_printf(sc->dev, "failed to initialize codec node\n");
392 return;
393 }
394
395 SLIST_FOREACH(aux_node, &sc->aux_devs, link) {
396 if (AUDIO_DAI_INIT(aux_node->dev, audio_soc_reverse_clocks(sc->format))) {
397 device_printf(sc->dev, "failed to initialize aux node\n");
398 return;
399 }
400 }
401
402 if (pcm_register(sc->dev, sc, 1, 1)) {
403 device_printf(sc->dev, "failed to register PCM\n");
404 return;
405 }
406
407 sc->play_channel.sc = sc;
408 sc->rec_channel.sc = sc;
409
410 pcm_addchan(sc->dev, PCMDIR_PLAY, &audio_soc_chan_class, &sc->play_channel);
411 pcm_addchan(sc->dev, PCMDIR_REC, &audio_soc_chan_class, &sc->rec_channel);
412
413 pcm_setstatus(sc->dev, "at EXPERIMENT");
414
415 AUDIO_DAI_SETUP_INTR(sc->cpu_dev, audio_soc_intr, sc);
416 AUDIO_DAI_SETUP_MIXER(sc->codec_dev, sc->dev);
417 SLIST_FOREACH(aux_node, &sc->aux_devs, link) {
418 AUDIO_DAI_SETUP_MIXER(aux_node->dev, sc->dev);
419 }
420}
421
422static int
424{
425 struct audio_soc_softc *sc;
426 char *name;
427 phandle_t node, cpu_child;
428 uint32_t xref;
429 int i, ret;
430 char tmp[32];
431 unsigned int fmt, pol, clk;
432 bool frame_master, bitclock_master;
433
434 sc = device_get_softc(dev);
435 sc->dev = dev;
436 node = ofw_bus_get_node(dev);
437
438 ret = OF_getprop_alloc(node, "name", (void **)&name);
439 if (ret == -1)
440 name = "SoC audio";
441
442 sc->name = strdup(name, M_DEVBUF);
443 device_set_desc(dev, sc->name);
444
445 if (ret != -1)
446 OF_prop_free(name);
447
448 SLIST_INIT(&sc->aux_devs);
449
450 ret = OF_getprop(node, "simple-audio-card,format", tmp, sizeof(tmp));
451 if (ret == 0) {
452 for (i = 0; i < nitems(ausoc_dai_formats); i++) {
453 if (strcmp(tmp, ausoc_dai_formats[i].name) == 0) {
454 fmt = ausoc_dai_formats[i].fmt;
455 break;
456 }
457 }
458 if (i == nitems(ausoc_dai_formats))
459 return (EINVAL);
460 } else
462
463 if (OF_getencprop(node, "simple-audio-card,mclk-fs",
464 &sc->link_mclk_fs, sizeof(sc->link_mclk_fs)) <= 0)
465 sc->link_mclk_fs = 0;
466
467 /* Unless specified otherwise, CPU node is the master */
468 frame_master = bitclock_master = true;
469
470 cpu_child = ofw_bus_find_child(node, "simple-audio-card,cpu");
471
472 if ((OF_getencprop(node, "simple-audio-card,frame-master", &xref, sizeof(xref))) > 0)
473 frame_master = cpu_child == OF_node_from_xref(xref);
474
475 if ((OF_getencprop(node, "simple-audio-card,bitclock-master", &xref, sizeof(xref))) > 0)
476 bitclock_master = cpu_child == OF_node_from_xref(xref);
477
478 if (frame_master) {
479 clk = bitclock_master ?
481 } else {
482 clk = bitclock_master ?
484 }
485
486 bool bitclock_inversion = OF_hasprop(node, "simple-audio-card,bitclock-inversion");
487 bool frame_inversion = OF_hasprop(node, "simple-audio-card,frame-inversion");
488 if (bitclock_inversion) {
489 pol = frame_inversion ?
491 } else {
492 pol = frame_inversion ?
494 }
495
496 sc->format = AUDIO_DAI_FORMAT(fmt, pol, clk);
497
498 sc->init_hook.ich_func = audio_soc_init;
499 sc->init_hook.ich_arg = sc;
500 if (config_intrhook_establish(&sc->init_hook) != 0)
501 return (ENOMEM);
502
503 return (0);
504}
505
506static int
508{
509 struct audio_soc_softc *sc;
510 struct audio_soc_aux_node *aux;
511
512 sc = device_get_softc(dev);
513 if (sc->name)
514 free(sc->name, M_DEVBUF);
515
516 while ((aux = SLIST_FIRST(&sc->aux_devs)) != NULL) {
517 SLIST_REMOVE_HEAD(&sc->aux_devs, link);
518 free(aux, M_DEVBUF);
519 }
520
521 return (0);
522}
523
524static device_method_t audio_soc_methods[] = {
525 /* device_if methods */
526 DEVMETHOD(device_probe, audio_soc_probe),
527 DEVMETHOD(device_attach, audio_soc_attach),
528 DEVMETHOD(device_detach, audio_soc_detach),
529
530 DEVMETHOD_END,
531};
532
533static driver_t audio_soc_driver = {
534 "pcm",
536 sizeof(struct audio_soc_softc),
537};
538
539DRIVER_MODULE(audio_soc, simplebus, audio_soc_driver, pcm_devclass, NULL, NULL);
540MODULE_VERSION(audio_soc, 1);
u_int32_t data
Definition: ac97_if.m:60
void * devinfo
Definition: ac97_if.m:47
#define AUDIO_DAI_POLARITY_NB_NF
Definition: audio_dai.h:41
#define AUDIO_DAI_FORMAT_LJ
Definition: audio_dai.h:32
#define AUDIO_DAI_FORMAT_POLARITY(format)
Definition: audio_dai.h:68
#define AUDIO_DAI_FORMAT_DSPB
Definition: audio_dai.h:34
#define AUDIO_DAI_CLOCK_CBS_CFM
Definition: audio_dai.h:49
#define AUDIO_DAI_REC_INTR
Definition: audio_dai.h:63
#define AUDIO_DAI_FORMAT_CLOCK(format)
Definition: audio_dai.h:69
#define AUDIO_DAI_CLOCK_IN
Definition: audio_dai.h:53
#define AUDIO_DAI_FORMAT_RJ
Definition: audio_dai.h:31
#define AUDIO_DAI_CLOCK_CBM_CFM
Definition: audio_dai.h:48
#define AUDIO_DAI_FORMAT(fmt, pol, clk)
Definition: audio_dai.h:66
#define AUDIO_DAI_PLAY_INTR
Definition: audio_dai.h:64
#define AUDIO_DAI_CLOCK_CBS_CFS
Definition: audio_dai.h:51
#define AUDIO_DAI_CLOCK_CBM_CFS
Definition: audio_dai.h:50
#define AUDIO_DAI_POLARITY_IB_IF
Definition: audio_dai.h:44
#define AUDIO_DAI_FORMAT_PDM
Definition: audio_dai.h:36
#define AUDIO_DAI_FORMAT_I2S
Definition: audio_dai.h:30
#define AUDIO_DAI_FORMAT_FORMAT(format)
Definition: audio_dai.h:67
#define AUDIO_DAI_FORMAT_DSPA
Definition: audio_dai.h:33
#define AUDIO_DAI_FORMAT_AC97
Definition: audio_dai.h:35
#define AUDIO_DAI_CLOCK_OUT
Definition: audio_dai.h:54
#define AUDIO_DAI_POLARITY_NB_IF
Definition: audio_dai.h:42
#define AUDIO_DAI_POLARITY_IB_NF
Definition: audio_dai.h:43
uint32_t format
Definition: audio_dai_if.m:39
uint32_t speed
Definition: audio_dai_if.m:86
uint32_t rate
Definition: audio_dai_if.m:58
int go
Definition: audio_dai_if.m:64
static struct @1 ausoc_dai_formats[]
static int audio_soc_chan_free(kobj_t obj, void *data)
Definition: audio_soc.c:246
#define AUDIO_BUFFER_SIZE
Definition: audio_soc.c:47
static int audio_soc_probe(device_t dev)
Definition: audio_soc.c:301
static driver_t audio_soc_driver
Definition: audio_soc.c:533
static void * audio_soc_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
Definition: audio_soc.c:207
static void audio_soc_intr(void *arg)
Definition: audio_soc.c:287
static void audio_soc_init(void *arg)
Definition: audio_soc.c:316
static device_method_t audio_soc_methods[]
Definition: audio_soc.c:524
static struct pcmchan_caps * audio_soc_chan_getcaps(kobj_t obj, void *data)
Definition: audio_soc.c:262
static int audio_soc_attach(device_t dev)
Definition: audio_soc.c:423
static int audio_soc_chan_trigger(kobj_t obj, void *data, int go)
Definition: audio_soc.c:229
static int audio_soc_detach(device_t dev)
Definition: audio_soc.c:507
__FBSDID("$FreeBSD$")
const char * name
Definition: audio_soc.c:90
static int audio_soc_chan_setformat(kobj_t obj, void *data, uint32_t format)
Definition: audio_soc.c:144
unsigned int fmt
Definition: audio_soc.c:91
static struct ofw_compat_data compat_data[]
Definition: audio_soc.c:84
static uint32_t audio_soc_chan_setblocksize(kobj_t obj, void *data, uint32_t blocksz)
Definition: audio_soc.c:137
static kobj_method_t audio_soc_chan_methods[]
Definition: audio_soc.c:273
MODULE_VERSION(audio_soc, 1)
static uint32_t audio_soc_chan_setspeed(kobj_t obj, void *data, uint32_t speed)
Definition: audio_soc.c:157
CHANNEL_DECLARE(audio_soc_chan)
DRIVER_MODULE(audio_soc, simplebus, audio_soc_driver, pcm_devclass, NULL, NULL)
static uint32_t audio_soc_reverse_clocks(uint32_t format)
Definition: audio_soc.c:110
static uint32_t audio_soc_chan_getptr(kobj_t obj, void *data)
Definition: audio_soc.c:195
int sndbuf_setup(struct snd_dbuf *b, void *buf, unsigned int size)
Definition: buffer.c:123
void * sndbuf_getbuf(struct snd_dbuf *b)
Definition: buffer.c:421
void chn_intr(struct pcm_channel *c)
Definition: channel.c:660
#define PCMDIR_PLAY
Definition: channel.h:339
SLIST_HEAD(pcm_synclist, pcmchan_syncgroup) snd_pcm_syncgroups
#define PCMDIR_REC
Definition: channel.h:341
struct pcm_channel * c
Definition: channel_if.m:106
METHOD int free
Definition: channel_if.m:110
struct snd_dbuf * b
Definition: channel_if.m:105
u_int8_t * buffer
Definition: feeder_if.m:85
device_t child
Definition: hdac_if.m:33
int dir
Definition: hdac_if.m:45
#define KOBJMETHOD_END
Definition: midi.c:76
unsigned dev
Definition: mixer_if.m:59
int pcm_setstatus(device_t dev, char *str)
Definition: sound.c:766
devclass_t pcm_devclass
Definition: sound.c:49
int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo)
Definition: sound.c:692
int pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
Definition: sound.c:1080
struct snd_dbuf * buf
Definition: audio_soc.c:57
struct pcm_channel * pcm
Definition: audio_soc.c:56
struct audio_soc_softc * sc
Definition: audio_soc.c:55
device_t dev
Definition: audio_soc.c:67
device_t cpu_dev
Definition: audio_soc.c:70
struct snddev_info info
Definition: audio_soc.c:66
device_t codec_dev
Definition: audio_soc.c:71
struct intr_config_hook init_hook
Definition: audio_soc.c:69