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