summaryrefslogtreecommitdiffstats
path: root/arch/sandbox
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2021-02-22 10:39:39 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2021-02-22 10:39:39 +0100
commit2b1f426e511bf5b41c84d05ec09949ebd5dc216e (patch)
treefcf06dba00432686c8c0bd5137357d2aabf356f8 /arch/sandbox
parent774f731a63500deec5d529bb17a75a983f3a4629 (diff)
parentfdb315c4a0764c43916236363a0060972108f5d5 (diff)
downloadbarebox-2b1f426e511bf5b41c84d05ec09949ebd5dc216e.tar.gz
barebox-2b1f426e511bf5b41c84d05ec09949ebd5dc216e.tar.xz
Merge branch 'for-next/sound'
Diffstat (limited to 'arch/sandbox')
-rw-r--r--arch/sandbox/Kconfig3
-rw-r--r--arch/sandbox/Makefile6
-rw-r--r--arch/sandbox/configs/sandbox_defconfig1
-rw-r--r--arch/sandbox/dts/sandbox.dts4
-rw-r--r--arch/sandbox/mach-sandbox/include/mach/linux.h22
-rw-r--r--arch/sandbox/os/Makefile4
-rw-r--r--arch/sandbox/os/sdl.c184
7 files changed, 147 insertions, 77 deletions
diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 5d1702480f..1a4e3bacf6 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -44,3 +44,6 @@ config 64BIT
config SANDBOX_LINUX_I386
bool "32-bit x86 barebox" if CC_HAS_LINUX_I386_SUPPORT
+
+config SDL
+ bool
diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile
index 17f9a298d7..ea594944e4 100644
--- a/arch/sandbox/Makefile
+++ b/arch/sandbox/Makefile
@@ -37,8 +37,8 @@ archprepare: maketools
PHONY += maketools
-ifeq ($(CONFIG_DRIVER_VIDEO_SDL),y)
-SDL_LIBS := $(shell pkg-config sdl --libs)
+ifeq ($(CONFIG_SDL),y)
+SDL_LIBS := $(shell pkg-config sdl2 --libs)
endif
ifeq ($(CONFIG_GPIO_LIBFTDI1),y)
@@ -64,7 +64,7 @@ endif
BAREBOX_LDFLAGS += \
-Wl,-T,$(BAREBOX_LDS) \
-Wl,--whole-archive $(BAREBOX_OBJS) -Wl,--no-whole-archive \
- -lrt -lpthread $(SDL_LIBS) $(FTDI1_LIBS) \
+ -lrt $(SDL_LIBS) $(FTDI1_LIBS) \
$(SANITIZER_LIBS)
cmd_barebox__ = $(CC) -o $@ $(BAREBOX_LDFLAGS)
diff --git a/arch/sandbox/configs/sandbox_defconfig b/arch/sandbox/configs/sandbox_defconfig
index dcd0557326..d9d96d9481 100644
--- a/arch/sandbox/configs/sandbox_defconfig
+++ b/arch/sandbox/configs/sandbox_defconfig
@@ -108,6 +108,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 f047c83e17..831e170d90 100644
--- a/arch/sandbox/mach-sandbox/include/mach/linux.h
+++ b/arch/sandbox/mach-sandbox/include/mach/linux.h
@@ -38,13 +38,21 @@ struct linux_console_data {
extern int sdl_xres;
extern int sdl_yres;
-void sdl_close(void);
-int sdl_open(int xres, int yres, int bpp, void* buf);
-void sdl_stop_timer(void);
-void sdl_start_timer(void);
-void sdl_get_bitfield_rgba(struct fb_bitfield *r, struct fb_bitfield *g,
- struct fb_bitfield *b, struct fb_bitfield *a);
-void sdl_setpixel(int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
+struct sdl_fb_info {
+ void *screen_base;
+ int xres;
+ int yres;
+ int bpp;
+ int rmask, gmask, bmask, amask;
+};
+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,
diff --git a/arch/sandbox/os/Makefile b/arch/sandbox/os/Makefile
index 9a264ca314..fb2c3cfd86 100644
--- a/arch/sandbox/os/Makefile
+++ b/arch/sandbox/os/Makefile
@@ -17,8 +17,8 @@ endif
obj-y = common.o tap.o
obj-$(CONFIG_MALLOC_LIBC) += libc_malloc.o
-CFLAGS_sdl.o = $(shell pkg-config sdl --cflags)
-obj-$(CONFIG_DRIVER_VIDEO_SDL) += sdl.o
+CFLAGS_sdl.o = $(shell pkg-config sdl2 --cflags)
+obj-$(CONFIG_SDL) += sdl.o
CFLAGS_ftdi.o = $(shell pkg-config libftdi1 --cflags)
obj-$(CONFIG_GPIO_LIBFTDI1) += ftdi.o
diff --git a/arch/sandbox/os/sdl.c b/arch/sandbox/os/sdl.c
index 9a35279eb7..13178abfc0 100644
--- a/arch/sandbox/os/sdl.c
+++ b/arch/sandbox/os/sdl.c
@@ -1,103 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
- *
- * GPL v2
+ * Copyright (c) 2021 Ahmad Fatoum
*/
#include <stdio.h>
+#include <stdbool.h>
#include <SDL.h>
-#include <time.h>
-#include <signal.h>
#include <mach/linux.h>
-#include <unistd.h>
-#include <pthread.h>
-struct fb_bitfield {
- uint32_t offset; /* beginning of bitfield */
- uint32_t length; /* length of bitfield */
- uint32_t msb_right; /* != 0 : Most significant bit is */
- /* right */
-};
+static void sdl_perror(const char *what)
+{
+ printf("SDL: Could not %s: %s.\n", what, SDL_GetError());
+}
-static SDL_Surface *real_screen;
-static void *buffer = NULL;
-pthread_t th;
+static struct sdl_fb_info info;
+static SDL_atomic_t shutdown;
+SDL_Window *window;
-static void sdl_copy_buffer(SDL_Surface *screen)
+static int scanout(void *ptr)
{
- if (SDL_MUSTLOCK(screen)) {
- if (SDL_LockSurface(screen) < 0)
- return;
+ SDL_Renderer *renderer;
+ SDL_Surface *surface;
+ SDL_Texture *texture;
+ void *buf = info.screen_base;
+ int ret = -1;
+
+ renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
+ if (!renderer) {
+ sdl_perror("create renderer");
+ return -1;
}
- memcpy(screen->pixels, buffer, screen->pitch * screen->h);
+ surface = SDL_CreateRGBSurface(0, info.xres, info.yres, info.bpp,
+ info.rmask, info.gmask, info.bmask, info.amask);
+ if (!surface) {
+ sdl_perror("create surface");
+ goto destroy_renderer;
+ }
- if(SDL_MUSTLOCK(screen))
- SDL_UnlockSurface(screen);
-}
+ texture = SDL_CreateTextureFromSurface(renderer, surface);
+ if (!texture) {
+ sdl_perror("create texture");
+ goto free_surface;
+ }
-static void *threadStart(void *ptr)
-{
- while (1) {
- usleep(1000 * 100);
+ while (!SDL_AtomicGet(&shutdown)) {
+ SDL_Delay(100);
- sdl_copy_buffer(real_screen);
- SDL_Flip(real_screen);
+ SDL_UpdateTexture(texture, NULL, buf, surface->pitch);
+ SDL_RenderClear(renderer);
+ SDL_RenderCopy(renderer, texture, NULL, NULL);
+ SDL_RenderPresent(renderer);
}
- return 0;
-}
+ ret = 0;
-void sdl_start_timer(void)
-{
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_create(&th, &attr, threadStart, NULL);
-}
+ SDL_DestroyTexture(texture);
+free_surface:
+ SDL_FreeSurface(surface);
+destroy_renderer:
+ SDL_DestroyRenderer(renderer);
-void sdl_stop_timer(void)
-{
- pthread_cancel(th);
+ return ret;
}
-void sdl_get_bitfield_rgba(struct fb_bitfield *r, struct fb_bitfield *g,
- struct fb_bitfield *b, struct fb_bitfield *a)
+static SDL_Thread *thread;
+
+void sdl_video_close(void)
{
- SDL_Surface *screen = real_screen;
-
- r->length = 8 - screen->format->Rloss;
- r->offset = screen->format->Rshift;
- g->length = 8 - screen->format->Gloss;
- g->offset = screen->format->Gshift;
- b->length = 8 - screen->format->Bloss;
- b->offset = screen->format->Bshift;
- a->length = 8 - screen->format->Aloss;
- a->offset = screen->format->Ashift;
+ SDL_AtomicSet(&shutdown, true); /* implies full memory barrier */
+ SDL_WaitThread(thread, NULL);
+ SDL_AtomicSet(&shutdown, false);
+ SDL_DestroyWindow(window);
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
-int sdl_open(int xres, int yres, int bpp, void* buf)
+int sdl_video_open(const struct sdl_fb_info *_info)
{
- int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
+ info = *_info;
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
- printf("Could not initialize SDL: %s.\n", SDL_GetError());
+ if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
+ sdl_perror("initialize SDL Video");
return -1;
}
- real_screen = SDL_SetVideoMode(xres, yres, bpp, flags);
- if (!real_screen) {
- sdl_close();
- fprintf(stderr, "Couldn't create renderer: %s\n", SDL_GetError());
+ window = SDL_CreateWindow("barebox", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+ info.xres, info.yres, 0);
+ if (!window) {
+ sdl_perror("create window");
+ goto quit_subsystem;
+ }
+
+ /* All scanout needs to happen in the same thread, because not all
+ * graphic backends are thread-safe. The window is created in the main
+ * thread though to work around libEGL crashing with SDL_VIDEODRIVER=wayland
+ */
+
+ thread = SDL_CreateThread(scanout, "video-scanout", NULL);
+ if (!thread) {
+ sdl_perror("start scanout thread");
+ goto destroy_window;
+ }
+
+ return 0;
+
+destroy_window:
+ SDL_DestroyWindow(window);
+quit_subsystem:
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+
+ 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;
}
- buffer = buf;
+ 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_close(void)
+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_stop_timer();
- SDL_Quit();
+ SDL_ClearQueuedAudio(dev);
}