summaryrefslogtreecommitdiff
path: root/src/libcamera/pipeline/raspberrypi/dma_heaps.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcamera/pipeline/raspberrypi/dma_heaps.cpp')
-rw-r--r--src/libcamera/pipeline/raspberrypi/dma_heaps.cpp84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/libcamera/pipeline/raspberrypi/dma_heaps.cpp b/src/libcamera/pipeline/raspberrypi/dma_heaps.cpp
new file mode 100644
index 00000000..6769c046
--- /dev/null
+++ b/src/libcamera/pipeline/raspberrypi/dma_heaps.cpp
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020, Raspberry Pi (Trading) Limited
+ *
+ * dma_heaps.h - Helper class for dma-heap allocations.
+ */
+
+#include "dma_heaps.h"
+
+#include <fcntl.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-heap.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "libcamera/internal/log.h"
+
+/*
+ * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma
+ * to only have to worry about importing.
+ *
+ * Annoyingly, should the cma heap size be specified on the kernel command line
+ * instead of DT, the heap gets named "reserved" instead.
+ */
+#define DMA_HEAP_CMA_NAME "/dev/dma_heap/linux,cma"
+#define DMA_HEAP_CMA_ALT_NAME "/dev/dma_heap/reserved"
+
+namespace libcamera {
+
+LOG_DECLARE_CATEGORY(RPI)
+
+namespace RPi {
+
+DmaHeap::DmaHeap()
+{
+ dmaHeapHandle_ = ::open(DMA_HEAP_CMA_NAME, O_RDWR, 0);
+ if (dmaHeapHandle_ == -1) {
+ dmaHeapHandle_ = ::open(DMA_HEAP_CMA_ALT_NAME, O_RDWR, 0);
+ if (dmaHeapHandle_ == -1) {
+ LOG(RPI, Error) << "Could not open dmaHeap device";
+ }
+ }
+}
+
+DmaHeap::~DmaHeap()
+{
+ if (dmaHeapHandle_)
+ ::close(dmaHeapHandle_);
+}
+
+FileDescriptor DmaHeap::alloc(const char *name, std::size_t size)
+{
+ int ret;
+
+ if (!name)
+ return FileDescriptor();
+
+ struct dma_heap_allocation_data alloc = {};
+
+ alloc.len = size;
+ alloc.fd_flags = O_CLOEXEC | O_RDWR;
+
+ ret = ::ioctl(dmaHeapHandle_, DMA_HEAP_IOCTL_ALLOC, &alloc);
+
+ if (ret < 0) {
+ LOG(RPI, Error) << "dmaHeap allocation failure for "
+ << name;
+ return FileDescriptor();
+ }
+
+ ret = ::ioctl(alloc.fd, DMA_BUF_SET_NAME, name);
+ if (ret < 0) {
+ LOG(RPI, Error) << "dmaHeap naming failure for "
+ << name;
+ ::close(alloc.fd);
+ return FileDescriptor();
+ }
+
+ return FileDescriptor(std::move(alloc.fd));
+}
+
+} /* namespace RPi */
+
+} /* namespace libcamera */