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_bo_sprd bo_sprd;
1377 tbm_bufmgr_sprd bufmgr_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) {
1418 struct dma_buf_fence fence;
1420 memset(&fence, 0, sizeof(struct dma_buf_fence));
1422 /* Check if the given type is valid or not. */
1423 if (opt & TBM_OPTION_WRITE) {
1424 if (device == TBM_DEVICE_CPU)
1425 fence.type = DMA_BUF_ACCESS_WRITE;
1426 else if (device == TBM_DEVICE_3D)
1427 fence.type = DMA_BUF_ACCESS_WRITE | DMA_BUF_ACCESS_DMA;
1429 DBG("[libtbm-sprd:%d] %s GET_FENCE is ignored(device type is not 3D/CPU),\n",
1430 getpid(), __FUNCTION__);
1433 } else if (opt & TBM_OPTION_READ) {
1434 if (device == TBM_DEVICE_CPU)
1435 fence.type = DMA_BUF_ACCESS_READ;
1436 else if (device == TBM_DEVICE_3D)
1437 fence.type = DMA_BUF_ACCESS_READ | DMA_BUF_ACCESS_DMA;
1439 DBG("[libtbm-sprd:%d] %s GET_FENCE is ignored(device type is not 3D/CPU),\n",
1440 getpid(), __FUNCTION__);
1444 TBM_SPRD_LOG("[libtbm-sprd:%d] error %s:%d Invalid argument\n", getpid(),
1445 __FUNCTION__, __LINE__);
1449 /* Check if the tbm manager supports dma fence or not. */
1450 if (!bufmgr_sprd->use_dma_fence) {
1451 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1452 "error %s:%d Not support DMA FENCE(%s)\n",
1453 getpid(), __FUNCTION__, __LINE__, strerror(errno));
1458 ret = ioctl(bo_sprd->dmabuf, DMABUF_IOCTL_GET_FENCE, &fence);
1460 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1461 "error %s:%d Can not set GET FENCE(%s)\n",
1462 getpid(), __FUNCTION__, __LINE__, strerror(errno));
1466 pthread_mutex_lock(&bo_sprd->mutex);
1468 for (i = 0; i < DMA_FENCE_LIST_MAX; i++) {
1469 if (bo_sprd->dma_fence[i].ctx == 0) {
1470 bo_sprd->dma_fence[i].type = fence.type;
1471 bo_sprd->dma_fence[i].ctx = fence.ctx;
1475 if (i == DMA_FENCE_LIST_MAX) {
1476 //TODO: if dma_fence list is full, it needs realloc. I will fix this. by minseok3.kim
1477 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1478 "error %s:%d fence list is full\n",
1479 getpid(), __FUNCTION__, __LINE__);
1481 pthread_mutex_unlock(&bo_sprd->mutex);
1483 DBG("[libtbm-sprd:%d] %s DMABUF_IOCTL_GET_FENCE! flink_id=%d dmabuf=%d\n",
1485 __FUNCTION__, bo_sprd->name, bo_sprd->dmabuf);
1488 ret = _tgl_lock(bufmgr_sprd->tgl_fd, bo_sprd->name);
1490 DBG("[libtbm-sprd:%d] lock tgl flink_id:%d\n",
1491 getpid(), __FUNCTION__, bo_sprd->name);
1501 tbm_sprd_bo_unlock(tbm_bo bo)
1503 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1505 tbm_bufmgr_sprd bufmgr_sprd;
1506 tbm_bo_sprd bo_sprd;
1508 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1509 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1511 bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1512 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1514 #if USE_BACKEND_LOCK
1517 if (bufmgr_sprd->use_dma_fence) {
1518 struct dma_buf_fence fence;
1520 if (!bo_sprd->dma_fence[0].ctx) {
1521 DBG("[libtbm-sprd:%d] %s FENCE not support or ignored,\n", getpid(),
1526 if (!bo_sprd->dma_fence[0].type) {
1527 DBG("[libtbm-sprd:%d] %s device type is not 3D/CPU,\n", getpid(),
1532 pthread_mutex_lock(&bo_sprd->mutex);
1533 fence.type = bo_sprd->dma_fence[0].type;
1534 fence.ctx = bo_sprd->dma_fence[0].ctx;
1536 for (i = 1; i < DMA_FENCE_LIST_MAX; i++) {
1537 bo_sprd->dma_fence[i - 1].type = bo_sprd->dma_fence[i].type;
1538 bo_sprd->dma_fence[i - 1].ctx = bo_sprd->dma_fence[i].ctx;
1540 bo_sprd->dma_fence[DMA_FENCE_LIST_MAX - 1].type = 0;
1541 bo_sprd->dma_fence[DMA_FENCE_LIST_MAX - 1].ctx = 0;
1542 pthread_mutex_unlock(&bo_sprd->mutex);
1544 ret = ioctl(bo_sprd->dmabuf, DMABUF_IOCTL_PUT_FENCE, &fence);
1546 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1547 "error %s:%d Can not set PUT FENCE(%s)\n",
1548 getpid(), __FUNCTION__, __LINE__, strerror(errno));
1552 DBG("[libtbm-sprd:%d] %s DMABUF_IOCTL_PUT_FENCE! flink_id=%d dmabuf=%d\n",
1554 __FUNCTION__, bo_sprd->name, bo_sprd->dmabuf);
1556 ret = _tgl_unlock(bufmgr_sprd->tgl_fd, bo_sprd->name);
1558 DBG("[libtbm-sprd:%d] unlock tgl flink_id:%d\n",
1559 getpid(), __FUNCTION__, bo_sprd->name);
1569 tbm_sprd_bufmgr_deinit(void *priv)
1571 SPRD_RETURN_IF_FAIL(priv != NULL);
1573 tbm_bufmgr_sprd bufmgr_sprd;
1575 bufmgr_sprd = (tbm_bufmgr_sprd)priv;
1577 if (bufmgr_sprd->hashBos) {
1581 while (drmHashFirst(bufmgr_sprd->hashBos, &key, &value) > 0) {
1583 drmHashDelete(bufmgr_sprd->hashBos, key);
1586 drmHashDestroy(bufmgr_sprd->hashBos);
1587 bufmgr_sprd->hashBos = NULL;
1590 if (bufmgr_sprd->bind_display)
1591 tbm_drm_helper_wl_auth_server_deinit();
1593 if (tbm_backend_is_display_server())
1594 tbm_drm_helper_unset_tbm_master_fd();
1596 if (bufmgr_sprd->device_name)
1597 free(bufmgr_sprd->device_name);
1599 _bufmgr_deinit_cache_state(bufmgr_sprd);
1601 close(bufmgr_sprd->fd);
1607 tbm_sprd_surface_supported_format(uint32_t **formats, uint32_t *num)
1609 uint32_t *color_formats;
1611 color_formats = (uint32_t *)calloc(1,
1612 sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
1613 if (color_formats == NULL)
1616 memcpy(color_formats, tbm_sprd_color_format_list,
1617 sizeof(uint32_t)*TBM_COLOR_FORMAT_COUNT);
1619 *formats = color_formats;
1620 *num = TBM_COLOR_FORMAT_COUNT;
1627 * @brief get the plane data of the surface.
1628 * @param[in] width : the width of the surface
1629 * @param[in] height : the height of the surface
1630 * @param[in] format : the format of the surface
1631 * @param[in] plane_idx : the format of the surface
1632 * @param[out] size : the size of the plane
1633 * @param[out] offset : the offset of the plane
1634 * @param[out] pitch : the pitch of the plane
1635 * @param[out] padding : the padding of the plane
1636 * @return 1 if this function succeeds, otherwise 0.
1639 tbm_sprd_surface_get_plane_data(int width, int height,
1640 tbm_format format, int plane_idx, uint32_t *size, uint32_t *offset,
1641 uint32_t *pitch, int *bo_idx)
1649 int _align_height = 0;
1653 case TBM_FORMAT_XRGB4444:
1654 case TBM_FORMAT_XBGR4444:
1655 case TBM_FORMAT_RGBX4444:
1656 case TBM_FORMAT_BGRX4444:
1657 case TBM_FORMAT_ARGB4444:
1658 case TBM_FORMAT_ABGR4444:
1659 case TBM_FORMAT_RGBA4444:
1660 case TBM_FORMAT_BGRA4444:
1661 case TBM_FORMAT_XRGB1555:
1662 case TBM_FORMAT_XBGR1555:
1663 case TBM_FORMAT_RGBX5551:
1664 case TBM_FORMAT_BGRX5551:
1665 case TBM_FORMAT_ARGB1555:
1666 case TBM_FORMAT_ABGR1555:
1667 case TBM_FORMAT_RGBA5551:
1668 case TBM_FORMAT_BGRA5551:
1669 case TBM_FORMAT_RGB565:
1672 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1673 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1677 case TBM_FORMAT_RGB888:
1678 case TBM_FORMAT_BGR888:
1681 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1682 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1686 case TBM_FORMAT_XRGB8888:
1687 case TBM_FORMAT_XBGR8888:
1688 case TBM_FORMAT_RGBX8888:
1689 case TBM_FORMAT_BGRX8888:
1690 case TBM_FORMAT_ARGB8888:
1691 case TBM_FORMAT_ABGR8888:
1692 case TBM_FORMAT_RGBA8888:
1693 case TBM_FORMAT_BGRA8888:
1696 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1697 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1702 case TBM_FORMAT_YUYV:
1703 case TBM_FORMAT_YVYU:
1704 case TBM_FORMAT_UYVY:
1705 case TBM_FORMAT_VYUY:
1706 case TBM_FORMAT_AYUV:
1709 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1710 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1716 * index 0 = Y plane, [7:0] Y
1717 * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1719 * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1721 case TBM_FORMAT_NV12:
1722 case TBM_FORMAT_NV21:
1724 if (plane_idx == 0) {
1726 _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1727 _align_height = SIZE_ALIGN(height, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1728 _size = SIZE_ALIGN(_pitch * _align_height, TBM_SURFACE_ALIGNMENT_PLANE);
1730 } else if (plane_idx == 1) {
1731 _offset = width * height;
1732 _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1733 _align_height = SIZE_ALIGN(height / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1734 _size = SIZE_ALIGN(_pitch * _align_height, TBM_SURFACE_ALIGNMENT_PLANE);
1739 case TBM_FORMAT_NV16:
1740 case TBM_FORMAT_NV61:
1742 //if(plane_idx == 0)
1745 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1746 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1751 //else if( plane_idx ==1 )
1754 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1755 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1762 * index 0: Y plane, [7:0] Y
1763 * index 1: Cb plane, [7:0] Cb
1764 * index 2: Cr plane, [7:0] Cr
1766 * index 1: Cr plane, [7:0] Cr
1767 * index 2: Cb plane, [7:0] Cb
1770 NATIVE_BUFFER_FORMAT_YV12
1771 NATIVE_BUFFER_FORMAT_I420
1773 case TBM_FORMAT_YUV410:
1774 case TBM_FORMAT_YVU410:
1777 case TBM_FORMAT_YUV411:
1778 case TBM_FORMAT_YVU411:
1779 case TBM_FORMAT_YUV420:
1780 case TBM_FORMAT_YVU420:
1782 //if(plane_idx == 0)
1785 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1786 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1791 //else if( plane_idx == 1 )
1794 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1795 _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1800 //else if (plane_idx == 2 )
1803 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1804 _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1808 case TBM_FORMAT_YUV422:
1809 case TBM_FORMAT_YVU422:
1811 //if(plane_idx == 0)
1814 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1815 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1820 //else if( plane_idx == 1 )
1823 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1824 _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
1829 //else if (plane_idx == 2 )
1832 _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1833 _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
1837 case TBM_FORMAT_YUV444:
1838 case TBM_FORMAT_YVU444:
1840 //if(plane_idx == 0)
1843 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1844 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1849 //else if( plane_idx == 1 )
1852 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1853 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1858 //else if (plane_idx == 2 )
1861 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1862 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1880 tbm_sprd_bo_get_flags(tbm_bo bo)
1882 SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1884 tbm_bo_sprd bo_sprd;
1886 bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1887 SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1889 return bo_sprd->flags_tbm;
1893 tbm_sprd_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1895 tbm_bufmgr_sprd bufmgr_sprd;
1897 bufmgr_sprd = tbm_backend_get_priv_from_bufmgr(bufmgr);
1898 SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1900 if (!tbm_drm_helper_wl_auth_server_init(NativeDisplay, bufmgr_sprd->fd,
1901 bufmgr_sprd->device_name, 0)) {
1902 TBM_SPRD_LOG("[libtbm-sprd:%d] error:Fail to tbm_drm_helper_wl_server_init\n");
1906 bufmgr_sprd->bind_display = NativeDisplay;
1911 MODULEINITPPROTO(init_tbm_bufmgr_priv);
1913 static TBMModuleVersionInfo SprdVersRec = {
1919 TBMModuleData tbmModuleData = { &SprdVersRec, init_tbm_bufmgr_priv};
1922 init_tbm_bufmgr_priv(tbm_bufmgr bufmgr, int fd)
1924 tbm_bufmgr_backend bufmgr_backend;
1925 tbm_bufmgr_sprd bufmgr_sprd;
1931 bufmgr_sprd = calloc(1, sizeof(struct _tbm_bufmgr_sprd));
1933 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to alloc bufmgr_sprd!\n", getpid());
1937 if (tbm_backend_is_display_server()) {
1938 bufmgr_sprd->fd = tbm_drm_helper_get_master_fd();
1939 if (bufmgr_sprd->fd < 0) {
1940 bufmgr_sprd->fd = _tbm_sprd_open_drm();
1941 if (bufmgr_sprd->fd < 0) {
1942 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to open drm!\n", getpid());
1947 tbm_drm_helper_set_tbm_master_fd(bufmgr_sprd->fd);
1949 bufmgr_sprd->device_name = drmGetDeviceNameFromFd(bufmgr_sprd->fd);
1950 if (!bufmgr_sprd->device_name) {
1951 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to get device name!\n", getpid());
1952 tbm_drm_helper_unset_tbm_master_fd();
1953 goto fail_get_device_name;
1956 if (!tbm_drm_helper_get_auth_info(&(bufmgr_sprd->fd), &(bufmgr_sprd->device_name), NULL)) {
1957 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to get auth drm info!\n", getpid());
1958 goto fail_get_auth_info;
1963 bufmgr_sprd->hashBos = drmHashCreate();
1965 //Check if the tbm manager supports dma fence or not.
1966 fp = open("/sys/module/dmabuf_sync/parameters/enabled", O_RDONLY);
1969 int length = read(fp, buf, 1);
1971 if (length == 1 && buf[0] == '1')
1972 bufmgr_sprd->use_dma_fence = 1;
1977 if (!_bufmgr_init_cache_state(bufmgr_sprd)) {
1978 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to init bufmgr cache state\n", getpid());
1979 goto fail_init_cache_state;
1982 bufmgr_backend = tbm_backend_alloc();
1983 if (!bufmgr_backend) {
1984 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to alloc backend!\n", getpid());
1985 goto fail_alloc_backend;
1988 bufmgr_backend->priv = (void *)bufmgr_sprd;
1989 bufmgr_backend->bufmgr_deinit = tbm_sprd_bufmgr_deinit;
1990 bufmgr_backend->bo_size = tbm_sprd_bo_size;
1991 bufmgr_backend->bo_alloc = tbm_sprd_bo_alloc;
1992 bufmgr_backend->bo_free = tbm_sprd_bo_free;
1993 bufmgr_backend->bo_import = tbm_sprd_bo_import;
1994 bufmgr_backend->bo_import_fd = tbm_sprd_bo_import_fd;
1995 bufmgr_backend->bo_export = tbm_sprd_bo_export;
1996 bufmgr_backend->bo_export_fd = tbm_sprd_bo_export_fd;
1997 bufmgr_backend->bo_get_handle = tbm_sprd_bo_get_handle;
1998 bufmgr_backend->bo_map = tbm_sprd_bo_map;
1999 bufmgr_backend->bo_unmap = tbm_sprd_bo_unmap;
2000 bufmgr_backend->surface_get_plane_data = tbm_sprd_surface_get_plane_data;
2001 bufmgr_backend->surface_supported_format = tbm_sprd_surface_supported_format;
2002 bufmgr_backend->bo_get_flags = tbm_sprd_bo_get_flags;
2003 bufmgr_backend->bo_lock = tbm_sprd_bo_lock;
2004 bufmgr_backend->bo_unlock = tbm_sprd_bo_unlock;
2005 bufmgr_backend->bufmgr_bind_native_display = tbm_sprd_bufmgr_bind_native_display;
2007 if (!tbm_backend_init(bufmgr, bufmgr_backend)) {
2008 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to init backend!\n", getpid());
2009 goto fail_init_backend;
2016 env = getenv("TBM_SPRD_DEBUG");
2019 TBM_SPRD_LOG("TBM_SPRD_DEBUG=%s\n", env);
2025 DBG("[libtbm-sprd:%d] %s DMABUF FENCE is %s\n", getpid(),
2026 __FUNCTION__, bufmgr_sprd->use_dma_fence ? "supported!" : "NOT supported!");
2027 DBG("[libtbm-sprd:%d] %s fd:%d\n", getpid(),
2028 __FUNCTION__, bufmgr_sprd->fd);
2033 tbm_backend_free(bufmgr_backend);
2035 _bufmgr_deinit_cache_state(bufmgr_sprd);
2036 fail_init_cache_state:
2037 if (bufmgr_sprd->hashBos)
2038 drmHashDestroy(bufmgr_sprd->hashBos);
2039 if (tbm_backend_is_display_server())
2040 tbm_drm_helper_unset_tbm_master_fd();
2041 fail_get_device_name:
2042 close(bufmgr_sprd->fd);