xref: /openbmc/u-boot/arch/sandbox/cpu/sdl.c (revision aac0c29d4b8418c5c78b552070ffeda022b16949)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2bbc09bf2SSimon Glass /*
3bbc09bf2SSimon Glass  * Copyright (c) 2013 Google, Inc
4bbc09bf2SSimon Glass  */
5bbc09bf2SSimon Glass 
6bbc09bf2SSimon Glass #include <errno.h>
7282e29ebSSimon Glass #include <unistd.h>
8bbc09bf2SSimon Glass #include <linux/input.h>
9*398ae026SSimon Glass #include <SDL.h>
10bbc09bf2SSimon Glass #include <asm/state.h>
11bbc09bf2SSimon Glass 
12e625b68bSSimon Glass /**
13e625b68bSSimon Glass  * struct buf_info - a data buffer holding audio data
14e625b68bSSimon Glass  *
15e625b68bSSimon Glass  * @pos:	Current position playing in audio buffer
16e625b68bSSimon Glass  * @size:	Size of data in audio buffer (0=empty)
17e625b68bSSimon Glass  * @alloced:	Allocated size of audio buffer (max size it can hold)
18e625b68bSSimon Glass  * @data:	Audio data
19e625b68bSSimon Glass  */
20e625b68bSSimon Glass struct buf_info {
21e625b68bSSimon Glass 	uint pos;
22e625b68bSSimon Glass 	uint size;
23e625b68bSSimon Glass 	uint alloced;
24e625b68bSSimon Glass 	uint8_t *data;
25e625b68bSSimon Glass };
26e625b68bSSimon Glass 
27bbc09bf2SSimon Glass static struct sdl_info {
28bbc09bf2SSimon Glass 	SDL_Surface *screen;
29bbc09bf2SSimon Glass 	int width;
30bbc09bf2SSimon Glass 	int height;
31bbc09bf2SSimon Glass 	int depth;
32bbc09bf2SSimon Glass 	int pitch;
33bbc09bf2SSimon Glass 	uint frequency;
34856b8f56SSimon Glass 	uint sample_rate;
35bbc09bf2SSimon Glass 	bool audio_active;
36bbc09bf2SSimon Glass 	bool inited;
37e625b68bSSimon Glass 	int cur_buf;
38e625b68bSSimon Glass 	struct buf_info buf[2];
39282e29ebSSimon Glass 	bool running;
40bbc09bf2SSimon Glass } sdl;
41bbc09bf2SSimon Glass 
sandbox_sdl_poll_events(void)42bbc09bf2SSimon Glass static void sandbox_sdl_poll_events(void)
43bbc09bf2SSimon Glass {
44bbc09bf2SSimon Glass 	/*
45bbc09bf2SSimon Glass 	 * We don't want to include common.h in this file since it uses
46bbc09bf2SSimon Glass 	 * system headers. So add a declation here.
47bbc09bf2SSimon Glass 	 */
48bbc09bf2SSimon Glass 	extern void reset_cpu(unsigned long addr);
49bbc09bf2SSimon Glass 	SDL_Event event;
50bbc09bf2SSimon Glass 
51bbc09bf2SSimon Glass 	while (SDL_PollEvent(&event)) {
52bbc09bf2SSimon Glass 		switch (event.type) {
53bbc09bf2SSimon Glass 		case SDL_QUIT:
54bbc09bf2SSimon Glass 			puts("LCD window closed - quitting\n");
55bbc09bf2SSimon Glass 			reset_cpu(1);
56bbc09bf2SSimon Glass 			break;
57bbc09bf2SSimon Glass 		}
58bbc09bf2SSimon Glass 	}
59bbc09bf2SSimon Glass }
60bbc09bf2SSimon Glass 
sandbox_sdl_ensure_init(void)61bbc09bf2SSimon Glass static int sandbox_sdl_ensure_init(void)
62bbc09bf2SSimon Glass {
63bbc09bf2SSimon Glass 	if (!sdl.inited) {
64bbc09bf2SSimon Glass 		if (SDL_Init(0) < 0) {
65bbc09bf2SSimon Glass 			printf("Unable to initialize SDL: %s\n",
66bbc09bf2SSimon Glass 			       SDL_GetError());
67bbc09bf2SSimon Glass 			return -EIO;
68bbc09bf2SSimon Glass 		}
69bbc09bf2SSimon Glass 
70bbc09bf2SSimon Glass 		atexit(SDL_Quit);
71bbc09bf2SSimon Glass 
72bbc09bf2SSimon Glass 		sdl.inited = true;
73bbc09bf2SSimon Glass 	}
74bbc09bf2SSimon Glass 	return 0;
75bbc09bf2SSimon Glass }
76bbc09bf2SSimon Glass 
sandbox_sdl_init_display(int width,int height,int log2_bpp)77bbc09bf2SSimon Glass int sandbox_sdl_init_display(int width, int height, int log2_bpp)
78bbc09bf2SSimon Glass {
79bbc09bf2SSimon Glass 	struct sandbox_state *state = state_get_current();
80bbc09bf2SSimon Glass 	int err;
81bbc09bf2SSimon Glass 
82bbc09bf2SSimon Glass 	if (!width || !state->show_lcd)
83bbc09bf2SSimon Glass 		return 0;
84bbc09bf2SSimon Glass 	err = sandbox_sdl_ensure_init();
85bbc09bf2SSimon Glass 	if (err)
86bbc09bf2SSimon Glass 		return err;
87bbc09bf2SSimon Glass 	if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
88bbc09bf2SSimon Glass 		printf("Unable to initialize SDL LCD: %s\n", SDL_GetError());
89bbc09bf2SSimon Glass 		return -EPERM;
90bbc09bf2SSimon Glass 	}
91bbc09bf2SSimon Glass 	SDL_WM_SetCaption("U-Boot", "U-Boot");
92bbc09bf2SSimon Glass 
93bbc09bf2SSimon Glass 	sdl.width = width;
94bbc09bf2SSimon Glass 	sdl.height = height;
95bbc09bf2SSimon Glass 	sdl.depth = 1 << log2_bpp;
96bbc09bf2SSimon Glass 	sdl.pitch = sdl.width * sdl.depth / 8;
97bbc09bf2SSimon Glass 	sdl.screen = SDL_SetVideoMode(width, height, 0, 0);
98bbc09bf2SSimon Glass 	sandbox_sdl_poll_events();
99bbc09bf2SSimon Glass 
100bbc09bf2SSimon Glass 	return 0;
101bbc09bf2SSimon Glass }
102bbc09bf2SSimon Glass 
sandbox_sdl_sync(void * lcd_base)103bbc09bf2SSimon Glass int sandbox_sdl_sync(void *lcd_base)
104bbc09bf2SSimon Glass {
105bbc09bf2SSimon Glass 	SDL_Surface *frame;
106bbc09bf2SSimon Glass 
107bbc09bf2SSimon Glass 	frame = SDL_CreateRGBSurfaceFrom(lcd_base, sdl.width, sdl.height,
108bbc09bf2SSimon Glass 			sdl.depth, sdl.pitch,
109bbc09bf2SSimon Glass 			0x1f << 11, 0x3f << 5, 0x1f << 0, 0);
110bbc09bf2SSimon Glass 	SDL_BlitSurface(frame, NULL, sdl.screen, NULL);
111bbc09bf2SSimon Glass 	SDL_FreeSurface(frame);
112bbc09bf2SSimon Glass 	SDL_UpdateRect(sdl.screen, 0, 0, 0, 0);
113bbc09bf2SSimon Glass 	sandbox_sdl_poll_events();
114bbc09bf2SSimon Glass 
115bbc09bf2SSimon Glass 	return 0;
116bbc09bf2SSimon Glass }
117bbc09bf2SSimon Glass 
118bbc09bf2SSimon Glass #define NONE (-1)
119bbc09bf2SSimon Glass #define NUM_SDL_CODES	(SDLK_UNDO + 1)
120bbc09bf2SSimon Glass 
121bbc09bf2SSimon Glass static int16_t sdl_to_keycode[NUM_SDL_CODES] = {
122bbc09bf2SSimon Glass 	/* 0 */
123bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
124bbc09bf2SSimon Glass 	NONE, NONE, NONE, KEY_BACKSPACE, KEY_TAB,
125bbc09bf2SSimon Glass 	NONE, NONE, NONE, KEY_ENTER, NONE,
126bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, KEY_POWER,	/* use PAUSE as POWER */
127bbc09bf2SSimon Glass 
128bbc09bf2SSimon Glass 	/* 20 */
129bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
130bbc09bf2SSimon Glass 	NONE, NONE, KEY_ESC, NONE, NONE,
131bbc09bf2SSimon Glass 	NONE, NONE, KEY_SPACE, NONE, NONE,
132bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
133bbc09bf2SSimon Glass 
134bbc09bf2SSimon Glass 	/* 40 */
135bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, KEY_COMMA,
136bbc09bf2SSimon Glass 	KEY_MINUS, KEY_DOT, KEY_SLASH, KEY_0, KEY_1,
137bbc09bf2SSimon Glass 	KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,
138bbc09bf2SSimon Glass 	KEY_7, KEY_8, KEY_9, NONE, KEY_SEMICOLON,
139bbc09bf2SSimon Glass 
140bbc09bf2SSimon Glass 	/* 60 */
141bbc09bf2SSimon Glass 	NONE, KEY_EQUAL, NONE, NONE, NONE,
142bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
143bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
144bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
145bbc09bf2SSimon Glass 
146bbc09bf2SSimon Glass 	/* 80 */
147bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
148bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
149bbc09bf2SSimon Glass 	NONE, NONE, KEY_BACKSLASH, NONE, NONE,
150bbc09bf2SSimon Glass 	NONE, KEY_GRAVE, KEY_A, KEY_B, KEY_C,
151bbc09bf2SSimon Glass 
152bbc09bf2SSimon Glass 	/* 100 */
153bbc09bf2SSimon Glass 	KEY_D, KEY_E, KEY_F, KEY_G, KEY_H,
154bbc09bf2SSimon Glass 	KEY_I, KEY_J, KEY_K, KEY_L, KEY_M,
155bbc09bf2SSimon Glass 	KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R,
156bbc09bf2SSimon Glass 	KEY_S, KEY_T, KEY_U, KEY_V, KEY_W,
157bbc09bf2SSimon Glass 
158bbc09bf2SSimon Glass 	/* 120 */
159bbc09bf2SSimon Glass 	KEY_X, KEY_Y, KEY_Z, NONE, NONE,
160bbc09bf2SSimon Glass 	NONE, NONE, KEY_DELETE, NONE, NONE,
161bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
162bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
163bbc09bf2SSimon Glass 
164bbc09bf2SSimon Glass 	/* 140 */
165bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
166bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
167bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
168bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
169bbc09bf2SSimon Glass 
170bbc09bf2SSimon Glass 	/* 160 */
171bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
172bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
173bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
174bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
175bbc09bf2SSimon Glass 
176bbc09bf2SSimon Glass 	/* 180 */
177bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
178bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
179bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
180bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
181bbc09bf2SSimon Glass 
182bbc09bf2SSimon Glass 	/* 200 */
183bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
184bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
185bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
186bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
187bbc09bf2SSimon Glass 
188bbc09bf2SSimon Glass 	/* 220 */
189bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
190bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
191bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
192bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
193bbc09bf2SSimon Glass 
194bbc09bf2SSimon Glass 	/* 240 */
195bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
196bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
197bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
198bbc09bf2SSimon Glass 	NONE, KEY_KP0, KEY_KP1, KEY_KP2, KEY_KP3,
199bbc09bf2SSimon Glass 
200bbc09bf2SSimon Glass 	/* 260 */
201bbc09bf2SSimon Glass 	KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8,
202bbc09bf2SSimon Glass 	KEY_KP9, KEY_KPDOT, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS,
203bbc09bf2SSimon Glass 	KEY_KPPLUS, KEY_KPENTER, KEY_KPEQUAL, KEY_UP, KEY_DOWN,
204bbc09bf2SSimon Glass 	KEY_RIGHT, KEY_LEFT, KEY_INSERT, KEY_HOME, KEY_END,
205bbc09bf2SSimon Glass 
206bbc09bf2SSimon Glass 	/* 280 */
207bbc09bf2SSimon Glass 	KEY_PAGEUP, KEY_PAGEDOWN, KEY_F1, KEY_F2, KEY_F3,
208bbc09bf2SSimon Glass 	KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8,
209bbc09bf2SSimon Glass 	KEY_F9, KEY_F10, KEY_F11, KEY_F12, NONE,
210bbc09bf2SSimon Glass 	NONE, NONE, NONE, NONE, NONE,
211bbc09bf2SSimon Glass 
212bbc09bf2SSimon Glass 	/* 300 */
213bbc09bf2SSimon Glass 	KEY_NUMLOCK, KEY_CAPSLOCK, KEY_SCROLLLOCK, KEY_RIGHTSHIFT,
214bbc09bf2SSimon Glass 		KEY_LEFTSHIFT,
215bbc09bf2SSimon Glass 	KEY_RIGHTCTRL, KEY_LEFTCTRL, KEY_RIGHTALT, KEY_LEFTALT, KEY_RIGHTMETA,
216bbc09bf2SSimon Glass 	KEY_LEFTMETA, NONE, KEY_FN, NONE, KEY_COMPOSE,
217bbc09bf2SSimon Glass 	NONE, KEY_PRINT, KEY_SYSRQ, KEY_PAUSE, NONE,
218bbc09bf2SSimon Glass 
219bbc09bf2SSimon Glass 	/* 320 */
220bbc09bf2SSimon Glass 	NONE, NONE, NONE,
221bbc09bf2SSimon Glass };
222bbc09bf2SSimon Glass 
sandbox_sdl_scan_keys(int key[],int max_keys)223bbc09bf2SSimon Glass int sandbox_sdl_scan_keys(int key[], int max_keys)
224bbc09bf2SSimon Glass {
225bbc09bf2SSimon Glass 	Uint8 *keystate;
226bbc09bf2SSimon Glass 	int i, count;
227bbc09bf2SSimon Glass 
228bbc09bf2SSimon Glass 	sandbox_sdl_poll_events();
229bbc09bf2SSimon Glass 	keystate = SDL_GetKeyState(NULL);
230bbc09bf2SSimon Glass 	for (i = count = 0; i < NUM_SDL_CODES; i++) {
231bbc09bf2SSimon Glass 		if (count >= max_keys)
232bbc09bf2SSimon Glass 			break;
233bbc09bf2SSimon Glass 		else if (keystate[i])
234bbc09bf2SSimon Glass 			key[count++] = sdl_to_keycode[i];
235bbc09bf2SSimon Glass 	}
236bbc09bf2SSimon Glass 
237bbc09bf2SSimon Glass 	return count;
238bbc09bf2SSimon Glass }
239bbc09bf2SSimon Glass 
sandbox_sdl_key_pressed(int keycode)240bbc09bf2SSimon Glass int sandbox_sdl_key_pressed(int keycode)
241bbc09bf2SSimon Glass {
242bbc09bf2SSimon Glass 	int key[8];	/* allow up to 8 keys to be pressed at once */
243bbc09bf2SSimon Glass 	int count;
244bbc09bf2SSimon Glass 	int i;
245bbc09bf2SSimon Glass 
246bbc09bf2SSimon Glass 	count = sandbox_sdl_scan_keys(key, sizeof(key) / sizeof(key[0]));
247bbc09bf2SSimon Glass 	for (i = 0; i < count; i++) {
248bbc09bf2SSimon Glass 		if (key[i] == keycode)
249bbc09bf2SSimon Glass 			return 0;
250bbc09bf2SSimon Glass 	}
251bbc09bf2SSimon Glass 
252bbc09bf2SSimon Glass 	return -ENOENT;
253bbc09bf2SSimon Glass }
254bbc09bf2SSimon Glass 
sandbox_sdl_fill_audio(void * udata,Uint8 * stream,int len)255bbc09bf2SSimon Glass void sandbox_sdl_fill_audio(void *udata, Uint8 *stream, int len)
256bbc09bf2SSimon Glass {
257e625b68bSSimon Glass 	struct buf_info *buf;
258bbc09bf2SSimon Glass 	int avail;
259e625b68bSSimon Glass 	int i;
260bbc09bf2SSimon Glass 
261e625b68bSSimon Glass 	for (i = 0; i < 2; i++) {
262e625b68bSSimon Glass 		buf = &sdl.buf[sdl.cur_buf];
263e625b68bSSimon Glass 		avail = buf->size - buf->pos;
264e625b68bSSimon Glass 		if (avail <= 0) {
265e625b68bSSimon Glass 			sdl.cur_buf = 1 - sdl.cur_buf;
266e625b68bSSimon Glass 			continue;
267e625b68bSSimon Glass 		}
268e625b68bSSimon Glass 		if (avail > len)
269e625b68bSSimon Glass 			avail = len;
270bbc09bf2SSimon Glass 
271e625b68bSSimon Glass 		SDL_MixAudio(stream, buf->data + buf->pos, avail,
272bbc09bf2SSimon Glass 			     SDL_MIX_MAXVOLUME);
273e625b68bSSimon Glass 		buf->pos += avail;
274e625b68bSSimon Glass 		len -= avail;
275bbc09bf2SSimon Glass 
276e625b68bSSimon Glass 		/* Move to next buffer if we are at the end */
277e625b68bSSimon Glass 		if (buf->pos == buf->size)
278e625b68bSSimon Glass 			buf->size = 0;
279e625b68bSSimon Glass 		else
280e625b68bSSimon Glass 			break;
281e625b68bSSimon Glass 	}
282bbc09bf2SSimon Glass }
283bbc09bf2SSimon Glass 
sandbox_sdl_sound_init(int rate,int channels)284e221cdcfSSimon Glass int sandbox_sdl_sound_init(int rate, int channels)
285bbc09bf2SSimon Glass {
286bbc09bf2SSimon Glass 	SDL_AudioSpec wanted;
287e625b68bSSimon Glass 	int i;
288bbc09bf2SSimon Glass 
289bbc09bf2SSimon Glass 	if (sandbox_sdl_ensure_init())
290bbc09bf2SSimon Glass 		return -1;
291bbc09bf2SSimon Glass 
292bbc09bf2SSimon Glass 	if (sdl.audio_active)
293bbc09bf2SSimon Glass 		return 0;
294bbc09bf2SSimon Glass 
295bbc09bf2SSimon Glass 	/* Set the audio format */
296e221cdcfSSimon Glass 	wanted.freq = rate;
297bbc09bf2SSimon Glass 	wanted.format = AUDIO_S16;
298e221cdcfSSimon Glass 	wanted.channels = channels;
299bbc09bf2SSimon Glass 	wanted.samples = 1024;  /* Good low-latency value for callback */
300bbc09bf2SSimon Glass 	wanted.callback = sandbox_sdl_fill_audio;
301bbc09bf2SSimon Glass 	wanted.userdata = NULL;
302bbc09bf2SSimon Glass 
303e625b68bSSimon Glass 	for (i = 0; i < 2; i++) {
304e625b68bSSimon Glass 		struct buf_info *buf = &sdl.buf[i];
305e625b68bSSimon Glass 
306e625b68bSSimon Glass 		buf->alloced = sizeof(uint16_t) * wanted.freq * wanted.channels;
307e625b68bSSimon Glass 		buf->data = malloc(buf->alloced);
308e625b68bSSimon Glass 		if (!buf->data) {
309bbc09bf2SSimon Glass 			printf("%s: Out of memory\n", __func__);
310e625b68bSSimon Glass 			if (i == 1)
311e625b68bSSimon Glass 				free(sdl.buf[0].data);
312bbc09bf2SSimon Glass 			return -1;
313bbc09bf2SSimon Glass 		}
314e625b68bSSimon Glass 		buf->pos = 0;
315e625b68bSSimon Glass 		buf->size = 0;
316e625b68bSSimon Glass 	}
317bbc09bf2SSimon Glass 
318bbc09bf2SSimon Glass 	if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
319bbc09bf2SSimon Glass 		printf("Unable to initialize SDL audio: %s\n", SDL_GetError());
320bbc09bf2SSimon Glass 		goto err;
321bbc09bf2SSimon Glass 	}
322bbc09bf2SSimon Glass 
323bbc09bf2SSimon Glass 	/* Open the audio device, forcing the desired format */
324bbc09bf2SSimon Glass 	if (SDL_OpenAudio(&wanted, NULL) < 0) {
325bbc09bf2SSimon Glass 		printf("Couldn't open audio: %s\n", SDL_GetError());
326bbc09bf2SSimon Glass 		goto err;
327bbc09bf2SSimon Glass 	}
328bbc09bf2SSimon Glass 	sdl.audio_active = true;
329856b8f56SSimon Glass 	sdl.sample_rate = wanted.freq;
330e625b68bSSimon Glass 	sdl.cur_buf = 0;
331282e29ebSSimon Glass 	sdl.running = 0;
332bbc09bf2SSimon Glass 
333bbc09bf2SSimon Glass 	return 0;
334bbc09bf2SSimon Glass 
335bbc09bf2SSimon Glass err:
336e625b68bSSimon Glass 	for (i = 0; i < 2; i++)
337e625b68bSSimon Glass 		free(sdl.buf[i].data);
338bbc09bf2SSimon Glass 	return -1;
339bbc09bf2SSimon Glass }
340bbc09bf2SSimon Glass 
sandbox_sdl_sound_play(const void * data,uint size)341282e29ebSSimon Glass int sandbox_sdl_sound_play(const void *data, uint size)
342bbc09bf2SSimon Glass {
343282e29ebSSimon Glass 	struct buf_info *buf;
344e625b68bSSimon Glass 
345bbc09bf2SSimon Glass 	if (!sdl.audio_active)
346282e29ebSSimon Glass 		return 0;
347282e29ebSSimon Glass 
348282e29ebSSimon Glass 	buf = &sdl.buf[0];
349282e29ebSSimon Glass 	if (buf->size)
350282e29ebSSimon Glass 		buf = &sdl.buf[1];
351282e29ebSSimon Glass 	while (buf->size)
352282e29ebSSimon Glass 		usleep(1000);
353282e29ebSSimon Glass 
354282e29ebSSimon Glass 	if (size > buf->alloced)
355282e29ebSSimon Glass 		return -E2BIG;
356282e29ebSSimon Glass 
357282e29ebSSimon Glass 	memcpy(buf->data, data, size);
358282e29ebSSimon Glass 	buf->size = size;
359e625b68bSSimon Glass 	buf->pos = 0;
360282e29ebSSimon Glass 	if (!sdl.running) {
361bbc09bf2SSimon Glass 		SDL_PauseAudio(0);
362282e29ebSSimon Glass 		sdl.running = 1;
363282e29ebSSimon Glass 	}
364bbc09bf2SSimon Glass 
365bbc09bf2SSimon Glass 	return 0;
366bbc09bf2SSimon Glass }
367bbc09bf2SSimon Glass 
sandbox_sdl_sound_stop(void)368bbc09bf2SSimon Glass int sandbox_sdl_sound_stop(void)
369bbc09bf2SSimon Glass {
370282e29ebSSimon Glass 	if (sdl.running) {
371bbc09bf2SSimon Glass 		SDL_PauseAudio(1);
372282e29ebSSimon Glass 		sdl.running = 0;
373282e29ebSSimon Glass 	}
374bbc09bf2SSimon Glass 
375bbc09bf2SSimon Glass 	return 0;
376bbc09bf2SSimon Glass }
377