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@xxxxxx> --- arch/sandbox/configs/sandbox_defconfig | 1 + arch/sandbox/dts/sandbox.dts | 4 + .../sandbox/mach-sandbox/include/mach/linux.h | 5 ++ arch/sandbox/os/sdl.c | 44 ++++++++++ drivers/sound/Kconfig | 5 ++ drivers/sound/Makefile | 1 + drivers/sound/sdl.c | 87 +++++++++++++++++++ 7 files changed, 147 insertions(+) create mode 100644 drivers/sound/sdl.c diff --git a/arch/sandbox/configs/sandbox_defconfig b/arch/sandbox/configs/sandbox_defconfig index ca24d81acac7..66fcfbdbd0a3 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 afe48154c488..ef1fa7b8661f 100644 --- a/arch/sandbox/dts/sandbox.dts +++ b/arch/sandbox/dts/sandbox.dts @@ -94,4 +94,8 @@ barebox,sandbox-power 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 c636a9af9cd2..6e10fdbe6d80 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 623e24cf0b26..13178abfc044 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 d9f63a5f3c55..889657305b0b 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 69873faab985..692105fd6b59 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 000000000000..118d7742955f --- /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); -- 2.30.0 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox