1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2013 Google, Inc
9 #include <linux/input.h>
11 #include <asm/state.h>
14 * struct buf_info - a data buffer holding audio data
16 * @pos: Current position playing in audio buffer
17 * @size: Size of data in audio buffer (0=empty)
18 * @alloced: Allocated size of audio buffer (max size it can hold)
29 * struct sdl_info - Information about our use of the SDL library
31 * @screen: Surface used to draw on the screen
32 * @width: Width of simulated LCD display
33 * @height: Height of simulated LCD display
34 * @depth: Depth of the display in bits per pixel (16 or 32)
35 * @pitch: Number of bytes per line of the display
36 * @sample_rate: Current sample rate for audio
37 * @audio_active: true if audio can be used
38 * @inited: true if this module is initialised
39 * @cur_buf: Current audio buffer being used by sandbox_sdl_fill_audio (0 or 1)
40 * @buf: The two available audio buffers. SDL can be reading from one while we
41 * are setting up the next
42 * @running: true if audio is running
43 * @stopping: true if audio will stop once it runs out of data
45 static struct sdl_info {
55 struct buf_info buf[2];
60 static void sandbox_sdl_poll_events(void)
63 * We don't want to include common.h in this file since it uses
64 * system headers. So add a declation here.
66 extern void reset_cpu(unsigned long addr);
69 while (SDL_PollEvent(&event)) {
72 puts("LCD window closed - quitting\n");
79 static int sandbox_sdl_ensure_init(void)
82 if (SDL_Init(0) < 0) {
83 printf("Unable to initialise SDL: %s\n",
95 int sandbox_sdl_init_display(int width, int height, int log2_bpp)
97 struct sandbox_state *state = state_get_current();
100 if (!width || !state->show_lcd)
102 err = sandbox_sdl_ensure_init();
105 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
106 printf("Unable to initialise SDL LCD: %s\n", SDL_GetError());
109 SDL_WM_SetCaption("U-Boot", "U-Boot");
113 sdl.depth = 1 << log2_bpp;
114 sdl.pitch = sdl.width * sdl.depth / 8;
115 sdl.screen = SDL_SetVideoMode(width, height, 0, 0);
116 sandbox_sdl_poll_events();
121 int sandbox_sdl_sync(void *lcd_base)
125 frame = SDL_CreateRGBSurfaceFrom(lcd_base, sdl.width, sdl.height,
126 sdl.depth, sdl.pitch,
127 0x1f << 11, 0x3f << 5, 0x1f << 0, 0);
128 SDL_BlitSurface(frame, NULL, sdl.screen, NULL);
129 SDL_FreeSurface(frame);
130 SDL_UpdateRect(sdl.screen, 0, 0, 0, 0);
131 sandbox_sdl_poll_events();
137 #define NUM_SDL_CODES (SDLK_UNDO + 1)
139 static int16_t sdl_to_keycode[NUM_SDL_CODES] = {
141 NONE, NONE, NONE, NONE, NONE,
142 NONE, NONE, NONE, KEY_BACKSPACE, KEY_TAB,
143 NONE, NONE, NONE, KEY_ENTER, NONE,
144 NONE, NONE, NONE, NONE, KEY_POWER, /* use PAUSE as POWER */
147 NONE, NONE, NONE, NONE, NONE,
148 NONE, NONE, KEY_ESC, NONE, NONE,
149 NONE, NONE, KEY_SPACE, NONE, NONE,
150 NONE, NONE, NONE, NONE, NONE,
153 NONE, NONE, NONE, NONE, KEY_COMMA,
154 KEY_MINUS, KEY_DOT, KEY_SLASH, KEY_0, KEY_1,
155 KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,
156 KEY_7, KEY_8, KEY_9, NONE, KEY_SEMICOLON,
159 NONE, KEY_EQUAL, NONE, NONE, NONE,
160 NONE, NONE, NONE, NONE, NONE,
161 NONE, NONE, NONE, NONE, NONE,
162 NONE, NONE, NONE, NONE, NONE,
165 NONE, NONE, NONE, NONE, NONE,
166 NONE, NONE, NONE, NONE, NONE,
167 NONE, NONE, KEY_BACKSLASH, NONE, NONE,
168 NONE, KEY_GRAVE, KEY_A, KEY_B, KEY_C,
171 KEY_D, KEY_E, KEY_F, KEY_G, KEY_H,
172 KEY_I, KEY_J, KEY_K, KEY_L, KEY_M,
173 KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R,
174 KEY_S, KEY_T, KEY_U, KEY_V, KEY_W,
177 KEY_X, KEY_Y, KEY_Z, NONE, NONE,
178 NONE, NONE, KEY_DELETE, NONE, NONE,
179 NONE, NONE, NONE, NONE, NONE,
180 NONE, NONE, NONE, NONE, NONE,
183 NONE, NONE, NONE, NONE, NONE,
184 NONE, NONE, NONE, NONE, NONE,
185 NONE, NONE, NONE, NONE, NONE,
186 NONE, NONE, NONE, NONE, NONE,
189 NONE, NONE, NONE, NONE, NONE,
190 NONE, NONE, NONE, NONE, NONE,
191 NONE, NONE, NONE, NONE, NONE,
192 NONE, NONE, NONE, NONE, NONE,
195 NONE, NONE, NONE, NONE, NONE,
196 NONE, NONE, NONE, NONE, NONE,
197 NONE, NONE, NONE, NONE, NONE,
198 NONE, NONE, NONE, NONE, NONE,
201 NONE, NONE, NONE, NONE, NONE,
202 NONE, NONE, NONE, NONE, NONE,
203 NONE, NONE, NONE, NONE, NONE,
204 NONE, NONE, NONE, NONE, NONE,
207 NONE, NONE, NONE, NONE, NONE,
208 NONE, NONE, NONE, NONE, NONE,
209 NONE, NONE, NONE, NONE, NONE,
210 NONE, NONE, NONE, NONE, NONE,
213 NONE, NONE, NONE, NONE, NONE,
214 NONE, NONE, NONE, NONE, NONE,
215 NONE, NONE, NONE, NONE, NONE,
216 NONE, KEY_KP0, KEY_KP1, KEY_KP2, KEY_KP3,
219 KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8,
220 KEY_KP9, KEY_KPDOT, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS,
221 KEY_KPPLUS, KEY_KPENTER, KEY_KPEQUAL, KEY_UP, KEY_DOWN,
222 KEY_RIGHT, KEY_LEFT, KEY_INSERT, KEY_HOME, KEY_END,
225 KEY_PAGEUP, KEY_PAGEDOWN, KEY_F1, KEY_F2, KEY_F3,
226 KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8,
227 KEY_F9, KEY_F10, KEY_F11, KEY_F12, NONE,
228 NONE, NONE, NONE, NONE, NONE,
231 KEY_NUMLOCK, KEY_CAPSLOCK, KEY_SCROLLLOCK, KEY_RIGHTSHIFT,
233 KEY_RIGHTCTRL, KEY_LEFTCTRL, KEY_RIGHTALT, KEY_LEFTALT, KEY_RIGHTMETA,
234 KEY_LEFTMETA, NONE, KEY_FN, NONE, KEY_COMPOSE,
235 NONE, KEY_PRINT, KEY_SYSRQ, KEY_PAUSE, NONE,
241 int sandbox_sdl_scan_keys(int key[], int max_keys)
246 sandbox_sdl_poll_events();
247 keystate = SDL_GetKeyState(NULL);
248 for (i = count = 0; i < NUM_SDL_CODES; i++) {
249 if (count >= max_keys)
251 else if (keystate[i])
252 key[count++] = sdl_to_keycode[i];
258 int sandbox_sdl_key_pressed(int keycode)
260 int key[8]; /* allow up to 8 keys to be pressed at once */
264 count = sandbox_sdl_scan_keys(key, sizeof(key) / sizeof(key[0]));
265 for (i = 0; i < count; i++) {
266 if (key[i] == keycode)
273 void sandbox_sdl_fill_audio(void *udata, Uint8 *stream, int len)
275 struct buf_info *buf;
277 bool have_data = false;
280 for (i = 0; i < 2; i++) {
281 buf = &sdl.buf[sdl.cur_buf];
282 avail = buf->size - buf->pos;
284 sdl.cur_buf = 1 - sdl.cur_buf;
291 SDL_MixAudio(stream, buf->data + buf->pos, avail,
296 /* Move to next buffer if we are at the end */
297 if (buf->pos == buf->size)
302 sdl.stopping = !have_data;
305 int sandbox_sdl_sound_init(int rate, int channels)
307 SDL_AudioSpec wanted, have;
310 if (sandbox_sdl_ensure_init())
313 if (sdl.audio_active)
316 /* Set the audio format */
318 wanted.format = AUDIO_S16;
319 wanted.channels = channels;
320 wanted.samples = 1024; /* Good low-latency value for callback */
321 wanted.callback = sandbox_sdl_fill_audio;
322 wanted.userdata = NULL;
324 for (i = 0; i < 2; i++) {
325 struct buf_info *buf = &sdl.buf[i];
327 buf->alloced = sizeof(uint16_t) * wanted.freq * wanted.channels;
328 buf->data = malloc(buf->alloced);
330 printf("%s: Out of memory\n", __func__);
332 free(sdl.buf[0].data);
339 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
340 printf("Unable to initialise SDL audio: %s\n", SDL_GetError());
344 /* Open the audio device, forcing the desired format */
345 if (SDL_OpenAudio(&wanted, &have) < 0) {
346 printf("Couldn't open audio: %s\n", SDL_GetError());
349 if (have.format != wanted.format) {
350 printf("Couldn't select required audio format\n");
353 sdl.audio_active = true;
354 sdl.sample_rate = wanted.freq;
361 for (i = 0; i < 2; i++)
362 free(sdl.buf[i].data);
366 int sandbox_sdl_sound_play(const void *data, uint size)
368 struct buf_info *buf;
370 if (!sdl.audio_active)
379 if (size > buf->alloced)
382 memcpy(buf->data, data, size);
388 sdl.stopping = false;
394 int sandbox_sdl_sound_stop(void)
397 while (!sdl.stopping)
402 sdl.stopping = false;