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