[{"id":25354,"web_url":"https://patchwork.libcamera.org/comment/25354/","msgid":"<Y0CvltJs52pAY7EX@pendragon.ideasonboard.com>","date":"2022-10-07T23:00:38","subject":"Re: [libcamera-devel] [PATCH v2 09/10] ipa: raspberrypi: Allow full\n\tline length control","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Naush,\n\nThank you for the patch.\n\nOn Thu, Oct 06, 2022 at 02:17:43PM +0100, Naushir Patuck via libcamera-devel wrote:\n> Rename CamHelper::getVBlanking to CamHelper::getBlanking, and update the\n> calculations in that function to return both horizontal and vertical blanking\n> values for a given exposure time and frame duration limits. The calculations\n> are setup such that vertical blanking is extended to the maximum allowable\n> value, and any remainder gets put into horizontal blanking.\n> \n> The calculated horizontal blanking value is now returned to the pipeline handler\n> to pass into DelayedControls to program into the sensor.\n> \n> Update the IPA to now specify the maximum frame duration from the maximum\n> horizontal + vertical blanking values provided by the sensor mode. Additionally,\n> the IPA now uses the frame specific horizontal blanking value (as returned by\n> DelayedControls) in all instances.\n> \n> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> Tested-by: Dave Stevenson <dave.stevenson@raspberrypi.com>\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> ---\n>  src/ipa/raspberrypi/cam_helper.cpp        | 48 +++++++++++++++++------\n>  src/ipa/raspberrypi/cam_helper.h          |  7 ++--\n>  src/ipa/raspberrypi/cam_helper_imx477.cpp | 24 +++++++-----\n>  src/ipa/raspberrypi/cam_helper_imx519.cpp | 24 +++++++-----\n>  src/ipa/raspberrypi/raspberrypi.cpp       | 43 ++++++++++++--------\n>  5 files changed, 95 insertions(+), 51 deletions(-)\n> \n> diff --git a/src/ipa/raspberrypi/cam_helper.cpp b/src/ipa/raspberrypi/cam_helper.cpp\n> index bc3f66a51254..afbc03d36b02 100644\n> --- a/src/ipa/raspberrypi/cam_helper.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper.cpp\n> @@ -7,6 +7,7 @@\n>  \n>  #include <linux/videodev2.h>\n>  \n> +#include <limits>\n>  #include <map>\n>  #include <string.h>\n>  \n> @@ -70,31 +71,56 @@ Duration CamHelper::exposure(uint32_t exposureLines, const Duration lineLength)\n>  \treturn exposureLines * lineLength;\n>  }\n>  \n> -uint32_t CamHelper::getVBlanking(Duration &exposure,\n> -\t\t\t\t Duration minFrameDuration,\n> -\t\t\t\t Duration maxFrameDuration) const\n> +std::pair<uint32_t, uint32_t> CamHelper::getBlanking(Duration &exposure,\n> +\t\t\t\t\t\t     Duration minFrameDuration,\n> +\t\t\t\t\t\t     Duration maxFrameDuration) const\n>  {\n> -\tuint32_t frameLengthMin, frameLengthMax, vblank;\n> -\tuint32_t exposureLines = CamHelper::exposureLines(exposure, mode_.minLineLength);\n> +\tuint32_t frameLengthMin, frameLengthMax, vblank, hblank;\n> +\tDuration lineLength = mode_.minLineLength;\n>  \n>  \t/*\n>  \t * minFrameDuration and maxFrameDuration are clamped by the caller\n>  \t * based on the limits for the active sensor mode.\n> +\t *\n> +\t * frameLengthMax gets calculated on the smallest line length as we do\n> +\t * not want to extend that unless absolutely necessary.\n>  \t */\n>  \tframeLengthMin = minFrameDuration / mode_.minLineLength;\n>  \tframeLengthMax = maxFrameDuration / mode_.minLineLength;\n>  \n> +\t/*\n> +\t * Watch out for (exposureLines + frameIntegrationDiff_) overflowing a\n> +\t * uint32_t in the std::clamp() below when the exposure time is\n> +\t * extremely (extremely!) long - as happens when the IPA calculates the\n> +\t * maximum possible exposure time.\n> +\t */\n> +\tuint32_t exposureLines = std::min(CamHelper::exposureLines(exposure, lineLength),\n> +\t\t\t\t\t  std::numeric_limits<uint32_t>::max() - frameIntegrationDiff_);\n> +\tuint32_t frameLengthLines = std::clamp(exposureLines + frameIntegrationDiff_,\n> +\t\t\t\t\t       frameLengthMin, frameLengthMax);\n> +\n> +\t/*\n> +\t * If our frame length lines is above the maximum allowed, see if we can\n> +\t * extend the line length to accommodate the requested frame length.\n> +\t */\n> +\tif (frameLengthLines > mode_.maxFrameLength) {\n> +\t\tDuration lineLengthAdjusted = lineLength * frameLengthLines / mode_.maxFrameLength;\n> +\t\tlineLength = std::min(mode_.maxLineLength, lineLengthAdjusted);\n> +\t\tframeLengthLines = mode_.maxFrameLength;\n> +\t}\n> +\n> +\thblank = lineLengthToHblank(lineLength);\n> +\tvblank = frameLengthLines - mode_.height;\n> +\n>  \t/*\n>  \t * Limit the exposure to the maximum frame duration requested, and\n>  \t * re-calculate if it has been clipped.\n>  \t */\n> -\texposureLines = std::min(frameLengthMax - frameIntegrationDiff_, exposureLines);\n> -\texposure = CamHelper::exposure(exposureLines, mode_.minLineLength);\n> +\texposureLines = std::min(frameLengthLines - frameIntegrationDiff_,\n> +\t\t\t\t CamHelper::exposureLines(exposure, lineLength));\n> +\texposure = CamHelper::exposure(exposureLines, lineLength);\n>  \n> -\t/* Limit the vblank to the range allowed by the frame length limits. */\n> -\tvblank = std::clamp(exposureLines + frameIntegrationDiff_,\n> -\t\t\t    frameLengthMin, frameLengthMax) - mode_.height;\n> -\treturn vblank;\n> +\treturn { vblank, hblank };\n>  }\n>  \n>  Duration CamHelper::hblankToLineLength(uint32_t hblank) const\n> diff --git a/src/ipa/raspberrypi/cam_helper.h b/src/ipa/raspberrypi/cam_helper.h\n> index 6cd1dd397b91..b3f8c9803094 100644\n> --- a/src/ipa/raspberrypi/cam_helper.h\n> +++ b/src/ipa/raspberrypi/cam_helper.h\n> @@ -8,6 +8,7 @@\n>  \n>  #include <memory>\n>  #include <string>\n> +#include <utility>\n>  \n>  #include <libcamera/base/span.h>\n>  #include <libcamera/base/utils.h>\n> @@ -82,9 +83,9 @@ public:\n>  \t\t\t\t       const libcamera::utils::Duration lineLength) const;\n>  \tvirtual libcamera::utils::Duration exposure(uint32_t exposureLines,\n>  \t\t\t\t\t\t    const libcamera::utils::Duration lineLength) const;\n> -\tvirtual uint32_t getVBlanking(libcamera::utils::Duration &exposure,\n> -\t\t\t\t      libcamera::utils::Duration minFrameDuration,\n> -\t\t\t\t      libcamera::utils::Duration maxFrameDuration) const;\n> +\tvirtual std::pair<uint32_t, uint32_t> getBlanking(libcamera::utils::Duration &exposure,\n> +\t\t\t\t\t\t\t  libcamera::utils::Duration minFrameDuration,\n> +\t\t\t\t\t\t\t  libcamera::utils::Duration maxFrameDuration) const;\n>  \tlibcamera::utils::Duration hblankToLineLength(uint32_t hblank) const;\n>  \tuint32_t lineLengthToHblank(const libcamera::utils::Duration &duration) const;\n>  \tlibcamera::utils::Duration lineLengthPckToDuration(uint32_t lineLengthPck) const;\n> diff --git a/src/ipa/raspberrypi/cam_helper_imx477.cpp b/src/ipa/raspberrypi/cam_helper_imx477.cpp\n> index 76a82cc51378..19a5e471c27e 100644\n> --- a/src/ipa/raspberrypi/cam_helper_imx477.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper_imx477.cpp\n> @@ -46,8 +46,8 @@ public:\n>  \tuint32_t gainCode(double gain) const override;\n>  \tdouble gain(uint32_t gainCode) const override;\n>  \tvoid prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata) override;\n> -\tuint32_t getVBlanking(Duration &exposure, Duration minFrameDuration,\n> -\t\t\t      Duration maxFrameDuration) const override;\n> +\tstd::pair<uint32_t, uint32_t> getBlanking(Duration &exposure, Duration minFrameDuration,\n> +\t\t\t\t\t\t  Duration maxFrameDuration) const override;\n>  \tvoid getDelays(int &exposureDelay, int &gainDelay,\n>  \t\t       int &vblankDelay, int &hblankDelay) const override;\n>  \tbool sensorEmbeddedDataPresent() const override;\n> @@ -118,15 +118,19 @@ void CamHelperImx477::prepare(libcamera::Span<const uint8_t> buffer, Metadata &m\n>  \t}\n>  }\n>  \n> -uint32_t CamHelperImx477::getVBlanking(Duration &exposure,\n> -\t\t\t\t       Duration minFrameDuration,\n> -\t\t\t\t       Duration maxFrameDuration) const\n> +std::pair<uint32_t, uint32_t> CamHelperImx477::getBlanking(Duration &exposure,\n> +\t\t\t\t\t\t\t   Duration minFrameDuration,\n> +\t\t\t\t\t\t\t   Duration maxFrameDuration) const\n>  {\n>  \tuint32_t frameLength, exposureLines;\n>  \tunsigned int shift = 0;\n>  \n> -\tframeLength = mode_.height + CamHelper::getVBlanking(exposure, minFrameDuration,\n> -\t\t\t\t\t\t\t     maxFrameDuration);\n> +\tauto [vblank, hblank] = CamHelper::getBlanking(exposure, minFrameDuration,\n> +\t\t\t\t\t\t       maxFrameDuration);\n> +\n> +\tframeLength = mode_.height + vblank;\n> +\tDuration lineLength = hblankToLineLength(hblank);\n> +\n>  \t/*\n>  \t * Check if the frame length calculated needs to be setup for long\n>  \t * exposure mode. This will require us to use a long exposure scale\n> @@ -144,12 +148,12 @@ uint32_t CamHelperImx477::getVBlanking(Duration &exposure,\n>  \tif (shift) {\n>  \t\t/* Account for any rounding in the scaled frame length value. */\n>  \t\tframeLength <<= shift;\n> -\t\texposureLines = CamHelperImx477::exposureLines(exposure, mode_.minLineLength);\n> +\t\texposureLines = CamHelperImx477::exposureLines(exposure, lineLength);\n>  \t\texposureLines = std::min(exposureLines, frameLength - frameIntegrationDiff);\n> -\t\texposure = CamHelperImx477::exposure(exposureLines, mode_.minLineLength);\n> +\t\texposure = CamHelperImx477::exposure(exposureLines, lineLength);\n>  \t}\n>  \n> -\treturn frameLength - mode_.height;\n> +\treturn { frameLength - mode_.height, hblank };\n>  }\n>  \n>  void CamHelperImx477::getDelays(int &exposureDelay, int &gainDelay,\n> diff --git a/src/ipa/raspberrypi/cam_helper_imx519.cpp b/src/ipa/raspberrypi/cam_helper_imx519.cpp\n> index 9dff1eeb899f..d2eb171912da 100644\n> --- a/src/ipa/raspberrypi/cam_helper_imx519.cpp\n> +++ b/src/ipa/raspberrypi/cam_helper_imx519.cpp\n> @@ -46,8 +46,8 @@ public:\n>  \tuint32_t gainCode(double gain) const override;\n>  \tdouble gain(uint32_t gainCode) const override;\n>  \tvoid prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata) override;\n> -\tuint32_t getVBlanking(Duration &exposure, Duration minFrameDuration,\n> -\t\t\t      Duration maxFrameDuration) const override;\n> +\tstd::pair<uint32_t, uint32_t> getBlanking(Duration &exposure, Duration minFrameDuration,\n> +\t\t\t\t\t\t  Duration maxFrameDuration) const override;\n>  \tvoid getDelays(int &exposureDelay, int &gainDelay,\n>  \t\t       int &vblankDelay, int &hblankDelay) const override;\n>  \tbool sensorEmbeddedDataPresent() const override;\n> @@ -118,15 +118,19 @@ void CamHelperImx519::prepare(libcamera::Span<const uint8_t> buffer, Metadata &m\n>  \t}\n>  }\n>  \n> -uint32_t CamHelperImx519::getVBlanking(Duration &exposure,\n> -\t\t\t\t       Duration minFrameDuration,\n> -\t\t\t\t       Duration maxFrameDuration) const\n> +std::pair<uint32_t, uint32_t> CamHelperImx519::getBlanking(Duration &exposure,\n> +\t\t\t\t\t\t\t   Duration minFrameDuration,\n> +\t\t\t\t\t\t\t   Duration maxFrameDuration) const\n>  {\n>  \tuint32_t frameLength, exposureLines;\n>  \tunsigned int shift = 0;\n>  \n> -\tframeLength = mode_.height + CamHelper::getVBlanking(exposure, minFrameDuration,\n> -\t\t\t\t\t\t\t     maxFrameDuration);\n> +\tauto [vblank, hblank] = CamHelper::getBlanking(exposure, minFrameDuration,\n> +\t\t\t\t\t\t       maxFrameDuration);\n> +\n> +\tframeLength = mode_.height + vblank;\n> +\tDuration lineLength = hblankToLineLength(hblank);\n> +\n>  \t/*\n>  \t * Check if the frame length calculated needs to be setup for long\n>  \t * exposure mode. This will require us to use a long exposure scale\n> @@ -144,12 +148,12 @@ uint32_t CamHelperImx519::getVBlanking(Duration &exposure,\n>  \tif (shift) {\n>  \t\t/* Account for any rounding in the scaled frame length value. */\n>  \t\tframeLength <<= shift;\n> -\t\texposureLines = CamHelperImx519::exposureLines(exposure, mode_.minLineLength);\n> +\t\texposureLines = CamHelperImx519::exposureLines(exposure, lineLength);\n>  \t\texposureLines = std::min(exposureLines, frameLength - frameIntegrationDiff);\n> -\t\texposure = CamHelperImx519::exposure(exposureLines, mode_.minLineLength);\n> +\t\texposure = CamHelperImx519::exposure(exposureLines, lineLength);\n>  \t}\n>  \n> -\treturn frameLength - mode_.height;\n> +\treturn { frameLength - mode_.height, hblank };\n>  }\n>  \n>  void CamHelperImx519::getDelays(int &exposureDelay, int &gainDelay,\n> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\n> index c8e15f2b04d1..497a83939ae6 100644\n> --- a/src/ipa/raspberrypi/raspberrypi.cpp\n> +++ b/src/ipa/raspberrypi/raspberrypi.cpp\n> @@ -315,7 +315,7 @@ void IPARPi::start(const ControlList &controls, StartConfig *startConfig)\n>  \t}\n>  \n>  \tstartConfig->dropFrameCount = dropFrameCount_;\n> -\tconst Duration maxSensorFrameDuration = mode_.maxFrameLength * mode_.minLineLength;\n> +\tconst Duration maxSensorFrameDuration = mode_.maxFrameLength * mode_.maxLineLength;\n>  \tstartConfig->maxSensorFrameLengthMs = maxSensorFrameDuration.get<std::milli>();\n>  \n>  \tfirstStart_ = false;\n> @@ -462,7 +462,7 @@ int IPARPi::configure(const IPACameraSensorInfo &sensorInfo,\n>  \t */\n>  \tControlInfoMap::Map ctrlMap = ipaControls;\n>  \tconst Duration minSensorFrameDuration = mode_.minFrameLength * mode_.minLineLength;\n> -\tconst Duration maxSensorFrameDuration = mode_.maxFrameLength * mode_.minLineLength;\n> +\tconst Duration maxSensorFrameDuration = mode_.maxFrameLength * mode_.maxLineLength;\n>  \tctrlMap[&controls::FrameDurationLimits] =\n>  \t\tControlInfo(static_cast<int64_t>(minSensorFrameDuration.get<std::micro>()),\n>  \t\t\t    static_cast<int64_t>(maxSensorFrameDuration.get<std::micro>()));\n> @@ -475,7 +475,7 @@ int IPARPi::configure(const IPACameraSensorInfo &sensorInfo,\n>  \t * will limit the maximum control value based on the current VBLANK value.\n>  \t */\n>  \tDuration maxShutter = Duration::max();\n> -\thelper_->getVBlanking(maxShutter, minSensorFrameDuration, maxSensorFrameDuration);\n> +\thelper_->getBlanking(maxShutter, minSensorFrameDuration, maxSensorFrameDuration);\n>  \tconst uint32_t exposureMin = sensorCtrls_.at(V4L2_CID_EXPOSURE).min().get<int32_t>();\n>  \n>  \tctrlMap[&controls::ExposureTime] =\n> @@ -552,7 +552,7 @@ void IPARPi::reportMetadata()\n>  \t\t\t\t       deviceStatus->shutterSpeed.get<std::micro>());\n>  \t\tlibcameraMetadata_.set(controls::AnalogueGain, deviceStatus->analogueGain);\n>  \t\tlibcameraMetadata_.set(controls::FrameDuration,\n> -\t\t\t\t       helper_->exposure(deviceStatus->frameLength, mode_.minLineLength).get<std::micro>());\n> +\t\t\t\t       helper_->exposure(deviceStatus->frameLength, deviceStatus->lineLength).get<std::micro>());\n>  \t\tif (deviceStatus->sensorTemperature)\n>  \t\t\tlibcameraMetadata_.set(controls::SensorTemperature, *deviceStatus->sensorTemperature);\n>  \t}\n> @@ -1111,7 +1111,7 @@ void IPARPi::fillDeviceStatus(const ControlList &sensorControls)\n>  \tint32_t hblank = sensorControls.get(V4L2_CID_HBLANK).get<int32_t>();\n>  \n>  \tdeviceStatus.lineLength = helper_->hblankToLineLength(hblank);\n> -\tdeviceStatus.shutterSpeed = helper_->exposure(exposureLines, mode_.minLineLength);\n> +\tdeviceStatus.shutterSpeed = helper_->exposure(exposureLines, deviceStatus.lineLength);\n>  \tdeviceStatus.analogueGain = helper_->gain(gainCode);\n>  \tdeviceStatus.frameLength = mode_.height + vblank;\n>  \n> @@ -1157,7 +1157,7 @@ void IPARPi::applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls)\n>  void IPARPi::applyFrameDurations(Duration minFrameDuration, Duration maxFrameDuration)\n>  {\n>  \tconst Duration minSensorFrameDuration = mode_.minFrameLength * mode_.minLineLength;\n> -\tconst Duration maxSensorFrameDuration = mode_.maxFrameLength * mode_.minLineLength;\n> +\tconst Duration maxSensorFrameDuration = mode_.maxFrameLength * mode_.maxLineLength;\n>  \n>  \t/*\n>  \t * This will only be applied once AGC recalculations occur.\n> @@ -1178,11 +1178,11 @@ void IPARPi::applyFrameDurations(Duration minFrameDuration, Duration maxFrameDur\n>  \n>  \t/*\n>  \t * Calculate the maximum exposure time possible for the AGC to use.\n> -\t * getVBlanking() will update maxShutter with the largest exposure\n> +\t * getBlanking() will update maxShutter with the largest exposure\n>  \t * value possible.\n>  \t */\n>  \tDuration maxShutter = Duration::max();\n> -\thelper_->getVBlanking(maxShutter, minFrameDuration_, maxFrameDuration_);\n> +\thelper_->getBlanking(maxShutter, minFrameDuration_, maxFrameDuration_);\n>  \n>  \tRPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(\n>  \t\tcontroller_.getAlgorithm(\"agc\"));\n> @@ -1200,10 +1200,11 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)\n>  \t */\n>  \tgainCode = std::min<int32_t>(gainCode, maxSensorGainCode_);\n>  \n> -\t/* getVBlanking might clip exposure time to the fps limits. */\n> +\t/* getBlanking might clip exposure time to the fps limits. */\n>  \tDuration exposure = agcStatus->shutterTime;\n> -\tint32_t vblanking = helper_->getVBlanking(exposure, minFrameDuration_, maxFrameDuration_);\n> -\tint32_t exposureLines = helper_->exposureLines(exposure, mode_.minLineLength);\n> +\tauto [vblank, hblank] = helper_->getBlanking(exposure, minFrameDuration_, maxFrameDuration_);\n> +\tint32_t exposureLines = helper_->exposureLines(exposure,\n> +\t\t\t\t\t\t       helper_->hblankToLineLength(hblank));\n>  \n>  \tLOG(IPARPI, Debug) << \"Applying AGC Exposure: \" << exposure\n>  \t\t\t   << \" (Shutter lines: \" << exposureLines << \", AGC requested \"\n> @@ -1211,14 +1212,22 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)\n>  \t\t\t   << agcStatus->analogueGain << \" (Gain Code: \"\n>  \t\t\t   << gainCode << \")\";\n>  \n> -\t/*\n> -\t * Due to the behavior of V4L2, the current value of VBLANK could clip the\n> -\t * exposure time without us knowing. The next time though this function should\n> -\t * clip exposure correctly.\n> -\t */\n> -\tctrls.set(V4L2_CID_VBLANK, vblanking);\n> +\tctrls.set(V4L2_CID_VBLANK, static_cast<int32_t>(vblank));\n>  \tctrls.set(V4L2_CID_EXPOSURE, exposureLines);\n>  \tctrls.set(V4L2_CID_ANALOGUE_GAIN, gainCode);\n> +\n> +\t/*\n> +\t * At present, there is no way of knowing if a control is read-only.\n> +\t * As a workaround, assume that if the minimum and maximum values of\n> +\t * the V4L2_CID_HBLANK control are the same, it implies the control\n> +\t * is read-only. This seems to be the case for all the cameras our IPA\n> +\t * works with.\n> +\t *\n> +\t * \\todo The control API ought to have a flag to specify if a control\n> +\t * is read-only which could be used below.\n> +\t */\n> +\tif (mode_.minLineLength != mode_.maxLineLength)\n> +\t\tctrls.set(V4L2_CID_HBLANK, static_cast<int32_t>(hblank));\n>  }\n>  \n>  void IPARPi::applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls)","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 1CC2DBD16B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri,  7 Oct 2022 23:00:46 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 55B8F62D45;\n\tSat,  8 Oct 2022 01:00:45 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 03FB6603D4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat,  8 Oct 2022 01:00:43 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 648B34E6;\n\tSat,  8 Oct 2022 01:00:43 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1665183645;\n\tbh=1eYxAEOHZnpSXpkgAbCA+RVrzkMteLQx5BuEbvAwe+I=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=myMfA0itZnPYyoqlfUKT5pqfdhOt1IGhkBLCeydtqRGVa/EHbGMk+H01lu4bxR6Do\n\tr12osVcixWkpci1Cpw2pbOg2X0iFvvPvxp0ZLzYdvyzB8nSyOedrSEYixisYi1ZYII\n\tD/LdE84TtXOGTIhRxKHr2+1IXWuc0xiD8GBcWq8+ucODN6H1M2GU+yD3r80ms1tEdT\n\tRJ7a/zywbmCu/2oajYyXQgj9wXvQ/fGaI3xHfWcJBf6cnpbYKUBQ7nrWc4avfpLKTi\n\t4/CHxvKCWaAUd3HWODXhEIFs0xupIMyBYExdYDI3HVSJKfnT57oInKpMupeQxUcLSd\n\t1rayRsGZKtOYQ==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1665183643;\n\tbh=1eYxAEOHZnpSXpkgAbCA+RVrzkMteLQx5BuEbvAwe+I=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=fibaHg+RIrP6JzjDYOANkLNZ5mQa0+CZrXrL/EtEy5eucJ+2RiQdsTzUim/HaqVC3\n\tP/NJxtSSUk9DOdX1Gem/fJsxlWwFemTbvvZSgOD+xdOQ6DKq5dR7o5TJygEK+zgZ3n\n\tthsloPnN3wySrv+DQS2B9v/jWUj8+B2Sflc3K5/I="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"fibaHg+R\"; dkim-atps=neutral","Date":"Sat, 8 Oct 2022 02:00:38 +0300","To":"Naushir Patuck <naush@raspberrypi.com>","Message-ID":"<Y0CvltJs52pAY7EX@pendragon.ideasonboard.com>","References":"<20221006131744.5179-1-naush@raspberrypi.com>\n\t<20221006131744.5179-10-naush@raspberrypi.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20221006131744.5179-10-naush@raspberrypi.com>","Subject":"Re: [libcamera-devel] [PATCH v2 09/10] ipa: raspberrypi: Allow full\n\tline length control","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>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]