summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Peresipkyn <r.peresipkyn@samsung.com>2016-01-29 16:51:19 +0200
committerSooChan Lim <sc1.lim@samsung.com>2016-03-07 19:51:49 +0900
commita8dcfe8f34c5bfa259a327c4373534bdfeeff40a (patch)
treeb349a936c2cf428a71070bc18075b6d20ec15595
parent2af0591c13028a975a75d467e1c005eab0141830 (diff)
downloadlibtdm-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.c259
-rw-r--r--src/tdm_fbdev.h19
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_ */