summaryrefslogtreecommitdiff
path: root/src/libcamera
diff options
context:
space:
mode:
authorNaushir Patuck <naush@raspberrypi.com>2020-07-15 10:39:11 +0100
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-07-17 16:36:28 +0300
commit3e7aa49344ad5233f644703559898572b57f9613 (patch)
tree579857871a6bff875f06579b5faf3910c24c90ce /src/libcamera
parent3c02a808e8934a0c2d875d5585403ce0a09d7c93 (diff)
libcamera: pipeline: ipa: raspberrypi: Use dma heap allocs for LS tables
Remove use of vcsm allocations and replace with dma heap allocations. The pipeline handler now passes the fd of the allocation over to the IPA instead of the raw pointer. Also use libcamera::FileDescriptor for fd lifetime management. This commit must be built alongside the accompanying BCM2835 ISP kernel driver changes at https://github.com/raspberrypi/linux/pull/3715. Otherwise a mismatch will cause undefined behavior. Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
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__ */