diff options
author | Roman Peresipkyn <r.peresipkyn@samsung.com> | 2016-01-29 16:51:19 +0200 |
---|---|---|
committer | SooChan Lim <sc1.lim@samsung.com> | 2016-03-07 19:51:49 +0900 |
commit | a8dcfe8f34c5bfa259a327c4373534bdfeeff40a (patch) | |
tree | b349a936c2cf428a71070bc18075b6d20ec15595 | |
parent | 2af0591c13028a975a75d467e1c005eab0141830 (diff) | |
download | libtdm-fbdev-a8dcfe8f34c5bfa259a327c4373534bdfeeff40a.tar.gz libtdm-fbdev-a8dcfe8f34c5bfa259a327c4373534bdfeeff40a.tar.bz2 libtdm-fbdev-a8dcfe8f34c5bfa259a327c4373534bdfeeff40a.zip |
add initialization of framebuffer device
Change-Id: I0b0fb08b4627d2ef5cd3a5a7f4b8653be3d7b499
Signed-off-by: Roman Peresipkyn <r.peresipkyn@samsung.com>
-rw-r--r-- | src/tdm_fbdev.c | 259 | ||||
-rw-r--r-- | src/tdm_fbdev.h | 19 |
2 files changed, 272 insertions, 6 deletions
diff --git a/src/tdm_fbdev.c b/src/tdm_fbdev.c index 54314d4..2cdc1e0 100644 --- a/src/tdm_fbdev.c +++ b/src/tdm_fbdev.c @@ -10,10 +10,7 @@ #include <tdm_helper.h> -/* - * TODO: How should it be named? - */ -#define TDM_FBDEV_NAME "vigs" +#define TDM_FBDEV_NAME "fbdev" static tdm_func_display fbdev_func_display = { @@ -48,24 +45,274 @@ static tdm_func_display fbdev_func_display = NULL, //layer_create_capture }; +static tdm_fbdev_data *fbdev_data; + +static int +_tdm_fbdev_open_fbdev(void) +{ + const char *name = "/dev/fb0"; + int fd = -1; + + fd = open(name, O_RDWR); + if (fd < 0) + { + TDM_ERR("Cannot open fbdev device.. search by udev"); + goto close; + } + + /* + * TODO: If we failed directly to open framebuffer device + * we would try to open it through udev + */ + +close: + return fd; +} + +static tdm_error +_tdm_fbdev_init_internal(void) +{ + struct fb_fix_screeninfo finfo; + struct fb_var_screeninfo vinfo; + int ret = -1; + + ret = ioctl(fbdev_data->fbdev_fd, FBIOGET_VSCREENINFO, &vinfo); + if (ret < 0) + { + TDM_ERR("FBIOGET_VSCREENINFO ioctl failed errno=%d", errno); + goto close_1; + } + + vinfo.reserved[0] = 0; + vinfo.reserved[1] = 0; + vinfo.reserved[2] = 0; + vinfo.xoffset = 0; + vinfo.yoffset = 0; + vinfo.activate = FB_ACTIVATE_NOW; + + /* + * Explicitly request 32 bits per pixel colors with corresponding + * red, blue and green color offsets and length of colors + */ + vinfo.bits_per_pixel = 32; + vinfo.red.offset = 16; + vinfo.red.length = 8; + vinfo.green.offset = 8; + vinfo.green.length = 8; + vinfo.blue.offset = 0; + vinfo.blue.length = 8; + vinfo.transp.offset = 0; + vinfo.transp.length = 0; + + /* + * Almost all framebuffers support off screen rendering. + * The code bellow requests Framebuffer to allocate memory equals to three + * buffers each of which width*height size. While the first drawn + * framebuffer's area is displaying the second or the third is redrawing + * or compositing by some application. When timer was expired or vblank + * was received Framebufer's areas swap, thus the second or the third is + * displaying and first is redrawing or compositing. Simple representation + * of what was said bellow + * + * SWAP Event SWAP Event + * | | + * +-------------+ | +-------------+ | +-------------+ + * | | | | | | | Redrawing | + * | Displaying | | | queued | | | or | + * | | | | | | | Compositing | + * +-------------+ | +-------------+ | +-------------+ + * | Redrawing | | | | | | | + * | or | +-------> | Displaying | +--------> | queued | + * | Compositing | | | | | | | + * +-------------+ | +-------------+ | +-------------+ + * | | | | Redrawing | | | | + * | queued | | | or | | | Displaying | + * | | | | Compositing | | | | + * +-------------+ | +-------------+ | +-------------+ + * | | + */ + vinfo.yres_virtual = vinfo.yres * MAX_BUF; + + ret = ioctl(fbdev_data->fbdev_fd, FBIOPAN_DISPLAY, vinfo); + if(ret < 0) + { + TDM_INFO("page flip not supported, errno=%d", errno); + vinfo.yres_virtual = vinfo.yres; + + /* + * TODO: Does FBIOPAN_DISPLAY ioctl must be invoked for the second time? + */ + ret = ioctl(fbdev_data->fbdev_fd, FBIOPAN_DISPLAY, vinfo); + if(ret < 0) + { + TDM_ERR("FBIOPAN_DISPLAY ioctl failed, errno=%d", errno); + goto close_1; + } + } + + ret = ioctl(fbdev_data->fbdev_fd, FBIOGET_FSCREENINFO, finfo); + if (ret < 0) + { + TDM_ERR("FBIOGET_FSCREENINFO ioctl failed, errno=%d", errno); + goto close_1; + } + + if (finfo.smem_len <= 0) + { + TDM_ERR("Length of frame buffer mem less then 0"); + goto close_1; + } + + /* + * TODO: Size of framebuffer must be aligned to system page size before + * it is mapped + */ + fbdev_data->size = finfo.line_length * vinfo.yres * MAX_BUF; + + fbdev_data->vaddr = mmap(0, fbdev_data->size, PROT_READ|PROT_WRITE, + MAP_SHARED, fbdev_data->fbdev_fd, 0); + if (fbdev_data->vaddr == MAP_FAILED) + { + TDM_ERR("MMap framebuffer failed, errno=%d", errno); + goto close_1; + } + + memset(fbdev_data->vaddr, 0, fbdev_data->size); + + /* + * Output framebuffer's related information + */ + TDM_INFO("\n" + " VInfo\n" + " fb = %d\n" + " xres = %d px \n" + " yres = %d px \n" + " xres_virtual = %d px \n" + " yres_virtual = %d px \n" + " bpp = %d \n" + " r = %2u:%u\n" + " g = %2u:%u\n" + " b = %2u:%u\n" + " t = %2u:%u\n" + " active = %d \n" + " width = %d mm \n" + " height = %d mm \n", + fbdev_data->fbdev_fd, + vinfo.xres, + vinfo.yres, + vinfo.xres_virtual, + vinfo.yres_virtual, + vinfo.bits_per_pixel, + vinfo.red.offset, vinfo.red.length, + vinfo.green.offset, vinfo.green.length, + vinfo.blue.offset, vinfo.blue.length, + vinfo.transp.offset, vinfo.transp.length, + vinfo.activate, + vinfo.width, + vinfo.height); + + TDM_INFO("\n" + " FInfo\n" + " id = %s\n" + " smem_len = %d\n" + " line_length = %d\n", + finfo.id, + finfo.smem_len, + finfo.line_length); + + return TDM_ERROR_NONE; +close_1: + ret = TDM_ERROR_OPERATION_FAILED; + return ret; +} void tdm_fbdev_deinit(tdm_backend_data *bdata) { + if (fbdev_data != bdata) + return; + + TDM_INFO("deinit"); + close(fbdev_data->fbdev_fd); + + free(fbdev_data); + fbdev_data = NULL; } tdm_backend_data* tdm_fbdev_init(tdm_display *dpy, tdm_error *error) { - (void) fbdev_func_display; + tdm_error ret; + if (!dpy) + { + TDM_ERR("display is null"); + if(error) + *error = TDM_ERROR_BAD_REQUEST; + return NULL; + } + + if(fbdev_data) + { + TDM_ERR("failed: init twice"); + if(error) + *error = TDM_ERROR_BAD_REQUEST; + return NULL; + } + + fbdev_data = calloc(1, sizeof(fbdev_data)); + if (!fbdev_data) + { + TDM_ERR("alloc failed"); + if(error) + *error = TDM_ERROR_OUT_OF_MEMORY; + return NULL; + } + + ret = tdm_backend_register_func_display(dpy, &fbdev_func_display); + if (ret != TDM_ERROR_NONE) + goto failed; + + fbdev_data->dpy = dpy; + + /* + * TODO: does somebody open framebuffer device beside us? + */ + fbdev_data->fbdev_fd = _tdm_fbdev_open_fbdev(); + if(fbdev_data->fbdev_fd < 0) + { + ret = TDM_ERROR_OPERATION_FAILED; + goto failed; + } + + ret = _tdm_fbdev_init_internal(); + if(ret != TDM_ERROR_NONE) + { + TDM_INFO("init of framebuffer failed"); + goto failed; + } + + + TDM_INFO("init success!"); + + if(error) + *error = TDM_ERROR_NONE; + + return (tdm_backend_data*)fbdev_data; + +failed: + if(error) + *error = ret; + + tdm_fbdev_deinit(fbdev_data); + TDM_ERR("init failed!"); return NULL; } tdm_backend_module tdm_backend_module_data = { - "vigs", + "fbdev", "Samsung", TDM_BACKEND_ABI_VERSION, tdm_fbdev_init, diff --git a/src/tdm_fbdev.h b/src/tdm_fbdev.h index a2c05fd..c57a513 100644 --- a/src/tdm_fbdev.h +++ b/src/tdm_fbdev.h @@ -11,14 +11,19 @@ #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> +#include <sys/mman.h> #include <fcntl.h> +#include <linux/fb.h> + #include <tbm_surface.h> #include <tbm_surface_internal.h> #include <tdm_backend.h> #include <tdm_log.h> #include <tdm_list.h> +#define MAX_BUF 3 + /* drm backend functions (display) */ tdm_error fbdev_display_get_capabilitiy(tdm_backend_data *bdata, tdm_caps_display *caps); tdm_output** fbdev_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error); @@ -45,4 +50,18 @@ tdm_error fbdev_layer_get_info(tdm_layer *layer, tdm_info_layer *info); tdm_error fbdev_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer); tdm_error fbdev_layer_unset_buffer(tdm_layer *layer); +typedef struct _tdm_fbdev_data +{ + int fbdev_fd; + + tdm_display *dpy; + + struct fb_fix_screeninfo finfo; + struct fb_var_screeninfo vinfo; + + void *vaddr; + size_t size; +}tdm_fbdev_data; + + #endif /* _TDM_fbdev_H_ */ |