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