diff options
author | Jacopo Mondi <jacopo.mondi@ideasonboard.com> | 2025-01-02 16:07:52 +0100 |
---|---|---|
committer | Jacopo Mondi <jacopo.mondi@ideasonboard.com> | 2025-01-03 12:33:44 +0100 |
commit | f1fd445d619be6ea5baf40d784f6c797e0055f5b (patch) | |
tree | f4509af8ad0c96f835c75f165c7785e41536e399 | |
parent | 35ed4b91291d9f3d08e4b51acfb51163e65df8f8 (diff) |
libcamera: introduce rcar-gen4 supportrcar-gen4
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
-rw-r--r-- | meson_options.txt | 1 | ||||
-rw-r--r-- | src/libcamera/pipeline/rcar-gen4/meson.build | 5 | ||||
-rw-r--r-- | src/libcamera/pipeline/rcar-gen4/rcar-gen4.cpp | 240 |
3 files changed, 246 insertions, 0 deletions
diff --git a/meson_options.txt b/meson_options.txt index 1dc3b4cd..2977aaff 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -49,6 +49,7 @@ option('pipelines', 'imx8-isi', 'ipu3', 'mali-c55', + 'rcar-gen4', 'rkisp1', 'rpi/vc4', 'simple', diff --git a/src/libcamera/pipeline/rcar-gen4/meson.build b/src/libcamera/pipeline/rcar-gen4/meson.build new file mode 100644 index 00000000..1d514677 --- /dev/null +++ b/src/libcamera/pipeline/rcar-gen4/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: CC0-1.0 + +libcamera_internal_sources += files([ + 'rcar-gen4.cpp', +]) diff --git a/src/libcamera/pipeline/rcar-gen4/rcar-gen4.cpp b/src/libcamera/pipeline/rcar-gen4/rcar-gen4.cpp new file mode 100644 index 00000000..9e5b4419 --- /dev/null +++ b/src/libcamera/pipeline/rcar-gen4/rcar-gen4.cpp @@ -0,0 +1,240 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Ideas On Board Oy + * + * Pipeline handler for Renesas R-Car Gen4 + */ + +#include <memory> +#include <string> + +#include <libcamera/stream.h> + +#include "libcamera/internal/camera.h" +#include "libcamera/internal/device_enumerator.h" +#include "libcamera/internal/media_device.h" +#include "libcamera/internal/pipeline_handler.h" +#include "libcamera/internal/v4l2_subdevice.h" +#include "libcamera/internal/v4l2_videodevice.h" + +namespace libcamera { + +LOG_DEFINE_CATEGORY(RCar4) + +class RCar4CameraData : public Camera::Private +{ +public: + RCar4CameraData(PipelineHandler *pipe) + : Camera::Private(pipe) + { + } + + Stream humanVision; + Stream machineVision; +}; + +struct RCar4CameraPipe { + MediaDevice *mdev; + std::unique_ptr<V4L2Subdevice> ispCore; + std::unique_ptr<V4L2Subdevice> ispCS; + std::unique_ptr<V4L2Subdevice> csi2Rx; + std::unique_ptr<V4L2Subdevice> sensor; + std::unique_ptr<V4L2VideoDevice> params; + std::unique_ptr<V4L2VideoDevice> stats; + std::unique_ptr<V4L2VideoDevice> exposure1; + std::unique_ptr<V4L2VideoDevice> exposure2; + std::unique_ptr<V4L2VideoDevice> machineVision; + std::unique_ptr<V4L2VideoDevice> humanVision; +}; + +class PipelineHandlerRCar4 : public PipelineHandler +{ +public: + PipelineHandlerRCar4(CameraManager *manager); + + std::unique_ptr<CameraConfiguration> generateConfiguration(Camera *camera, + Span<const StreamRole> roles) override; + int configure(Camera *camera, CameraConfiguration *config) override; + + int exportFrameBuffers(Camera *camera, Stream *stream, + std::vector<std::unique_ptr<FrameBuffer>> *buffers) override; + + int start(Camera *camera, const ControlList *controls) override; + void stopDevice(Camera *camera) override; + + int queueRequestDevice(Camera *camera, Request *request) override; + + bool match(DeviceEnumerator *enumerator) override; + +private: + int createCamera(MediaDevice *mdev, std::string &pipeId); + + std::vector<RCar4CameraPipe> pipes_; +}; + +PipelineHandlerRCar4::PipelineHandlerRCar4(CameraManager *manager) + : PipelineHandler(manager) +{ +} + +std::unique_ptr<CameraConfiguration> +PipelineHandlerRCar4::generateConfiguration([[maybe_unused]] Camera *camera, + [[maybe_unused]] Span<const StreamRole> roles) +{ + return {}; +} + +int PipelineHandlerRCar4::configure([[maybe_unused]] Camera *camera, + [[maybe_unused]] CameraConfiguration *c) +{ + return 0; +} + +int PipelineHandlerRCar4::exportFrameBuffers([[maybe_unused]] Camera *camera, + [[maybe_unused]] Stream *stream, + [[maybe_unused]] std::vector<std::unique_ptr<FrameBuffer>> *buffers) +{ + return 0; +} + +int PipelineHandlerRCar4::start([[maybe_unused]] Camera *camera, + [[maybe_unused]] const ControlList *controls) +{ + return 0; +} + +void PipelineHandlerRCar4::stopDevice([[maybe_unused]] Camera *camera) +{ +} + +int PipelineHandlerRCar4::queueRequestDevice([[maybe_unused]] Camera *camera, + [[maybe_unused]] Request *request) +{ + return 0; +} + +int PipelineHandlerRCar4::createCamera(MediaDevice *mdev, std::string &pipeId) +{ + RCar4CameraPipe pipe{}; + + pipe.mdev = mdev; + pipe.ispCS = V4L2Subdevice::fromEntityName(mdev, pipeId); + if (!pipe.ispCS) { + LOG(RCar4, Error) << "Failed to find " << pipeId; + return -EINVAL; + } + + pipe.ispCore = V4L2Subdevice::fromEntityName(mdev, pipeId + " core"); + if (!pipe.ispCore) { + LOG(RCar4, Error) << "Failed to find " << pipeId + " core"; + return -EINVAL; + } + + /* Create the ISP video devices. */ + const MediaEntity *ispEntity = pipe.ispCore->entity(); + const MediaPad *pad = ispEntity->getPadByIndex(0); + const MediaPad *vdevPad = pad->links()[0]->source(); + pipe.exposure1 = V4L2VideoDevice::fromEntityName(mdev, + vdevPad->entity()->name()); + + pad = ispEntity->getPadByIndex(1); + vdevPad = pad->links()[0]->source(); + pipe.exposure2 = V4L2VideoDevice::fromEntityName(mdev, + vdevPad->entity()->name()); + + pad = ispEntity->getPadByIndex(2); + vdevPad = pad->links()[0]->source(); + pipe.params = V4L2VideoDevice::fromEntityName(mdev, + vdevPad->entity()->name()); + + pad = ispEntity->getPadByIndex(3); + vdevPad = pad->links()[0]->sink(); + pipe.stats = V4L2VideoDevice::fromEntityName(mdev, + vdevPad->entity()->name()); + + pad = ispEntity->getPadByIndex(4); + vdevPad = pad->links()[0]->sink(); + pipe.humanVision = V4L2VideoDevice::fromEntityName(mdev, + vdevPad->entity()->name()); + + pad = ispEntity->getPadByIndex(5); + vdevPad = pad->links()[0]->sink(); + pipe.machineVision = V4L2VideoDevice::fromEntityName(mdev, + vdevPad->entity()->name()); + + if (!pipe.exposure1 || !pipe.exposure2 || !pipe.params || !pipe.stats || + !pipe.humanVision || !pipe.machineVision) { + LOG(RCar4, Error) << "Unable to find ISP components"; + return -ENODEV; + } + + /* + * Walk the ispCS sink link to get to the csi-2 Rx and from + * there create a camera. + */ + const MediaEntity *entity = pipe.ispCS->entity(); + pad = entity->getPadByIndex(0); + const MediaPad *source = pad->links()[0]->source(); + pipe.csi2Rx = V4L2Subdevice::fromEntityName(mdev, source->entity()->name()); + if (!pipe.csi2Rx) { + LOG(RCar4, Error) << "Failed to find CSI-2 Rx entity"; + return -EINVAL; + } + + entity = pipe.csi2Rx->entity(); + pad = entity->getPadByIndex(0); + source = pad->links()[0]->source(); + pipe.sensor = V4L2Subdevice::fromEntityName(mdev, source->entity()->name()); + if (!pipe.sensor) { + LOG(RCar4, Error) << "Failed to find sensor entity"; + return -EINVAL; + } + + std::unique_ptr<RCar4CameraData> data = + std::make_unique<RCar4CameraData>(this); + + std::set<Stream *> streams{ + &data->humanVision, + &data->machineVision, + }; + + const std::string id = pipe.sensor->entity()->name(); + std::shared_ptr<Camera> camera = + Camera::create(std::move(data), id, streams); + registerCamera(std::move(camera)); + + return 0; +} + +bool PipelineHandlerRCar4::match(DeviceEnumerator *enumerator) +{ + DeviceMatch dm("rcar_vin"); + + MediaDevice *media = acquireMediaDevice(enumerator, dm); + if (!media) + return false; + + /* + * Walk the entities in the media graph to identify the required + * components. + */ + for (const MediaEntity *entity : media->entities()) { + /* Identify the ISP core entries (part of the same media graph). */ + if (entity->name().substr(0, 8) == "rcar_isp" && + entity->name().rfind("core") != std::string::npos) { + /* + * Isolate the unit address that identifies one ISP + * instance. pipeId will look like + * 'rcar_isp fed00000.isp'. + */ + std::string pipeId = entity->name().substr(0, 21); + createCamera(media, pipeId); + } + } + + return false; +} + +REGISTER_PIPELINE_HANDLER(PipelineHandlerRCar4, "rcar-gen4") + +} /* namespace libcamera */ |