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
65 #define TBM_COLOR_FORMAT_COUNT 4
68 #define LOG_TAG "TBM_BACKEND"
70 static int bDebug = 0;
72 #define SPRD_DRM_NAME "sprd"
77 static char app_name[128] = {0, };
78 static int initialized = 0;
85 /* get the application name */
86 f = fopen("/proc/self/cmdline", "r");
90 if (fgets(app_name, 100, f) == NULL) {
97 slash = strrchr(app_name, '/');
99 memmove(app_name, slash + 1, strlen(slash));
105 #define TBM_SPRD_LOG(fmt, args...) LOGE("\033[31m" "[%s]" fmt "\033[0m", _target_name(), ##args)
106 #define DBG(fmt, args...) if (bDebug&01) LOGE("[%s]" fmt, _target_name(), ##args)
108 #define TBM_SPRD_LOG(...)
112 #define SIZE_ALIGN(value, base) (((value) + ((base) - 1)) & ~((base) - 1))
114 #define TBM_SURFACE_ALIGNMENT_PLANE (64)
115 #define TBM_SURFACE_ALIGNMENT_PITCH_RGB (128)
116 #define TBM_SURFACE_ALIGNMENT_PITCH_YUV (16)
119 /* check condition */
120 #define SPRD_RETURN_IF_FAIL(cond) {\
122 TBM_SPRD_LOG("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
126 #define SPRD_RETURN_VAL_IF_FAIL(cond, val) {\
128 TBM_SPRD_LOG("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
133 struct dma_buf_info {
135 unsigned int fence_supported;
136 unsigned int padding;
139 #define DMA_BUF_ACCESS_READ 0x1
140 #define DMA_BUF_ACCESS_WRITE 0x2
141 #define DMA_BUF_ACCESS_DMA 0x4
142 #define DMA_BUF_ACCESS_MAX 0x8
144 #define DMA_FENCE_LIST_MAX 5
146 struct dma_buf_fence {
151 #define DMABUF_IOCTL_BASE 'F'
152 #define DMABUF_IOWR(nr, type) _IOWR(DMABUF_IOCTL_BASE, nr, type)
154 #define DMABUF_IOCTL_GET_INFO DMABUF_IOWR(0x00, struct dma_buf_info)
155 #define DMABUF_IOCTL_GET_FENCE DMABUF_IOWR(0x01, struct dma_buf_fence)
156 #define DMABUF_IOCTL_PUT_FENCE DMABUF_IOWR(0x02, struct dma_buf_fence)
159 #define GLOBAL_KEY ((unsigned int)(-1))
161 #define TBM_SPRD_CACHE_INV 0x01 /**< cache invalidate */
162 #define TBM_SPRD_CACHE_CLN 0x02 /**< cache clean */
163 #define TBM_SPRD_CACHE_ALL 0x10 /**< cache all */
164 #define TBM_SPRD_CACHE_FLUSH (TBM_SPRD_CACHE_INV|TBM_SPRD_CACHE_CLN) /**< cache flush */
165 #define TBM_SPRD_CACHE_FLUSH_ALL (TBM_SPRD_CACHE_FLUSH|TBM_SPRD_CACHE_ALL) /**< cache flush all */
169 DEVICE_CA, /* cache aware device */
170 DEVICE_CO /* cache oblivious device */
173 typedef union _tbm_bo_cache_state tbm_bo_cache_state;
175 union _tbm_bo_cache_state {
178 unsigned int cntFlush:16; /*Flush all index for sync */
179 unsigned int isCached:1;
180 unsigned int isDirtied:2;
184 typedef struct _tbm_bufmgr_sprd *tbm_bufmgr_sprd;
185 typedef struct _tbm_bo_sprd *tbm_bo_sprd;
187 typedef struct _sprd_private {
189 struct _tbm_bo_sprd *bo_priv;
192 /* tbm buffor object for sprd */
193 struct _tbm_bo_sprd {
196 unsigned int name; /* FLINK ID */
198 unsigned int gem; /* GEM Handle */
200 unsigned int dmabuf; /* fd for dmabuf */
202 void *pBase; /* virtual address */
206 unsigned int flags_sprd;
207 unsigned int flags_tbm;
211 pthread_mutex_t mutex;
212 struct dma_buf_fence dma_fence[DMA_FENCE_LIST_MAX];
216 tbm_bo_cache_state cache_state;
217 unsigned int map_cnt;
220 /* tbm bufmgr private for sprd */
221 struct _tbm_bufmgr_sprd {
233 char *STR_DEVICE[] = {
249 uint32_t tbm_sprd_color_format_list[TBM_COLOR_FORMAT_COUNT] = {
257 _tgl_get_version(int fd)
259 struct tgl_ver_data data;
262 err = ioctl(fd, TGL_IOCTL_GET_VERSION, &data);
264 TBM_SPRD_LOG("[libtbm-sprd:%d] error(%s) %s:%d\n",
265 getpid(), strerror(errno), __func__, __LINE__);
269 TBM_SPRD_LOG("[libtbm-sprd:%d] %s:%d tgl version is (%u, %u).\n",
270 getpid(), __func__, __LINE__, data.major, data.minor);
277 _tgl_init(int fd, unsigned int key)
279 struct tgl_reg_data data;
283 data.timeout_ms = 1000;
285 err = ioctl(fd, TGL_IOCTL_REGISTER, &data);
287 TBM_SPRD_LOG("[libtbm-sprd:%d] error(%s) %s:%d key:%d\n",
288 getpid(), strerror(errno), __func__, __LINE__, key);
296 _tgl_destroy(int fd, unsigned int key)
298 struct tgl_reg_data data;
302 err = ioctl(fd, TGL_IOCTL_UNREGISTER, &data);
304 TBM_SPRD_LOG("[libtbm-sprd:%d] error(%s) %s:%d key:%d\n",
305 getpid(), strerror(errno), __func__, __LINE__, key);
313 _tgl_lock(int fd, unsigned int key, int opt)
315 struct tgl_lock_data data;
316 enum tgl_type_data tgl_type;
320 case TBM_OPTION_READ:
321 tgl_type = TGL_TYPE_READ;
323 case TBM_OPTION_WRITE:
324 tgl_type = TGL_TYPE_WRITE;
327 tgl_type = TGL_TYPE_NONE;
332 data.type = tgl_type;
334 err = ioctl(fd, TGL_IOCTL_LOCK, data);
336 TBM_SPRD_LOG("[libtbm-sprd:%d] error(%s) %s:%d key:%d opt:%d\n",
337 getpid(), strerror(errno), __func__, __LINE__, key, opt);
345 _tgl_unlock(int fd, unsigned int key)
347 struct tgl_lock_data data;
351 data.type = TGL_TYPE_NONE;
353 err = ioctl(fd, TGL_IOCTL_UNLOCK, data);
355 TBM_SPRD_LOG("[libtbm-sprd:%d] error(%s) %s:%d key:%d\n",
356 getpid(), strerror(errno), __func__, __LINE__, key);
365 _tgl_set_data(int fd, unsigned int key, unsigned int val)
367 struct tgl_usr_data data;
373 err = ioctl(fd, TGL_IOCTL_SET_DATA, &data);
375 TBM_SPRD_LOG("[libtbm-sprd:%d] error(%s) %s:%d key:%d\n",
376 getpid(), strerror(errno), __func__, __LINE__, key);
383 static inline unsigned int
384 _tgl_get_data(int fd, unsigned int key, unsigned int *locked)
386 struct tgl_usr_data data = { 0, };
391 err = ioctl(fd, TGL_IOCTL_GET_DATA, &data);
393 TBM_SPRD_LOG("[libtbm-sprd:%d] error(%s) %s:%d key:%d\n",
394 getpid(), strerror(errno), __func__, __LINE__, key);
399 *locked = (unsigned int)data.status;
406 _tbm_sprd_open_drm(void)
409 struct udev_device *drm_device = NULL;
410 struct udev_list_entry *entry = NULL;
411 struct udev_enumerate *e;
412 const char *filepath;
418 fd = drmOpen(SPRD_DRM_NAME, NULL);
423 TBM_SPRD_LOG("[libtbm-sprd:%d] warning %s:%d fail to open drm, "
424 "so search drm-device by udev\n",
425 getpid(), __FUNCTION__, __LINE__);
429 TBM_SPRD_LOG("udev_new() failed.\n");
433 e = udev_enumerate_new(udev);
434 udev_enumerate_add_match_subsystem(e, "drm");
435 udev_enumerate_add_match_sysname(e, "card[0-9]*");
436 udev_enumerate_scan_devices(e);
438 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
439 struct udev_device *device, *device_parent;
441 device = udev_device_new_from_syspath(udev_enumerate_get_udev(e),
442 udev_list_entry_get_name(entry));
443 device_parent = udev_device_get_parent(device);
444 /* Not need unref device_parent. device_parent and device have same refcnt */
446 if (strcmp(udev_device_get_sysname(device_parent), "sprd-drm") == 0) {
448 DBG("[%s] Found render device: '%s' (%s)\n",
450 udev_device_get_syspath(drm_device),
451 udev_device_get_sysname(device_parent));
455 udev_device_unref(device);
458 udev_enumerate_unref(e);
460 /* Get device file path. */
461 filepath = udev_device_get_devnode(drm_device);
463 TBM_SPRD_LOG("udev_device_get_devnode() failed.\n");
464 udev_device_unref(drm_device);
469 udev_device_unref(drm_device);
472 /* Open DRM device file and check validity. */
473 fd = open(filepath, O_RDWR | O_CLOEXEC);
475 TBM_SPRD_LOG("open(%s, O_RDWR | O_CLOEXEC) failed.\n");
480 TBM_SPRD_LOG("fstat() failed %s.\n");
485 TBM_SPRD_LOG("[libtbm-sprd:%d] warning %s:%d fail to open drm\n",
486 getpid(), __FUNCTION__, __LINE__);
494 _sprd_bo_cache_flush(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int flags)
496 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
498 /* cache flush is managed by kernel side when using dma-fence. */
499 if (bufmgr_sprd->use_dma_fence)
501 // TODO: The tm1 kernel does not support ioctl for cache flush right now.
502 // The drm in tm1 kernel has to support cache_flush to turn on this feature(TBM_SRPD_CACHE_FLUSH).
503 #if TBM_SRPD_CACHE_FLUSH
504 struct drm_sprd_gem_cache_op cache_op = {0, };
507 /* if bo_sprd is null, do cache_flush_all */
510 cache_op.usr_addr = (uint64_t)((uint32_t)bo_sprd->pBase);
511 cache_op.size = bo_sprd->size;
513 flags = TBM_SPRD_CACHE_FLUSH_ALL;
515 cache_op.usr_addr = 0;
519 if (flags & TBM_SPRD_CACHE_INV) {
520 if (flags & TBM_SPRD_CACHE_ALL)
521 cache_op.flags |= SPRD_DRM_CACHE_INV_ALL;
523 cache_op.flags |= SPRD_DRM_CACHE_INV_RANGE;
526 if (flags & TBM_SPRD_CACHE_CLN) {
527 if (flags & TBM_SPRD_CACHE_ALL)
528 cache_op.flags |= SPRD_DRM_CACHE_CLN_ALL;
530 cache_op.flags |= SPRD_DRM_CACHE_CLN_RANGE;
533 if (flags & TBM_SPRD_CACHE_ALL)
534 cache_op.flags |= SPRD_DRM_ALL_CACHES_CORES;
536 ret = drmCommandWriteRead(bufmgr_sprd->fd, DRM_SPRD_GEM_CACHE_OP, &cache_op,
539 TBM_SPRD_LOG("[libtbm-sprd:%d] "
540 "error %s:%d fail to flush the cache.\n",
541 getpid(), __FUNCTION__, __LINE__);
550 _bo_init_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int import)
552 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
553 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
555 if (bufmgr_sprd->use_dma_fence)
558 _tgl_init(bufmgr_sprd->tgl_fd, bo_sprd->name);
561 tbm_bo_cache_state cache_state;
564 cache_state.data.isDirtied = DEVICE_NONE;
565 cache_state.data.isCached = 0;
566 cache_state.data.cntFlush = 0;
568 _tgl_set_data(bufmgr_sprd->tgl_fd, bo_sprd->name, cache_state.val);
576 _bo_set_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int device, int opt)
579 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
580 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
583 unsigned short cntFlush = 0;
585 if (bufmgr_sprd->use_dma_fence)
588 if (bo_sprd->flags_sprd & SPRD_BO_NONCACHABLE)
591 /* get cache state of a bo */
592 bo_sprd->cache_state.val = _tgl_get_data(bufmgr_sprd->tgl_fd, bo_sprd->name, NULL);
594 /* get global cache flush count */
595 cntFlush = (unsigned short)_tgl_get_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, NULL);
597 if (opt == TBM_DEVICE_CPU) {
598 if (bo_sprd->cache_state.data.isDirtied == DEVICE_CO &&
599 bo_sprd->cache_state.data.isCached)
600 need_flush = TBM_SPRD_CACHE_INV;
602 bo_sprd->cache_state.data.isCached = 1;
603 if (opt & TBM_OPTION_WRITE)
604 bo_sprd->cache_state.data.isDirtied = DEVICE_CA;
606 if (bo_sprd->cache_state.data.isDirtied != DEVICE_CA)
607 bo_sprd->cache_state.data.isDirtied = DEVICE_NONE;
610 if (bo_sprd->cache_state.data.isDirtied == DEVICE_CA &&
611 bo_sprd->cache_state.data.isCached &&
612 bo_sprd->cache_state.data.cntFlush == cntFlush)
613 need_flush = TBM_SPRD_CACHE_CLN | TBM_SPRD_CACHE_ALL;
615 if (opt & TBM_OPTION_WRITE)
616 bo_sprd->cache_state.data.isDirtied = DEVICE_CO;
618 if (bo_sprd->cache_state.data.isDirtied != DEVICE_CO)
619 bo_sprd->cache_state.data.isDirtied = DEVICE_NONE;
624 if (need_flush & TBM_SPRD_CACHE_ALL)
625 _tgl_set_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, (unsigned int)(++cntFlush));
627 /* call cache flush */
628 _sprd_bo_cache_flush(bufmgr_sprd, bo_sprd, need_flush);
630 DBG("[libtbm:%d] \tcache(%d,%d)....flush:0x%x, cntFlush(%d)\n",
632 bo_sprd->cache_state.data.isCached,
633 bo_sprd->cache_state.data.isDirtied,
643 _bo_save_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd)
646 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
647 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
649 if (bufmgr_sprd->use_dma_fence)
652 unsigned short cntFlush = 0;
654 /* get global cache flush count */
655 cntFlush = (unsigned short)_tgl_get_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, NULL);
657 /* save global cache flush count */
658 bo_sprd->cache_state.data.cntFlush = cntFlush;
659 _tgl_set_data(bufmgr_sprd->tgl_fd, bo_sprd->name, bo_sprd->cache_state.val);
666 _bo_destroy_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd)
668 SPRD_RETURN_IF_FAIL(bo_sprd != NULL);
669 SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
671 if (bufmgr_sprd->use_dma_fence)
674 _tgl_destroy(bufmgr_sprd->tgl_fd, bo_sprd->name);
678 _bufmgr_init_cache_state(tbm_bufmgr_sprd bufmgr_sprd)
680 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
682 if (bufmgr_sprd->use_dma_fence)
685 /* open tgl fd for saving cache flush data */
686 bufmgr_sprd->tgl_fd = open(tgl_devfile, O_RDWR);
687 if (bufmgr_sprd->tgl_fd < 0) {
688 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to open global_lock:%s\n",
689 getpid(), tgl_devfile);
693 if (!_tgl_get_version(bufmgr_sprd->tgl_fd)) {
694 TBM_SPRD_LOG("[libtbm-sprd:%d] "
695 "error: fail to get tgl_version. tgl init failed.\n",
698 close(bufmgr_sprd->tgl_fd);
703 if (!_tgl_init(bufmgr_sprd->tgl_fd, GLOBAL_KEY)) {
704 TBM_SPRD_LOG("[libtbm-sprd:%d] "
705 "error: Fail to initialize the tgl\n",
708 close(bufmgr_sprd->tgl_fd);
717 _bufmgr_deinit_cache_state(tbm_bufmgr_sprd bufmgr_sprd)
719 SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
721 if (bufmgr_sprd->use_dma_fence)
724 if (bufmgr_sprd->tgl_fd >= 0)
725 close(bufmgr_sprd->tgl_fd);
728 #ifndef USE_CONTIG_ONLY
730 _get_sprd_flag_from_tbm(unsigned int ftbm)
732 unsigned int flags = 0;
735 * TBM_BO_DEFAULT => ION_HEAP_ID_MASK_SYSTEM
736 * TBM_BO_SCANOUT => ION_HEAP_ID_MASK_MM
737 * TBM_BO_VENDOR => ION_HEAP_ID_MASK_OVERLAY
738 * To be updated appropriately once DRM-GEM supports different heap id masks.
741 if (ftbm & TBM_BO_SCANOUT)
742 flags = SPRD_BO_CONTIG;
744 flags = SPRD_BO_NONCONTIG | SPRD_BO_DEV_SYSTEM;
746 if (ftbm & TBM_BO_WC)
748 else if (ftbm & TBM_BO_NONCACHABLE)
749 flags |= SPRD_BO_NONCACHABLE;
755 _get_tbm_flag_from_sprd(unsigned int fsprd)
757 unsigned int flags = 0;
759 if (fsprd & SPRD_BO_NONCONTIG)
760 flags |= TBM_BO_DEFAULT;
762 flags |= TBM_BO_SCANOUT;
764 if (fsprd & SPRD_BO_WC)
766 else if (fsprd & SPRD_BO_CACHABLE)
767 flags |= TBM_BO_DEFAULT;
769 flags |= TBM_BO_NONCACHABLE;
776 _get_name(int fd, unsigned int gem)
778 struct drm_gem_flink arg = {0,};
781 if (drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &arg)) {
782 TBM_SPRD_LOG("[libtbm-sprd:%d] "
783 "error %s:%d fail to get flink gem=%d\n",
784 getpid(), __FUNCTION__, __LINE__, gem);
788 return (unsigned int)arg.name;
792 _sprd_bo_handle(tbm_bo_sprd bo_sprd, int device)
794 tbm_bo_handle bo_handle;
795 memset(&bo_handle, 0x0, sizeof(uint64_t));
798 case TBM_DEVICE_DEFAULT:
800 bo_handle.u32 = (uint32_t)bo_sprd->gem;
803 if (!bo_sprd->pBase) {
804 struct drm_sprd_gem_mmap arg = {0,};
806 arg.handle = bo_sprd->gem;
807 arg.size = bo_sprd->size;
808 if (drmCommandWriteRead(bo_sprd->fd, DRM_SPRD_GEM_MMAP, &arg, sizeof(arg))) {
809 TBM_SPRD_LOG("[libtbm-sprd:%d] "
810 "error %s:%d Cannot usrptr gem=%d\n",
811 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
812 return (tbm_bo_handle) NULL;
814 bo_sprd->pBase = (void *)((uint32_t)arg.mapped);
817 bo_handle.ptr = (void *)bo_sprd->pBase;
821 if (!bo_sprd->dmabuf) {
822 struct drm_prime_handle arg = {0, };
823 arg.handle = bo_sprd->gem;
824 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
825 TBM_SPRD_LOG("[libtbm-sprd:%d] "
826 "error %s:%d Cannot dmabuf=%d\n",
827 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
828 return (tbm_bo_handle) NULL;
830 bo_sprd->dmabuf = arg.fd;
833 bo_handle.u32 = (uint32_t)bo_sprd->dmabuf;
840 //TODO : Add ioctl for GSP MAP once available.
841 DBG("[libtbm-sprd:%d] %s In case TBM_DEVICE_MM: \n", getpid(),
846 if (!bo_sprd->dmabuf) {
847 struct drm_prime_handle arg = {0, };
849 arg.handle = bo_sprd->gem;
850 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
851 TBM_SPRD_LOG("[libtbm-sprd:%d] "
852 "error %s:%d Cannot dmabuf=%d\n",
853 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
854 return (tbm_bo_handle) NULL;
856 bo_sprd->dmabuf = arg.fd;
859 bo_handle.u32 = (uint32_t)bo_sprd->dmabuf;
863 bo_handle.ptr = (void *) NULL;
871 tbm_sprd_bo_size(tbm_bo bo)
873 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
877 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
878 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
880 return bo_sprd->size;
884 tbm_sprd_bo_alloc(tbm_bo bo, int size, int flags)
886 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
888 tbm_bufmgr_sprd bufmgr_sprd;
889 unsigned int sprd_flags;
892 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
893 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
895 bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
897 TBM_SPRD_LOG("[libtbm-sprd:%d] "
898 "error %s:%d fail to allocate the bo private\n",
899 getpid(), __FUNCTION__, __LINE__);
903 #ifdef USE_CONTIG_ONLY
904 flags = TBM_BO_SCANOUT;
905 sprd_flags = SPRD_BO_CONTIG;
907 sprd_flags = _get_sprd_flag_from_tbm(flags);
908 if ((flags & TBM_BO_SCANOUT) && (size <= 4 * 1024))
909 sprd_flags |= SPRD_BO_NONCONTIG;
910 #endif // USE_CONTIG_ONLY
912 struct drm_sprd_gem_create arg = {0, };
913 arg.size = (uint64_t)size;
914 arg.flags = sprd_flags;
915 if (drmCommandWriteRead(bufmgr_sprd->fd, DRM_SPRD_GEM_CREATE, &arg,
917 TBM_SPRD_LOG("[libtbm-sprd:%d] "
918 "error %s:%d Cannot create bo(flag:%x, size:%d)\n",
919 getpid(), __FUNCTION__, __LINE__, arg.flags, (unsigned int)arg.size);
924 bo_sprd->fd = bufmgr_sprd->fd;
925 bo_sprd->gem = arg.handle;
926 bo_sprd->size = size;
927 bo_sprd->flags_tbm = flags;
928 bo_sprd->flags_sprd = sprd_flags;
929 bo_sprd->name = _get_name(bo_sprd->fd, bo_sprd->gem);
931 if (!_bo_init_cache_state(bufmgr_sprd, bo_sprd, 0)) {
932 TBM_SPRD_LOG("error fail init cache state(%d)\n", bo_sprd->name);
937 pthread_mutex_init(&bo_sprd->mutex, NULL);
939 if (bufmgr_sprd->use_dma_fence
940 && !bo_sprd->dmabuf) {
941 struct drm_prime_handle arg = {0, };
943 arg.handle = bo_sprd->gem;
944 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
945 TBM_SPRD_LOG("[libtbm-sprd:%d] "
946 "error %s:%d Cannot dmabuf=%d\n",
947 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
951 bo_sprd->dmabuf = arg.fd;
955 PrivGem *privGem = calloc(1, sizeof(PrivGem));
957 TBM_SPRD_LOG("[libtbm-sprd:%d] "
958 "error %s:%d Fail to calloc PrivGem\n",
959 getpid(), __FUNCTION__, __LINE__);
964 privGem->ref_count = 1;
965 privGem->bo_priv = bo_sprd;
966 if (drmHashInsert(bufmgr_sprd->hashBos, bo_sprd->name, (void *)privGem) < 0) {
967 TBM_SPRD_LOG("[libtbm-sprd:%d] "
968 "error %s:%d Cannot insert bo to Hash(%d)\n",
969 getpid(), __FUNCTION__, __LINE__, bo_sprd->name);
972 DBG("[libtbm-sprd:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
973 __FUNCTION__, bo_sprd->size,
974 bo_sprd->gem, bo_sprd->name,
977 return (void *)bo_sprd;
981 tbm_sprd_bo_free(tbm_bo bo)
984 tbm_bufmgr_sprd bufmgr_sprd;
989 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
990 SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
992 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
993 SPRD_RETURN_IF_FAIL(bo_sprd != NULL);
995 DBG("[libtbm-sprd:%d] %s size:%d, gem:%d(%d)\n",
996 getpid(), __FUNCTION__, bo_sprd->size, bo_sprd->gem, bo_sprd->name);
998 if (bo_sprd->pBase) {
999 if (munmap(bo_sprd->pBase, bo_sprd->size) == -1) {
1000 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1002 getpid(), __FUNCTION__, __LINE__);
1007 if (bo_sprd->dmabuf) {
1008 close(bo_sprd->dmabuf);
1009 bo_sprd->dmabuf = 0;
1012 /* delete bo from hash */
1013 PrivGem *privGem = NULL;
1016 ret = drmHashLookup(bufmgr_sprd->hashBos, bo_sprd->name, (void **)&privGem);
1018 privGem->ref_count--;
1019 if (privGem->ref_count == 0) {
1020 drmHashDelete(bufmgr_sprd->hashBos, bo_sprd->name);
1025 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1026 "warning %s:%d Cannot find bo to Hash(%d), ret=%d\n",
1027 getpid(), __FUNCTION__, __LINE__, bo_sprd->name, ret);
1030 _bo_destroy_cache_state(bufmgr_sprd, bo_sprd);
1032 /* Free gem handle */
1033 struct drm_gem_close arg = {0, };
1034 memset(&arg, 0, sizeof(arg));
1035 arg.handle = bo_sprd->gem;
1036 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_GEM_CLOSE, &arg)) {
1037 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1039 getpid(), __FUNCTION__, __LINE__);
1047 tbm_sprd_bo_import(tbm_bo bo, unsigned int key)
1049 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, NULL);
1051 tbm_bufmgr_sprd bufmgr_sprd;
1052 tbm_bo_sprd bo_sprd;
1053 PrivGem *privGem = NULL;
1056 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1057 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, NULL);
1059 ret = drmHashLookup(bufmgr_sprd->hashBos, key, (void **)&privGem);
1061 return privGem->bo_priv;
1063 struct drm_sprd_gem_info info = {0, };
1064 struct drm_gem_open arg = {0, };
1067 if (drmIoctl(bufmgr_sprd->fd, DRM_IOCTL_GEM_OPEN, &arg)) {
1068 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1069 "error %s:%d Cannot open gem name=%d\n",
1070 getpid(), __FUNCTION__, __LINE__, key);
1074 info.handle = arg.handle;
1075 if (drmCommandWriteRead(bufmgr_sprd->fd,
1078 sizeof(struct drm_sprd_gem_info))) {
1079 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1080 "error %s:%d Cannot get gem info=%d\n",
1081 getpid(), __FUNCTION__, __LINE__, key);
1085 bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
1087 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1088 "error %s:%d fail to allocate the bo private\n",
1089 getpid(), __FUNCTION__, __LINE__);
1093 bo_sprd->fd = bufmgr_sprd->fd;
1094 bo_sprd->gem = arg.handle;
1095 bo_sprd->size = arg.size;
1096 bo_sprd->flags_sprd = info.flags;
1097 bo_sprd->name = key;
1098 #ifdef USE_CONTIG_ONLY
1099 bo_sprd->flags_sprd = SPRD_BO_CONTIG;
1100 bo_sprd->flags_tbm |= TBM_BO_SCANOUT;
1102 bo_sprd->flags_tbm = _get_tbm_flag_from_sprd(bo_sprd->flags_sprd);
1105 if (!_bo_init_cache_state(bufmgr_sprd, bo_sprd, 1)) {
1106 TBM_SPRD_LOG("error fail init cache state(%d)\n", bo_sprd->name);
1107 goto fail_init_cache;
1110 if (!bo_sprd->dmabuf) {
1111 struct drm_prime_handle arg = {0, };
1113 arg.handle = bo_sprd->gem;
1114 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
1115 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1116 "error %s:%d Cannot dmabuf=%d\n",
1117 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
1118 goto fail_prime_handle_to_fd;
1120 bo_sprd->dmabuf = arg.fd;
1123 /* add bo to hash */
1124 privGem = calloc(1, sizeof(PrivGem));
1126 TBM_SPRD_LOG("[libtbm-sprd:%d] error %s:%d Fail to alloc\n",
1127 getpid(), __FUNCTION__, __LINE__);
1128 goto fail_alloc_gem_priv;
1131 privGem->ref_count = 1;
1132 privGem->bo_priv = bo_sprd;
1133 if (drmHashInsert(bufmgr_sprd->hashBos, bo_sprd->name, (void *)privGem) < 0) {
1134 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1135 "error %s:%d Cannot insert bo to Hash(%d)\n",
1136 getpid(), __FUNCTION__, __LINE__, bo_sprd->name);
1139 DBG("[libtbm-sprd:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
1140 __FUNCTION__, bo_sprd->size,
1141 bo_sprd->gem, bo_sprd->name,
1142 bo_sprd->flags_tbm, bo_sprd->flags_sprd);
1144 return (void *)bo_sprd;
1146 fail_alloc_gem_priv:
1147 if (bo_sprd->dmabuf)
1148 close(bo_sprd->dmabuf);
1149 fail_prime_handle_to_fd:
1150 _bo_destroy_cache_state(bufmgr_sprd, bo_sprd);
1156 struct drm_gem_close gem_close_arg = {arg.handle, 0};
1157 drmIoctl(bufmgr_sprd->fd, DRM_IOCTL_GEM_CLOSE, &gem_close_arg);
1163 tbm_sprd_bo_import_fd(tbm_bo bo, tbm_fd key)
1165 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, NULL);
1167 tbm_bufmgr_sprd bufmgr_sprd;
1168 tbm_bo_sprd bo_sprd;
1172 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1173 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, NULL);
1175 //getting handle from fd
1176 struct drm_prime_handle arg = {0, };
1180 if (drmIoctl(bufmgr_sprd->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg)) {
1181 TBM_SPRD_LOG("error bo:%p Cannot get gem handle from fd:%d (%s)\n",
1182 bo, arg.fd, strerror(errno));
1187 name = _get_name(bufmgr_sprd->fd, gem);
1189 TBM_SPRD_LOG("error bo:%p Cannot get name from gem:%d, fd:%d (%s)\n",
1190 bo, gem, key, strerror(errno));
1194 if (!drmHashLookup(bufmgr_sprd->hashBos, name, (void **)&privGem)) {
1195 if (gem == privGem->bo_priv->gem)
1196 return privGem->bo_priv;
1199 unsigned int real_size;
1200 struct drm_sprd_gem_info info = {0, };
1202 /* Determine size of bo. The fd-to-handle ioctl really should
1203 * return the size, but it doesn't. If we have kernel 3.12 or
1204 * later, we can lseek on the prime fd to get the size. Older
1205 * kernels will just fail, in which case we fall back to the
1206 * provided (estimated or guess size). */
1207 real_size = lseek(key, 0, SEEK_END);
1210 if (drmCommandWriteRead(bufmgr_sprd->fd,
1213 sizeof(struct drm_sprd_gem_info))) {
1214 TBM_SPRD_LOG("error bo:%p Cannot get gem info from gem:%d, fd:%d (%s)\n",
1215 bo, gem, key, strerror(errno));
1219 if (real_size == -1)
1220 real_size = info.size;
1222 bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
1224 TBM_SPRD_LOG("error bo:%p fail to allocate the bo private\n", bo);
1228 bo_sprd->fd = bufmgr_sprd->fd;
1230 bo_sprd->size = real_size;
1231 bo_sprd->flags_sprd = info.flags;
1232 bo_sprd->flags_tbm = _get_tbm_flag_from_sprd(bo_sprd->flags_sprd);
1234 bo_sprd->name = name;
1235 if (!bo_sprd->name) {
1236 TBM_SPRD_LOG("error bo:%p Cannot get name from gem:%d, fd:%d (%s)\n",
1237 bo, gem, key, strerror(errno));
1238 goto fail_check_name;
1241 if (!_bo_init_cache_state(bufmgr_sprd, bo_sprd, 1)) {
1242 TBM_SPRD_LOG("error fail init cache state(%d)\n", bo_sprd->name);
1243 goto fail_init_cache;
1246 /* add bo to hash */
1247 privGem = calloc(1, sizeof(PrivGem));
1249 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1250 "error %s:%d Fail to callocprivGem\n",
1251 getpid(), __FUNCTION__, __LINE__);
1252 goto fail_alloc_gem_priv;
1255 privGem->ref_count = 1;
1256 privGem->bo_priv = bo_sprd;
1257 if (drmHashInsert(bufmgr_sprd->hashBos, bo_sprd->name, (void *)privGem) < 0) {
1258 TBM_SPRD_LOG("error bo:%p Cannot insert bo to Hash(%d) from gem:%d, fd:%d\n",
1259 bo, bo_sprd->name, gem, key);
1262 DBG(" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n",
1265 bo_sprd->gem, bo_sprd->name,
1268 bo_sprd->flags_tbm, bo_sprd->flags_sprd,
1271 return (void *)bo_sprd;
1273 fail_alloc_gem_priv:
1274 _bo_destroy_cache_state(bufmgr_sprd, bo_sprd);
1282 tbm_sprd_bo_export(tbm_bo bo)
1284 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1286 tbm_bo_sprd bo_sprd;
1288 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1289 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1291 if (!bo_sprd->name) {
1292 bo_sprd->name = _get_name(bo_sprd->fd, bo_sprd->gem);
1293 if (!bo_sprd->name) {
1294 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1295 "error %s:%d Cannot get name\n",
1296 getpid(), __FUNCTION__, __LINE__);
1301 DBG("[libtbm-sprd:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
1302 __FUNCTION__, bo_sprd->size,
1303 bo_sprd->gem, bo_sprd->name,
1304 bo_sprd->flags_tbm, bo_sprd->flags_sprd);
1306 return (unsigned int)bo_sprd->name;
1310 tbm_sprd_bo_export_fd(tbm_bo bo)
1312 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, -1);
1314 tbm_bo_sprd bo_sprd;
1317 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1318 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, -1);
1320 struct drm_prime_handle arg = {0, };
1322 arg.handle = bo_sprd->gem;
1323 ret = drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg);
1325 TBM_SPRD_LOG("error bo:%p Cannot dmabuf=%d (%s)\n",
1326 bo, bo_sprd->gem, strerror(errno));
1327 return (tbm_fd) ret;
1330 DBG(" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n",
1333 bo_sprd->gem, bo_sprd->name,
1336 bo_sprd->flags_tbm, bo_sprd->flags_sprd,
1339 return (tbm_fd)arg.fd;
1343 static tbm_bo_handle
1344 tbm_sprd_bo_get_handle(tbm_bo bo, int device)
1346 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, (tbm_bo_handle) NULL);
1348 tbm_bo_handle bo_handle;
1349 tbm_bo_sprd bo_sprd;
1351 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1352 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, (tbm_bo_handle) NULL);
1354 if (!bo_sprd->gem) {
1355 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1356 "error %s:%d Cannot map gem=%d\n",
1357 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
1358 return (tbm_bo_handle) NULL;
1361 DBG("[libtbm-sprd:%d] %s gem:%d(%d), %s\n", getpid(),
1362 __FUNCTION__, bo_sprd->gem, bo_sprd->name, STR_DEVICE[device]);
1364 /*Get mapped bo_handle*/
1365 bo_handle = _sprd_bo_handle(bo_sprd, device);
1366 if (bo_handle.ptr == NULL) {
1367 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1368 "error %s:%d Cannot get handle: gem:%d, device:%d\n",
1369 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem, device);
1370 return (tbm_bo_handle) NULL;
1376 static tbm_bo_handle
1377 tbm_sprd_bo_map(tbm_bo bo, int device, int opt)
1379 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, (tbm_bo_handle) NULL);
1381 tbm_bo_handle bo_handle;
1382 tbm_bo_sprd bo_sprd;
1383 tbm_bufmgr_sprd bufmgr_sprd;
1385 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1386 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, (tbm_bo_handle) NULL);
1388 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1389 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, (tbm_bo_handle) NULL);
1391 if (!bo_sprd->gem) {
1392 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1393 "error %s:%d Cannot map gem=%d\n",
1394 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
1395 return (tbm_bo_handle) NULL;
1398 DBG("[libtbm-sprd:%d] %s gem:%d(%d), %s, %s\n", getpid(),
1399 __FUNCTION__, bo_sprd->gem, bo_sprd->name, STR_DEVICE[device], STR_OPT[opt]);
1401 /*Get mapped bo_handle*/
1402 bo_handle = _sprd_bo_handle(bo_sprd, device);
1403 if (bo_handle.ptr == NULL) {
1404 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1405 "error %s:%d Cannot get handle: gem:%d, device:%d, opt:%d\n",
1406 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem, device, opt);
1407 return (tbm_bo_handle) NULL;
1410 if (bo_sprd->map_cnt == 0)
1411 _bo_set_cache_state(bufmgr_sprd, bo_sprd, device, opt);
1419 tbm_sprd_bo_unmap(tbm_bo bo)
1421 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1423 tbm_bufmgr_sprd bufmgr_sprd;
1424 tbm_bo_sprd bo_sprd;
1426 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1427 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1429 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1430 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1437 if (bo_sprd->map_cnt == 0)
1438 _bo_save_cache_state(bufmgr_sprd, bo_sprd);
1440 DBG("[libtbm-sprd:%d] %s gem:%d(%d) \n", getpid(),
1441 __FUNCTION__, bo_sprd->gem, bo_sprd->name);
1447 tbm_sprd_bo_lock(tbm_bo bo, int device, int opt)
1449 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1451 tbm_bufmgr_sprd bufmgr_sprd;
1452 tbm_bo_sprd bo_sprd;
1454 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1455 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1457 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1458 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1460 #if USE_BACKEND_LOCK
1463 if (bufmgr_sprd->use_dma_fence) {
1464 struct dma_buf_fence fence;
1466 memset(&fence, 0, sizeof(struct dma_buf_fence));
1468 /* Check if the given type is valid or not. */
1469 if (opt & TBM_OPTION_WRITE) {
1470 if (device == TBM_DEVICE_CPU)
1471 fence.type = DMA_BUF_ACCESS_WRITE;
1472 else if (device == TBM_DEVICE_3D)
1473 fence.type = DMA_BUF_ACCESS_WRITE | DMA_BUF_ACCESS_DMA;
1475 DBG("[libtbm-sprd:%d] %s GET_FENCE is ignored(device type is not 3D/CPU),\n",
1476 getpid(), __FUNCTION__);
1479 } else if (opt & TBM_OPTION_READ) {
1480 if (device == TBM_DEVICE_CPU)
1481 fence.type = DMA_BUF_ACCESS_READ;
1482 else if (device == TBM_DEVICE_3D)
1483 fence.type = DMA_BUF_ACCESS_READ | DMA_BUF_ACCESS_DMA;
1485 DBG("[libtbm-sprd:%d] %s GET_FENCE is ignored(device type is not 3D/CPU),\n",
1486 getpid(), __FUNCTION__);
1490 TBM_SPRD_LOG("[libtbm-sprd:%d] error %s:%d Invalid argument\n", getpid(),
1491 __FUNCTION__, __LINE__);
1495 ret = ioctl(bo_sprd->dmabuf, DMABUF_IOCTL_GET_FENCE, &fence);
1497 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1498 "error %s:%d Can not set GET FENCE(%s)\n",
1499 getpid(), __FUNCTION__, __LINE__, strerror(errno));
1503 pthread_mutex_lock(&bo_sprd->mutex);
1505 for (i = 0; i < DMA_FENCE_LIST_MAX; i++) {
1506 if (bo_sprd->dma_fence[i].ctx == 0) {
1507 bo_sprd->dma_fence[i].type = fence.type;
1508 bo_sprd->dma_fence[i].ctx = fence.ctx;
1512 if (i == DMA_FENCE_LIST_MAX) {
1513 //TODO: if dma_fence list is full, it needs realloc. I will fix this. by minseok3.kim
1514 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1515 "error %s:%d fence list is full\n",
1516 getpid(), __FUNCTION__, __LINE__);
1518 pthread_mutex_unlock(&bo_sprd->mutex);
1520 DBG("[libtbm-sprd:%d] %s DMABUF_IOCTL_GET_FENCE! flink_id=%d dmabuf=%d\n",
1522 __FUNCTION__, bo_sprd->name, bo_sprd->dmabuf);
1524 ret = _tgl_lock(bufmgr_sprd->tgl_fd, bo_sprd->name, opt);
1526 DBG("[libtbm-sprd:%d] lock tgl flink_id:%d\n",
1527 getpid(), __FUNCTION__, bo_sprd->name);
1537 tbm_sprd_bo_unlock(tbm_bo bo)
1539 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1541 tbm_bufmgr_sprd bufmgr_sprd;
1542 tbm_bo_sprd bo_sprd;
1544 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1545 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1547 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1548 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1550 #if USE_BACKEND_LOCK
1553 if (bufmgr_sprd->use_dma_fence) {
1554 struct dma_buf_fence fence;
1556 if (!bo_sprd->dma_fence[0].ctx) {
1557 DBG("[libtbm-sprd:%d] %s FENCE not support or ignored,\n", getpid(),
1562 if (!bo_sprd->dma_fence[0].type) {
1563 DBG("[libtbm-sprd:%d] %s device type is not 3D/CPU,\n", getpid(),
1568 pthread_mutex_lock(&bo_sprd->mutex);
1569 fence.type = bo_sprd->dma_fence[0].type;
1570 fence.ctx = bo_sprd->dma_fence[0].ctx;
1572 for (i = 1; i < DMA_FENCE_LIST_MAX; i++) {
1573 bo_sprd->dma_fence[i - 1].type = bo_sprd->dma_fence[i].type;
1574 bo_sprd->dma_fence[i - 1].ctx = bo_sprd->dma_fence[i].ctx;
1576 bo_sprd->dma_fence[DMA_FENCE_LIST_MAX - 1].type = 0;
1577 bo_sprd->dma_fence[DMA_FENCE_LIST_MAX - 1].ctx = 0;
1578 pthread_mutex_unlock(&bo_sprd->mutex);
1580 ret = ioctl(bo_sprd->dmabuf, DMABUF_IOCTL_PUT_FENCE, &fence);
1582 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1583 "error %s:%d Can not set PUT FENCE(%s)\n",
1584 getpid(), __FUNCTION__, __LINE__, strerror(errno));
1588 DBG("[libtbm-sprd:%d] %s DMABUF_IOCTL_PUT_FENCE! flink_id=%d dmabuf=%d\n",
1590 __FUNCTION__, bo_sprd->name, bo_sprd->dmabuf);
1592 ret = _tgl_unlock(bufmgr_sprd->tgl_fd, bo_sprd->name);
1594 DBG("[libtbm-sprd:%d] unlock tgl flink_id:%d\n",
1595 getpid(), __FUNCTION__, bo_sprd->name);
1605 tbm_sprd_bufmgr_deinit(void *priv)
1607 SPRD_RETURN_IF_FAIL(priv != NULL);
1609 tbm_bufmgr_sprd bufmgr_sprd;
1611 bufmgr_sprd = (tbm_bufmgr_sprd)priv;
1613 if (bufmgr_sprd->hashBos) {
1617 while (drmHashFirst(bufmgr_sprd->hashBos, &key, &value) > 0) {
1619 drmHashDelete(bufmgr_sprd->hashBos, key);
1622 drmHashDestroy(bufmgr_sprd->hashBos);
1623 bufmgr_sprd->hashBos = NULL;
1626 if (bufmgr_sprd->bind_display)
1627 tbm_drm_helper_wl_auth_server_deinit();
1629 if (tbm_backend_is_display_server())
1630 tbm_drm_helper_unset_tbm_master_fd();
1632 if (bufmgr_sprd->device_name)
1633 free(bufmgr_sprd->device_name);
1635 _bufmgr_deinit_cache_state(bufmgr_sprd);
1637 close(bufmgr_sprd->fd);
1643 tbm_sprd_surface_supported_format(uint32_t **formats, uint32_t *num)
1645 uint32_t *color_formats;
1647 color_formats = (uint32_t *)calloc(1,
1648 sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
1649 if (color_formats == NULL)
1652 memcpy(color_formats, tbm_sprd_color_format_list,
1653 sizeof(uint32_t)*TBM_COLOR_FORMAT_COUNT);
1655 *formats = color_formats;
1656 *num = TBM_COLOR_FORMAT_COUNT;
1663 * @brief get the plane data of the surface.
1664 * @param[in] width : the width of the surface
1665 * @param[in] height : the height of the surface
1666 * @param[in] format : the format of the surface
1667 * @param[in] plane_idx : the format of the surface
1668 * @param[out] size : the size of the plane
1669 * @param[out] offset : the offset of the plane
1670 * @param[out] pitch : the pitch of the plane
1671 * @param[out] padding : the padding of the plane
1672 * @return 1 if this function succeeds, otherwise 0.
1675 tbm_sprd_surface_get_plane_data(int width, int height,
1676 tbm_format format, int plane_idx, uint32_t *size, uint32_t *offset,
1677 uint32_t *pitch, int *bo_idx)
1685 int _align_height = 0;
1689 case TBM_FORMAT_XRGB4444:
1690 case TBM_FORMAT_XBGR4444:
1691 case TBM_FORMAT_RGBX4444:
1692 case TBM_FORMAT_BGRX4444:
1693 case TBM_FORMAT_ARGB4444:
1694 case TBM_FORMAT_ABGR4444:
1695 case TBM_FORMAT_RGBA4444:
1696 case TBM_FORMAT_BGRA4444:
1697 case TBM_FORMAT_XRGB1555:
1698 case TBM_FORMAT_XBGR1555:
1699 case TBM_FORMAT_RGBX5551:
1700 case TBM_FORMAT_BGRX5551:
1701 case TBM_FORMAT_ARGB1555:
1702 case TBM_FORMAT_ABGR1555:
1703 case TBM_FORMAT_RGBA5551:
1704 case TBM_FORMAT_BGRA5551:
1705 case TBM_FORMAT_RGB565:
1708 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1709 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1713 case TBM_FORMAT_RGB888:
1714 case TBM_FORMAT_BGR888:
1717 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1718 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1722 case TBM_FORMAT_XRGB8888:
1723 case TBM_FORMAT_XBGR8888:
1724 case TBM_FORMAT_RGBX8888:
1725 case TBM_FORMAT_BGRX8888:
1726 case TBM_FORMAT_ARGB8888:
1727 case TBM_FORMAT_ABGR8888:
1728 case TBM_FORMAT_RGBA8888:
1729 case TBM_FORMAT_BGRA8888:
1732 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1733 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1738 case TBM_FORMAT_YUYV:
1739 case TBM_FORMAT_YVYU:
1740 case TBM_FORMAT_UYVY:
1741 case TBM_FORMAT_VYUY:
1742 case TBM_FORMAT_AYUV:
1745 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1746 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1752 * index 0 = Y plane, [7:0] Y
1753 * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1755 * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1757 case TBM_FORMAT_NV12:
1758 case TBM_FORMAT_NV21:
1760 if (plane_idx == 0) {
1762 _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1763 _align_height = SIZE_ALIGN(height, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1764 _size = SIZE_ALIGN(_pitch * _align_height, TBM_SURFACE_ALIGNMENT_PLANE);
1766 } else if (plane_idx == 1) {
1767 _offset = width * height;
1768 _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1769 _align_height = SIZE_ALIGN(height / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1770 _size = SIZE_ALIGN(_pitch * _align_height, TBM_SURFACE_ALIGNMENT_PLANE);
1775 case TBM_FORMAT_NV16:
1776 case TBM_FORMAT_NV61:
1778 //if(plane_idx == 0)
1781 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1782 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1787 //else if( plane_idx ==1 )
1790 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1791 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1798 * index 0: Y plane, [7:0] Y
1799 * index 1: Cb plane, [7:0] Cb
1800 * index 2: Cr plane, [7:0] Cr
1802 * index 1: Cr plane, [7:0] Cr
1803 * index 2: Cb plane, [7:0] Cb
1806 NATIVE_BUFFER_FORMAT_YV12
1807 NATIVE_BUFFER_FORMAT_I420
1809 case TBM_FORMAT_YUV410:
1810 case TBM_FORMAT_YVU410:
1813 case TBM_FORMAT_YUV411:
1814 case TBM_FORMAT_YVU411:
1815 case TBM_FORMAT_YUV420:
1816 case TBM_FORMAT_YVU420:
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 / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1831 _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1836 //else if (plane_idx == 2 )
1839 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1840 _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1844 case TBM_FORMAT_YUV422:
1845 case TBM_FORMAT_YVU422:
1847 //if(plane_idx == 0)
1850 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1851 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1856 //else if( plane_idx == 1 )
1859 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1860 _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
1865 //else if (plane_idx == 2 )
1868 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1869 _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
1873 case TBM_FORMAT_YUV444:
1874 case TBM_FORMAT_YVU444:
1876 //if(plane_idx == 0)
1879 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1880 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1885 //else if( plane_idx == 1 )
1888 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1889 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1894 //else if (plane_idx == 2 )
1897 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1898 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1916 tbm_sprd_bo_get_flags(tbm_bo bo)
1918 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1920 tbm_bo_sprd bo_sprd;
1922 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1923 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1925 return bo_sprd->flags_tbm;
1929 tbm_sprd_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1931 tbm_bufmgr_sprd bufmgr_sprd;
1933 bufmgr_sprd = tbm_backend_get_priv_from_bufmgr(bufmgr);
1934 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1936 if (!tbm_drm_helper_wl_auth_server_init(NativeDisplay, bufmgr_sprd->fd,
1937 bufmgr_sprd->device_name, 0)) {
1938 TBM_SPRD_LOG("[libtbm-sprd:%d] error:Fail to tbm_drm_helper_wl_server_init\n");
1942 bufmgr_sprd->bind_display = NativeDisplay;
1947 MODULEINITPPROTO(init_tbm_bufmgr_priv);
1949 static TBMModuleVersionInfo SprdVersRec = {
1955 TBMModuleData tbmModuleData = { &SprdVersRec, init_tbm_bufmgr_priv};
1958 init_tbm_bufmgr_priv(tbm_bufmgr bufmgr, int fd)
1960 tbm_bufmgr_backend bufmgr_backend;
1961 tbm_bufmgr_sprd bufmgr_sprd;
1967 bufmgr_sprd = calloc(1, sizeof(struct _tbm_bufmgr_sprd));
1969 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to alloc bufmgr_sprd!\n", getpid());
1973 if (tbm_backend_is_display_server()) {
1974 bufmgr_sprd->fd = tbm_drm_helper_get_master_fd();
1975 if (bufmgr_sprd->fd < 0) {
1976 bufmgr_sprd->fd = _tbm_sprd_open_drm();
1977 if (bufmgr_sprd->fd < 0) {
1978 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to open drm!\n", getpid());
1983 tbm_drm_helper_set_tbm_master_fd(bufmgr_sprd->fd);
1985 bufmgr_sprd->device_name = drmGetDeviceNameFromFd(bufmgr_sprd->fd);
1986 if (!bufmgr_sprd->device_name) {
1987 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to get device name!\n", getpid());
1988 tbm_drm_helper_unset_tbm_master_fd();
1989 goto fail_get_device_name;
1992 if (!tbm_drm_helper_get_auth_info(&(bufmgr_sprd->fd), &(bufmgr_sprd->device_name), NULL)) {
1993 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to get auth drm info!\n", getpid());
1994 goto fail_get_auth_info;
1999 bufmgr_sprd->hashBos = drmHashCreate();
2001 //Check if the tbm manager supports dma fence or not.
2002 fp = open("/sys/module/dmabuf_sync/parameters/enabled", O_RDONLY);
2005 int length = read(fp, buf, 1);
2007 if (length == 1 && buf[0] == '1')
2008 bufmgr_sprd->use_dma_fence = 1;
2013 if (!_bufmgr_init_cache_state(bufmgr_sprd)) {
2014 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to init bufmgr cache state\n", getpid());
2015 goto fail_init_cache_state;
2018 bufmgr_backend = tbm_backend_alloc();
2019 if (!bufmgr_backend) {
2020 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to alloc backend!\n", getpid());
2021 goto fail_alloc_backend;
2024 bufmgr_backend->priv = (void *)bufmgr_sprd;
2025 bufmgr_backend->bufmgr_deinit = tbm_sprd_bufmgr_deinit;
2026 bufmgr_backend->bo_size = tbm_sprd_bo_size;
2027 bufmgr_backend->bo_alloc = tbm_sprd_bo_alloc;
2028 bufmgr_backend->bo_free = tbm_sprd_bo_free;
2029 bufmgr_backend->bo_import = tbm_sprd_bo_import;
2030 bufmgr_backend->bo_import_fd = tbm_sprd_bo_import_fd;
2031 bufmgr_backend->bo_export = tbm_sprd_bo_export;
2032 bufmgr_backend->bo_export_fd = tbm_sprd_bo_export_fd;
2033 bufmgr_backend->bo_get_handle = tbm_sprd_bo_get_handle;
2034 bufmgr_backend->bo_map = tbm_sprd_bo_map;
2035 bufmgr_backend->bo_unmap = tbm_sprd_bo_unmap;
2036 bufmgr_backend->surface_get_plane_data = tbm_sprd_surface_get_plane_data;
2037 bufmgr_backend->surface_supported_format = tbm_sprd_surface_supported_format;
2038 bufmgr_backend->bo_get_flags = tbm_sprd_bo_get_flags;
2039 bufmgr_backend->bo_lock = tbm_sprd_bo_lock;
2040 bufmgr_backend->bo_unlock = tbm_sprd_bo_unlock;
2041 bufmgr_backend->bufmgr_bind_native_display = tbm_sprd_bufmgr_bind_native_display;
2043 if (!tbm_backend_init(bufmgr, bufmgr_backend)) {
2044 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to init backend!\n", getpid());
2045 goto fail_init_backend;
2052 env = getenv("TBM_SPRD_DEBUG");
2055 TBM_SPRD_LOG("TBM_SPRD_DEBUG=%s\n", env);
2061 DBG("[libtbm-sprd:%d] %s DMABUF FENCE is %s\n", getpid(),
2062 __FUNCTION__, bufmgr_sprd->use_dma_fence ? "supported!" : "NOT supported!");
2063 DBG("[libtbm-sprd:%d] %s fd:%d\n", getpid(),
2064 __FUNCTION__, bufmgr_sprd->fd);
2069 tbm_backend_free(bufmgr_backend);
2071 _bufmgr_deinit_cache_state(bufmgr_sprd);
2072 fail_init_cache_state:
2073 if (bufmgr_sprd->hashBos)
2074 drmHashDestroy(bufmgr_sprd->hashBos);
2075 if (tbm_backend_is_display_server())
2076 tbm_drm_helper_unset_tbm_master_fd();
2077 fail_get_device_name:
2078 close(bufmgr_sprd->fd);