diff options
author | Ahmad Fatoum <ahmad@a3f.at> | 2021-01-31 21:18:43 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2021-02-08 10:57:05 +0100 |
commit | 86e9d9354c59f0b360cc5e7c40c779cb9292105a (patch) | |
tree | e29d77f5ece5b63c09e543d42809c0b82aac27ae | |
parent | 01a55d345dbb8d861cda0d430d42c3bbbaff718a (diff) | |
download | barebox-86e9d9354c59f0b360cc5e7c40c779cb9292105a.tar.gz barebox-86e9d9354c59f0b360cc5e7c40c779cb9292105a.tar.xz |
sound: add SDL 2.0 sound driver
SDL 2.0.4 features SDL_QueueAudio, which we could use to just queue
buffers for audio playback. Use it to implement the new sound API for
the sandbox architecture.
Signed-off-by: Ahmad Fatoum <ahmad@a3f.at>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r-- | arch/sandbox/configs/sandbox_defconfig | 1 | ||||
-rw-r--r-- | arch/sandbox/dts/sandbox.dts | 4 | ||||
-rw-r--r-- | arch/sandbox/mach-sandbox/include/mach/linux.h | 5 | ||||
-rw-r--r-- | arch/sandbox/os/sdl.c | 44 | ||||
-rw-r--r-- | drivers/sound/Kconfig | 5 | ||||
-rw-r--r-- | drivers/sound/Makefile | 1 | ||||
-rw-r--r-- | drivers/sound/sdl.c | 87 |
7 files changed, 147 insertions, 0 deletions
diff --git a/arch/sandbox/configs/sandbox_defconfig b/arch/sandbox/configs/sandbox_defconfig index ca24d81aca..66fcfbdbd0 100644 --- a/arch/sandbox/configs/sandbox_defconfig +++ b/arch/sandbox/configs/sandbox_defconfig @@ -107,6 +107,7 @@ CONFIG_MTD=y CONFIG_MTD_M25P80=y CONFIG_VIDEO=y CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_SOUND=y CONFIG_MFD_SYSCON=y CONFIG_STATE_DRV=y CONFIG_UBOOTVAR=y diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts index afe48154c4..ef1fa7b866 100644 --- a/arch/sandbox/dts/sandbox.dts +++ b/arch/sandbox/dts/sandbox.dts @@ -94,4 +94,8 @@ compatible = "barebox,sandbox-watchdog"; barebox,reset-source = <&stickypage 0>; }; + + sound { + compatible = "barebox,sandbox-sound"; + }; }; diff --git a/arch/sandbox/mach-sandbox/include/mach/linux.h b/arch/sandbox/mach-sandbox/include/mach/linux.h index c636a9af9c..6e10fdbe6d 100644 --- a/arch/sandbox/mach-sandbox/include/mach/linux.h +++ b/arch/sandbox/mach-sandbox/include/mach/linux.h @@ -49,6 +49,11 @@ int sdl_video_open(const struct sdl_fb_info *); void sdl_video_pause(void); void sdl_video_close(void); +int sdl_sound_init(unsigned sample_rate); +int sdl_sound_play(const void *data, unsigned nsamples); +void sdl_sound_stop(void); +void sdl_sound_close(void); + struct ft2232_bitbang; struct ft2232_bitbang *barebox_libftdi1_open(int vendor_id, int device_id, const char *serial); diff --git a/arch/sandbox/os/sdl.c b/arch/sandbox/os/sdl.c index 623e24cf0b..13178abfc0 100644 --- a/arch/sandbox/os/sdl.c +++ b/arch/sandbox/os/sdl.c @@ -111,3 +111,47 @@ quit_subsystem: return -1; } + +static SDL_AudioDeviceID dev; + +int sdl_sound_init(unsigned sample_rate) +{ + SDL_AudioSpec audiospec = { + .freq = sample_rate, + .format = AUDIO_S16, + .channels = 1, + .samples = 2048, + }; + + if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { + sdl_perror("initialize SDL Audio"); + return -1; + } + + dev = SDL_OpenAudioDevice(NULL, 0, &audiospec, NULL, 0); + if (!dev) { + sdl_perror("initialize open audio device"); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + return -1; + } + + SDL_PauseAudioDevice(dev, 0); + return 0; +} + +void sdl_sound_close(void) +{ + SDL_QuitSubSystem(SDL_INIT_AUDIO); +} + +int sdl_sound_play(const void *data, unsigned nsamples) +{ + /* core sound support handles all the queueing for us */ + SDL_ClearQueuedAudio(dev); + return SDL_QueueAudio(dev, data, nsamples * sizeof(uint16_t)); +} + +void sdl_sound_stop(void) +{ + SDL_ClearQueuedAudio(dev); +} diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig index d9f63a5f3c..889657305b 100644 --- a/drivers/sound/Kconfig +++ b/drivers/sound/Kconfig @@ -9,6 +9,11 @@ menuconfig SOUND if SOUND +config SOUND_SDL + bool "SDL sound driver for sandbox" + depends on SANDBOX && OFDEVICE + select SDL + config SYNTH_SQUARES bool "Synthesize square waves only" help diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index 69873faab9..692105fd6b 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only obj-y += core.o synth.o +obj-$(CONFIG_SOUND_SDL) += sdl.o diff --git a/drivers/sound/sdl.c b/drivers/sound/sdl.c new file mode 100644 index 0000000000..118d774295 --- /dev/null +++ b/drivers/sound/sdl.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <common.h> +#include <errno.h> +#include <driver.h> +#include <mach/linux.h> +#include <linux/time.h> +#include <linux/math64.h> +#include <of.h> +#include <sound.h> + +#define AMPLITUDE 28000 +#define SAMPLERATE 44000ULL + +struct sandbox_sound { + struct sound_card card; +}; + +static int sandbox_sound_beep(struct sound_card *card, unsigned freq, unsigned duration) +{ + size_t nsamples = div_s64(SAMPLERATE * duration, USEC_PER_SEC); + int16_t *data; + int ret; + + if (!freq) { + sdl_sound_stop(); + return 0; + } + + data = malloc(nsamples * sizeof(*data)); + if (!data) + return -ENOMEM; + + synth_sin(freq, AMPLITUDE, data, SAMPLERATE, nsamples); + ret = sdl_sound_play(data, nsamples); + if (ret) + ret = -EIO; + free(data); + + return ret; +} + +static int sandbox_sound_probe(struct device_d *dev) +{ + struct sandbox_sound *priv; + struct sound_card *card; + int ret; + + priv = xzalloc(sizeof(*priv)); + + card = &priv->card; + card->name = "SDL-Audio"; + card->beep = sandbox_sound_beep; + + ret = sdl_sound_init(SAMPLERATE); + if (ret) { + ret = -ENODEV; + goto free_priv; + } + + ret = sound_card_register(card); + if (ret) + goto sdl_sound_close; + + dev_info(dev, "probed\n"); + return 0; + +sdl_sound_close: + sdl_sound_close(); +free_priv: + free(priv); + + return ret; +} + + +static __maybe_unused struct of_device_id sandbox_sound_dt_ids[] = { + { .compatible = "barebox,sandbox-sound" }, + { /* sentinel */ } +}; + +static struct driver_d sandbox_sound_drv = { + .name = "sandbox-sound", + .of_compatible = sandbox_sound_dt_ids, + .probe = sandbox_sound_probe, +}; +device_platform_driver(sandbox_sound_drv); |