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