tbm_bufmgr_sprd: clean up _tbm_sprd_open_drm()
[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         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
457
458         /* cache flush is managed by kernel side when using dma-fence. */
459         if (bufmgr_sprd->use_dma_fence)
460                 return 1;
461
462         struct drm_sprd_gem_cache_op cache_op = {0, };
463         int ret;
464
465         /* if bo_sprd is null, do cache_flush_all */
466         if (bo_sprd) {
467                 cache_op.flags = 0;
468                 cache_op.usr_addr = (uint64_t)((uint32_t)bo_sprd->pBase);
469                 cache_op.size = bo_sprd->size;
470         } else {
471                 flags = TBM_SPRD_CACHE_FLUSH_ALL;
472                 cache_op.flags = 0;
473                 cache_op.usr_addr = 0;
474                 cache_op.size = 0;
475         }
476
477         if (flags & TBM_SPRD_CACHE_INV) {
478                 if (flags & TBM_SPRD_CACHE_ALL)
479                         cache_op.flags |= SPRD_DRM_CACHE_INV_ALL;
480                 else
481                         cache_op.flags |= SPRD_DRM_CACHE_INV_RANGE;
482         }
483
484         if (flags & TBM_SPRD_CACHE_CLN) {
485                 if (flags & TBM_SPRD_CACHE_ALL)
486                         cache_op.flags |= SPRD_DRM_CACHE_CLN_ALL;
487                 else
488                         cache_op.flags |= SPRD_DRM_CACHE_CLN_RANGE;
489         }
490
491         if (flags & TBM_SPRD_CACHE_ALL)
492                 cache_op.flags |= SPRD_DRM_ALL_CACHES_CORES;
493
494         ret = drmCommandWriteRead(bufmgr_sprd->fd, DRM_SPRD_GEM_CACHE_OP, &cache_op,
495                                    sizeof(cache_op));
496         if (ret) {
497                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
498                               "error %s:%d fail to flush the cache.\n",
499                               getpid(), __FUNCTION__, __LINE__);
500                 return 0;
501         }
502
503         return 1;
504 }
505 #endif
506
507 static int
508 _bo_init_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int import)
509 {
510         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
511         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
512
513         if (bufmgr_sprd->use_dma_fence)
514                 return 1;
515
516         _tgl_init(bufmgr_sprd->tgl_fd, bo_sprd->name);
517
518 #ifdef USE_CACHE
519         tbm_bo_cache_state cache_state;
520
521         if (import == 0) {
522                 cache_state.data.isDirtied = DEVICE_NONE;
523                 cache_state.data.isCached = 0;
524                 cache_state.data.cntFlush = 0;
525
526                 _tgl_set_data(bufmgr_sprd->tgl_fd, bo_sprd->name, cache_state.val);
527         }
528 #endif
529
530         return 1;
531 }
532
533 static int
534 _bo_set_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd, int device, int opt)
535 {
536 #ifdef USE_CACHE
537         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
538         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
539
540         char need_flush = 0;
541         unsigned short cntFlush = 0;
542
543         if (bufmgr_sprd->use_dma_fence)
544                 return 1;
545
546         if (bo_sprd->flags_sprd & SPRD_BO_NONCACHABLE)
547                 return 1;
548
549         /* get cache state of a bo */
550         bo_sprd->cache_state.val = _tgl_get_data(bufmgr_sprd->tgl_fd, bo_sprd->name, NULL);
551
552         /* get global cache flush count */
553         cntFlush = (unsigned short)_tgl_get_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, NULL);
554
555         if (opt == TBM_DEVICE_CPU) {
556                 if (bo_sprd->cache_state.data.isDirtied == DEVICE_CO &&
557                     bo_sprd->cache_state.data.isCached)
558                         need_flush = TBM_SPRD_CACHE_INV;
559
560                 bo_sprd->cache_state.data.isCached = 1;
561                 if (opt & TBM_OPTION_WRITE)
562                         bo_sprd->cache_state.data.isDirtied = DEVICE_CA;
563                 else {
564                         if (bo_sprd->cache_state.data.isDirtied != DEVICE_CA)
565                                 bo_sprd->cache_state.data.isDirtied = DEVICE_NONE;
566                 }
567         } else {
568                 if (bo_sprd->cache_state.data.isDirtied == DEVICE_CA &&
569                     bo_sprd->cache_state.data.isCached &&
570                     bo_sprd->cache_state.data.cntFlush == cntFlush)
571                         need_flush = TBM_SPRD_CACHE_CLN | TBM_SPRD_CACHE_ALL;
572
573                 if (opt & TBM_OPTION_WRITE)
574                         bo_sprd->cache_state.data.isDirtied = DEVICE_CO;
575                 else {
576                         if (bo_sprd->cache_state.data.isDirtied != DEVICE_CO)
577                                 bo_sprd->cache_state.data.isDirtied = DEVICE_NONE;
578                 }
579         }
580
581         if (need_flush) {
582                 if (need_flush & TBM_SPRD_CACHE_ALL)
583                         _tgl_set_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, (unsigned int)(++cntFlush));
584
585                 /* call cache flush */
586                 _sprd_bo_cache_flush(bufmgr_sprd, bo_sprd, need_flush);
587
588                 DBG("[libtbm:%d] \tcache(%d,%d)....flush:0x%x, cntFlush(%d)\n",
589                     getpid(),
590                     bo_sprd->cache_state.data.isCached,
591                     bo_sprd->cache_state.data.isDirtied,
592                     need_flush,
593                     cntFlush);
594         }
595 #endif
596
597         return 1;
598 }
599
600 static int
601 _bo_save_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd)
602 {
603 #ifdef USE_CACHE
604         SPRD_RETURN_VAL_IF_FAIL(bo_sprd != NULL, 0);
605         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
606
607         if (bufmgr_sprd->use_dma_fence)
608                 return 1;
609
610         unsigned short cntFlush = 0;
611
612         /* get global cache flush count */
613         cntFlush = (unsigned short)_tgl_get_data(bufmgr_sprd->tgl_fd, GLOBAL_KEY, NULL);
614
615         /* save global cache flush count */
616         bo_sprd->cache_state.data.cntFlush = cntFlush;
617         _tgl_set_data(bufmgr_sprd->tgl_fd, bo_sprd->name, bo_sprd->cache_state.val);
618 #endif
619
620         return 1;
621 }
622
623 static void
624 _bo_destroy_cache_state(tbm_bufmgr_sprd bufmgr_sprd, tbm_bo_sprd bo_sprd)
625 {
626         SPRD_RETURN_IF_FAIL(bo_sprd != NULL);
627         SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
628
629         if (bufmgr_sprd->use_dma_fence)
630                 return;
631
632         _tgl_destroy(bufmgr_sprd->tgl_fd, bo_sprd->name);
633 }
634
635 static int
636 _bufmgr_init_cache_state(tbm_bufmgr_sprd bufmgr_sprd)
637 {
638         SPRD_RETURN_VAL_IF_FAIL(bufmgr_sprd != NULL, 0);
639
640         if (bufmgr_sprd->use_dma_fence)
641                 return 1;
642
643         /* open tgl fd for saving cache flush data */
644         bufmgr_sprd->tgl_fd = open(tgl_devfile, O_RDWR);
645
646         if (bufmgr_sprd->tgl_fd < 0) {
647                 bufmgr_sprd->tgl_fd = open(tgl_devfile1, O_RDWR);
648                 if (bufmgr_sprd->tgl_fd < 0) {
649                         TBM_SPRD_LOG("[libtbm-sprd:%d] "
650                                        "error: Fail to open global_lock:%s\n",
651                                        getpid(), tgl_devfile);
652                         return 0;
653                 }
654         }
655
656 #ifdef USE_CACHE
657         if (!_tgl_init(bufmgr_sprd->tgl_fd, GLOBAL_KEY)) {
658                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
659                                "error: Fail to initialize the tgl\n",
660                                getpid());
661
662                 close(bufmgr_sprd->tgl_fd);
663                 return 0;
664         }
665 #endif
666
667         return 1;
668 }
669
670 static void
671 _bufmgr_deinit_cache_state(tbm_bufmgr_sprd bufmgr_sprd)
672 {
673         SPRD_RETURN_IF_FAIL(bufmgr_sprd != NULL);
674
675         if (bufmgr_sprd->use_dma_fence)
676                 return;
677
678         if (bufmgr_sprd->tgl_fd >= 0)
679                 close(bufmgr_sprd->tgl_fd);
680 }
681
682 #ifndef USE_CONTIG_ONLY
683 static unsigned int
684 _get_sprd_flag_from_tbm(unsigned int ftbm)
685 {
686         unsigned int flags = 0;
687
688         /*
689          * TBM_BO_DEFAULT  => ION_HEAP_ID_MASK_SYSTEM
690          * TBM_BO_SCANOUT => ION_HEAP_ID_MASK_MM
691          * TBM_BO_VENDOR => ION_HEAP_ID_MASK_OVERLAY
692          * To be updated appropriately once DRM-GEM supports different heap id masks.
693          * */
694
695         if (ftbm & TBM_BO_SCANOUT)
696                 flags = SPRD_BO_CONTIG;
697         else
698                 flags = SPRD_BO_NONCONTIG | SPRD_BO_DEV_SYSTEM;
699
700         if (ftbm & TBM_BO_WC)
701                 flags |= SPRD_BO_WC;
702         else if (ftbm & TBM_BO_NONCACHABLE)
703                 flags |= SPRD_BO_NONCACHABLE;
704
705         return flags;
706 }
707
708 static unsigned int
709 _get_tbm_flag_from_sprd(unsigned int fsprd)
710 {
711         unsigned int flags = 0;
712
713         if (fsprd & SPRD_BO_NONCONTIG)
714                 flags |= TBM_BO_DEFAULT;
715         else
716                 flags |= TBM_BO_SCANOUT;
717
718         if (fsprd & SPRD_BO_WC)
719                 flags |= TBM_BO_WC;
720         else if (fsprd & SPRD_BO_CACHABLE)
721                 flags |= TBM_BO_DEFAULT;
722         else
723                 flags |= TBM_BO_NONCACHABLE;
724
725         return flags;
726 }
727 #endif
728
729 static unsigned int
730 _get_name(int fd, unsigned int gem)
731 {
732         struct drm_gem_flink arg = {0,};
733
734         arg.handle = gem;
735         if (drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &arg)) {
736                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
737                               "error %s:%d fail to get flink gem=%d\n",
738                               getpid(), __FUNCTION__, __LINE__, gem);
739                 return 0;
740         }
741
742         return (unsigned int)arg.name;
743 }
744
745 static tbm_bo_handle
746 _sprd_bo_handle(tbm_bo_sprd bo_sprd, int device)
747 {
748         tbm_bo_handle bo_handle;
749         memset(&bo_handle, 0x0, sizeof(uint64_t));
750
751         switch (device) {
752         case TBM_DEVICE_DEFAULT:
753         case TBM_DEVICE_2D:
754                 bo_handle.u32 = (uint32_t)bo_sprd->gem;
755                 break;
756         case TBM_DEVICE_CPU:
757                 if (!bo_sprd->pBase) {
758                         struct drm_sprd_gem_mmap arg = {0,};
759
760                         arg.handle = bo_sprd->gem;
761                         arg.size = bo_sprd->size;
762                         if (drmCommandWriteRead(bo_sprd->fd, DRM_SPRD_GEM_MMAP, &arg, sizeof(arg))) {
763                                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
764                                               "error %s:%d Cannot usrptr gem=%d\n",
765                                               getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
766                                 return (tbm_bo_handle) NULL;
767                         }
768                         bo_sprd->pBase = (void *)((uint32_t)arg.mapped);
769                 }
770
771                 bo_handle.ptr = (void *)bo_sprd->pBase;
772                 break;
773         case TBM_DEVICE_3D:
774 #ifdef USE_DMAIMPORT
775                 if (!bo_sprd->dmabuf) {
776                         struct drm_prime_handle arg = {0, };
777                         arg.handle = bo_sprd->gem;
778                         if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
779                                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
780                                               "error %s:%d Cannot dmabuf=%d\n",
781                                               getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
782                                 return (tbm_bo_handle) NULL;
783                         }
784                         bo_sprd->dmabuf = arg.fd;
785                 }
786
787                 bo_handle.u32 = (uint32_t)bo_sprd->dmabuf;
788
789 #endif
790                 break;
791
792         case TBM_DEVICE_MM:
793 #ifdef USE_HEAP_ID
794                 //TODO : Add ioctl for GSP MAP once available.
795                 DBG("[libtbm-sprd:%d] %s In case TBM_DEVICE_MM:  \n", getpid(),
796                      __FUNCTION_);
797                 _
798
799 #else
800                 if (!bo_sprd->dmabuf) {
801                         struct drm_prime_handle arg = {0, };
802
803                         arg.handle = bo_sprd->gem;
804                         if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
805                                 TBM_SPRD_LOG("[libtbm-sprd:%d] "
806                                               "error %s:%d Cannot dmabuf=%d\n",
807                                               getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
808                                 return (tbm_bo_handle) NULL;
809                         }
810                         bo_sprd->dmabuf = arg.fd;
811                 }
812
813                 bo_handle.u32 = (uint32_t)bo_sprd->dmabuf;
814 #endif
815                 break;
816         default:
817                 bo_handle.ptr = (void *) NULL;
818                 break;
819         }
820
821         return bo_handle;
822 }
823
824 static int
825 tbm_sprd_bo_size(tbm_bo bo)
826 {
827         SPRD_RETURN_VAL_IF_FAIL(bo != NULL, 0);
828
829         tbm_bo_sprd bo_sprd;
830
831         bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
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