diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2021-02-22 10:39:39 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2021-02-22 10:39:39 +0100 |
commit | 2b1f426e511bf5b41c84d05ec09949ebd5dc216e (patch) | |
tree | fcf06dba00432686c8c0bd5137357d2aabf356f8 /arch/sandbox | |
parent | 774f731a63500deec5d529bb17a75a983f3a4629 (diff) | |
parent | fdb315c4a0764c43916236363a0060972108f5d5 (diff) | |
download | barebox-2b1f426e511bf5b41c84d05ec09949ebd5dc216e.tar.gz barebox-2b1f426e511bf5b41c84d05ec09949ebd5dc216e.tar.xz |
Merge branch 'for-next/sound'
Diffstat (limited to 'arch/sandbox')
-rw-r--r-- | arch/sandbox/Kconfig | 3 | ||||
-rw-r--r-- | arch/sandbox/Makefile | 6 | ||||
-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 | 22 | ||||
-rw-r--r-- | arch/sandbox/os/Makefile | 4 | ||||
-rw-r--r-- | arch/sandbox/os/sdl.c | 184 |
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); } |