1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2013 Google, Inc
8 #include <linux/input.h>
10 #include <asm/state.h>
13 * struct buf_info - a data buffer holding audio data
15 * @pos: Current position playing in audio buffer
16 * @size: Size of data in audio buffer (0=empty)
17 * @alloced: Allocated size of audio buffer (max size it can hold)
28 * struct sdl_info - Information about our use of the SDL library
30 * @screen: Surface used to draw on the screen
31 * @width: Width of simulated LCD display
32 * @height: Height of simulated LCD display
33 * @depth: Depth of the display in bits per pixel (16 or 32)
34 * @pitch: Number of bytes per line of the display
35 * @sample_rate: Current sample rate for audio
36 * @audio_active: true if audio can be used
37 * @inited: true if this module is initialised
38 * @cur_buf: Current audio buffer being used by sandbox_sdl_fill_audio (0 or 1)
39 * @buf: The two available audio buffers. SDL can be reading from one while we
40 * are setting up the next
41 * @running: true if audio is running
43 static struct sdl_info {
53 struct buf_info buf[2];
57 static void sandbox_sdl_poll_events(void)
60 * We don't want to include common.h in this file since it uses
61 * system headers. So add a declation here.
63 extern void reset_cpu(unsigned long addr);
66 while (SDL_PollEvent(&event)) {
69 puts("LCD window closed - quitting\n");
76 static int sandbox_sdl_ensure_init(void)
79 if (SDL_Init(0) < 0) {
80 printf("Unable to initialize SDL: %s\n",
92 int sandbox_sdl_init_display(int width, int height, int log2_bpp)
94 struct sandbox_state *state = state_get_current();
97 if (!width || !state->show_lcd)
99 err = sandbox_sdl_ensure_init();
102 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
103 printf("Unable to initialize SDL LCD: %s\n", SDL_GetError());
106 SDL_WM_SetCaption("U-Boot", "U-Boot");
110 sdl.depth = 1 << log2_bpp;
111 sdl.pitch = sdl.width * sdl.depth / 8;
112 sdl.screen = SDL_SetVideoMode(width, height, 0, 0);
113 sandbox_sdl_poll_events();
118 int sandbox_sdl_sync(void *lcd_base)
122 frame = SDL_CreateRGBSurfaceFrom(lcd_base, sdl.width, sdl.height,
123 sdl.depth, sdl.pitch,
124 0x1f << 11, 0x3f << 5, 0x1f << 0, 0);
125 SDL_BlitSurface(frame, NULL, sdl.screen, NULL);
126 SDL_FreeSurface(frame);
127 SDL_UpdateRect(sdl.screen, 0, 0, 0, 0);
128 sandbox_sdl_poll_events();
134 #define NUM_SDL_CODES (SDLK_UNDO + 1)
136 static int16_t sdl_to_keycode[NUM_SDL_CODES] = {
138 NONE, NONE, NONE, NONE, NONE,
139 NONE, NONE, NONE, KEY_BACKSPACE, KEY_TAB,
140 NONE, NONE, NONE, KEY_ENTER, NONE,
141 NONE, NONE, NONE, NONE, KEY_POWER, /* use PAUSE as POWER */
144 NONE, NONE, NONE, NONE, NONE,
145 NONE, NONE, KEY_ESC, NONE, NONE,
146 NONE, NONE, KEY_SPACE, NONE, NONE,
147 NONE, NONE, NONE, NONE, NONE,
150 NONE, NONE, NONE, NONE, KEY_COMMA,
151 KEY_MINUS, KEY_DOT, KEY_SLASH, KEY_0, KEY_1,
152 KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,
153 KEY_7, KEY_8, KEY_9, NONE, KEY_SEMICOLON,
156 NONE, KEY_EQUAL, NONE, NONE, NONE,
157 NONE, NONE, NONE, NONE, NONE,
158 NONE, NONE, NONE, NONE, NONE,
159 NONE, NONE, NONE, NONE, NONE,
162 NONE, NONE, NONE, NONE, NONE,
163 NONE, NONE, NONE, NONE, NONE,
164 NONE, NONE, KEY_BACKSLASH, NONE, NONE,
165 NONE, KEY_GRAVE, KEY_A, KEY_B, KEY_C,
168 KEY_D, KEY_E, KEY_F, KEY_G, KEY_H,
169 KEY_I, KEY_J, KEY_K, KEY_L, KEY_M,
170 KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R,
171 KEY_S, KEY_T, KEY_U, KEY_V, KEY_W,
174 KEY_X, KEY_Y, KEY_Z, NONE, NONE,
175 NONE, NONE, KEY_DELETE, NONE, NONE,
176 NONE, NONE, NONE, NONE, NONE,
177 NONE, NONE, NONE, NONE, NONE,
180 NONE, NONE, NONE, NONE, NONE,
181 NONE, NONE, NONE, NONE, NONE,
182 NONE, NONE, NONE, NONE, NONE,
183 NONE, NONE, NONE, NONE, NONE,
186 NONE, NONE, NONE, NONE, NONE,
187 NONE, NONE, NONE, NONE, NONE,
188 NONE, NONE, NONE, NONE, NONE,
189 NONE, NONE, NONE, NONE, NONE,
192 NONE, NONE, NONE, NONE, NONE,
193 NONE, NONE, NONE, NONE, NONE,
194 NONE, NONE, NONE, NONE, NONE,
195 NONE, NONE, NONE, NONE, NONE,
198 NONE, NONE, NONE, NONE, NONE,
199 NONE, NONE, NONE, NONE, NONE,
200 NONE, NONE, NONE, NONE, NONE,
201 NONE, NONE, NONE, NONE, NONE,
204 NONE, NONE, NONE, NONE, NONE,
205 NONE, NONE, NONE, NONE, NONE,
206 NONE, NONE, NONE, NONE, NONE,
207 NONE, NONE, NONE, NONE, NONE,
210 NONE, NONE, NONE, NONE, NONE,
211 NONE, NONE, NONE, NONE, NONE,
212 NONE, NONE, NONE, NONE, NONE,
213 NONE, KEY_KP0, KEY_KP1, KEY_KP2, KEY_KP3,
216 KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8,
217 KEY_KP9, KEY_KPDOT, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS,
218 KEY_KPPLUS, KEY_KPENTER, KEY_KPEQUAL, KEY_UP, KEY_DOWN,
219 KEY_RIGHT, KEY_LEFT, KEY_INSERT, KEY_HOME, KEY_END,
222 KEY_PAGEUP, KEY_PAGEDOWN, KEY_F1, KEY_F2, KEY_F3,
223 KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8,
224 KEY_F9, KEY_F10, KEY_F11, KEY_F12, NONE,
225 NONE, NONE, NONE, NONE, NONE,
228 KEY_NUMLOCK, KEY_CAPSLOCK, KEY_SCROLLLOCK, KEY_RIGHTSHIFT,
230 KEY_RIGHTCTRL, KEY_LEFTCTRL, KEY_RIGHTALT, KEY_LEFTALT, KEY_RIGHTMETA,
231 KEY_LEFTMETA, NONE, KEY_FN, NONE, KEY_COMPOSE,
232 NONE, KEY_PRINT, KEY_SYSRQ, KEY_PAUSE, NONE,
238 int sandbox_sdl_scan_keys(int key[], int max_keys)
243 sandbox_sdl_poll_events();
244 keystate = SDL_GetKeyState(NULL);
245 for (i = count = 0; i < NUM_SDL_CODES; i++) {
246 if (count >= max_keys)
248 else if (keystate[i])
249 key[count++] = sdl_to_keycode[i];
255 int sandbox_sdl_key_pressed(int keycode)
257 int key[8]; /* allow up to 8 keys to be pressed at once */
261 count = sandbox_sdl_scan_keys(key, sizeof(key) / sizeof(key[0]));
262 for (i = 0; i < count; i++) {
263 if (key[i] == keycode)
270 void sandbox_sdl_fill_audio(void *udata, Uint8 *stream, int len)
272 struct buf_info *buf;
276 for (i = 0; i < 2; i++) {
277 buf = &sdl.buf[sdl.cur_buf];
278 avail = buf->size - buf->pos;
280 sdl.cur_buf = 1 - sdl.cur_buf;
286 SDL_MixAudio(stream, buf->data + buf->pos, avail,
291 /* Move to next buffer if we are at the end */
292 if (buf->pos == buf->size)
299 int sandbox_sdl_sound_init(int rate, int channels)
301 SDL_AudioSpec wanted;
304 if (sandbox_sdl_ensure_init())
307 if (sdl.audio_active)
310 /* Set the audio format */
312 wanted.format = AUDIO_S16;
313 wanted.channels = channels;
314 wanted.samples = 1024; /* Good low-latency value for callback */
315 wanted.callback = sandbox_sdl_fill_audio;
316 wanted.userdata = NULL;
318 for (i = 0; i < 2; i++) {
319 struct buf_info *buf = &sdl.buf[i];
321 buf->alloced = sizeof(uint16_t) * wanted.freq * wanted.channels;
322 buf->data = malloc(buf->alloced);
324 printf("%s: Out of memory\n", __func__);
326 free(sdl.buf[0].data);
333 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
334 printf("Unable to initialize SDL audio: %s\n", SDL_GetError());
338 /* Open the audio device, forcing the desired format */
339 if (SDL_OpenAudio(&wanted, NULL) < 0) {
340 printf("Couldn't open audio: %s\n", SDL_GetError());
343 sdl.audio_active = true;
344 sdl.sample_rate = wanted.freq;
351 for (i = 0; i < 2; i++)
352 free(sdl.buf[i].data);
356 int sandbox_sdl_sound_play(const void *data, uint size)
358 struct buf_info *buf;
360 if (!sdl.audio_active)
369 if (size > buf->alloced)
372 memcpy(buf->data, data, size);
383 int sandbox_sdl_sound_stop(void)