From f641fccb7413775feab03ea268cc503cfb47b9b7 Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 14 Nov 2010 23:21:59 +0200 Subject: [PATCH] add OMAP layer handling --- configure.in | 1 + src/video/omapdss/Makefile | 3 +- src/video/omapdss/config.c | 8 + src/video/omapdss/omapfb.h | 427 +++++++++++++++++++++++++++++++++ src/video/omapdss/omapsdl.h | 17 ++ src/video/omapdss/osdl_video.c | 318 ++++++++++++++++++++++++ src/video/omapdss/sdlif.c | 42 +--- src/video/omapdss/standalone.c | 25 +- 8 files changed, 787 insertions(+), 54 deletions(-) create mode 100644 src/video/omapdss/omapfb.h create mode 100644 src/video/omapdss/osdl_video.c diff --git a/configure.in b/configure.in index 478014b..fa56690 100644 --- a/configure.in +++ b/configure.in @@ -1617,6 +1617,7 @@ AC_HELP_STRING([--enable-video-omapdss], [use OMAP DSS2 video driver [[default=y AC_DEFINE(SDL_VIDEO_DRIVER_OMAPDSS) SOURCES="$SOURCES $srcdir/src/video/omapdss/sdlif.c" SOURCES="$SOURCES $srcdir/src/video/omapdss/osdl_input.c" + SOURCES="$SOURCES $srcdir/src/video/omapdss/osdl_video.c" SOURCES="$SOURCES $srcdir/src/video/omapdss/config.c" SOURCES="$SOURCES $srcdir/src/video/omapdss/linux/fbdev.c" SOURCES="$SOURCES $srcdir/src/video/omapdss/linux/oshide.c" diff --git a/src/video/omapdss/Makefile b/src/video/omapdss/Makefile index 8fea694..3cef9e0 100644 --- a/src/video/omapdss/Makefile +++ b/src/video/omapdss/Makefile @@ -8,9 +8,10 @@ endif ARCH ?= arm TARGET = libSDL-1.2.so.0 -OBJS += standalone.o osdl_input.o config.o \ +OBJS += standalone.o osdl_input.o osdl_video.o config.o \ linux/fbdev.o linux/oshide.o ifeq ($(ARCH),arm) +LDFLAGS += -lts OBJS += arm_utils.o else CFLAGS += -fPIC diff --git a/src/video/omapdss/config.c b/src/video/omapdss/config.c index 52809d6..b829847 100644 --- a/src/video/omapdss/config.c +++ b/src/video/omapdss/config.c @@ -96,4 +96,12 @@ bad: fclose(f); } +void omapsdl_config_from_env(void) +{ + const char *tmp; + + tmp = getenv("SDL_OMAP_VSYNC"); + if (tmp != NULL) + gcfg_force_vsync = atoi(tmp); +} diff --git a/src/video/omapdss/omapfb.h b/src/video/omapdss/omapfb.h new file mode 100644 index 0000000..f156e3a --- /dev/null +++ b/src/video/omapdss/omapfb.h @@ -0,0 +1,427 @@ +/* + * File: arch/arm/plat-omap/include/mach/omapfb.h + * + * Framebuffer driver for TI OMAP boards + * + * Copyright (C) 2004 Nokia Corporation + * Author: Imre Deak + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __OMAPFB_H +#define __OMAPFB_H + +#include +#include + +/* IOCTL commands. */ + +#define OMAP_IOW(num, dtype) _IOW('O', num, dtype) +#define OMAP_IOR(num, dtype) _IOR('O', num, dtype) +#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype) +#define OMAP_IO(num) _IO('O', num) + +#define OMAPFB_MIRROR OMAP_IOW(31, int) +#define OMAPFB_SYNC_GFX OMAP_IO(37) +#define OMAPFB_VSYNC OMAP_IO(38) +#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int) +#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps) +#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int) +#define OMAPFB_LCD_TEST OMAP_IOW(45, int) +#define OMAPFB_CTRL_TEST OMAP_IOW(46, int) +#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old) +#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key) +#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key) +#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info) +#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info) +#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window) +#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info) +#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info) +#define OMAPFB_WAITFORVSYNC OMAP_IO(57) +#define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read) + +#ifndef FBIO_WAITFORVSYNC +#define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t) +#endif + +#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff +#define OMAPFB_CAPS_LCDC_MASK 0x00fff000 +#define OMAPFB_CAPS_PANEL_MASK 0xff000000 + +#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000 +#define OMAPFB_CAPS_TEARSYNC 0x00002000 +#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000 +#define OMAPFB_CAPS_PLANE_SCALE 0x00008000 +#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000 +#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000 +#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000 +#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000 +#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000 + +/* Values from DSP must map to lower 16-bits */ +#define OMAPFB_FORMAT_MASK 0x00ff +#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100 +#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200 +#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400 +#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800 +#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000 + +#define OMAPFB_EVENT_READY 1 +#define OMAPFB_EVENT_DISABLED 2 + +#define OMAPFB_MEMTYPE_SDRAM 0 +#define OMAPFB_MEMTYPE_SRAM 1 +#define OMAPFB_MEMTYPE_MAX 1 + +enum omapfb_color_format { + OMAPFB_COLOR_RGB565 = 0, + OMAPFB_COLOR_YUV422, + OMAPFB_COLOR_YUV420, + OMAPFB_COLOR_CLUT_8BPP, + OMAPFB_COLOR_CLUT_4BPP, + OMAPFB_COLOR_CLUT_2BPP, + OMAPFB_COLOR_CLUT_1BPP, + OMAPFB_COLOR_RGB444, + OMAPFB_COLOR_YUY422, + + OMAPFB_COLOR_ARGB16, + OMAPFB_COLOR_RGB24U, /* RGB24, 32-bit container */ + OMAPFB_COLOR_RGB24P, /* RGB24, 24-bit container */ + OMAPFB_COLOR_ARGB32, + OMAPFB_COLOR_RGBA32, + OMAPFB_COLOR_RGBX32, +}; + +struct omapfb_update_window { + __u32 x, y; + __u32 width, height; + __u32 format; + __u32 out_x, out_y; + __u32 out_width, out_height; + __u32 reserved[8]; +}; + +struct omapfb_update_window_old { + __u32 x, y; + __u32 width, height; + __u32 format; +}; + +enum omapfb_plane { + OMAPFB_PLANE_GFX = 0, + OMAPFB_PLANE_VID1, + OMAPFB_PLANE_VID2, +}; + +enum omapfb_channel_out { + OMAPFB_CHANNEL_OUT_LCD = 0, + OMAPFB_CHANNEL_OUT_DIGIT, +}; + +struct omapfb_plane_info { + __u32 pos_x; + __u32 pos_y; + __u8 enabled; + __u8 channel_out; + __u8 mirror; + __u8 reserved1; + __u32 out_width; + __u32 out_height; + __u32 reserved2[12]; +}; + +struct omapfb_mem_info { + __u32 size; + __u8 type; + __u8 reserved[3]; +}; + +struct omapfb_caps { + __u32 ctrl; + __u32 plane_color; + __u32 wnd_color; +}; + +enum omapfb_color_key_type { + OMAPFB_COLOR_KEY_DISABLED = 0, + OMAPFB_COLOR_KEY_GFX_DST, + OMAPFB_COLOR_KEY_VID_SRC, +}; + +struct omapfb_color_key { + __u8 channel_out; + __u32 background; + __u32 trans_key; + __u8 key_type; +}; + +enum omapfb_update_mode { + OMAPFB_UPDATE_DISABLED = 0, + OMAPFB_AUTO_UPDATE, + OMAPFB_MANUAL_UPDATE +}; + +struct omapfb_memory_read { + __u16 x; + __u16 y; + __u16 w; + __u16 h; + size_t buffer_size; + void *buffer; +}; + +#ifdef __KERNEL__ + +#include +#include +#include +#include + +#include + +#define OMAP_LCDC_INV_VSYNC 0x0001 +#define OMAP_LCDC_INV_HSYNC 0x0002 +#define OMAP_LCDC_INV_PIX_CLOCK 0x0004 +#define OMAP_LCDC_INV_OUTPUT_EN 0x0008 +#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010 +#define OMAP_LCDC_HSVS_OPPOSITE 0x0020 + +#define OMAP_LCDC_SIGNAL_MASK 0x003f + +#define OMAP_LCDC_PANEL_TFT 0x0100 + +#define OMAPFB_PLANE_XRES_MIN 8 +#define OMAPFB_PLANE_YRES_MIN 8 + +#ifdef CONFIG_ARCH_OMAP1 +#define OMAPFB_PLANE_NUM 1 +#else +#define OMAPFB_PLANE_NUM 3 +#endif + +struct omapfb_device; + +struct lcd_panel { + const char *name; + int config; /* TFT/STN, signal inversion */ + int bpp; /* Pixel format in fb mem */ + int data_lines; /* Lines on LCD HW interface */ + + int x_res, y_res; + int pixel_clock; /* In kHz */ + int hsw; /* Horizontal synchronization + pulse width */ + int hfp; /* Horizontal front porch */ + int hbp; /* Horizontal back porch */ + int vsw; /* Vertical synchronization + pulse width */ + int vfp; /* Vertical front porch */ + int vbp; /* Vertical back porch */ + int acb; /* ac-bias pin frequency */ + int pcd; /* pixel clock divider. + Obsolete use pixel_clock instead */ + + int (*init) (struct lcd_panel *panel, + struct omapfb_device *fbdev); + void (*cleanup) (struct lcd_panel *panel); + int (*enable) (struct lcd_panel *panel); + void (*disable) (struct lcd_panel *panel); + unsigned long (*get_caps) (struct lcd_panel *panel); + int (*set_bklight_level)(struct lcd_panel *panel, + unsigned int level); + unsigned int (*get_bklight_level)(struct lcd_panel *panel); + unsigned int (*get_bklight_max) (struct lcd_panel *panel); + int (*run_test) (struct lcd_panel *panel, int test_num); +}; + +struct extif_timings { + int cs_on_time; + int cs_off_time; + int we_on_time; + int we_off_time; + int re_on_time; + int re_off_time; + int we_cycle_time; + int re_cycle_time; + int cs_pulse_width; + int access_time; + + int clk_div; + + u32 tim[5]; /* set by extif->convert_timings */ + + int converted; +}; + +struct lcd_ctrl_extif { + int (*init) (struct omapfb_device *fbdev); + void (*cleanup) (void); + void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div); + unsigned long (*get_max_tx_rate)(void); + int (*convert_timings) (struct extif_timings *timings); + void (*set_timings) (const struct extif_timings *timings); + void (*set_bits_per_cycle)(int bpc); + void (*write_command) (const void *buf, unsigned int len); + void (*read_data) (void *buf, unsigned int len); + void (*write_data) (const void *buf, unsigned int len); + void (*transfer_area) (int width, int height, + void (callback)(void * data), void *data); + int (*setup_tearsync) (unsigned pin_cnt, + unsigned hs_pulse_time, unsigned vs_pulse_time, + int hs_pol_inv, int vs_pol_inv, int div); + int (*enable_tearsync) (int enable, unsigned line); + + unsigned long max_transmit_size; +}; + +struct omapfb_notifier_block { + struct notifier_block nb; + void *data; + int plane_idx; +}; + +typedef int (*omapfb_notifier_callback_t)(struct notifier_block *, + unsigned long event, + void *fbi); + +struct omapfb_mem_region { + u32 paddr; + void __iomem *vaddr; + unsigned long size; + u8 type; /* OMAPFB_PLANE_MEM_* */ + enum omapfb_color_format format;/* OMAPFB_COLOR_* */ + unsigned format_used:1; /* Must be set when format is set. + * Needed b/c of the badly chosen 0 + * base for OMAPFB_COLOR_* values + */ + unsigned alloc:1; /* allocated by the driver */ + unsigned map:1; /* kernel mapped by the driver */ +}; + +struct omapfb_mem_desc { + int region_cnt; + struct omapfb_mem_region region[OMAPFB_PLANE_NUM]; +}; + +struct lcd_ctrl { + const char *name; + void *data; + + int (*init) (struct omapfb_device *fbdev, + int ext_mode, + struct omapfb_mem_desc *req_md); + void (*cleanup) (void); + void (*bind_client) (struct omapfb_notifier_block *nb); + void (*get_caps) (int plane, struct omapfb_caps *caps); + int (*set_update_mode)(enum omapfb_update_mode mode); + enum omapfb_update_mode (*get_update_mode)(void); + int (*setup_plane) (int plane, int channel_out, + unsigned long offset, + int screen_width, + int pos_x, int pos_y, int width, + int height, int color_mode); + int (*set_rotate) (int angle); + int (*setup_mem) (int plane, size_t size, + int mem_type, unsigned long *paddr); + int (*mmap) (struct fb_info *info, + struct vm_area_struct *vma); + int (*set_scale) (int plane, + int orig_width, int orig_height, + int out_width, int out_height); + int (*enable_plane) (int plane, int enable); + int (*update_window) (struct fb_info *fbi, + struct omapfb_update_window *win, + void (*callback)(void *), + void *callback_data); + void (*sync) (void); + void (*suspend) (void); + void (*resume) (void); + int (*run_test) (int test_num); + int (*setcolreg) (u_int regno, u16 red, u16 green, + u16 blue, u16 transp, + int update_hw_mem); + int (*set_color_key) (struct omapfb_color_key *ck); + int (*get_color_key) (struct omapfb_color_key *ck); +}; + +enum omapfb_state { + OMAPFB_DISABLED = 0, + OMAPFB_SUSPENDED= 99, + OMAPFB_ACTIVE = 100 +}; + +struct omapfb_plane_struct { + int idx; + struct omapfb_plane_info info; + enum omapfb_color_format color_mode; + struct omapfb_device *fbdev; +}; + +struct omapfb_device { + int state; + int ext_lcdc; /* Using external + LCD controller */ + struct mutex rqueue_mutex; + + int palette_size; + u32 pseudo_palette[17]; + + struct lcd_panel *panel; /* LCD panel */ + const struct lcd_ctrl *ctrl; /* LCD controller */ + const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */ + struct lcd_ctrl_extif *ext_if; /* LCD ctrl external + interface */ + struct device *dev; + struct fb_var_screeninfo new_var; /* for mode changes */ + + struct omapfb_mem_desc mem_desc; + struct fb_info *fb_info[OMAPFB_PLANE_NUM]; +}; + +struct omapfb_platform_data { + struct omap_lcd_config lcd; + struct omapfb_mem_desc mem_desc; + void *ctrl_platform_data; +}; + +#ifdef CONFIG_ARCH_OMAP1 +extern struct lcd_ctrl omap1_lcd_ctrl; +#else +extern struct lcd_ctrl omap2_disp_ctrl; +#endif + +extern void omapfb_set_platform_data(struct omapfb_platform_data *data); + +extern void omapfb_reserve_sdram(void); +extern void omapfb_register_panel(struct lcd_panel *panel); +extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); +extern void omapfb_notify_clients(struct omapfb_device *fbdev, + unsigned long event); +extern int omapfb_register_client(struct omapfb_notifier_block *nb, + omapfb_notifier_callback_t callback, + void *callback_data); +extern int omapfb_unregister_client(struct omapfb_notifier_block *nb); +extern int omapfb_update_window_async(struct fb_info *fbi, + struct omapfb_update_window *win, + void (*callback)(void *), + void *callback_data); + +/* in arch/arm/plat-omap/fb.c */ +extern void omapfb_set_ctrl_platform_data(void *pdata); + +#endif /* __KERNEL__ */ + +#endif /* __OMAPFB_H */ diff --git a/src/video/omapdss/omapsdl.h b/src/video/omapdss/omapsdl.h index 250099f..b59533e 100644 --- a/src/video/omapdss/omapsdl.h +++ b/src/video/omapdss/omapsdl.h @@ -1,3 +1,9 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2010 + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING file in the top-level directory. + */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) @@ -11,6 +17,16 @@ #define dbg(...) #endif +struct SDL_PrivateVideoData { + struct vout_fbdev *fbdev; + void *saved_layer; + unsigned int oshide_done:1; +}; + +int osdl_video_set_mode(struct SDL_PrivateVideoData *pdata, int width, int height, int bpp); +void *osdl_video_flip(struct SDL_PrivateVideoData *pdata); +void osdl_video_finish(struct SDL_PrivateVideoData *pdata); + void omapsdl_input_init(void); void omapsdl_input_bind(const char *kname, const char *sdlname); int omapsdl_input_get_events(int timeout_ms, @@ -20,6 +36,7 @@ int omapsdl_input_get_events(int timeout_ms, void omapsdl_input_finish(void); void omapsdl_config(void); +void omapsdl_config_from_env(void); /* functions for standalone */ void do_clut(void *dest, void *src, unsigned short *pal, int count); diff --git a/src/video/omapdss/osdl_video.c b/src/video/omapdss/osdl_video.c new file mode 100644 index 0000000..d492d36 --- /dev/null +++ b/src/video/omapdss/osdl_video.c @@ -0,0 +1,318 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2010 + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING file in the top-level directory. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "omapsdl.h" +#include "omapfb.h" +#include "linux/fbdev.h" +#include "linux/oshide.h" + +struct omapfb_saved_layer { + struct omapfb_plane_info pi; + struct omapfb_mem_info mi; +}; + +static int osdl_setup_omapfb(int fd, int enabled, int x, int y, int w, int h, int mem) +{ + struct omapfb_plane_info pi; + struct omapfb_mem_info mi; + int ret; + + ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi); + if (ret != 0) { + perror("QUERY_PLANE"); + return -1; + } + + ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi); + if (ret != 0) { + perror("QUERY_MEM"); + return -1; + } + + /* must disable when changing stuff */ + if (pi.enabled) { + pi.enabled = 0; + ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi); + if (ret != 0) + perror("SETUP_PLANE"); + } + + mi.size = mem; + ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi); + if (ret != 0) { + perror("SETUP_MEM"); + return -1; + } + + pi.pos_x = x; + pi.pos_y = y; + pi.out_width = w; + pi.out_height = h; + pi.enabled = enabled; + + ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi); + if (ret != 0) { + perror("SETUP_PLANE"); + return -1; + } + + return 0; +} + +static int read_sysfs(const char *fname, char *buff, size_t size) +{ + FILE *f; + int ret; + + f = fopen(fname, "r"); + if (f == NULL) { + fprintf(stderr, "open %s: ", fname); + perror(NULL); + return -1; + } + + ret = fread(buff, 1, size - 1, f); + fclose(f); + if (ret <= 0) { + fprintf(stderr, "read %s: ", fname); + perror(NULL); + return -1; + } + + buff[ret] = 0; + for (ret--; ret >= 0 && isspace(buff[ret]); ret--) + buff[ret] = 0; + + return 0; +} + +static int osdl_setup_omap_layer(struct SDL_PrivateVideoData *pdata, + const char *fbname, int width, int height, int bpp) +{ + int x = 0, y = 0, w = width, h = height; /* layer size and pos */ + int screen_w = w, screen_h = h; + int fb_id, overlay_id = -1, screen_id = -1; + char buff[64], screen_name[64]; + struct stat status; + const char *tmp; + int i, ret, fd; + FILE *f; + + fd = open(fbname, O_RDWR); + if (fd == -1) { + fprintf(stderr, "open %s: ", fbname); + perror(NULL); + return -1; + } + + /* FIXME: assuming layer doesn't change here */ + if (pdata->saved_layer == NULL) { + struct omapfb_saved_layer *slayer; + slayer = calloc(1, sizeof(*slayer)); + if (slayer == NULL) + return -1; + + ret = ioctl(fd, OMAPFB_QUERY_PLANE, &slayer->pi); + if (ret != 0) { + perror("QUERY_PLANE"); + return -1; + } + + ret = ioctl(fd, OMAPFB_QUERY_MEM, &slayer->mi); + if (ret != 0) { + perror("QUERY_MEM"); + return -1; + } + + pdata->saved_layer = slayer; + } + + /* Figure out screen resolution, we will want to center if scaling is not enabled. + * The only way to achieve this seems to be walking some sysfs files.. */ + ret = stat(fbname, &status); + if (ret != 0) { + fprintf(stderr, "can't stat %s: ", fbname); + perror(NULL); + return -1; + } + fb_id = minor(status.st_rdev); + + snprintf(buff, sizeof(buff), "/sys/class/graphics/fb%d/overlays", fb_id); + f = fopen(buff, "r"); + if (f == NULL) { + fprintf(stderr, "can't open %s, skip screen detection\n", buff); + goto skip_screen; + } + + ret = fscanf(f, "%d", &overlay_id); + fclose(f); + if (ret != 1) { + fprintf(stderr, "can't parse %s, skip screen detection\n", buff); + goto skip_screen; + } + + snprintf(buff, sizeof(buff), "/sys/devices/platform/omapdss/overlay%d/manager", overlay_id); + ret = read_sysfs(buff, screen_name, sizeof(screen_name)); + if (ret < 0) { + fprintf(stderr, "skip screen detection\n"); + goto skip_screen; + } + + for (i = 0; ; i++) { + snprintf(buff, sizeof(buff), "/sys/devices/platform/omapdss/display%d/name", i); + ret = read_sysfs(buff, buff, sizeof(buff)); + if (ret < 0) + break; + + if (strcmp(screen_name, buff) == 0) { + screen_id = i; + break; + } + } + + if (screen_id < 0) { + fprintf(stderr, "could not find screen\n"); + goto skip_screen; + } + + snprintf(buff, sizeof(buff), "/sys/devices/platform/omapdss/display%d/timings", screen_id); + f = fopen(buff, "r"); + if (f == NULL) { + fprintf(stderr, "can't open %s, skip screen detection\n", buff); + goto skip_screen; + } + + ret = fscanf(f, "%*d,%d/%*d/%*d/%*d,%d/%*d/%*d/%*d", &screen_w, &screen_h); + fclose(f); + if (ret != 2) { + fprintf(stderr, "can't parse %s (%d), skip screen detection\n", buff, ret); + goto skip_screen; + } + + printf("detected %dx%d '%s' (%d) screen attached to fb %d and overlay %d\n", + screen_w, screen_h, screen_name, screen_id, fb_id, overlay_id); + +skip_screen: + tmp = getenv("SDL_OMAP_LAYER_SIZE"); + if (tmp != NULL) { + int w_, h_; + if (strcasecmp(tmp, "fullscreen") == 0) + w = screen_w, h = screen_h; + else if (sscanf(tmp, "%dx%d", &w_, &h_) == 2) + w = w_, h = h_; + else + fprintf(stderr, "layer size specified incorrectly, " + "should be like 800x480"); + } + + x = screen_w / 2 - w / 2; + y = screen_h / 2 - h / 2; + ret = osdl_setup_omapfb(fd, 1, x, y, w, h, width * height * ((bpp + 7) / 8) * 3); + close(fd); + + return ret; +} + +int osdl_video_set_mode(struct SDL_PrivateVideoData *pdata, int width, int height, int bpp) +{ + const char *fbname; + int ret; + + bpp = 16; // FIXME + + fbname = getenv("SDL_FBDEV"); + if (fbname == NULL) + fbname = "/dev/fb1"; + + if (pdata->fbdev != NULL) { + vout_fbdev_finish(pdata->fbdev); + pdata->fbdev = NULL; + } + + omapsdl_config_from_env(); + + ret = osdl_setup_omap_layer(pdata, fbname, width, height, bpp); + if (ret < 0) + return -1; + + pdata->fbdev = vout_fbdev_init(fbname, &width, &height, 0); + if (pdata->fbdev == NULL) + return -1; + + if (!pdata->oshide_done) { + oshide_init(); + pdata->oshide_done = 1; + } + + return 0; +} + +void *osdl_video_flip(struct SDL_PrivateVideoData *pdata) +{ + if (pdata->fbdev == NULL) + return NULL; + + if (gcfg_force_vsync) + vout_fbdev_wait_vsync(pdata->fbdev); + + return vout_fbdev_flip(pdata->fbdev); +} + +void osdl_video_finish(struct SDL_PrivateVideoData *pdata) +{ + static const char *fbname; + + fbname = getenv("SDL_FBDEV"); + if (fbname == NULL) + fbname = "/dev/fb1"; + + if (pdata->fbdev != NULL) { + vout_fbdev_finish(pdata->fbdev); + pdata->fbdev = NULL; + } + + /* restore the OMAP layer */ + if (pdata->saved_layer != NULL) { + struct omapfb_saved_layer *slayer = pdata->saved_layer; + int fd; + + fd = open(fbname, O_RDWR); + if (fd != -1) { + int enabled = slayer->pi.enabled; + + /* be sure to disable while setting up */ + slayer->pi.enabled = 0; + ioctl(fd, OMAPFB_SETUP_PLANE, &slayer->pi); + ioctl(fd, OMAPFB_SETUP_MEM, &slayer->mi); + if (enabled) { + slayer->pi.enabled = enabled; + ioctl(fd, OMAPFB_SETUP_PLANE, &slayer->pi); + } + close(fd); + } + free(slayer); + pdata->saved_layer = NULL; + } + + if (pdata->oshide_done) { + oshide_finish(); + pdata->oshide_done = 0; + } +} + diff --git a/src/video/omapdss/sdlif.c b/src/video/omapdss/sdlif.c index b33aa0f..93d18f7 100644 --- a/src/video/omapdss/sdlif.c +++ b/src/video/omapdss/sdlif.c @@ -10,16 +10,9 @@ #include "../SDL_sysvideo.h" #include "../SDL_pixels_c.h" #include "../../events/SDL_events_c.h" -#include "linux/fbdev.h" -#include "linux/oshide.h" #include "omapsdl.h" -struct SDL_PrivateVideoData { - struct vout_fbdev *fbdev; -// void *fbmem; -}; - static int omap_available(void) { trace(); @@ -49,12 +42,7 @@ static void omap_VideoQuit(SDL_VideoDevice *this) { trace(); - if (this->hidden->fbdev != NULL) { - vout_fbdev_finish(this->hidden->fbdev); - this->hidden->fbdev = NULL; - - oshide_finish(); - } + osdl_video_finish(this->hidden); this->screen->pixels = NULL; omapsdl_input_finish(); } @@ -98,17 +86,8 @@ static SDL_Surface *omap_SetVideoMode(SDL_VideoDevice *this, SDL_Surface *curren { trace("%d, %d, %d, %08x", width, height, bpp, flags); - if (this->hidden->fbdev == NULL) { - this->hidden->fbdev = vout_fbdev_init("/dev/fb0", &width, &height, 0); - if (this->hidden->fbdev == NULL) - return NULL; - - oshide_init(); - } - else { - if (vout_fbdev_resize(this->hidden->fbdev, width, height, 0, 0, 0, 0, 0) < 0) - return NULL; - } + if (osdl_video_set_mode(this->hidden, width, height, bpp) < 0) + return NULL; if (!SDL_ReallocFormat(current, 16, 0xf800, 0x07e0, 0x001f, 0)) return NULL; @@ -118,19 +97,11 @@ static SDL_Surface *omap_SetVideoMode(SDL_VideoDevice *this, SDL_Surface *curren current->h = height; current->pitch = SDL_CalculatePitch(current); - current->pixels = vout_fbdev_flip(this->hidden->fbdev); + current->pixels = osdl_video_flip(this->hidden); return current; } -static void *flip_it(struct vout_fbdev *fbdev) -{ - if (gcfg_force_vsync) - vout_fbdev_wait_vsync(fbdev); - - return vout_fbdev_flip(fbdev); -} - static int omap_LockHWSurface(SDL_VideoDevice *this, SDL_Surface *surface) { trace("%p", surface); @@ -147,7 +118,7 @@ static int omap_FlipHWSurface(SDL_VideoDevice *this, SDL_Surface *surface) { trace("%p", surface); - surface->pixels = flip_it(this->hidden->fbdev); + surface->pixels = osdl_video_flip(this->hidden); return 0; } @@ -171,8 +142,7 @@ static void omap_UpdateRects(SDL_VideoDevice *this, int nrects, SDL_Rect *rects) } } - if (this->hidden->fbdev) - this->screen->pixels = flip_it(this->hidden->fbdev); + this->screen->pixels = osdl_video_flip(this->hidden); } static void omap_InitOSKeymap(SDL_VideoDevice *this) diff --git a/src/video/omapdss/standalone.c b/src/video/omapdss/standalone.c index de238e0..8465efb 100644 --- a/src/video/omapdss/standalone.c +++ b/src/video/omapdss/standalone.c @@ -12,9 +12,8 @@ #include #include "omapsdl.h" -#include "linux/fbdev.h" -#include "linux/oshide.h" +static struct SDL_PrivateVideoData state; static SDL_Surface *g_screen; static void *g_screen_fbp; static Uint16 g_8bpp_pal[256]; @@ -57,7 +56,6 @@ SDL_Init(Uint32 flags) if (g_start_ticks == 0) { omapsdl_input_init(); - oshide_init(); omapsdl_config(); } @@ -72,10 +70,7 @@ SDL_Quit(void) { trace(""); - if (g_start_ticks != 0) { - oshide_finish(); - g_start_ticks = 0; - } + osdl_video_finish(&state); } DECLSPEC int SDLCALL @@ -109,7 +104,7 @@ SDL_GetTicks(void) DECLSPEC SDL_Surface * SDLCALL SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) { - struct vout_fbdev *fbdev; + int ret; trace("%d, %d, %d, %08x", width, height, bpp, flags); @@ -127,11 +122,11 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) if (g_screen == NULL) return NULL; - fbdev = vout_fbdev_init("/dev/fb0", &width, &height, 0); - if (fbdev == NULL) + ret = osdl_video_set_mode(&state, width, height, 16); + if (ret < 0) goto fail_fbdev_init; - g_screen_fbp = vout_fbdev_flip(fbdev); + g_screen_fbp = osdl_video_flip(&state); if (bpp == 16) g_screen->pixels = g_screen_fbp; else @@ -142,13 +137,12 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) err("fb NULL"); goto fail_pixels; } - g_screen->hwdata = (void *)fbdev; dbg("returning %p", g_screen); return g_screen; fail_pixels: - vout_fbdev_finish(fbdev); + osdl_video_finish(&state); fail_fbdev_init: free(g_screen); g_screen = NULL; @@ -158,8 +152,6 @@ fail_fbdev_init: DECLSPEC int SDLCALL SDL_Flip(SDL_Surface *screen) { - struct vout_fbdev *fbdev; - trace("%p", screen); if (screen != g_screen) { @@ -181,8 +173,7 @@ SDL_Flip(SDL_Surface *screen) #endif } - fbdev = (void *)screen->hwdata; - g_screen_fbp = vout_fbdev_flip(fbdev); + g_screen_fbp = osdl_video_flip(&state); if (screen->format->BitsPerPixel != 8) screen->pixels = g_screen_fbp; -- 2.39.2