summaryrefslogtreecommitdiff
path: root/src/libcamera
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcamera')
-rw-r--r--src/libcamera/pipeline/raspberrypi/dma_heaps.cpp84
-rw-r--r--src/libcamera/pipeline/raspberrypi/dma_heaps.h31
-rw-r--r--src/libcamera/pipeline/raspberrypi/meson.build1
-rw-r--r--src/libcamera/pipeline/raspberrypi/raspberrypi.cpp49
-rw-r--r--src/libcamera/pipeline/raspberrypi/vcsm.h149
5 files changed, 129 insertions, 185 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 */
diff --git a/src/libcamera/pipeline/raspberrypi/dma_heaps.h b/src/libcamera/pipeline/raspberrypi/dma_heaps.h
new file mode 100644
index 00000000..ae6be113
--- /dev/null
+++ b/src/libcamera/pipeline/raspberrypi/dma_heaps.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020, Raspberry Pi (Trading) Limited
+ *
+ * dma_heaps.h - Helper class for dma-heap allocations.
+ */
+#ifndef __LIBCAMERA_PIPELINE_RASPBERRYPI_DMA_HEAPS_H__
+#define __LIBCAMERA_PIPELINE_RASPBERRYPI_DMA_HEAPS_H__
+
+#include <libcamera/file_descriptor.h>
+
+namespace libcamera {
+
+namespace RPi {
+
+class DmaHeap
+{
+public:
+ DmaHeap();
+ ~DmaHeap();
+ FileDescriptor alloc(const char *name, std::size_t size);
+
+private:
+ int dmaHeapHandle_;
+};
+
+} /* namespace RPi */
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_PIPELINE_RASPBERRYPI_DMA_HEAPS_H__ */
diff --git a/src/libcamera/pipeline/raspberrypi/meson.build b/src/libcamera/pipeline/raspberrypi/meson.build
index dcfe07c5..ae0aed3b 100644
--- a/src/libcamera/pipeline/raspberrypi/meson.build
+++ b/src/libcamera/pipeline/raspberrypi/meson.build
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: CC0-1.0
libcamera_sources += files([
+ 'dma_heaps.cpp',
'raspberrypi.cpp',
'staggered_ctrl.cpp',
])
diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
index 718749af..bf1c7714 100644
--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
@@ -13,6 +13,7 @@
#include <libcamera/camera.h>
#include <libcamera/control_ids.h>
+#include <libcamera/file_descriptor.h>
#include <libcamera/formats.h>
#include <libcamera/ipa/raspberrypi.h>
#include <libcamera/logging.h>
@@ -31,8 +32,8 @@
#include "libcamera/internal/v4l2_controls.h"
#include "libcamera/internal/v4l2_videodevice.h"
+#include "dma_heaps.h"
#include "staggered_ctrl.h"
-#include "vcsm.h"
namespace libcamera {
@@ -286,24 +287,11 @@ class RPiCameraData : public CameraData
{
public:
RPiCameraData(PipelineHandler *pipe)
- : CameraData(pipe), sensor_(nullptr), lsTable_(nullptr),
- state_(State::Stopped), dropFrame_(false), ispOutputCount_(0)
+ : CameraData(pipe), sensor_(nullptr), state_(State::Stopped),
+ dropFrame_(false), ispOutputCount_(0)
{
}
- ~RPiCameraData()
- {
- /*
- * Free the LS table if we have allocated one. Another
- * allocation will occur in applyLS() with the appropriate
- * size.
- */
- if (lsTable_) {
- vcsm_.free(lsTable_);
- lsTable_ = nullptr;
- }
- }
-
void frameStarted(uint32_t sequence);
int loadIPA();
@@ -329,9 +317,9 @@ public:
/* Buffers passed to the IPA. */
std::vector<IPABuffer> ipaBuffers_;
- /* VCSM allocation helper. */
- ::RPi::Vcsm vcsm_;
- void *lsTable_;
+ /* DMAHEAP allocation helper. */
+ RPi::DmaHeap dmaHeap_;
+ FileDescriptor lsTable_;
RPi::StaggeredCtrl staggeredCtrl_;
uint32_t expectedSequence_;
@@ -1142,26 +1130,15 @@ int RPiCameraData::configureIPA()
entityControls.emplace(0, unicam_[Unicam::Image].dev()->controls());
entityControls.emplace(1, isp_[Isp::Input].dev()->controls());
- /* Allocate the lens shading table via vcsm and pass to the IPA. */
- if (!lsTable_) {
- lsTable_ = vcsm_.alloc("ls_grid", MAX_LS_GRID_SIZE);
- uintptr_t ptr = reinterpret_cast<uintptr_t>(lsTable_);
-
- if (!lsTable_)
+ /* Allocate the lens shading table via dmaHeap and pass to the IPA. */
+ if (!lsTable_.isValid()) {
+ lsTable_ = dmaHeap_.alloc("ls_grid", MAX_LS_GRID_SIZE);
+ if (!lsTable_.isValid())
return -ENOMEM;
- /*
- * The vcsm allocation will always be in the memory region
- * < 32-bits to allow Videocore to access the memory.
- *
- * \todo Sending a pointer to the IPA is a workaround for
- * vc_sm_cma not yet supporting dmabuf. This will not work with
- * IPA module isolation and should be reworked when vc_sma_cma
- * will permit.
- */
+ /* Allow the IPA to mmap the LS table via the file descriptor. */
ipaConfig.operation = RPI_IPA_CONFIG_LS_TABLE;
- ipaConfig.data = { static_cast<uint32_t>(ptr & 0xffffffff),
- vcsm_.getVCHandle(lsTable_) };
+ ipaConfig.data = { static_cast<unsigned int>(lsTable_.fd()) };
}
CameraSensorInfo sensorInfo = {};
diff --git a/src/libcamera/pipeline/raspberrypi/vcsm.h b/src/libcamera/pipeline/raspberrypi/vcsm.h
deleted file mode 100644
index bebe86a7..00000000
--- a/src/libcamera/pipeline/raspberrypi/vcsm.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2019, Raspberry Pi (Trading) Limited
- *
- * vcsm.h - Helper class for vcsm allocations.
- */
-#ifndef __LIBCAMERA_PIPELINE_RASPBERRYPI_VCSM_H__
-#define __LIBCAMERA_PIPELINE_RASPBERRYPI_VCSM_H__
-
-#include <iostream>
-#include <mutex>
-
-#include <fcntl.h>
-#include <linux/vc_sm_cma_ioctl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-namespace RPi {
-
-#define VCSM_CMA_DEVICE_NAME "/dev/vcsm-cma"
-
-class Vcsm
-{
-public:
- Vcsm()
- {
- vcsmHandle_ = ::open(VCSM_CMA_DEVICE_NAME, O_RDWR, 0);
- if (vcsmHandle_ == -1) {
- std::cerr << "Could not open vcsm device: "
- << VCSM_CMA_DEVICE_NAME;
- }
- }
-
- ~Vcsm()
- {
- /* Free all existing allocations. */
- auto it = allocMap_.begin();
- while (it != allocMap_.end())
- it = remove(it->first);
-
- if (vcsmHandle_)
- ::close(vcsmHandle_);
- }
-
- void *alloc(const char *name, unsigned int size,
- vc_sm_cma_cache_e cache = VC_SM_CMA_CACHE_NONE)
- {
- unsigned int pageSize = getpagesize();
- void *user_ptr;
- int ret;
-
- if (!name)
- return nullptr;
-
- /* Ask for page aligned allocation. */
- size = (size + pageSize - 1) & ~(pageSize - 1);
-
- struct vc_sm_cma_ioctl_alloc alloc;
- memset(&alloc, 0, sizeof(alloc));
- alloc.size = size;
- alloc.num = 1;
- alloc.cached = cache;
- alloc.handle = 0;
- memcpy(alloc.name, name, 32);
-
- ret = ::ioctl(vcsmHandle_, VC_SM_CMA_IOCTL_MEM_ALLOC, &alloc);
-
- if (ret < 0 || alloc.handle < 0) {
- std::cerr << "vcsm allocation failure for "
- << name << std::endl;
- return nullptr;
- }
-
- /* Map the buffer into user space. */
- user_ptr = ::mmap(0, alloc.size, PROT_READ | PROT_WRITE,
- MAP_SHARED, alloc.handle, 0);
-
- if (user_ptr == MAP_FAILED) {
- std::cerr << "vcsm mmap failure for " << name << std::endl;
- ::close(alloc.handle);
- return nullptr;
- }
-
- std::lock_guard<std::mutex> lock(lock_);
- allocMap_.emplace(user_ptr, AllocInfo(alloc.handle,
- alloc.size, alloc.vc_handle));
-
- return user_ptr;
- }
-
- void free(void *user_ptr)
- {
- std::lock_guard<std::mutex> lock(lock_);
- remove(user_ptr);
- }
-
- unsigned int getVCHandle(void *user_ptr)
- {
- std::lock_guard<std::mutex> lock(lock_);
- auto it = allocMap_.find(user_ptr);
- if (it != allocMap_.end())
- return it->second.vcHandle;
-
- return 0;
- }
-
-private:
- struct AllocInfo {
- AllocInfo(int handle_, int size_, int vcHandle_)
- : handle(handle_), size(size_), vcHandle(vcHandle_)
- {
- }
-
- int handle;
- int size;
- uint32_t vcHandle;
- };
-
- /* Map of all allocations that have been requested. */
- using AllocMap = std::map<void *, AllocInfo>;
-
- AllocMap::iterator remove(void *user_ptr)
- {
- auto it = allocMap_.find(user_ptr);
- if (it != allocMap_.end()) {
- int handle = it->second.handle;
- int size = it->second.size;
- ::munmap(user_ptr, size);
- ::close(handle);
- /*
- * Remove the allocation from the map. This returns
- * an iterator to the next element.
- */
- it = allocMap_.erase(it);
- }
-
- /* Returns an iterator to the next element. */
- return it;
- }
-
- AllocMap allocMap_;
- int vcsmHandle_;
- std::mutex lock_;
-};
-
-} /* namespace RPi */
-
-#endif /* __LIBCAMERA_PIPELINE_RASPBERRYPI_VCSM_H__ */