1 /**************************************************************************
5 Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
43 #include <sys/ioctl.h>
44 #include <sys/types.h>
51 #include <tbm_bufmgr.h>
52 #include <tbm_bufmgr_backend.h>
53 #include <drm/sprd_drm.h>
55 #include <tbm_surface.h>
56 #include <tbm_drm_helper.h>
59 #include "tbm_bufmgr_tgl.h"
61 //#define USE_CONTIG_ONLY
64 #define TBM_COLOR_FORMAT_COUNT 4
67 #define LOG_TAG "TBM_BACKEND"
69 static int bDebug = 0;
71 #define SPRD_DRM_NAME "sprd"
76 static char app_name[128] = {0, };
77 static int initialized = 0;
84 /* get the application name */
85 f = fopen("/proc/self/cmdline", "r");
89 if (fgets(app_name, 100, f) == NULL) {
96 slash = strrchr(app_name, '/');
98 memmove(app_name, slash + 1, strlen(slash));
104 #define TBM_SPRD_LOG(fmt, args...) LOGE("\033[31m" "[%s]" fmt "\033[0m", _target_name(), ##args)
105 #define DBG(fmt, args...) if (bDebug&01) LOGE("[%s]" fmt, _target_name(), ##args)
107 #define TBM_SPRD_LOG(...)
111 #define SIZE_ALIGN(value, base) (((value) + ((base) - 1)) & ~((base) - 1))
113 #define TBM_SURFACE_ALIGNMENT_PLANE (64)
114 #define TBM_SURFACE_ALIGNMENT_PITCH_RGB (128)
115 #define TBM_SURFACE_ALIGNMENT_PITCH_YUV (16)
118 /* check condition */
119 #define SPRD_RETURN_IF_FAIL(cond) {\
121 TBM_SPRD_LOG("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
125 #define SPRD_RETURN_VAL_IF_FAIL(cond, val) {\
127 TBM_SPRD_LOG("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
132 struct dma_buf_info {
134 unsigned int fence_supported;
135 unsigned int padding;
138 #define DMA_BUF_ACCESS_READ 0x1
139 #define DMA_BUF_ACCESS_WRITE 0x2
140 #define DMA_BUF_ACCESS_DMA 0x4
141 #define DMA_BUF_ACCESS_MAX 0x8
143 #define DMA_FENCE_LIST_MAX 5
145 struct dma_buf_fence {
150 #define DMABUF_IOCTL_BASE 'F'
151 #define DMABUF_IOWR(nr, type) _IOWR(DMABUF_IOCTL_BASE, nr, type)
153 #define DMABUF_IOCTL_GET_INFO DMABUF_IOWR(0x00, struct dma_buf_info)
154 #define DMABUF_IOCTL_GET_FENCE DMABUF_IOWR(0x01, struct dma_buf_fence)
155 #define DMABUF_IOCTL_PUT_FENCE DMABUF_IOWR(0x02, struct dma_buf_fence)
158 #define GLOBAL_KEY ((unsigned int)(-1))
160 #define TBM_SPRD_CACHE_INV 0x01 /**< cache invalidate */
161 #define TBM_SPRD_CACHE_CLN 0x02 /**< cache clean */
162 #define TBM_SPRD_CACHE_ALL 0x10 /**< cache all */
163 #define TBM_SPRD_CACHE_FLUSH (TBM_SPRD_CACHE_INV|TBM_SPRD_CACHE_CLN) /**< cache flush */
164 #define TBM_SPRD_CACHE_FLUSH_ALL (TBM_SPRD_CACHE_FLUSH|TBM_SPRD_CACHE_ALL) /**< cache flush all */
168 DEVICE_CA, /* cache aware device */
169 DEVICE_CO /* cache oblivious device */
172 typedef union _tbm_bo_cache_state tbm_bo_cache_state;
174 union _tbm_bo_cache_state {
177 unsigned int cntFlush:16; /*Flush all index for sync */
178 unsigned int isCached:1;
179 unsigned int isDirtied:2;
183 typedef struct _tbm_bufmgr_sprd *tbm_bufmgr_sprd;
184 typedef struct _tbm_bo_sprd *tbm_bo_sprd;
186 typedef struct _sprd_private {
188 struct _tbm_bo_sprd *bo_priv;
191 /* tbm buffor object for sprd */
192 struct _tbm_bo_sprd {
195 unsigned int name; /* FLINK ID */
197 unsigned int gem; /* GEM Handle */
199 unsigned int dmabuf; /* fd for dmabuf */
201 void *pBase; /* virtual address */
205 unsigned int flags_sprd;
206 unsigned int flags_tbm;
210 pthread_mutex_t mutex;
211 struct dma_buf_fence dma_fence[DMA_FENCE_LIST_MAX];
215 tbm_bo_cache_state cache_state;
216 unsigned int map_cnt;
219 /* tbm bufmgr private for sprd */
220 struct _tbm_bufmgr_sprd {
232 char *STR_DEVICE[] = {
248 uint32_t tbm_sprd_color_format_list[TBM_COLOR_FORMAT_COUNT] = {
256 _tgl_init(int fd, unsigned int key)
258 struct tgl_attribute attr;
262 attr.timeout_ms = 1000;
264 err = ioctl(fd, TGL_IOC_INIT_LOCK, &attr);
266 TBM_SPRD_LOG("[libtbm-sprd:%d] error(%s) %s:%d key:%d\n",
267 getpid(), strerror(errno), __func__, __LINE__, key);
275 _tgl_destroy(int fd, unsigned int key)
279 err = ioctl(fd, TGL_IOC_DESTROY_LOCK, key);
281 TBM_SPRD_LOG("[libtbm-sprd:%d] "
282 "error(%s) %s:%d key:%d\n",
283 getpid(), strerror(errno), __func__, __LINE__, key);
291 _tgl_lock(int fd, unsigned int key)
295 err = ioctl(fd, TGL_IOC_LOCK_LOCK, key);
297 TBM_SPRD_LOG("[libtbm-sprd:%d] "
298 "error(%s) %s:%d key:%d\n",
299 getpid(), strerror(errno), __func__, __LINE__, key);
307 _tgl_unlock(int fd, unsigned int key)
311 err = ioctl(fd, TGL_IOC_UNLOCK_LOCK, key);
313 TBM_SPRD_LOG("[libtbm-sprd:%d] "
314 "error(%s) %s:%d key:%d\n",
315 getpid(), strerror(errno), __func__, __LINE__, key);
324 _tgl_set_data(int fd, unsigned int key, unsigned int val)
327 struct tgl_user_data arg;
331 err = ioctl(fd, TGL_IOC_SET_DATA, &arg);
333 TBM_SPRD_LOG("[libtbm-sprd:%d] "
334 "error(%s) %s:%d key:%d\n",
335 getpid(), strerror(errno), __func__, __LINE__, key);
342 static inline unsigned int
343 _tgl_get_data(int fd, unsigned int key, unsigned int *locked)
346 struct tgl_user_data arg = { 0, };
349 err = ioctl(fd, TGL_IOC_GET_DATA, &arg);
351 TBM_SPRD_LOG("[libtbm-sprd:%d] "
352 "error(%s) %s:%d key:%d\n",
353 getpid(), strerror(errno), __func__, __LINE__, key);
358 *locked = arg.locked;
365 _tbm_sprd_open_drm(void)
368 struct udev_device *drm_device = NULL;
369 struct udev_list_entry *entry = NULL;
370 struct udev_enumerate *e;
371 const char *filepath;
377 fd = drmOpen(SPRD_DRM_NAME, NULL);
382 TBM_SPRD_LOG("[libtbm-sprd:%d] warning %s:%d fail to open drm, "
383 "so search drm-device by udev\n",
384 getpid(), __FUNCTION__, __LINE__);
388 TBM_SPRD_LOG("udev_new() failed.\n");
392 e = udev_enumerate_new(udev);
393 udev_enumerate_add_match_subsystem(e, "drm");
394 udev_enumerate_add_match_sysname(e, "card[0-9]*");
395 udev_enumerate_scan_devices(e);
397 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
398 struct udev_device *device, *device_parent;
400 device = udev_device_new_from_syspath(udev_enumerate_get_udev(e),
401 udev_list_entry_get_name(entry));
402 device_parent = udev_device_get_parent(device);
403 /* Not need unref device_parent. device_parent and device have same refcnt */
405 if (strcmp(udev_device_get_sysname(device_parent), "sprd-drm") == 0) {
407 DBG("[%s] Found render device: '%s' (%s)\n",
409 udev_device_get_syspath(drm_device),
410 udev_device_get_sysname(device_parent));
414 udev_device_unref(device);
417 udev_enumerate_unref(e);
419 /* Get device file path. */
420 filepath = udev_device_get_devnode(drm_device);
422 TBM_SPRD_LOG("udev_device_get_devnode() failed.\n");
423 udev_device_unref(drm_device);
428 udev_device_unref(drm_device);
431 /* Open DRM device file and check validity. */
432 fd = open(filepath, O_RDWR | O_CLOEXEC);
434 TBM_SPRD_LOG("open(%s, O_RDWR | O_CLOEXEC) failed.\n");
439 TBM_SPRD_LOG("fstat() failed %s.\n");
444 TBM_SPRD_LOG("[libtbm-sprd:%d] warning %s:%d fail to open drm\n",
445 getpid(), __FUNCTION__, __LINE__);
453 _sprd_bo_cache_flush(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int flags)
455 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
457 /* cache flush is managed by kernel side when using dma-fence. */
458 if (bufmgr_sprd->use_dma_fence)
461 struct drm_sprd_gem_cache_op cache_op = {0, };
464 /* if bo_sprd is null, do cache_flush_all */
467 cache_op.usr_addr = (uint64_t)((uint32_t)bo_sprd->pBase);
468 cache_op.size = bo_sprd->size;
470 flags = TBM_SPRD_CACHE_FLUSH_ALL;
472 cache_op.usr_addr = 0;
476 if (flags & TBM_SPRD_CACHE_INV) {
477 if (flags & TBM_SPRD_CACHE_ALL)
478 cache_op.flags |= SPRD_DRM_CACHE_INV_ALL;
480 cache_op.flags |= SPRD_DRM_CACHE_INV_RANGE;
483 if (flags & TBM_SPRD_CACHE_CLN) {
484 if (flags & TBM_SPRD_CACHE_ALL)
485 cache_op.flags |= SPRD_DRM_CACHE_CLN_ALL;
487 cache_op.flags |= SPRD_DRM_CACHE_CLN_RANGE;
490 if (flags & TBM_SPRD_CACHE_ALL)
491 cache_op.flags |= SPRD_DRM_ALL_CACHES_CORES;
493 ret = drmCommandWriteRead(bufmgr_sprd->fd, DRM_SPRD_GEM_CACHE_OP, &cache_op,
496 TBM_SPRD_LOG("[libtbm-sprd:%d] "
497 "error %s:%d fail to flush the cache.\n",
498 getpid(), __FUNCTION__, __LINE__);
507 _bo_init_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int import)
509 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
510 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
512 if (bufmgr_sprd->use_dma_fence)
515 _tgl_init(bufmgr_sprd->tgl_fd, bo_sprd->name);
518 tbm_bo_cache_state cache_state;
521 cache_state.data.isDirtied = DEVICE_NONE;
522 cache_state.data.isCached = 0;
523 cache_state.data.cntFlush = 0;
525 _tgl_set_data(bufmgr_sprd->tgl_fd, bo_sprd->name, cache_state.val);
533 _bo_set_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int device, int opt)
536 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
537 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
540 unsigned short cntFlush = 0;
542 if (bufmgr_sprd->use_dma_fence)
545 if (bo_sprd->flags_sprd & SPRD_BO_NONCACHABLE)
548 /* get cache state of a bo */
549 bo_sprd->cache_state.val = _tgl_get_data(bufmgr_sprd->tgl_fd, bo_sprd->name, NULL);
551 /* get global cache flush count */
552 cntFlush = (unsigned short)_tgl_get_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, NULL);
554 if (opt == TBM_DEVICE_CPU) {
555 if (bo_sprd->cache_state.data.isDirtied == DEVICE_CO &&
556 bo_sprd->cache_state.data.isCached)
557 need_flush = TBM_SPRD_CACHE_INV;
559 bo_sprd->cache_state.data.isCached = 1;
560 if (opt & TBM_OPTION_WRITE)
561 bo_sprd->cache_state.data.isDirtied = DEVICE_CA;
563 if (bo_sprd->cache_state.data.isDirtied != DEVICE_CA)
564 bo_sprd->cache_state.data.isDirtied = DEVICE_NONE;
567 if (bo_sprd->cache_state.data.isDirtied == DEVICE_CA &&
568 bo_sprd->cache_state.data.isCached &&
569 bo_sprd->cache_state.data.cntFlush == cntFlush)
570 need_flush = TBM_SPRD_CACHE_CLN | TBM_SPRD_CACHE_ALL;
572 if (opt & TBM_OPTION_WRITE)
573 bo_sprd->cache_state.data.isDirtied = DEVICE_CO;
575 if (bo_sprd->cache_state.data.isDirtied != DEVICE_CO)
576 bo_sprd->cache_state.data.isDirtied = DEVICE_NONE;
581 if (need_flush & TBM_SPRD_CACHE_ALL)
582 _tgl_set_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, (unsigned int)(++cntFlush));
584 /* call cache flush */
585 _sprd_bo_cache_flush(bufmgr_sprd, bo_sprd, need_flush);
587 DBG("[libtbm:%d] \tcache(%d,%d)....flush:0x%x, cntFlush(%d)\n",
589 bo_sprd->cache_state.data.isCached,
590 bo_sprd->cache_state.data.isDirtied,
600 _bo_save_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd)
603 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
604 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
606 if (bufmgr_sprd->use_dma_fence)
609 unsigned short cntFlush = 0;
611 /* get global cache flush count */
612 cntFlush = (unsigned short)_tgl_get_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, NULL);
614 /* save global cache flush count */
615 bo_sprd->cache_state.data.cntFlush = cntFlush;
616 _tgl_set_data(bufmgr_sprd->tgl_fd, bo_sprd->name, bo_sprd->cache_state.val);
623 _bo_destroy_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd)
625 SPRD_RETURN_IF_FAIL(bo_sprd != NULL);
626 SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
628 if (bufmgr_sprd->use_dma_fence)
631 _tgl_destroy(bufmgr_sprd->tgl_fd, bo_sprd->name);
635 _bufmgr_init_cache_state(tbm_bufmgr_sprd bufmgr_sprd)
637 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
639 if (bufmgr_sprd->use_dma_fence)
642 /* open tgl fd for saving cache flush data */
643 bufmgr_sprd->tgl_fd = open(tgl_devfile, O_RDWR);
645 if (bufmgr_sprd->tgl_fd < 0) {
646 bufmgr_sprd->tgl_fd = open(tgl_devfile1, O_RDWR);
647 if (bufmgr_sprd->tgl_fd < 0) {
648 TBM_SPRD_LOG("[libtbm-sprd:%d] "
649 "error: Fail to open global_lock:%s\n",
650 getpid(), tgl_devfile);
656 if (!_tgl_init(bufmgr_sprd->tgl_fd, GLOBAL_KEY)) {
657 TBM_SPRD_LOG("[libtbm-sprd:%d] "
658 "error: Fail to initialize the tgl\n",
661 close(bufmgr_sprd->tgl_fd);
670 _bufmgr_deinit_cache_state(tbm_bufmgr_sprd bufmgr_sprd)
672 SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
674 if (bufmgr_sprd->use_dma_fence)
677 if (bufmgr_sprd->tgl_fd >= 0)
678 close(bufmgr_sprd->tgl_fd);
681 #ifndef USE_CONTIG_ONLY
683 _get_sprd_flag_from_tbm(unsigned int ftbm)
685 unsigned int flags = 0;
688 * TBM_BO_DEFAULT => ION_HEAP_ID_MASK_SYSTEM
689 * TBM_BO_SCANOUT => ION_HEAP_ID_MASK_MM
690 * TBM_BO_VENDOR => ION_HEAP_ID_MASK_OVERLAY
691 * To be updated appropriately once DRM-GEM supports different heap id masks.
694 if (ftbm & TBM_BO_SCANOUT)
695 flags = SPRD_BO_CONTIG;
697 flags = SPRD_BO_NONCONTIG | SPRD_BO_DEV_SYSTEM;
699 if (ftbm & TBM_BO_WC)
701 else if (ftbm & TBM_BO_NONCACHABLE)
702 flags |= SPRD_BO_NONCACHABLE;
708 _get_tbm_flag_from_sprd(unsigned int fsprd)
710 unsigned int flags = 0;
712 if (fsprd & SPRD_BO_NONCONTIG)
713 flags |= TBM_BO_DEFAULT;
715 flags |= TBM_BO_SCANOUT;
717 if (fsprd & SPRD_BO_WC)
719 else if (fsprd & SPRD_BO_CACHABLE)
720 flags |= TBM_BO_DEFAULT;
722 flags |= TBM_BO_NONCACHABLE;
729 _get_name(int fd, unsigned int gem)
731 struct drm_gem_flink arg = {0,};
734 if (drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &arg)) {
735 TBM_SPRD_LOG("[libtbm-sprd:%d] "
736 "error %s:%d fail to get flink gem=%d\n",
737 getpid(), __FUNCTION__, __LINE__, gem);
741 return (unsigned int)arg.name;
745 _sprd_bo_handle(tbm_bo_sprd bo_sprd, int device)
747 tbm_bo_handle bo_handle;
748 memset(&bo_handle, 0x0, sizeof(uint64_t));
751 case TBM_DEVICE_DEFAULT:
753 bo_handle.u32 = (uint32_t)bo_sprd->gem;
756 if (!bo_sprd->pBase) {
757 struct drm_sprd_gem_mmap arg = {0,};
759 arg.handle = bo_sprd->gem;
760 arg.size = bo_sprd->size;
761 if (drmCommandWriteRead(bo_sprd->fd, DRM_SPRD_GEM_MMAP, &arg, sizeof(arg))) {
762 TBM_SPRD_LOG("[libtbm-sprd:%d] "
763 "error %s:%d Cannot usrptr gem=%d\n",
764 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
765 return (tbm_bo_handle) NULL;
767 bo_sprd->pBase = (void *)((uint32_t)arg.mapped);
770 bo_handle.ptr = (void *)bo_sprd->pBase;
774 if (!bo_sprd->dmabuf) {
775 struct drm_prime_handle arg = {0, };
776 arg.handle = bo_sprd->gem;
777 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
778 TBM_SPRD_LOG("[libtbm-sprd:%d] "
779 "error %s:%d Cannot dmabuf=%d\n",
780 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
781 return (tbm_bo_handle) NULL;
783 bo_sprd->dmabuf = arg.fd;
786 bo_handle.u32 = (uint32_t)bo_sprd->dmabuf;
793 //TODO : Add ioctl for GSP MAP once available.
794 DBG("[libtbm-sprd:%d] %s In case TBM_DEVICE_MM: \n", getpid(),
799 if (!bo_sprd->dmabuf) {
800 struct drm_prime_handle arg = {0, };
802 arg.handle = bo_sprd->gem;
803 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
804 TBM_SPRD_LOG("[libtbm-sprd:%d] "
805 "error %s:%d Cannot dmabuf=%d\n",
806 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
807 return (tbm_bo_handle) NULL;
809 bo_sprd->dmabuf = arg.fd;
812 bo_handle.u32 = (uint32_t)bo_sprd->dmabuf;
816 bo_handle.ptr = (void *) NULL;
824 tbm_sprd_bo_size(tbm_bo bo)
826 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
830 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
831 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
833 return bo_sprd->size;
837 tbm_sprd_bo_alloc(tbm_bo bo, int size, int flags)
839 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
841 tbm_bufmgr_sprd bufmgr_sprd;
842 unsigned int sprd_flags;
845 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
846 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
848 bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
850 TBM_SPRD_LOG("[libtbm-sprd:%d] "
851 "error %s:%d fail to allocate the bo private\n",
852 getpid(), __FUNCTION__, __LINE__);
856 #ifdef USE_CONTIG_ONLY
857 flags = TBM_BO_SCANOUT;
858 sprd_flags = SPRD_BO_CONTIG;
860 sprd_flags = _get_sprd_flag_from_tbm(flags);
861 if ((flags & TBM_BO_SCANOUT) && (size <= 4 * 1024))
862 sprd_flags |= SPRD_BO_NONCONTIG;
863 #endif // USE_CONTIG_ONLY
865 struct drm_sprd_gem_create arg = {0, };
866 arg.size = (uint64_t)size;
867 arg.flags = sprd_flags;
868 if (drmCommandWriteRead(bufmgr_sprd->fd, DRM_SPRD_GEM_CREATE, &arg,
870 TBM_SPRD_LOG("[libtbm-sprd:%d] "
871 "error %s:%d Cannot create bo(flag:%x, size:%d)\n",
872 getpid(), __FUNCTION__, __LINE__, arg.flags, (unsigned int)arg.size);
877 bo_sprd->fd = bufmgr_sprd->fd;
878 bo_sprd->gem = arg.handle;
879 bo_sprd->size = size;
880 bo_sprd->flags_tbm = flags;
881 bo_sprd->flags_sprd = sprd_flags;
882 bo_sprd->name = _get_name(bo_sprd->fd, bo_sprd->gem);
884 if (!_bo_init_cache_state(bufmgr_sprd, bo_sprd, 0)) {
885 TBM_SPRD_LOG("error fail init cache state(%d)\n", bo_sprd->name);
890 pthread_mutex_init(&bo_sprd->mutex, NULL);
892 if (bufmgr_sprd->use_dma_fence
893 && !bo_sprd->dmabuf) {
894 struct drm_prime_handle arg = {0, };
896 arg.handle = bo_sprd->gem;
897 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
898 TBM_SPRD_LOG("[libtbm-sprd:%d] "
899 "error %s:%d Cannot dmabuf=%d\n",
900 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
904 bo_sprd->dmabuf = arg.fd;
908 PrivGem *privGem = calloc(1, sizeof(PrivGem));
910 TBM_SPRD_LOG("[libtbm-sprd:%d] "
911 "error %s:%d Fail to calloc PrivGem\n",
912 getpid(), __FUNCTION__, __LINE__);
917 privGem->ref_count = 1;
918 privGem->bo_priv = bo_sprd;
919 if (drmHashInsert(bufmgr_sprd->hashBos, bo_sprd->name, (void *)privGem) < 0) {
920 TBM_SPRD_LOG("[libtbm-sprd:%d] "
921 "error %s:%d Cannot insert bo to Hash(%d)\n",
922 getpid(), __FUNCTION__, __LINE__, bo_sprd->name);
925 DBG("[libtbm-sprd:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
926 __FUNCTION__, bo_sprd->size,
927 bo_sprd->gem, bo_sprd->name,
930 return (void *)bo_sprd;
934 tbm_sprd_bo_free(tbm_bo bo)
937 tbm_bufmgr_sprd bufmgr_sprd;
942 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
943 SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
945 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
946 SPRD_RETURN_IF_FAIL(bo_sprd != NULL);
948 DBG("[libtbm-sprd:%d] %s size:%d, gem:%d(%d)\n",
949 getpid(), __FUNCTION__, bo_sprd->size, bo_sprd->gem, bo_sprd->name);
951 if (bo_sprd->pBase) {
952 if (munmap(bo_sprd->pBase, bo_sprd->size) == -1) {
953 TBM_SPRD_LOG("[libtbm-sprd:%d] "
955 getpid(), __FUNCTION__, __LINE__);
960 if (bo_sprd->dmabuf) {
961 close(bo_sprd->dmabuf);
965 /* delete bo from hash */
966 PrivGem *privGem = NULL;
969 ret = drmHashLookup(bufmgr_sprd->hashBos, bo_sprd->name, (void **)&privGem);
971 privGem->ref_count--;
972 if (privGem->ref_count == 0) {
973 drmHashDelete(bufmgr_sprd->hashBos, bo_sprd->name);
978 TBM_SPRD_LOG("[libtbm-sprd:%d] "
979 "warning %s:%d Cannot find bo to Hash(%d), ret=%d\n",
980 getpid(), __FUNCTION__, __LINE__, bo_sprd->name, ret);
983 _bo_destroy_cache_state(bufmgr_sprd, bo_sprd);
985 /* Free gem handle */
986 struct drm_gem_close arg = {0, };
987 memset(&arg, 0, sizeof(arg));
988 arg.handle = bo_sprd->gem;
989 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_GEM_CLOSE, &arg)) {
990 TBM_SPRD_LOG("[libtbm-sprd:%d] "
992 getpid(), __FUNCTION__, __LINE__);
1000 tbm_sprd_bo_import(tbm_bo bo, unsigned int key)
1002 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, NULL);
1004 tbm_bufmgr_sprd bufmgr_sprd;
1005 tbm_bo_sprd bo_sprd;
1006 PrivGem *privGem = NULL;
1009 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1010 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, NULL);
1012 ret = drmHashLookup(bufmgr_sprd->hashBos, key, (void **)&privGem);
1014 return privGem->bo_priv;
1016 struct drm_sprd_gem_info info = {0, };
1017 struct drm_gem_open arg = {0, };
1020 if (drmIoctl(bufmgr_sprd->fd, DRM_IOCTL_GEM_OPEN, &arg)) {
1021 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1022 "error %s:%d Cannot open gem name=%d\n",
1023 getpid(), __FUNCTION__, __LINE__, key);
1027 info.handle = arg.handle;
1028 if (drmCommandWriteRead(bufmgr_sprd->fd,
1031 sizeof(struct drm_sprd_gem_info))) {
1032 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1033 "error %s:%d Cannot get gem info=%d\n",
1034 getpid(), __FUNCTION__, __LINE__, key);
1038 bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
1040 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1041 "error %s:%d fail to allocate the bo private\n",
1042 getpid(), __FUNCTION__, __LINE__);
1046 bo_sprd->fd = bufmgr_sprd->fd;
1047 bo_sprd->gem = arg.handle;
1048 bo_sprd->size = arg.size;
1049 bo_sprd->flags_sprd = info.flags;
1050 bo_sprd->name = key;
1051 #ifdef USE_CONTIG_ONLY
1052 bo_sprd->flags_sprd = SPRD_BO_CONTIG;
1053 bo_sprd->flags_tbm |= TBM_BO_SCANOUT;
1055 bo_sprd->flags_tbm = _get_tbm_flag_from_sprd(bo_sprd->flags_sprd);
1058 if (!_bo_init_cache_state(bufmgr_sprd, bo_sprd, 1)) {
1059 TBM_SPRD_LOG("error fail init cache state(%d)\n", bo_sprd->name);
1060 goto fail_init_cache;
1063 if (!bo_sprd->dmabuf) {
1064 struct drm_prime_handle arg = {0, };
1066 arg.handle = bo_sprd->gem;
1067 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
1068 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1069 "error %s:%d Cannot dmabuf=%d\n",
1070 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
1071 goto fail_prime_handle_to_fd;
1073 bo_sprd->dmabuf = arg.fd;
1076 /* add bo to hash */
1077 privGem = calloc(1, sizeof(PrivGem));
1079 TBM_SPRD_LOG("[libtbm-sprd:%d] error %s:%d Fail to alloc\n",
1080 getpid(), __FUNCTION__, __LINE__);
1081 goto fail_alloc_gem_priv;
1084 privGem->ref_count = 1;
1085 privGem->bo_priv = bo_sprd;
1086 if (drmHashInsert(bufmgr_sprd->hashBos, bo_sprd->name, (void *)privGem) < 0) {
1087 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1088 "error %s:%d Cannot insert bo to Hash(%d)\n",
1089 getpid(), __FUNCTION__, __LINE__, bo_sprd->name);
1092 DBG("[libtbm-sprd:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
1093 __FUNCTION__, bo_sprd->size,
1094 bo_sprd->gem, bo_sprd->name,
1095 bo_sprd->flags_tbm, bo_sprd->flags_sprd);
1097 return (void *)bo_sprd;
1099 fail_alloc_gem_priv:
1100 if (bo_sprd->dmabuf)
1101 close(bo_sprd->dmabuf);
1102 fail_prime_handle_to_fd:
1103 _bo_destroy_cache_state(bufmgr_sprd, bo_sprd);
1109 struct drm_gem_close gem_close_arg = {arg.handle, 0};
1110 drmIoctl(bufmgr_sprd->fd, DRM_IOCTL_GEM_CLOSE, &gem_close_arg);
1116 tbm_sprd_bo_import_fd(tbm_bo bo, tbm_fd key)
1118 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, NULL);
1120 tbm_bufmgr_sprd bufmgr_sprd;
1121 tbm_bo_sprd bo_sprd;
1125 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1126 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, NULL);
1128 //getting handle from fd
1129 struct drm_prime_handle arg = {0, };
1133 if (drmIoctl(bufmgr_sprd->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg)) {
1134 TBM_SPRD_LOG("error bo:%p Cannot get gem handle from fd:%d (%s)\n",
1135 bo, arg.fd, strerror(errno));
1140 name = _get_name(bufmgr_sprd->fd, gem);
1142 TBM_SPRD_LOG("error bo:%p Cannot get name from gem:%d, fd:%d (%s)\n",
1143 bo, gem, key, strerror(errno));
1147 if (!drmHashLookup(bufmgr_sprd->hashBos, name, (void **)&privGem)) {
1148 if (gem == privGem->bo_priv->gem)
1149 return privGem->bo_priv;
1152 unsigned int real_size;
1153 struct drm_sprd_gem_info info = {0, };
1155 /* Determine size of bo. The fd-to-handle ioctl really should
1156 * return the size, but it doesn't. If we have kernel 3.12 or
1157 * later, we can lseek on the prime fd to get the size. Older
1158 * kernels will just fail, in which case we fall back to the
1159 * provided (estimated or guess size). */
1160 real_size = lseek(key, 0, SEEK_END);
1163 if (drmCommandWriteRead(bufmgr_sprd->fd,
1166 sizeof(struct drm_sprd_gem_info))) {
1167 TBM_SPRD_LOG("error bo:%p Cannot get gem info from gem:%d, fd:%d (%s)\n",
1168 bo, gem, key, strerror(errno));
1172 if (real_size == -1)
1173 real_size = info.size;
1175 bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
1177 TBM_SPRD_LOG("error bo:%p fail to allocate the bo private\n", bo);
1181 bo_sprd->fd = bufmgr_sprd->fd;
1183 bo_sprd->size = real_size;
1184 bo_sprd->flags_sprd = info.flags;
1185 bo_sprd->flags_tbm = _get_tbm_flag_from_sprd(bo_sprd->flags_sprd);
1187 bo_sprd->name = name;
1188 if (!bo_sprd->name) {
1189 TBM_SPRD_LOG("error bo:%p Cannot get name from gem:%d, fd:%d (%s)\n",
1190 bo, gem, key, strerror(errno));
1191 goto fail_check_name;
1194 if (!_bo_init_cache_state(bufmgr_sprd, bo_sprd, 1)) {
1195 TBM_SPRD_LOG("error fail init cache state(%d)\n", bo_sprd->name);
1196 goto fail_init_cache;
1199 /* add bo to hash */
1200 privGem = calloc(1, sizeof(PrivGem));
1202 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1203 "error %s:%d Fail to callocprivGem\n",
1204 getpid(), __FUNCTION__, __LINE__);
1205 goto fail_alloc_gem_priv;
1208 privGem->ref_count = 1;
1209 privGem->bo_priv = bo_sprd;
1210 if (drmHashInsert(bufmgr_sprd->hashBos, bo_sprd->name, (void *)privGem) < 0) {
1211 TBM_SPRD_LOG("error bo:%p Cannot insert bo to Hash(%d) from gem:%d, fd:%d\n",
1212 bo, bo_sprd->name, gem, key);
1215 DBG(" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n",
1218 bo_sprd->gem, bo_sprd->name,
1221 bo_sprd->flags_tbm, bo_sprd->flags_sprd,
1224 return (void *)bo_sprd;
1226 fail_alloc_gem_priv:
1227 _bo_destroy_cache_state(bufmgr_sprd, bo_sprd);
1235 tbm_sprd_bo_export(tbm_bo bo)
1237 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1239 tbm_bo_sprd bo_sprd;
1241 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1242 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1244 if (!bo_sprd->name) {
1245 bo_sprd->name = _get_name(bo_sprd->fd, bo_sprd->gem);
1246 if (!bo_sprd->name) {
1247 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1248 "error %s:%d Cannot get name\n",
1249 getpid(), __FUNCTION__, __LINE__);
1254 DBG("[libtbm-sprd:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
1255 __FUNCTION__, bo_sprd->size,
1256 bo_sprd->gem, bo_sprd->name,
1257 bo_sprd->flags_tbm, bo_sprd->flags_sprd);
1259 return (unsigned int)bo_sprd->name;
1263 tbm_sprd_bo_export_fd(tbm_bo bo)
1265 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, -1);
1267 tbm_bo_sprd bo_sprd;
1270 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1271 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, -1);
1273 struct drm_prime_handle arg = {0, };
1275 arg.handle = bo_sprd->gem;
1276 ret = drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg);
1278 TBM_SPRD_LOG("error bo:%p Cannot dmabuf=%d (%s)\n",
1279 bo, bo_sprd->gem, strerror(errno));
1280 return (tbm_fd) ret;
1283 DBG(" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n",
1286 bo_sprd->gem, bo_sprd->name,
1289 bo_sprd->flags_tbm, bo_sprd->flags_sprd,
1292 return (tbm_fd)arg.fd;
1296 static tbm_bo_handle
1297 tbm_sprd_bo_get_handle(tbm_bo bo, int device)
1299 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, (tbm_bo_handle) NULL);
1301 tbm_bo_handle bo_handle;
1302 tbm_bo_sprd bo_sprd;
1304 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1305 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, (tbm_bo_handle) NULL);
1307 if (!bo_sprd->gem) {
1308 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1309 "error %s:%d Cannot map gem=%d\n",
1310 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
1311 return (tbm_bo_handle) NULL;
1314 DBG("[libtbm-sprd:%d] %s gem:%d(%d), %s\n", getpid(),
1315 __FUNCTION__, bo_sprd->gem, bo_sprd->name, STR_DEVICE[device]);
1317 /*Get mapped bo_handle*/
1318 bo_handle = _sprd_bo_handle(bo_sprd, device);
1319 if (bo_handle.ptr == NULL) {
1320 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1321 "error %s:%d Cannot get handle: gem:%d, device:%d\n",
1322 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem, device);
1323 return (tbm_bo_handle) NULL;
1329 static tbm_bo_handle
1330 tbm_sprd_bo_map(tbm_bo bo, int device, int opt)
1332 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, (tbm_bo_handle) NULL);
1334 tbm_bo_handle bo_handle;
1335 tbm_bo_sprd bo_sprd;
1336 tbm_bufmgr_sprd bufmgr_sprd;
1338 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1339 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, (tbm_bo_handle) NULL);
1341 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1342 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, (tbm_bo_handle) NULL);
1344 if (!bo_sprd->gem) {
1345 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1346 "error %s:%d Cannot map gem=%d\n",
1347 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
1348 return (tbm_bo_handle) NULL;
1351 DBG("[libtbm-sprd:%d] %s gem:%d(%d), %s, %s\n", getpid(),
1352 __FUNCTION__, bo_sprd->gem, bo_sprd->name, STR_DEVICE[device], STR_OPT[opt]);
1354 /*Get mapped bo_handle*/
1355 bo_handle = _sprd_bo_handle(bo_sprd, device);
1356 if (bo_handle.ptr == NULL) {
1357 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1358 "error %s:%d Cannot get handle: gem:%d, device:%d, opt:%d\n",
1359 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem, device, opt);
1360 return (tbm_bo_handle) NULL;
1363 if (bo_sprd->map_cnt == 0)
1364 _bo_set_cache_state(bufmgr_sprd, bo_sprd, device, opt);
1372 tbm_sprd_bo_unmap(tbm_bo bo)
1374 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1376 tbm_bufmgr_sprd bufmgr_sprd;
1377 tbm_bo_sprd bo_sprd;
1379 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1380 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1382 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1383 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1390 if (bo_sprd->map_cnt == 0)
1391 _bo_save_cache_state(bufmgr_sprd, bo_sprd);
1393 DBG("[libtbm-sprd:%d] %s gem:%d(%d) \n", getpid(),
1394 __FUNCTION__, bo_sprd->gem, bo_sprd->name);
1400 tbm_sprd_bo_lock(tbm_bo bo, int device, int opt)
1402 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1404 tbm_bufmgr_sprd bufmgr_sprd;
1405 tbm_bo_sprd bo_sprd;
1407 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1408 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1410 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1411 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1413 #if USE_BACKEND_LOCK
1416 if (bufmgr_sprd->use_dma_fence) {
1417 struct dma_buf_fence fence;
1419 memset(&fence, 0, sizeof(struct dma_buf_fence));
1421 /* Check if the given type is valid or not. */
1422 if (opt & TBM_OPTION_WRITE) {
1423 if (device == TBM_DEVICE_CPU)
1424 fence.type = DMA_BUF_ACCESS_WRITE;
1425 else if (device == TBM_DEVICE_3D)
1426 fence.type = DMA_BUF_ACCESS_WRITE | DMA_BUF_ACCESS_DMA;
1428 DBG("[libtbm-sprd:%d] %s GET_FENCE is ignored(device type is not 3D/CPU),\n",
1429 getpid(), __FUNCTION__);
1432 } else if (opt & TBM_OPTION_READ) {
1433 if (device == TBM_DEVICE_CPU)
1434 fence.type = DMA_BUF_ACCESS_READ;
1435 else if (device == TBM_DEVICE_3D)
1436 fence.type = DMA_BUF_ACCESS_READ | DMA_BUF_ACCESS_DMA;
1438 DBG("[libtbm-sprd:%d] %s GET_FENCE is ignored(device type is not 3D/CPU),\n",
1439 getpid(), __FUNCTION__);
1443 TBM_SPRD_LOG("[libtbm-sprd:%d] error %s:%d Invalid argument\n", getpid(),
1444 __FUNCTION__, __LINE__);
1448 ret = ioctl(bo_sprd->dmabuf, DMABUF_IOCTL_GET_FENCE, &fence);
1450 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1451 "error %s:%d Can not set GET FENCE(%s)\n",
1452 getpid(), __FUNCTION__, __LINE__, strerror(errno));
1456 pthread_mutex_lock(&bo_sprd->mutex);
1458 for (i = 0; i < DMA_FENCE_LIST_MAX; i++) {
1459 if (bo_sprd->dma_fence[i].ctx == 0) {
1460 bo_sprd->dma_fence[i].type = fence.type;
1461 bo_sprd->dma_fence[i].ctx = fence.ctx;
1465 if (i == DMA_FENCE_LIST_MAX) {
1466 //TODO: if dma_fence list is full, it needs realloc. I will fix this. by minseok3.kim
1467 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1468 "error %s:%d fence list is full\n",
1469 getpid(), __FUNCTION__, __LINE__);
1471 pthread_mutex_unlock(&bo_sprd->mutex);
1473 DBG("[libtbm-sprd:%d] %s DMABUF_IOCTL_GET_FENCE! flink_id=%d dmabuf=%d\n",
1475 __FUNCTION__, bo_sprd->name, bo_sprd->dmabuf);
1477 ret = _tgl_lock(bufmgr_sprd->tgl_fd, bo_sprd->name);
1479 DBG("[libtbm-sprd:%d] lock tgl flink_id:%d\n",
1480 getpid(), __FUNCTION__, bo_sprd->name);
1490 tbm_sprd_bo_unlock(tbm_bo bo)
1492 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1494 tbm_bufmgr_sprd bufmgr_sprd;
1495 tbm_bo_sprd bo_sprd;
1497 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1498 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1500 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1501 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1503 #if USE_BACKEND_LOCK
1506 if (bufmgr_sprd->use_dma_fence) {
1507 struct dma_buf_fence fence;
1509 if (!bo_sprd->dma_fence[0].ctx) {
1510 DBG("[libtbm-sprd:%d] %s FENCE not support or ignored,\n", getpid(),
1515 if (!bo_sprd->dma_fence[0].type) {
1516 DBG("[libtbm-sprd:%d] %s device type is not 3D/CPU,\n", getpid(),
1521 pthread_mutex_lock(&bo_sprd->mutex);
1522 fence.type = bo_sprd->dma_fence[0].type;
1523 fence.ctx = bo_sprd->dma_fence[0].ctx;
1525 for (i = 1; i < DMA_FENCE_LIST_MAX; i++) {
1526 bo_sprd->dma_fence[i - 1].type = bo_sprd->dma_fence[i].type;
1527 bo_sprd->dma_fence[i - 1].ctx = bo_sprd->dma_fence[i].ctx;
1529 bo_sprd->dma_fence[DMA_FENCE_LIST_MAX - 1].type = 0;
1530 bo_sprd->dma_fence[DMA_FENCE_LIST_MAX - 1].ctx = 0;
1531 pthread_mutex_unlock(&bo_sprd->mutex);
1533 ret = ioctl(bo_sprd->dmabuf, DMABUF_IOCTL_PUT_FENCE, &fence);
1535 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1536 "error %s:%d Can not set PUT FENCE(%s)\n",
1537 getpid(), __FUNCTION__, __LINE__, strerror(errno));
1541 DBG("[libtbm-sprd:%d] %s DMABUF_IOCTL_PUT_FENCE! flink_id=%d dmabuf=%d\n",
1543 __FUNCTION__, bo_sprd->name, bo_sprd->dmabuf);
1545 ret = _tgl_unlock(bufmgr_sprd->tgl_fd, bo_sprd->name);
1547 DBG("[libtbm-sprd:%d] unlock tgl flink_id:%d\n",
1548 getpid(), __FUNCTION__, bo_sprd->name);
1558 tbm_sprd_bufmgr_deinit(void *priv)
1560 SPRD_RETURN_IF_FAIL(priv != NULL);
1562 tbm_bufmgr_sprd bufmgr_sprd;
1564 bufmgr_sprd = (tbm_bufmgr_sprd)priv;
1566 if (bufmgr_sprd->hashBos) {
1570 while (drmHashFirst(bufmgr_sprd->hashBos, &key, &value) > 0) {
1572 drmHashDelete(bufmgr_sprd->hashBos, key);
1575 drmHashDestroy(bufmgr_sprd->hashBos);
1576 bufmgr_sprd->hashBos = NULL;
1579 if (bufmgr_sprd->bind_display)
1580 tbm_drm_helper_wl_auth_server_deinit();
1582 if (tbm_backend_is_display_server())
1583 tbm_drm_helper_unset_tbm_master_fd();
1585 if (bufmgr_sprd->device_name)
1586 free(bufmgr_sprd->device_name);
1588 _bufmgr_deinit_cache_state(bufmgr_sprd);
1590 close(bufmgr_sprd->fd);
1596 tbm_sprd_surface_supported_format(uint32_t **formats, uint32_t *num)
1598 uint32_t *color_formats;
1600 color_formats = (uint32_t *)calloc(1,
1601 sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
1602 if (color_formats == NULL)
1605 memcpy(color_formats, tbm_sprd_color_format_list,
1606 sizeof(uint32_t)*TBM_COLOR_FORMAT_COUNT);
1608 *formats = color_formats;
1609 *num = TBM_COLOR_FORMAT_COUNT;
1616 * @brief get the plane data of the surface.
1617 * @param[in] width : the width of the surface
1618 * @param[in] height : the height of the surface
1619 * @param[in] format : the format of the surface
1620 * @param[in] plane_idx : the format of the surface
1621 * @param[out] size : the size of the plane
1622 * @param[out] offset : the offset of the plane
1623 * @param[out] pitch : the pitch of the plane
1624 * @param[out] padding : the padding of the plane
1625 * @return 1 if this function succeeds, otherwise 0.
1628 tbm_sprd_surface_get_plane_data(int width, int height,
1629 tbm_format format, int plane_idx, uint32_t *size, uint32_t *offset,
1630 uint32_t *pitch, int *bo_idx)
1638 int _align_height = 0;
1642 case TBM_FORMAT_XRGB4444:
1643 case TBM_FORMAT_XBGR4444:
1644 case TBM_FORMAT_RGBX4444:
1645 case TBM_FORMAT_BGRX4444:
1646 case TBM_FORMAT_ARGB4444:
1647 case TBM_FORMAT_ABGR4444:
1648 case TBM_FORMAT_RGBA4444:
1649 case TBM_FORMAT_BGRA4444:
1650 case TBM_FORMAT_XRGB1555:
1651 case TBM_FORMAT_XBGR1555:
1652 case TBM_FORMAT_RGBX5551:
1653 case TBM_FORMAT_BGRX5551:
1654 case TBM_FORMAT_ARGB1555:
1655 case TBM_FORMAT_ABGR1555:
1656 case TBM_FORMAT_RGBA5551:
1657 case TBM_FORMAT_BGRA5551:
1658 case TBM_FORMAT_RGB565:
1661 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1662 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1666 case TBM_FORMAT_RGB888:
1667 case TBM_FORMAT_BGR888:
1670 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1671 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1675 case TBM_FORMAT_XRGB8888:
1676 case TBM_FORMAT_XBGR8888:
1677 case TBM_FORMAT_RGBX8888:
1678 case TBM_FORMAT_BGRX8888:
1679 case TBM_FORMAT_ARGB8888:
1680 case TBM_FORMAT_ABGR8888:
1681 case TBM_FORMAT_RGBA8888:
1682 case TBM_FORMAT_BGRA8888:
1685 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1686 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1691 case TBM_FORMAT_YUYV:
1692 case TBM_FORMAT_YVYU:
1693 case TBM_FORMAT_UYVY:
1694 case TBM_FORMAT_VYUY:
1695 case TBM_FORMAT_AYUV:
1698 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1699 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1705 * index 0 = Y plane, [7:0] Y
1706 * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1708 * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1710 case TBM_FORMAT_NV12:
1711 case TBM_FORMAT_NV21:
1713 if (plane_idx == 0) {
1715 _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1716 _align_height = SIZE_ALIGN(height, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1717 _size = SIZE_ALIGN(_pitch * _align_height, TBM_SURFACE_ALIGNMENT_PLANE);
1719 } else if (plane_idx == 1) {
1720 _offset = width * height;
1721 _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1722 _align_height = SIZE_ALIGN(height / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1723 _size = SIZE_ALIGN(_pitch * _align_height, TBM_SURFACE_ALIGNMENT_PLANE);
1728 case TBM_FORMAT_NV16:
1729 case TBM_FORMAT_NV61:
1731 //if(plane_idx == 0)
1734 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1735 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1740 //else if( plane_idx ==1 )
1743 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1744 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1751 * index 0: Y plane, [7:0] Y
1752 * index 1: Cb plane, [7:0] Cb
1753 * index 2: Cr plane, [7:0] Cr
1755 * index 1: Cr plane, [7:0] Cr
1756 * index 2: Cb plane, [7:0] Cb
1759 NATIVE_BUFFER_FORMAT_YV12
1760 NATIVE_BUFFER_FORMAT_I420
1762 case TBM_FORMAT_YUV410:
1763 case TBM_FORMAT_YVU410:
1766 case TBM_FORMAT_YUV411:
1767 case TBM_FORMAT_YVU411:
1768 case TBM_FORMAT_YUV420:
1769 case TBM_FORMAT_YVU420:
1771 //if(plane_idx == 0)
1774 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1775 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1780 //else if( plane_idx == 1 )
1783 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1784 _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1789 //else if (plane_idx == 2 )
1792 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1793 _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1797 case TBM_FORMAT_YUV422:
1798 case TBM_FORMAT_YVU422:
1800 //if(plane_idx == 0)
1803 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1804 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1809 //else if( plane_idx == 1 )
1812 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1813 _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
1818 //else if (plane_idx == 2 )
1821 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1822 _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
1826 case TBM_FORMAT_YUV444:
1827 case TBM_FORMAT_YVU444:
1829 //if(plane_idx == 0)
1832 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1833 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1838 //else if( plane_idx == 1 )
1841 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1842 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1847 //else if (plane_idx == 2 )
1850 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1851 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1869 tbm_sprd_bo_get_flags(tbm_bo bo)
1871 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1873 tbm_bo_sprd bo_sprd;
1875 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1876 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1878 return bo_sprd->flags_tbm;
1882 tbm_sprd_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1884 tbm_bufmgr_sprd bufmgr_sprd;
1886 bufmgr_sprd = tbm_backend_get_priv_from_bufmgr(bufmgr);
1887 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1889 if (!tbm_drm_helper_wl_auth_server_init(NativeDisplay, bufmgr_sprd->fd,
1890 bufmgr_sprd->device_name, 0)) {
1891 TBM_SPRD_LOG("[libtbm-sprd:%d] error:Fail to tbm_drm_helper_wl_server_init\n");
1895 bufmgr_sprd->bind_display = NativeDisplay;
1900 MODULEINITPPROTO(init_tbm_bufmgr_priv);
1902 static TBMModuleVersionInfo SprdVersRec = {
1908 TBMModuleData tbmModuleData = { &SprdVersRec, init_tbm_bufmgr_priv};
1911 init_tbm_bufmgr_priv(tbm_bufmgr bufmgr, int fd)
1913 tbm_bufmgr_backend bufmgr_backend;
1914 tbm_bufmgr_sprd bufmgr_sprd;
1920 bufmgr_sprd = calloc(1, sizeof(struct _tbm_bufmgr_sprd));
1922 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to alloc bufmgr_sprd!\n", getpid());
1926 if (tbm_backend_is_display_server()) {
1927 bufmgr_sprd->fd = tbm_drm_helper_get_master_fd();
1928 if (bufmgr_sprd->fd < 0) {
1929 bufmgr_sprd->fd = _tbm_sprd_open_drm();
1930 if (bufmgr_sprd->fd < 0) {
1931 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to open drm!\n", getpid());
1936 tbm_drm_helper_set_tbm_master_fd(bufmgr_sprd->fd);
1938 bufmgr_sprd->device_name = drmGetDeviceNameFromFd(bufmgr_sprd->fd);
1939 if (!bufmgr_sprd->device_name) {
1940 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to get device name!\n", getpid());
1941 tbm_drm_helper_unset_tbm_master_fd();
1942 goto fail_get_device_name;
1945 if (!tbm_drm_helper_get_auth_info(&(bufmgr_sprd->fd), &(bufmgr_sprd->device_name), NULL)) {
1946 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to get auth drm info!\n", getpid());
1947 goto fail_get_auth_info;
1952 bufmgr_sprd->hashBos = drmHashCreate();
1954 //Check if the tbm manager supports dma fence or not.
1955 fp = open("/sys/module/dmabuf_sync/parameters/enabled", O_RDONLY);
1958 int length = read(fp, buf, 1);
1960 if (length == 1 && buf[0] == '1')
1961 bufmgr_sprd->use_dma_fence = 1;
1966 if (!_bufmgr_init_cache_state(bufmgr_sprd)) {
1967 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to init bufmgr cache state\n", getpid());
1968 goto fail_init_cache_state;
1971 bufmgr_backend = tbm_backend_alloc();
1972 if (!bufmgr_backend) {
1973 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to alloc backend!\n", getpid());
1974 goto fail_alloc_backend;
1977 bufmgr_backend->priv = (void *)bufmgr_sprd;
1978 bufmgr_backend->bufmgr_deinit = tbm_sprd_bufmgr_deinit;
1979 bufmgr_backend->bo_size = tbm_sprd_bo_size;
1980 bufmgr_backend->bo_alloc = tbm_sprd_bo_alloc;
1981 bufmgr_backend->bo_free = tbm_sprd_bo_free;
1982 bufmgr_backend->bo_import = tbm_sprd_bo_import;
1983 bufmgr_backend->bo_import_fd = tbm_sprd_bo_import_fd;
1984 bufmgr_backend->bo_export = tbm_sprd_bo_export;
1985 bufmgr_backend->bo_export_fd = tbm_sprd_bo_export_fd;
1986 bufmgr_backend->bo_get_handle = tbm_sprd_bo_get_handle;
1987 bufmgr_backend->bo_map = tbm_sprd_bo_map;
1988 bufmgr_backend->bo_unmap = tbm_sprd_bo_unmap;
1989 bufmgr_backend->surface_get_plane_data = tbm_sprd_surface_get_plane_data;
1990 bufmgr_backend->surface_supported_format = tbm_sprd_surface_supported_format;
1991 bufmgr_backend->bo_get_flags = tbm_sprd_bo_get_flags;
1992 bufmgr_backend->bo_lock = tbm_sprd_bo_lock;
1993 bufmgr_backend->bo_unlock = tbm_sprd_bo_unlock;
1994 bufmgr_backend->bufmgr_bind_native_display = tbm_sprd_bufmgr_bind_native_display;
1996 if (!tbm_backend_init(bufmgr, bufmgr_backend)) {
1997 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to init backend!\n", getpid());
1998 goto fail_init_backend;
2005 env = getenv("TBM_SPRD_DEBUG");
2008 TBM_SPRD_LOG("TBM_SPRD_DEBUG=%s\n", env);
2014 DBG("[libtbm-sprd:%d] %s DMABUF FENCE is %s\n", getpid(),
2015 __FUNCTION__, bufmgr_sprd->use_dma_fence ? "supported!" : "NOT supported!");
2016 DBG("[libtbm-sprd:%d] %s fd:%d\n", getpid(),
2017 __FUNCTION__, bufmgr_sprd->fd);
2022 tbm_backend_free(bufmgr_backend);
2024 _bufmgr_deinit_cache_state(bufmgr_sprd);
2025 fail_init_cache_state:
2026 if (bufmgr_sprd->hashBos)
2027 drmHashDestroy(bufmgr_sprd->hashBos);
2028 if (tbm_backend_is_display_server())
2029 tbm_drm_helper_unset_tbm_master_fd();
2030 fail_get_device_name:
2031 close(bufmgr_sprd->fd);