diff options
Diffstat (limited to 'src/libcamera/pipeline/raspberrypi')
-rw-r--r-- | src/libcamera/pipeline/raspberrypi/dma_heaps.cpp | 84 | ||||
-rw-r--r-- | src/libcamera/pipeline/raspberrypi/dma_heaps.h | 31 | ||||
-rw-r--r-- | src/libcamera/pipeline/raspberrypi/meson.build | 1 | ||||
-rw-r--r-- | src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 49 | ||||
-rw-r--r-- | src/libcamera/pipeline/raspberrypi/vcsm.h | 149 |
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__ */ |