blob: f73eed3f631e10983176e2d8aca6d9046de8fce8 [file] [log] [blame]
/*
* # Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include "gstionallocator.h"
#include "ion_coral.h"
GST_DEBUG_CATEGORY_STATIC (ion_debug);
#define GST_CAT_DEFAULT ion_debug
#define gst_allocator_ion_parent_class parent_class
G_DEFINE_TYPE (GstAllocatorIon, gst_allocator_ion, GST_TYPE_DMABUF_ALLOCATOR);
static void gst_allocator_ion_finalize (GObject * object);
static GstMemory * gst_allocator_ion_alloc (GstAllocator * allocator,
gsize size,GstAllocationParams * params);
static void
gst_allocator_ion_class_init (GstAllocatorIonClass * klass)
{
GST_ALLOCATOR_CLASS (klass)->alloc = gst_allocator_ion_alloc;
G_OBJECT_CLASS (klass)->finalize = gst_allocator_ion_finalize;
GST_DEBUG_CATEGORY_INIT (ion_debug, "ion", 0,
"Linux dma-buf allocator based on ION");
}
static void
gst_allocator_ion_init (GstAllocatorIon * ion)
{
GstAllocator *allocator = GST_ALLOCATOR (ion);
allocator->mem_type = GST_ALLOCATOR_ION_NAME;
ion->fd = -1;
ion->heap_mask = -1;
g_mutex_init (&ion->mutex);
}
static void
gst_allocator_ion_finalize (GObject * object)
{
GstAllocatorIon *ion = GST_ALLOCATOR_ION (object);
if (ion->fd > -1) {
close (ion->fd);
ion->fd = -1;
}
g_mutex_clear (&ion->mutex);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
gboolean
gst_allocator_ion_init_check (GstAllocatorIon * ion)
{
int fd, buf_fd, heap_mask, i;
gboolean success;
struct ion_heap_query query;
struct ion_allocation_data alloc_data;
struct ion_heap_data *heap_data = NULL;
g_mutex_lock (&ion->mutex);
fd = 1;
buf_fd = -1;
heap_mask = 0;
success = FALSE;
if (ion->fd > -1) {
GST_DEBUG_OBJECT (ion, "Already initialized");
goto beach;
}
GST_DEBUG_OBJECT (ion, "Opening /dev/ion");
fd = open ("/dev/ion", O_RDWR);
if (fd == -1) {
GST_INFO_OBJECT (ion, "ION allocator not supported");
g_mutex_unlock (&ion->mutex);
return FALSE;
}
GST_DEBUG_OBJECT (ion, "/dev/ion opened with fd=%d", fd);
memset (&query, 0, sizeof(query));
if (ioctl (fd, ION_IOC_HEAP_QUERY, &query) < 0) {
GST_ERROR_OBJECT (ion, "ION_IOC_HEAP_QUERY failed: %d", errno);
goto beach;
}
GST_DEBUG_OBJECT (ion, "ION_IOC_HEAP_QUERY returned %u heaps", query.cnt);
heap_data = g_malloc0_n (query.cnt, sizeof(*heap_data));
query.heaps = (uintptr_t) heap_data;
if (ioctl (fd, ION_IOC_HEAP_QUERY, &query) < 0) {
GST_ERROR_OBJECT (ion, "ION_IOC_HEAP_QUERY failed: %d", errno);
goto beach;
}
for (i = 0; i < query.cnt; ++i) {
if (heap_data[i].type == ION_HEAP_TYPE_DMA) {
heap_mask |= 1 << heap_data[i].heap_id;
}
}
memset (&alloc_data, 0, sizeof(alloc_data));
alloc_data.len = 42;
alloc_data.heap_id_mask = heap_mask;
alloc_data.flags = ION_FLAG_CACHED;
if (ioctl (fd, ION_IOC_ALLOC, &alloc_data) < 0) {
GST_ERROR_OBJECT (ion, "ION_IOC_ALLOC failed: %d", errno);
goto beach;
}
buf_fd = alloc_data.fd;
beach:
success = buf_fd != -1;
if (success) {
close (buf_fd);
ion->fd = fd;
ion->heap_mask = heap_mask;
GST_INFO_OBJECT (ion, "ION allocator initialized");
} else {
GST_ERROR_OBJECT (ion, "ION allocator initialization failed");
}
g_mutex_unlock (&ion->mutex);
return success;
}
static GstMemory *
gst_allocator_ion_alloc (GstAllocator * allocator, gsize size,
GstAllocationParams * params)
{
GstAllocatorIon *ion = GST_ALLOCATOR_ION (allocator);
struct ion_allocation_data alloc_data = { 0 };
alloc_data.len = size;
alloc_data.heap_id_mask = ion->heap_mask;
alloc_data.flags = ION_FLAG_CACHED;
if (ioctl (ion->fd, ION_IOC_ALLOC, &alloc_data) < 0) {
GST_ERROR_OBJECT (ion, "ION_IOC_ALLOC failed: %d", errno);
return NULL;
}
GST_DEBUG_OBJECT (ion, "allocated size %" G_GSIZE_FORMAT " b, fd %d",
size, alloc_data.fd);
return gst_dmabuf_allocator_alloc (allocator, alloc_data.fd, size);
}
gboolean gst_allocator_ion_init_check (GstAllocatorIon * ion);