From patchwork Thu Feb 28 20:04:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 681 Return-Path: Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6BCAE610BF for ; Thu, 28 Feb 2019 21:03:48 +0100 (CET) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay4-d.mail.gandi.net (Postfix) with ESMTPSA id DE1CDE0006; Thu, 28 Feb 2019 20:03:47 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 28 Feb 2019 21:04:03 +0100 Message-Id: <20190228200410.3022-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190228200410.3022-1-jacopo@jmondi.org> References: <20190228200410.3022-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 03/10] libcamera: ipu3: Initialize and link ImgU devices 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: Thu, 28 Feb 2019 20:03:49 -0000 Create video devices and subdevices associated with an ImgU unit, and link the entities in the media graph to prepare the device for capture operations at stream configuration time. As we support a single stream at the moment, always select imgu0. Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 219 +++++++++++++++++++++++++-- 1 file changed, 207 insertions(+), 12 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 4f1ab72debf8..9fa59c1bc97e 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -24,6 +24,28 @@ namespace libcamera { LOG_DEFINE_CATEGORY(IPU3) +struct ImguDevice { + ImguDevice() + : imgu(nullptr), input(nullptr), output(nullptr), + viewfinder(nullptr), stat(nullptr) {} + + ~ImguDevice() + { + delete imgu; + delete input; + delete output; + delete viewfinder; + delete stat; + } + + V4L2Subdevice *imgu; + V4L2Device *input; + V4L2Device *output; + V4L2Device *viewfinder; + V4L2Device *stat; + /* TODO: add param video device for 3A tuning */ +}; + struct Cio2Device { Cio2Device() : output(nullptr), csi2(nullptr), sensor(nullptr) {} @@ -44,6 +66,7 @@ class IPU3CameraData : public CameraData { public: Cio2Device cio2; + ImguDevice *imgu; Stream stream_; }; @@ -71,6 +94,10 @@ public: bool match(DeviceEnumerator *enumerator); private: + static constexpr unsigned int IMGU_PAD_INPUT = 0; + static constexpr unsigned int IMGU_PAD_OUTPUT = 2; + static constexpr unsigned int IMGU_PAD_VF = 3; + static constexpr unsigned int IMGU_PAD_STAT = 4; static constexpr unsigned int IPU3_BUF_NUM = 4; IPU3CameraData *cameraData(const Camera *camera) @@ -79,9 +106,17 @@ private: PipelineHandler::cameraData(camera)); } + int linkImgu(ImguDevice *imgu); + + V4L2Device *openDevice(MediaDevice *media, std::string &name); + V4L2Subdevice *openSubdevice(MediaDevice *media, std::string &name); + int initImgu(ImguDevice *imgu); int initCio2(unsigned int index, Cio2Device *cio2); void registerCameras(); + ImguDevice imgu0_; + ImguDevice imgu1_; + std::shared_ptr cio2MediaDev_; std::shared_ptr imguMediaDev_; }; @@ -159,6 +194,15 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera, V4L2DeviceFormat devFormat = {}; int ret; + /* + * TODO: dynamically assign ImgU devices; as of now, with a single + * stream supported, always use 'imgu0'. + */ + data->imgu = &imgu0_; + ret = linkImgu(data->imgu); + if (ret) + return ret; + /* * FIXME: as of now, the format gets applied to the sensor and is * propagated along the pipeline. It should instead be applied on the @@ -334,17 +378,29 @@ bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator) if (cio2MediaDev_->open()) goto error_release_mdev; + if (imguMediaDev_->open()) + goto error_close_mdev; + if (cio2MediaDev_->disableLinks()) - goto error_close_cio2; + goto error_close_mdev; + + if (initImgu(&imgu0_)) + goto error_close_mdev; + + if (initImgu(&imgu1_)) + goto error_close_mdev; + registerCameras(); cio2MediaDev_->close(); + imguMediaDev_->close(); return true; -error_close_cio2: +error_close_mdev: cio2MediaDev_->close(); + imguMediaDev_->close(); error_release_mdev: cio2MediaDev_->release(); @@ -353,6 +409,153 @@ error_release_mdev: return false; } +/* Link entities in the ImgU unit to prepare for capture operations. */ +int PipelineHandlerIPU3::linkImgu(ImguDevice *imguDevice) +{ + MediaLink *link; + int ret; + + unsigned int index = imguDevice == &imgu0_ ? 0 : 1; + std::string imguName = "ipu3-imgu " + std::to_string(index); + std::string inputName = imguName + " input"; + std::string outputName = imguName + " output"; + std::string viewfinderName = imguName + " viewfinder"; + std::string statName = imguName + " 3a stat"; + + ret = imguMediaDev_->open(); + if (ret) + return ret; + + ret = imguMediaDev_->disableLinks(); + if (ret) { + imguMediaDev_->close(); + return ret; + } + + /* Link entities to configure the IMGU unit for capture. */ + link = imguMediaDev_->link(inputName, 0, imguName, IMGU_PAD_INPUT); + if (!link) { + LOG(IPU3, Error) + << "Failed to get link '" << inputName << "':0 -> '" + << imguName << "':0"; + ret = -ENODEV; + goto error_close_mediadev; + } + link->setEnabled(true); + + link = imguMediaDev_->link(imguName, IMGU_PAD_OUTPUT, outputName, 0); + if (!link) { + LOG(IPU3, Error) + << "Failed to get link '" << imguName << "':2 -> '" + << outputName << "':0"; + ret = -ENODEV; + goto error_close_mediadev; + } + link->setEnabled(true); + + link = imguMediaDev_->link(imguName, IMGU_PAD_VF, viewfinderName, 0); + if (!link) { + LOG(IPU3, Error) + << "Failed to get link '" << imguName << "':3 -> '" + << viewfinderName << "':0"; + ret = -ENODEV; + goto error_close_mediadev; + } + link->setEnabled(true); + + link = imguMediaDev_->link(imguName, IMGU_PAD_STAT, statName, 0); + if (!link) { + LOG(IPU3, Error) + << "Failed to get link '" << imguName << "':4 -> '" + << statName << "':0"; + ret = -ENODEV; + goto error_close_mediadev; + } + link->setEnabled(true); + + imguMediaDev_->close(); + + return 0; + +error_close_mediadev: + imguMediaDev_->close(); + + return ret; + +} + +V4L2Device *PipelineHandlerIPU3::openDevice(MediaDevice *media, + std::string &name) +{ + V4L2Device *dev; + + MediaEntity *entity = media->getEntityByName(name); + if (!entity) { + LOG(IPU3, Error) + << "Failed to get entity '" << name << "'"; + return nullptr; + } + + dev = new V4L2Device(entity); + if (dev->open()) + return nullptr; + + return dev; +} + +V4L2Subdevice *PipelineHandlerIPU3::openSubdevice(MediaDevice *media, + std::string &name) +{ + V4L2Subdevice *dev; + + MediaEntity *entity = media->getEntityByName(name); + if (!entity) { + LOG(IPU3, Error) + << "Failed to get entity '" << name << "'"; + return nullptr; + } + + dev = new V4L2Subdevice(entity); + if (dev->open()) + return nullptr; + + return dev; +} + +/* Create video devices and subdevices for the ImgU instance. */ +int PipelineHandlerIPU3::initImgu(ImguDevice *imgu) +{ + unsigned int index = imgu == &imgu0_ ? 0 : 1; + std::string imguName = "ipu3-imgu " + std::to_string(index); + std::string devName; + + imgu->imgu = openSubdevice(imguMediaDev_.get(), imguName); + if (!imgu->imgu) + return -ENODEV; + + devName = imguName + " input"; + imgu->input = openDevice(imguMediaDev_.get(), devName); + if (!imgu->input) + return -ENODEV; + + devName = imguName + " output"; + imgu->output = openDevice(imguMediaDev_.get(), devName); + if (!imgu->output) + return -ENODEV; + + devName = imguName + " viewfinder"; + imgu->viewfinder = openDevice(imguMediaDev_.get(), devName); + if (!imgu->viewfinder) + return -ENODEV; + + devName = imguName + " 3a stat"; + imgu->stat = openDevice(imguMediaDev_.get(), devName); + if (!imgu->stat) + return -ENODEV; + + return 0; +} + int PipelineHandlerIPU3::initCio2(unsigned int index, Cio2Device *cio2) { int ret; @@ -400,16 +603,8 @@ int PipelineHandlerIPU3::initCio2(unsigned int index, Cio2Device *cio2) return ret; std::string cio2Name = "ipu3-cio2 " + std::to_string(index); - entity = cio2MediaDev_->getEntityByName(cio2Name); - if (!entity) { - LOG(IPU3, Error) - << "Failed to get entity '" << cio2Name << "'"; - return -EINVAL; - } - - cio2->output = new V4L2Device(entity); - ret = cio2->output->open(); - if (ret) + cio2->output = openDevice(cio2MediaDev_.get(), cio2Name); + if (!cio2->output) return ret; return 0;