Revert "change the slp_global_lock to the tgl"
[platform/adaptation/spreadtrum/libtbm-sprd.git] / src / tbm_bufmgr_sprd.c
1 /**************************************************************************
2
3 libtbm_sprd
4
5 Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8
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:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
19 of the Software.
20
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.
28
29 **************************************************************************/
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #if HAVE_UDEV
36 #include <libudev.h>
37 #endif
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <stdint.h>
42 #include <string.h>
43 #include <sys/ioctl.h>
44 #include <sys/types.h>
45 #include <unistd.h>
46 #include <sys/mman.h>
47 #include <sys/stat.h>
48 #include <fcntl.h>
49 #include <errno.h>
50 #include <xf86drm.h>
51 #include <tbm_bufmgr.h>
52 #include <tbm_bufmgr_backend.h>
53 #include <drm/sprd_drm.h>
54 #include <pthread.h>
55 #include <tbm_surface.h>
56 #include <tbm_drm_helper.h>
57
58 #define DEBUG
59 #include "tbm_bufmgr_tgl.h"
60
61 //#define USE_CONTIG_ONLY
62 #define USE_DMAIMPORT
63
64 #define TBM_COLOR_FORMAT_COUNT 4
65
66 #ifdef DEBUG
67 #define LOG_TAG    "TBM_BACKEND"
68 #include <dlog.h>
69 static int bDebug = 0;
70
71 #define SPRD_DRM_NAME "sprd"
72
73 static char *
74 _target_name(void)
75 {
76         static char app_name[128] = {0, };
77         static int initialized = 0;
78         char *slash;
79         FILE *f;
80
81         if (initialized)
82                 return app_name;
83
84         /* get the application name */
85         f = fopen("/proc/self/cmdline", "r");
86         if (!f)
87                 return NULL;
88
89         if (fgets(app_name, 100, f) == NULL) {
90                 fclose(f);
91                 return NULL;
92         }
93
94         fclose(f);
95
96         slash = strrchr(app_name, '/');
97         if (slash != NULL)
98                 memmove(app_name, slash + 1, strlen(slash));
99
100         initialized = 1;
101
102         return app_name;
103 }
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)
106 #else
107 #define TBM_SPRD_LOG(...)
108 #define DBG(...)
109 #endif
110
111 #define SIZE_ALIGN(value, base) (((value) + ((base) - 1)) & ~((base) - 1))
112
113 #define TBM_SURFACE_ALIGNMENT_PLANE (64)
114 #define TBM_SURFACE_ALIGNMENT_PITCH_RGB (128)
115 #define TBM_SURFACE_ALIGNMENT_PITCH_YUV (16)
116
117
118 /* check condition */
119 #define SPRD_RETURN_IF_FAIL(cond) {\
120         if (!(cond)) {\
121                 TBM_SPRD_LOG("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
122                 return;\
123         } \
124 }
125 #define SPRD_RETURN_VAL_IF_FAIL(cond, val) {\
126         if (!(cond)) {\
127                 TBM_SPRD_LOG("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
128                 return val;\
129         } \
130 }
131
132 struct dma_buf_info {
133         unsigned long    size;
134         unsigned int    fence_supported;
135         unsigned int    padding;
136 };
137
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
142
143 #define DMA_FENCE_LIST_MAX         5
144
145 struct dma_buf_fence {
146         unsigned long        ctx;
147         unsigned int        type;
148 };
149
150 #define DMABUF_IOCTL_BASE    'F'
151 #define DMABUF_IOWR(nr, type)    _IOWR(DMABUF_IOCTL_BASE, nr, type)
152
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)
156
157 /* tgl key values */
158 #define GLOBAL_KEY   ((unsigned int)(-1))
159 /* TBM_CACHE */
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 */
165
166 enum {
167         DEVICE_NONE = 0,
168         DEVICE_CA,                                      /* cache aware device */
169         DEVICE_CO                                       /* cache oblivious device */
170 };
171
172 typedef union _tbm_bo_cache_state tbm_bo_cache_state;
173
174 union _tbm_bo_cache_state {
175         unsigned int val;
176         struct {
177                 unsigned int cntFlush:16;       /*Flush all index for sync */
178                 unsigned int isCached:1;
179                 unsigned int isDirtied:2;
180         } data;
181 };
182
183 typedef struct _tbm_bufmgr_sprd *tbm_bufmgr_sprd;
184 typedef struct _tbm_bo_sprd *tbm_bo_sprd;
185
186 typedef struct _sprd_private {
187         int ref_count;
188         struct _tbm_bo_sprd *bo_priv;
189 } PrivGem;
190
191 /* tbm buffor object for sprd */
192 struct _tbm_bo_sprd {
193         int fd;
194
195         unsigned int name;    /* FLINK ID */
196
197         unsigned int gem;     /* GEM Handle */
198
199         unsigned int dmabuf;  /* fd for dmabuf */
200
201         void *pBase;          /* virtual address */
202
203         unsigned int size;
204
205         unsigned int flags_sprd;
206         unsigned int flags_tbm;
207
208         PrivGem *private;
209
210         pthread_mutex_t mutex;
211         struct dma_buf_fence dma_fence[DMA_FENCE_LIST_MAX];
212         int device;
213         int opt;
214
215         tbm_bo_cache_state cache_state;
216         unsigned int map_cnt;
217 };
218
219 /* tbm bufmgr private for sprd */
220 struct _tbm_bufmgr_sprd {
221         int fd;
222         void *hashBos;
223
224         int use_dma_fence;
225
226         int tgl_fd;
227
228         void *bind_display;
229         char *device_name;
230 };
231
232 char *STR_DEVICE[] = {
233         "DEF",
234         "CPU",
235         "2D",
236         "3D",
237         "MM"
238 };
239
240 char *STR_OPT[] = {
241         "NONE",
242         "RD",
243         "WR",
244         "RDWR"
245 };
246
247
248 uint32_t tbm_sprd_color_format_list[TBM_COLOR_FORMAT_COUNT] = {
249                                     TBM_FORMAT_ARGB8888,
250                                     TBM_FORMAT_XRGB8888,
251                                     TBM_FORMAT_NV12,
252                                     TBM_FORMAT_YUV420
253                                     };
254
255 static inline int
256 _tgl_init(int fd, unsigned int key)
257 {
258         struct tgl_attribute attr;
259         int err;
260
261         attr.key = key;
262         attr.timeout_ms = 1000;
263
264         err = ioctl(fd, TGL_IOC_INIT_LOCK, &attr);
265         if (err) {
266                 TBM_SPRD_LOG("[libtbm-sprd:%d] error(%s) %s:%d key:%d\n",
267                              getpid(), strerror(errno), __func__, __LINE__, key);
268                 return 0;
269         }
270
271         return 1;
272 }
273
274 static inline int
275 _tgl_destroy(int fd, unsigned int key)
276 {
277         int err;
278
279         err = ioctl(fd, TGL_IOC_DESTROY_LOCK, key);
280         if (err) {
281                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
282                              "error(%s) %s:%d key:%d\n",
283                              getpid(), strerror(errno), __func__, __LINE__, key);
284                 return 0;
285         }
286
287         return 1;
288 }
289
290 static inline int
291 _tgl_lock(int fd, unsigned int key)
292 {
293         int err;
294
295         err = ioctl(fd, TGL_IOC_LOCK_LOCK, key);
296         if (err) {
297                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
298                              "error(%s) %s:%d key:%d\n",
299                              getpid(), strerror(errno), __func__, __LINE__, key);
300                 return 0;
301         }
302
303         return 1;
304 }
305
306 static inline int
307 _tgl_unlock(int fd, unsigned int key)
308 {
309         int err;
310
311         err = ioctl(fd, TGL_IOC_UNLOCK_LOCK, key);
312         if (err) {
313                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
314                              "error(%s) %s:%d key:%d\n",
315                              getpid(), strerror(errno), __func__, __LINE__, key);
316                 return 0;
317         }
318
319         return 1;
320 }
321
322 #ifdef USE_CACHE
323 static inline int
324 _tgl_set_data(int fd, unsigned int key, unsigned int val)
325 {
326         int err;
327         struct tgl_user_data arg;
328
329         arg.key = key;
330         arg.data1 = val;
331         err = ioctl(fd, TGL_IOC_SET_DATA, &arg);
332         if (err) {
333                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
334                              "error(%s) %s:%d key:%d\n",
335                              getpid(), strerror(errno), __func__, __LINE__, key);
336                 return 0;
337         }
338
339         return 1;
340 }
341
342 static inline unsigned int
343 _tgl_get_data(int fd, unsigned int key, unsigned int *locked)
344 {
345         int err;
346         struct tgl_user_data arg = { 0, };
347
348         arg.key = key;
349         err = ioctl(fd, TGL_IOC_GET_DATA, &arg);
350         if (err) {
351                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
352                              "error(%s) %s:%d key:%d\n",
353                              getpid(), strerror(errno), __func__, __LINE__, key);
354                 return 0;
355         }
356
357         if (locked)
358                 *locked = arg.locked;
359
360         return arg.data1;
361 }
362 #endif
363
364 static int
365 _tbm_sprd_open_drm(void)
366 {
367 #ifdef HAVE_UDEV
368         struct udev_device *drm_device = NULL;
369         struct udev_list_entry *entry = NULL;
370         struct udev_enumerate *e;
371         const char *filepath;
372         struct udev *udev;
373         struct stat s;
374 #endif
375         int fd;
376
377         fd = drmOpen(SPRD_DRM_NAME, NULL);
378         if (fd != -1)
379                 return fd;
380
381 #ifdef HAVE_UDEV
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__);
385
386         udev = udev_new();
387         if (!udev) {
388                 TBM_SPRD_LOG("udev_new() failed.\n");
389                 return -1;
390         }
391
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);
396
397         udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
398                 struct udev_device *device, *device_parent;
399
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 */
404                 if (device_parent) {
405                         if (strcmp(udev_device_get_sysname(device_parent), "sprd-drm") == 0) {
406                                 drm_device = device;
407                                 DBG("[%s] Found render device: '%s' (%s)\n",
408                                     _target_name(),
409                                     udev_device_get_syspath(drm_device),
410                                     udev_device_get_sysname(device_parent));
411                                 break;
412                         }
413                 }
414                 udev_device_unref(device);
415         }
416
417         udev_enumerate_unref(e);
418
419         /* Get device file path. */
420         filepath = udev_device_get_devnode(drm_device);
421         if (!filepath) {
422                 TBM_SPRD_LOG("udev_device_get_devnode() failed.\n");
423                 udev_device_unref(drm_device);
424                 udev_unref(udev);
425                 return -1;
426         }
427
428         udev_device_unref(drm_device);
429         udev_unref(udev);
430
431         /* Open DRM device file and check validity. */
432         fd = open(filepath, O_RDWR | O_CLOEXEC);
433         if (fd < 0) {
434                 TBM_SPRD_LOG("open(%s, O_RDWR | O_CLOEXEC) failed.\n");
435                 return -1;
436         }
437
438         if (fstat(fd, &s)) {
439                 TBM_SPRD_LOG("fstat() failed %s.\n");
440                 close(fd);
441                 return -1;
442         }
443 #else
444         TBM_SPRD_LOG("[libtbm-sprd:%d] warning %s:%d fail to open drm\n",
445                       getpid(), __FUNCTION__, __LINE__);
446 #endif
447
448         return fd;
449 }
450
451 #ifdef USE_CACHE
452 static int
453 _sprd_bo_cache_flush(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int flags)
454 {
455         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
456
457         /* cache flush is managed by kernel side when using dma-fence. */
458         if (bufmgr_sprd->use_dma_fence)
459                 return 1;
460
461         struct drm_sprd_gem_cache_op cache_op = {0, };
462         int ret;
463
464         /* if bo_sprd is null, do cache_flush_all */
465         if (bo_sprd) {
466                 cache_op.flags = 0;
467                 cache_op.usr_addr = (uint64_t)((uint32_t)bo_sprd->pBase);
468                 cache_op.size = bo_sprd->size;
469         } else {
470                 flags = TBM_SPRD_CACHE_FLUSH_ALL;
471                 cache_op.flags = 0;
472                 cache_op.usr_addr = 0;
473                 cache_op.size = 0;
474         }
475
476         if (flags & TBM_SPRD_CACHE_INV) {
477                 if (flags & TBM_SPRD_CACHE_ALL)
478                         cache_op.flags |= SPRD_DRM_CACHE_INV_ALL;
479                 else
480                         cache_op.flags |= SPRD_DRM_CACHE_INV_RANGE;
481         }
482
483         if (flags & TBM_SPRD_CACHE_CLN) {
484                 if (flags & TBM_SPRD_CACHE_ALL)
485                         cache_op.flags |= SPRD_DRM_CACHE_CLN_ALL;
486                 else
487                         cache_op.flags |= SPRD_DRM_CACHE_CLN_RANGE;
488         }
489
490         if (flags & TBM_SPRD_CACHE_ALL)
491                 cache_op.flags |= SPRD_DRM_ALL_CACHES_CORES;
492
493         ret = drmCommandWriteRead(bufmgr_sprd->fd, DRM_SPRD_GEM_CACHE_OP, &cache_op,
494                                    sizeof(cache_op));
495         if (ret) {
496                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
497                               "error %s:%d fail to flush the cache.\n",
498                               getpid(), __FUNCTION__, __LINE__);
499                 return 0;
500         }
501
502         return 1;
503 }
504 #endif
505
506 static int
507 _bo_init_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int import)
508 {
509         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
510         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
511
512         if (bufmgr_sprd->use_dma_fence)
513                 return 1;
514
515         _tgl_init(bufmgr_sprd->tgl_fd, bo_sprd->name);
516
517 #ifdef USE_CACHE
518         tbm_bo_cache_state cache_state;
519
520         if (import == 0) {
521                 cache_state.data.isDirtied = DEVICE_NONE;
522                 cache_state.data.isCached = 0;
523                 cache_state.data.cntFlush = 0;
524
525                 _tgl_set_data(bufmgr_sprd->tgl_fd, bo_sprd->name, cache_state.val);
526         }
527 #endif
528
529         return 1;
530 }
531
532 static int
533 _bo_set_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int device, int opt)
534 {
535 #ifdef USE_CACHE
536         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
537         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
538
539         char need_flush = 0;
540         unsigned short cntFlush = 0;
541
542         if (bufmgr_sprd->use_dma_fence)
543                 return 1;
544
545         if (bo_sprd->flags_sprd & SPRD_BO_NONCACHABLE)
546                 return 1;
547
548         /* get cache state of a bo */
549         bo_sprd->cache_state.val = _tgl_get_data(bufmgr_sprd->tgl_fd, bo_sprd->name, NULL);
550
551         /* get global cache flush count */
552         cntFlush = (unsigned short)_tgl_get_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, NULL);
553
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;
558
559                 bo_sprd->cache_state.data.isCached = 1;
560                 if (opt & TBM_OPTION_WRITE)
561                         bo_sprd->cache_state.data.isDirtied = DEVICE_CA;
562                 else {
563                         if (bo_sprd->cache_state.data.isDirtied != DEVICE_CA)
564                                 bo_sprd->cache_state.data.isDirtied = DEVICE_NONE;
565                 }
566         } else {
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;
571
572                 if (opt & TBM_OPTION_WRITE)
573                         bo_sprd->cache_state.data.isDirtied = DEVICE_CO;
574                 else {
575                         if (bo_sprd->cache_state.data.isDirtied != DEVICE_CO)
576                                 bo_sprd->cache_state.data.isDirtied = DEVICE_NONE;
577                 }
578         }
579
580         if (need_flush) {
581                 if (need_flush & TBM_SPRD_CACHE_ALL)
582                         _tgl_set_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, (unsigned int)(++cntFlush));
583
584                 /* call cache flush */
585                 _sprd_bo_cache_flush(bufmgr_sprd, bo_sprd, need_flush);
586
587                 DBG("[libtbm:%d] \tcache(%d,%d)....flush:0x%x, cntFlush(%d)\n",
588                     getpid(),
589                     bo_sprd->cache_state.data.isCached,
590                     bo_sprd->cache_state.data.isDirtied,
591                     need_flush,
592                     cntFlush);
593         }
594 #endif
595
596         return 1;
597 }
598
599 static int
600 _bo_save_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd)
601 {
602 #ifdef USE_CACHE
603         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
604         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
605
606         if (bufmgr_sprd->use_dma_fence)
607                 return 1;
608
609         unsigned short cntFlush = 0;
610
611         /* get global cache flush count */
612         cntFlush = (unsigned short)_tgl_get_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, NULL);
613
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);
617 #endif
618
619         return 1;
620 }
621
622 static void
623 _bo_destroy_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd)
624 {
625         SPRD_RETURN_IF_FAIL(bo_sprd != NULL);
626         SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
627
628         if (bufmgr_sprd->use_dma_fence)
629                 return;
630
631         _tgl_destroy(bufmgr_sprd->tgl_fd, bo_sprd->name);
632 }
633
634 static int
635 _bufmgr_init_cache_state(tbm_bufmgr_sprd bufmgr_sprd)
636 {
637         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
638
639         if (bufmgr_sprd->use_dma_fence)
640                 return 1;
641
642         /* open tgl fd for saving cache flush data */
643         bufmgr_sprd->tgl_fd = open(tgl_devfile, O_RDWR);
644
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);
651                         return 0;
652                 }
653         }
654
655 #ifdef USE_CACHE
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",
659                                getpid());
660
661                 close(bufmgr_sprd->tgl_fd);
662                 return 0;
663         }
664 #endif
665
666         return 1;
667 }
668
669 static void
670 _bufmgr_deinit_cache_state(tbm_bufmgr_sprd bufmgr_sprd)
671 {
672         SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
673
674         if (bufmgr_sprd->use_dma_fence)
675                 return;
676
677         if (bufmgr_sprd->tgl_fd >= 0)
678                 close(bufmgr_sprd->tgl_fd);
679 }
680
681 #ifndef USE_CONTIG_ONLY
682 static unsigned int
683 _get_sprd_flag_from_tbm(unsigned int ftbm)
684 {
685         unsigned int flags = 0;
686
687         /*
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.
692          * */
693
694         if (ftbm & TBM_BO_SCANOUT)
695                 flags = SPRD_BO_CONTIG;
696         else
697                 flags = SPRD_BO_NONCONTIG | SPRD_BO_DEV_SYSTEM;
698
699         if (ftbm & TBM_BO_WC)
700                 flags |= SPRD_BO_WC;
701         else if (ftbm & TBM_BO_NONCACHABLE)
702                 flags |= SPRD_BO_NONCACHABLE;
703
704         return flags;
705 }
706
707 static unsigned int
708 _get_tbm_flag_from_sprd(unsigned int fsprd)
709 {
710         unsigned int flags = 0;
711
712         if (fsprd & SPRD_BO_NONCONTIG)
713                 flags |= TBM_BO_DEFAULT;
714         else
715                 flags |= TBM_BO_SCANOUT;
716
717         if (fsprd & SPRD_BO_WC)
718                 flags |= TBM_BO_WC;
719         else if (fsprd & SPRD_BO_CACHABLE)
720                 flags |= TBM_BO_DEFAULT;
721         else
722                 flags |= TBM_BO_NONCACHABLE;
723
724         return flags;
725 }
726 #endif
727
728 static unsigned int
729 _get_name(int fd, unsigned int gem)
730 {
731         struct drm_gem_flink arg = {0,};
732
733         arg.handle = gem;
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);
738                 return 0;
739         }
740
741         return (unsigned int)arg.name;
742 }
743
744 static tbm_bo_handle
745 _sprd_bo_handle(tbm_bo_sprd bo_sprd, int device)
746 {
747         tbm_bo_handle bo_handle;
748         memset(&bo_handle, 0x0, sizeof(uint64_t));
749
750         switch (device) {
751         case TBM_DEVICE_DEFAULT:
752         case TBM_DEVICE_2D:
753                 bo_handle.u32 = (uint32_t)bo_sprd->gem;
754                 break;
755         case TBM_DEVICE_CPU:
756                 if (!bo_sprd->pBase) {
757                         struct drm_sprd_gem_mmap arg = {0,};
758
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;
766                         }
767                         bo_sprd->pBase = (void *)((uint32_t)arg.mapped);
768                 }
769
770                 bo_handle.ptr = (void *)bo_sprd->pBase;
771                 break;
772         case TBM_DEVICE_3D:
773 #ifdef USE_DMAIMPORT
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;
782                         }
783                         bo_sprd->dmabuf = arg.fd;
784                 }
785
786                 bo_handle.u32 = (uint32_t)bo_sprd->dmabuf;
787
788 #endif
789                 break;
790
791         case TBM_DEVICE_MM:
792 #ifdef USE_HEAP_ID
793                 //TODO : Add ioctl for GSP MAP once available.
794                 DBG("[libtbm-sprd:%d] %s In case TBM_DEVICE_MM:  \n", getpid(),
795                      __FUNCTION_);
796                 _
797
798 #else
799                 if (!bo_sprd->dmabuf) {
800                         struct drm_prime_handle arg = {0, };
801
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;
808                         }
809                         bo_sprd->dmabuf = arg.fd;
810                 }
811
812                 bo_handle.u32 = (uint32_t)bo_sprd->dmabuf;
813 #endif
814                 break;
815         default:
816                 bo_handle.ptr = (void *) NULL;
817                 break;
818         }
819
820         return bo_handle;
821 }
822
823 static int
824 tbm_sprd_bo_size(tbm_bo bo)
825 {
826         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
827
828         tbm_bo_sprd bo_sprd;
829
830         bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
831         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
832
833         return bo_sprd->size;
834 }
835
836 static void *
837 tbm_sprd_bo_alloc(tbm_bo bo, int size, int flags)
838 {
839         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
840
841         tbm_bufmgr_sprd bufmgr_sprd;
842         unsigned int sprd_flags;
843         tbm_bo_sprd bo_sprd;
844
845         bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
846         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
847
848         bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
849         if (!bo_sprd) {
850                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
851                               "error %s:%d fail to allocate the bo private\n",
852                               getpid(), __FUNCTION__, __LINE__);
853                 return 0;
854         }
855
856 #ifdef USE_CONTIG_ONLY
857         flags = TBM_BO_SCANOUT;
858         sprd_flags = SPRD_BO_CONTIG;
859 #else
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
864
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,
869                                 sizeof(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);
873                 free(bo_sprd);
874                 return 0;
875         }
876
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);
883
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);
886                 free(bo_sprd);
887                 return 0;
888         }
889
890         pthread_mutex_init(&bo_sprd->mutex, NULL);
891
892         if (bufmgr_sprd->use_dma_fence
893             && !bo_sprd->dmabuf) {
894                 struct drm_prime_handle arg = {0, };
895
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);
901                         free(bo_sprd);
902                         return 0;
903                 }
904                 bo_sprd->dmabuf = arg.fd;
905         }
906
907         /* add bo to hash */
908         PrivGem *privGem = calloc(1, sizeof(PrivGem));
909         if (!privGem) {
910                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
911                               "error %s:%d Fail to calloc PrivGem\n",
912                               getpid(), __FUNCTION__, __LINE__);
913                 free(bo_sprd);
914                 return 0;
915         }
916
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);
923         }
924
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,
928              flags, sprd_flags);
929
930         return (void *)bo_sprd;
931 }
932
933 static void
934 tbm_sprd_bo_free(tbm_bo bo)
935 {
936         tbm_bo_sprd bo_sprd;
937         tbm_bufmgr_sprd bufmgr_sprd;
938
939         if (!bo)
940                 return;
941
942         bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
943         SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
944
945         bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
946         SPRD_RETURN_IF_FAIL(bo_sprd != NULL);
947
948         DBG("[libtbm-sprd:%d] %s size:%d, gem:%d(%d)\n",
949              getpid(), __FUNCTION__, bo_sprd->size, bo_sprd->gem, bo_sprd->name);
950
951         if (bo_sprd->pBase) {
952                 if (munmap(bo_sprd->pBase, bo_sprd->size) == -1) {
953                         TBM_SPRD_LOG("[libtbm-sprd:%d] "
954                                       "error %s:%d\n",
955                                       getpid(), __FUNCTION__, __LINE__);
956                 }
957         }
958
959         /* closedmabuf */
960         if (bo_sprd->dmabuf) {
961                 close(bo_sprd->dmabuf);
962                 bo_sprd->dmabuf = 0;
963         }
964
965         /* delete bo from hash */
966         PrivGem *privGem = NULL;
967         int ret;
968
969         ret = drmHashLookup(bufmgr_sprd->hashBos, bo_sprd->name, (void **)&privGem);
970         if (ret == 0) {
971                 privGem->ref_count--;
972                 if (privGem->ref_count == 0) {
973                         drmHashDelete(bufmgr_sprd->hashBos, bo_sprd->name);
974                         free(privGem);
975                         privGem = NULL;
976                 }
977         } else {
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);
981         }
982
983         _bo_destroy_cache_state(bufmgr_sprd, bo_sprd);
984
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] "
991                               "error %s:%d\n",
992                               getpid(), __FUNCTION__, __LINE__);
993         }
994
995         free(bo_sprd);
996 }
997
998
999 static void *
1000 tbm_sprd_bo_import(tbm_bo bo, unsigned int key)
1001 {
1002         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, NULL);
1003
1004         tbm_bufmgr_sprd bufmgr_sprd;
1005         tbm_bo_sprd bo_sprd;
1006         PrivGem *privGem = NULL;
1007         int ret;
1008
1009         bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1010         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, NULL);
1011
1012         ret = drmHashLookup(bufmgr_sprd->hashBos, key, (void **)&privGem);
1013         if (ret == 0)
1014                 return privGem->bo_priv;
1015
1016         struct drm_sprd_gem_info info = {0, };
1017         struct drm_gem_open arg = {0, };
1018
1019         arg.name = key;
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);
1024                 return NULL;
1025         }
1026
1027         info.handle = arg.handle;
1028         if (drmCommandWriteRead(bufmgr_sprd->fd,
1029                                 DRM_SPRD_GEM_GET,
1030                                 &info,
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);
1035                 goto fail_get_gem;
1036         }
1037
1038         bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
1039         if (!bo_sprd) {
1040                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
1041                               "error %s:%d fail to allocate the bo private\n",
1042                               getpid(), __FUNCTION__, __LINE__);
1043                 goto fail_alloc_bo;
1044         }
1045
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;
1054 #else
1055         bo_sprd->flags_tbm = _get_tbm_flag_from_sprd(bo_sprd->flags_sprd);
1056 #endif
1057
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;
1061         }
1062
1063         if (!bo_sprd->dmabuf) {
1064                 struct drm_prime_handle arg = {0, };
1065
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;
1072                 }
1073                 bo_sprd->dmabuf = arg.fd;
1074         }
1075
1076         /* add bo to hash */
1077         privGem = calloc(1, sizeof(PrivGem));
1078         if (!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;
1082         }
1083
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);
1090         }
1091
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);
1096
1097         return (void *)bo_sprd;
1098
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);
1104 fail_init_cache:
1105         free(bo_sprd);
1106 fail_alloc_bo:
1107 fail_get_gem:
1108         {
1109                 struct drm_gem_close gem_close_arg = {arg.handle, 0};
1110                 drmIoctl(bufmgr_sprd->fd, DRM_IOCTL_GEM_CLOSE, &gem_close_arg);
1111         }
1112         return NULL;
1113 }
1114
1115 static void *
1116 tbm_sprd_bo_import_fd(tbm_bo bo, tbm_fd key)
1117 {
1118         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, NULL);
1119
1120         tbm_bufmgr_sprd bufmgr_sprd;
1121         tbm_bo_sprd bo_sprd;
1122         unsigned int name;
1123         PrivGem *privGem;
1124
1125         bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1126         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, NULL);
1127
1128         //getting handle from fd
1129         struct drm_prime_handle arg = {0, };
1130         unsigned int gem;
1131
1132         arg.fd = key;
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));
1136                 return NULL;
1137         }
1138         gem = arg.handle;
1139
1140         name = _get_name(bufmgr_sprd->fd, gem);
1141         if (!name) {
1142                 TBM_SPRD_LOG("error bo:%p Cannot get name from gem:%d, fd:%d (%s)\n",
1143                                 bo, gem, key, strerror(errno));
1144                 return NULL;
1145         }
1146
1147         if (!drmHashLookup(bufmgr_sprd->hashBos, name, (void **)&privGem)) {
1148                 if (gem == privGem->bo_priv->gem)
1149                         return privGem->bo_priv;
1150         }
1151
1152         unsigned int real_size;
1153         struct drm_sprd_gem_info info = {0, };
1154
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);
1161
1162         info.handle = gem;
1163         if (drmCommandWriteRead(bufmgr_sprd->fd,
1164                                 DRM_SPRD_GEM_GET,
1165                                 &info,
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));
1169                 return NULL;
1170         }
1171
1172         if (real_size == -1)
1173                 real_size = info.size;
1174
1175         bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
1176         if (!bo_sprd) {
1177                 TBM_SPRD_LOG("error bo:%p fail to allocate the bo private\n", bo);
1178                 return NULL;
1179         }
1180
1181         bo_sprd->fd = bufmgr_sprd->fd;
1182         bo_sprd->gem = gem;
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);
1186
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;
1192         }
1193
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;
1197         }
1198
1199         /* add bo to hash */
1200         privGem = calloc(1, sizeof(PrivGem));
1201         if (!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;
1206         }
1207
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);
1213         }
1214
1215         DBG(" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n",
1216              _target_name(),
1217              bo,
1218              bo_sprd->gem, bo_sprd->name,
1219              bo_sprd->dmabuf,
1220              key,
1221              bo_sprd->flags_tbm, bo_sprd->flags_sprd,
1222              bo_sprd->size);
1223
1224         return (void *)bo_sprd;
1225
1226 fail_alloc_gem_priv:
1227         _bo_destroy_cache_state(bufmgr_sprd, bo_sprd);
1228 fail_init_cache:
1229 fail_check_name:
1230         free(bo_sprd);
1231         return NULL;
1232 }
1233
1234 static unsigned int
1235 tbm_sprd_bo_export(tbm_bo bo)
1236 {
1237         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1238
1239         tbm_bo_sprd bo_sprd;
1240
1241         bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1242         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1243
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__);
1250                         return 0;
1251                 }
1252         }
1253
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);
1258
1259         return (unsigned int)bo_sprd->name;
1260 }
1261
1262 static tbm_fd
1263 tbm_sprd_bo_export_fd(tbm_bo bo)
1264 {
1265         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, -1);
1266
1267         tbm_bo_sprd bo_sprd;
1268         int ret;
1269
1270         bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1271         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, -1);
1272
1273         struct drm_prime_handle arg = {0, };
1274
1275         arg.handle = bo_sprd->gem;
1276         ret = drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg);
1277         if (ret) {
1278                 TBM_SPRD_LOG("error bo:%p Cannot dmabuf=%d (%s)\n",
1279                               bo, bo_sprd->gem, strerror(errno));
1280                 return (tbm_fd) ret;
1281         }
1282
1283         DBG(" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n",
1284              _target_name(),
1285              bo,
1286              bo_sprd->gem, bo_sprd->name,
1287              bo_sprd->dmabuf,
1288              arg.fd,
1289              bo_sprd->flags_tbm, bo_sprd->flags_sprd,
1290              bo_sprd->size);
1291
1292         return (tbm_fd)arg.fd;
1293 }
1294
1295
1296 static tbm_bo_handle
1297 tbm_sprd_bo_get_handle(tbm_bo bo, int device)
1298 {
1299         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, (tbm_bo_handle) NULL);
1300
1301         tbm_bo_handle bo_handle;
1302         tbm_bo_sprd bo_sprd;
1303
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);
1306
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;
1312         }
1313
1314         DBG("[libtbm-sprd:%d] %s gem:%d(%d), %s\n", getpid(),
1315              __FUNCTION__, bo_sprd->gem, bo_sprd->name, STR_DEVICE[device]);
1316
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;
1324         }
1325
1326         return bo_handle;
1327 }
1328
1329 static tbm_bo_handle
1330 tbm_sprd_bo_map(tbm_bo bo, int device, int opt)
1331 {
1332         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, (tbm_bo_handle) NULL);
1333
1334         tbm_bo_handle bo_handle;
1335         tbm_bo_sprd bo_sprd;
1336         tbm_bufmgr_sprd bufmgr_sprd;
1337
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);
1340
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);
1343
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;
1349         }
1350
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]);
1353
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;
1361         }
1362
1363         if (bo_sprd->map_cnt == 0)
1364                 _bo_set_cache_state(bufmgr_sprd, bo_sprd, device, opt);
1365
1366         bo_sprd->map_cnt++;
1367
1368         return bo_handle;
1369 }
1370
1371 static int
1372 tbm_sprd_bo_unmap(tbm_bo bo)
1373 {
1374         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1375
1376         tbm_bufmgr_sprd bufmgr_sprd;
1377         tbm_bo_sprd bo_sprd;
1378
1379         bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1380         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1381
1382         bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1383         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1384
1385         if (!bo_sprd->gem)
1386                 return 0;
1387
1388         bo_sprd->map_cnt--;
1389
1390         if (bo_sprd->map_cnt == 0)
1391                 _bo_save_cache_state(bufmgr_sprd, bo_sprd);
1392
1393         DBG("[libtbm-sprd:%d] %s gem:%d(%d) \n", getpid(),
1394              __FUNCTION__, bo_sprd->gem, bo_sprd->name);
1395
1396         return 1;
1397 }
1398
1399 static int
1400 tbm_sprd_bo_lock(tbm_bo bo, int device, int opt)
1401 {
1402         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1403
1404         tbm_bufmgr_sprd bufmgr_sprd;
1405         tbm_bo_sprd bo_sprd;
1406
1407         bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1408         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1409
1410         bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1411         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1412
1413 #if USE_BACKEND_LOCK
1414         int ret = 0;
1415
1416         if (bufmgr_sprd->use_dma_fence) {
1417                 struct dma_buf_fence fence;
1418
1419                 memset(&fence, 0, sizeof(struct dma_buf_fence));
1420
1421                 /* Check if the given type is valid or not. */
1422                 if (opt & TBM_OPTION_WRITE) {
1423                         if (device == TBM_DEVICE_CPU)
1424                                 fence.type = DMA_BUF_ACCESS_WRITE;
1425                         else if (device == TBM_DEVICE_3D)
1426                                 fence.type = DMA_BUF_ACCESS_WRITE | DMA_BUF_ACCESS_DMA;
1427                         else {
1428                                 DBG("[libtbm-sprd:%d] %s GET_FENCE is ignored(device type is not 3D/CPU),\n",
1429                                      getpid(), __FUNCTION__);
1430                                 return 0;
1431                         }
1432                 } else if (opt & TBM_OPTION_READ) {
1433                         if (device == TBM_DEVICE_CPU)
1434                                 fence.type = DMA_BUF_ACCESS_READ;
1435                         else if (device == TBM_DEVICE_3D)
1436                                 fence.type = DMA_BUF_ACCESS_READ | DMA_BUF_ACCESS_DMA;
1437                         else {
1438                                 DBG("[libtbm-sprd:%d] %s GET_FENCE is ignored(device type is not 3D/CPU),\n",
1439                                      getpid(), __FUNCTION__);
1440                                 return 0;
1441                         }
1442                 } else {
1443                         TBM_SPRD_LOG("[libtbm-sprd:%d] error %s:%d Invalid argument\n", getpid(),
1444                                       __FUNCTION__, __LINE__);
1445                         return 0;
1446                 }
1447
1448                 ret = ioctl(bo_sprd->dmabuf, DMABUF_IOCTL_GET_FENCE, &fence);
1449                 if (ret < 0) {
1450                         TBM_SPRD_LOG("[libtbm-sprd:%d] "
1451                                       "error %s:%d  Can not set GET FENCE(%s)\n",
1452                                       getpid(), __FUNCTION__, __LINE__, strerror(errno));
1453                         return 0;
1454                 }
1455
1456                 pthread_mutex_lock(&bo_sprd->mutex);
1457                 int i;
1458                 for (i = 0; i < DMA_FENCE_LIST_MAX; i++) {
1459                         if (bo_sprd->dma_fence[i].ctx == 0) {
1460                                 bo_sprd->dma_fence[i].type = fence.type;
1461                                 bo_sprd->dma_fence[i].ctx = fence.ctx;
1462                                 break;
1463                         }
1464                 }
1465                 if (i == DMA_FENCE_LIST_MAX) {
1466                         //TODO: if dma_fence list is full, it needs realloc. I will fix this. by minseok3.kim
1467                         TBM_SPRD_LOG("[libtbm-sprd:%d] "
1468                                       "error %s:%d  fence list is full\n",
1469                                       getpid(), __FUNCTION__, __LINE__);
1470                 }
1471                 pthread_mutex_unlock(&bo_sprd->mutex);
1472
1473                 DBG("[libtbm-sprd:%d] %s DMABUF_IOCTL_GET_FENCE! flink_id=%d dmabuf=%d\n",
1474                      getpid(),
1475                      __FUNCTION__, bo_sprd->name, bo_sprd->dmabuf);
1476         } else {
1477                 ret = _tgl_lock(bufmgr_sprd->tgl_fd, bo_sprd->name);
1478
1479                 DBG("[libtbm-sprd:%d] lock tgl flink_id:%d\n",
1480                      getpid(), __FUNCTION__, bo_sprd->name);
1481
1482                 return ret;
1483         }
1484 #endif
1485
1486         return 1;
1487 }
1488
1489 static int
1490 tbm_sprd_bo_unlock(tbm_bo bo)
1491 {
1492         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1493
1494         tbm_bufmgr_sprd bufmgr_sprd;
1495         tbm_bo_sprd bo_sprd;
1496
1497         bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1498         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1499
1500         bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
1501         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1502
1503 #if USE_BACKEND_LOCK
1504         int ret = 0;
1505
1506         if (bufmgr_sprd->use_dma_fence) {
1507                 struct dma_buf_fence fence;
1508
1509                 if (!bo_sprd->dma_fence[0].ctx) {
1510                         DBG("[libtbm-sprd:%d] %s FENCE not support or ignored,\n", getpid(),
1511                              __FUNCTION__);
1512                         return 0;
1513                 }
1514
1515                 if (!bo_sprd->dma_fence[0].type) {
1516                         DBG("[libtbm-sprd:%d] %s device type is not 3D/CPU,\n", getpid(),
1517                              __FUNCTION__);
1518                         return 0;
1519                 }
1520
1521                 pthread_mutex_lock(&bo_sprd->mutex);
1522                 fence.type = bo_sprd->dma_fence[0].type;
1523                 fence.ctx = bo_sprd->dma_fence[0].ctx;
1524                 int i;
1525                 for (i = 1; i < DMA_FENCE_LIST_MAX; i++) {
1526                         bo_sprd->dma_fence[i - 1].type = bo_sprd->dma_fence[i].type;
1527                         bo_sprd->dma_fence[i - 1].ctx = bo_sprd->dma_fence[i].ctx;
1528                 }
1529                 bo_sprd->dma_fence[DMA_FENCE_LIST_MAX - 1].type = 0;
1530                 bo_sprd->dma_fence[DMA_FENCE_LIST_MAX - 1].ctx = 0;
1531                 pthread_mutex_unlock(&bo_sprd->mutex);
1532
1533                 ret = ioctl(bo_sprd->dmabuf, DMABUF_IOCTL_PUT_FENCE, &fence);
1534                 if (ret < 0) {
1535                         TBM_SPRD_LOG("[libtbm-sprd:%d] "
1536                                       "error %s:%d  Can not set PUT FENCE(%s)\n",
1537                                       getpid(), __FUNCTION__, __LINE__, strerror(errno));
1538                         return 0;
1539                 }
1540
1541                 DBG("[libtbm-sprd:%d] %s DMABUF_IOCTL_PUT_FENCE! flink_id=%d dmabuf=%d\n",
1542                      getpid(),
1543                      __FUNCTION__, bo_sprd->name, bo_sprd->dmabuf);
1544         } else {
1545                 ret = _tgl_unlock(bufmgr_sprd->tgl_fd, bo_sprd->name);
1546
1547                 DBG("[libtbm-sprd:%d] unlock tgl flink_id:%d\n",
1548                      getpid(), __FUNCTION__, bo_sprd->name);
1549
1550                 return ret;
1551         }
1552 #endif
1553
1554         return 1;
1555 }
1556
1557 static void
1558 tbm_sprd_bufmgr_deinit(void *priv)
1559 {
1560         SPRD_RETURN_IF_FAIL(priv != NULL);
1561
1562         tbm_bufmgr_sprd bufmgr_sprd;
1563
1564         bufmgr_sprd = (tbm_bufmgr_sprd)priv;
1565
1566         if (bufmgr_sprd->hashBos) {
1567                 unsigned long key;
1568                 void *value;
1569
1570                 while (drmHashFirst(bufmgr_sprd->hashBos, &key, &value) > 0) {
1571                         free(value);
1572                         drmHashDelete(bufmgr_sprd->hashBos, key);
1573                 }
1574
1575                 drmHashDestroy(bufmgr_sprd->hashBos);
1576                 bufmgr_sprd->hashBos = NULL;
1577         }
1578
1579         if (bufmgr_sprd->bind_display)
1580                 tbm_drm_helper_wl_auth_server_deinit();
1581
1582         if (tbm_backend_is_display_server())
1583                 tbm_drm_helper_unset_tbm_master_fd();
1584
1585         if (bufmgr_sprd->device_name)
1586                 free(bufmgr_sprd->device_name);
1587
1588         _bufmgr_deinit_cache_state(bufmgr_sprd);
1589
1590         close(bufmgr_sprd->fd);
1591
1592         free(bufmgr_sprd);
1593 }
1594
1595 static int
1596 tbm_sprd_surface_supported_format(uint32_t **formats, uint32_t *num)
1597 {
1598         uint32_t *color_formats;
1599
1600         color_formats = (uint32_t *)calloc(1,
1601                                             sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
1602         if (color_formats == NULL)
1603                 return 0;
1604
1605         memcpy(color_formats, tbm_sprd_color_format_list,
1606                 sizeof(uint32_t)*TBM_COLOR_FORMAT_COUNT);
1607
1608         *formats = color_formats;
1609         *num = TBM_COLOR_FORMAT_COUNT;
1610
1611         return 1;
1612 }
1613
1614
1615 /**
1616  * @brief get the plane data of the surface.
1617  * @param[in] width : the width of the surface
1618  * @param[in] height : the height of the surface
1619  * @param[in] format : the format of the surface
1620  * @param[in] plane_idx : the format of the surface
1621  * @param[out] size : the size of the plane
1622  * @param[out] offset : the offset of the plane
1623  * @param[out] pitch : the pitch of the plane
1624  * @param[out] padding : the padding of the plane
1625  * @return 1 if this function succeeds, otherwise 0.
1626  */
1627 static int
1628 tbm_sprd_surface_get_plane_data(int width, int height,
1629                                 tbm_format format, int plane_idx, uint32_t *size, uint32_t *offset,
1630                                 uint32_t *pitch, int *bo_idx)
1631 {
1632         int ret = 1;
1633         int bpp;
1634         int _offset = 0;
1635         int _pitch = 0;
1636         int _size = 0;
1637         int _bo_idx = 0;
1638         int _align_height = 0;
1639
1640         switch (format) {
1641                 /* 16 bpp RGB */
1642         case TBM_FORMAT_XRGB4444:
1643         case TBM_FORMAT_XBGR4444:
1644         case TBM_FORMAT_RGBX4444:
1645         case TBM_FORMAT_BGRX4444:
1646         case TBM_FORMAT_ARGB4444:
1647         case TBM_FORMAT_ABGR4444:
1648         case TBM_FORMAT_RGBA4444:
1649         case TBM_FORMAT_BGRA4444:
1650         case TBM_FORMAT_XRGB1555:
1651         case TBM_FORMAT_XBGR1555:
1652         case TBM_FORMAT_RGBX5551:
1653         case TBM_FORMAT_BGRX5551:
1654         case TBM_FORMAT_ARGB1555:
1655         case TBM_FORMAT_ABGR1555:
1656         case TBM_FORMAT_RGBA5551:
1657         case TBM_FORMAT_BGRA5551:
1658         case TBM_FORMAT_RGB565:
1659                 bpp = 16;
1660                 _offset = 0;
1661                 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1662                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1663                 _bo_idx = 0;
1664                 break;
1665                 /* 24 bpp RGB */
1666         case TBM_FORMAT_RGB888:
1667         case TBM_FORMAT_BGR888:
1668                 bpp = 24;
1669                 _offset = 0;
1670                 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1671                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1672                 _bo_idx = 0;
1673                 break;
1674                 /* 32 bpp RGB */
1675         case TBM_FORMAT_XRGB8888:
1676         case TBM_FORMAT_XBGR8888:
1677         case TBM_FORMAT_RGBX8888:
1678         case TBM_FORMAT_BGRX8888:
1679         case TBM_FORMAT_ARGB8888:
1680         case TBM_FORMAT_ABGR8888:
1681         case TBM_FORMAT_RGBA8888:
1682         case TBM_FORMAT_BGRA8888:
1683                 bpp = 32;
1684                 _offset = 0;
1685                 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1686                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1687                 _bo_idx = 0;
1688                 break;
1689
1690                 /* packed YCbCr */
1691         case TBM_FORMAT_YUYV:
1692         case TBM_FORMAT_YVYU:
1693         case TBM_FORMAT_UYVY:
1694         case TBM_FORMAT_VYUY:
1695         case TBM_FORMAT_AYUV:
1696                 bpp = 32;
1697                 _offset = 0;
1698                 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1699                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1700                 _bo_idx = 0;
1701                 break;
1702
1703                 /*
1704                 * 2 plane YCbCr
1705                 * index 0 = Y plane, [7:0] Y
1706                 * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1707                 * or
1708                 * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1709                 */
1710         case TBM_FORMAT_NV12:
1711         case TBM_FORMAT_NV21:
1712                 bpp = 12;
1713                 if (plane_idx == 0) {
1714                         _offset = 0;
1715                         _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1716                         _align_height = SIZE_ALIGN(height, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1717                         _size = SIZE_ALIGN(_pitch * _align_height, TBM_SURFACE_ALIGNMENT_PLANE);
1718                         _bo_idx = 0;
1719                 } else if (plane_idx == 1) {
1720                         _offset = width * height;
1721                         _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1722                         _align_height = SIZE_ALIGN(height / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1723                         _size = SIZE_ALIGN(_pitch * _align_height, TBM_SURFACE_ALIGNMENT_PLANE);
1724                         _bo_idx = 0;
1725                 }
1726                 break;
1727
1728         case TBM_FORMAT_NV16:
1729         case TBM_FORMAT_NV61:
1730                 bpp = 16;
1731                 //if(plane_idx == 0)
1732                 {
1733                         _offset = 0;
1734                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1735                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1736                         _bo_idx = 0;
1737                         if (plane_idx == 0)
1738                                 break;
1739                 }
1740                 //else if( plane_idx ==1 )
1741                 {
1742                         _offset += _size;
1743                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1744                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1745                         _bo_idx = 0;
1746                 }
1747                 break;
1748
1749                 /*
1750                 * 3 plane YCbCr
1751                 * index 0: Y plane, [7:0] Y
1752                 * index 1: Cb plane, [7:0] Cb
1753                 * index 2: Cr plane, [7:0] Cr
1754                 * or
1755                 * index 1: Cr plane, [7:0] Cr
1756                 * index 2: Cb plane, [7:0] Cb
1757                 */
1758                 /*
1759                 NATIVE_BUFFER_FORMAT_YV12
1760                 NATIVE_BUFFER_FORMAT_I420
1761                 */
1762         case TBM_FORMAT_YUV410:
1763         case TBM_FORMAT_YVU410:
1764                 bpp = 9;
1765                 break;
1766         case TBM_FORMAT_YUV411:
1767         case TBM_FORMAT_YVU411:
1768         case TBM_FORMAT_YUV420:
1769         case TBM_FORMAT_YVU420:
1770                 bpp = 12;
1771                 //if(plane_idx == 0)
1772                 {
1773                         _offset = 0;
1774                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1775                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1776                         _bo_idx = 0;
1777                         if (plane_idx == 0)
1778                                 break;
1779                 }
1780                 //else if( plane_idx == 1 )
1781                 {
1782                         _offset += _size;
1783                         _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1784                         _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1785                         _bo_idx = 0;
1786                         if (plane_idx == 1)
1787                                 break;
1788                 }
1789                 //else if (plane_idx == 2 )
1790                 {
1791                         _offset += _size;
1792                         _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1793                         _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1794                         _bo_idx = 0;
1795                 }
1796                 break;
1797         case TBM_FORMAT_YUV422:
1798         case TBM_FORMAT_YVU422:
1799                 bpp = 16;
1800                 //if(plane_idx == 0)
1801                 {
1802                         _offset = 0;
1803                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1804                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1805                         _bo_idx = 0;
1806                         if (plane_idx == 0)
1807                                 break;
1808                 }
1809                 //else if( plane_idx == 1 )
1810                 {
1811                         _offset += _size;
1812                         _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1813                         _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
1814                         _bo_idx = 0;
1815                         if (plane_idx == 1)
1816                                 break;
1817                 }
1818                 //else if (plane_idx == 2 )
1819                 {
1820                         _offset += _size;
1821                         _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1822                         _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
1823                         _bo_idx = 0;
1824                 }
1825                 break;
1826         case TBM_FORMAT_YUV444:
1827         case TBM_FORMAT_YVU444:
1828                 bpp = 24;
1829                 //if(plane_idx == 0)
1830                 {
1831                         _offset = 0;
1832                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1833                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1834                         _bo_idx = 0;
1835                         if (plane_idx == 0)
1836                                 break;
1837                 }
1838                 //else if( plane_idx == 1 )
1839                 {
1840                         _offset += _size;
1841                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1842                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1843                         _bo_idx = 0;
1844                         if (plane_idx == 1)
1845                                 break;
1846                 }
1847                 //else if (plane_idx == 2 )
1848                 {
1849                         _offset += _size;
1850                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1851                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1852                         _bo_idx = 0;
1853                 }
1854                 break;
1855         default:
1856                 bpp = 0;
1857                 break;
1858         }
1859
1860         *size = _size;
1861         *offset = _offset;
1862         *pitch = _pitch;
1863         *bo_idx = _bo_idx;
1864
1865         return ret;
1866 }
1867
1868 static int
1869 tbm_sprd_bo_get_flags(tbm_bo bo)
1870 {
1871         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1872
1873         tbm_bo_sprd bo_sprd;
1874
1875         bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1876         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1877
1878         return bo_sprd->flags_tbm;
1879 }
1880
1881 static int
1882 tbm_sprd_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1883 {
1884         tbm_bufmgr_sprd bufmgr_sprd;
1885
1886         bufmgr_sprd = tbm_backend_get_priv_from_bufmgr(bufmgr);
1887         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1888
1889         if (!tbm_drm_helper_wl_auth_server_init(NativeDisplay, bufmgr_sprd->fd,
1890                                            bufmgr_sprd->device_name, 0)) {
1891                 TBM_SPRD_LOG("[libtbm-sprd:%d] error:Fail to tbm_drm_helper_wl_server_init\n");
1892                 return 0;
1893         }
1894
1895         bufmgr_sprd->bind_display = NativeDisplay;
1896
1897         return 1;
1898 }
1899
1900 MODULEINITPPROTO(init_tbm_bufmgr_priv);
1901
1902 static TBMModuleVersionInfo SprdVersRec = {
1903         "sprd",
1904         "Samsung",
1905         TBM_ABI_VERSION,
1906 };
1907
1908 TBMModuleData tbmModuleData = { &SprdVersRec, init_tbm_bufmgr_priv};
1909
1910 int
1911 init_tbm_bufmgr_priv(tbm_bufmgr bufmgr, int fd)
1912 {
1913         tbm_bufmgr_backend bufmgr_backend;
1914         tbm_bufmgr_sprd bufmgr_sprd;
1915         int fp;
1916
1917         if (!bufmgr)
1918                 return 0;
1919
1920         bufmgr_sprd = calloc(1, sizeof(struct _tbm_bufmgr_sprd));
1921         if (!bufmgr_sprd) {
1922                 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to alloc bufmgr_sprd!\n", getpid());
1923                 return 0;
1924         }
1925
1926         if (tbm_backend_is_display_server()) {
1927                 bufmgr_sprd->fd = tbm_drm_helper_get_master_fd();
1928                 if (bufmgr_sprd->fd < 0) {
1929                         bufmgr_sprd->fd = _tbm_sprd_open_drm();
1930                         if (bufmgr_sprd->fd < 0) {
1931                                 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to open drm!\n", getpid());
1932                                 goto fail_open_drm;
1933                         }
1934                 }
1935
1936                 tbm_drm_helper_set_tbm_master_fd(bufmgr_sprd->fd);
1937
1938                 bufmgr_sprd->device_name = drmGetDeviceNameFromFd(bufmgr_sprd->fd);
1939                 if (!bufmgr_sprd->device_name) {
1940                         TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to get device name!\n", getpid());
1941                         tbm_drm_helper_unset_tbm_master_fd();
1942                         goto fail_get_device_name;
1943                 }
1944         } else {
1945                 if (!tbm_drm_helper_get_auth_info(&(bufmgr_sprd->fd), &(bufmgr_sprd->device_name), NULL)) {
1946                         TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to get auth drm info!\n", getpid());
1947                         goto fail_get_auth_info;
1948                 }
1949         }
1950
1951         //Create Hash Table
1952         bufmgr_sprd->hashBos = drmHashCreate();
1953
1954         //Check if the tbm manager supports dma fence or not.
1955         fp = open("/sys/module/dmabuf_sync/parameters/enabled", O_RDONLY);
1956         if (fp != -1) {
1957                 char buf[1];
1958                 int length = read(fp, buf, 1);
1959
1960                 if (length == 1 && buf[0] == '1')
1961                         bufmgr_sprd->use_dma_fence = 1;
1962
1963                 close(fp);
1964         }
1965
1966         if (!_bufmgr_init_cache_state(bufmgr_sprd)) {
1967                 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to init bufmgr cache state\n", getpid());
1968                 goto fail_init_cache_state;
1969         }
1970
1971         bufmgr_backend = tbm_backend_alloc();
1972         if (!bufmgr_backend) {
1973                 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to alloc backend!\n", getpid());
1974                 goto fail_alloc_backend;
1975         }
1976
1977         bufmgr_backend->priv = (void *)bufmgr_sprd;
1978         bufmgr_backend->bufmgr_deinit = tbm_sprd_bufmgr_deinit;
1979         bufmgr_backend->bo_size = tbm_sprd_bo_size;
1980         bufmgr_backend->bo_alloc = tbm_sprd_bo_alloc;
1981         bufmgr_backend->bo_free = tbm_sprd_bo_free;
1982         bufmgr_backend->bo_import = tbm_sprd_bo_import;
1983         bufmgr_backend->bo_import_fd = tbm_sprd_bo_import_fd;
1984         bufmgr_backend->bo_export = tbm_sprd_bo_export;
1985         bufmgr_backend->bo_export_fd = tbm_sprd_bo_export_fd;
1986         bufmgr_backend->bo_get_handle = tbm_sprd_bo_get_handle;
1987         bufmgr_backend->bo_map = tbm_sprd_bo_map;
1988         bufmgr_backend->bo_unmap = tbm_sprd_bo_unmap;
1989         bufmgr_backend->surface_get_plane_data = tbm_sprd_surface_get_plane_data;
1990         bufmgr_backend->surface_supported_format = tbm_sprd_surface_supported_format;
1991         bufmgr_backend->bo_get_flags = tbm_sprd_bo_get_flags;
1992         bufmgr_backend->bo_lock = tbm_sprd_bo_lock;
1993         bufmgr_backend->bo_unlock = tbm_sprd_bo_unlock;
1994         bufmgr_backend->bufmgr_bind_native_display = tbm_sprd_bufmgr_bind_native_display;
1995
1996         if (!tbm_backend_init(bufmgr, bufmgr_backend)) {
1997                 TBM_SPRD_LOG("[libtbm-sprd:%d] error: Fail to init backend!\n", getpid());
1998                 goto fail_init_backend;
1999         }
2000
2001 #ifdef DEBUG
2002         {
2003                 char *env;
2004
2005                 env = getenv("TBM_SPRD_DEBUG");
2006                 if (env) {
2007                         bDebug = atoi(env);
2008                         TBM_SPRD_LOG("TBM_SPRD_DEBUG=%s\n", env);
2009                 } else
2010                         bDebug = 0;
2011         }
2012 #endif
2013
2014         DBG("[libtbm-sprd:%d] %s DMABUF FENCE is %s\n", getpid(),
2015              __FUNCTION__, bufmgr_sprd->use_dma_fence ? "supported!" : "NOT supported!");
2016         DBG("[libtbm-sprd:%d] %s fd:%d\n", getpid(),
2017              __FUNCTION__, bufmgr_sprd->fd);
2018
2019         return 1;
2020
2021 fail_init_backend:
2022         tbm_backend_free(bufmgr_backend);
2023 fail_alloc_backend:
2024         _bufmgr_deinit_cache_state(bufmgr_sprd);
2025 fail_init_cache_state:
2026         if (bufmgr_sprd->hashBos)
2027                 drmHashDestroy(bufmgr_sprd->hashBos);
2028         if (tbm_backend_is_display_server())
2029                 tbm_drm_helper_unset_tbm_master_fd();
2030 fail_get_device_name:
2031         close(bufmgr_sprd->fd);
2032 fail_get_auth_info:
2033 fail_open_drm:
2034         free(bufmgr_sprd);
2035         return 0;
2036 }
2037