Files
2026-08-24 10:03:24 +08:00

208 lines
4.6 KiB
C

/*
* 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 <linux/amlogic/drm/meson_drm.h>
#include "meson_drmif.h"
#include "meson_drm_log.h"
#define LOG_NDEBUG 0
#define LOG_TAG "meson_drm"
/*
* 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) {
MESON_ALOGE("%s %d failed to create device[%s].\n",__FUNCTION__,__LINE__,
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) {
MESON_ALOGE("%s %d invalid size.\n",__FUNCTION__,__LINE__);
goto fail;
}
bo = calloc(sizeof(*bo), 1);
MESON_ALOGD("%s %d meson_bo_create:%p\n",__FUNCTION__,__LINE__,bo);
if (!bo) {
MESON_ALOGE("%s %d failed to create bo[%s].\n",__FUNCTION__,__LINE__,
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)) {
MESON_ALOGE("%s %d failed to create gem object[%s].\n",__FUNCTION__,__LINE__,
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)
{
MESON_ALOGD("%s %d meson_bo_destroy:%p\n",__FUNCTION__,__LINE__,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 ready_only)
{
int fd = alloc_only ? bo->dev->render_fd : bo->dev->fd;
MESON_ALOGD("%s, bo is %p, alloc_only is %d.\n", __func__, bo, alloc_only);
if (!bo->fd) {
struct drm_prime_handle req = {
.handle = bo->handle,
.flags = DRM_CLOEXEC | DRM_RDWR,
};
int ret;
if (ready_only)
req.flags = MESON_RDONLY;
else
req.flags = DRM_CLOEXEC | DRM_RDWR;
ret = drmIoctl(fd, DRM_IOCTL_MESON_PRIME_HANDLE_TO_FD, &req);
if (ret) {
MESON_ALOGE("%s, FD_TO_HANDLE error return is %d.\n", __func__, 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) {
MESON_ALOGE("%s %d failed to create bo[%s].\n",__FUNCTION__,__LINE__,
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;
}