[PATCH 4/7] sound: add SDL 2.0 sound driver
Ahmad Fatoum
ahmad at a3f.at
Sun Jan 31 15:18:43 EST 2021
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 at a3f.at>
---
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
More information about the barebox
mailing list