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