remove the unused code
[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         if (bufmgr_sprd->device_name)
1413                 free(bufmgr_sprd->device_name);
1414
1415         _bufmgr_deinit_cache_state(bufmgr_sprd);
1416
1417         close(bufmgr_sprd->fd);
1418
1419         free(bufmgr_sprd);
1420 }
1421
1422 static int
1423 tbm_sprd_surface_supported_format(uint32_t **formats, uint32_t *num)
1424 {
1425         uint32_t *color_formats;
1426
1427         color_formats = (uint32_t *)calloc(1,
1428                                             sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
1429         if (color_formats == NULL)
1430                 return 0;
1431
1432         memcpy(color_formats, tbm_sprd_color_format_list,
1433                 sizeof(uint32_t)*TBM_COLOR_FORMAT_COUNT);
1434
1435         *formats = color_formats;
1436         *num = TBM_COLOR_FORMAT_COUNT;
1437
1438         return 1;
1439 }
1440
1441
1442 /**
1443  * @brief get the plane data of the surface.
1444  * @param[in] width : the width of the surface
1445  * @param[in] height : the height of the surface
1446  * @param[in] format : the format of the surface
1447  * @param[in] plane_idx : the format of the surface
1448  * @param[out] size : the size of the plane
1449  * @param[out] offset : the offset of the plane
1450  * @param[out] pitch : the pitch of the plane
1451  * @param[out] padding : the padding of the plane
1452  * @return 1 if this function succeeds, otherwise 0.
1453  */
1454 static int
1455 tbm_sprd_surface_get_plane_data(int width, int height,
1456                                 tbm_format format, int plane_idx, uint32_t *size, uint32_t *offset,
1457                                 uint32_t *pitch, int *bo_idx)
1458 {
1459         int ret = 1;
1460         int bpp;
1461         int _offset = 0;
1462         int _pitch = 0;
1463         int _size = 0;
1464         int _bo_idx = 0;
1465         int _align_height = 0;
1466
1467         switch (format) {
1468                 /* 16 bpp RGB */
1469         case TBM_FORMAT_XRGB4444:
1470         case TBM_FORMAT_XBGR4444:
1471         case TBM_FORMAT_RGBX4444:
1472         case TBM_FORMAT_BGRX4444:
1473         case TBM_FORMAT_ARGB4444:
1474         case TBM_FORMAT_ABGR4444:
1475         case TBM_FORMAT_RGBA4444:
1476         case TBM_FORMAT_BGRA4444:
1477         case TBM_FORMAT_XRGB1555:
1478         case TBM_FORMAT_XBGR1555:
1479         case TBM_FORMAT_RGBX5551:
1480         case TBM_FORMAT_BGRX5551:
1481         case TBM_FORMAT_ARGB1555:
1482         case TBM_FORMAT_ABGR1555:
1483         case TBM_FORMAT_RGBA5551:
1484         case TBM_FORMAT_BGRA5551:
1485         case TBM_FORMAT_RGB565:
1486                 bpp = 16;
1487                 _offset = 0;
1488                 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1489                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1490                 _bo_idx = 0;
1491                 break;
1492                 /* 24 bpp RGB */
1493         case TBM_FORMAT_RGB888:
1494         case TBM_FORMAT_BGR888:
1495                 bpp = 24;
1496                 _offset = 0;
1497                 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1498                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1499                 _bo_idx = 0;
1500                 break;
1501                 /* 32 bpp RGB */
1502         case TBM_FORMAT_XRGB8888:
1503         case TBM_FORMAT_XBGR8888:
1504         case TBM_FORMAT_RGBX8888:
1505         case TBM_FORMAT_BGRX8888:
1506         case TBM_FORMAT_ARGB8888:
1507         case TBM_FORMAT_ABGR8888:
1508         case TBM_FORMAT_RGBA8888:
1509         case TBM_FORMAT_BGRA8888:
1510                 bpp = 32;
1511                 _offset = 0;
1512                 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1513                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1514                 _bo_idx = 0;
1515                 break;
1516
1517                 /* packed YCbCr */
1518         case TBM_FORMAT_YUYV:
1519         case TBM_FORMAT_YVYU:
1520         case TBM_FORMAT_UYVY:
1521         case TBM_FORMAT_VYUY:
1522         case TBM_FORMAT_AYUV:
1523                 bpp = 32;
1524                 _offset = 0;
1525                 _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1526                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1527                 _bo_idx = 0;
1528                 break;
1529
1530                 /*
1531                 * 2 plane YCbCr
1532                 * index 0 = Y plane, [7:0] Y
1533                 * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1534                 * or
1535                 * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1536                 */
1537         case TBM_FORMAT_NV12:
1538         case TBM_FORMAT_NV21:
1539                 bpp = 12;
1540                 if (plane_idx == 0) {
1541                         _offset = 0;
1542                         _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1543                         _align_height = SIZE_ALIGN(height, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1544                         _size = SIZE_ALIGN(_pitch * _align_height, TBM_SURFACE_ALIGNMENT_PLANE);
1545                         _bo_idx = 0;
1546                 } else if (plane_idx == 1) {
1547                         _offset = width * height;
1548                         _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1549                         _align_height = SIZE_ALIGN(height / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1550                         _size = SIZE_ALIGN(_pitch * _align_height, TBM_SURFACE_ALIGNMENT_PLANE);
1551                         _bo_idx = 0;
1552                 }
1553                 break;
1554
1555         case TBM_FORMAT_NV16:
1556         case TBM_FORMAT_NV61:
1557                 bpp = 16;
1558                 //if(plane_idx == 0)
1559                 {
1560                         _offset = 0;
1561                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1562                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1563                         _bo_idx = 0;
1564                         if (plane_idx == 0)
1565                                 break;
1566                 }
1567                 //else if( plane_idx ==1 )
1568                 {
1569                         _offset += _size;
1570                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1571                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1572                         _bo_idx = 0;
1573                 }
1574                 break;
1575
1576                 /*
1577                 * 3 plane YCbCr
1578                 * index 0: Y plane, [7:0] Y
1579                 * index 1: Cb plane, [7:0] Cb
1580                 * index 2: Cr plane, [7:0] Cr
1581                 * or
1582                 * index 1: Cr plane, [7:0] Cr
1583                 * index 2: Cb plane, [7:0] Cb
1584                 */
1585                 /*
1586                 NATIVE_BUFFER_FORMAT_YV12
1587                 NATIVE_BUFFER_FORMAT_I420
1588                 */
1589         case TBM_FORMAT_YUV410:
1590         case TBM_FORMAT_YVU410:
1591                 bpp = 9;
1592                 break;
1593         case TBM_FORMAT_YUV411:
1594         case TBM_FORMAT_YVU411:
1595         case TBM_FORMAT_YUV420:
1596         case TBM_FORMAT_YVU420:
1597                 bpp = 12;
1598                 //if(plane_idx == 0)
1599                 {
1600                         _offset = 0;
1601                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1602                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1603                         _bo_idx = 0;
1604                         if (plane_idx == 0)
1605                                 break;
1606                 }
1607                 //else if( plane_idx == 1 )
1608                 {
1609                         _offset += _size;
1610                         _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1611                         _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1612                         _bo_idx = 0;
1613                         if (plane_idx == 1)
1614                                 break;
1615                 }
1616                 //else if (plane_idx == 2 )
1617                 {
1618                         _offset += _size;
1619                         _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1620                         _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1621                         _bo_idx = 0;
1622                 }
1623                 break;
1624         case TBM_FORMAT_YUV422:
1625         case TBM_FORMAT_YVU422:
1626                 bpp = 16;
1627                 //if(plane_idx == 0)
1628                 {
1629                         _offset = 0;
1630                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1631                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1632                         _bo_idx = 0;
1633                         if (plane_idx == 0)
1634                                 break;
1635                 }
1636                 //else if( plane_idx == 1 )
1637                 {
1638                         _offset += _size;
1639                         _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1640                         _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
1641                         _bo_idx = 0;
1642                         if (plane_idx == 1)
1643                                 break;
1644                 }
1645                 //else if (plane_idx == 2 )
1646                 {
1647                         _offset += _size;
1648                         _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV / 2);
1649                         _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
1650                         _bo_idx = 0;
1651                 }
1652                 break;
1653         case TBM_FORMAT_YUV444:
1654         case TBM_FORMAT_YVU444:
1655                 bpp = 24;
1656                 //if(plane_idx == 0)
1657                 {
1658                         _offset = 0;
1659                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1660                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1661                         _bo_idx = 0;
1662                         if (plane_idx == 0)
1663                                 break;
1664                 }
1665                 //else if( plane_idx == 1 )
1666                 {
1667                         _offset += _size;
1668                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1669                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1670                         _bo_idx = 0;
1671                         if (plane_idx == 1)
1672                                 break;
1673                 }
1674                 //else if (plane_idx == 2 )
1675                 {
1676                         _offset += _size;
1677                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1678                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1679                         _bo_idx = 0;
1680                 }
1681                 break;
1682         default:
1683                 bpp = 0;
1684                 break;
1685         }
1686
1687         *size = _size;
1688         *offset = _offset;
1689         *pitch = _pitch;
1690         *bo_idx = _bo_idx;
1691
1692         return ret;
1693 }
1694
1695 static int
1696 tbm_sprd_bo_get_flags(tbm_bo bo)
1697 {
1698         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1699
1700         tbm_bo_sprd bo_sprd;
1701
1702         bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
1703         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
1704
1705         return bo_sprd->flags_tbm;
1706 }
1707
1708 static int
1709 tbm_sprd_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1710 {
1711         tbm_bufmgr_sprd bufmgr_sprd;
1712
1713         bufmgr_sprd = tbm_backend_get_priv_from_bufmgr(bufmgr);
1714         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
1715
1716         if (!tbm_drm_helper_wl_auth_server_init(NativeDisplay, bufmgr_sprd->fd,
1717                                            bufmgr_sprd->device_name, 0)) {
1718                 TBM_SPRD_ERROR("fail to tbm_drm_helper_wl_server_init\n");
1719                 return 0;
1720         }
1721
1722         bufmgr_sprd->bind_display = NativeDisplay;
1723
1724         return 1;
1725 }
1726
1727 MODULEINITPPROTO(init_tbm_bufmgr_priv);
1728
1729 static TBMModuleVersionInfo SprdVersRec = {
1730         "sprd",
1731         "Samsung",
1732         TBM_ABI_VERSION,
1733 };
1734
1735 TBMModuleData tbmModuleData = { &SprdVersRec, init_tbm_bufmgr_priv};
1736
1737 int
1738 init_tbm_bufmgr_priv(tbm_bufmgr bufmgr, int fd)
1739 {
1740         tbm_bufmgr_backend bufmgr_backend;
1741         tbm_bufmgr_sprd bufmgr_sprd;
1742         int fp;
1743
1744         if (!bufmgr)
1745                 return 0;
1746
1747         bufmgr_sprd = calloc(1, sizeof(struct _tbm_bufmgr_sprd));
1748         if (!bufmgr_sprd) {
1749                 TBM_SPRD_ERROR("fail to alloc bufmgr_sprd!\n");
1750                 return 0;
1751         }
1752
1753         if (tbm_backend_is_display_server()) {
1754                 bufmgr_sprd->fd = tbm_drm_helper_get_master_fd();
1755                 if (bufmgr_sprd->fd < 0) {
1756                         bufmgr_sprd->fd = _tbm_sprd_open_drm();
1757                         if (bufmgr_sprd->fd < 0) {
1758                                 TBM_SPRD_ERROR("fail to open drm!\n");
1759                                 goto fail_open_drm;
1760                         }
1761                 }
1762
1763                 tbm_drm_helper_set_tbm_master_fd(bufmgr_sprd->fd);
1764
1765                 bufmgr_sprd->device_name = drmGetDeviceNameFromFd(bufmgr_sprd->fd);
1766                 if (!bufmgr_sprd->device_name) {
1767                         TBM_SPRD_ERROR("fail to get device name!\n");
1768                         tbm_drm_helper_unset_tbm_master_fd();
1769                         goto fail_get_device_name;
1770                 }
1771         } else {
1772                 if (!tbm_drm_helper_get_auth_info(&(bufmgr_sprd->fd), &(bufmgr_sprd->device_name), NULL)) {
1773                         TBM_SPRD_ERROR("fail to get auth drm info!\n");
1774                         goto fail_get_auth_info;
1775                 }
1776         }
1777
1778         //Create Hash Table
1779         bufmgr_sprd->hashBos = drmHashCreate();
1780
1781         //Check if the tbm manager supports dma fence or not.
1782         fp = open("/sys/module/dmabuf_sync/parameters/enabled", O_RDONLY);
1783         if (fp != -1) {
1784                 char buf[1];
1785                 int length = read(fp, buf, 1);
1786
1787                 if (length == 1 && buf[0] == '1')
1788                         bufmgr_sprd->use_dma_fence = 1;
1789
1790                 close(fp);
1791         }
1792
1793         if (!_bufmgr_init_cache_state(bufmgr_sprd)) {
1794                 TBM_SPRD_ERROR("fail to init bufmgr cache state\n");
1795                 goto fail_init_cache_state;
1796         }
1797
1798         bufmgr_backend = tbm_backend_alloc();
1799         if (!bufmgr_backend) {
1800                 TBM_SPRD_ERROR("fail to alloc backend!\n");
1801                 goto fail_alloc_backend;
1802         }
1803
1804         bufmgr_backend->priv = (void *)bufmgr_sprd;
1805         bufmgr_backend->bufmgr_deinit = tbm_sprd_bufmgr_deinit;
1806         bufmgr_backend->bo_size = tbm_sprd_bo_size;
1807         bufmgr_backend->bo_alloc = tbm_sprd_bo_alloc;
1808         bufmgr_backend->bo_free = tbm_sprd_bo_free;
1809         bufmgr_backend->bo_import = tbm_sprd_bo_import;
1810         bufmgr_backend->bo_import_fd = tbm_sprd_bo_import_fd;
1811         bufmgr_backend->bo_export = tbm_sprd_bo_export;
1812         bufmgr_backend->bo_export_fd = tbm_sprd_bo_export_fd;
1813         bufmgr_backend->bo_get_handle = tbm_sprd_bo_get_handle;
1814         bufmgr_backend->bo_map = tbm_sprd_bo_map;
1815         bufmgr_backend->bo_unmap = tbm_sprd_bo_unmap;
1816         bufmgr_backend->surface_get_plane_data = tbm_sprd_surface_get_plane_data;
1817         bufmgr_backend->surface_supported_format = tbm_sprd_surface_supported_format;
1818         bufmgr_backend->bo_get_flags = tbm_sprd_bo_get_flags;
1819         bufmgr_backend->bo_lock = NULL;
1820         bufmgr_backend->bo_unlock = NULL;
1821         bufmgr_backend->bufmgr_bind_native_display = tbm_sprd_bufmgr_bind_native_display;
1822
1823         if (!tbm_backend_init(bufmgr, bufmgr_backend)) {
1824                 TBM_SPRD_ERROR("fail to init backend!\n");
1825                 goto fail_init_backend;
1826         }
1827
1828 #ifdef DEBUG
1829         {
1830                 char *env;
1831
1832                 env = getenv("TBM_SPRD_DEBUG");
1833                 if (env) {
1834                         bDebug = atoi(env);
1835                         TBM_SPRD_ERROR("TBM_SPRD_DEBUG=%s\n", env);
1836                 } else
1837                         bDebug = 0;
1838         }
1839 #endif
1840
1841         TBM_SPRD_DEBUG("DMABUF FENCE is %s\n",
1842                 bufmgr_sprd->use_dma_fence ? "supported!" : "NOT supported!");
1843         TBM_SPRD_DEBUG("fd:%d\n", bufmgr_sprd->fd);
1844
1845         return 1;
1846
1847 fail_init_backend:
1848         tbm_backend_free(bufmgr_backend);
1849 fail_alloc_backend:
1850         _bufmgr_deinit_cache_state(bufmgr_sprd);
1851 fail_init_cache_state:
1852         if (bufmgr_sprd->hashBos)
1853                 drmHashDestroy(bufmgr_sprd->hashBos);
1854         if (tbm_backend_is_display_server())
1855                 tbm_drm_helper_unset_tbm_master_fd();
1856 fail_get_device_name:
1857         close(bufmgr_sprd->fd);
1858 fail_get_auth_info:
1859 fail_open_drm:
1860         free(bufmgr_sprd);
1861         return 0;
1862 }
1863