{"id":681,"url":"https://patchwork.libcamera.org/api/1.1/patches/681/?format=json","web_url":"https://patchwork.libcamera.org/patch/681/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/1.1/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":"<20190228200410.3022-4-jacopo@jmondi.org>","date":"2019-02-28T20:04:03","name":"[libcamera-devel,03/10] libcamera: ipu3: Initialize and link ImgU devices","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"60369ef248273d2ae5067564172b528e592408ea","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/1.1/people/3/?format=json","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/681/mbox/","series":[{"id":199,"url":"https://patchwork.libcamera.org/api/1.1/series/199/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=199","date":"2019-02-28T20:04:00","name":"libcamera: ipu3: ImgU support","version":1,"mbox":"https://patchwork.libcamera.org/series/199/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/681/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/681/checks/","tags":{},"headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net\n\t[217.70.183.196])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6BCAE610BF\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 28 Feb 2019 21:03:48 +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 relay4-d.mail.gandi.net (Postfix) with ESMTPSA id DE1CDE0006;\n\tThu, 28 Feb 2019 20:03:47 +0000 (UTC)"],"X-Originating-IP":"2.224.242.101","From":"Jacopo Mondi <jacopo@jmondi.org>","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","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH 03/10] libcamera: ipu3: Initialize and\n\tlink ImgU devices","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":"Thu, 28 Feb 2019 20:03:49 -0000"},"content":"Create video devices and subdevices associated with an ImgU unit, and\nlink the entities in the media graph to prepare the device for capture\noperations at stream configuration time.\n\nAs we support a single stream at the moment, always select imgu0.\n\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\n---\n src/libcamera/pipeline/ipu3/ipu3.cpp | 219 +++++++++++++++++++++++++--\n 1 file changed, 207 insertions(+), 12 deletions(-)","diff":"diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\nindex 4f1ab72debf8..9fa59c1bc97e 100644\n--- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n@@ -24,6 +24,28 @@ namespace libcamera {\n \n LOG_DEFINE_CATEGORY(IPU3)\n \n+struct ImguDevice {\n+\tImguDevice()\n+\t\t: imgu(nullptr), input(nullptr), output(nullptr),\n+\t\t  viewfinder(nullptr), stat(nullptr) {}\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+\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@@ -44,6 +66,7 @@ class IPU3CameraData : public CameraData\n {\n public:\n \tCio2Device cio2;\n+\tImguDevice *imgu;\n \n \tStream stream_;\n };\n@@ -71,6 +94,10 @@ public:\n \tbool match(DeviceEnumerator *enumerator);\n \n private:\n+\tstatic constexpr unsigned int IMGU_PAD_INPUT = 0;\n+\tstatic constexpr unsigned int IMGU_PAD_OUTPUT = 2;\n+\tstatic constexpr unsigned int IMGU_PAD_VF = 3;\n+\tstatic constexpr unsigned int IMGU_PAD_STAT = 4;\n \tstatic constexpr unsigned int IPU3_BUF_NUM = 4;\n \n \tIPU3CameraData *cameraData(const Camera *camera)\n@@ -79,9 +106,17 @@ private:\n \t\t\tPipelineHandler::cameraData(camera));\n \t}\n \n+\tint linkImgu(ImguDevice *imgu);\n+\n+\tV4L2Device *openDevice(MediaDevice *media, std::string &name);\n+\tV4L2Subdevice *openSubdevice(MediaDevice *media, std::string &name);\n+\tint initImgu(ImguDevice *imgu);\n \tint initCio2(unsigned int index, Cio2Device *cio2);\n \tvoid registerCameras();\n \n+\tImguDevice imgu0_;\n+\tImguDevice imgu1_;\n+\n \tstd::shared_ptr<MediaDevice> cio2MediaDev_;\n \tstd::shared_ptr<MediaDevice> imguMediaDev_;\n };\n@@ -159,6 +194,15 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera,\n \tV4L2DeviceFormat devFormat = {};\n \tint ret;\n \n+\t/*\n+\t * TODO: dynamically assign ImgU devices; as of now, with a single\n+\t * stream supported, always use 'imgu0'.\n+\t */\n+\tdata->imgu = &imgu0_;\n+\tret = linkImgu(data->imgu);\n+\tif (ret)\n+\t\treturn ret;\n+\n \t/*\n \t * FIXME: as of now, the format gets applied to the sensor and is\n \t * propagated along the pipeline. It should instead be applied on the\n@@ -334,17 +378,29 @@ bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)\n \tif (cio2MediaDev_->open())\n \t\tgoto error_release_mdev;\n \n+\tif (imguMediaDev_->open())\n+\t\tgoto error_close_mdev;\n+\n \tif (cio2MediaDev_->disableLinks())\n-\t\tgoto error_close_cio2;\n+\t\tgoto error_close_mdev;\n+\n+\tif (initImgu(&imgu0_))\n+\t\tgoto error_close_mdev;\n+\n+\tif (initImgu(&imgu1_))\n+\t\tgoto error_close_mdev;\n+\n \n \tregisterCameras();\n \n \tcio2MediaDev_->close();\n+\timguMediaDev_->close();\n \n \treturn true;\n \n-error_close_cio2:\n+error_close_mdev:\n \tcio2MediaDev_->close();\n+\timguMediaDev_->close();\n \n error_release_mdev:\n \tcio2MediaDev_->release();\n@@ -353,6 +409,153 @@ error_release_mdev:\n \treturn false;\n }\n \n+/* Link entities in the ImgU unit to prepare for capture operations. */\n+int PipelineHandlerIPU3::linkImgu(ImguDevice *imguDevice)\n+{\n+\tMediaLink *link;\n+\tint ret;\n+\n+\tunsigned int index = imguDevice == &imgu0_ ? 0 : 1;\n+\tstd::string imguName = \"ipu3-imgu \" + std::to_string(index);\n+\tstd::string inputName = imguName + \" input\";\n+\tstd::string outputName = imguName + \" output\";\n+\tstd::string viewfinderName = imguName + \" viewfinder\";\n+\tstd::string statName = imguName + \" 3a stat\";\n+\n+\tret = imguMediaDev_->open();\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = imguMediaDev_->disableLinks();\n+\tif (ret) {\n+\t\timguMediaDev_->close();\n+\t\treturn ret;\n+\t}\n+\n+\t/* Link entities to configure the IMGU unit for capture. */\n+\tlink = imguMediaDev_->link(inputName, 0, imguName, IMGU_PAD_INPUT);\n+\tif (!link) {\n+\t\tLOG(IPU3, Error)\n+\t\t\t<< \"Failed to get link '\" << inputName << \"':0 -> '\"\n+\t\t\t<< imguName << \"':0\";\n+\t\tret = -ENODEV;\n+\t\tgoto error_close_mediadev;\n+\t}\n+\tlink->setEnabled(true);\n+\n+\tlink = imguMediaDev_->link(imguName, IMGU_PAD_OUTPUT, outputName, 0);\n+\tif (!link) {\n+\t\tLOG(IPU3, Error)\n+\t\t\t<< \"Failed to get link '\" << imguName << \"':2 -> '\"\n+\t\t\t<< outputName << \"':0\";\n+\t\tret = -ENODEV;\n+\t\tgoto error_close_mediadev;\n+\t}\n+\tlink->setEnabled(true);\n+\n+\tlink = imguMediaDev_->link(imguName, IMGU_PAD_VF, viewfinderName, 0);\n+\tif (!link) {\n+\t\tLOG(IPU3, Error)\n+\t\t\t<< \"Failed to get link '\" << imguName << \"':3 -> '\"\n+\t\t\t<< viewfinderName << \"':0\";\n+\t\tret = -ENODEV;\n+\t\tgoto error_close_mediadev;\n+\t}\n+\tlink->setEnabled(true);\n+\n+\tlink = imguMediaDev_->link(imguName, IMGU_PAD_STAT, statName, 0);\n+\tif (!link) {\n+\t\tLOG(IPU3, Error)\n+\t\t\t<< \"Failed to get link '\" << imguName << \"':4 -> '\"\n+\t\t\t<< statName << \"':0\";\n+\t\tret = -ENODEV;\n+\t\tgoto error_close_mediadev;\n+\t}\n+\tlink->setEnabled(true);\n+\n+\timguMediaDev_->close();\n+\n+\treturn 0;\n+\n+error_close_mediadev:\n+\timguMediaDev_->close();\n+\n+\treturn ret;\n+\n+}\n+\n+V4L2Device *PipelineHandlerIPU3::openDevice(MediaDevice *media,\n+\t\t\t\t\t    std::string &name)\n+{\n+\tV4L2Device *dev;\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+\tdev = new V4L2Device(entity);\n+\tif (dev->open())\n+\t\treturn nullptr;\n+\n+\treturn dev;\n+}\n+\n+V4L2Subdevice *PipelineHandlerIPU3::openSubdevice(MediaDevice *media,\n+\t\t\t\t\t\t  std::string &name)\n+{\n+\tV4L2Subdevice *dev;\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+\tdev = new V4L2Subdevice(entity);\n+\tif (dev->open())\n+\t\treturn nullptr;\n+\n+\treturn dev;\n+}\n+\n+/* Create video devices and subdevices for the ImgU instance. */\n+int PipelineHandlerIPU3::initImgu(ImguDevice *imgu)\n+{\n+\tunsigned int index = imgu == &imgu0_ ? 0 : 1;\n+\tstd::string imguName = \"ipu3-imgu \" + std::to_string(index);\n+\tstd::string devName;\n+\n+\timgu->imgu = openSubdevice(imguMediaDev_.get(), imguName);\n+\tif (!imgu->imgu)\n+\t\treturn -ENODEV;\n+\n+\tdevName = imguName + \" input\";\n+\timgu->input = openDevice(imguMediaDev_.get(), devName);\n+\tif (!imgu->input)\n+\t\treturn -ENODEV;\n+\n+\tdevName = imguName + \" output\";\n+\timgu->output = openDevice(imguMediaDev_.get(), devName);\n+\tif (!imgu->output)\n+\t\treturn -ENODEV;\n+\n+\tdevName = imguName + \" viewfinder\";\n+\timgu->viewfinder = openDevice(imguMediaDev_.get(), devName);\n+\tif (!imgu->viewfinder)\n+\t\treturn -ENODEV;\n+\n+\tdevName = imguName + \" 3a stat\";\n+\timgu->stat = openDevice(imguMediaDev_.get(), devName);\n+\tif (!imgu->stat)\n+\t\treturn -ENODEV;\n+\n+\treturn 0;\n+}\n+\n int PipelineHandlerIPU3::initCio2(unsigned int index, Cio2Device *cio2)\n {\n \tint ret;\n@@ -400,16 +603,8 @@ int PipelineHandlerIPU3::initCio2(unsigned int index, Cio2Device *cio2)\n \t\treturn ret;\n \n \tstd::string cio2Name = \"ipu3-cio2 \" + std::to_string(index);\n-\tentity = cio2MediaDev_->getEntityByName(cio2Name);\n-\tif (!entity) {\n-\t\tLOG(IPU3, Error)\n-\t\t\t<< \"Failed to get entity '\" << cio2Name << \"'\";\n-\t\treturn -EINVAL;\n-\t}\n-\n-\tcio2->output = new V4L2Device(entity);\n-\tret = cio2->output->open();\n-\tif (ret)\n+\tcio2->output = openDevice(cio2MediaDev_.get(), cio2Name);\n+\tif (!cio2->output)\n \t\treturn ret;\n \n \treturn 0;\n","prefixes":["libcamera-devel","03/10"]}