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;
369 fd = drmOpen(SPRD_DRM_NAME, NULL);
371 TBM_SPRD_LOG("[libtbm-sprd:%d] "
372 "warning %s:%d fail to open drm\n",
373 getpid(), __FUNCTION__, __LINE__);
378 struct udev *udev = NULL;
379 struct udev_enumerate *e = NULL;
380 struct udev_list_entry *entry = NULL;
381 struct udev_device *device = NULL, *drm_device = NULL, *device_parent = NULL;
382 const char *filepath;
386 TBM_SPRD_LOG("[libtbm-sprd:%d] "
387 "%s:%d search drm-device by udev\n",
388 getpid(), __FUNCTION__, __LINE__);
392 TBM_SPRD_LOG("udev_new() failed.\n");
396 e = udev_enumerate_new(udev);
397 udev_enumerate_add_match_subsystem(e, "drm");
398 udev_enumerate_add_match_sysname(e, "card[0-9]*");
399 udev_enumerate_scan_devices(e);
401 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
402 device = udev_device_new_from_syspath(udev_enumerate_get_udev(e),
403 udev_list_entry_get_name(entry));
404 device_parent = udev_device_get_parent(device);
405 /* Not need unref device_parent. device_parent and device have same refcnt */
407 if (strcmp(udev_device_get_sysname(device_parent), "sprd-drm") == 0) {
409 DBG("[%s] Found render device: '%s' (%s)\n",
411 udev_device_get_syspath(drm_device),
412 udev_device_get_sysname(device_parent));
416 udev_device_unref(device);
419 udev_enumerate_unref(e);
421 /* Get device file path. */
422 filepath = udev_device_get_devnode(drm_device);
424 TBM_SPRD_LOG("udev_device_get_devnode() failed.\n");
425 udev_device_unref(drm_device);
430 /* Open DRM device file and check validity. */
431 fd = open(filepath, O_RDWR | O_CLOEXEC);
433 TBM_SPRD_LOG("open(%s, O_RDWR | O_CLOEXEC) failed.\n");
434 udev_device_unref(drm_device);
441 TBM_SPRD_LOG("fstat() failed %s.\n");
443 udev_device_unref(drm_device);
448 udev_device_unref(drm_device);
458 _sprd_bo_cache_flush(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int flags)
460 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
461 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
463 /* cache flush is managed by kernel side when using dma-fence. */
464 if (bufmgr_sprd->use_dma_fence)
467 struct drm_sprd_gem_cache_op cache_op = {0, };
470 /* if bo_sprd is null, do cache_flush_all */
473 cache_op.usr_addr = (uint64_t)((uint32_t)bo_sprd->pBase);
474 cache_op.size = bo_sprd->size;
476 flags = TBM_SPRD_CACHE_FLUSH_ALL;
478 cache_op.usr_addr = 0;
482 if (flags & TBM_SPRD_CACHE_INV) {
483 if (flags & TBM_SPRD_CACHE_ALL)
484 cache_op.flags |= SPRD_DRM_CACHE_INV_ALL;
486 cache_op.flags |= SPRD_DRM_CACHE_INV_RANGE;
489 if (flags & TBM_SPRD_CACHE_CLN) {
490 if (flags & TBM_SPRD_CACHE_ALL)
491 cache_op.flags |= SPRD_DRM_CACHE_CLN_ALL;
493 cache_op.flags |= SPRD_DRM_CACHE_CLN_RANGE;
496 if (flags & TBM_SPRD_CACHE_ALL)
497 cache_op.flags |= SPRD_DRM_ALL_CACHES_CORES;
499 ret = drmCommandWriteRead(bufmgr_sprd->fd, DRM_SPRD_GEM_CACHE_OP, &cache_op,
502 TBM_SPRD_LOG("[libtbm-sprd:%d] "
503 "error %s:%d fail to flush the cache.\n",
504 getpid(), __FUNCTION__, __LINE__);
513 _bo_init_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int import)
515 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
516 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
518 if (bufmgr_sprd->use_dma_fence)
521 _tgl_init(bufmgr_sprd->tgl_fd, bo_sprd->name);
524 tbm_bo_cache_state cache_state;
527 cache_state.data.isDirtied = DEVICE_NONE;
528 cache_state.data.isCached = 0;
529 cache_state.data.cntFlush = 0;
531 _tgl_set_data(bufmgr_sprd->tgl_fd, bo_sprd->name, cache_state.val);
539 _bo_set_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int device, int opt)
542 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
543 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
546 unsigned short cntFlush = 0;
548 if (bufmgr_sprd->use_dma_fence)
551 if (bo_sprd->flags_sprd & SPRD_BO_NONCACHABLE)
554 /* get cache state of a bo */
555 bo_sprd->cache_state.val = _tgl_get_data(bufmgr_sprd->tgl_fd, bo_sprd->name, NULL);
557 /* get global cache flush count */
558 cntFlush = (unsigned short)_tgl_get_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, NULL);
560 if (opt == TBM_DEVICE_CPU) {
561 if (bo_sprd->cache_state.data.isDirtied == DEVICE_CO &&
562 bo_sprd->cache_state.data.isCached)
563 need_flush = TBM_SPRD_CACHE_INV;
565 bo_sprd->cache_state.data.isCached = 1;
566 if (opt & TBM_OPTION_WRITE)
567 bo_sprd->cache_state.data.isDirtied = DEVICE_CA;
569 if (bo_sprd->cache_state.data.isDirtied != DEVICE_CA)
570 bo_sprd->cache_state.data.isDirtied = DEVICE_NONE;
573 if (bo_sprd->cache_state.data.isDirtied == DEVICE_CA &&
574 bo_sprd->cache_state.data.isCached &&
575 bo_sprd->cache_state.data.cntFlush == cntFlush)
576 need_flush = TBM_SPRD_CACHE_CLN | TBM_SPRD_CACHE_ALL;
578 if (opt & TBM_OPTION_WRITE)
579 bo_sprd->cache_state.data.isDirtied = DEVICE_CO;
581 if (bo_sprd->cache_state.data.isDirtied != DEVICE_CO)
582 bo_sprd->cache_state.data.isDirtied = DEVICE_NONE;
587 if (need_flush & TBM_SPRD_CACHE_ALL)
588 _tgl_set_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, (unsigned int)(++cntFlush));
590 /* call cache flush */
591 _sprd_bo_cache_flush(bufmgr_sprd, bo_sprd, need_flush);
593 DBG("[libtbm:%d] \tcache(%d,%d)....flush:0x%x, cntFlush(%d)\n",
595 bo_sprd->cache_state.data.isCached,
596 bo_sprd->cache_state.data.isDirtied,
606 _bo_save_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd)
609 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
610 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
612 if (bufmgr_sprd->use_dma_fence)
615 unsigned short cntFlush = 0;
617 /* get global cache flush count */
618 cntFlush = (unsigned short)_tgl_get_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, NULL);
620 /* save global cache flush count */
621 bo_sprd->cache_state.data.cntFlush = cntFlush;
622 _tgl_set_data(bufmgr_sprd->tgl_fd, bo_sprd->name, bo_sprd->cache_state.val);
629 _bo_destroy_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd)
631 SPRD_RETURN_IF_FAIL(bo_sprd != NULL);
632 SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
634 if (bufmgr_sprd->use_dma_fence)
637 _tgl_destroy(bufmgr_sprd->tgl_fd, bo_sprd->name);
641 _bufmgr_init_cache_state(tbm_bufmgr_sprd bufmgr_sprd)
643 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
645 if (bufmgr_sprd->use_dma_fence)
648 /* open tgl fd for saving cache flush data */
649 bufmgr_sprd->tgl_fd = open(tgl_devfile, O_RDWR);
651 if (bufmgr_sprd->tgl_fd < 0) {
652 bufmgr_sprd->tgl_fd = open(tgl_devfile1, O_RDWR);
653 if (bufmgr_sprd->tgl_fd < 0) {
654 TBM_SPRD_LOG("[libtbm-sprd:%d] "
655 "error: Fail to open global_lock:%s\n",
656 getpid(), tgl_devfile);
662 if (!_tgl_init(bufmgr_sprd->tgl_fd, GLOBAL_KEY)) {
663 TBM_SPRD_LOG("[libtbm-sprd:%d] "
664 "error: Fail to initialize the tgl\n",
667 close(bufmgr_sprd->tgl_fd);
676 _bufmgr_deinit_cache_state(tbm_bufmgr_sprd bufmgr_sprd)
678 SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
680 if (bufmgr_sprd->use_dma_fence)
683 if (bufmgr_sprd->tgl_fd >= 0)
684 close(bufmgr_sprd->tgl_fd);
687 #ifndef USE_CONTIG_ONLY
689 _get_sprd_flag_from_tbm(unsigned int ftbm)
691 unsigned int flags = 0;
694 * TBM_BO_DEFAULT => ION_HEAP_ID_MASK_SYSTEM
695 * TBM_BO_SCANOUT => ION_HEAP_ID_MASK_MM
696 * TBM_BO_VENDOR => ION_HEAP_ID_MASK_OVERLAY
697 * To be updated appropriately once DRM-GEM supports different heap id masks.
700 if (ftbm & TBM_BO_SCANOUT)
701 flags = SPRD_BO_CONTIG;
703 flags = SPRD_BO_NONCONTIG | SPRD_BO_DEV_SYSTEM;
705 if (ftbm & TBM_BO_WC)
707 else if (ftbm & TBM_BO_NONCACHABLE)
708 flags |= SPRD_BO_NONCACHABLE;
714 _get_tbm_flag_from_sprd(unsigned int fsprd)
716 unsigned int flags = 0;
718 if (fsprd & SPRD_BO_NONCONTIG)
719 flags |= TBM_BO_DEFAULT;
721 flags |= TBM_BO_SCANOUT;
723 if (fsprd & SPRD_BO_WC)
725 else if (fsprd & SPRD_BO_CACHABLE)
726 flags |= TBM_BO_DEFAULT;
728 flags |= TBM_BO_NONCACHABLE;
735 _get_name(int fd, unsigned int gem)
737 struct drm_gem_flink arg = {0,};
740 if (drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &arg)) {
741 TBM_SPRD_LOG("[libtbm-sprd:%d] "
742 "error %s:%d fail to get flink gem=%d\n",
743 getpid(), __FUNCTION__, __LINE__, gem);
747 return (unsigned int)arg.name;
751 _sprd_bo_handle(tbm_bo_sprd bo_sprd, int device)
753 tbm_bo_handle bo_handle;
754 memset(&bo_handle, 0x0, sizeof(uint64_t));
757 case TBM_DEVICE_DEFAULT:
759 bo_handle.u32 = (uint32_t)bo_sprd->gem;
762 if (!bo_sprd->pBase) {
763 struct drm_sprd_gem_mmap arg = {0,};
765 arg.handle = bo_sprd->gem;
766 arg.size = bo_sprd->size;
767 if (drmCommandWriteRead(bo_sprd->fd, DRM_SPRD_GEM_MMAP, &arg, sizeof(arg))) {
768 TBM_SPRD_LOG("[libtbm-sprd:%d] "
769 "error %s:%d Cannot usrptr gem=%d\n",
770 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
771 return (tbm_bo_handle) NULL;
773 bo_sprd->pBase = (void *)((uint32_t)arg.mapped);
776 bo_handle.ptr = (void *)bo_sprd->pBase;
780 if (!bo_sprd->dmabuf) {
781 struct drm_prime_handle arg = {0, };
782 arg.handle = bo_sprd->gem;
783 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
784 TBM_SPRD_LOG("[libtbm-sprd:%d] "
785 "error %s:%d Cannot dmabuf=%d\n",
786 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
787 return (tbm_bo_handle) NULL;
789 bo_sprd->dmabuf = arg.fd;
792 bo_handle.u32 = (uint32_t)bo_sprd->dmabuf;
799 //TODO : Add ioctl for GSP MAP once available.
800 DBG("[libtbm-sprd:%d] %s In case TBM_DEVICE_MM: \n", getpid(),
805 if (!bo_sprd->dmabuf) {
806 struct drm_prime_handle arg = {0, };
808 arg.handle = bo_sprd->gem;
809 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
810 TBM_SPRD_LOG("[libtbm-sprd:%d] "
811 "error %s:%d Cannot dmabuf=%d\n",
812 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
813 return (tbm_bo_handle) NULL;
815 bo_sprd->dmabuf = arg.fd;
818 bo_handle.u32 = (uint32_t)bo_sprd->dmabuf;
822 bo_handle.ptr = (void *) NULL;
830 tbm_sprd_bo_size(tbm_bo bo)
832 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
836 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
838 return bo_sprd->size;
842 tbm_sprd_bo_alloc(tbm_bo bo, int size, int flags)
844 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
847 tbm_bufmgr_sprd bufmgr_sprd;
848 unsigned int sprd_flags;
850 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
851 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
853 bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
855 TBM_SPRD_LOG("[libtbm-sprd:%d] "
856 "error %s:%d fail to allocate the bo private\n",
857 getpid(), __FUNCTION__, __LINE__);
861 #ifdef USE_CONTIG_ONLY
862 flags = TBM_BO_SCANOUT;
863 sprd_flags = SPRD_BO_CONTIG;
865 sprd_flags = _get_sprd_flag_from_tbm(flags);
866 if ((flags & TBM_BO_SCANOUT) &&
868 sprd_flags |= SPRD_BO_NONCONTIG;
870 #endif // USE_CONTIG_ONLY
871 struct drm_sprd_gem_create arg = {0, };
872 arg.size = (uint64_t)size;
873 arg.flags = sprd_flags;
874 if (drmCommandWriteRead(bufmgr_sprd->fd, DRM_SPRD_GEM_CREATE, &arg,
876 TBM_SPRD_LOG("[libtbm-sprd:%d] "
877 "error %s:%d Cannot create bo(flag:%x, size:%d)\n",
878 getpid(), __FUNCTION__, __LINE__, arg.flags, (unsigned int)arg.size);
883 bo_sprd->fd = bufmgr_sprd->fd;
884 bo_sprd->gem = arg.handle;
885 bo_sprd->size = size;
886 bo_sprd->flags_tbm = flags;
887 bo_sprd->flags_sprd = sprd_flags;
888 bo_sprd->name = _get_name(bo_sprd->fd, bo_sprd->gem);
890 if (!_bo_init_cache_state(bufmgr_sprd, bo_sprd, 0)) {
891 TBM_SPRD_LOG("error fail init cache state(%d)\n", bo_sprd->name);
896 pthread_mutex_init(&bo_sprd->mutex, NULL);
898 if (bufmgr_sprd->use_dma_fence
899 && !bo_sprd->dmabuf) {
900 struct drm_prime_handle arg = {0, };
902 arg.handle = bo_sprd->gem;
903 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
904 TBM_SPRD_LOG("[libtbm-sprd:%d] "
905 "error %s:%d Cannot dmabuf=%d\n",
906 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
910 bo_sprd->dmabuf = arg.fd;
914 PrivGem *privGem = calloc(1, sizeof(PrivGem));
915 privGem->ref_count = 1;
916 privGem->bo_priv = bo_sprd;
917 if (drmHashInsert(bufmgr_sprd->hashBos, bo_sprd->name, (void *)privGem) < 0) {
918 TBM_SPRD_LOG("[libtbm-sprd:%d] "
919 "error %s:%d Cannot insert bo to Hash(%d)\n",
920 getpid(), __FUNCTION__, __LINE__, bo_sprd->name);
923 DBG("[libtbm-sprd:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
924 __FUNCTION__, bo_sprd->size,
925 bo_sprd->gem, bo_sprd->name,
928 return (void *)bo_sprd;
932 tbm_sprd_bo_free(tbm_bo bo)
935 tbm_bufmgr_sprd bufmgr_sprd;
940 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
941 SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
943 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
944 SPRD_RETURN_IF_FAIL(bo_sprd != NULL);
946 DBG("[libtbm-sprd:%d] %s size:%d, gem:%d(%d)\n",
947 getpid(), __FUNCTION__, bo_sprd->size, bo_sprd->gem, bo_sprd->name);
949 if (bo_sprd->pBase) {
950 if (munmap(bo_sprd->pBase, bo_sprd->size) == -1) {
951 TBM_SPRD_LOG("[libtbm-sprd:%d] "
953 getpid(), __FUNCTION__, __LINE__);
958 if (bo_sprd->dmabuf) {
959 close(bo_sprd->dmabuf);
963 /* delete bo from hash */
964 PrivGem *privGem = NULL;
967 ret = drmHashLookup(bufmgr_sprd->hashBos, bo_sprd->name, (void **)&privGem);
969 privGem->ref_count--;
970 if (privGem->ref_count == 0) {
971 drmHashDelete(bufmgr_sprd->hashBos, bo_sprd->name);
976 TBM_SPRD_LOG("[libtbm-sprd:%d] "
977 "warning %s:%d Cannot find bo to Hash(%d), ret=%d\n",
978 getpid(), __FUNCTION__, __LINE__, bo_sprd->name, ret);
981 _bo_destroy_cache_state(bufmgr_sprd, bo_sprd);
983 /* Free gem handle */
984 struct drm_gem_close arg = {0, };
985 memset(&arg, 0, sizeof(arg));
986 arg.handle = bo_sprd->gem;
987 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_GEM_CLOSE, &arg)) {
988 TBM_SPRD_LOG("[libtbm-sprd:%d] "
990 getpid(), __FUNCTION__, __LINE__);
998 tbm_sprd_bo_import(tbm_bo bo, unsigned int key)
1000 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1002 tbm_bufmgr_sprd bufmgr_sprd;
1003 tbm_bo_sprd bo_sprd;
1004 PrivGem *privGem = NULL;
1007 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1008 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1010 ret = drmHashLookup(bufmgr_sprd->hashBos, key, (void **)&privGem);
1012 return privGem->bo_priv;
1014 struct drm_gem_open arg = {0, };
1015 struct drm_sprd_gem_info info = {0, };
1018 if (drmIoctl(bufmgr_sprd->fd, DRM_IOCTL_GEM_OPEN, &arg)) {
1019 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1020 "error %s:%d Cannot open gem name=%d\n",
1021 getpid(), __FUNCTION__, __LINE__, key);
1025 info.handle = arg.handle;
1026 if (drmCommandWriteRead(bufmgr_sprd->fd,
1029 sizeof(struct drm_sprd_gem_info))) {
1030 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1031 "error %s:%d Cannot get gem info=%d\n",
1032 getpid(), __FUNCTION__, __LINE__, key);
1036 bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
1038 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1039 "error %s:%d fail to allocate the bo private\n",
1040 getpid(), __FUNCTION__, __LINE__);
1044 bo_sprd->fd = bufmgr_sprd->fd;
1045 bo_sprd->gem = arg.handle;
1046 bo_sprd->size = arg.size;
1047 bo_sprd->flags_sprd = info.flags;
1048 bo_sprd->name = key;
1049 #ifdef USE_CONTIG_ONLY
1050 bo_sprd->flags_sprd = SPRD_BO_CONTIG;
1051 bo_sprd->flags_tbm |= TBM_BO_SCANOUT;
1053 bo_sprd->flags_tbm = _get_tbm_flag_from_sprd(bo_sprd->flags_sprd);
1056 if (!_bo_init_cache_state(bufmgr_sprd, bo_sprd, 1)) {
1057 TBM_SPRD_LOG("error fail init cache state(%d)\n", bo_sprd->name);
1062 if (!bo_sprd->dmabuf) {
1063 struct drm_prime_handle arg = {0, };
1065 arg.handle = bo_sprd->gem;
1066 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
1067 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1068 "error %s:%d Cannot dmabuf=%d\n",
1069 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
1073 bo_sprd->dmabuf = arg.fd;
1076 /* add bo to hash */
1077 privGem = calloc(1, sizeof(PrivGem));
1078 privGem->ref_count = 1;
1079 privGem->bo_priv = bo_sprd;
1080 if (drmHashInsert(bufmgr_sprd->hashBos, bo_sprd->name, (void *)privGem) < 0) {
1081 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1082 "error %s:%d Cannot insert bo to Hash(%d)\n",
1083 getpid(), __FUNCTION__, __LINE__, bo_sprd->name);
1086 DBG("[libtbm-sprd:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
1087 __FUNCTION__, bo_sprd->size,
1088 bo_sprd->gem, bo_sprd->name,
1089 bo_sprd->flags_tbm, bo_sprd->flags_sprd);
1091 return (void *)bo_sprd;
1095 tbm_sprd_bo_import_fd(tbm_bo bo, tbm_fd key)
1097 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1099 tbm_bufmgr_sprd bufmgr_sprd;
1100 tbm_bo_sprd bo_sprd;
1101 PrivGem *privGem = NULL;
1105 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1106 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1108 //getting handle from fd
1109 unsigned int gem = 0;
1110 struct drm_prime_handle arg = {0, };
1114 if (drmIoctl(bufmgr_sprd->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg)) {
1115 TBM_SPRD_LOG("error bo:%p Cannot get gem handle from fd:%d (%s)\n",
1116 bo, arg.fd, strerror(errno));
1121 name = _get_name(bufmgr_sprd->fd, gem);
1123 ret = drmHashLookup(bufmgr_sprd->hashBos, name, (void **)&privGem);
1125 if (gem == privGem->bo_priv->gem)
1126 return privGem->bo_priv;
1129 unsigned int real_size = -1;
1130 struct drm_sprd_gem_info info = {0, };
1132 /* Determine size of bo. The fd-to-handle ioctl really should
1133 * return the size, but it doesn't. If we have kernel 3.12 or
1134 * later, we can lseek on the prime fd to get the size. Older
1135 * kernels will just fail, in which case we fall back to the
1136 * provided (estimated or guess size). */
1137 real_size = lseek(key, 0, SEEK_END);
1140 if (drmCommandWriteRead(bufmgr_sprd->fd,
1143 sizeof(struct drm_sprd_gem_info))) {
1144 TBM_SPRD_LOG("error bo:%p Cannot get gem info from gem:%d, fd:%d (%s)\n",
1145 bo, gem, key, strerror(errno));
1149 if (real_size == -1)
1150 real_size = info.size;
1152 bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
1154 TBM_SPRD_LOG("error bo:%p fail to allocate the bo private\n", bo);
1158 bo_sprd->fd = bufmgr_sprd->fd;
1160 bo_sprd->size = real_size;
1161 bo_sprd->flags_sprd = info.flags;
1162 bo_sprd->flags_tbm = _get_tbm_flag_from_sprd(bo_sprd->flags_sprd);
1164 bo_sprd->name = name;
1165 if (!bo_sprd->name) {
1166 TBM_SPRD_LOG("error bo:%p Cannot get name from gem:%d, fd:%d (%s)\n",
1167 bo, gem, key, strerror(errno));
1172 if (!_bo_init_cache_state(bufmgr_sprd, bo_sprd, 1)) {
1173 TBM_SPRD_LOG("error fail init cache state(%d)\n", bo_sprd->name);
1178 /* add bo to hash */
1181 privGem = calloc(1, sizeof(PrivGem));
1183 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1184 "error %s:%d Fail to callocprivGem\n",
1185 getpid(), __FUNCTION__, __LINE__);
1190 privGem->ref_count = 1;
1191 privGem->bo_priv = bo_sprd;
1192 if (drmHashInsert(bufmgr_sprd->hashBos, bo_sprd->name, (void *)privGem) < 0) {
1193 TBM_SPRD_LOG("error bo:%p Cannot insert bo to Hash(%d) from gem:%d, fd:%d\n",
1194 bo, bo_sprd->name, gem, key);
1197 DBG(" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n",
1200 bo_sprd->gem, bo_sprd->name,
1203 bo_sprd->flags_tbm, bo_sprd->flags_sprd,
1206 return (void *)bo_sprd;
1210 tbm_sprd_bo_export(tbm_bo bo)
1212 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1214 tbm_bo_sprd bo_sprd;
1216 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1217 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1219 if (!bo_sprd->name) {
1220 bo_sprd->name = _get_name(bo_sprd->fd, bo_sprd->gem);
1221 if (!bo_sprd->name) {
1222 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1223 "error %s:%d Cannot get name\n",
1224 getpid(), __FUNCTION__, __LINE__);
1229 DBG("[libtbm-sprd:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
1230 __FUNCTION__, bo_sprd->size,
1231 bo_sprd->gem, bo_sprd->name,
1232 bo_sprd->flags_tbm, bo_sprd->flags_sprd);
1234 return (unsigned int)bo_sprd->name;
1238 tbm_sprd_bo_export_fd(tbm_bo bo)
1240 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, -1);
1242 tbm_bo_sprd bo_sprd;
1245 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1246 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, -1);
1248 struct drm_prime_handle arg = {0, };
1250 arg.handle = bo_sprd->gem;
1251 ret = drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg);
1253 TBM_SPRD_LOG("error bo:%p Cannot dmabuf=%d (%s)\n",
1254 bo, bo_sprd->gem, strerror(errno));
1255 return (tbm_fd) ret;
1258 DBG(" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n",
1261 bo_sprd->gem, bo_sprd->name,
1264 bo_sprd->flags_tbm, bo_sprd->flags_sprd,
1267 return (tbm_fd)arg.fd;
1271 static tbm_bo_handle
1272 tbm_sprd_bo_get_handle(tbm_bo bo, int device)
1274 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, (tbm_bo_handle) NULL);
1276 tbm_bo_handle bo_handle;
1277 tbm_bo_sprd bo_sprd;
1279 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1280 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, (tbm_bo_handle) NULL);
1282 if (!bo_sprd->gem) {
1283 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1284 "error %s:%d Cannot map gem=%d\n",
1285 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
1286 return (tbm_bo_handle) NULL;
1289 DBG("[libtbm-sprd:%d] %s gem:%d(%d), %s\n", getpid(),
1290 __FUNCTION__, bo_sprd->gem, bo_sprd->name, STR_DEVICE[device]);
1292 /*Get mapped bo_handle*/
1293 bo_handle = _sprd_bo_handle(bo_sprd, device);
1294 if (bo_handle.ptr == NULL) {
1295 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1296 "error %s:%d Cannot get handle: gem:%d, device:%d\n",
1297 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem, device);
1298 return (tbm_bo_handle) NULL;
1304 static tbm_bo_handle
1305 tbm_sprd_bo_map(tbm_bo bo, int device, int opt)
1307 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, (tbm_bo_handle) NULL);
1309 tbm_bo_handle bo_handle;
1310 tbm_bo_sprd bo_sprd;
1311 tbm_bufmgr_sprd bufmgr_sprd;
1313 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1314 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, (tbm_bo_handle) NULL);
1316 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1317 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, (tbm_bo_handle) NULL);
1319 if (!bo_sprd->gem) {
1320 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1321 "error %s:%d Cannot map gem=%d\n",
1322 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
1323 return (tbm_bo_handle) NULL;
1326 DBG("[libtbm-sprd:%d] %s gem:%d(%d), %s, %s\n", getpid(),
1327 __FUNCTION__, bo_sprd->gem, bo_sprd->name, STR_DEVICE[device], STR_OPT[opt]);
1329 /*Get mapped bo_handle*/
1330 bo_handle = _sprd_bo_handle(bo_sprd, device);
1331 if (bo_handle.ptr == NULL) {
1332 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1333 "error %s:%d Cannot get handle: gem:%d, device:%d, opt:%d\n",
1334 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem, device, opt);
1335 return (tbm_bo_handle) NULL;
1338 if (bo_sprd->map_cnt == 0)
1339 _bo_set_cache_state(bufmgr_sprd, bo_sprd, device, opt);
1347 tbm_sprd_bo_unmap(tbm_bo bo)
1349 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1351 tbm_bo_sprd bo_sprd;
1352 tbm_bufmgr_sprd bufmgr_sprd;
1354 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1355 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1357 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1358 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1365 if (bo_sprd->map_cnt == 0)
1366 _bo_save_cache_state(bufmgr_sprd, bo_sprd);
1368 DBG("[libtbm-sprd:%d] %s gem:%d(%d) \n", getpid(),
1369 __FUNCTION__, bo_sprd->gem, bo_sprd->name);
1375 tbm_sprd_bo_lock(tbm_bo bo, int device, int opt)
1377 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1379 tbm_bufmgr_sprd bufmgr_sprd;
1380 tbm_bo_sprd bo_sprd;
1382 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1383 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1385 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1386 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1388 #if USE_BACKEND_LOCK
1391 if (bufmgr_sprd->use_dma_fence) {
1393 struct dma_buf_fence fence;
1395 memset(&fence, 0, sizeof(struct dma_buf_fence));
1397 /* Check if the given type is valid or not. */
1398 if (opt & TBM_OPTION_WRITE) {
1399 if (device == TBM_DEVICE_CPU)
1400 fence.type = DMA_BUF_ACCESS_WRITE;
1401 else if (device == TBM_DEVICE_3D)
1402 fence.type = DMA_BUF_ACCESS_WRITE | DMA_BUF_ACCESS_DMA;
1404 DBG("[libtbm-sprd:%d] %s GET_FENCE is ignored(device type is not 3D/CPU),\n",
1405 getpid(), __FUNCTION__);
1408 } else if (opt & TBM_OPTION_READ) {
1409 if (device == TBM_DEVICE_CPU)
1410 fence.type = DMA_BUF_ACCESS_READ;
1411 else if (device == TBM_DEVICE_3D)
1412 fence.type = DMA_BUF_ACCESS_READ | DMA_BUF_ACCESS_DMA;
1414 DBG("[libtbm-sprd:%d] %s GET_FENCE is ignored(device type is not 3D/CPU),\n",
1415 getpid(), __FUNCTION__);
1419 TBM_SPRD_LOG("[libtbm-sprd:%d] error %s:%d Invalid argument\n", getpid(),
1420 __FUNCTION__, __LINE__);
1424 /* Check if the tbm manager supports dma fence or not. */
1425 if (!bufmgr_sprd->use_dma_fence) {
1426 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1427 "error %s:%d Not support DMA FENCE(%s)\n",
1428 getpid(), __FUNCTION__, __LINE__, strerror(errno));
1433 ret = ioctl(bo_sprd->dmabuf, DMABUF_IOCTL_GET_FENCE, &fence);
1435 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1436 "error %s:%d Can not set GET FENCE(%s)\n",
1437 getpid(), __FUNCTION__, __LINE__, strerror(errno));
1441 pthread_mutex_lock(&bo_sprd->mutex);
1443 for (i = 0; i < DMA_FENCE_LIST_MAX; i++) {
1444 if (bo_sprd->dma_fence[i].ctx == 0) {
1445 bo_sprd->dma_fence[i].type = fence.type;
1446 bo_sprd->dma_fence[i].ctx = fence.ctx;
1450 if (i == DMA_FENCE_LIST_MAX) {
1451 //TODO: if dma_fence list is full, it needs realloc. I will fix this. by minseok3.kim
1452 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1453 "error %s:%d fence list is full\n",
1454 getpid(), __FUNCTION__, __LINE__);
1456 pthread_mutex_unlock(&bo_sprd->mutex);
1458 DBG("[libtbm-sprd:%d] %s DMABUF_IOCTL_GET_FENCE! flink_id=%d dmabuf=%d\n",
1460 __FUNCTION__, bo_sprd->name, bo_sprd->dmabuf);
1463 ret = _tgl_lock(bufmgr_sprd->tgl_fd, bo_sprd->name);
1465 DBG("[libtbm-sprd:%d] lock tgl flink_id:%d\n",
1466 getpid(), __FUNCTION__, bo_sprd->name);
1476 tbm_sprd_bo_unlock(tbm_bo bo)
1478 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1480 tbm_bufmgr_sprd bufmgr_sprd;
1481 tbm_bo_sprd bo_sprd;
1483 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1484 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1486 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1487 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1489 #if USE_BACKEND_LOCK
1492 if (bufmgr_sprd->use_dma_fence) {
1493 struct dma_buf_fence fence;
1495 if (!bo_sprd->dma_fence[0].ctx) {
1496 DBG("[libtbm-sprd:%d] %s FENCE not support or ignored,\n", getpid(),
1501 if (!bo_sprd->dma_fence[0].type) {
1502 DBG("[libtbm-sprd:%d] %s device type is not 3D/CPU,\n", getpid(),
1507 pthread_mutex_lock(&bo_sprd->mutex);
1508 fence.type = bo_sprd->dma_fence[0].type;
1509 fence.ctx = bo_sprd->dma_fence[0].ctx;
1511 for (i = 1; i < DMA_FENCE_LIST_MAX; i++) {
1512 bo_sprd->dma_fence[i - 1].type = bo_sprd->dma_fence[i].type;
1513 bo_sprd->dma_fence[i - 1].ctx = bo_sprd->dma_fence[i].ctx;
1515 bo_sprd->dma_fence[DMA_FENCE_LIST_MAX - 1].type = 0;
1516 bo_sprd->dma_fence[DMA_FENCE_LIST_MAX - 1].ctx = 0;
1517 pthread_mutex_unlock(&bo_sprd->mutex);
1519 ret = ioctl(bo_sprd->dmabuf, DMABUF_IOCTL_PUT_FENCE, &fence);
1521 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1522 "error %s:%d Can not set PUT FENCE(%s)\n",
1523 getpid(), __FUNCTION__, __LINE__, strerror(errno));
1527 DBG("[libtbm-sprd:%d] %s DMABUF_IOCTL_PUT_FENCE! flink_id=%d dmabuf=%d\n",
1529 __FUNCTION__, bo_sprd->name, bo_sprd->dmabuf);
1531 ret = _tgl_unlock(bufmgr_sprd->tgl_fd, bo_sprd->name);
1533 DBG("[libtbm-sprd:%d] unlock tgl flink_id:%d\n",
1534 getpid(), __FUNCTION__, bo_sprd->name);
1544 tbm_sprd_bufmgr_deinit(void *priv)
1546 SPRD_RETURN_IF_FAIL(priv != NULL);
1548 tbm_bufmgr_sprd bufmgr_sprd;
1550 bufmgr_sprd = (tbm_bufmgr_sprd)priv;
1552 if (bufmgr_sprd->hashBos) {
1556 while (drmHashFirst(bufmgr_sprd->hashBos, &key, &value) > 0) {
1558 drmHashDelete(bufmgr_sprd->hashBos, key);
1561 drmHashDestroy(bufmgr_sprd->hashBos);
1562 bufmgr_sprd->hashBos = NULL;
1565 if (bufmgr_sprd->bind_display)
1566 tbm_drm_helper_wl_auth_server_deinit();
1568 if (tbm_backend_is_display_server())
1569 tbm_drm_helper_unset_tbm_master_fd();
1571 if (bufmgr_sprd->device_name)
1572 free(bufmgr_sprd->device_name);
1574 _bufmgr_deinit_cache_state(bufmgr_sprd);
1576 close(bufmgr_sprd->fd);
1582 tbm_sprd_surface_supported_format(uint32_t **formats, uint32_t *num)
1584 uint32_t *color_formats = NULL;
1586 color_formats = (uint32_t *)calloc(1,
1587 sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
1589 if (color_formats == NULL)
1592 memcpy(color_formats, tbm_sprd_color_format_list,
1593 sizeof(uint32_t)*TBM_COLOR_FORMAT_COUNT);
1596 *formats = color_formats;
1597 *num = TBM_COLOR_FORMAT_COUNT;
1605 * @brief get the plane data of the surface.
1606 * @param[in] width : the width of the surface
1607 * @param[in] height : the height of the surface
1608 * @param[in] format : the format of the surface
1609 * @param[in] plane_idx : the format of the surface
1610 * @param[out] size : the size of the plane
1611 * @param[out] offset : the offset of the plane
1612 * @param[out] pitch : the pitch of the plane
1613 * @param[out] padding : the padding of the plane
1614 * @return 1 if this function succeeds, otherwise 0.
1617 tbm_sprd_surface_get_plane_data(int width, int height,
1618 tbm_format format, int plane_idx, uint32_t *size, uint32_t *offset,
1619 uint32_t *pitch, int *bo_idx)
1627 int _align_height = 0;
1631 case TBM_FORMAT_XRGB4444:
1632 case TBM_FORMAT_XBGR4444:
1633 case TBM_FORMAT_RGBX4444:
1634 case TBM_FORMAT_BGRX4444:
1635 case TBM_FORMAT_ARGB4444:
1636 case TBM_FORMAT_ABGR4444:
1637 case TBM_FORMAT_RGBA4444:
1638 case TBM_FORMAT_BGRA4444:
1639 case TBM_FORMAT_XRGB1555:
1640 case TBM_FORMAT_XBGR1555:
1641 case TBM_FORMAT_RGBX5551:
1642 case TBM_FORMAT_BGRX5551:
1643 case TBM_FORMAT_ARGB1555:
1644 case TBM_FORMAT_ABGR1555:
1645 case TBM_FORMAT_RGBA5551:
1646 case TBM_FORMAT_BGRA5551:
1647 case TBM_FORMAT_RGB565:
1650 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1651 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1655 case TBM_FORMAT_RGB888:
1656 case TBM_FORMAT_BGR888:
1659 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1660 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1664 case TBM_FORMAT_XRGB8888:
1665 case TBM_FORMAT_XBGR8888:
1666 case TBM_FORMAT_RGBX8888:
1667 case TBM_FORMAT_BGRX8888:
1668 case TBM_FORMAT_ARGB8888:
1669 case TBM_FORMAT_ABGR8888:
1670 case TBM_FORMAT_RGBA8888:
1671 case TBM_FORMAT_BGRA8888:
1674 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1675 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1680 case TBM_FORMAT_YUYV:
1681 case TBM_FORMAT_YVYU:
1682 case TBM_FORMAT_UYVY:
1683 case TBM_FORMAT_VYUY:
1684 case TBM_FORMAT_AYUV:
1687 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1688 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1694 * index 0 = Y plane, [7:0] Y
1695 * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1697 * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1699 case TBM_FORMAT_NV12:
1700 case TBM_FORMAT_NV21:
1702 if (plane_idx == 0) {
1704 _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1705 _align_height = SIZE_ALIGN(height, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1706 _size = SIZE_ALIGN(_pitch * _align_height, TBM_SURFACE_ALIGNMENT_PLANE);
1708 } else if (plane_idx == 1) {
1709 _offset = width * height;
1710 _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1711 _align_height = SIZE_ALIGN(height / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1712 _size = SIZE_ALIGN(_pitch * _align_height, TBM_SURFACE_ALIGNMENT_PLANE);
1717 case TBM_FORMAT_NV16:
1718 case TBM_FORMAT_NV61:
1720 //if(plane_idx == 0)
1723 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1724 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1729 //else if( plane_idx ==1 )
1732 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1733 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1740 * index 0: Y plane, [7:0] Y
1741 * index 1: Cb plane, [7:0] Cb
1742 * index 2: Cr plane, [7:0] Cr
1744 * index 1: Cr plane, [7:0] Cr
1745 * index 2: Cb plane, [7:0] Cb
1748 NATIVE_BUFFER_FORMAT_YV12
1749 NATIVE_BUFFER_FORMAT_I420
1751 case TBM_FORMAT_YUV410:
1752 case TBM_FORMAT_YVU410:
1755 case TBM_FORMAT_YUV411:
1756 case TBM_FORMAT_YVU411:
1757 case TBM_FORMAT_YUV420:
1758 case TBM_FORMAT_YVU420:
1760 //if(plane_idx == 0)
1763 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1764 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1769 //else if( plane_idx == 1 )
1772 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1773 _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1778 //else if (plane_idx == 2 )
1781 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1782 _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1786 case TBM_FORMAT_YUV422:
1787 case TBM_FORMAT_YVU422:
1789 //if(plane_idx == 0)
1792 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1793 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1798 //else if( plane_idx == 1 )
1801 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1802 _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
1807 //else if (plane_idx == 2 )
1810 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1811 _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
1815 case TBM_FORMAT_YUV444:
1816 case TBM_FORMAT_YVU444:
1818 //if(plane_idx == 0)
1821 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1822 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1827 //else if( plane_idx == 1 )
1830 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1831 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1836 //else if (plane_idx == 2 )
1839 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1840 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1858 tbm_sprd_bo_get_flags(tbm_bo bo)
1860 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1862 tbm_bo_sprd bo_sprd;
1864 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1865 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1867 return bo_sprd->flags_tbm;
1871 tbm_sprd_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1873 tbm_bufmgr_sprd bufmgr_sprd;
1875 bufmgr_sprd = tbm_backend_get_priv_from_bufmgr(bufmgr);
1876 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1878 if (!tbm_drm_helper_wl_auth_server_init(NativeDisplay, bufmgr_sprd->fd,
1879 bufmgr_sprd->device_name, 0)) {
1880 TBM_SPRD_LOG("[libtbm-sprd:%d] error:Fail to tbm_drm_helper_wl_server_init\n");
1884 bufmgr_sprd->bind_display = NativeDisplay;
1889 MODULEINITPPROTO(init_tbm_bufmgr_priv);
1891 static TBMModuleVersionInfo SprdVersRec = {
1897 TBMModuleData tbmModuleData = { &SprdVersRec, init_tbm_bufmgr_priv};
1900 init_tbm_bufmgr_priv(tbm_bufmgr bufmgr, int fd)
1902 tbm_bufmgr_backend bufmgr_backend;
1903 tbm_bufmgr_sprd bufmgr_sprd;
1909 bufmgr_sprd = calloc(1, sizeof(struct _tbm_bufmgr_sprd));
1911 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to alloc bufmgr_sprd!\n", getpid());
1915 if (tbm_backend_is_display_server()) {
1916 bufmgr_sprd->fd = tbm_drm_helper_get_master_fd();
1917 if (bufmgr_sprd->fd < 0) {
1918 bufmgr_sprd->fd = _tbm_sprd_open_drm();
1919 if (bufmgr_sprd->fd < 0) {
1920 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to open drm!\n", getpid());
1925 tbm_drm_helper_set_tbm_master_fd(bufmgr_sprd->fd);
1927 bufmgr_sprd->device_name = drmGetDeviceNameFromFd(bufmgr_sprd->fd);
1928 if (!bufmgr_sprd->device_name) {
1929 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to get device name!\n", getpid());
1930 tbm_drm_helper_unset_tbm_master_fd();
1931 goto fail_get_device_name;
1934 if (!tbm_drm_helper_get_auth_info(&(bufmgr_sprd->fd), &(bufmgr_sprd->device_name), NULL)) {
1935 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to get auth drm info!\n", getpid());
1936 goto fail_get_auth_info;
1941 bufmgr_sprd->hashBos = drmHashCreate();
1943 //Check if the tbm manager supports dma fence or not.
1944 fp = open("/sys/module/dmabuf_sync/parameters/enabled", O_RDONLY);
1947 int length = read(fp, buf, 1);
1949 if (length == 1 && buf[0] == '1')
1950 bufmgr_sprd->use_dma_fence = 1;
1955 if (!_bufmgr_init_cache_state(bufmgr_sprd)) {
1956 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to init bufmgr cache state\n", getpid());
1957 goto fail_init_cache_state;
1960 bufmgr_backend = tbm_backend_alloc();
1961 if (!bufmgr_backend) {
1962 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to alloc backend!\n", getpid());
1963 goto fail_alloc_backend;
1966 bufmgr_backend->priv = (void *)bufmgr_sprd;
1967 bufmgr_backend->bufmgr_deinit = tbm_sprd_bufmgr_deinit;
1968 bufmgr_backend->bo_size = tbm_sprd_bo_size;
1969 bufmgr_backend->bo_alloc = tbm_sprd_bo_alloc;
1970 bufmgr_backend->bo_free = tbm_sprd_bo_free;
1971 bufmgr_backend->bo_import = tbm_sprd_bo_import;
1972 bufmgr_backend->bo_import_fd = tbm_sprd_bo_import_fd;
1973 bufmgr_backend->bo_export = tbm_sprd_bo_export;
1974 bufmgr_backend->bo_export_fd = tbm_sprd_bo_export_fd;
1975 bufmgr_backend->bo_get_handle = tbm_sprd_bo_get_handle;
1976 bufmgr_backend->bo_map = tbm_sprd_bo_map;
1977 bufmgr_backend->bo_unmap = tbm_sprd_bo_unmap;
1978 bufmgr_backend->surface_get_plane_data = tbm_sprd_surface_get_plane_data;
1979 bufmgr_backend->surface_supported_format = tbm_sprd_surface_supported_format;
1980 bufmgr_backend->bo_get_flags = tbm_sprd_bo_get_flags;
1981 bufmgr_backend->bo_lock = tbm_sprd_bo_lock;
1982 bufmgr_backend->bo_unlock = tbm_sprd_bo_unlock;
1983 bufmgr_backend->bufmgr_bind_native_display = tbm_sprd_bufmgr_bind_native_display;
1985 if (!tbm_backend_init(bufmgr, bufmgr_backend)) {
1986 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to init backend!\n", getpid());
1987 goto fail_init_backend;
1994 env = getenv("TBM_SPRD_DEBUG");
1997 TBM_SPRD_LOG("TBM_SPRD_DEBUG=%s\n", env);
2003 DBG("[libtbm-sprd:%d] %s DMABUF FENCE is %s\n", getpid(),
2004 __FUNCTION__, bufmgr_sprd->use_dma_fence ? "supported!" : "NOT supported!");
2005 DBG("[libtbm-sprd:%d] %s fd:%d\n", getpid(),
2006 __FUNCTION__, bufmgr_sprd->fd);
2011 tbm_backend_free(bufmgr_backend);
2013 _bufmgr_deinit_cache_state(bufmgr_sprd);
2014 fail_init_cache_state:
2015 if (bufmgr_sprd->hashBos)
2016 drmHashDestroy(bufmgr_sprd->hashBos);
2017 if (tbm_backend_is_display_server())
2018 tbm_drm_helper_unset_tbm_master_fd();
2019 fail_get_device_name:
2020 close(bufmgr_sprd->fd);