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