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