From patchwork Tue Jan 15 14:07:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 231 Return-Path: Received: from relay12.mail.gandi.net (relay12.mail.gandi.net [217.70.178.232]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4BCF260C8D for ; Tue, 15 Jan 2019 15:07:49 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id D5B5B200011; Tue, 15 Jan 2019 14:07:48 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 15 Jan 2019 15:07:49 +0100 Message-Id: <20190115140749.8297-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190115140749.8297-1-jacopo@jmondi.org> References: <20190115140749.8297-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 4/4] libcamera: pipeline: Add Intel IPU3 pipeline X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 15 Jan 2019 14:07:49 -0000 Add a pipeline handler for the Intel IPU3 device. The pipeline handler creates a Camera for each image sensor it finds to be connected to an IPU3 CSI-2 receiver, and enables the link between the two. Tested on Soraka, listing detected cameras on the system, verifying the pipeline handler gets matched and links properly enabled. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/ipu3/ipu3.cpp | 249 ++++++++++++++++++++++++ src/libcamera/pipeline/ipu3/meson.build | 3 + src/libcamera/pipeline/meson.build | 2 + 3 files changed, 254 insertions(+) create mode 100644 src/libcamera/pipeline/ipu3/ipu3.cpp create mode 100644 src/libcamera/pipeline/ipu3/meson.build diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp new file mode 100644 index 0000000..4c24c79 --- /dev/null +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -0,0 +1,249 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * ipu3.cpp - Pipeline handler for Intel IPU3 + */ + +#include +#include + +#include + +#include "device_enumerator.h" +#include "log.h" +#include "media_device.h" +#include "pipeline_handler.h" + +namespace libcamera { + +class PipelineHandlerIPU3 : public PipelineHandler +{ +public: + PipelineHandlerIPU3(); + ~PipelineHandlerIPU3(); + + bool match(DeviceEnumerator *enumerator); + + unsigned int count(); + Camera *camera(unsigned int id) final; + +private: + MediaDevice *cio2_; + MediaDevice *imgu_; + + unsigned int numCameras_; + std::map cameras_; + + unsigned int registerCameras(); +}; + +PipelineHandlerIPU3::PipelineHandlerIPU3() + : cio2_(nullptr), imgu_(nullptr), numCameras_(0) +{ +} + +PipelineHandlerIPU3::~PipelineHandlerIPU3() +{ + if (cio2_) + cio2_->release(); + + if (imgu_) + imgu_->release(); + + for (auto camera : cameras_) { + if (!camera.second) + continue; + + camera.second->put(); + + /* + * FIXME + * The lifetime management of Camera instances will be + * soon changed: as of now, the handler creates cameras, and + * -shall- destroy them as well to avoid leaks. + */ + delete camera.second; + } + + cio2_ = nullptr; + imgu_ = nullptr; + cameras_.clear(); +} + +unsigned int PipelineHandlerIPU3::count() +{ + return numCameras_; +} + +Camera *PipelineHandlerIPU3::camera(unsigned int id) +{ + if (id >= numCameras_) + return nullptr; + + /* + * The requested camera id does not match the key index used to store + * Camera instances in the 'cameras_' map. + * + * The 'id' argument represent the n-th valid cameras registered + * in the system, while the indexing key is the CSI-2 receiver index + * the camera sensor is associated to, and some receiver might have no + * camera sensor connected. + */ + for (auto it = cameras_.begin(); it != cameras_.end(); ++it, --id) { + if (id == 0) + return (*it).second; + } + + return nullptr; +} + +bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator) +{ + DeviceMatch cio2_dm("ipu3-cio2"); + cio2_dm.add("ipu3-csi2 0"); + cio2_dm.add("ipu3-cio2 0"); + cio2_dm.add("ipu3-csi2 1"); + cio2_dm.add("ipu3-cio2 1"); + cio2_dm.add("ipu3-csi2 2"); + cio2_dm.add("ipu3-cio2 2"); + cio2_dm.add("ipu3-csi2 3"); + cio2_dm.add("ipu3-cio2 3"); + + cio2_ = enumerator->search(cio2_dm); + if (!cio2_) + return false; + + cio2_->acquire(); + + DeviceMatch imgu_dm("ipu3-imgu"); + imgu_dm.add("ipu3-imgu 0"); + imgu_dm.add("ipu3-imgu 0 input"); + imgu_dm.add("ipu3-imgu 0 parameters"); + imgu_dm.add("ipu3-imgu 0 output"); + imgu_dm.add("ipu3-imgu 0 viewfinder"); + imgu_dm.add("ipu3-imgu 0 3a stat"); + imgu_dm.add("ipu3-imgu 1"); + imgu_dm.add("ipu3-imgu 1 input"); + imgu_dm.add("ipu3-imgu 1 parameters"); + imgu_dm.add("ipu3-imgu 1 output"); + imgu_dm.add("ipu3-imgu 1 viewfinder"); + imgu_dm.add("ipu3-imgu 1 3a stat"); + + imgu_ = enumerator->search(imgu_dm); + if (!imgu_) { + cio2_->release(); + return false; + } + + imgu_->acquire(); + + /* + * Disable all links that are enabled by default on CIO2, as camera + * creation enables all valid links it finds. + * + * Close the CIO2 media device after, as links are enabled and should + * not need to be changed after. + */ + if (cio2_->open()) { + cio2_->release(); + imgu_->release(); + return false; + } + cio2_->disableLinks(); + + numCameras_ = registerCameras(); + LOG(Debug) << "\"Intel IPU3\" pipeline handler initialized with " + << numCameras_ << " cameras registered"; + + cio2_->close(); + + return true; +} + +/* + * Cameras are created associating an image sensor (represented by a + * media entity with function MEDIA_ENT_F_CAM_SENSOR) to one of the four + * CIO2 CSI-2 receivers. + * + * Cameras are here created and stored in the member field 'cameras_' map, + * indexed by the id of the CSI-2 receiver they are connected, to maintain + * an ordering that does not depend on the device enumeration order. + * + * The function returns the number of cameras found in the system. + */ +unsigned int PipelineHandlerIPU3::registerCameras() +{ + const std::vector entities = cio2_->entities(); + unsigned int numCameras = 0; + struct { + unsigned int id; + MediaEntity *csi2; + } csi2Receivers[] = { + { 0, cio2_->getEntityByName("ipu3-csi2 0") }, + { 1, cio2_->getEntityByName("ipu3-csi2 1") }, + { 2, cio2_->getEntityByName("ipu3-csi2 2") }, + { 3, cio2_->getEntityByName("ipu3-csi2 3") }, + }; + + /* + * For each CSI-2 receiver on the IPU3, create a Camera if an + * image sensor is connected to it. + */ + for (auto csi2Receiver : csi2Receivers) { + MediaEntity *csi2 = csi2Receiver.csi2; + unsigned int id = csi2Receiver.id; + + /* IPU3 CSI-2 receivers have a single sink pad. */ + std::vector pads = csi2->pads(); + MediaPad *sink; + for (MediaPad *pad : pads) { + if (!(pad->flags() & MEDIA_PAD_FL_SINK)) + continue; + + sink = pad; + break; + } + + /* Verify that the receiver is connected to a sensor. */ + std::vector links = sink->links(); + if (links.empty()) + continue; + + /* + * FIXME + * This supports creating a single camera per CSI-2 receiver. + */ + for (MediaLink *link : links) { + MediaEntity *sensor = link->source()->entity(); + if (!sensor) + continue; + + if (sensor->function() != MEDIA_ENT_F_CAM_SENSOR) + continue; + + /* Enable the link between sensor and CSI-2 receiver. */ + if (link->setEnabled(true)) + continue; + + /* Create the camera using the sensor name. */ + std::size_t pos = sensor->name().find(" "); + std::string cameraName = sensor->name().substr(0, pos); + + cameras_[id] = new Camera(cameraName); + + LOG(Debug) << "Registered Camera[" << numCameras + << "] \"" << cameraName << "\"" + << " connected to CSI-2 receiver " << id; + + numCameras++; + break; + } + } + + return numCameras; +} + +REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3); + +} /* namespace libcamera */ diff --git a/src/libcamera/pipeline/ipu3/meson.build b/src/libcamera/pipeline/ipu3/meson.build new file mode 100644 index 0000000..0ab766a --- /dev/null +++ b/src/libcamera/pipeline/ipu3/meson.build @@ -0,0 +1,3 @@ +libcamera_sources += files([ + 'ipu3.cpp', +]) diff --git a/src/libcamera/pipeline/meson.build b/src/libcamera/pipeline/meson.build index 615ecd2..811c075 100644 --- a/src/libcamera/pipeline/meson.build +++ b/src/libcamera/pipeline/meson.build @@ -1,3 +1,5 @@ libcamera_sources += files([ 'vimc.cpp', ]) + +subdir('ipu3')