{"id":752,"url":"https://patchwork.libcamera.org/api/patches/752/?format=json","web_url":"https://patchwork.libcamera.org/patch/752/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20190320163055.22056-7-jacopo@jmondi.org>","date":"2019-03-20T16:30:30","name":"[libcamera-devel,v4,06/31] libcamera: ipu3: Initialize and configure ImgUs","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"8f1440533c7cb474c1330a119b369da047f48c19","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/?format=json","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/752/mbox/","series":[{"id":214,"url":"https://patchwork.libcamera.org/api/series/214/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=214","date":"2019-03-20T16:30:24","name":"libcamera: ipu3: Add ImgU support + multiple streams","version":4,"mbox":"https://patchwork.libcamera.org/series/214/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/752/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/752/checks/","tags":{},"headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay12.mail.gandi.net (relay12.mail.gandi.net\n\t[217.70.178.232])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D7A5D611B4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 20 Mar 2019 17:30:31 +0100 (CET)","from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101])\n\t(Authenticated sender: jacopo@jmondi.org)\n\tby relay12.mail.gandi.net (Postfix) with ESMTPSA id 69090200010;\n\tWed, 20 Mar 2019 16:30:31 +0000 (UTC)"],"From":"Jacopo Mondi <jacopo@jmondi.org>","To":"libcamera-devel@lists.libcamera.org","Date":"Wed, 20 Mar 2019 17:30:30 +0100","Message-Id":"<20190320163055.22056-7-jacopo@jmondi.org>","X-Mailer":"git-send-email 2.21.0","In-Reply-To":"<20190320163055.22056-1-jacopo@jmondi.org>","References":"<20190320163055.22056-1-jacopo@jmondi.org>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH v4 06/31] libcamera: ipu3: Initialize and\n\tconfigure ImgUs","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Wed, 20 Mar 2019 16:30:32 -0000"},"content":"Create video devices and subdevices associated with an ImgU unit at\ncamera registration time.\n\nStatically assign imgu0 to the first camera and imgu1 to the second one\nand limit support to two camera. This will have to be revised in future.\n\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\n---\n src/libcamera/pipeline/ipu3/ipu3.cpp | 223 +++++++++++++++++++++++++--\n 1 file changed, 209 insertions(+), 14 deletions(-)","diff":"diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\nindex 2e351d04a784..26fc56a76eb1 100644\n--- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n@@ -27,6 +27,38 @@ namespace libcamera {\n \n LOG_DEFINE_CATEGORY(IPU3)\n \n+class ImgUDevice\n+{\n+public:\n+\tImgUDevice()\n+\t\t: imgu(nullptr), input(nullptr), output(nullptr),\n+\t\t  viewfinder(nullptr), stat(nullptr)\n+\t{\n+\t}\n+\n+\t~ImgUDevice()\n+\t{\n+\t\tdelete imgu;\n+\t\tdelete input;\n+\t\tdelete output;\n+\t\tdelete viewfinder;\n+\t\tdelete stat;\n+\t}\n+\n+\tvoid init(MediaDevice *media, unsigned int index);\n+\n+\tunsigned int index_;\n+\tstd::string imguName_;\n+\tMediaDevice *mediaDevice_;\n+\n+\tV4L2Subdevice *imgu;\n+\tV4L2Device *input;\n+\tV4L2Device *output;\n+\tV4L2Device *viewfinder;\n+\tV4L2Device *stat;\n+\t/* \\todo Add param video device for 3A tuning */\n+};\n+\n struct CIO2Device {\n \tCIO2Device()\n \t\t: output(nullptr), csi2(nullptr), sensor(nullptr)\n@@ -68,6 +100,7 @@ public:\n \tbool match(DeviceEnumerator *enumerator);\n \n private:\n+\tstatic constexpr unsigned int IPU3_IMGU_COUNT = 2;\n \tstatic constexpr unsigned int IPU3_BUFFER_COUNT = 4;\n \n \tclass IPU3CameraData : public CameraData\n@@ -81,6 +114,7 @@ private:\n \t\tvoid bufferReady(Buffer *buffer);\n \n \t\tCIO2Device cio2;\n+\t\tImgUDevice *imgu;\n \n \t\tStream stream_;\n \t};\n@@ -92,10 +126,18 @@ private:\n \t}\n \n \tint mediaBusToCIO2Format(unsigned int code);\n+\tV4L2Device *openDevice(MediaDevice *media, const std::string &name);\n+\tV4L2Subdevice *openSubdevice(MediaDevice *media,\n+\t\t\t\t     const std::string &name);\n \n \tint initCIO2(unsigned int index, CIO2Device *cio2);\n+\tvoid deleteCIO2(CIO2Device *cio2);\n+\n+\tint initImgU(ImgUDevice *imgu);\n+\n \tvoid registerCameras();\n \n+\tImgUDevice imgus_[IPU3_IMGU_COUNT];\n \tstd::shared_ptr<MediaDevice> cio2MediaDev_;\n \tstd::shared_ptr<MediaDevice> imguMediaDev_;\n };\n@@ -355,11 +397,45 @@ bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)\n \t\treturn false;\n \t}\n \n+\tif (imguMediaDev_->open()) {\n+\t\tcio2MediaDev_->close();\n+\t\treturn false;\n+\t}\n+\n+\tif (imguMediaDev_->disableLinks())\n+\t\tgoto error_close_mdev;\n+\n+\tfor (unsigned int i = 0; i < IPU3_IMGU_COUNT; ++i)\n+\t\timgus_[i].init(imguMediaDev_.get(), i);\n+\n \tregisterCameras();\n \n \tcio2MediaDev_->close();\n+\timguMediaDev_->close();\n \n \treturn true;\n+\n+error_close_mdev:\n+\tcio2MediaDev_->close();\n+\timguMediaDev_->close();\n+\n+\treturn false;\n+}\n+\n+/* ----------------------------------------------------------------------------\n+ * Helpers\n+ */\n+\n+/**\n+ * \\brief Initialize fields of the ImgU instance\n+ * \\param mediaDevice The ImgU instance media device\n+ * \\param index The ImgU instance index\n+ */\n+void ImgUDevice::init(MediaDevice *mediaDevice, unsigned int index)\n+{\n+\tindex_ = index;\n+\timguName_ = \"ipu3-imgu \" + std::to_string(index_);\n+\tmediaDevice_ = mediaDevice;\n }\n \n int PipelineHandlerIPU3::mediaBusToCIO2Format(unsigned int code)\n@@ -378,6 +454,114 @@ int PipelineHandlerIPU3::mediaBusToCIO2Format(unsigned int code)\n \t}\n }\n \n+/**\n+ * \\brief Create and open the video device with \\a name in media device \\a media\n+ *\n+ * \\todo Make a generic helper out of this method.\n+ *\n+ * \\return Pointer to the video device on success, nullptr otherwise\n+ */\n+V4L2Device *PipelineHandlerIPU3::openDevice(MediaDevice *media,\n+\t\t\t\t\t    const std::string &name)\n+{\n+\tMediaEntity *entity = media->getEntityByName(name);\n+\tif (!entity) {\n+\t\tLOG(IPU3, Error)\n+\t\t\t<< \"Failed to get entity '\" << name << \"'\";\n+\t\treturn nullptr;\n+\t}\n+\n+\tV4L2Device *dev = new V4L2Device(entity);\n+\tif (dev->open()) {\n+\t\tdelete dev;\n+\t\treturn nullptr;\n+\t}\n+\n+\treturn dev;\n+}\n+\n+/**\n+ * \\brief Create and open the subdevice with \\a name in media device \\a media\n+ *\n+ * \\todo Make a generic helper out of this method.\n+ *\n+ * \\return Pointer to the subdevice on success, nullptr otherwise\n+ */\n+V4L2Subdevice *PipelineHandlerIPU3::openSubdevice(MediaDevice *media,\n+\t\t\t\t\t\t  const std::string &name)\n+{\n+\tMediaEntity *entity = media->getEntityByName(name);\n+\tif (!entity) {\n+\t\tLOG(IPU3, Error)\n+\t\t\t<< \"Failed to get entity '\" << name << \"'\";\n+\t\treturn nullptr;\n+\t}\n+\n+\tV4L2Subdevice *dev = new V4L2Subdevice(entity);\n+\tif (dev->open()) {\n+\t\tdelete dev;\n+\t\treturn nullptr;\n+\t}\n+\n+\treturn dev;\n+}\n+\n+/* ----------------------------------------------------------------------------\n+ * IPU3 pipeline configuration\n+ */\n+\n+/**\n+ * \\brief Initialize and configure components of the ImgU instance\n+ *\n+ * Create and open the devices and subdevices in the ImgU instance.\n+ * This methods configures the ImgU instance for capture operations, and\n+ * should be called at stream configuration time.\n+ *\n+ * \\todo Expand the ImgU configuration with controls setting\n+ *\n+ * \\return 0 on success or a negative error code otherwise\n+ * \\retval -ENODEV Failed to open one of the video devices or subdevices\n+ */\n+int PipelineHandlerIPU3::initImgU(ImgUDevice *imgu)\n+{\n+\timgu->imgu = openSubdevice(imgu->mediaDevice_, imgu->imguName_);\n+\tif (!imgu->imgu)\n+\t\treturn -ENODEV;\n+\n+\timgu->input = openDevice(imgu->mediaDevice_,\n+\t\t\t\t imgu->imguName_ + \" input\");\n+\tif (!imgu->input)\n+\t\tgoto error_delete_imgu;\n+\n+\timgu->output = openDevice(imgu->mediaDevice_,\n+\t\t\t\t  imgu->imguName_ + \" output\");\n+\tif (!imgu->output)\n+\t\tgoto error_delete_input;\n+\n+\timgu->viewfinder = openDevice(imgu->mediaDevice_,\n+\t\t\t\t      imgu->imguName_ + \" viewfinder\");\n+\tif (!imgu->viewfinder)\n+\t\tgoto error_delete_output;\n+\n+\timgu->stat = openDevice(imgu->mediaDevice_,\n+\t\t\t\timgu->imguName_ + \" 3a stat\");\n+\tif (!imgu->stat)\n+\t\tgoto error_delete_vf;\n+\n+\treturn 0;\n+\n+error_delete_vf:\n+\tdelete imgu->viewfinder;\n+error_delete_output:\n+\tdelete imgu->output;\n+error_delete_input:\n+\tdelete imgu->input;\n+error_delete_imgu:\n+\tdelete imgu->imgu;\n+\n+\treturn -ENODEV;\n+}\n+\n /**\n  * \\brief Initialize components of the CIO2 device \\a index used by a camera\n  * \\param index The CIO2 device index\n@@ -458,23 +642,12 @@ int PipelineHandlerIPU3::initCIO2(unsigned int index, CIO2Device *cio2)\n \tif (ret)\n \t\tgoto error_delete_csi2;\n \n-\tentity = cio2MediaDev_->getEntityByName(cio2Name);\n-\tif (!entity) {\n-\t\tLOG(IPU3, Error)\n-\t\t\t<< \"Failed to get entity '\" << cio2Name << \"'\";\n-\t\tret = -EINVAL;\n+\tcio2->output = openDevice(cio2MediaDev_.get(), cio2Name);\n+\tif (!cio2->output)\n \t\tgoto error_delete_csi2;\n-\t}\n-\n-\tcio2->output = new V4L2Device(entity);\n-\tret = cio2->output->open();\n-\tif (ret)\n-\t\tgoto error_delete_output;\n \n \treturn 0;\n \n-error_delete_output:\n-\tdelete cio2->output;\n error_delete_csi2:\n \tdelete cio2->csi2;\n error_delete_sensor:\n@@ -483,6 +656,16 @@ error_delete_sensor:\n \treturn ret;\n }\n \n+/**\n+ * \\brief Delete all devices associated with a CIO2 unit\n+ */\n+void PipelineHandlerIPU3::deleteCIO2(CIO2Device *cio2)\n+{\n+\tdelete cio2->output;\n+\tdelete cio2->csi2;\n+\tdelete cio2->sensor;\n+}\n+\n /*\n  * Cameras are created associating an image sensor (represented by a\n  * media entity with function MEDIA_ENT_F_CAM_SENSOR) to one of the four\n@@ -495,7 +678,7 @@ void PipelineHandlerIPU3::registerCameras()\n \t * image sensor is connected to it.\n \t */\n \tunsigned int numCameras = 0;\n-\tfor (unsigned int id = 0; id < 4; ++id) {\n+\tfor (unsigned int id = 0; id < 4 && numCameras < 2; ++id) {\n \t\tstd::unique_ptr<IPU3CameraData> data =\n \t\t\tutils::make_unique<IPU3CameraData>(this);\n \t\tstd::set<Stream *> streams{ &data->stream_ };\n@@ -506,6 +689,18 @@ void PipelineHandlerIPU3::registerCameras()\n \t\tif (ret)\n \t\t\tcontinue;\n \n+\t\t/**\n+\t\t * \\todo Dynamically assign ImgU devices; as of now, limit\n+\t\t * support to two cameras only, and assign imgu0 to the first\n+\t\t * one and imgu1 to the second.\n+\t\t */\n+\t\tdata->imgu = &imgus_[numCameras];\n+\t\tret = initImgU(data->imgu);\n+\t\tif (ret) {\n+\t\t\tdeleteCIO2(cio2);\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\tstd::string cameraName = cio2->sensor->deviceName() + \" \"\n \t\t\t\t       + std::to_string(id);\n \t\tstd::shared_ptr<Camera> camera = Camera::create(this,\n","prefixes":["libcamera-devel","v4","06/31"]}