29#include "opt_platform.h"
35#include <sys/kernel.h>
37#include <sys/module.h>
38#include <sys/endian.h>
40#include <dev/ofw/ofw_bus.h>
41#include <dev/ofw/ofw_bus_subr.h>
45#include "audio_dai_if.h"
47#define AUDIO_BUFFER_SIZE 48000 * 4
81 uint32_t link_mclk_fs;
85 {
"simple-audio-card", 1},
168 if (sc->link_mclk_fs) {
171 device_printf(sc->
dev,
"failed to set sysclk for CPU node\n");
174 device_printf(sc->
dev,
"failed to set sysclk for codec node\n");
176 SLIST_FOREACH(aux_node, &sc->aux_devs, link) {
178 device_printf(sc->
dev,
"failed to set sysclk for aux node\n");
187 SLIST_FOREACH(aux_node, &sc->aux_devs, link) {
188 AUDIO_DAI_SET_CHANSPEED(aux_node->dev,
speed);
238 SLIST_FOREACH(aux_node, &
sc->aux_devs, link) {
239 AUDIO_DAI_TRIGGER(aux_node->dev,
go, ausoc_chan->
dir);
290 int channel_intr_required;
293 channel_intr_required = AUDIO_DAI_INTR(sc->
cpu_dev, sc->play_channel.buf, sc->rec_channel.buf);
304 if (!ofw_bus_status_okay(
dev))
308 device_set_desc(
dev,
"simple-audio-card");
309 return (BUS_PROBE_DEFAULT);
319 phandle_t node,
child;
320 device_t daidev, auxdev;
327 config_intrhook_disestablish(&sc->
init_hook);
329 node = ofw_bus_get_node(sc->
dev);
331 child = ofw_bus_find_child(node,
"simple-audio-card,cpu");
333 device_printf(sc->
dev,
"cpu node is missing\n");
336 if ((OF_getencprop(
child,
"sound-dai", &xref,
sizeof(xref))) <= 0) {
337 device_printf(sc->
dev,
"missing sound-dai property in cpu node\n");
340 daidev = OF_device_from_xref(xref);
341 if (daidev == NULL) {
342 device_printf(sc->
dev,
"no driver attached to cpu node\n");
347 child = ofw_bus_find_child(node,
"simple-audio-card,codec");
349 device_printf(sc->
dev,
"codec node is missing\n");
352 if ((OF_getencprop(
child,
"sound-dai", &xref,
sizeof(xref))) <= 0) {
353 device_printf(sc->
dev,
"missing sound-dai property in codec node\n");
356 daidev = OF_device_from_xref(xref);
357 if (daidev == NULL) {
358 device_printf(sc->
dev,
"no driver attached to codec node\n");
365 ncells = OF_getencprop_alloc_multi(node,
"simple-audio-card,aux-devs",
sizeof(*aux_devs),
368 for (i = 0; i < ncells; i++) {
369 auxdev = OF_device_from_xref(aux_devs[i]);
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");
377 aux_node->dev = auxdev;
378 SLIST_INSERT_HEAD(&sc->aux_devs, aux_node, link);
382 OF_prop_free(aux_devs);
384 if (AUDIO_DAI_INIT(sc->
cpu_dev, sc->format)) {
385 device_printf(sc->
dev,
"failed to initialize cpu node\n");
391 device_printf(sc->
dev,
"failed to initialize codec node\n");
395 SLIST_FOREACH(aux_node, &sc->aux_devs, link) {
397 device_printf(sc->
dev,
"failed to initialize aux node\n");
403 device_printf(sc->
dev,
"failed to register PCM\n");
407 sc->play_channel.sc = sc;
408 sc->rec_channel.sc = sc;
417 SLIST_FOREACH(aux_node, &sc->aux_devs, link) {
418 AUDIO_DAI_SETUP_MIXER(aux_node->dev, sc->
dev);
427 phandle_t node, cpu_child;
431 unsigned int fmt, pol, clk;
432 bool frame_master, bitclock_master;
434 sc = device_get_softc(
dev);
436 node = ofw_bus_get_node(
dev);
438 ret = OF_getprop_alloc(node,
"name", (
void **)&
name);
443 device_set_desc(
dev, sc->
name);
448 SLIST_INIT(&sc->aux_devs);
450 ret = OF_getprop(node,
"simple-audio-card,format", tmp,
sizeof(tmp));
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;
468 frame_master = bitclock_master =
true;
470 cpu_child = ofw_bus_find_child(node,
"simple-audio-card,cpu");
472 if ((OF_getencprop(node,
"simple-audio-card,frame-master", &xref,
sizeof(xref))) > 0)
473 frame_master = cpu_child == OF_node_from_xref(xref);
475 if ((OF_getencprop(node,
"simple-audio-card,bitclock-master", &xref,
sizeof(xref))) > 0)
476 bitclock_master = cpu_child == OF_node_from_xref(xref);
479 clk = bitclock_master ?
482 clk = bitclock_master ?
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 ?
492 pol = frame_inversion ?
500 if (config_intrhook_establish(&sc->
init_hook) != 0)
512 sc = device_get_softc(
dev);
516 while ((aux = SLIST_FIRST(&sc->aux_devs)) != NULL) {
517 SLIST_REMOVE_HEAD(&sc->aux_devs, link);
#define AUDIO_DAI_POLARITY_NB_NF
#define AUDIO_DAI_FORMAT_LJ
#define AUDIO_DAI_FORMAT_POLARITY(format)
#define AUDIO_DAI_FORMAT_DSPB
#define AUDIO_DAI_CLOCK_CBS_CFM
#define AUDIO_DAI_REC_INTR
#define AUDIO_DAI_FORMAT_CLOCK(format)
#define AUDIO_DAI_CLOCK_IN
#define AUDIO_DAI_FORMAT_RJ
#define AUDIO_DAI_CLOCK_CBM_CFM
#define AUDIO_DAI_FORMAT(fmt, pol, clk)
#define AUDIO_DAI_PLAY_INTR
#define AUDIO_DAI_CLOCK_CBS_CFS
#define AUDIO_DAI_CLOCK_CBM_CFS
#define AUDIO_DAI_POLARITY_IB_IF
#define AUDIO_DAI_FORMAT_PDM
#define AUDIO_DAI_FORMAT_I2S
#define AUDIO_DAI_FORMAT_FORMAT(format)
#define AUDIO_DAI_FORMAT_DSPA
#define AUDIO_DAI_FORMAT_AC97
#define AUDIO_DAI_CLOCK_OUT
#define AUDIO_DAI_POLARITY_NB_IF
#define AUDIO_DAI_POLARITY_IB_NF
static struct @1 ausoc_dai_formats[]
static int audio_soc_chan_free(kobj_t obj, void *data)
#define AUDIO_BUFFER_SIZE
static int audio_soc_probe(device_t dev)
static driver_t audio_soc_driver
static void * audio_soc_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
static void audio_soc_intr(void *arg)
static void audio_soc_init(void *arg)
static device_method_t audio_soc_methods[]
static struct pcmchan_caps * audio_soc_chan_getcaps(kobj_t obj, void *data)
static int audio_soc_attach(device_t dev)
static int audio_soc_chan_trigger(kobj_t obj, void *data, int go)
static int audio_soc_detach(device_t dev)
static int audio_soc_chan_setformat(kobj_t obj, void *data, uint32_t format)
static struct ofw_compat_data compat_data[]
static uint32_t audio_soc_chan_setblocksize(kobj_t obj, void *data, uint32_t blocksz)
static kobj_method_t audio_soc_chan_methods[]
MODULE_VERSION(audio_soc, 1)
static uint32_t audio_soc_chan_setspeed(kobj_t obj, void *data, uint32_t speed)
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)
static uint32_t audio_soc_chan_getptr(kobj_t obj, void *data)
int sndbuf_setup(struct snd_dbuf *b, void *buf, unsigned int size)
void * sndbuf_getbuf(struct snd_dbuf *b)
void chn_intr(struct pcm_channel *c)
SLIST_HEAD(pcm_synclist, pcmchan_syncgroup) snd_pcm_syncgroups
int pcm_setstatus(device_t dev, char *str)
int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo)
int pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
struct audio_soc_softc * sc
struct intr_config_hook init_hook