2 * Copyright (C) 2016 Nexell Co., Ltd.
3 * Author: SeongO, Park <ray@nexell.co.kr>
17 #include <sys/types.h>
19 #include <sys/ioctl.h>
20 #include <sys/mman.h> // PROT_READ/PROT_WRITE/MAP_SHARED/mmap/munmap
22 #include <nexell/nexell_drm.h>
23 #include <nx_video_alloc.h>
25 #include <libdrm/drm_fourcc.h>
26 #include <linux/videodev2.h>
27 #include <linux/videodev2_nxp_media.h>
28 #ifdef TIZEN_FEATURE_ARTIK530
29 #include <tbm_bufmgr.h>
32 #include "nx_video_log.h"
34 #define DRM_DEVICE_NAME "/dev/dri/renderD128"
36 #define DRM_IOCTL_NR(n) _IOC_NR(n)
37 #define DRM_IOC_VOID _IOC_NONE
38 #define DRM_IOC_READ _IOC_READ
39 #define DRM_IOC_WRITE _IOC_WRITE
40 #define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE
41 #define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
44 drm_ioctl (int32_t drm_fd, uint32_t request, void *arg)
49 ret = ioctl (drm_fd, request, arg);
50 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
55 drm_command_write_read (int fd, uint32_t command_index,
56 void *data, uint32_t size)
60 request = DRM_IOC (DRM_IOC_READ | DRM_IOC_WRITE, DRM_IOCTL_BASE,
61 DRM_COMMAND_BASE + command_index, size);
62 if (drm_ioctl (fd, request, data))
71 alloc_gem (int drm_fd, int size, int flags)
73 struct nx_drm_gem_create arg = { 0, };
76 arg.size = (uint32_t) size;
79 ret = drm_command_write_read (drm_fd, DRM_NX_GEM_CREATE, &arg, sizeof (arg));
81 _E ("drm_command_write_read(errno=%d, flags=%d)\n", -ret, flags);
84 //_D ("[DRM ALLOC] gem %d, size %d, flags 0x%x\n", arg.handle, size, flags);
90 free_gem (int drm_fd, int gem)
92 struct drm_gem_close arg = { 0, };
95 drm_ioctl (drm_fd, DRM_IOCTL_GEM_CLOSE, &arg);
102 gem_to_dmafd (int drm_fd, int gem_fd)
105 struct drm_prime_handle arg = { 0, };
108 arg.flags = O_CLOEXEC | O_RDWR;
109 ret = drm_ioctl (drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg);
111 _E ("fail : get fd from gem:%d (DRM_IOCTL_PRIME_HANDLE_TO_FD)\n", ret);
118 get_flink_name (int fd, int gem)
120 struct drm_gem_flink arg = { 0, };
123 if (drm_ioctl (fd, DRM_IOCTL_GEM_FLINK, &arg)) {
124 _E ("fail : get flink from gem:%d (DRM_IOCTL_GEM_FLINK)\n", gem);
131 gem_from_flink (int fd, uint32_t flink_name)
133 struct drm_gem_open arg = { 0, };
134 /* struct nx_drm_gem_info info = { 0, }; */
136 arg.name = flink_name;
137 if (drm_ioctl (fd, DRM_IOCTL_GEM_OPEN, &arg)) {
138 _E ("fail : cannot open gem name=%d\n", flink_name);
146 // Nexell Private Video Memory Allocator for DRM
150 #define ALIGN(X,N) ( (X+N-1) & (~(N-1)) )
153 #define ALIGNED16(X) ALIGN(X,16)
156 // Nexell Private Memory Allocator
158 NX_AllocateMemory (int size, int align)
163 NX_MEMORY_INFO *pMem;
165 int drmFd = open (DRM_DEVICE_NAME, O_RDWR);
169 drmDropMaster (drmFd);
171 gemFd = alloc_gem (drmFd, size, flags);
175 dmaFd = gem_to_dmafd (drmFd, gemFd);
179 pMem = (NX_MEMORY_INFO *) calloc (1, sizeof (NX_MEMORY_INFO));
192 free_gem (drmFd, gemFd);
200 NX_FreeMemory (NX_MEMORY_INFO * pMem)
204 munmap (pMem->pBuffer, pMem->size);
207 free_gem (pMem->drmFd, pMem->gemFd);
215 // Video Specific Allocator Wrapper
217 // Suport Format & Planes
219 // 1 Plane : I420, NV12
224 NX_AllocateVideoMemory (void *bufmgr, int width, int height, int32_t planes, uint32_t format,
227 int gemFd[NX_MAX_PLANES] = { 0, };
228 int dmaFd[NX_MAX_PLANES] = { 0, };
229 #ifdef TIZEN_FEATURE_ARTIK530
230 int32_t flags = NEXELL_BO_DMA, i = 0;
232 int32_t flags = 0, i = 0;
234 int32_t luStride, cStride;
235 int32_t luVStride, cVStride;
236 int32_t stride[NX_MAX_PLANES];
237 int32_t size[NX_MAX_PLANES];
238 uint32_t flink[NX_MAX_PLANES];
239 #ifdef TIZEN_FEATURE_ARTIK530
240 tbm_surface_info_s info;
243 NX_VID_MEMORY_INFO *pVidMem = NULL;
245 int drmFd = open (DRM_DEVICE_NAME, O_RDWR);
249 drmDropMaster (drmFd);
252 luStride = ALIGN (width, 32);
253 luVStride = ALIGN (height, 16);
257 case DRM_FORMAT_YUV420:
258 case DRM_FORMAT_NV12:
259 case DRM_FORMAT_NV21:
260 case V4L2_PIX_FMT_YUV420M:
261 case V4L2_PIX_FMT_NV12M:
262 case V4L2_PIX_FMT_NV21M:
263 cStride = luStride / 2;
264 cVStride = ALIGN (height / 2, 16);
267 case DRM_FORMAT_YUV422:
268 case DRM_FORMAT_NV16:
269 case DRM_FORMAT_NV61:
270 case V4L2_PIX_FMT_YUV422M:
271 #if 0 // Disabled by DIGNSYS
272 case V4L2_PIX_FMT_NV16M:
273 case V4L2_PIX_FMT_NV61M:
275 cStride = luStride / 2;
276 cVStride = luVStride;
279 case DRM_FORMAT_YUV444:
280 //case DRM_FORMAT_NV24:
281 //case DRM_FORMAT_NV42:
282 case V4L2_PIX_FMT_YUV444M:
283 case V4L2_PIX_FMT_NV24M:
284 case V4L2_PIX_FMT_NV42M:
286 cVStride = luVStride;
289 case V4L2_PIX_FMT_GREY:
294 _E ("Unknown format type\n");
298 // Decide Memory Size
301 size[0] = luStride * luVStride + cStride * cVStride * 2;
302 stride[0] = luStride;
303 gemFd[0] = alloc_gem (drmFd, size[0], flags);
306 dmaFd[0] = gem_to_dmafd (drmFd, gemFd[0]);
312 size[0] = luStride * luVStride;
313 stride[0] = luStride;
314 gemFd[0] = alloc_gem (drmFd, size[0], flags);
317 dmaFd[0] = gem_to_dmafd (drmFd, gemFd[0]);
322 size[1] = cStride * cVStride * 2;
323 stride[1] = cStride * 2;
324 gemFd[1] = alloc_gem (drmFd, size[1], flags);
327 dmaFd[1] = gem_to_dmafd (drmFd, gemFd[1]);
333 size[0] = luStride * luVStride;
334 stride[0] = luStride;
335 gemFd[0] = alloc_gem (drmFd, size[0], flags);
338 dmaFd[0] = gem_to_dmafd (drmFd, gemFd[0]);
343 size[1] = cStride * cVStride;
345 gemFd[1] = alloc_gem (drmFd, size[1], flags);
348 dmaFd[1] = gem_to_dmafd (drmFd, gemFd[1]);
353 size[2] = cStride * cVStride;
355 gemFd[2] = alloc_gem (drmFd, size[2], flags);
358 dmaFd[2] = gem_to_dmafd (drmFd, gemFd[2]);
365 pVidMem = (NX_VID_MEMORY_INFO *) calloc (1, sizeof (NX_VID_MEMORY_INFO));
369 pVidMem->width = width;
370 pVidMem->height = height;
371 pVidMem->align = align;
372 pVidMem->planes = planes;
373 pVidMem->format = format;
374 pVidMem->drmFd = drmFd;
376 #ifdef TIZEN_FEATURE_ARTIK530
378 info.height = height;
379 info.format = TBM_FORMAT_YUV420;
382 info.planes[0].stride = luStride;
383 info.planes[0].size = luStride * luVStride;
384 info.planes[0].offset = 0;
385 info.planes[1].stride = cStride;
386 info.planes[1].size = cStride * cVStride;
387 info.planes[1].offset = info.planes[0].size;
388 info.planes[2].stride = cStride;
389 info.planes[2].size = cStride * cVStride;
390 info.planes[2].offset = info.planes[1].offset + info.planes[1].size;
392 for (i = 0; i < planes; i++) {
393 pVidMem->dmaFd[i] = dmaFd[i];
394 pVidMem->gemFd[i] = gemFd[i];
395 pVidMem->size[i] = size[i];
396 pVidMem->stride[i] = stride[i];
397 #ifdef TIZEN_FEATURE_ARTIK530
398 pVidMem->bo[i] = tbm_bo_import_fd (bufmgr, dmaFd[i]);
403 #ifdef TIZEN_FEATURE_ARTIK530
404 pVidMem->surface = tbm_surface_internal_create_with_bos (&info, (tbm_bo *)pVidMem->bo, planes);
405 if (!pVidMem->surface)
411 #ifdef TIZEN_FEATURE_ARTIK530
413 for (i = 0; i < planes; i++) {
415 tbm_bo_unref (pVidMem->bo[i]);
420 for (i = 0; i < planes; i++) {
422 free_gem (drmFd, gemFd[i]);
438 NX_FreeVideoMemory (NX_VID_MEMORY_INFO * pMem)
442 for (i = 0; i < pMem->planes; i++) {
443 #ifdef TIZEN_FEATURE_ARTIK530
445 tbm_bo_unref (pMem->bo[i]);
447 if (pMem->pBuffer[i]) {
448 munmap (pMem->pBuffer[i], pMem->size[i]);
450 free_gem (pMem->drmFd, pMem->gemFd[i]);
451 close (pMem->dmaFd[i]);
453 #ifdef TIZEN_FEATURE_ARTIK530
455 tbm_surface_internal_destroy (pMem->surface);
464 // Memory Mapping/Unmapping Memory
467 NX_MapMemory (NX_MEMORY_INFO * pMem)
478 (char *) mmap (0, pMem->size, PROT_READ | PROT_WRITE, MAP_SHARED, pMem->dmaFd, 0);
479 if (pBuf == MAP_FAILED) {
480 _E ("Map failed : size %d, fd %d", pMem->size, pMem->dmaFd);
483 pMem->pBuffer = pBuf;
489 NX_UnmapMemory (NX_MEMORY_INFO * pMem)
497 if (0 != munmap (pMem->pBuffer, pMem->size))
500 pMem->pBuffer = NULL;
505 NX_MapVideoMemory (NX_VID_MEMORY_INFO * pMem)
513 for (i = 0; i < pMem->planes; i++) {
514 if (pMem->pBuffer[i])
518 (char *) mmap (0, pMem->size[i], PROT_READ | PROT_WRITE, MAP_SHARED,
520 if (pBuf == MAP_FAILED) {
524 pMem->pBuffer[i] = pBuf;
530 NX_UnmapVideoMemory (NX_VID_MEMORY_INFO * pMem)
535 for (i = 0; i < pMem->planes; i++) {
536 if (pMem->pBuffer[i]) {
537 munmap (pMem->pBuffer[i], pMem->size[i]);
545 NX_GetGEMHandles (int drmFd, NX_VID_MEMORY_INFO * pMem,
546 uint32_t handles[NX_MAX_PLANES])
549 memset (handles, 0, sizeof (uint32_t) * NX_MAX_PLANES);
551 for (i = 0; i < pMem->planes; i++) {
552 handles[i] = gem_from_flink (drmFd, pMem->flink[i]);
553 if (0 > (int) handles[i]) {
561 NX_GetGemHandle (int drmFd, NX_VID_MEMORY_INFO * pMem, int32_t plane)
563 if (plane >= NX_MAX_PLANES || plane < 0)
566 return gem_from_flink (drmFd, pMem->flink[plane]);