+ close(bufmgr_exynos->tgl_fd);
+ return 0;
+ }
+ }
+
+ if (!_tgl_init(bufmgr_exynos->tgl_fd, GLOBAL_KEY)) {
+ TBM_EXYNOS_LOG("[libtbm-exynos:%d] "
+ "error: Fail to initialize the tgl\n",
+ getpid());
+
+ close(bufmgr_exynos->tgl_fd);
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+
+static void
+_bufmgr_deinit_cache_state(tbm_bufmgr_exynos bufmgr_exynos)
+{
+#ifdef ENABLE_CACHECRTL
+ EXYNOS_RETURN_IF_FAIL(bufmgr_exynos != NULL);
+
+ if (bufmgr_exynos->use_dma_fence)
+ return;
+
+ if (bufmgr_exynos->tgl_fd >= 0)
+ close(bufmgr_exynos->tgl_fd);
+#endif
+}
+
+static int
+_tbm_exynos_open_drm()
+{
+ int fd = -1;
+
+ fd = drmOpen(EXYNOS_DRM_NAME, NULL);
+ if (fd < 0) {
+ TBM_EXYNOS_LOG ("[libtbm-exynos:%d] "
+ "warning %s:%d fail to open drm\n",
+ getpid(), __FUNCTION__, __LINE__);
+ }
+
+ if (fd < 0) {
+ struct udev *udev = NULL;
+ struct udev_enumerate *e = NULL;
+ struct udev_list_entry *entry = NULL;
+ struct udev_device *device = NULL, *drm_device = NULL, *device_parent = NULL;
+ const char *filepath;
+ struct stat s;
+ int fd = -1;
+ int ret;
+
+ TBM_EXYNOS_LOG ("[libtbm-exynos:%d] "
+ "%s:%d search drm-device by udev\n",
+ getpid(), __FUNCTION__, __LINE__);
+
+ udev = udev_new();
+ if (!udev) {
+ TBM_EXYNOS_LOG("udev_new() failed.\n");
+ return -1;
+ }
+
+ e = udev_enumerate_new(udev);
+ udev_enumerate_add_match_subsystem(e, "drm");
+ udev_enumerate_add_match_sysname(e, "card[0-9]*");
+ udev_enumerate_scan_devices(e);
+
+ udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
+ device = udev_device_new_from_syspath(udev_enumerate_get_udev(e),
+ udev_list_entry_get_name(entry));
+ device_parent = udev_device_get_parent(device);
+ /* Not need unref device_parent. device_parent and device have same refcnt */
+ if (device_parent) {
+ if (strcmp(udev_device_get_sysname(device_parent), "exynos-drm") == 0) {
+ drm_device = device;
+ DBG("[%s] Found render device: '%s' (%s)\n",
+ target_name(),
+ udev_device_get_syspath(drm_device),
+ udev_device_get_sysname(device_parent));
+ break;
+ }
+ }
+ udev_device_unref(device);
+ }
+
+ udev_enumerate_unref(e);
+
+ /* Get device file path. */
+ filepath = udev_device_get_devnode(drm_device);
+ if (!filepath) {
+ TBM_EXYNOS_LOG("udev_device_get_devnode() failed.\n");
+ udev_device_unref(drm_device);
+ udev_unref(udev);
+ return -1;
+ }
+
+ /* Open DRM device file and check validity. */
+ fd = open(filepath, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ TBM_EXYNOS_LOG("open(%s, O_RDWR | O_CLOEXEC) failed.\n");
+ udev_device_unref(drm_device);
+ udev_unref(udev);
+ return -1;
+ }
+
+ ret = fstat(fd, &s);
+ if (ret) {
+ TBM_EXYNOS_LOG("fstat() failed %s.\n");
+ udev_device_unref(drm_device);
+ udev_unref(udev);
+ return -1;
+ }
+
+ udev_device_unref(drm_device);
+ udev_unref(udev);
+ }
+
+ return fd;
+}
+
+static int
+_check_render_node(void)
+{
+ struct udev *udev = NULL;
+ struct udev_enumerate *e = NULL;
+ struct udev_list_entry *entry = NULL;
+ struct udev_device *device = NULL, *drm_device = NULL, *device_parent = NULL;
+
+ udev = udev_new();
+ if (!udev) {
+ TBM_EXYNOS_LOG("udev_new() failed.\n");
+ return -1;
+ }
+
+ e = udev_enumerate_new(udev);
+ udev_enumerate_add_match_subsystem(e, "drm");
+ udev_enumerate_add_match_sysname(e, "renderD[0-9]*");
+ udev_enumerate_scan_devices(e);
+
+ udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
+ device = udev_device_new_from_syspath(udev_enumerate_get_udev(e),
+ udev_list_entry_get_name(entry));
+ device_parent = udev_device_get_parent(device);
+ /* Not need unref device_parent. device_parent and device have same refcnt */
+ if (device_parent) {
+ if (strcmp(udev_device_get_sysname(device_parent), "exynos-drm") == 0) {
+ drm_device = device;
+ DBG("[%s] Found render device: '%s' (%s)\n",
+ target_name(),
+ udev_device_get_syspath(drm_device),
+ udev_device_get_sysname(device_parent));
+ break;
+ }
+ }
+ udev_device_unref(device);
+ }
+
+ udev_enumerate_unref(e);
+ udev_unref(udev);
+
+ if (!drm_device) {
+ udev_device_unref(drm_device);
+ return 0;
+ }
+
+ udev_device_unref(drm_device);
+ return 1;
+}
+
+static int
+_get_render_node(void)
+{
+ struct udev *udev = NULL;
+ struct udev_enumerate *e = NULL;
+ struct udev_list_entry *entry = NULL;
+ struct udev_device *device = NULL, *drm_device = NULL, *device_parent = NULL;
+ const char *filepath;
+ struct stat s;
+ int fd = -1;
+ int ret;
+
+ udev = udev_new();
+ if (!udev) {
+ TBM_EXYNOS_LOG("udev_new() failed.\n");
+ return -1;
+ }
+
+ e = udev_enumerate_new(udev);
+ udev_enumerate_add_match_subsystem(e, "drm");
+ udev_enumerate_add_match_sysname(e, "renderD[0-9]*");
+ udev_enumerate_scan_devices(e);
+
+ udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
+ device = udev_device_new_from_syspath(udev_enumerate_get_udev(e),
+ udev_list_entry_get_name(entry));
+ device_parent = udev_device_get_parent(device);
+ /* Not need unref device_parent. device_parent and device have same refcnt */
+ if (device_parent) {
+ if (strcmp(udev_device_get_sysname(device_parent), "exynos-drm") == 0) {
+ drm_device = device;
+ DBG("[%s] Found render device: '%s' (%s)\n",
+ target_name(),
+ udev_device_get_syspath(drm_device),
+ udev_device_get_sysname(device_parent));
+ break;
+ }
+ }
+ udev_device_unref(device);
+ }
+
+ udev_enumerate_unref(e);
+
+ /* Get device file path. */
+ filepath = udev_device_get_devnode(drm_device);
+ if (!filepath) {
+ TBM_EXYNOS_LOG("udev_device_get_devnode() failed.\n");
+ udev_device_unref(drm_device);
+ udev_unref(udev);
+ return -1;
+ }
+
+ /* Open DRM device file and check validity. */
+ fd = open(filepath, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ TBM_EXYNOS_LOG("open(%s, O_RDWR | O_CLOEXEC) failed.\n");
+ udev_device_unref(drm_device);
+ udev_unref(udev);
+ return -1;
+ }
+
+ ret = fstat(fd, &s);
+ if (ret) {
+ TBM_EXYNOS_LOG("fstat() failed %s.\n");
+ udev_device_unref(drm_device);
+ udev_unref(udev);
+ close(fd);
+ return -1;
+ }
+
+ udev_device_unref(drm_device);
+ udev_unref(udev);
+
+ return fd;
+}
+
+static unsigned int
+_get_exynos_flag_from_tbm(unsigned int ftbm)
+{
+ unsigned int flags = 0;
+
+ if (ftbm & TBM_BO_SCANOUT)
+ flags |= EXYNOS_BO_CONTIG;
+ else
+ flags |= EXYNOS_BO_NONCONTIG;
+
+ if (ftbm & TBM_BO_WC)
+ flags |= EXYNOS_BO_WC;
+ else if (ftbm & TBM_BO_NONCACHABLE)
+ flags |= EXYNOS_BO_NONCACHABLE;
+ else
+ flags |= EXYNOS_BO_CACHABLE;
+
+ return flags;
+}
+
+static unsigned int
+_get_tbm_flag_from_exynos(unsigned int fexynos)
+{
+ unsigned int flags = 0;
+
+ if (fexynos & EXYNOS_BO_NONCONTIG)
+ flags |= TBM_BO_DEFAULT;
+ else
+ flags |= TBM_BO_SCANOUT;
+
+ if (fexynos & EXYNOS_BO_WC)
+ flags |= TBM_BO_WC;
+ else if (fexynos & EXYNOS_BO_CACHABLE)
+ flags |= TBM_BO_DEFAULT;
+ else
+ flags |= TBM_BO_NONCACHABLE;
+
+ return flags;
+}
+
+static unsigned int
+_get_name(int fd, unsigned int gem)
+{
+ struct drm_gem_flink arg = {0,};
+
+ arg.handle = gem;
+ if (drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &arg)) {
+ TBM_EXYNOS_LOG("error fail to get flink from gem:%d (DRM_IOCTL_GEM_FLINK)\n",
+ gem);
+ return 0;
+ }
+
+ return (unsigned int)arg.name;
+}
+
+static tbm_bo_handle
+_exynos_bo_handle(tbm_bo_exynos bo_exynos, int device)
+{
+ tbm_bo_handle bo_handle;
+
+ memset(&bo_handle, 0x0, sizeof(uint64_t));
+
+ switch (device) {
+ case TBM_DEVICE_DEFAULT:
+ case TBM_DEVICE_2D:
+ bo_handle.u32 = (uint32_t)bo_exynos->gem;
+ break;
+ case TBM_DEVICE_CPU:
+ if (!bo_exynos->pBase) {
+ struct drm_exynos_gem_map arg = {0,};
+ void *map = NULL;
+
+ arg.handle = bo_exynos->gem;
+ if (drmCommandWriteRead(bo_exynos->fd, DRM_EXYNOS_GEM_MAP, &arg,
+ sizeof(arg))) {
+ TBM_EXYNOS_LOG("error Cannot map_dumb gem=%d\n", bo_exynos->gem);
+ return (tbm_bo_handle) NULL;
+ }
+
+ map = mmap(NULL, bo_exynos->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ bo_exynos->fd, arg.offset);
+ if (map == MAP_FAILED) {
+ TBM_EXYNOS_LOG("error Cannot usrptr gem=%d\n", bo_exynos->gem);
+ return (tbm_bo_handle) NULL;
+ }
+ bo_exynos->pBase = map;
+ }
+ bo_handle.ptr = (void *)bo_exynos->pBase;
+ break;
+ case TBM_DEVICE_3D:
+#ifdef USE_DMAIMPORT
+ if (bo_exynos->dmabuf) {
+ bo_handle.u32 = (uint32_t)bo_exynos->dmabuf;
+ break;
+ }
+
+ if (!bo_exynos->dmabuf) {
+ struct drm_prime_handle arg = {0, };
+
+ arg.handle = bo_exynos->gem;
+ if (drmIoctl(bo_exynos->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
+ TBM_EXYNOS_LOG("error Cannot dmabuf=%d\n", bo_exynos->gem);
+ return (tbm_bo_handle) NULL;
+ }
+ bo_exynos->dmabuf = arg.fd;
+ }
+
+ bo_handle.u32 = (uint32_t)bo_exynos->dmabuf;
+#endif
+ break;
+ case TBM_DEVICE_MM:
+ if (!bo_exynos->dmabuf) {
+ struct drm_prime_handle arg = {0, };
+
+ arg.handle = bo_exynos->gem;
+ if (drmIoctl(bo_exynos->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
+ TBM_EXYNOS_LOG("error Cannot dmabuf=%d\n", bo_exynos->gem);
+ return (tbm_bo_handle) NULL;
+ }
+ bo_exynos->dmabuf = arg.fd;
+ }
+
+ bo_handle.u32 = (uint32_t)bo_exynos->dmabuf;
+ break;
+ default:
+ TBM_EXYNOS_LOG("error Not supported device:%d\n", device);
+ bo_handle.ptr = (void *) NULL;
+ break;
+ }
+
+ return bo_handle;
+}
+
+static int
+tbm_exynos_bo_size(tbm_bo bo)
+{
+ EXYNOS_RETURN_VAL_IF_FAIL(bo != NULL, 0);
+
+ tbm_bo_exynos bo_exynos;
+
+ bo_exynos = (tbm_bo_exynos)tbm_backend_get_bo_priv(bo);
+ EXYNOS_RETURN_VAL_IF_FAIL(bo_exynos != NULL, 0);
+
+ return bo_exynos->size;