You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
3.2 KiB
181 lines
3.2 KiB
#include <ion/ion.h>
|
|
#include <linux/ion_4.12.h>
|
|
|
|
#include "ion.h"
|
|
|
|
int ion_get_heap_id(int ion_fd, uint32_t heap_type)
|
|
{
|
|
int heap_count = 0;
|
|
int ret = -1;
|
|
|
|
if (ion_query_heap_cnt(ion_fd, &heap_count))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
struct ion_heap_data *heap_data =
|
|
malloc(heap_count * sizeof(struct ion_heap_data));
|
|
|
|
if (ion_query_get_heaps(ion_fd, heap_count, heap_data))
|
|
{
|
|
free(heap_data);
|
|
return -1;
|
|
}
|
|
|
|
for (struct ion_heap_data *hi = heap_data;
|
|
(hi - heap_data) < heap_count;
|
|
++hi)
|
|
{
|
|
if (hi->type == heap_type)
|
|
{
|
|
ret = hi->heap_id;
|
|
break;
|
|
}
|
|
}
|
|
|
|
free(heap_data);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static const int kBitsInAnInt = (sizeof(int) * 8);
|
|
|
|
int ion_alloc_one_fd(int ion_fd, size_t size, int heap_id, int *ion_buffer_fd)
|
|
{
|
|
if (heap_id < 0 || heap_id >= kBitsInAnInt)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
const int align = 0;
|
|
const int heap_mask = 1 << heap_id;
|
|
const int flags = 0;
|
|
|
|
return ion_alloc_fd(ion_fd, size, align, heap_mask, flags, ion_buffer_fd);
|
|
}
|
|
|
|
int ion_mmap(void **ptr, int ion_buffer_fd, size_t size)
|
|
{
|
|
void *const k_addr = 0;
|
|
const int k_prot = PROT_READ | PROT_WRITE;
|
|
const int k_flags = MAP_SHARED;
|
|
|
|
void *ret = mmap(k_addr, size, k_prot, k_flags, ion_buffer_fd, 0);
|
|
|
|
if (ret == MAP_FAILED)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
*ptr = ret;
|
|
return 0;
|
|
}
|
|
|
|
int ion_munmap(void *ptr, size_t size)
|
|
{
|
|
if (munmap(ptr, size))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int drm_check_prime_caps(int drm_fd)
|
|
{
|
|
struct drm_get_cap drm_get_cap_arg = {
|
|
.capability = DRM_CAP_PRIME,
|
|
.value = 0
|
|
};
|
|
|
|
if (drmIoctl(drm_fd, DRM_IOCTL_GET_CAP, &drm_get_cap_arg))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (!(drm_get_cap_arg.value & DRM_PRIME_CAP_IMPORT) ||
|
|
!(drm_get_cap_arg.value & DRM_PRIME_CAP_EXPORT))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int gem_handle_for_ion_buffer(int drm_fd, uint32_t *gem_handle, int ion_buffer_fd)
|
|
{
|
|
struct drm_prime_handle drm_prime_fd_to_handle_arg = {
|
|
.handle = 0,
|
|
.flags = 0,
|
|
.fd = ion_buffer_fd
|
|
};
|
|
|
|
if (drmIoctl(drm_fd,
|
|
DRM_IOCTL_PRIME_FD_TO_HANDLE,
|
|
&drm_prime_fd_to_handle_arg))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
*gem_handle = drm_prime_fd_to_handle_arg.handle;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ion_fd_for_gem_handle(int drm_fd, int *ion_fd, uint32_t gem_handle)
|
|
{
|
|
struct drm_prime_handle drm_prime_handle_to_fd_arg = {
|
|
.handle = gem_handle,
|
|
.flags = 0,
|
|
.fd = 0
|
|
};
|
|
|
|
if (drmIoctl(drm_fd,
|
|
DRM_IOCTL_PRIME_HANDLE_TO_FD,
|
|
&drm_prime_handle_to_fd_arg))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
*ion_fd = drm_prime_handle_to_fd_arg.fd;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int drm_fb_for_ion_buffer(int drm_fd, uint32_t *fb_id, int ion_buffer_fd,
|
|
const struct fb_configuration *fb_config)
|
|
{
|
|
uint32_t gem_handle = 0;
|
|
|
|
if (gem_handle_for_ion_buffer(drm_fd, &gem_handle, ion_buffer_fd))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int ret = drm_fb_for_gem_handle(drm_fd, fb_id, gem_handle, fb_config);
|
|
|
|
gem_release_handle(drm_fd, gem_handle);
|
|
return ret;
|
|
}
|
|
|
|
void drm_release_fb(int drm_fd, uint32_t fb_id)
|
|
{
|
|
(void)drmIoctl(drm_fd, DRM_IOCTL_MODE_RMFB, &fb_id);
|
|
}
|
|
|
|
int ion_clone_fd_via_gem(int drm_fd, int *cloned_fd, int ion_buffer_fd)
|
|
{
|
|
uint32_t gem_handle = 0;
|
|
if (gem_handle_for_ion_buffer(drm_fd, &gem_handle, ion_buffer_fd))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int ret = ion_fd_for_gem_handle(drm_fd, cloned_fd, gem_handle);
|
|
gem_release_handle(drm_fd, gem_handle);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|