874deb0cc051beafe2c48b0ba33633866cd60e7c
[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 <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_OPERATION_FAILED;
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 / 2);
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 / 2);
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, int size, tbm_bo_memory_type flags, tbm_error_e *error)
1111 {
1112         tbm_bufmgr_sprd bufmgr_sprd = (tbm_bufmgr_sprd)bufmgr_data;
1113         tbm_bo_sprd bo_sprd;
1114         unsigned int sprd_flags;
1115
1116         if (bufmgr_sprd == NULL) {
1117                 TBM_ERR("bufmgr_data is null\n");
1118                 if (error)
1119                         *error = TBM_ERROR_INVALID_PARAMETER;
1120                 return NULL;
1121         }
1122
1123         bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
1124         if (!bo_sprd) {
1125                 TBM_ERR("error fail to allocate the bo_sprd\n");
1126                 if (error)
1127                         *error = TBM_ERROR_OUT_OF_MEMORY;
1128                 return NULL;
1129         }
1130         bo_sprd->bufmgr_sprd = bufmgr_sprd;
1131
1132 #ifdef USE_CONTIG_ONLY
1133         flags = TBM_BO_SCANOUT;
1134         sprd_flags = SPRD_BO_CONTIG;
1135 #else
1136         sprd_flags = _get_sprd_flag_from_tbm(flags);
1137         if ((flags & TBM_BO_SCANOUT) && (size <= 4 * 1024))
1138                 sprd_flags |= SPRD_BO_NONCONTIG;
1139 #endif // USE_CONTIG_ONLY
1140
1141         struct drm_sprd_gem_create arg = {0, };
1142
1143         arg.size = (uint64_t)size;
1144         arg.flags = sprd_flags;
1145         if (drmCommandWriteRead(bufmgr_sprd->fd, DRM_SPRD_GEM_CREATE, &arg,
1146                                 sizeof(arg))) {
1147                 TBM_ERR("error Cannot create bo_sprd(flag:%x, size:%d)\n",
1148                         arg.flags, (unsigned int)arg.size);
1149                 free(bo_sprd);
1150                 if (error)
1151                         *error = TBM_ERROR_OPERATION_FAILED;
1152                 return NULL;
1153         }
1154
1155         bo_sprd->fd = bufmgr_sprd->fd;
1156         bo_sprd->gem = arg.handle;
1157         bo_sprd->size = size;
1158         bo_sprd->flags_tbm = flags;
1159         bo_sprd->flags_sprd = sprd_flags;
1160         bo_sprd->name = _get_name(bo_sprd->fd, bo_sprd->gem);
1161
1162         if (!_bo_init_cache_state(bufmgr_sprd, bo_sprd, 0)) {
1163                 TBM_ERR("error fail init cache state(%d)\n", bo_sprd->name);
1164                 free(bo_sprd);
1165                 if (error)
1166                         *error = TBM_ERROR_OPERATION_FAILED;
1167                 return NULL;
1168         }
1169
1170         pthread_mutex_init(&bo_sprd->mutex, NULL);
1171
1172         if (bufmgr_sprd->use_dma_fence && !bo_sprd->dmabuf) {
1173                 struct drm_prime_handle arg = {0, };
1174
1175                 arg.handle = bo_sprd->gem;
1176                 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
1177                         TBM_ERR("error Cannot dmabuf=%d\n", bo_sprd->gem);
1178                         free(bo_sprd);
1179                         if (error)
1180                                 *error = TBM_ERROR_OPERATION_FAILED;
1181                         return NULL;
1182                 }
1183                 bo_sprd->dmabuf = arg.fd;
1184         }
1185
1186         /* add bo_sprd to hash */
1187         if (drmHashInsert(bufmgr_sprd->hashBos, bo_sprd->name, (void *)bo_sprd) < 0)
1188                 TBM_ERR("Cannot insert bo_sprd to Hash(%d)\n", bo_sprd->name);
1189
1190         TBM_DBG("%s size:%d, gem:%d(%d), flags:%d(%d)\n",
1191                 __FUNCTION__, bo_sprd->size,
1192                 bo_sprd->gem, bo_sprd->name,
1193                 flags, sprd_flags);
1194
1195         if (error)
1196                 *error = TBM_ERROR_NONE;
1197
1198         return (tbm_backend_bo_data *)bo_sprd;
1199 }
1200
1201 static tbm_backend_bo_data *
1202 tbm_sprd_bufmgr_import_fd(tbm_backend_bufmgr_data *bufmgr_data, tbm_fd key, tbm_error_e *error)
1203 {
1204         tbm_bufmgr_sprd bufmgr_sprd = (tbm_bufmgr_sprd)bufmgr_data;
1205         tbm_bo_sprd bo_sprd;
1206         unsigned int gem;
1207         unsigned int name;
1208         int ret;
1209         char buf[STRERR_BUFSIZE];
1210
1211         if (bufmgr_sprd == NULL) {
1212                 TBM_ERR("bufmgr_data is null\n");
1213                 if (error)
1214                         *error = TBM_ERROR_INVALID_PARAMETER;
1215                 return NULL;
1216         }
1217
1218         /*getting handle from fd*/
1219         struct drm_prime_handle arg = {0, };
1220
1221         arg.fd = key;
1222         if (drmIoctl(bufmgr_sprd->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg)) {
1223                 TBM_ERR("Cannot get gem handle from fd:%d (%s)\n",
1224                                arg.fd, strerror_r(errno, buf, STRERR_BUFSIZE));
1225                 if (error)
1226                         *error = TBM_ERROR_OPERATION_FAILED;
1227                 return NULL;
1228         }
1229         gem = arg.handle;
1230
1231         name = _get_name(bufmgr_sprd->fd, gem);
1232         if (!name) {
1233                 TBM_ERR("Cannot get name from gem:%d, fd:%d (%s)\n",
1234                                gem, key, strerror_r(errno, buf, STRERR_BUFSIZE));
1235                 if (error)
1236                         *error = TBM_ERROR_OPERATION_FAILED;
1237                 return NULL;
1238         }
1239
1240         ret = drmHashLookup(bufmgr_sprd->hashBos, name, (void **)&bo_sprd);
1241         if (ret == 0) {
1242                 if (gem == bo_sprd->gem) {
1243                         if (error)
1244                                 *error = TBM_ERROR_NONE;
1245                         return bo_sprd;
1246                 }
1247         }
1248
1249         /* Determine size of bo_sprd.  The fd-to-handle ioctl really should
1250          * return the size, but it doesn't.  If we have kernel 3.12 or
1251          * later, we can lseek on the prime fd to get the size.  Older
1252          * kernels will just fail, in which case we fall back to the
1253          * provided (estimated or guess size).
1254          * */
1255
1256         unsigned int real_size;
1257         struct drm_sprd_gem_info info = {0, };
1258
1259         real_size = lseek(key, 0, SEEK_END);
1260
1261         info.handle = gem;
1262         if (drmCommandWriteRead(bufmgr_sprd->fd,
1263                                 DRM_SPRD_GEM_GET,
1264                                 &info,
1265                                 sizeof(struct drm_sprd_gem_info))) {
1266                 TBM_ERR("Cannot get gem info from gem:%d, fd:%d (%s)\n",
1267                                gem, key, strerror_r(errno, buf, STRERR_BUFSIZE));
1268                 if (error)
1269                         *error = TBM_ERROR_OPERATION_FAILED;
1270                 return NULL;
1271         }
1272
1273         if (real_size == -1)
1274                 real_size = info.size;
1275
1276         bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
1277         if (!bo_sprd) {
1278                 TBM_ERR("error bo_sprd:%p fail to allocate the bo_sprd\n", bo_sprd);
1279                 if (error)
1280                         *error = TBM_ERROR_OUT_OF_MEMORY;
1281                 return NULL;
1282         }
1283         bo_sprd->bufmgr_sprd = bufmgr_sprd;
1284
1285         bo_sprd->fd = bufmgr_sprd->fd;
1286         bo_sprd->gem = gem;
1287         bo_sprd->size = real_size;
1288         bo_sprd->flags_sprd = info.flags;
1289         bo_sprd->flags_tbm = _get_tbm_flag_from_sprd(bo_sprd->flags_sprd);
1290         bo_sprd->name = name;
1291
1292         if (!_bo_init_cache_state(bufmgr_sprd, bo_sprd, 1)) {
1293                 TBM_ERR("error fail init cache state(%d)\n", bo_sprd->name);
1294                 if (error)
1295                         *error = TBM_ERROR_OPERATION_FAILED;
1296                 goto fail_init_cache;
1297         }
1298
1299         /* add bo_sprd to hash */
1300         if (drmHashInsert(bufmgr_sprd->hashBos, bo_sprd->name, (void *)bo_sprd) < 0)
1301                 TBM_ERR("bo_sprd:%p Cannot insert bo_sprd to Hash(%d) from gem:%d, fd:%d\n",
1302                                bo_sprd, bo_sprd->name, gem, key);
1303
1304         TBM_DBG("bo_sprd:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n",
1305              bo_sprd,
1306              bo_sprd->gem, bo_sprd->name,
1307              bo_sprd->dmabuf,
1308              key,
1309              bo_sprd->flags_tbm, bo_sprd->flags_sprd,
1310              bo_sprd->size);
1311
1312         if (error)
1313                 *error = TBM_ERROR_NONE;
1314
1315         return (tbm_backend_bo_data *)bo_sprd;
1316
1317 fail_init_cache:
1318         free(bo_sprd);
1319         return NULL;
1320 }
1321
1322 static tbm_backend_bo_data *
1323 tbm_sprd_bufmgr_import_key(tbm_backend_bufmgr_data *bufmgr_data, tbm_key key, tbm_error_e *error)
1324 {
1325         tbm_bufmgr_sprd bufmgr_sprd = (tbm_bufmgr_sprd)bufmgr_data;
1326         tbm_bo_sprd bo_sprd;
1327         int ret;
1328
1329         if (bufmgr_sprd == NULL) {
1330                 TBM_ERR("bufmgr_data is null\n");
1331                 if (error)
1332                         *error = TBM_ERROR_INVALID_PARAMETER;
1333                 return NULL;
1334         }
1335
1336         ret = drmHashLookup(bufmgr_sprd->hashBos, key, (void **)&bo_sprd);
1337         if (ret == 0) {
1338                 if (error)
1339                         *error = TBM_ERROR_NONE;
1340                 return (tbm_backend_bo_data *)bo_sprd;
1341         }
1342
1343         struct drm_gem_open arg = {0, };
1344         struct drm_sprd_gem_info info = {0, };
1345
1346         arg.name = key;
1347         if (drmIoctl(bufmgr_sprd->fd, DRM_IOCTL_GEM_OPEN, &arg)) {
1348                 TBM_ERR("error Cannot open gem name=%d\n", key);
1349                 if (error)
1350                         *error = TBM_ERROR_OPERATION_FAILED;
1351                 return NULL;
1352         }
1353
1354         info.handle = arg.handle;
1355         if (drmCommandWriteRead(bufmgr_sprd->fd,
1356                                 DRM_SPRD_GEM_GET,
1357                                 &info,
1358                                 sizeof(struct drm_sprd_gem_info))) {
1359                 TBM_ERR("error Cannot get gem info=%d\n", key);
1360                 if (error)
1361                         *error = TBM_ERROR_OPERATION_FAILED;
1362                 goto fail_get_gem;
1363         }
1364
1365         bo_sprd = calloc(1, sizeof(struct _tbm_bo_sprd));
1366         if (!bo_sprd) {
1367                 TBM_ERR("error fail to allocate the bo_sprd\n");
1368                 if (error)
1369                         *error = TBM_ERROR_OUT_OF_MEMORY;
1370                 goto fail_alloc_bo;
1371         }
1372         bo_sprd->bufmgr_sprd = bufmgr_sprd;
1373
1374         bo_sprd->fd = bufmgr_sprd->fd;
1375         bo_sprd->gem = arg.handle;
1376         bo_sprd->size = arg.size;
1377         bo_sprd->flags_sprd = info.flags;
1378         bo_sprd->name = key;
1379 #ifdef USE_CONTIG_ONLY
1380         bo_sprd->flags_sprd = SPRD_BO_CONTIG;
1381         bo_sprd->flags_tbm |= TBM_BO_SCANOUT;
1382 #else
1383         bo_sprd->flags_tbm = _get_tbm_flag_from_sprd(bo_sprd->flags_sprd);
1384 #endif
1385
1386         if (!_bo_init_cache_state(bufmgr_sprd, bo_sprd, 1)) {
1387                 TBM_ERR("error fail init cache state(%d)\n", bo_sprd->name);
1388                 if (error)
1389                         *error = TBM_ERROR_OPERATION_FAILED;
1390                 goto fail_init_cache;
1391         }
1392
1393         if (!bo_sprd->dmabuf) {
1394                 struct drm_prime_handle arg = {0, };
1395
1396                 arg.handle = bo_sprd->gem;
1397                 if (drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
1398                         TBM_ERR("error Cannot dmabuf=%d\n", bo_sprd->gem);
1399                         if (error)
1400                                 *error = TBM_ERROR_OPERATION_FAILED;
1401                         goto fail_prime_handle_to_fd;
1402                 }
1403                 bo_sprd->dmabuf = arg.fd;
1404         }
1405
1406         /* add bo_sprd to hash */
1407         if (drmHashInsert(bufmgr_sprd->hashBos, bo_sprd->name, (void *)bo_sprd) < 0)
1408                 TBM_ERR("Cannot insert bo_sprd to Hash(%d)\n", bo_sprd->name);
1409
1410         TBM_DBG("    bo_sprd:%p, gem:%d(%d), fd:%d, flags:%d(%d), size:%d\n",
1411             bo_sprd,
1412             bo_sprd->gem, bo_sprd->name,
1413             bo_sprd->dmabuf,
1414             bo_sprd->flags_tbm, bo_sprd->flags_sprd,
1415             bo_sprd->size);
1416
1417         if (error)
1418                 *error = TBM_ERROR_NONE;
1419
1420         return (tbm_backend_bo_data *)bo_sprd;
1421
1422 fail_prime_handle_to_fd:
1423         _bo_destroy_cache_state(bufmgr_sprd, bo_sprd);
1424 fail_init_cache:
1425         free(bo_sprd);
1426 fail_alloc_bo:
1427 fail_get_gem:
1428         {
1429                 struct drm_gem_close gem_close_arg = {arg.handle, 0};
1430                 drmIoctl(bufmgr_sprd->fd, DRM_IOCTL_GEM_CLOSE, &gem_close_arg);
1431         }
1432         return NULL;
1433 }
1434
1435 static void
1436 tbm_sprd_bo_free(tbm_backend_bo_data *bo_data)
1437 {
1438         tbm_bo_sprd bo_sprd = (tbm_bo_sprd)bo_data;
1439         tbm_bo_sprd temp;
1440         tbm_bufmgr_sprd bufmgr_sprd;
1441         char buf[STRERR_BUFSIZE];
1442         int ret;
1443
1444         if (!bo_data)
1445                 return;
1446
1447         bufmgr_sprd = bo_sprd->bufmgr_sprd;
1448         if (!bufmgr_sprd)
1449                 return;
1450
1451         TBM_DBG("      bo_sprd:%p, gem:%d(%d), fd:%d, size:%d\n",
1452             bo_sprd,
1453             bo_sprd->gem, bo_sprd->name,
1454             bo_sprd->dmabuf,
1455             bo_sprd->size);
1456
1457         if (bo_sprd->pBase) {
1458                 if (munmap(bo_sprd->pBase, bo_sprd->size) == -1) {
1459                         TBM_ERR("bo_sprd:%p fail to munmap(%s)\n",
1460                                        bo_sprd, strerror_r(errno, buf, STRERR_BUFSIZE));
1461                 }
1462         }
1463
1464         /* close dmabuf */
1465         if (bo_sprd->dmabuf) {
1466                 close(bo_sprd->dmabuf);
1467                 bo_sprd->dmabuf = 0;
1468         }
1469
1470         /* delete bo from hash */
1471         ret = drmHashLookup(bufmgr_sprd->hashBos, bo_sprd->name,
1472                              (void **)&temp);
1473         if (ret == 0)
1474                 drmHashDelete(bufmgr_sprd->hashBos, bo_sprd->name);
1475         else
1476                 TBM_ERR("Cannot find bo_sprd to Hash(%d), ret=%d\n", bo_sprd->name, ret);
1477
1478         if (temp != bo_sprd)
1479                 TBM_ERR("hashBos probably has several BOs with same name!!!\n");
1480
1481         _bo_destroy_cache_state(bufmgr_sprd, bo_sprd);
1482
1483         /* Free gem handle */
1484         struct drm_gem_close arg = {0, };
1485
1486         memset(&arg, 0, sizeof(arg));
1487         arg.handle = bo_sprd->gem;
1488         if (drmIoctl(bo_sprd->fd, DRM_IOCTL_GEM_CLOSE, &arg))
1489                 TBM_ERR("bo_sprd:%p fail to gem close.(%s)\n",
1490                                bo_sprd, strerror_r(errno, buf, STRERR_BUFSIZE));
1491         free(bo_sprd);
1492 }
1493
1494 static int
1495 tbm_sprd_bo_get_size(tbm_backend_bo_data *bo_data, tbm_error_e *error)
1496 {
1497         tbm_bo_sprd bo_sprd = (tbm_bo_sprd)bo_data;
1498
1499         if (!bo_sprd) {
1500                 if (error)
1501                         *error = TBM_ERROR_INVALID_PARAMETER;
1502                 return 0;
1503         }
1504
1505         if (error)
1506                 *error = TBM_ERROR_NONE;
1507
1508         return bo_sprd->size;
1509 }
1510
1511 static tbm_bo_memory_type
1512 tbm_sprd_bo_get_memory_type(tbm_backend_bo_data *bo_data, tbm_error_e *error)
1513 {
1514         tbm_bo_sprd bo_sprd = (tbm_bo_sprd)bo_data;
1515
1516         if (!bo_sprd) {
1517                 if (error)
1518                         *error = TBM_ERROR_INVALID_PARAMETER;
1519                 return TBM_BO_DEFAULT;
1520         }
1521
1522         if (error)
1523                 *error = TBM_ERROR_NONE;
1524
1525         return bo_sprd->flags_tbm;
1526 }
1527
1528 static tbm_bo_handle
1529 tbm_sprd_bo_get_handle(tbm_backend_bo_data *bo_data, tbm_bo_device_type device, tbm_error_e *error)
1530 {
1531         tbm_bo_sprd bo_sprd = (tbm_bo_sprd)bo_data;
1532         tbm_bo_handle bo_handle;
1533
1534         if (!bo_sprd) {
1535                 if (error)
1536                         *error = TBM_ERROR_INVALID_PARAMETER;
1537                 return (tbm_bo_handle) NULL;
1538         }
1539
1540         if (!bo_sprd->gem) {
1541                 TBM_ERR("Cannot map gem=%d\n", bo_sprd->gem);
1542                 if (error)
1543                         *error = TBM_ERROR_INVALID_PARAMETER;
1544                 return (tbm_bo_handle) NULL;
1545         }
1546
1547         TBM_DBG("bo_sprd:%p, gem:%d(%d), fd:%d, flags:%d(%d), size:%d, %s\n",
1548             bo_sprd,
1549             bo_sprd->gem, bo_sprd->name,
1550             bo_sprd->dmabuf,
1551             bo_sprd->flags_tbm, bo_sprd->flags_sprd,
1552             bo_sprd->size,
1553             STR_DEVICE[device]);
1554
1555         /*Get mapped bo_handle*/
1556         bo_handle = _sprd_bo_handle(bo_sprd, device);
1557         if (bo_handle.ptr == NULL) {
1558                 TBM_ERR("Cannot get handle: gem:%d, device:%d\n",
1559                         bo_sprd->gem, device);
1560                 if (error)
1561                         *error = TBM_ERROR_OPERATION_FAILED;
1562                 return (tbm_bo_handle) NULL;
1563         }
1564
1565         if (error)
1566                 *error = TBM_ERROR_NONE;
1567
1568         return bo_handle;
1569 }
1570
1571 static tbm_bo_handle
1572 tbm_sprd_bo_map(tbm_backend_bo_data *bo_data, tbm_bo_device_type device,
1573                                 tbm_bo_access_option opt, tbm_error_e *error)
1574 {
1575         tbm_bo_sprd bo_sprd = (tbm_bo_sprd)bo_data;
1576         tbm_bo_handle bo_handle;
1577         tbm_bufmgr_sprd bufmgr_sprd;
1578
1579         if (!bo_sprd) {
1580                 if (error)
1581                         *error = TBM_ERROR_INVALID_PARAMETER;
1582                 return (tbm_bo_handle) NULL;
1583         }
1584
1585         bufmgr_sprd = bo_sprd->bufmgr_sprd;
1586         if (!bufmgr_sprd) {
1587                 if (error)
1588                         *error = TBM_ERROR_INVALID_PARAMETER;
1589                 return (tbm_bo_handle) NULL;
1590         }
1591
1592         if (!bo_sprd->gem) {
1593                 TBM_ERR("Cannot map gem=%d\n", bo_sprd->gem);
1594                 if (error)
1595                         *error = TBM_ERROR_INVALID_PARAMETER;
1596                 return (tbm_bo_handle) NULL;
1597         }
1598
1599         TBM_DBG("       bo_sprd:%p, gem:%d(%d), fd:%d, %s, %s\n",
1600             bo_sprd,
1601             bo_sprd->gem, bo_sprd->name,
1602             bo_sprd->dmabuf,
1603             STR_DEVICE[device],
1604             STR_OPT[opt]);
1605
1606         /*Get mapped bo_handle*/
1607         bo_handle = _sprd_bo_handle(bo_sprd, device);
1608         if (bo_handle.ptr == NULL) {
1609                 TBM_ERR("Cannot get handle: gem:%d, device:%d, opt:%d\n",
1610                         bo_sprd->gem, device, opt);
1611                 if (error)
1612                         *error = TBM_ERROR_OPERATION_FAILED;
1613                 return (tbm_bo_handle) NULL;
1614         }
1615
1616         if (bo_sprd->map_cnt == 0)
1617                 _bo_set_cache_state(bufmgr_sprd, bo_sprd, device, opt);
1618
1619         bo_sprd->map_cnt++;
1620
1621         if (error)
1622                 *error = TBM_ERROR_NONE;
1623
1624         return bo_handle;
1625 }
1626
1627 static tbm_error_e
1628 tbm_sprd_bo_unmap(tbm_backend_bo_data *bo_data)
1629 {
1630         tbm_bo_sprd bo_sprd = (tbm_bo_sprd)bo_data;
1631         tbm_bufmgr_sprd bufmgr_sprd;
1632
1633         if (!bo_sprd)
1634                 return TBM_ERROR_INVALID_PARAMETER;
1635
1636         bufmgr_sprd = bo_sprd->bufmgr_sprd;
1637         if (!bufmgr_sprd)
1638                 return TBM_ERROR_INVALID_PARAMETER;
1639
1640         if (!bo_sprd->gem)
1641                 return TBM_ERROR_INVALID_PARAMETER;
1642
1643         bo_sprd->map_cnt--;
1644
1645         if (bo_sprd->map_cnt == 0)
1646                 _bo_save_cache_state(bufmgr_sprd, bo_sprd);
1647
1648         TBM_DBG("     bo_sprd:%p, gem:%d(%d), fd:%d\n",
1649             bo_sprd,
1650             bo_sprd->gem, bo_sprd->name,
1651             bo_sprd->dmabuf);
1652
1653         return TBM_ERROR_NONE;
1654 }
1655
1656 static tbm_fd
1657 tbm_sprd_bo_export_fd(tbm_backend_bo_data *bo_data, tbm_error_e *error)
1658 {
1659         tbm_bo_sprd bo_sprd = (tbm_bo_sprd)bo_data;
1660         struct drm_prime_handle arg = {0, };
1661         int ret;
1662         char buf[STRERR_BUFSIZE];
1663
1664         if (!bo_sprd) {
1665                 if (error)
1666                         *error = TBM_ERROR_INVALID_PARAMETER;
1667                 return -1;
1668         }
1669
1670         arg.handle = bo_sprd->gem;
1671         ret = drmIoctl(bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg);
1672         if (ret) {
1673                 TBM_ERR("bo_sprd:%p Cannot dmabuf=%d (%s)\n",
1674                                bo_sprd, bo_sprd->gem, strerror_r(errno, buf, STRERR_BUFSIZE));
1675                 if (error)
1676                         *error = TBM_ERROR_OPERATION_FAILED;
1677                 return (tbm_fd) ret;
1678         }
1679
1680         TBM_DBG("bo_sprd:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n",
1681                 bo_sprd,
1682                 bo_sprd->gem, bo_sprd->name,
1683                 bo_sprd->dmabuf,
1684                 arg.fd,
1685                 bo_sprd->flags_tbm, bo_sprd->flags_sprd,
1686                 bo_sprd->size);
1687
1688         if (error)
1689                 *error = TBM_ERROR_NONE;
1690
1691         return (tbm_fd)arg.fd;
1692 }
1693
1694 static tbm_key
1695 tbm_sprd_bo_export_key(tbm_backend_bo_data *bo_data, tbm_error_e *error)
1696 {
1697         tbm_bo_sprd bo_sprd = (tbm_bo_sprd)bo_data;
1698
1699         if (!bo_sprd) {
1700                 if (error)
1701                         *error = TBM_ERROR_INVALID_PARAMETER;
1702                 return 0;
1703         }
1704
1705         if (!bo_sprd->name) {
1706                 bo_sprd->name = _get_name(bo_sprd->fd, bo_sprd->gem);
1707                 if (!bo_sprd->name) {
1708                         TBM_ERR("error Cannot get name\n");
1709                         if (error)
1710                                 *error = TBM_ERROR_INVALID_PARAMETER;
1711                         return 0;
1712                 }
1713         }
1714
1715         TBM_DBG("    bo_sprd:%p, gem:%d(%d), fd:%d, flags:%d(%d), size:%d\n",
1716             bo_sprd,
1717             bo_sprd->gem, bo_sprd->name,
1718             bo_sprd->dmabuf,
1719             bo_sprd->flags_tbm, bo_sprd->flags_sprd,
1720             bo_sprd->size);
1721
1722         if (error)
1723                 *error = TBM_ERROR_NONE;
1724
1725         return (tbm_key)bo_sprd->name;
1726 }
1727
1728 static void
1729 tbm_sprd_deinit(tbm_backend_bufmgr_data *bufmgr_data)
1730 {
1731         tbm_bufmgr_sprd bufmgr_sprd = (tbm_bufmgr_sprd)bufmgr_data;
1732         tbm_bufmgr bufmgr;
1733         tbm_error_e error;
1734         unsigned long key;
1735         void *value;
1736
1737         TBM_RETURN_IF_FAIL(bufmgr_sprd != NULL);
1738
1739         bufmgr = bufmgr_sprd->bufmgr;
1740
1741         tbm_backend_bufmgr_free_bufmgr_func(bufmgr, bufmgr_sprd->bufmgr_func);
1742         tbm_backend_bufmgr_free_bo_func(bufmgr, bufmgr_sprd->bo_func);
1743
1744         if (bufmgr_sprd->hashBos) {
1745                 while (drmHashFirst(bufmgr_sprd->hashBos, &key, &value) > 0) {
1746                         free(value);
1747                         drmHashDelete(bufmgr_sprd->hashBos, key);
1748                 }
1749
1750                 drmHashDestroy(bufmgr_sprd->hashBos);
1751                 bufmgr_sprd->hashBos = NULL;
1752         }
1753
1754         if (bufmgr_sprd->bind_display)
1755                 tbm_drm_helper_wl_auth_server_deinit();
1756
1757         if (tbm_backend_bufmgr_query_display_server(bufmgr, &error))
1758                 tbm_drm_helper_unset_tbm_master_fd();
1759
1760         tbm_drm_helper_unset_fd();
1761
1762         if (bufmgr_sprd->device_name)
1763                 free(bufmgr_sprd->device_name);
1764
1765         _bufmgr_deinit_cache_state(bufmgr_sprd);
1766
1767         close(bufmgr_sprd->fd);
1768
1769         free(bufmgr_sprd);
1770 }
1771
1772 static tbm_backend_bufmgr_data *
1773 tbm_sprd_init(tbm_bufmgr bufmgr, tbm_error_e *error)
1774 {
1775         tbm_bufmgr_sprd bufmgr_sprd = NULL;
1776         tbm_backend_bufmgr_func *bufmgr_func = NULL;
1777         tbm_backend_bo_func *bo_func = NULL;
1778         int fp;
1779         tbm_error_e err;
1780
1781         if (!bufmgr) {
1782                 TBM_ERR("bufmgr is null.\n");
1783                 if (error)
1784                         *error = TBM_ERROR_INVALID_PARAMETER;
1785                 return NULL;
1786         }
1787
1788         bufmgr_sprd = calloc(1, sizeof(struct _tbm_bufmgr_sprd));
1789         if (!bufmgr_sprd) {
1790                 TBM_ERR("fail to alloc bufmgr_sprd!\n");
1791                 if (error)
1792                         *error = TBM_ERROR_OUT_OF_MEMORY;
1793                 return NULL;
1794         }
1795
1796         if (tbm_backend_bufmgr_query_display_server(bufmgr, &err)) {
1797                 bufmgr_sprd->fd = tbm_drm_helper_get_master_fd();
1798                 if (bufmgr_sprd->fd < 0) {
1799                         bufmgr_sprd->fd = _tbm_sprd_open_drm();
1800                         if (bufmgr_sprd->fd < 0) {
1801                                 TBM_ERR("fail to open drm!\n");
1802                                 if (error)
1803                                         *error = TBM_ERROR_OPERATION_FAILED;
1804                                 goto fail_open_drm;
1805                         }
1806                 }
1807
1808                 tbm_drm_helper_set_tbm_master_fd(bufmgr_sprd->fd);
1809
1810                 bufmgr_sprd->device_name = drmGetDeviceNameFromFd(bufmgr_sprd->fd);
1811                 if (!bufmgr_sprd->device_name) {
1812                         TBM_ERR("fail to get device name!\n");
1813                         tbm_drm_helper_unset_tbm_master_fd();
1814                         if (error)
1815                                 *error = TBM_ERROR_OPERATION_FAILED;
1816                         goto fail_get_device_name;
1817                 }
1818         } else {
1819                 if (!tbm_drm_helper_get_auth_info(&(bufmgr_sprd->fd), &(bufmgr_sprd->device_name), NULL)) {
1820                         TBM_ERR("fail to get auth drm info!\n");
1821                         if (error)
1822                                 *error = TBM_ERROR_OPERATION_FAILED;
1823                         goto fail_get_auth_info;
1824                 }
1825
1826         }
1827         tbm_drm_helper_set_fd(bufmgr_sprd->fd);
1828
1829         //Check if the tbm manager supports dma fence or not.
1830         fp = open("/sys/module/dmabuf_sync/parameters/enabled", O_RDONLY);
1831         if (fp != -1) {
1832                 char buf[1];
1833                 int length = read(fp, buf, 1);
1834
1835                 if (length == 1 && buf[0] == '1')
1836                         bufmgr_sprd->use_dma_fence = 1;
1837
1838                 close(fp);
1839         }
1840
1841         if (!_bufmgr_init_cache_state(bufmgr_sprd)) {
1842                 TBM_ERR("fail to init bufmgr cache state\n");
1843                 if (error)
1844                         *error = TBM_ERROR_OPERATION_FAILED;
1845                 goto fail_init_cache_state;
1846         }
1847
1848         /*Create Hash Table*/
1849         bufmgr_sprd->hashBos = drmHashCreate();
1850
1851         /* alloc and register bufmgr_funcs */
1852         bufmgr_func = tbm_backend_bufmgr_alloc_bufmgr_func(bufmgr, &err);
1853         if (!bufmgr_func) {
1854                 TBM_ERR("fail to alloc bufmgr_func! err(%d)\n", err);
1855                 if (error)
1856                         *error = TBM_ERROR_OUT_OF_MEMORY;
1857                 goto fail_alloc_bufmgr_func;
1858         }
1859
1860         bufmgr_func->bufmgr_get_capabilities = tbm_sprd_bufmgr_get_capabilities;
1861         bufmgr_func->bufmgr_bind_native_display = tbm_sprd_bufmgr_bind_native_display;
1862         bufmgr_func->bufmgr_get_supported_formats = tbm_sprd_bufmgr_get_supported_formats;
1863         bufmgr_func->bufmgr_get_plane_data = tbm_sprd_bufmgr_get_plane_data;
1864         bufmgr_func->bufmgr_alloc_bo = tbm_sprd_bufmgr_alloc_bo;
1865         bufmgr_func->bufmgr_alloc_bo_with_format = NULL;
1866         bufmgr_func->bufmgr_import_fd = tbm_sprd_bufmgr_import_fd;
1867         bufmgr_func->bufmgr_import_key = tbm_sprd_bufmgr_import_key;
1868
1869         err = tbm_backend_bufmgr_register_bufmgr_func(bufmgr, bufmgr_func);
1870         if (err != TBM_ERROR_NONE) {
1871                 TBM_ERR("fail to register bufmgr_func! err(%d)\n", err);
1872                 if (error)
1873                         *error = TBM_ERROR_OPERATION_FAILED;
1874                 goto fail_register_bufmgr_func;
1875         }
1876         bufmgr_sprd->bufmgr_func = bufmgr_func;
1877
1878         /* alloc and register bo_funcs */
1879         bo_func = tbm_backend_bufmgr_alloc_bo_func(bufmgr, &err);
1880         if (!bo_func) {
1881                 TBM_ERR("fail to alloc bo_func! err(%d)\n", err);
1882                 if (error)
1883                         *error = TBM_ERROR_OUT_OF_MEMORY;
1884                 goto fail_alloc_bo_func;
1885         }
1886
1887         bo_func->bo_free = tbm_sprd_bo_free;
1888         bo_func->bo_get_size = tbm_sprd_bo_get_size;
1889         bo_func->bo_get_memory_types = tbm_sprd_bo_get_memory_type;
1890         bo_func->bo_get_handle = tbm_sprd_bo_get_handle;
1891         bo_func->bo_map = tbm_sprd_bo_map;
1892         bo_func->bo_unmap = tbm_sprd_bo_unmap;
1893         bo_func->bo_lock = NULL;
1894         bo_func->bo_unlock = NULL;
1895         bo_func->bo_export_fd = tbm_sprd_bo_export_fd;
1896         bo_func->bo_export_key = tbm_sprd_bo_export_key;
1897
1898         err = tbm_backend_bufmgr_register_bo_func(bufmgr, bo_func);
1899         if (err != TBM_ERROR_NONE) {
1900                 TBM_ERR("fail to register bo_func! err(%d)\n", err);
1901                 if (error)
1902                         *error = TBM_ERROR_OPERATION_FAILED;
1903                 goto fail_register_bo_func;
1904         }
1905         bufmgr_sprd->bo_func = bo_func;
1906
1907         TBM_DBG("DMABUF FENCE is %s\n",
1908                 bufmgr_sprd->use_dma_fence ? "supported!" : "NOT supported!");
1909         TBM_DBG("fd:%d\n", bufmgr_sprd->fd);
1910
1911         if (error)
1912                 *error = TBM_ERROR_NONE;
1913
1914         bufmgr_sprd->bufmgr = bufmgr;
1915
1916         return (tbm_backend_bufmgr_data *)bufmgr_sprd;
1917
1918 fail_register_bo_func:
1919         tbm_backend_bufmgr_free_bo_func(bufmgr, bo_func);
1920 fail_alloc_bo_func:
1921 fail_register_bufmgr_func:
1922         tbm_backend_bufmgr_free_bufmgr_func(bufmgr, bufmgr_func);
1923 fail_alloc_bufmgr_func:
1924         _bufmgr_deinit_cache_state(bufmgr_sprd);
1925         if (bufmgr_sprd->hashBos)
1926                 drmHashDestroy(bufmgr_sprd->hashBos);
1927 fail_init_cache_state:
1928         if (tbm_backend_bufmgr_query_display_server(bufmgr, &err))
1929                 tbm_drm_helper_unset_tbm_master_fd();
1930         tbm_drm_helper_unset_fd();
1931         if (bufmgr_sprd->device_name)
1932                 free(bufmgr_sprd->device_name);
1933 fail_get_device_name:
1934         close(bufmgr_sprd->fd);
1935 fail_get_auth_info:
1936 fail_open_drm:
1937         free(bufmgr_sprd);
1938         return NULL;
1939 }
1940
1941 tbm_backend_module tbm_backend_module_data = {
1942         "sprd",
1943         "Samsung",
1944         TBM_BACKEND_ABI_VERSION_2_0,
1945         tbm_sprd_init,
1946         tbm_sprd_deinit
1947 };