blob: 50dd59e5591f5befebff069440ce81b8393c9356 [file] [log] [blame]
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*
* This source code is subject to the terms and conditions defined in the
* file 'LICENSE' which is part of this source code package.
*
* Description:
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <linux/stddef.h>
#include <linux/types.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <xf86drm.h>
#include "meson_drm.h"
#include "meson_drmif.h"
/*
* Create meson drm device object.
* @fd: file descriptor to meson drm driver opened.
*
* if true, returen the device object else NULL.
*/
struct meson_device *meson_device_create(int fd, int render_fd)
{
struct meson_device *dev;
dev = calloc(sizeof(*dev), 1);
if (!dev) {
fprintf(stderr, "failed to create device[%s].\n",
strerror(errno));
return NULL;
}
dev->fd = fd;
dev->render_fd = render_fd;
return dev;
}
/*
* Destroy meson drm device object
*
* @dev: meson drm device object.
*/
void meson_device_destroy(struct meson_device *dev)
{
free(dev);
}
/*
* Create a meson buffer object to meson drm device.
*
* @dev: meson drm device object.
* @size: buffer size.
* @flags: buffer allocation flag.
*
* user can set one or more flags to allocation specified buffer object
*
* if true, return a meson buffer object else NULL.
*/
struct meson_bo *meson_bo_create(struct meson_device *dev, size_t size,
uint32_t flags, int alloc_only)
{
int fd;
struct meson_bo *bo;
struct drm_meson_gem_create req = {
.size = size,
.flags = flags,
};
if (size == 0) {
fprintf(stderr, "invalid size.\n");
goto fail;
}
bo = calloc(sizeof(*bo), 1);
printf("meson_bo_create:%p\n",bo);
if (!bo) {
fprintf(stderr, "failed to create bo[%s].\n",
strerror(errno));
goto err_free_bo;
}
bo->dev = dev;
fd = alloc_only ? dev->render_fd : dev->fd;
if (drmIoctl(fd, DRM_IOCTL_MESON_GEM_CREATE, &req)) {
fprintf(stderr, "failed to create gem object[%s].\n",
strerror(errno));
goto err_free_bo;
}
bo->handle = req.handle;
bo->size = size;
bo->flags = flags;
return bo;
err_free_bo:
free(bo);
fail:
return NULL;
}
/*
* Destroy a meson buffer object.
* @bo: a meson buffer object to be destroyed.
*/
void meson_bo_destroy(struct meson_bo *bo)
{
printf("meson_bo_destroy:%p\n",bo);
if (!bo)
return;
if (bo->vaddr)
munmap(bo->vaddr, bo->size);
if (bo->fd)
close(bo->fd);
if (bo->handle) {
struct drm_gem_close req = {
.handle = bo->handle,
};
drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
}
free(bo);
}
uint32_t meson_bo_handle(struct meson_bo *bo)
{
return bo->handle;
}
int meson_bo_dmabuf(struct meson_bo *bo, int alloc_only)
{
int fd;
fd = alloc_only ? bo->dev->render_fd : bo->dev->fd;
if (!bo->fd) {
struct drm_prime_handle req = {
.handle = bo->handle,
.flags = DRM_CLOEXEC | DRM_RDWR,
};
int ret;
ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &req);
if (ret)
return ret;
bo->fd = req.fd;
}
return bo->fd;
}
size_t meson_bo_size(struct meson_bo *bo)
{
return bo->size;
}
struct meson_bo *meson_bo_import(struct meson_device *dev, int fd, size_t size, uint32_t flags)
{
int ret;
struct meson_bo *bo = NULL;
struct drm_prime_handle req = {
.fd = fd,
};
bo = calloc(sizeof(*bo), 1);
if (!bo) {
fprintf(stderr, "failed to create bo[%s].\n",
strerror(errno));
goto fail;
}
ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &req);
if (ret)
goto err_free_bo;
bo->dev = dev;
bo->size = size;
bo->flags = flags;
bo->handle = req.handle;
return bo;
err_free_bo:
free(bo);
fail:
return NULL;
}