{"id":9732,"url":"https://patchwork.libcamera.org/api/1.1/patches/9732/?format=json","web_url":"https://patchwork.libcamera.org/patch/9732/","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":"<20200922133537.258098-29-paul.elder@ideasonboard.com>","date":"2020-09-22T13:35:27","name":"[libcamera-devel,28/38] libcamera: pipeline, ipa: raspberrypi: Use new data definition","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"84c163807dd4142654f8faa04f2dbb83d6c7d613","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/1.1/people/17/?format=json","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/9732/mbox/","series":[{"id":1309,"url":"https://patchwork.libcamera.org/api/1.1/series/1309/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=1309","date":"2020-09-22T13:34:59","name":"IPA isolation implementation","version":1,"mbox":"https://patchwork.libcamera.org/series/1309/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/9732/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/9732/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E1372BF01C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 22 Sep 2020 13:39:11 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id AA1A862FFB;\n\tTue, 22 Sep 2020 15:39:11 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 95A6A62FD6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 22 Sep 2020 15:39:10 +0200 (CEST)","from pyrite.rasen.tech (unknown\n\t[IPv6:2400:4051:61:600:2c71:1b79:d06d:5032])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 657C62D7;\n\tTue, 22 Sep 2020 15:39:03 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"izhXpck8\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1600781945;\n\tbh=T8nZ7VZ99y4onSlTZCMhmM+WolGbAkpEIB2QFKBr6cg=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=izhXpck8/ySfOgMFy6oOahIOxbsmIViCVqiUPJxvzadShcU99Ca9mTpBwzue6COM1\n\tbUOV+c777rfT4y1GE5rsmJaUWro5RjIWMZukEo8K3VoD4dqSCT7VEdzm5vblr7g1D5\n\t2gkeB52L7CuVyklj5Purre5ZvO2g5/n/k28BJl28=","From":"Paul Elder <paul.elder@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Date":"Tue, 22 Sep 2020 22:35:27 +0900","Message-Id":"<20200922133537.258098-29-paul.elder@ideasonboard.com>","X-Mailer":"git-send-email 2.27.0","In-Reply-To":"<20200922133537.258098-1-paul.elder@ideasonboard.com>","References":"<20200922133537.258098-1-paul.elder@ideasonboard.com>","MIME-Version":"1.0","Subject":"[libcamera-devel] [PATCH 28/38] libcamera: pipeline,\n\tipa: raspberrypi: Use new data definition","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","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>","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"Now that we can generate custom functions and data structures with mojo,\nswitch the raspberrypi pipeline handler and IPA to use the custom data\nstructures as defined in the mojom data definition file.\n\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\n\n---\nChanges in v2:\n- rebased on \"libcamera: pipeline: ipa: raspberrypi: Rework drop frame\n  signalling\"\n- use newly customized RPi IPA interface\n---\n include/libcamera/ipa/raspberrypi.h           |  37 ++--\n src/ipa/raspberrypi/raspberrypi.cpp           | 152 +++++++---------\n .../pipeline/raspberrypi/raspberrypi.cpp      | 171 +++++++++---------\n 3 files changed, 170 insertions(+), 190 deletions(-)","diff":"diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h\nindex 4e38d009..3357bf61 100644\n--- a/include/libcamera/ipa/raspberrypi.h\n+++ b/include/libcamera/ipa/raspberrypi.h\n@@ -24,22 +24,27 @@ enum RPiBufferMask {\n namespace libcamera {\n \n /* List of controls handled by the Raspberry Pi IPA */\n-static const ControlInfoMap RPiControls = {\n-\t{ &controls::AeEnable, ControlInfo(false, true) },\n-\t{ &controls::ExposureTime, ControlInfo(0, 999999) },\n-\t{ &controls::AnalogueGain, ControlInfo(1.0f, 32.0f) },\n-\t{ &controls::AeMeteringMode, ControlInfo(0, static_cast<int32_t>(controls::MeteringModeMax)) },\n-\t{ &controls::AeConstraintMode, ControlInfo(0, static_cast<int32_t>(controls::ConstraintModeMax)) },\n-\t{ &controls::AeExposureMode, ControlInfo(0, static_cast<int32_t>(controls::ExposureModeMax)) },\n-\t{ &controls::ExposureValue, ControlInfo(0.0f, 16.0f) },\n-\t{ &controls::AwbEnable, ControlInfo(false, true) },\n-\t{ &controls::ColourGains, ControlInfo(0.0f, 32.0f) },\n-\t{ &controls::AwbMode, ControlInfo(0, static_cast<int32_t>(controls::AwbModeMax)) },\n-\t{ &controls::Brightness, ControlInfo(-1.0f, 1.0f) },\n-\t{ &controls::Contrast, ControlInfo(0.0f, 32.0f) },\n-\t{ &controls::Saturation, ControlInfo(0.0f, 32.0f) },\n-\t{ &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) },\n-\t{ &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) },\n+static ControlInfoMap RPiControls;\n+\n+inline void initializeRPiControls()\n+{\n+\tRPiControls = {\n+\t\t{ &controls::AeEnable, ControlInfo(false, true) },\n+\t\t{ &controls::ExposureTime, ControlInfo(0, 999999) },\n+\t\t{ &controls::AnalogueGain, ControlInfo(1.0f, 32.0f) },\n+\t\t{ &controls::AeMeteringMode, ControlInfo(0, static_cast<int32_t>(controls::MeteringModeMax)) },\n+\t\t{ &controls::AeConstraintMode, ControlInfo(0, static_cast<int32_t>(controls::ConstraintModeMax)) },\n+\t\t{ &controls::AeExposureMode, ControlInfo(0, static_cast<int32_t>(controls::ExposureModeMax)) },\n+\t\t{ &controls::ExposureValue, ControlInfo(0.0f, 16.0f) },\n+\t\t{ &controls::AwbEnable, ControlInfo(false, true) },\n+\t\t{ &controls::ColourGains, ControlInfo(0.0f, 32.0f) },\n+\t\t{ &controls::AwbMode, ControlInfo(0, static_cast<int32_t>(controls::AwbModeMax)) },\n+\t\t{ &controls::Brightness, ControlInfo(-1.0f, 1.0f) },\n+\t\t{ &controls::Contrast, ControlInfo(0.0f, 32.0f) },\n+\t\t{ &controls::Saturation, ControlInfo(0.0f, 32.0f) },\n+\t\t{ &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) },\n+\t\t{ &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) },\n+\t};\n };\n \n } /* namespace libcamera */\ndiff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\nindex 0555cc4e..805ced33 100644\n--- a/src/ipa/raspberrypi/raspberrypi.cpp\n+++ b/src/ipa/raspberrypi/raspberrypi.cpp\n@@ -19,6 +19,7 @@\n #include <libcamera/ipa/ipa_interface.h>\n #include <libcamera/ipa/ipa_module_info.h>\n #include <libcamera/ipa/raspberrypi.h>\n+#include <libcamera/ipa/raspberrypi_generated.h>\n #include <libcamera/request.h>\n #include <libcamera/span.h>\n \n@@ -60,7 +61,7 @@ namespace libcamera {\n \n LOG_DEFINE_CATEGORY(IPARPI)\n \n-class IPARPi : public IPAInterface\n+class IPARPi : public IPARPiInterface\n {\n public:\n \tIPARPi()\n@@ -68,6 +69,7 @@ public:\n \t\t  frame_count_(0), check_count_(0), mistrust_count_(0),\n \t\t  lsTable_(nullptr)\n \t{\n+\t\tinitializeRPiControls();\n \t}\n \n \t~IPARPi()\n@@ -82,12 +84,14 @@ public:\n \n \tvoid configure(const CameraSensorInfo &sensorInfo,\n \t\t       const std::map<unsigned int, IPAStream> &streamConfig,\n-\t\t       const std::map<unsigned int, const ControlInfoMap &> &entityControls,\n-\t\t       const IPAOperationData &data,\n-\t\t       IPAOperationData *response) override;\n+\t\t       const std::map<unsigned int, ControlInfoMap> &entityControls,\n+\t\t       const RPiConfigInput &data,\n+\t\t       RPiConfigOutput *response) override;\n \tvoid mapBuffers(const std::vector<IPABuffer> &buffers) override;\n \tvoid unmapBuffers(const std::vector<unsigned int> &ids) override;\n-\tvoid processEvent(const IPAOperationData &event) override;\n+\tvoid signalStatReady(const uint32_t bufferId) override;\n+\tvoid signalQueueRequest(const ControlList &controls) override;\n+\tvoid signalIspPrepare(const RPiIspPreparePayload &data) override;\n \n private:\n \tvoid setMode(const CameraSensorInfo &sensorInfo);\n@@ -141,6 +145,11 @@ private:\n \tunsigned int mistrust_count_;\n \t/* LS table allocation passed in from the pipeline handler. */\n \tFileDescriptor lsTableHandle_;\n+\t/*\n+\t * LS table allocation passed in from the pipeline handler,\n+\t * in the context of the pipeline handler.\n+\t */\n+\tint32_t lsTableHandlePH_;\n \tvoid *lsTable_;\n };\n \n@@ -190,15 +199,13 @@ void IPARPi::setMode(const CameraSensorInfo &sensorInfo)\n \n void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n \t\t       [[maybe_unused]] const std::map<unsigned int, IPAStream> &streamConfig,\n-\t\t       const std::map<unsigned int, const ControlInfoMap &> &entityControls,\n-\t\t       const IPAOperationData &ipaConfig,\n-\t\t       IPAOperationData *result)\n+\t\t       const std::map<unsigned int, ControlInfoMap> &entityControls,\n+\t\t       const RPiConfigInput &ipaConfig,\n+\t\t       RPiConfigOutput *result)\n {\n \tif (entityControls.empty())\n \t\treturn;\n \n-\tresult->operation = 0;\n-\n \tunicam_ctrls_ = entityControls.at(0);\n \tisp_ctrls_ = entityControls.at(1);\n \t/* Setup a metadata ControlList to output metadata. */\n@@ -220,11 +227,10 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n \t\thelper_->GetDelays(exposureDelay, gainDelay);\n \t\tsensorMetadata = helper_->SensorEmbeddedDataPresent();\n \n-\t\tresult->data.push_back(gainDelay);\n-\t\tresult->data.push_back(exposureDelay);\n-\t\tresult->data.push_back(sensorMetadata);\n-\n-\t\tresult->operation |= RPI_IPA_CONFIG_STAGGERED_WRITE;\n+\t\tresult->op_ |= RPI_IPA_CONFIG_STAGGERED_WRITE;\n+\t\tresult->staggeredWriteResult_.gainDelay_ = gainDelay;\n+\t\tresult->staggeredWriteResult_.exposureDelay_ = exposureDelay;\n+\t\tresult->staggeredWriteResult_.sensorMetadata_ = sensorMetadata;\n \t}\n \n \t/* Re-assemble camera mode using the sensor info. */\n@@ -240,18 +246,15 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n \t */\n \tframe_count_ = 0;\n \tcheck_count_ = 0;\n-\tunsigned int drop_frame = 0;\n+\tresult->op_ |= RPI_IPA_CONFIG_DROP_FRAMES;\n \tif (controllerInit_) {\n-\t\tdrop_frame = helper_->HideFramesModeSwitch();\n+\t\tresult->dropFrameCount_ = helper_->HideFramesModeSwitch();\n \t\tmistrust_count_ = helper_->MistrustFramesModeSwitch();\n \t} else {\n-\t\tdrop_frame = helper_->HideFramesStartup();\n+\t\tresult->dropFrameCount_ = helper_->HideFramesStartup();\n \t\tmistrust_count_ = helper_->MistrustFramesStartup();\n \t}\n \n-\tresult->data.push_back(drop_frame);\n-\tresult->operation |= RPI_IPA_CONFIG_DROP_FRAMES;\n-\n \tstruct AgcStatus agcStatus;\n \t/* These zero values mean not program anything (unless overwritten). */\n \tagcStatus.shutter_time = 0.0;\n@@ -276,15 +279,15 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n \tif (agcStatus.shutter_time != 0.0 && agcStatus.analogue_gain != 0.0) {\n \t\tControlList ctrls(unicam_ctrls_);\n \t\tapplyAGC(&agcStatus, ctrls);\n-\t\tresult->controls.push_back(ctrls);\n \n-\t\tresult->operation |= RPI_IPA_CONFIG_SENSOR;\n+\t\tresult->op_ |= RPI_IPA_CONFIG_SENSOR;\n+\t\tresult->controls_ = ctrls;\n \t}\n \n \tlastMode_ = mode_;\n \n \t/* Store the lens shading table pointer and handle if available. */\n-\tif (ipaConfig.operation & RPI_IPA_CONFIG_LS_TABLE) {\n+\tif (ipaConfig.op_ & RPI_IPA_CONFIG_LS_TABLE) {\n \t\t/* Remove any previous table, if there was one. */\n \t\tif (lsTable_) {\n \t\t\tmunmap(lsTable_, MAX_LS_GRID_SIZE);\n@@ -292,7 +295,8 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n \t\t}\n \n \t\t/* Map the LS table buffer into user space. */\n-\t\tlsTableHandle_ = FileDescriptor(ipaConfig.data[0]);\n+\t\tlsTableHandle_ = FileDescriptor(ipaConfig.lsTableHandle_);\n+\t\tlsTableHandlePH_ = ipaConfig.lsTableHandleStatic_;\n \t\tif (lsTableHandle_.isValid()) {\n \t\t\tlsTable_ = mmap(nullptr, MAX_LS_GRID_SIZE, PROT_READ | PROT_WRITE,\n \t\t\t\t\tMAP_SHARED, lsTableHandle_.fd(), 0);\n@@ -337,56 +341,38 @@ void IPARPi::unmapBuffers(const std::vector<unsigned int> &ids)\n \t}\n }\n \n-void IPARPi::processEvent(const IPAOperationData &event)\n+void IPARPi::signalStatReady(const uint32_t bufferId)\n {\n-\tswitch (event.operation) {\n-\tcase RPI_IPA_EVENT_SIGNAL_STAT_READY: {\n-\t\tunsigned int bufferId = event.data[0];\n-\n-\t\tif (++check_count_ != frame_count_) /* assert here? */\n-\t\t\tLOG(IPARPI, Error) << \"WARNING: Prepare/Process mismatch!!!\";\n-\t\tif (frame_count_ > mistrust_count_)\n-\t\t\tprocessStats(bufferId);\n-\n-\t\treportMetadata();\n-\n-\t\tIPAOperationData op;\n-\t\top.operation = RPI_IPA_ACTION_STATS_METADATA_COMPLETE;\n-\t\top.data = { bufferId & RPiBufferMask::ID };\n-\t\top.controls = { libcameraMetadata_ };\n-\t\tqueueFrameAction.emit(0, op);\n-\t\tbreak;\n-\t}\n+\tif (++check_count_ != frame_count_) /* assert here? */\n+\t\tLOG(IPARPI, Error) << \"WARNING: Prepare/Process mismatch!!!\";\n+\tif (frame_count_ > mistrust_count_)\n+\t\tprocessStats(bufferId);\n \n-\tcase RPI_IPA_EVENT_SIGNAL_ISP_PREPARE: {\n-\t\tunsigned int embeddedbufferId = event.data[0];\n-\t\tunsigned int bayerbufferId = event.data[1];\n+\treportMetadata();\n \n-\t\t/*\n-\t\t * At start-up, or after a mode-switch, we may want to\n-\t\t * avoid running the control algos for a few frames in case\n-\t\t * they are \"unreliable\".\n-\t\t */\n-\t\tprepareISP(embeddedbufferId);\n-\t\tframe_count_++;\n-\n-\t\t/* Ready to push the input buffer into the ISP. */\n-\t\tIPAOperationData op;\n-\t\top.operation = RPI_IPA_ACTION_RUN_ISP;\n-\t\top.data = { bayerbufferId & RPiBufferMask::ID };\n-\t\tqueueFrameAction.emit(0, op);\n-\t\tbreak;\n-\t}\n+\tstatsMetadataComplete.emit(bufferId & RPiBufferMask::ID, libcameraMetadata_);\n+}\n \n-\tcase RPI_IPA_EVENT_QUEUE_REQUEST: {\n-\t\tqueueRequest(event.controls[0]);\n-\t\tbreak;\n-\t}\n+void IPARPi::signalQueueRequest(const ControlList &controls)\n+{\n+\tqueueRequest(controls);\n+}\n \n-\tdefault:\n-\t\tLOG(IPARPI, Error) << \"Unknown event \" << event.operation;\n-\t\tbreak;\n-\t}\n+void IPARPi::signalIspPrepare(const RPiIspPreparePayload &data)\n+{\n+\tunsigned int embeddedbufferId = data.embeddedbufferId_;\n+\tunsigned int bayerbufferId = data.bayerbufferId_;\n+\n+\t/*\n+\t * At start-up, or after a mode-switch, we may want to\n+\t * avoid running the control algos for a few frames in case\n+\t * they are \"unreliable\".\n+\t */\n+\tprepareISP(embeddedbufferId);\n+\tframe_count_++;\n+\n+\t/* Ready to push the input buffer into the ISP. */\n+\trunIsp.emit(bayerbufferId & RPiBufferMask::ID);\n }\n \n void IPARPi::reportMetadata()\n@@ -489,6 +475,8 @@ void IPARPi::queueRequest(const ControlList &controls)\n \t/* Clear the return metadata buffer. */\n \tlibcameraMetadata_.clear();\n \n+\tLOG(IPARPI, Info) << \"Request ctrl length: \" << controls.size();\n+\n \tfor (auto const &ctrl : controls) {\n \t\tLOG(IPARPI, Info) << \"Request ctrl: \"\n \t\t\t\t  << controls::controls.at(ctrl.first)->name()\n@@ -698,10 +686,7 @@ void IPARPi::queueRequest(const ControlList &controls)\n \n void IPARPi::returnEmbeddedBuffer(unsigned int bufferId)\n {\n-\tIPAOperationData op;\n-\top.operation = RPI_IPA_ACTION_EMBEDDED_COMPLETE;\n-\top.data = { bufferId & RPiBufferMask::ID };\n-\tqueueFrameAction.emit(0, op);\n+\tembeddedComplete.emit(bufferId & RPiBufferMask::ID);\n }\n \n void IPARPi::prepareISP(unsigned int bufferId)\n@@ -762,12 +747,8 @@ void IPARPi::prepareISP(unsigned int bufferId)\n \t\tif (dpcStatus)\n \t\t\tapplyDPC(dpcStatus, ctrls);\n \n-\t\tif (!ctrls.empty()) {\n-\t\t\tIPAOperationData op;\n-\t\t\top.operation = RPI_IPA_ACTION_V4L2_SET_ISP;\n-\t\t\top.controls.push_back(ctrls);\n-\t\t\tqueueFrameAction.emit(0, op);\n-\t\t}\n+\t\tif (!ctrls.empty())\n+\t\t\tsetIsp.emit(ctrls);\n \t}\n }\n \n@@ -823,10 +804,7 @@ void IPARPi::processStats(unsigned int bufferId)\n \t\tControlList ctrls(unicam_ctrls_);\n \t\tapplyAGC(&agcStatus, ctrls);\n \n-\t\tIPAOperationData op;\n-\t\top.operation = RPI_IPA_ACTION_V4L2_SET_STAGGERED;\n-\t\top.controls.push_back(ctrls);\n-\t\tqueueFrameAction.emit(0, op);\n+\t\tsetStaggered.emit(ctrls);\n \t}\n }\n \n@@ -1056,7 +1034,7 @@ void IPARPi::applyLS(const struct AlscStatus *lsStatus, ControlList &ctrls)\n \t\t.grid_width = w,\n \t\t.grid_stride = w,\n \t\t.grid_height = h,\n-\t\t.dmabuf = lsTableHandle_.fd(),\n+\t\t.dmabuf = lsTableHandlePH_,\n \t\t.ref_transform = 0,\n \t\t.corner_sampled = 1,\n \t\t.gain_format = GAIN_FORMAT_U4P10\n@@ -1136,9 +1114,9 @@ const struct IPAModuleInfo ipaModuleInfo = {\n \t\"raspberrypi\",\n };\n \n-struct ipa_context *ipaCreate()\n+IPAInterface *ipaCreate()\n {\n-\treturn new IPAInterfaceWrapper(std::make_unique<IPARPi>());\n+\treturn new IPARPi();\n }\n \n }; /* extern \"C\" */\ndiff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\nindex 50f07182..49e28e0c 100644\n--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n@@ -16,7 +16,9 @@\n #include <libcamera/control_ids.h>\n #include <libcamera/file_descriptor.h>\n #include <libcamera/formats.h>\n+#include <libcamera/ipa/ipa_proxy_raspberrypi.h>\n #include <libcamera/ipa/raspberrypi.h>\n+#include <libcamera/ipa/raspberrypi_generated.h>\n #include <libcamera/logging.h>\n #include <libcamera/property_ids.h>\n #include <libcamera/request.h>\n@@ -142,7 +144,11 @@ public:\n \tint loadIPA();\n \tint configureIPA();\n \n-\tvoid queueFrameAction(unsigned int frame, const IPAOperationData &action);\n+\tvoid statsMetadataComplete(uint32_t bufferId, const ControlList &controls);\n+\tvoid runIsp(uint32_t bufferId);\n+\tvoid embeddedComplete(uint32_t bufferId);\n+\tvoid setIsp(const ControlList &controls);\n+\tvoid setStaggered(const ControlList &controls);\n \n \t/* bufferComplete signal handlers. */\n \tvoid unicamBufferDequeue(FrameBuffer *buffer);\n@@ -154,6 +160,8 @@ public:\n \tvoid handleExternalBuffer(FrameBuffer *buffer, RPi::RPiStream *stream);\n \tvoid handleState();\n \n+\tstd::unique_ptr<IPAProxyRPi> ipa_;\n+\n \tCameraSensor *sensor_;\n \t/* Array of Unicam and ISP device streams and associated buffers/streams. */\n \tRPi::RPiDevice<Unicam, 2> unicam_;\n@@ -356,6 +364,7 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()\n PipelineHandlerRPi::PipelineHandlerRPi(CameraManager *manager)\n \t: PipelineHandler(manager), unicam_(nullptr), isp_(nullptr)\n {\n+\tinitializeRPiControls();\n }\n \n CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n@@ -974,11 +983,17 @@ void RPiCameraData::frameStarted(uint32_t sequence)\n \n int RPiCameraData::loadIPA()\n {\n-\tipa_ = IPAManager::createIPA(pipe_, 1, 1);\n+\tstd::unique_ptr<IPAProxy> ptr = IPAManager::createIPA(pipe_, 1, 1);\n+\tipa_ = std::unique_ptr<IPAProxyRPi>{static_cast<IPAProxyRPi*>(std::move(ptr).release())};\n+\n \tif (!ipa_)\n \t\treturn -ENOENT;\n \n-\tipa_->queueFrameAction.connect(this, &RPiCameraData::queueFrameAction);\n+\tipa_->statsMetadataComplete.connect(this, &RPiCameraData::statsMetadataComplete);\n+\tipa_->runIsp.connect(this, &RPiCameraData::runIsp);\n+\tipa_->embeddedComplete.connect(this, &RPiCameraData::embeddedComplete);\n+\tipa_->setIsp.connect(this, &RPiCameraData::setIsp);\n+\tipa_->setStaggered.connect(this, &RPiCameraData::setStaggered);\n \n \tIPASettings settings{\n \t\t.configurationFile = ipa_->configurationFile(sensor_->model() + \".json\")\n@@ -990,8 +1005,8 @@ int RPiCameraData::loadIPA()\n int RPiCameraData::configureIPA()\n {\n \tstd::map<unsigned int, IPAStream> streamConfig;\n-\tstd::map<unsigned int, const ControlInfoMap &> entityControls;\n-\tIPAOperationData ipaConfig = {};\n+\tstd::map<unsigned int, ControlInfoMap> entityControls;\n+\tRPiConfigInput ipaConfig;\n \n \t/* Get the device format to pass to the IPA. */\n \tV4L2DeviceFormat sensorFormat;\n@@ -1017,8 +1032,9 @@ int RPiCameraData::configureIPA()\n \t\t\treturn -ENOMEM;\n \n \t\t/* Allow the IPA to mmap the LS table via the file descriptor. */\n-\t\tipaConfig.operation = RPI_IPA_CONFIG_LS_TABLE;\n-\t\tipaConfig.data = { static_cast<unsigned int>(lsTable_.fd()) };\n+\t\tipaConfig.op_ = RPI_IPA_CONFIG_LS_TABLE;\n+\t\tipaConfig.lsTableHandle_ = lsTable_;\n+\t\tipaConfig.lsTableHandleStatic_ = lsTable_.fd();\n \t}\n \n \tCameraSensorInfo sensorInfo = {};\n@@ -1029,105 +1045,92 @@ int RPiCameraData::configureIPA()\n \t}\n \n \t/* Ready the IPA - it must know about the sensor resolution. */\n-\tIPAOperationData result;\n+\tRPiConfigOutput result;\n \n \tipa_->configure(sensorInfo, streamConfig, entityControls, ipaConfig,\n \t\t\t&result);\n \n-\tunsigned int resultIdx = 0;\n-\tif (result.operation & RPI_IPA_CONFIG_STAGGERED_WRITE) {\n+\tif (result.op_ & RPI_IPA_CONFIG_STAGGERED_WRITE) {\n+\n \t\t/*\n \t\t * Setup our staggered control writer with the sensor default\n \t\t * gain and exposure delays.\n \t\t */\n \t\tif (!staggeredCtrl_) {\n \t\t\tstaggeredCtrl_.init(unicam_[Unicam::Image].dev(),\n-\t\t\t\t\t    { { V4L2_CID_ANALOGUE_GAIN, result.data[resultIdx++] },\n-\t\t\t\t\t      { V4L2_CID_EXPOSURE, result.data[resultIdx++] } });\n-\t\t\tsensorMetadata_ = result.data[resultIdx++];\n+\t\t\t\t\t{ { V4L2_CID_ANALOGUE_GAIN,\n+\t\t\t\t\tresult.staggeredWriteResult_.gainDelay_ },\n+\t\t\t\t\t{ V4L2_CID_EXPOSURE,\n+\t\t\t\t\tresult.staggeredWriteResult_.exposureDelay_ } });\n+\t\t\tsensorMetadata_ = result.staggeredWriteResult_.sensorMetadata_;\n+\t\t}\n+\n+\t\tif (result.op_ & RPI_IPA_CONFIG_SENSOR) {\n+\t\t\tconst ControlList &ctrls = result.controls_;\n+\t\t\tif (!staggeredCtrl_.set(ctrls))\n+\t\t\t\tLOG(RPI, Error) << \"V4L2 staggered set failed\";\n \t\t}\n-\t}\n \n-\tif (result.operation & RPI_IPA_CONFIG_SENSOR) {\n-\t\tconst ControlList &ctrls = result.controls[0];\n-\t\tif (!staggeredCtrl_.set(ctrls))\n-\t\t\tLOG(RPI, Error) << \"V4L2 staggered set failed\";\n \t}\n \n-\tif (result.operation & RPI_IPA_CONFIG_DROP_FRAMES) {\n+\tif (result.op_ & RPI_IPA_CONFIG_DROP_FRAMES) {\n \t\t/* Configure the number of dropped frames required on startup. */\n-\t\tdropFrameCount_ = result.data[resultIdx++];\n+\t\tdropFrameCount_ = result.dropFrameCount_;\n \t}\n \n \treturn 0;\n }\n \n-void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame,\n-\t\t\t\t     const IPAOperationData &action)\n+void RPiCameraData::statsMetadataComplete(uint32_t bufferId, const ControlList &controls)\n {\n-\t/*\n-\t * The following actions can be handled when the pipeline handler is in\n-\t * a stopped state.\n-\t */\n-\tswitch (action.operation) {\n-\tcase RPI_IPA_ACTION_V4L2_SET_STAGGERED: {\n-\t\tconst ControlList &controls = action.controls[0];\n-\t\tif (!staggeredCtrl_.set(controls))\n-\t\t\tLOG(RPI, Error) << \"V4L2 staggered set failed\";\n-\t\tgoto done;\n-\t}\n+\tif (state_ == State::Stopped)\n+\t\thandleState();\n \n-\tcase RPI_IPA_ACTION_V4L2_SET_ISP: {\n-\t\tControlList controls = action.controls[0];\n-\t\tisp_[Isp::Input].dev()->setControls(&controls);\n-\t\tgoto done;\n-\t}\n-\t}\n+\tFrameBuffer *buffer = isp_[Isp::Stats].getBuffers().at(bufferId);\n+\n+\thandleStreamBuffer(buffer, &isp_[Isp::Stats]);\n+\t/* Fill the Request metadata buffer with what the IPA has provided */\n+\trequestQueue_.front()->metadata() = std::move(controls);\n+\tstate_ = State::IpaComplete;\n+\thandleState();\n+}\n \n+void RPiCameraData::runIsp(uint32_t bufferId)\n+{\n \tif (state_ == State::Stopped)\n-\t\tgoto done;\n+\t\thandleState();\n \n-\t/*\n-\t * The following actions must not be handled when the pipeline handler\n-\t * is in a stopped state.\n-\t */\n-\tswitch (action.operation) {\n-\tcase RPI_IPA_ACTION_STATS_METADATA_COMPLETE: {\n-\t\tunsigned int bufferId = action.data[0];\n-\t\tFrameBuffer *buffer = isp_[Isp::Stats].getBuffers().at(bufferId);\n-\n-\t\thandleStreamBuffer(buffer, &isp_[Isp::Stats]);\n-\t\t/* Fill the Request metadata buffer with what the IPA has provided */\n-\t\trequestQueue_.front()->metadata() = std::move(action.controls[0]);\n-\t\tstate_ = State::IpaComplete;\n-\t\tbreak;\n-\t}\n+\tFrameBuffer *buffer = unicam_[Unicam::Image].getBuffers().at(bufferId);\n \n-\tcase RPI_IPA_ACTION_EMBEDDED_COMPLETE: {\n-\t\tunsigned int bufferId = action.data[0];\n-\t\tFrameBuffer *buffer = unicam_[Unicam::Embedded].getBuffers().at(bufferId);\n-\t\thandleStreamBuffer(buffer, &unicam_[Unicam::Embedded]);\n-\t\tbreak;\n-\t}\n+\tLOG(RPI, Debug) << \"Input re-queue to ISP, buffer id \" << bufferId\n+\t\t\t<< \", timestamp: \" << buffer->metadata().timestamp;\n \n-\tcase RPI_IPA_ACTION_RUN_ISP: {\n-\t\tunsigned int bufferId = action.data[0];\n-\t\tFrameBuffer *buffer = unicam_[Unicam::Image].getBuffers().at(bufferId);\n+\tisp_[Isp::Input].queueBuffer(buffer);\n+\tispOutputCount_ = 0;\n+\thandleState();\n+}\n \n-\t\tLOG(RPI, Debug) << \"Input re-queue to ISP, buffer id \" << bufferId\n-\t\t\t\t<< \", timestamp: \" << buffer->metadata().timestamp;\n+void RPiCameraData::embeddedComplete(uint32_t bufferId)\n+{\n+\tif (state_ == State::Stopped)\n+\t\thandleState();\n \n-\t\tisp_[Isp::Input].queueBuffer(buffer);\n-\t\tispOutputCount_ = 0;\n-\t\tbreak;\n-\t}\n+\tFrameBuffer *buffer = unicam_[Unicam::Embedded].getBuffers().at(bufferId);\n+\thandleStreamBuffer(buffer, &unicam_[Unicam::Embedded]);\n+\thandleState();\n+}\n \n-\tdefault:\n-\t\tLOG(RPI, Error) << \"Unknown action \" << action.operation;\n-\t\tbreak;\n-\t}\n+void RPiCameraData::setIsp(const ControlList &controls)\n+{\n+\tControlList ctrls = controls;\n+\tisp_[Isp::Input].dev()->setControls(&ctrls);\n+\thandleState();\n+}\n \n-done:\n+void RPiCameraData::setStaggered(const ControlList &controls)\n+{\n+\tif (!staggeredCtrl_.set(controls))\n+\t\tLOG(RPI, Error) << \"V4L2 staggered set failed\";\n \thandleState();\n }\n \n@@ -1227,10 +1230,7 @@ void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer)\n \t * application until after the IPA signals so.\n \t */\n \tif (stream == &isp_[Isp::Stats]) {\n-\t\tIPAOperationData op;\n-\t\top.operation = RPI_IPA_EVENT_SIGNAL_STAT_READY;\n-\t\top.data = { RPiBufferMask::STATS | static_cast<unsigned int>(index) };\n-\t\tipa_->processEvent(op);\n+\t\tipa_->signalStatReady(RPiBufferMask::STATS | static_cast<unsigned int>(index));\n \t} else {\n \t\t/* Any other ISP output can be handed back to the application now. */\n \t\thandleStreamBuffer(buffer, stream);\n@@ -1403,7 +1403,6 @@ void RPiCameraData::checkRequestCompleted()\n void RPiCameraData::tryRunPipeline()\n {\n \tFrameBuffer *bayerBuffer, *embeddedBuffer;\n-\tIPAOperationData op;\n \n \t/* If any of our request or buffer queues are empty, we cannot proceed. */\n \tif (state_ != State::Idle || requestQueue_.empty() ||\n@@ -1454,9 +1453,7 @@ void RPiCameraData::tryRunPipeline()\n \t * queue the ISP output buffer listed in the request to start the HW\n \t * pipeline.\n \t */\n-\top.operation = RPI_IPA_EVENT_QUEUE_REQUEST;\n-\top.controls = { request->controls() };\n-\tipa_->processEvent(op);\n+\tipa_->signalQueueRequest(request->controls());\n \n \t/* Ready to use the buffers, pop them off the queue. */\n \tbayerQueue_.pop();\n@@ -1472,10 +1469,10 @@ void RPiCameraData::tryRunPipeline()\n \t\t\t<< \" Bayer buffer id: \" << bayerId\n \t\t\t<< \" Embedded buffer id: \" << embeddedId;\n \n-\top.operation = RPI_IPA_EVENT_SIGNAL_ISP_PREPARE;\n-\top.data = { RPiBufferMask::EMBEDDED_DATA | embeddedId,\n-\t\t    RPiBufferMask::BAYER_DATA | bayerId };\n-\tipa_->processEvent(op);\n+\tRPiIspPreparePayload ispPrepare;\n+\tispPrepare.embeddedbufferId_ = RPiBufferMask::EMBEDDED_DATA | embeddedId;\n+\tispPrepare.bayerbufferId_ = RPiBufferMask::BAYER_DATA | bayerId;\n+\tipa_->signalIspPrepare(ispPrepare);\n }\n \n void RPiCameraData::tryFlushQueues()\n","prefixes":["libcamera-devel","28/38"]}