add initial codes
[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 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <sys/ioctl.h>
40 #include <sys/types.h>
41 #include <unistd.h>
42 #include <sys/mman.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
45 #include <errno.h>
46 #include <xf86drm.h>
47 #include <tbm_bufmgr.h>
48 #include <tbm_bufmgr_backend.h>
49 #include <drm/sprd_drm.h>
50 #include <pthread.h>
51 #include <tbm_surface.h>
52
53 #define DEBUG
54
55 //#define USE_CONTIG_ONLY
56 #define USE_DMAIMPORT
57
58 #define TBM_COLOR_FORMAT_COUNT 8
59
60
61
62 #ifdef DEBUG
63 #define LOG_TAG "TBM_BACKEND"
64 #include <dlog.h>
65 static int bDebug=0;
66
67 char* target_name()
68 {
69     FILE *f;
70     char *slash;
71     static int  initialized = 0;
72     static char app_name[128];
73
74     if ( initialized )
75         return app_name;
76
77     /* get the application name */
78     f = fopen("/proc/self/cmdline", "r");
79
80     if ( !f )
81     {
82         return 0;
83     }
84
85     memset(app_name, 0x00, sizeof(app_name));
86
87     if ( fgets(app_name, 100, f) == NULL )
88     {
89         fclose(f);
90         return 0;
91     }
92
93     fclose(f);
94
95     if ( (slash=strrchr(app_name, '/')) != NULL )
96     {
97         memmove(app_name, slash+1, strlen(slash));
98     }
99
100     initialized = 1;
101
102     return app_name;
103 }
104 #define TBM_SPRD_LOG(fmt, args...)              LOGE("\033[31m"  "[%s]" fmt "\033[0m", target_name(), ##args)
105 #define DBG(fmt, args...)               if(bDebug&01) LOGE("[%s]" fmt, target_name(), ##args)
106 #else
107 #define TBM_SPRD_LOG(...)
108 #define DBG(...)
109 #endif
110
111 #define SIZE_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1))
112
113 #define TBM_SURFACE_ALIGNMENT_PLANE (64)
114 #define TBM_SURFACE_ALIGNMENT_PITCH_RGB (64)
115 #define TBM_SURFACE_ALIGNMENT_PITCH_YUV (16)
116
117
118 /* check condition */
119 #define SPRD_RETURN_IF_FAIL(cond) {\
120     if (!(cond)) {\
121         TBM_SPRD_LOG ("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
122         return;\
123     }\
124 }
125 #define SPRD_RETURN_VAL_IF_FAIL(cond, val) {\
126     if (!(cond)) {\
127         TBM_SPRD_LOG ("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
128         return val;\
129     }\
130 }
131
132 struct dma_buf_info {
133         unsigned long   size;
134         unsigned int    fence_supported;
135         unsigned int    padding;
136 };
137
138 #define DMA_BUF_ACCESS_READ             0x1
139 #define DMA_BUF_ACCESS_WRITE            0x2
140 #define DMA_BUF_ACCESS_DMA              0x4
141 #define DMA_BUF_ACCESS_MAX              0x8
142
143 #define DMA_FENCE_LIST_MAX              5
144
145 struct dma_buf_fence {
146         unsigned long           ctx;
147         unsigned int            type;
148 };
149
150 #define DMABUF_IOCTL_BASE       'F'
151 #define DMABUF_IOWR(nr, type)   _IOWR(DMABUF_IOCTL_BASE, nr, type)
152
153 #define DMABUF_IOCTL_GET_INFO   DMABUF_IOWR(0x00, struct dma_buf_info)
154 #define DMABUF_IOCTL_GET_FENCE  DMABUF_IOWR(0x01, struct dma_buf_fence)
155 #define DMABUF_IOCTL_PUT_FENCE  DMABUF_IOWR(0x02, struct dma_buf_fence)
156
157 typedef struct _tbm_bufmgr_sprd *tbm_bufmgr_sprd;
158 typedef struct _tbm_bo_sprd *tbm_bo_sprd;
159
160 typedef struct _sprd_private
161 {
162     int ref_count;
163 } PrivGem;
164
165 /* tbm buffor object for sprd */
166 struct _tbm_bo_sprd
167 {
168     int fd;
169
170     unsigned int name;    /* FLINK ID */
171
172     unsigned int gem;     /* GEM Handle */
173
174     unsigned int dmabuf;  /* fd for dmabuf */
175
176     void *pBase;          /* virtual address */
177
178     unsigned int size;
179
180     unsigned int flags_sprd;
181     unsigned int flags_tbm;
182
183     PrivGem* private;
184
185     pthread_mutex_t mutex;
186     struct dma_buf_fence dma_fence[DMA_FENCE_LIST_MAX];
187     int device;
188     int opt;
189 };
190
191 /* tbm bufmgr private for sprd */
192 struct _tbm_bufmgr_sprd
193 {
194     int fd;
195     void* hashBos;
196
197     int use_dma_fence;
198 };
199
200 char *STR_DEVICE[]=
201 {
202     "DEF",
203     "CPU",
204     "2D",
205     "3D",
206     "MM"
207 };
208
209 char *STR_OPT[]=
210 {
211     "NONE",
212     "RD",
213     "WR",
214     "RDWR"
215 };
216
217
218 uint32_t tbm_sprd_color_format_list[TBM_COLOR_FORMAT_COUNT] = { TBM_FORMAT_RGBA8888,
219                                                                     TBM_FORMAT_BGRA8888,
220                                                                     TBM_FORMAT_RGBX8888,
221                                                                     TBM_FORMAT_RGB888,
222                                                                     TBM_FORMAT_NV12,
223                                                                     TBM_FORMAT_NV21,
224                                                                     TBM_FORMAT_YUV420,
225                                                                     TBM_FORMAT_YVU420 };
226
227
228 #ifndef USE_CONTIG_ONLY
229 static unsigned int
230 _get_sprd_flag_from_tbm (unsigned int ftbm)
231 {
232     unsigned int flags = 0;
233
234 /*
235  * TBM_BO_DEFAULT  => ION_HEAP_ID_MASK_SYSTEM
236  * TBM_BO_SCANOUT => ION_HEAP_ID_MASK_MM
237  * TBM_BO_VENDOR => ION_HEAP_ID_MASK_OVERLAY
238  * To be updated appropriately once DRM-GEM supports different heap id masks.
239  * */
240
241     if (ftbm & TBM_BO_SCANOUT)
242     {
243       flags = SPRD_BO_CONTIG;
244     }
245     else
246     {
247       flags = SPRD_BO_NONCONTIG | SPRD_BO_DEV_SYSTEM;
248     }
249
250     if (ftbm & TBM_BO_WC)
251         flags |= SPRD_BO_WC;
252     else if (ftbm & TBM_BO_NONCACHABLE)
253         flags |= SPRD_BO_NONCACHABLE;
254
255     return flags;
256 }
257
258 static unsigned int
259 _get_tbm_flag_from_sprd (unsigned int fsprd)
260 {
261     unsigned int flags = 0;
262
263     if (fsprd & SPRD_BO_NONCONTIG)
264         flags |= TBM_BO_DEFAULT;
265     else
266         flags |= TBM_BO_SCANOUT;
267
268     if (fsprd & SPRD_BO_WC)
269         flags |= TBM_BO_WC;
270     else if (fsprd & SPRD_BO_CACHABLE)
271         flags |= TBM_BO_DEFAULT;
272     else
273         flags |= TBM_BO_NONCACHABLE;
274
275     return flags;
276 }
277 #endif
278
279 static unsigned int
280 _get_name (int fd, unsigned int gem)
281 {
282     struct drm_gem_flink arg = {0,};
283
284     arg.handle = gem;
285     if (drmIoctl (fd, DRM_IOCTL_GEM_FLINK, &arg))
286     {
287         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
288                  "error %s:%d fail to get flink gem=%d\n",
289                  getpid(), __FUNCTION__, __LINE__, gem);
290         return 0;
291     }
292
293     return (unsigned int)arg.name;
294 }
295
296 static tbm_bo_handle
297 _sprd_bo_handle (tbm_bo_sprd bo_sprd, int device)
298 {
299     tbm_bo_handle bo_handle;
300     memset (&bo_handle, 0x0, sizeof (uint64_t));
301
302     switch(device)
303     {
304     case TBM_DEVICE_DEFAULT:
305     case TBM_DEVICE_2D:
306         bo_handle.u32 = (uint32_t)bo_sprd->gem;
307         break;
308     case TBM_DEVICE_CPU:
309         if (!bo_sprd->pBase)
310         {
311             struct drm_sprd_gem_mmap arg = {0,};
312
313             arg.handle = bo_sprd->gem;
314             arg.size = bo_sprd->size;
315             if (drmCommandWriteRead (bo_sprd->fd, DRM_SPRD_GEM_MMAP, &arg, sizeof(arg)))
316             {
317                 TBM_SPRD_LOG ("[libtbm-sprd:%d] "
318                          "error %s:%d Cannot usrptr gem=%d\n",
319                          getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
320                 return (tbm_bo_handle) NULL;
321             }
322             bo_sprd->pBase = (void*)((uint32_t)arg.mapped);
323         }
324
325         bo_handle.ptr = (void *)bo_sprd->pBase;
326         break;
327     case TBM_DEVICE_3D:
328 #ifdef USE_DMAIMPORT
329    if (!bo_sprd->dmabuf)
330         {
331             struct drm_prime_handle arg = {0, };
332             arg.handle = bo_sprd->gem;
333             if (drmIoctl (bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg))
334             {
335                 TBM_SPRD_LOG ("[libtbm-sprd:%d] "
336                          "error %s:%d Cannot dmabuf=%d\n",
337                          getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
338                 return (tbm_bo_handle) NULL;
339             }
340             bo_sprd->dmabuf = arg.fd;
341         }
342
343         bo_handle.u32 = (uint32_t)bo_sprd->dmabuf;
344
345 #endif
346         break;
347
348     case TBM_DEVICE_MM:
349 #ifdef USE_HEAP_ID
350         //TODO : Add ioctl for GSP MAP once available.
351     DBG ("[libtbm-sprd:%d] %s In case TBM_DEVICE_MM:  \n", getpid(),
352          __FUNCTION_);_
353
354 #else
355         if (!bo_sprd->dmabuf)
356         {
357             struct drm_prime_handle arg = {0, };
358
359             arg.handle = bo_sprd->gem;
360             if (drmIoctl (bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg))
361             {
362                 TBM_SPRD_LOG ("[libtbm-sprd:%d] "
363                          "error %s:%d Cannot dmabuf=%d\n",
364                          getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
365                 return (tbm_bo_handle) NULL;
366             }
367             bo_sprd->dmabuf = arg.fd;
368         }
369
370         bo_handle.u32 = (uint32_t)bo_sprd->dmabuf;
371 #endif
372         break;
373     default:
374         bo_handle.ptr = (void *) NULL;
375         break;
376     }
377
378     return bo_handle;
379 }
380
381 #ifdef USE_CACHE
382 static int
383 _sprd_cache_flush (int fd, tbm_bo_sprd bo_sprd, int flags)
384 {
385     struct drm_sprd_gem_cache_op cache_op = {0, };
386     int ret;
387
388     /* if bo_sprd is null, do cache_flush_all */
389     if(bo_sprd)
390     {
391         cache_op.flags = 0;
392         cache_op.usr_addr = (uint64_t)((uint32_t)bo_sprd->pBase);
393         cache_op.size = bo_sprd->size;
394     }
395     else
396     {
397         flags = TBM_CACHE_FLUSH_ALL;
398         cache_op.flags = 0;
399         cache_op.usr_addr = 0;
400         cache_op.size = 0;
401     }
402
403     if (flags & TBM_CACHE_INV)
404     {
405         if(flags & TBM_CACHE_ALL)
406             cache_op.flags |= SPRD_DRM_CACHE_INV_ALL;
407         else
408             cache_op.flags |= SPRD_DRM_CACHE_INV_RANGE;
409     }
410
411     if (flags & TBM_CACHE_CLN)
412     {
413         if(flags & TBM_CACHE_ALL)
414             cache_op.flags |= SPRD_DRM_CACHE_CLN_ALL;
415         else
416             cache_op.flags |= SPRD_DRM_CACHE_CLN_RANGE;
417     }
418
419     if(flags & TBM_CACHE_ALL)
420         cache_op.flags |= SPRD_DRM_ALL_CACHES_CORES;
421
422     ret = drmCommandWriteRead (fd, DRM_SPRD_GEM_CACHE_OP, &cache_op, sizeof(cache_op));
423     if (ret)
424     {
425         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
426                  "error %s:%d fail to flush the cache.\n",
427                  getpid(), __FUNCTION__, __LINE__);
428         return 0;
429     }
430
431     return 1;
432 }
433 #endif
434
435 static int
436 tbm_sprd_bo_size (tbm_bo bo)
437 {
438     SPRD_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
439
440     tbm_bo_sprd bo_sprd;
441
442     bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
443
444     return bo_sprd->size;
445 }
446
447 static void *
448 tbm_sprd_bo_alloc (tbm_bo bo, int size, int flags)
449 {
450     SPRD_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
451
452     tbm_bo_sprd bo_sprd;
453     tbm_bufmgr_sprd bufmgr_sprd;
454     unsigned int sprd_flags;
455
456     bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
457     SPRD_RETURN_VAL_IF_FAIL (bufmgr_sprd!=NULL, 0);
458
459     bo_sprd = calloc (1, sizeof(struct _tbm_bo_sprd));
460     if (!bo_sprd)
461     {
462         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
463                  "error %s:%d fail to allocate the bo private\n",
464                  getpid(), __FUNCTION__, __LINE__);
465         return 0;
466     }
467
468 #ifdef USE_CONTIG_ONLY
469     flags = TBM_BO_SCANOUT;
470     sprd_flags = SPRD_BO_CONTIG;
471 #else
472     sprd_flags = _get_sprd_flag_from_tbm (flags);
473     if((flags & TBM_BO_SCANOUT) &&
474         size <= 4*1024)
475     {
476         sprd_flags |= SPRD_BO_NONCONTIG;
477     }
478 #endif // USE_CONTIG_ONLY
479     struct drm_sprd_gem_create arg = {0, };
480     arg.size = size;
481     arg.flags = sprd_flags;
482     if (drmCommandWriteRead(bufmgr_sprd->fd, DRM_SPRD_GEM_CREATE, &arg, sizeof(arg)))
483     {
484         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
485                  "error %s:%d Cannot create bo(flag:%x, size:%d)\n",
486                  getpid(), __FUNCTION__, __LINE__, arg.flags, (unsigned int)arg.size);
487         free (bo_sprd);
488         return 0;
489     }
490
491     bo_sprd->fd = bufmgr_sprd->fd;
492     bo_sprd->gem = arg.handle;
493     bo_sprd->size = size;
494     bo_sprd->flags_tbm = flags;
495     bo_sprd->flags_sprd = sprd_flags;
496     bo_sprd->name = _get_name (bo_sprd->fd, bo_sprd->gem);
497
498     pthread_mutex_init(&bo_sprd->mutex, NULL);
499
500     if (bufmgr_sprd->use_dma_fence
501         && !bo_sprd->dmabuf)
502     {
503         struct drm_prime_handle arg = {0, };
504
505         arg.handle = bo_sprd->gem;
506         if (drmIoctl (bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg))
507         {
508             TBM_SPRD_LOG ("[libtbm-sprd:%d] "
509                     "error %s:%d Cannot dmabuf=%d\n",
510                     getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
511             free (bo_sprd);
512             return 0;
513         }
514         bo_sprd->dmabuf = arg.fd;
515     }
516
517     /* add bo to hash */
518     PrivGem* privGem = calloc (1, sizeof(PrivGem));
519     privGem->ref_count = 1;
520     if (drmHashInsert(bufmgr_sprd->hashBos, bo_sprd->name, (void *)privGem) < 0)
521     {
522         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
523                  "error %s:%d Cannot insert bo to Hash(%d)\n",
524                  getpid(), __FUNCTION__, __LINE__, bo_sprd->name);
525     }
526
527     DBG ("[libtbm-sprd:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
528          __FUNCTION__, bo_sprd->size,
529          bo_sprd->gem, bo_sprd->name,
530          flags, sprd_flags);
531
532     return (void *)bo_sprd;
533 }
534
535 static void
536 tbm_sprd_bo_free(tbm_bo bo)
537 {
538     tbm_bo_sprd bo_sprd;
539     tbm_bufmgr_sprd bufmgr_sprd;
540
541     if (!bo)
542         return;
543
544     bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
545     SPRD_RETURN_IF_FAIL (bufmgr_sprd!=NULL);
546
547     bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
548     SPRD_RETURN_IF_FAIL (bo_sprd!=NULL);
549
550     DBG ("[libtbm-sprd:%d] %s size:%d, gem:%d(%d)\n",
551          getpid(), __FUNCTION__, bo_sprd->size, bo_sprd->gem, bo_sprd->name);
552
553     if (bo_sprd->pBase)
554     {
555         if (munmap(bo_sprd->pBase, bo_sprd->size) == -1)
556         {
557             TBM_SPRD_LOG ("[libtbm-sprd:%d] "
558                      "error %s:%d\n",
559                      getpid(), __FUNCTION__, __LINE__);
560         }
561     }
562
563     /* close dmabuf */
564     if (bo_sprd->dmabuf)
565     {
566         close (bo_sprd->dmabuf);
567         bo_sprd->dmabuf = 0;
568     }
569
570     /* delete bo from hash */
571     PrivGem *privGem = NULL;
572     int ret;
573
574     ret = drmHashLookup (bufmgr_sprd->hashBos, bo_sprd->name, (void**)&privGem);
575     if (ret == 0)
576     {
577         privGem->ref_count--;
578         if (privGem->ref_count == 0)
579         {
580             drmHashDelete (bufmgr_sprd->hashBos, bo_sprd->name);
581             free (privGem);
582             privGem = NULL;
583         }
584     }
585     else
586     {
587         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
588                  "warning %s:%d Cannot find bo to Hash(%d), ret=%d\n",
589                  getpid(), __FUNCTION__, __LINE__, bo_sprd->name, ret);
590     }
591
592     /* Free gem handle */
593     struct drm_gem_close arg = {0, };
594     memset (&arg, 0, sizeof(arg));
595     arg.handle = bo_sprd->gem;
596     if (drmIoctl (bo_sprd->fd, DRM_IOCTL_GEM_CLOSE, &arg))
597     {
598         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
599                  "error %s:%d\n",
600                  getpid(), __FUNCTION__, __LINE__);
601     }
602
603     free (bo_sprd);
604 }
605
606
607 static void *
608 tbm_sprd_bo_import (tbm_bo bo, unsigned int key)
609 {
610     SPRD_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
611
612     tbm_bufmgr_sprd bufmgr_sprd;
613     tbm_bo_sprd bo_sprd;
614
615     bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
616     SPRD_RETURN_VAL_IF_FAIL (bufmgr_sprd!=NULL, 0);
617
618     struct drm_gem_open arg = {0, };
619     struct drm_sprd_gem_info info = {0, };
620
621     arg.name = key;
622     if (drmIoctl(bufmgr_sprd->fd, DRM_IOCTL_GEM_OPEN, &arg))
623     {
624         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
625                 "error %s:%d Cannot open gem name=%d\n",
626                 getpid(), __FUNCTION__, __LINE__, key);
627         return 0;
628     }
629
630     info.handle = arg.handle;
631     if (drmCommandWriteRead(bufmgr_sprd->fd,
632                            DRM_SPRD_GEM_GET,
633                            &info,
634                            sizeof(struct drm_sprd_gem_info)))
635     {
636         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
637                 "error %s:%d Cannot get gem info=%d\n",
638                 getpid(), __FUNCTION__, __LINE__, key);
639         return 0;
640     }
641
642     bo_sprd = calloc (1, sizeof(struct _tbm_bo_sprd));
643     if (!bo_sprd)
644     {
645         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
646                 "error %s:%d fail to allocate the bo private\n",
647                 getpid(), __FUNCTION__, __LINE__);
648         return 0;
649     }
650
651     bo_sprd->fd = bufmgr_sprd->fd;
652     bo_sprd->gem = arg.handle;
653     bo_sprd->size = arg.size;
654     bo_sprd->flags_sprd = info.flags;
655     bo_sprd->name = key;
656 #ifdef USE_CONTIG_ONLY
657     bo_sprd->flags_sprd = SPRD_BO_CONTIG;
658     bo_sprd->flags_tbm |= TBM_BO_SCANOUT;
659 #else
660     bo_sprd->flags_tbm = _get_tbm_flag_from_sprd (bo_sprd->flags_sprd);
661 #endif
662
663
664     if (!bo_sprd->dmabuf)
665     {
666         struct drm_prime_handle arg = {0, };
667
668         arg.handle = bo_sprd->gem;
669         if (drmIoctl (bo_sprd->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg))
670         {
671             TBM_SPRD_LOG ("[libtbm-sprd:%d] "
672                     "error %s:%d Cannot dmabuf=%d\n",
673                     getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
674             free (bo_sprd);
675             return 0;
676         }
677         bo_sprd->dmabuf = arg.fd;
678     }
679
680     /* add bo to hash */
681     PrivGem *privGem = NULL;
682     int ret;
683
684     ret = drmHashLookup (bufmgr_sprd->hashBos, bo_sprd->name, (void**)&privGem);
685     if (ret == 0)
686     {
687         privGem->ref_count++;
688     }
689     else if (ret == 1)
690     {
691         privGem = calloc (1, sizeof(PrivGem));
692         privGem->ref_count = 1;
693         if (drmHashInsert (bufmgr_sprd->hashBos, bo_sprd->name, (void *)privGem) < 0)
694         {
695             TBM_SPRD_LOG ("[libtbm-sprd:%d] "
696                     "error %s:%d Cannot insert bo to Hash(%d)\n",
697                     getpid(), __FUNCTION__, __LINE__, bo_sprd->name);
698         }
699     }
700     else
701     {
702         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
703                 "error %s:%d Cannot insert bo to Hash(%d)\n",
704                 getpid(), __FUNCTION__, __LINE__, bo_sprd->name);
705     }
706
707     DBG ("[libtbm-sprd:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
708          __FUNCTION__, bo_sprd->size,
709          bo_sprd->gem, bo_sprd->name,
710          bo_sprd->flags_tbm, bo_sprd->flags_sprd);
711
712     return (void *)bo_sprd;
713 }
714
715 static unsigned int
716 tbm_sprd_bo_export (tbm_bo bo)
717 {
718     SPRD_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
719
720     tbm_bo_sprd bo_sprd;
721
722     bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
723     SPRD_RETURN_VAL_IF_FAIL (bo_sprd!=NULL, 0);
724
725     if (!bo_sprd->name)
726     {
727         bo_sprd->name = _get_name(bo_sprd->fd, bo_sprd->gem);
728         if (!bo_sprd->name)
729         {
730             TBM_SPRD_LOG ("[libtbm-sprd:%d] "
731                     "error %s:%d Cannot get name\n",
732                     getpid(), __FUNCTION__, __LINE__);
733             return 0;
734         }
735     }
736
737     DBG ("[libtbm-sprd:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
738          __FUNCTION__, bo_sprd->size,
739          bo_sprd->gem, bo_sprd->name,
740          bo_sprd->flags_tbm, bo_sprd->flags_sprd);
741
742     return (unsigned int)bo_sprd->name;
743 }
744
745 static tbm_bo_handle
746 tbm_sprd_bo_get_handle (tbm_bo bo, int device)
747 {
748     SPRD_RETURN_VAL_IF_FAIL (bo!=NULL, (tbm_bo_handle) NULL);
749
750     tbm_bo_handle bo_handle;
751     tbm_bo_sprd bo_sprd;
752
753     bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
754     SPRD_RETURN_VAL_IF_FAIL (bo_sprd!=NULL, (tbm_bo_handle) NULL);
755
756     if (!bo_sprd->gem)
757     {
758         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
759                 "error %s:%d Cannot map gem=%d\n",
760                 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
761         return (tbm_bo_handle) NULL;
762     }
763
764     DBG ("[libtbm-sprd:%d] %s gem:%d(%d), %s\n", getpid(),
765          __FUNCTION__, bo_sprd->gem, bo_sprd->name, STR_DEVICE[device]);
766
767     /*Get mapped bo_handle*/
768     bo_handle = _sprd_bo_handle (bo_sprd, device);
769     if (bo_handle.ptr == NULL)
770     {
771         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
772                 "error %s:%d Cannot get handle: gem:%d, device:%d\n",
773                 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem, device);
774         return (tbm_bo_handle) NULL;
775     }
776
777     return bo_handle;
778 }
779
780 static tbm_bo_handle
781 tbm_sprd_bo_map (tbm_bo bo, int device, int opt)
782 {
783     SPRD_RETURN_VAL_IF_FAIL (bo!=NULL, (tbm_bo_handle) NULL);
784
785     tbm_bo_handle bo_handle;
786     tbm_bo_sprd bo_sprd;
787
788     bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
789     SPRD_RETURN_VAL_IF_FAIL (bo_sprd!=NULL, (tbm_bo_handle) NULL);
790
791     if (!bo_sprd->gem)
792     {
793         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
794                 "error %s:%d Cannot map gem=%d\n",
795                 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem);
796         return (tbm_bo_handle) NULL;
797     }
798
799     DBG ("[libtbm-sprd:%d] %s gem:%d(%d), %s, %s\n", getpid(),
800          __FUNCTION__, bo_sprd->gem, bo_sprd->name, STR_DEVICE[device], STR_OPT[opt]);
801
802     /*Get mapped bo_handle*/
803     bo_handle = _sprd_bo_handle (bo_sprd, device);
804     if (bo_handle.ptr == NULL)
805     {
806         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
807                 "error %s:%d Cannot get handle: gem:%d, device:%d, opt:%d\n",
808                 getpid(), __FUNCTION__, __LINE__, bo_sprd->gem, device, opt);
809         return (tbm_bo_handle) NULL;
810     }
811
812     return bo_handle;
813 }
814
815 static int
816 tbm_sprd_bo_unmap (tbm_bo bo)
817 {
818     SPRD_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
819
820     tbm_bo_sprd bo_sprd;
821
822     bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
823     SPRD_RETURN_VAL_IF_FAIL (bo_sprd!=NULL, 0);
824
825     if (!bo_sprd->gem)
826         return 0;
827
828     DBG ("[libtbm-sprd:%d] %s gem:%d(%d) \n", getpid(),
829          __FUNCTION__, bo_sprd->gem, bo_sprd->name);
830
831     return 1;
832 }
833
834 static int
835 tbm_sprd_bo_cache_flush (tbm_bo bo, int flags)
836 {
837     tbm_bufmgr_sprd bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
838     SPRD_RETURN_VAL_IF_FAIL (bufmgr_sprd!=NULL, 0);
839
840     /* cache flush is managed by kernel side when using dma-fence. */
841     if (bufmgr_sprd->use_dma_fence)
842        return 1;
843
844     SPRD_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
845
846     tbm_bo_sprd bo_sprd;
847
848     bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
849     SPRD_RETURN_VAL_IF_FAIL (bo_sprd!=NULL, 0);
850
851 #ifdef USE_CACHE
852     if (!_sprd_cache_flush(bo_sprd->fd, bo_sprd, flags))
853         return 0;
854 #endif
855
856     return 1;
857 }
858
859 static int
860 tbm_sprd_bo_get_global_key (tbm_bo bo)
861 {
862     SPRD_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
863
864     tbm_bo_sprd bo_sprd;
865
866     bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
867     SPRD_RETURN_VAL_IF_FAIL (bo_sprd!=NULL, 0);
868
869     if (!bo_sprd->name)
870     {
871         if (!bo_sprd->gem)
872             return 0;
873
874         bo_sprd->name = _get_name(bo_sprd->fd, bo_sprd->gem);
875     }
876
877     return bo_sprd->name;
878 }
879
880 static int
881 tbm_sprd_bo_lock(tbm_bo bo, int device, int opt)
882 {
883     SPRD_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
884
885 #if USE_BACKEND_LOCK
886     tbm_bufmgr_sprd bufmgr_sprd;
887     tbm_bo_sprd bo_sprd;
888     struct dma_buf_fence fence;
889     int ret=0;
890
891     bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
892     SPRD_RETURN_VAL_IF_FAIL (bo_sprd!=NULL, 0);
893
894     bufmgr_sprd = (tbm_bufmgr_sprd)tbm_backend_get_bufmgr_priv(bo);
895     SPRD_RETURN_VAL_IF_FAIL (bufmgr_sprd!=NULL, 0);
896
897     memset(&fence, 0, sizeof(struct dma_buf_fence));
898
899     /* Check if the given type is valid or not. */
900     if (opt & TBM_OPTION_WRITE)
901     {
902         if (device == TBM_DEVICE_CPU)
903             fence.type = DMA_BUF_ACCESS_WRITE;
904         else if (device == TBM_DEVICE_3D)
905             fence.type = DMA_BUF_ACCESS_WRITE | DMA_BUF_ACCESS_DMA;
906         else
907         {
908             DBG ("[libtbm-sprd:%d] %s GET_FENCE is ignored(device type is not 3D/CPU),\n", getpid(), __FUNCTION__);
909             return 0;
910         }
911     }
912     else if (opt & TBM_OPTION_READ)
913     {
914         if (device == TBM_DEVICE_CPU)
915             fence.type = DMA_BUF_ACCESS_READ;
916         else if (device == TBM_DEVICE_3D)
917             fence.type = DMA_BUF_ACCESS_READ | DMA_BUF_ACCESS_DMA;
918         else
919         {
920             DBG ("[libtbm-sprd:%d] %s GET_FENCE is ignored(device type is not 3D/CPU),\n", getpid(), __FUNCTION__);
921             return 0;
922         }
923     }
924     else
925     {
926         TBM_SPRD_LOG ("[libtbm-sprd:%d] error %s:%d Invalid argument\n", getpid(), __FUNCTION__, __LINE__);
927         return 0;
928     }
929
930     /* Check if the tbm manager supports dma fence or not. */
931     if (!bufmgr_sprd->use_dma_fence)
932     {
933         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
934                 "error %s:%d  Not support DMA FENCE(%s)\n",
935                 getpid(), __FUNCTION__, __LINE__, strerror(errno) );
936         return 0;
937
938     }
939
940     ret = ioctl(bo_sprd->dmabuf, DMABUF_IOCTL_GET_FENCE, &fence);
941     if (ret < 0)
942     {
943         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
944                 "error %s:%d  Can not set GET FENCE(%s)\n",
945                 getpid(), __FUNCTION__, __LINE__, strerror(errno) );
946         return 0;
947     }
948
949     pthread_mutex_lock(&bo_sprd->mutex);
950     int i;
951     for (i = 0; i < DMA_FENCE_LIST_MAX; i++)
952     {
953         if (bo_sprd->dma_fence[i].ctx == 0)
954         {
955             bo_sprd->dma_fence[i].type = fence.type;
956             bo_sprd->dma_fence[i].ctx = fence.ctx;
957             break;
958         }
959     }
960     if (i == DMA_FENCE_LIST_MAX)
961     {
962         //TODO: if dma_fence list is full, it needs realloc. I will fix this. by minseok3.kim
963         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
964                 "error %s:%d  fence list is full\n",
965                 getpid(), __FUNCTION__, __LINE__);
966     }
967     pthread_mutex_unlock(&bo_sprd->mutex);
968
969     DBG ("[libtbm-sprd:%d] %s DMABUF_IOCTL_GET_FENCE! flink_id=%d dmabuf=%d\n", getpid(),
970             __FUNCTION__, bo_sprd->name, bo_sprd->dmabuf);
971
972 #endif
973     return 1;
974 }
975
976 static int
977 tbm_sprd_bo_unlock(tbm_bo bo)
978 {
979     SPRD_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
980
981 #if USE_BACKEND_LOCK
982     tbm_bo_sprd bo_sprd;
983     struct dma_buf_fence fence;
984     int ret=0;
985
986     bo_sprd = (tbm_bo_sprd)tbm_backend_get_bo_priv(bo);
987     SPRD_RETURN_VAL_IF_FAIL (bo_sprd!=NULL, 0);
988
989     if (!bo_sprd->dma_fence[0].ctx)
990     {
991         DBG ("[libtbm-sprd:%d] %s FENCE not support or ignored,\n", getpid(), __FUNCTION__);
992         return 0;
993     }
994
995     if (!bo_sprd->dma_fence[0].type)
996     {
997         DBG ("[libtbm-sprd:%d] %s device type is not 3D/CPU,\n", getpid(), __FUNCTION__);
998         return 0;
999     }
1000
1001     pthread_mutex_lock(&bo_sprd->mutex);
1002     fence.type = bo_sprd->dma_fence[0].type;
1003     fence.ctx = bo_sprd->dma_fence[0].ctx;
1004     int i;
1005     for (i = 1; i < DMA_FENCE_LIST_MAX; i++)
1006     {
1007         bo_sprd->dma_fence[i-1].type = bo_sprd->dma_fence[i].type;
1008         bo_sprd->dma_fence[i-1].ctx = bo_sprd->dma_fence[i].ctx;
1009     }
1010     bo_sprd->dma_fence[DMA_FENCE_LIST_MAX-1].type = 0;
1011     bo_sprd->dma_fence[DMA_FENCE_LIST_MAX-1].ctx = 0;
1012     pthread_mutex_unlock(&bo_sprd->mutex);
1013
1014     ret = ioctl(bo_sprd->dmabuf, DMABUF_IOCTL_PUT_FENCE, &fence);
1015     if (ret < 0)
1016     {
1017         TBM_SPRD_LOG ("[libtbm-sprd:%d] "
1018                 "error %s:%d  Can not set PUT FENCE(%s)\n",
1019                 getpid(), __FUNCTION__, __LINE__, strerror(errno) );
1020         return 0;
1021     }
1022
1023     DBG ("[libtbm-sprd:%d] %s DMABUF_IOCTL_PUT_FENCE! flink_id=%d dmabuf=%d\n", getpid(),
1024             __FUNCTION__, bo_sprd->name, bo_sprd->dmabuf);
1025
1026 #endif
1027     return 1;
1028 }
1029
1030 static void
1031 tbm_sprd_bufmgr_deinit (void *priv)
1032 {
1033     SPRD_RETURN_IF_FAIL (priv!=NULL);
1034
1035     tbm_bufmgr_sprd bufmgr_sprd;
1036
1037     bufmgr_sprd = (tbm_bufmgr_sprd)priv;
1038
1039     if (bufmgr_sprd->hashBos)
1040     {
1041         unsigned long key;
1042         void *value;
1043
1044         while (drmHashFirst(bufmgr_sprd->hashBos, &key, &value) > 0)
1045         {
1046             free (value);
1047             drmHashDelete (bufmgr_sprd->hashBos, key);
1048         }
1049
1050         drmHashDestroy (bufmgr_sprd->hashBos);
1051         bufmgr_sprd->hashBos = NULL;
1052     }
1053
1054     free (bufmgr_sprd);
1055 }
1056
1057 int
1058 tbm_sprd_surface_supported_format(uint32_t **formats, uint32_t *num)
1059 {
1060     uint32_t* color_formats=NULL;
1061
1062     color_formats = (uint32_t*)calloc (1,sizeof(uint32_t)*TBM_COLOR_FORMAT_COUNT);
1063
1064     if( color_formats == NULL )
1065     {
1066         return 0;
1067     }
1068     memcpy( color_formats, tbm_sprd_color_format_list , sizeof(uint32_t)*TBM_COLOR_FORMAT_COUNT );
1069
1070
1071     *formats = color_formats;
1072     *num = TBM_COLOR_FORMAT_COUNT;
1073
1074
1075     return 1;
1076 }
1077
1078
1079 /**
1080  * @brief get the plane data of the surface.
1081  * @param[in] surface : the surface
1082  * @param[in] width : the width of the surface
1083  * @param[in] height : the height of the surface
1084  * @param[in] format : the format of the surface
1085  * @param[in] plane_idx : the format of the surface
1086  * @param[out] size : the size of the plane
1087  * @param[out] offset : the offset of the plane
1088  * @param[out] pitch : the pitch of the plane
1089  * @param[out] padding : the padding of the plane
1090  * @return 1 if this function succeeds, otherwise 0.
1091  */
1092 int
1093 tbm_sprd_surface_get_plane_data(tbm_surface_h surface, int width, int height, tbm_format format, int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
1094 {
1095     int ret = 1;
1096     int bpp;
1097     int _offset =0;
1098     int _pitch =0;
1099     int _size =0;
1100     int _bo_idx = 0;
1101
1102     switch(format)
1103     {
1104         /* 16 bpp RGB */
1105         case TBM_FORMAT_XRGB4444:
1106         case TBM_FORMAT_XBGR4444:
1107         case TBM_FORMAT_RGBX4444:
1108         case TBM_FORMAT_BGRX4444:
1109         case TBM_FORMAT_ARGB4444:
1110         case TBM_FORMAT_ABGR4444:
1111         case TBM_FORMAT_RGBA4444:
1112         case TBM_FORMAT_BGRA4444:
1113         case TBM_FORMAT_XRGB1555:
1114         case TBM_FORMAT_XBGR1555:
1115         case TBM_FORMAT_RGBX5551:
1116         case TBM_FORMAT_BGRX5551:
1117         case TBM_FORMAT_ARGB1555:
1118         case TBM_FORMAT_ABGR1555:
1119         case TBM_FORMAT_RGBA5551:
1120         case TBM_FORMAT_BGRA5551:
1121         case TBM_FORMAT_RGB565:
1122             bpp = 16;
1123             _offset = 0;
1124             _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1125             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1126             _bo_idx = 0;
1127             break;
1128         /* 24 bpp RGB */
1129         case TBM_FORMAT_RGB888:
1130         case TBM_FORMAT_BGR888:
1131             bpp = 24;
1132             _offset = 0;
1133             _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1134             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1135             _bo_idx = 0;
1136             break;
1137         /* 32 bpp RGB */
1138         case TBM_FORMAT_XRGB8888:
1139         case TBM_FORMAT_XBGR8888:
1140         case TBM_FORMAT_RGBX8888:
1141         case TBM_FORMAT_BGRX8888:
1142         case TBM_FORMAT_ARGB8888:
1143         case TBM_FORMAT_ABGR8888:
1144         case TBM_FORMAT_RGBA8888:
1145         case TBM_FORMAT_BGRA8888:
1146             bpp = 32;
1147             _offset = 0;
1148             _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1149             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1150             _bo_idx = 0;
1151             break;
1152
1153         /* packed YCbCr */
1154         case TBM_FORMAT_YUYV:
1155         case TBM_FORMAT_YVYU:
1156         case TBM_FORMAT_UYVY:
1157         case TBM_FORMAT_VYUY:
1158         case TBM_FORMAT_AYUV:
1159             bpp = 32;
1160             _offset = 0;
1161             _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1162             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1163             _bo_idx = 0;
1164             break;
1165
1166         /*
1167         * 2 plane YCbCr
1168         * index 0 = Y plane, [7:0] Y
1169         * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1170         * or
1171         * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1172         */
1173         case TBM_FORMAT_NV12:
1174         case TBM_FORMAT_NV21:
1175             bpp = 12;
1176             if(plane_idx == 0)
1177             {
1178                 _offset = 0;
1179                 _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1180                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1181                 _bo_idx = 0;
1182             }
1183             else if( plane_idx ==1 )
1184             {
1185                 _offset = width*height;
1186                 _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1187                 _size = SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1188                 _bo_idx = 0;
1189             }
1190             break;
1191
1192         case TBM_FORMAT_NV16:
1193         case TBM_FORMAT_NV61:
1194                         bpp = 16;
1195             //if(plane_idx == 0)
1196             {
1197                 _offset = 0;
1198                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1199                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1200                 _bo_idx = 0;
1201                 if(plane_idx == 0)
1202                         break;
1203             }
1204             //else if( plane_idx ==1 )
1205             {
1206                 _offset += _size;
1207                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1208                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1209                 _bo_idx = 0;
1210             }
1211             break;
1212
1213         /*
1214         * 3 plane YCbCr
1215         * index 0: Y plane, [7:0] Y
1216         * index 1: Cb plane, [7:0] Cb
1217         * index 2: Cr plane, [7:0] Cr
1218         * or
1219         * index 1: Cr plane, [7:0] Cr
1220         * index 2: Cb plane, [7:0] Cb
1221         */
1222         /*
1223         NATIVE_BUFFER_FORMAT_YV12
1224         NATIVE_BUFFER_FORMAT_I420
1225         */
1226         case TBM_FORMAT_YUV410:
1227         case TBM_FORMAT_YVU410:
1228             bpp = 9;
1229             break;
1230         case TBM_FORMAT_YUV411:
1231         case TBM_FORMAT_YVU411:
1232         case TBM_FORMAT_YUV420:
1233         case TBM_FORMAT_YVU420:
1234             bpp = 12;
1235             //if(plane_idx == 0)
1236             {
1237                 _offset = 0;
1238                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1239                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1240                 _bo_idx = 0;
1241                 if(plane_idx == 0)
1242                     break;
1243             }
1244             //else if( plane_idx == 1 )
1245             {
1246                 _offset += _size;
1247                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1248                 _size = SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1249                 _bo_idx = 0;
1250                 if(plane_idx == 1)
1251                     break;
1252             }
1253             //else if (plane_idx == 2 )
1254             {
1255                 _offset += _size;
1256                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1257                 _size = SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1258                 _bo_idx = 0;
1259             }
1260             break;
1261         case TBM_FORMAT_YUV422:
1262         case TBM_FORMAT_YVU422:
1263             bpp = 16;
1264             //if(plane_idx == 0)
1265             {
1266                 _offset = 0;
1267                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1268                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1269                 _bo_idx = 0;
1270                 if(plane_idx == 0)
1271                     break;
1272             }
1273             //else if( plane_idx == 1 )
1274             {
1275                 _offset += _size;
1276                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1277                 _size = SIZE_ALIGN(_pitch*(height),TBM_SURFACE_ALIGNMENT_PLANE);
1278                 _bo_idx = 0;
1279                 if(plane_idx == 1)
1280                     break;
1281             }
1282             //else if (plane_idx == 2 )
1283             {
1284                 _offset += _size;
1285                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1286                 _size = SIZE_ALIGN(_pitch*(height),TBM_SURFACE_ALIGNMENT_PLANE);
1287                 _bo_idx = 0;
1288             }
1289             break;
1290         case TBM_FORMAT_YUV444:
1291         case TBM_FORMAT_YVU444:
1292             bpp = 24;
1293             //if(plane_idx == 0)
1294             {
1295                 _offset = 0;
1296                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1297                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1298                 _bo_idx = 0;
1299                 if(plane_idx == 0)
1300                     break;
1301             }
1302             //else if( plane_idx == 1 )
1303             {
1304                 _offset += _size;
1305                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1306                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1307                 _bo_idx = 0;
1308                 if(plane_idx == 1)
1309                     break;
1310             }
1311             //else if (plane_idx == 2 )
1312             {
1313                 _offset += _size;
1314                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1315                _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1316                 _bo_idx = 0;
1317             }
1318             break;
1319         default:
1320             bpp = 0;
1321             break;
1322     }
1323
1324     *size = _size;
1325     *offset = _offset;
1326     *pitch = _pitch;
1327     *bo_idx = _bo_idx;
1328
1329     return ret;
1330 }
1331 /**
1332 * @brief get the size of the surface with a format.
1333 * @param[in] surface : the surface
1334 * @param[in] width : the width of the surface
1335 * @param[in] height : the height of the surface
1336 * @param[in] format : the format of the surface
1337 * @return size of the surface if this function succeeds, otherwise 0.
1338 */
1339
1340 int
1341 tbm_sprd_surface_get_size(tbm_surface_h surface, int width, int height, tbm_format format)
1342 {
1343     int ret = 0;
1344     int bpp = 0;
1345     int _pitch =0;
1346     int _size =0;
1347     int align =TBM_SURFACE_ALIGNMENT_PLANE;
1348
1349
1350     switch(format)
1351     {
1352         /* 16 bpp RGB */
1353         case TBM_FORMAT_XRGB4444:
1354         case TBM_FORMAT_XBGR4444:
1355         case TBM_FORMAT_RGBX4444:
1356         case TBM_FORMAT_BGRX4444:
1357         case TBM_FORMAT_ARGB4444:
1358         case TBM_FORMAT_ABGR4444:
1359         case TBM_FORMAT_RGBA4444:
1360         case TBM_FORMAT_BGRA4444:
1361         case TBM_FORMAT_XRGB1555:
1362         case TBM_FORMAT_XBGR1555:
1363         case TBM_FORMAT_RGBX5551:
1364         case TBM_FORMAT_BGRX5551:
1365         case TBM_FORMAT_ARGB1555:
1366         case TBM_FORMAT_ABGR1555:
1367         case TBM_FORMAT_RGBA5551:
1368         case TBM_FORMAT_BGRA5551:
1369         case TBM_FORMAT_RGB565:
1370             bpp = 16;
1371             _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1372             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1373             break;
1374         /* 24 bpp RGB */
1375         case TBM_FORMAT_RGB888:
1376         case TBM_FORMAT_BGR888:
1377             bpp = 24;
1378             _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1379             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1380             break;
1381         /* 32 bpp RGB */
1382         case TBM_FORMAT_XRGB8888:
1383         case TBM_FORMAT_XBGR8888:
1384         case TBM_FORMAT_RGBX8888:
1385         case TBM_FORMAT_BGRX8888:
1386         case TBM_FORMAT_ARGB8888:
1387         case TBM_FORMAT_ABGR8888:
1388         case TBM_FORMAT_RGBA8888:
1389         case TBM_FORMAT_BGRA8888:
1390             bpp = 32;
1391             _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1392             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1393             break;
1394         /* packed YCbCr */
1395         case TBM_FORMAT_YUYV:
1396         case TBM_FORMAT_YVYU:
1397         case TBM_FORMAT_UYVY:
1398         case TBM_FORMAT_VYUY:
1399         case TBM_FORMAT_AYUV:
1400             bpp = 32;
1401             _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1402             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1403             break;
1404         /*
1405         * 2 plane YCbCr
1406         * index 0 = Y plane, [7:0] Y
1407         * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1408         * or
1409         * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1410         */
1411         case TBM_FORMAT_NV12:
1412         case TBM_FORMAT_NV21:
1413             bpp = 12;
1414             //plane_idx == 0
1415             {
1416                 _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1417                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1418             }
1419             //plane_idx ==1
1420             {
1421                 _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1422                 _size += SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1423             }
1424             break;
1425         case TBM_FORMAT_NV16:
1426         case TBM_FORMAT_NV61:
1427             bpp = 16;
1428             //plane_idx == 0
1429             {
1430                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1431                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1432             }
1433             //plane_idx ==1
1434             {
1435                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1436                 _size += SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1437             }
1438
1439             break;
1440         /*
1441         * 3 plane YCbCr
1442         * index 0: Y plane, [7:0] Y
1443         * index 1: Cb plane, [7:0] Cb
1444         * index 2: Cr plane, [7:0] Cr
1445         * or
1446         * index 1: Cr plane, [7:0] Cr
1447         * index 2: Cb plane, [7:0] Cb
1448         */
1449         case TBM_FORMAT_YUV410:
1450         case TBM_FORMAT_YVU410:
1451             bpp = 9;
1452             align = TBM_SURFACE_ALIGNMENT_PITCH_YUV;
1453             break;
1454         case TBM_FORMAT_YUV411:
1455         case TBM_FORMAT_YVU411:
1456         case TBM_FORMAT_YUV420:
1457         case TBM_FORMAT_YVU420:
1458             bpp = 12;
1459             //plane_idx == 0
1460             {
1461                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1462                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1463             }
1464             //plane_idx == 1
1465             {
1466                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1467                 _size += SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1468             }
1469             //plane_idx == 2
1470             {
1471                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1472                 _size += SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1473             }
1474
1475             break;
1476         case TBM_FORMAT_YUV422:
1477         case TBM_FORMAT_YVU422:
1478             bpp = 16;
1479             //plane_idx == 0
1480             {
1481                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1482                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1483             }
1484             //plane_idx == 1
1485             {
1486                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1487                 _size += SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1488             }
1489             //plane_idx == 2
1490             {
1491                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1492                 _size += SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1493             }
1494             break;
1495         case TBM_FORMAT_YUV444:
1496         case TBM_FORMAT_YVU444:
1497             bpp = 24;
1498             align = TBM_SURFACE_ALIGNMENT_PITCH_YUV;
1499             break;
1500
1501         default:
1502             bpp = 0;
1503             break;
1504     }
1505
1506         if(_size > 0)
1507                 ret = _size;
1508         else
1509             ret =  SIZE_ALIGN( (width * height * bpp) >> 3, align);
1510
1511     return ret;
1512
1513 }
1514
1515 int
1516 tbm_sprd_surface_get_num_bos(tbm_format format)
1517 {
1518         int num = 0;
1519
1520     switch(format)
1521     {
1522         /* 16 bpp RGB */
1523         case TBM_FORMAT_XRGB4444:
1524         case TBM_FORMAT_XBGR4444:
1525         case TBM_FORMAT_RGBX4444:
1526         case TBM_FORMAT_BGRX4444:
1527         case TBM_FORMAT_ARGB4444:
1528         case TBM_FORMAT_ABGR4444:
1529         case TBM_FORMAT_RGBA4444:
1530         case TBM_FORMAT_BGRA4444:
1531         case TBM_FORMAT_XRGB1555:
1532         case TBM_FORMAT_XBGR1555:
1533         case TBM_FORMAT_RGBX5551:
1534         case TBM_FORMAT_BGRX5551:
1535         case TBM_FORMAT_ARGB1555:
1536         case TBM_FORMAT_ABGR1555:
1537         case TBM_FORMAT_RGBA5551:
1538         case TBM_FORMAT_BGRA5551:
1539         case TBM_FORMAT_RGB565:
1540         /* 24 bpp RGB */
1541         case TBM_FORMAT_RGB888:
1542         case TBM_FORMAT_BGR888:
1543         /* 32 bpp RGB */
1544         case TBM_FORMAT_XRGB8888:
1545         case TBM_FORMAT_XBGR8888:
1546         case TBM_FORMAT_RGBX8888:
1547         case TBM_FORMAT_BGRX8888:
1548         case TBM_FORMAT_ARGB8888:
1549         case TBM_FORMAT_ABGR8888:
1550         case TBM_FORMAT_RGBA8888:
1551         case TBM_FORMAT_BGRA8888:
1552         /* packed YCbCr */
1553         case TBM_FORMAT_YUYV:
1554         case TBM_FORMAT_YVYU:
1555         case TBM_FORMAT_UYVY:
1556         case TBM_FORMAT_VYUY:
1557         case TBM_FORMAT_AYUV:
1558         /*
1559         * 2 plane YCbCr
1560         * index 0 = Y plane, [7:0] Y
1561         * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1562         * or
1563         * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1564         */
1565         case TBM_FORMAT_NV12:
1566         case TBM_FORMAT_NV21:
1567         case TBM_FORMAT_NV16:
1568         case TBM_FORMAT_NV61:
1569         /*
1570         * 3 plane YCbCr
1571         * index 0: Y plane, [7:0] Y
1572         * index 1: Cb plane, [7:0] Cb
1573         * index 2: Cr plane, [7:0] Cr
1574         * or
1575         * index 1: Cr plane, [7:0] Cr
1576         * index 2: Cb plane, [7:0] Cb
1577         */
1578         case TBM_FORMAT_YUV410:
1579         case TBM_FORMAT_YVU410:
1580         case TBM_FORMAT_YUV411:
1581         case TBM_FORMAT_YVU411:
1582         case TBM_FORMAT_YUV420:
1583         case TBM_FORMAT_YVU420:
1584         case TBM_FORMAT_YUV422:
1585         case TBM_FORMAT_YVU422:
1586         case TBM_FORMAT_YUV444:
1587         case TBM_FORMAT_YVU444:
1588             num = 1;
1589             break;
1590
1591         default:
1592             num = 0;
1593             break;
1594     }
1595
1596     return num;
1597 }
1598
1599 MODULEINITPPROTO (init_tbm_bufmgr_priv);
1600
1601 static TBMModuleVersionInfo SprdVersRec =
1602 {
1603     "sprd",
1604     "Samsung",
1605     TBM_ABI_VERSION,
1606 };
1607
1608 TBMModuleData tbmModuleData = { &SprdVersRec, init_tbm_bufmgr_priv};
1609
1610 int
1611 init_tbm_bufmgr_priv (tbm_bufmgr bufmgr, int fd)
1612 {
1613     tbm_bufmgr_sprd bufmgr_sprd;
1614     tbm_bufmgr_backend bufmgr_backend;
1615
1616     if (!bufmgr)
1617         return 0;
1618
1619     bufmgr_sprd = calloc (1, sizeof(struct _tbm_bufmgr_sprd));
1620     if (!bufmgr_sprd)
1621     {
1622         TBM_SPRD_LOG ("[libtbm-sprd:%d] error: Fail to alloc bufmgr_sprd!\n", getpid());
1623         return 0;
1624     }
1625
1626     bufmgr_sprd->fd = fd;
1627     if (bufmgr_sprd->fd < 0)
1628     {
1629         TBM_SPRD_LOG ("[libtbm-sprd:%d] error: Fail to create drm!\n", getpid());
1630         free (bufmgr_sprd);
1631         return 0;
1632     }
1633
1634     //Create Hash Table
1635     bufmgr_sprd->hashBos = drmHashCreate ();
1636
1637     //Check if the tbm manager supports dma fence or not.
1638     int fp = open("/sys/module/dmabuf_sync/parameters/enabled", O_RDONLY);
1639     int length;
1640     char buf[1];
1641     if (fp != -1)
1642     {
1643         length = read(fp, buf, 1);
1644
1645         if (length == 1 && buf[0] == '1')
1646             bufmgr_sprd->use_dma_fence = 1;
1647
1648         close(fp);
1649     }
1650
1651     bufmgr_backend = tbm_backend_alloc();
1652     if (!bufmgr_backend)
1653     {
1654         TBM_SPRD_LOG ("[libtbm-sprd:%d] error: Fail to create drm!\n", getpid());
1655         free (bufmgr_sprd);
1656         return 0;
1657     }
1658
1659     bufmgr_backend->priv = (void *)bufmgr_sprd;
1660     bufmgr_backend->bufmgr_deinit = tbm_sprd_bufmgr_deinit,
1661     bufmgr_backend->bo_size = tbm_sprd_bo_size,
1662     bufmgr_backend->bo_alloc = tbm_sprd_bo_alloc,
1663     bufmgr_backend->bo_free = tbm_sprd_bo_free,
1664     bufmgr_backend->bo_import = tbm_sprd_bo_import,
1665     bufmgr_backend->bo_export = tbm_sprd_bo_export,
1666     bufmgr_backend->bo_get_handle = tbm_sprd_bo_get_handle,
1667     bufmgr_backend->bo_map = tbm_sprd_bo_map,
1668     bufmgr_backend->bo_unmap = tbm_sprd_bo_unmap,
1669     bufmgr_backend->bo_cache_flush = tbm_sprd_bo_cache_flush,
1670     bufmgr_backend->bo_get_global_key = tbm_sprd_bo_get_global_key;
1671     bufmgr_backend->surface_get_plane_data = tbm_sprd_surface_get_plane_data;
1672     bufmgr_backend->surface_get_size = tbm_sprd_surface_get_size;
1673     bufmgr_backend->surface_supported_format = tbm_sprd_surface_supported_format;
1674     bufmgr_backend->surface_get_num_bos = tbm_sprd_surface_get_num_bos;
1675
1676     if (bufmgr_sprd->use_dma_fence)
1677     {
1678         bufmgr_backend->flags = (TBM_LOCK_CTRL_BACKEND | TBM_CACHE_CTRL_BACKEND);
1679         bufmgr_backend->bo_lock = NULL;
1680         bufmgr_backend->bo_lock2 = tbm_sprd_bo_lock;
1681         bufmgr_backend->bo_unlock = tbm_sprd_bo_unlock;
1682     }
1683     else
1684     {
1685         bufmgr_backend->flags = 0;
1686         bufmgr_backend->bo_lock = NULL;
1687         bufmgr_backend->bo_unlock = NULL;
1688     }
1689
1690     if (!tbm_backend_init (bufmgr, bufmgr_backend))
1691     {
1692         TBM_SPRD_LOG ("[libtbm-sprd:%d] error: Fail to init backend!\n", getpid());
1693         tbm_backend_free (bufmgr_backend);
1694         free (bufmgr_sprd);
1695         return 0;
1696     }
1697
1698 #ifdef DEBUG
1699     {
1700         char* env;
1701         env = getenv ("TBM_SPRD_DEBUG");
1702         if (env)
1703         {
1704             bDebug = atoi (env);
1705             TBM_SPRD_LOG ("TBM_SPRD_DEBUG=%s\n", env);
1706         }
1707         else
1708         {
1709             bDebug = 0;
1710         }
1711     }
1712 #endif
1713
1714     DBG ("[libtbm-sprd:%d] %s DMABUF FENCE is %s\n", getpid(),
1715          __FUNCTION__, bufmgr_sprd->use_dma_fence ? "supported!" : "NOT supported!");
1716
1717     DBG ("[libtbm-sprd:%d] %s fd:%d\n", getpid(),
1718          __FUNCTION__, bufmgr_sprd->fd);
1719
1720     return 1;
1721 }
1722
1723