[{"id":11199,"web_url":"https://patchwork.libcamera.org/comment/11199/","msgid":"<20200706092510.xa2bfrebqeurtqgn@uno.localdomain>","date":"2020-07-06T09:25:10","subject":"Re: [libcamera-devel] [PATCH v2 11/12] ipa: raspberrypi: Pass\n\tsensor config back from configure()","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Laurent,\n\nOn Sat, Jul 04, 2020 at 03:52:26AM +0300, Laurent Pinchart wrote:\n> The Raspberry Pi IPA uses the custom RPI_IPA_ACTION_SET_SENSOR_CONFIG\n> frame action to send the sensor staggered write configuration to the\n> pipeline handler when the IPA is configured. Replace this ad-hoc\n> mechanism by passing the corresponding data back from the IPA to the\n> pipeline handler through the configure() response. This allows\n> synchronous handling of the response on the pipeline handler side.\n>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nLooks good to me, but of course let's wait for RPi people to validate\nthis :)\n\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n\nThanks\n  j\n\n> ---\n> Changes since v1:\n>\n> - Restore RPI_IPA_ACTION_V4L2_SET_ISP handling in stop state\n> - Drop sensor orientation handling based on IPA result\n> ---\n>  include/libcamera/ipa/raspberrypi.h           |  3 +-\n>  src/ipa/raspberrypi/raspberrypi.cpp           | 42 ++++++++-------\n>  .../pipeline/raspberrypi/raspberrypi.cpp      | 53 +++++++++++--------\n>  3 files changed, 56 insertions(+), 42 deletions(-)\n>\n> diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h\n> index 46ce7c286b20..a49377695f22 100644\n> --- a/include/libcamera/ipa/raspberrypi.h\n> +++ b/include/libcamera/ipa/raspberrypi.h\n> @@ -12,6 +12,8 @@\n>\n>  enum RPiConfigParameters {\n>  \tRPI_IPA_CONFIG_LS_TABLE = (1 << 0),\n> +\tRPI_IPA_CONFIG_STAGGERED_WRITE = (1 << 1),\n> +\tRPI_IPA_CONFIG_SENSOR = (1 << 2),\n>  };\n>\n>  enum RPiOperations {\n> @@ -20,7 +22,6 @@ enum RPiOperations {\n>  \tRPI_IPA_ACTION_STATS_METADATA_COMPLETE,\n>  \tRPI_IPA_ACTION_RUN_ISP,\n>  \tRPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME,\n> -\tRPI_IPA_ACTION_SET_SENSOR_CONFIG,\n>  \tRPI_IPA_ACTION_EMBEDDED_COMPLETE,\n>  \tRPI_IPA_EVENT_SIGNAL_STAT_READY,\n>  \tRPI_IPA_EVENT_SIGNAL_ISP_PREPARE,\n> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\n> index 0e39a1137cd0..378ea309fa81 100644\n> --- a/src/ipa/raspberrypi/raspberrypi.cpp\n> +++ b/src/ipa/raspberrypi/raspberrypi.cpp\n> @@ -93,7 +93,7 @@ private:\n>  \tvoid reportMetadata();\n>  \tbool parseEmbeddedData(unsigned int bufferId, struct DeviceStatus &deviceStatus);\n>  \tvoid processStats(unsigned int bufferId);\n> -\tvoid applyAGC(const struct AgcStatus *agcStatus);\n> +\tvoid applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls);\n>  \tvoid applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls);\n>  \tvoid applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls);\n>  \tvoid applyCCM(const struct CcmStatus *ccmStatus, ControlList &ctrls);\n> @@ -195,6 +195,8 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\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> @@ -216,13 +218,11 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n>  \t\thelper_->GetDelays(exposureDelay, gainDelay);\n>  \t\tsensorMetadata = helper_->SensorEmbeddedDataPresent();\n>\n> -\t\tIPAOperationData op;\n> -\t\top.operation = RPI_IPA_ACTION_SET_SENSOR_CONFIG;\n> -\t\top.data.push_back(gainDelay);\n> -\t\top.data.push_back(exposureDelay);\n> -\t\top.data.push_back(sensorMetadata);\n> +\t\tresult->data.push_back(gainDelay);\n> +\t\tresult->data.push_back(exposureDelay);\n> +\t\tresult->data.push_back(sensorMetadata);\n>\n> -\t\tqueueFrameAction.emit(0, op);\n> +\t\tresult->operation |= RPI_IPA_CONFIG_STAGGERED_WRITE;\n>  \t}\n>\n>  \t/* Re-assemble camera mode using the sensor info. */\n> @@ -267,8 +267,13 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n>\n>  \t/* SwitchMode may supply updated exposure/gain values to use. */\n>  \tmetadata.Get(\"agc.status\", agcStatus);\n> -\tif (agcStatus.shutter_time != 0.0 && agcStatus.analogue_gain != 0.0)\n> -\t\tapplyAGC(&agcStatus);\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}\n>\n>  \tlastMode_ = mode_;\n>\n> @@ -775,8 +780,15 @@ void IPARPi::processStats(unsigned int bufferId)\n>  \tcontroller_.Process(statistics, &rpiMetadata_);\n>\n>  \tstruct AgcStatus agcStatus;\n> -\tif (rpiMetadata_.Get(\"agc.status\", agcStatus) == 0)\n> -\t\tapplyAGC(&agcStatus);\n> +\tif (rpiMetadata_.Get(\"agc.status\", agcStatus) == 0) {\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}\n>  }\n>\n>  void IPARPi::applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls)\n> @@ -802,11 +814,8 @@ void IPARPi::applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls)\n>  \t\t  static_cast<int32_t>(awbStatus->gain_b * 1000));\n>  }\n>\n> -void IPARPi::applyAGC(const struct AgcStatus *agcStatus)\n> +void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)\n>  {\n> -\tIPAOperationData op;\n> -\top.operation = RPI_IPA_ACTION_V4L2_SET_STAGGERED;\n> -\n>  \tint32_t gain_code = helper_->GainCode(agcStatus->analogue_gain);\n>  \tint32_t exposure_lines = helper_->ExposureLines(agcStatus->shutter_time);\n>\n> @@ -825,11 +834,8 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus)\n>  \t\t\t   << agcStatus->analogue_gain << \" (Gain Code: \"\n>  \t\t\t   << gain_code << \")\";\n>\n> -\tControlList ctrls(unicam_ctrls_);\n>  \tctrls.set(V4L2_CID_ANALOGUE_GAIN, gain_code);\n>  \tctrls.set(V4L2_CID_EXPOSURE, exposure_lines);\n> -\top.controls.push_back(ctrls);\n> -\tqueueFrameAction.emit(0, op);\n>  }\n>\n>  void IPARPi::applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls)\n> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> index 57602349cab2..9babf9f4a19c 100644\n> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> @@ -819,7 +819,7 @@ int PipelineHandlerRPi::start(Camera *camera)\n>  \t/*\n>  \t * Write the last set of gain and exposure values to the camera before\n>  \t * starting. First check that the staggered ctrl has been initialised\n> -\t * by the IPA action.\n> +\t * by configure().\n>  \t */\n>  \tASSERT(data->staggeredCtrl_);\n>  \tdata->staggeredCtrl_.reset();\n> @@ -1170,15 +1170,36 @@ int RPiCameraData::configureIPA()\n>  \t}\n>\n>  \t/* Ready the IPA - it must know about the sensor resolution. */\n> +\tIPAOperationData result;\n> +\n>  \tipa_->configure(sensorInfo, streamConfig, entityControls, ipaConfig,\n> -\t\t\tnullptr);\n> +\t\t\t&result);\n>\n> -\t/* Configure the H/V flip controls based on the sensor rotation. */\n> -\tControlList ctrls(unicam_[Unicam::Image].dev()->controls());\n> -\tint32_t rotation = sensor_->properties().get(properties::Rotation);\n> -\tctrls.set(V4L2_CID_HFLIP, static_cast<int32_t>(!!rotation));\n> -\tctrls.set(V4L2_CID_VFLIP, static_cast<int32_t>(!!rotation));\n> -\tunicam_[Unicam::Image].dev()->setControls(&ctrls);\n> +\tif (result.operation & RPI_IPA_CONFIG_STAGGERED_WRITE) {\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[0] },\n> +\t\t\t\t\t      { V4L2_CID_EXPOSURE, result.data[1] } });\n> +\t\t\tsensorMetadata_ = result.data[2];\n> +\t\t}\n> +\n> +\t\t/* Configure the H/V flip controls based on the sensor rotation. */\n> +\t\tControlList ctrls(unicam_[Unicam::Image].dev()->controls());\n> +\t\tint32_t rotation = sensor_->properties().get(properties::Rotation);\n> +\t\tctrls.set(V4L2_CID_HFLIP, static_cast<int32_t>(!!rotation));\n> +\t\tctrls.set(V4L2_CID_VFLIP, static_cast<int32_t>(!!rotation));\n> +\t\tunicam_[Unicam::Image].dev()->setControls(&ctrls);\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>  \treturn 0;\n>  }\n> @@ -1191,26 +1212,12 @@ void RPiCameraData::queueFrameAction(unsigned int frame, const IPAOperationData\n>  \t */\n>  \tswitch (action.operation) {\n>  \tcase RPI_IPA_ACTION_V4L2_SET_STAGGERED: {\n> -\t\tControlList controls = action.controls[0];\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\treturn;\n>  \t}\n>\n> -\tcase RPI_IPA_ACTION_SET_SENSOR_CONFIG: {\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, action.data[0] },\n> -\t\t\t\t\t      { V4L2_CID_EXPOSURE, action.data[1] } });\n> -\t\t\tsensorMetadata_ = action.data[2];\n> -\t\t}\n> -\t\treturn;\n> -\t}\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> --\n> Regards,\n>\n> Laurent Pinchart\n>\n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","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 7C290BD792\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  6 Jul 2020 09:21:40 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1F53B60E01;\n\tMon,  6 Jul 2020 11:21:40 +0200 (CEST)","from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net\n\t[217.70.183.197])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 983C8603B1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  6 Jul 2020 11:21:38 +0200 (CEST)","from uno.localdomain (host-79-34-235-173.business.telecomitalia.it\n\t[79.34.235.173]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay5-d.mail.gandi.net (Postfix) with ESMTPSA id 92F051C0011;\n\tMon,  6 Jul 2020 09:21:37 +0000 (UTC)"],"X-Originating-IP":"79.34.235.173","Date":"Mon, 6 Jul 2020 11:25:10 +0200","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Message-ID":"<20200706092510.xa2bfrebqeurtqgn@uno.localdomain>","References":"<20200704005227.21782-1-laurent.pinchart@ideasonboard.com>\n\t<20200704005227.21782-12-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20200704005227.21782-12-laurent.pinchart@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v2 11/12] ipa: raspberrypi: Pass\n\tsensor config back from configure()","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>","Cc":"libcamera-devel@lists.libcamera.org","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>"}},{"id":11242,"web_url":"https://patchwork.libcamera.org/comment/11242/","msgid":"<CAEmqJPpj984dzRf9rdaSre+yNT9vLZAsxDTWvqWfdSe9MXQ6yw@mail.gmail.com>","date":"2020-07-08T11:08:27","subject":"Re: [libcamera-devel] [PATCH v2 11/12] ipa: raspberrypi: Pass\n\tsensor config back from configure()","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"Hi Laurent,\n\nThank you for the patch.  Apart from the one note below,\n\nReviewed-by: Naushir Patuck <naush@raspberrypi.com>\n\nOn Sat, 4 Jul 2020 at 01:52, Laurent Pinchart\n<laurent.pinchart@ideasonboard.com> wrote:\n>\n> The Raspberry Pi IPA uses the custom RPI_IPA_ACTION_SET_SENSOR_CONFIG\n> frame action to send the sensor staggered write configuration to the\n> pipeline handler when the IPA is configured. Replace this ad-hoc\n> mechanism by passing the corresponding data back from the IPA to the\n> pipeline handler through the configure() response. This allows\n> synchronous handling of the response on the pipeline handler side.\n>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n> Changes since v1:\n>\n> - Restore RPI_IPA_ACTION_V4L2_SET_ISP handling in stop state\n> - Drop sensor orientation handling based on IPA result\n> ---\n>  include/libcamera/ipa/raspberrypi.h           |  3 +-\n>  src/ipa/raspberrypi/raspberrypi.cpp           | 42 ++++++++-------\n>  .../pipeline/raspberrypi/raspberrypi.cpp      | 53 +++++++++++--------\n>  3 files changed, 56 insertions(+), 42 deletions(-)\n>\n> diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h\n> index 46ce7c286b20..a49377695f22 100644\n> --- a/include/libcamera/ipa/raspberrypi.h\n> +++ b/include/libcamera/ipa/raspberrypi.h\n> @@ -12,6 +12,8 @@\n>\n>  enum RPiConfigParameters {\n>         RPI_IPA_CONFIG_LS_TABLE = (1 << 0),\n> +       RPI_IPA_CONFIG_STAGGERED_WRITE = (1 << 1),\n> +       RPI_IPA_CONFIG_SENSOR = (1 << 2),\n>  };\n>\n>  enum RPiOperations {\n> @@ -20,7 +22,6 @@ enum RPiOperations {\n>         RPI_IPA_ACTION_STATS_METADATA_COMPLETE,\n>         RPI_IPA_ACTION_RUN_ISP,\n>         RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME,\n> -       RPI_IPA_ACTION_SET_SENSOR_CONFIG,\n>         RPI_IPA_ACTION_EMBEDDED_COMPLETE,\n>         RPI_IPA_EVENT_SIGNAL_STAT_READY,\n>         RPI_IPA_EVENT_SIGNAL_ISP_PREPARE,\n> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\n> index 0e39a1137cd0..378ea309fa81 100644\n> --- a/src/ipa/raspberrypi/raspberrypi.cpp\n> +++ b/src/ipa/raspberrypi/raspberrypi.cpp\n> @@ -93,7 +93,7 @@ private:\n>         void reportMetadata();\n>         bool parseEmbeddedData(unsigned int bufferId, struct DeviceStatus &deviceStatus);\n>         void processStats(unsigned int bufferId);\n> -       void applyAGC(const struct AgcStatus *agcStatus);\n> +       void applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls);\n>         void applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls);\n>         void applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls);\n>         void applyCCM(const struct CcmStatus *ccmStatus, ControlList &ctrls);\n> @@ -195,6 +195,8 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n>         if (entityControls.empty())\n>                 return;\n>\n> +       result->operation = 0;\n> +\n>         unicam_ctrls_ = entityControls.at(0);\n>         isp_ctrls_ = entityControls.at(1);\n>         /* Setup a metadata ControlList to output metadata. */\n> @@ -216,13 +218,11 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n>                 helper_->GetDelays(exposureDelay, gainDelay);\n>                 sensorMetadata = helper_->SensorEmbeddedDataPresent();\n>\n> -               IPAOperationData op;\n> -               op.operation = RPI_IPA_ACTION_SET_SENSOR_CONFIG;\n> -               op.data.push_back(gainDelay);\n> -               op.data.push_back(exposureDelay);\n> -               op.data.push_back(sensorMetadata);\n> +               result->data.push_back(gainDelay);\n> +               result->data.push_back(exposureDelay);\n> +               result->data.push_back(sensorMetadata);\n>\n> -               queueFrameAction.emit(0, op);\n> +               result->operation |= RPI_IPA_CONFIG_STAGGERED_WRITE;\n>         }\n>\n>         /* Re-assemble camera mode using the sensor info. */\n> @@ -267,8 +267,13 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n>\n>         /* SwitchMode may supply updated exposure/gain values to use. */\n>         metadata.Get(\"agc.status\", agcStatus);\n> -       if (agcStatus.shutter_time != 0.0 && agcStatus.analogue_gain != 0.0)\n> -               applyAGC(&agcStatus);\n> +       if (agcStatus.shutter_time != 0.0 && agcStatus.analogue_gain != 0.0) {\n> +               ControlList ctrls(unicam_ctrls_);\n> +               applyAGC(&agcStatus, ctrls);\n> +               result->controls.push_back(ctrls);\n> +\n> +               result->operation |= RPI_IPA_CONFIG_SENSOR;\n> +       }\n>\n>         lastMode_ = mode_;\n>\n> @@ -775,8 +780,15 @@ void IPARPi::processStats(unsigned int bufferId)\n>         controller_.Process(statistics, &rpiMetadata_);\n>\n>         struct AgcStatus agcStatus;\n> -       if (rpiMetadata_.Get(\"agc.status\", agcStatus) == 0)\n> -               applyAGC(&agcStatus);\n> +       if (rpiMetadata_.Get(\"agc.status\", agcStatus) == 0) {\n> +               ControlList ctrls(unicam_ctrls_);\n> +               applyAGC(&agcStatus, ctrls);\n> +\n> +               IPAOperationData op;\n> +               op.operation = RPI_IPA_ACTION_V4L2_SET_STAGGERED;\n> +               op.controls.push_back(ctrls);\n> +               queueFrameAction.emit(0, op);\n> +       }\n>  }\n>\n>  void IPARPi::applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls)\n> @@ -802,11 +814,8 @@ void IPARPi::applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls)\n>                   static_cast<int32_t>(awbStatus->gain_b * 1000));\n>  }\n>\n> -void IPARPi::applyAGC(const struct AgcStatus *agcStatus)\n> +void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)\n>  {\n> -       IPAOperationData op;\n> -       op.operation = RPI_IPA_ACTION_V4L2_SET_STAGGERED;\n> -\n>         int32_t gain_code = helper_->GainCode(agcStatus->analogue_gain);\n>         int32_t exposure_lines = helper_->ExposureLines(agcStatus->shutter_time);\n>\n> @@ -825,11 +834,8 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus)\n>                            << agcStatus->analogue_gain << \" (Gain Code: \"\n>                            << gain_code << \")\";\n>\n> -       ControlList ctrls(unicam_ctrls_);\n>         ctrls.set(V4L2_CID_ANALOGUE_GAIN, gain_code);\n>         ctrls.set(V4L2_CID_EXPOSURE, exposure_lines);\n> -       op.controls.push_back(ctrls);\n> -       queueFrameAction.emit(0, op);\n>  }\n>\n>  void IPARPi::applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls)\n> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> index 57602349cab2..9babf9f4a19c 100644\n> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> @@ -819,7 +819,7 @@ int PipelineHandlerRPi::start(Camera *camera)\n>         /*\n>          * Write the last set of gain and exposure values to the camera before\n>          * starting. First check that the staggered ctrl has been initialised\n> -        * by the IPA action.\n> +        * by configure().\n>          */\n>         ASSERT(data->staggeredCtrl_);\n>         data->staggeredCtrl_.reset();\n> @@ -1170,15 +1170,36 @@ int RPiCameraData::configureIPA()\n>         }\n>\n>         /* Ready the IPA - it must know about the sensor resolution. */\n> +       IPAOperationData result;\n> +\n>         ipa_->configure(sensorInfo, streamConfig, entityControls, ipaConfig,\n> -                       nullptr);\n> +                       &result);\n>\n> -       /* Configure the H/V flip controls based on the sensor rotation. */\n> -       ControlList ctrls(unicam_[Unicam::Image].dev()->controls());\n> -       int32_t rotation = sensor_->properties().get(properties::Rotation);\n> -       ctrls.set(V4L2_CID_HFLIP, static_cast<int32_t>(!!rotation));\n> -       ctrls.set(V4L2_CID_VFLIP, static_cast<int32_t>(!!rotation));\n> -       unicam_[Unicam::Image].dev()->setControls(&ctrls);\n> +       if (result.operation & RPI_IPA_CONFIG_STAGGERED_WRITE) {\n> +               /*\n> +                * Setup our staggered control writer with the sensor default\n> +                * gain and exposure delays.\n> +                */\n> +               if (!staggeredCtrl_) {\n> +                       staggeredCtrl_.init(unicam_[Unicam::Image].dev(),\n> +                                           { { V4L2_CID_ANALOGUE_GAIN, result.data[0] },\n> +                                             { V4L2_CID_EXPOSURE, result.data[1] } });\n> +                       sensorMetadata_ = result.data[2];\n> +               }\n> +\n> +               /* Configure the H/V flip controls based on the sensor rotation. */\n> +               ControlList ctrls(unicam_[Unicam::Image].dev()->controls());\n> +               int32_t rotation = sensor_->properties().get(properties::Rotation);\n> +               ctrls.set(V4L2_CID_HFLIP, static_cast<int32_t>(!!rotation));\n> +               ctrls.set(V4L2_CID_VFLIP, static_cast<int32_t>(!!rotation));\n> +               unicam_[Unicam::Image].dev()->setControls(&ctrls);\n\nThis will work fine for now, given we only have sensors either at 0\ndegrees or 180 degrees.  I wonder if we should make this more generic\nand allow further transformations for other orientations?  Something\nfor us to consider separately.\n\n> +       }\n> +\n> +       if (result.operation & RPI_IPA_CONFIG_SENSOR) {\n> +               const ControlList &ctrls = result.controls[0];\n> +               if (!staggeredCtrl_.set(ctrls))\n> +                       LOG(RPI, Error) << \"V4L2 staggered set failed\";\n> +       }\n>\n>         return 0;\n>  }\n> @@ -1191,26 +1212,12 @@ void RPiCameraData::queueFrameAction(unsigned int frame, const IPAOperationData\n>          */\n>         switch (action.operation) {\n>         case RPI_IPA_ACTION_V4L2_SET_STAGGERED: {\n> -               ControlList controls = action.controls[0];\n> +               const ControlList &controls = action.controls[0];\n>                 if (!staggeredCtrl_.set(controls))\n>                         LOG(RPI, Error) << \"V4L2 staggered set failed\";\n>                 return;\n>         }\n>\n> -       case RPI_IPA_ACTION_SET_SENSOR_CONFIG: {\n> -               /*\n> -                * Setup our staggered control writer with the sensor default\n> -                * gain and exposure delays.\n> -                */\n> -               if (!staggeredCtrl_) {\n> -                       staggeredCtrl_.init(unicam_[Unicam::Image].dev(),\n> -                                           { { V4L2_CID_ANALOGUE_GAIN, action.data[0] },\n> -                                             { V4L2_CID_EXPOSURE, action.data[1] } });\n> -                       sensorMetadata_ = action.data[2];\n> -               }\n> -               return;\n> -       }\n> -\n>         case RPI_IPA_ACTION_V4L2_SET_ISP: {\n>                 ControlList controls = action.controls[0];\n>                 isp_[Isp::Input].dev()->setControls(&controls);\n> --\n> Regards,\n>\n> Laurent Pinchart\n>","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 41339BD792\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  8 Jul 2020 11:08:48 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A639261105;\n\tWed,  8 Jul 2020 13:08:47 +0200 (CEST)","from mail-lf1-x12b.google.com (mail-lf1-x12b.google.com\n\t[IPv6:2a00:1450:4864:20::12b])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A260860E05\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  8 Jul 2020 13:08:44 +0200 (CEST)","by mail-lf1-x12b.google.com with SMTP id t74so26648104lff.2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 08 Jul 2020 04:08:44 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"NOAgOZGN\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc; bh=lpMBxIezmbrntAmkHtvdE1Ls95wLeaBJ9DcmGL+gUzI=;\n\tb=NOAgOZGN0WSeyDm2tpmNCdyQ5TdmzyZXmuIXTBx7Ivh2ow9jkJ0FIWYUdmbiFQcfE+\n\tCX5+k0kBF1b7IECK6swyZxvN6KSeTXPYFAmkBqV/fbriz6JYjcFZHZjbkjdFvJpW+xWL\n\tJgsY3ZfsmnPsC2kDSUwrZb8w3IJG/yVdOndyoS9uIpya13ChErnrZkVEmviuVHUoXZ+h\n\t2bWTmdfB3nw0VrXsIl4UqaN7GZR/HvF9Bh7Ydo5S5oHiMcyYTLjUn3pPJnRX+vmbhdp3\n\t7fTPyq2d+cbptedSIOF9I80wSfK9d3X1sGS0LNO34Ih6tntrHg3V+380ro5PhkBXgOpV\n\t19Cw==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc;\n\tbh=lpMBxIezmbrntAmkHtvdE1Ls95wLeaBJ9DcmGL+gUzI=;\n\tb=deMMAxYdUXejFfvfPrDfuOqkSvGzb+yayKsFHueyi/E/vyMmHUsZsEkRaoe3kyKP4P\n\tVEhb+TtUBxrNTYTVSMlqJaVg8YusvJlXcVZDEZZ/ZMNUQZG/1PE6LrIlSb4uuvW9oOlv\n\tVrFKHS7E5i8Kbyht3cNqOSbbpKKhk6XlOgU9umzPqMdQpmPMW3aEjyuYZvZGEjohx2ro\n\tZJ4ta99JdqBa8OAGEDIfgw+Wzx7mhPgWc7pEtIOxlgd482Nb4te+xEwIwrj7hEzkJfUN\n\ti1siiySt11468rnVl9lodSviDR3uhv1tWCkGztMUqvX3DwOOTU6hoxP2xoa5YUapQmTA\n\tJDiA==","X-Gm-Message-State":"AOAM530BmyT3OfNwcBlu9E/duKCX4IKdI/cAz1OZ8T2+OuNlrfl1lnUi\n\tEL5snZHXCZ1FcreOGwvBXs5I7Vlb9nnQRGJdiAlzgfvH","X-Google-Smtp-Source":"ABdhPJyKk/bQ97YWsue4pKvODKtFIEEaxoYawl1IahGS7UaaEcUTHeYzdnwu9Ydi/o84hqpMKCqZV8X8fvD4Q9wZjwU=","X-Received":"by 2002:a19:f20a:: with SMTP id\n\tq10mr36409544lfh.89.1594206523903; \n\tWed, 08 Jul 2020 04:08:43 -0700 (PDT)","MIME-Version":"1.0","References":"<20200704005227.21782-1-laurent.pinchart@ideasonboard.com>\n\t<20200704005227.21782-12-laurent.pinchart@ideasonboard.com>","In-Reply-To":"<20200704005227.21782-12-laurent.pinchart@ideasonboard.com>","From":"Naushir Patuck <naush@raspberrypi.com>","Date":"Wed, 8 Jul 2020 12:08:27 +0100","Message-ID":"<CAEmqJPpj984dzRf9rdaSre+yNT9vLZAsxDTWvqWfdSe9MXQ6yw@mail.gmail.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v2 11/12] ipa: raspberrypi: Pass\n\tsensor config back from configure()","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>","Cc":"libcamera-devel@lists.libcamera.org","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>"}},{"id":11256,"web_url":"https://patchwork.libcamera.org/comment/11256/","msgid":"<20200708204244.GQ20298@pendragon.ideasonboard.com>","date":"2020-07-08T20:42:44","subject":"Re: [libcamera-devel] [PATCH v2 11/12] ipa: raspberrypi: Pass\n\tsensor config back from configure()","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Naush,\n\nOn Wed, Jul 08, 2020 at 12:08:27PM +0100, Naushir Patuck wrote:\n> Hi Laurent,\n> \n> Thank you for the patch.  Apart from the one note below,\n> \n> Reviewed-by: Naushir Patuck <naush@raspberrypi.com>\n> \n> On Sat, 4 Jul 2020 at 01:52, Laurent Pinchart\n> <laurent.pinchart@ideasonboard.com> wrote:\n> >\n> > The Raspberry Pi IPA uses the custom RPI_IPA_ACTION_SET_SENSOR_CONFIG\n> > frame action to send the sensor staggered write configuration to the\n> > pipeline handler when the IPA is configured. Replace this ad-hoc\n> > mechanism by passing the corresponding data back from the IPA to the\n> > pipeline handler through the configure() response. This allows\n> > synchronous handling of the response on the pipeline handler side.\n> >\n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> > Changes since v1:\n> >\n> > - Restore RPI_IPA_ACTION_V4L2_SET_ISP handling in stop state\n> > - Drop sensor orientation handling based on IPA result\n> > ---\n> >  include/libcamera/ipa/raspberrypi.h           |  3 +-\n> >  src/ipa/raspberrypi/raspberrypi.cpp           | 42 ++++++++-------\n> >  .../pipeline/raspberrypi/raspberrypi.cpp      | 53 +++++++++++--------\n> >  3 files changed, 56 insertions(+), 42 deletions(-)\n> >\n> > diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h\n> > index 46ce7c286b20..a49377695f22 100644\n> > --- a/include/libcamera/ipa/raspberrypi.h\n> > +++ b/include/libcamera/ipa/raspberrypi.h\n> > @@ -12,6 +12,8 @@\n> >\n> >  enum RPiConfigParameters {\n> >         RPI_IPA_CONFIG_LS_TABLE = (1 << 0),\n> > +       RPI_IPA_CONFIG_STAGGERED_WRITE = (1 << 1),\n> > +       RPI_IPA_CONFIG_SENSOR = (1 << 2),\n> >  };\n> >\n> >  enum RPiOperations {\n> > @@ -20,7 +22,6 @@ enum RPiOperations {\n> >         RPI_IPA_ACTION_STATS_METADATA_COMPLETE,\n> >         RPI_IPA_ACTION_RUN_ISP,\n> >         RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME,\n> > -       RPI_IPA_ACTION_SET_SENSOR_CONFIG,\n> >         RPI_IPA_ACTION_EMBEDDED_COMPLETE,\n> >         RPI_IPA_EVENT_SIGNAL_STAT_READY,\n> >         RPI_IPA_EVENT_SIGNAL_ISP_PREPARE,\n> > diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\n> > index 0e39a1137cd0..378ea309fa81 100644\n> > --- a/src/ipa/raspberrypi/raspberrypi.cpp\n> > +++ b/src/ipa/raspberrypi/raspberrypi.cpp\n> > @@ -93,7 +93,7 @@ private:\n> >         void reportMetadata();\n> >         bool parseEmbeddedData(unsigned int bufferId, struct DeviceStatus &deviceStatus);\n> >         void processStats(unsigned int bufferId);\n> > -       void applyAGC(const struct AgcStatus *agcStatus);\n> > +       void applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls);\n> >         void applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls);\n> >         void applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls);\n> >         void applyCCM(const struct CcmStatus *ccmStatus, ControlList &ctrls);\n> > @@ -195,6 +195,8 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n> >         if (entityControls.empty())\n> >                 return;\n> >\n> > +       result->operation = 0;\n> > +\n> >         unicam_ctrls_ = entityControls.at(0);\n> >         isp_ctrls_ = entityControls.at(1);\n> >         /* Setup a metadata ControlList to output metadata. */\n> > @@ -216,13 +218,11 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n> >                 helper_->GetDelays(exposureDelay, gainDelay);\n> >                 sensorMetadata = helper_->SensorEmbeddedDataPresent();\n> >\n> > -               IPAOperationData op;\n> > -               op.operation = RPI_IPA_ACTION_SET_SENSOR_CONFIG;\n> > -               op.data.push_back(gainDelay);\n> > -               op.data.push_back(exposureDelay);\n> > -               op.data.push_back(sensorMetadata);\n> > +               result->data.push_back(gainDelay);\n> > +               result->data.push_back(exposureDelay);\n> > +               result->data.push_back(sensorMetadata);\n> >\n> > -               queueFrameAction.emit(0, op);\n> > +               result->operation |= RPI_IPA_CONFIG_STAGGERED_WRITE;\n> >         }\n> >\n> >         /* Re-assemble camera mode using the sensor info. */\n> > @@ -267,8 +267,13 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n> >\n> >         /* SwitchMode may supply updated exposure/gain values to use. */\n> >         metadata.Get(\"agc.status\", agcStatus);\n> > -       if (agcStatus.shutter_time != 0.0 && agcStatus.analogue_gain != 0.0)\n> > -               applyAGC(&agcStatus);\n> > +       if (agcStatus.shutter_time != 0.0 && agcStatus.analogue_gain != 0.0) {\n> > +               ControlList ctrls(unicam_ctrls_);\n> > +               applyAGC(&agcStatus, ctrls);\n> > +               result->controls.push_back(ctrls);\n> > +\n> > +               result->operation |= RPI_IPA_CONFIG_SENSOR;\n> > +       }\n> >\n> >         lastMode_ = mode_;\n> >\n> > @@ -775,8 +780,15 @@ void IPARPi::processStats(unsigned int bufferId)\n> >         controller_.Process(statistics, &rpiMetadata_);\n> >\n> >         struct AgcStatus agcStatus;\n> > -       if (rpiMetadata_.Get(\"agc.status\", agcStatus) == 0)\n> > -               applyAGC(&agcStatus);\n> > +       if (rpiMetadata_.Get(\"agc.status\", agcStatus) == 0) {\n> > +               ControlList ctrls(unicam_ctrls_);\n> > +               applyAGC(&agcStatus, ctrls);\n> > +\n> > +               IPAOperationData op;\n> > +               op.operation = RPI_IPA_ACTION_V4L2_SET_STAGGERED;\n> > +               op.controls.push_back(ctrls);\n> > +               queueFrameAction.emit(0, op);\n> > +       }\n> >  }\n> >\n> >  void IPARPi::applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls)\n> > @@ -802,11 +814,8 @@ void IPARPi::applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls)\n> >                   static_cast<int32_t>(awbStatus->gain_b * 1000));\n> >  }\n> >\n> > -void IPARPi::applyAGC(const struct AgcStatus *agcStatus)\n> > +void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)\n> >  {\n> > -       IPAOperationData op;\n> > -       op.operation = RPI_IPA_ACTION_V4L2_SET_STAGGERED;\n> > -\n> >         int32_t gain_code = helper_->GainCode(agcStatus->analogue_gain);\n> >         int32_t exposure_lines = helper_->ExposureLines(agcStatus->shutter_time);\n> >\n> > @@ -825,11 +834,8 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus)\n> >                            << agcStatus->analogue_gain << \" (Gain Code: \"\n> >                            << gain_code << \")\";\n> >\n> > -       ControlList ctrls(unicam_ctrls_);\n> >         ctrls.set(V4L2_CID_ANALOGUE_GAIN, gain_code);\n> >         ctrls.set(V4L2_CID_EXPOSURE, exposure_lines);\n> > -       op.controls.push_back(ctrls);\n> > -       queueFrameAction.emit(0, op);\n> >  }\n> >\n> >  void IPARPi::applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls)\n> > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > index 57602349cab2..9babf9f4a19c 100644\n> > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > @@ -819,7 +819,7 @@ int PipelineHandlerRPi::start(Camera *camera)\n> >         /*\n> >          * Write the last set of gain and exposure values to the camera before\n> >          * starting. First check that the staggered ctrl has been initialised\n> > -        * by the IPA action.\n> > +        * by configure().\n> >          */\n> >         ASSERT(data->staggeredCtrl_);\n> >         data->staggeredCtrl_.reset();\n> > @@ -1170,15 +1170,36 @@ int RPiCameraData::configureIPA()\n> >         }\n> >\n> >         /* Ready the IPA - it must know about the sensor resolution. */\n> > +       IPAOperationData result;\n> > +\n> >         ipa_->configure(sensorInfo, streamConfig, entityControls, ipaConfig,\n> > -                       nullptr);\n> > +                       &result);\n> >\n> > -       /* Configure the H/V flip controls based on the sensor rotation. */\n> > -       ControlList ctrls(unicam_[Unicam::Image].dev()->controls());\n> > -       int32_t rotation = sensor_->properties().get(properties::Rotation);\n> > -       ctrls.set(V4L2_CID_HFLIP, static_cast<int32_t>(!!rotation));\n> > -       ctrls.set(V4L2_CID_VFLIP, static_cast<int32_t>(!!rotation));\n> > -       unicam_[Unicam::Image].dev()->setControls(&ctrls);\n> > +       if (result.operation & RPI_IPA_CONFIG_STAGGERED_WRITE) {\n> > +               /*\n> > +                * Setup our staggered control writer with the sensor default\n> > +                * gain and exposure delays.\n> > +                */\n> > +               if (!staggeredCtrl_) {\n> > +                       staggeredCtrl_.init(unicam_[Unicam::Image].dev(),\n> > +                                           { { V4L2_CID_ANALOGUE_GAIN, result.data[0] },\n> > +                                             { V4L2_CID_EXPOSURE, result.data[1] } });\n> > +                       sensorMetadata_ = result.data[2];\n> > +               }\n> > +\n> > +               /* Configure the H/V flip controls based on the sensor rotation. */\n> > +               ControlList ctrls(unicam_[Unicam::Image].dev()->controls());\n> > +               int32_t rotation = sensor_->properties().get(properties::Rotation);\n> > +               ctrls.set(V4L2_CID_HFLIP, static_cast<int32_t>(!!rotation));\n> > +               ctrls.set(V4L2_CID_VFLIP, static_cast<int32_t>(!!rotation));\n> > +               unicam_[Unicam::Image].dev()->setControls(&ctrls);\n> \n> This will work fine for now, given we only have sensors either at 0\n> degrees or 180 degrees.  I wonder if we should make this more generic\n> and allow further transformations for other orientations?  Something\n> for us to consider separately.\n\nI think we should. David has started a separate mail thread on that\ntopic. I think it should build on top of this series.\n\n> > +       }\n> > +\n> > +       if (result.operation & RPI_IPA_CONFIG_SENSOR) {\n> > +               const ControlList &ctrls = result.controls[0];\n> > +               if (!staggeredCtrl_.set(ctrls))\n> > +                       LOG(RPI, Error) << \"V4L2 staggered set failed\";\n> > +       }\n> >\n> >         return 0;\n> >  }\n> > @@ -1191,26 +1212,12 @@ void RPiCameraData::queueFrameAction(unsigned int frame, const IPAOperationData\n> >          */\n> >         switch (action.operation) {\n> >         case RPI_IPA_ACTION_V4L2_SET_STAGGERED: {\n> > -               ControlList controls = action.controls[0];\n> > +               const ControlList &controls = action.controls[0];\n> >                 if (!staggeredCtrl_.set(controls))\n> >                         LOG(RPI, Error) << \"V4L2 staggered set failed\";\n> >                 return;\n> >         }\n> >\n> > -       case RPI_IPA_ACTION_SET_SENSOR_CONFIG: {\n> > -               /*\n> > -                * Setup our staggered control writer with the sensor default\n> > -                * gain and exposure delays.\n> > -                */\n> > -               if (!staggeredCtrl_) {\n> > -                       staggeredCtrl_.init(unicam_[Unicam::Image].dev(),\n> > -                                           { { V4L2_CID_ANALOGUE_GAIN, action.data[0] },\n> > -                                             { V4L2_CID_EXPOSURE, action.data[1] } });\n> > -                       sensorMetadata_ = action.data[2];\n> > -               }\n> > -               return;\n> > -       }\n> > -\n> >         case RPI_IPA_ACTION_V4L2_SET_ISP: {\n> >                 ControlList controls = action.controls[0];\n> >                 isp_[Isp::Input].dev()->setControls(&controls);","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 05800BD790\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  8 Jul 2020 20:42:52 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 8FF7361163;\n\tWed,  8 Jul 2020 22:42:51 +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 94DEF60E05\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  8 Jul 2020 22:42:50 +0200 (CEST)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 1353B543;\n\tWed,  8 Jul 2020 22:42:50 +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=\"kf5bfGca\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1594240970;\n\tbh=DBkIYFtRjjll133p/uGkQAA3rwJSijrwLuUaSTFh5j8=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=kf5bfGcapR/nwlM10AxdsVcMGt+yR970ozi12Ywb8n7ZahiBhqfCg7iXGdnznlude\n\tvdpi6BWzYKlWgTZx2KgJDgMBkXBTvkDKhjURHKmIQAa0jnsXG/iBd4Xj0SpnFJgf2I\n\tZWT/YLRoK145oTdr13CB4IOgeL3TZuCT/e2D7sZQ=","Date":"Wed, 8 Jul 2020 23:42:44 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Naushir Patuck <naush@raspberrypi.com>","Message-ID":"<20200708204244.GQ20298@pendragon.ideasonboard.com>","References":"<20200704005227.21782-1-laurent.pinchart@ideasonboard.com>\n\t<20200704005227.21782-12-laurent.pinchart@ideasonboard.com>\n\t<CAEmqJPpj984dzRf9rdaSre+yNT9vLZAsxDTWvqWfdSe9MXQ6yw@mail.gmail.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<CAEmqJPpj984dzRf9rdaSre+yNT9vLZAsxDTWvqWfdSe9MXQ6yw@mail.gmail.com>","Subject":"Re: [libcamera-devel] [PATCH v2 11/12] ipa: raspberrypi: Pass\n\tsensor config back from configure()","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>","Cc":"libcamera-devel@lists.libcamera.org","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>"}}]