[{"id":14852,"web_url":"https://patchwork.libcamera.org/comment/14852/","msgid":"<20210129100919.fqez2vgect6kshti@uno.localdomain>","date":"2021-01-29T10:09:19","subject":"Re: [libcamera-devel] [PATCH v3 5/5] pipeline: raspberrypi: Add\n\tnotion of priority write to StaggeredCtrl","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Naush,\n\nOn Thu, Jan 28, 2021 at 09:10:50AM +0000, Naushir Patuck wrote:\n> If an exposure time change adjusts the vblanking limits, and we write\n> both VBLANK and EXPOSURE controls as a set, the latter may fail if the\n> value is outside of the limits calculated by the old VBLANK value. This\n> is a limitation in V4L2 and cannot be fixed by writing VBLANK before\n> EXPOSURE.\n>\n> The workaround here is to have the StaggeredCtrl mark the\n> VBLANK control as \"priority write\", which then write VBLANK separately\n> from (and ahead of) any other controls. This way, the sensor driver will\n> update the EXPOSURE control with new limits before the new values is\n> presented, and will thus be seen as valid.\n>\n> In addition to this, the following changes have also been made to\n> the module:\n>\n> - The initializer list passed into init() now uses a structure type\n>   instead of a std::pair.\n> - Use unsigned int to store control delays to avoid unnecessary casts.\n>\n> StaggeredCtrl is due to be deprecated and replaced by DelayedCtrl, so\n> this change serves more a working proof-of-concept on the workaround,\n> and not much care has been taken to provide a nice new API for applying\n> this \"priority write\" flag to the control. A similar workaround must be\n> available to DelayedCtrl eventually.\n>\n> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> ---\n>  src/ipa/raspberrypi/raspberrypi.cpp           |  5 ++-\n>  .../pipeline/raspberrypi/raspberrypi.cpp      | 12 ++++--\n>  .../pipeline/raspberrypi/staggered_ctrl.cpp   | 41 +++++++++++++------\n>  .../pipeline/raspberrypi/staggered_ctrl.h     | 17 ++++++--\n>  4 files changed, 54 insertions(+), 21 deletions(-)\n>\n> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\n> index 8c0e699184f6..2ad7b7dabb3e 100644\n> --- a/src/ipa/raspberrypi/raspberrypi.cpp\n> +++ b/src/ipa/raspberrypi/raspberrypi.cpp\n> @@ -1038,8 +1038,9 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)\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 * exposure time without us knowing. We get around this by ensuring the\n> +\t * staggered write component submits VBLANK separately from, and before the\n> +\t * EXPOSURE control.\n>  \t */\n>  \tctrls.set(V4L2_CID_VBLANK, vblanking);\n>  \tctrls.set(V4L2_CID_EXPOSURE, exposureLines);\n> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> index 524cc960dd37..2118f2e72486 100644\n> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> @@ -1229,12 +1229,18 @@ int RPiCameraData::configureIPA(const CameraConfiguration *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\t * VBLANK must be flagged as \"priority write\" to allow it to\n> +\t\t * be set ahead of (and separate from) all other controls that\n> +\t\t * are batched together. This is needed so that any update to the\n> +\t\t * EXPOSURE control will be validated based on the new VBLANK\n> +\t\t * control value.\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\t\t\t      { V4L2_CID_VBLANK, result.data[resultIdx++] } });\n> +\t\t\t\t\t    { { V4L2_CID_ANALOGUE_GAIN, result.data[resultIdx++], false },\n> +\t\t\t\t\t      { V4L2_CID_EXPOSURE, result.data[resultIdx++], false },\n> +\t\t\t\t\t      { V4L2_CID_VBLANK, result.data[resultIdx++], true } });\n>  \t\t\tsensorMetadata_ = result.data[resultIdx++];\n>  \t\t}\n>  \t}\n> diff --git a/src/libcamera/pipeline/raspberrypi/staggered_ctrl.cpp b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.cpp\n> index 62605c0fceee..498cd65b4cb6 100644\n> --- a/src/libcamera/pipeline/raspberrypi/staggered_ctrl.cpp\n> +++ b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.cpp\n> @@ -22,21 +22,23 @@ LOG_DEFINE_CATEGORY(RPI_S_W)\n>  namespace RPi {\n>\n>  void StaggeredCtrl::init(V4L2VideoDevice *dev,\n> -\t  std::initializer_list<std::pair<const uint32_t, uint8_t>> delayList)\n> +\t\t\t std::initializer_list<CtrlInitParams> ctrlList)\n>  {\n>  \tstd::lock_guard<std::mutex> lock(lock_);\n>\n>  \tdev_ = dev;\n> -\tdelay_ = delayList;\n> +\tctrlParams_.clear();\n>  \tctrl_.clear();\n>\n> -\t/* Find the largest delay across all controls. */\n>  \tmaxDelay_ = 0;\n> -\tfor (auto const &p : delay_) {\n> +\tfor (auto const &c : ctrlList) {\n>  \t\tLOG(RPI_S_W, Info) << \"Init ctrl \"\n> -\t\t\t\t   << utils::hex(p.first) << \" with delay \"\n> -\t\t\t\t   << static_cast<int>(p.second);\n> -\t\tmaxDelay_ = std::max(maxDelay_, p.second);\n> +\t\t\t\t   << utils::hex(c.id) << \" with delay \"\n> +\t\t\t\t   << static_cast<int>(c.delay);\n> +\n> +\t\tctrlParams_[c.id] = { c.delay, c.priorityWrite };\n> +\t\t/* Find the largest delay across all controls. */\n> +\t\tmaxDelay_ = std::max(maxDelay_, c.delay);\n>  \t}\n>\n>  \tinit_ = true;\n> @@ -67,7 +69,7 @@ bool StaggeredCtrl::set(uint32_t ctrl, int32_t value)\n>  \tstd::lock_guard<std::mutex> lock(lock_);\n>\n>  \t/* Can we find this ctrl as one that is registered? */\n> -\tif (delay_.find(ctrl) == delay_.end())\n> +\tif (ctrlParams_.find(ctrl) == ctrlParams_.end())\n>  \t\treturn false;\n>\n>  \tctrl_[ctrl][setCount_].value = value;\n> @@ -82,7 +84,7 @@ bool StaggeredCtrl::set(std::initializer_list<std::pair<const uint32_t, int32_t>\n>\n>  \tfor (auto const &p : ctrlList) {\n>  \t\t/* Can we find this ctrl? */\n> -\t\tif (delay_.find(p.first) == delay_.end())\n> +\t\tif (ctrlParams_.find(p.first) == ctrlParams_.end())\n>  \t\t\treturn false;\n>\n>  \t\tctrl_[p.first][setCount_] = CtrlInfo(p.second);\n> @@ -97,7 +99,7 @@ bool StaggeredCtrl::set(const ControlList &controls)\n>\n>  \tfor (auto const &p : controls) {\n>  \t\t/* Can we find this ctrl? */\n> -\t\tif (delay_.find(p.first) == delay_.end())\n> +\t\tif (ctrlParams_.find(p.first) == ctrlParams_.end())\n>  \t\t\treturn false;\n>\n>  \t\tctrl_[p.first][setCount_] = CtrlInfo(p.second.get<int32_t>());\n> @@ -117,12 +119,25 @@ int StaggeredCtrl::write()\n>  \tControlList controls(dev_->controls());\n>\n>  \tfor (auto &p : ctrl_) {\n> -\t\tint delayDiff = maxDelay_ - delay_[p.first];\n> +\t\tint delayDiff = maxDelay_ - ctrlParams_[p.first].delay;\n>  \t\tint index = std::max<int>(0, setCount_ - delayDiff);\n>\n>  \t\tif (p.second[index].updated) {\n> -\t\t\t/* We need to write this value out. */\n> -\t\t\tcontrols.set(p.first, p.second[index].value);\n> +\t\t\tif (ctrlParams_[p.first].priorityWrite) {\n> +\t\t\t\t/*\n> +\t\t\t\t * This control must be written now, it could\n> +\t\t\t\t * affect validity of the other controls.\n> +\t\t\t\t */\n> +\t\t\t\tControlList immediate(dev_->controls());\n> +\t\t\t\timmediate.set(p.first, p.second[index].value);\n> +\t\t\t\tdev_->setControls(&immediate);\n> +\t\t\t} else {\n> +\t\t\t\t/*\n> +\t\t\t\t * Batch up the list of controls and write them\n> +\t\t\t\t * at the end of the function.\n> +\t\t\t\t */\n> +\t\t\t\tcontrols.set(p.first, p.second[index].value);\n> +\t\t\t}\n>  \t\t\tp.second[index].updated = false;\n\nWon't nextFrame() set updated to false ?\nAnyway, this was here already and it's really minor. Feel free to\nleave it as it is.\n\nThe patch looks *unfortunately* reasonable. And I say unfortunately as\nyou're really working around a limitation of the kernel API,\n\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n\nThanks\n  j\n\n>  \t\t\tLOG(RPI_S_W, Debug) << \"Writing ctrl \"\n>  \t\t\t\t\t    << utils::hex(p.first) << \" to \"\n> diff --git a/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h\n> index 382fa31a6853..637629c0d9a8 100644\n> --- a/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h\n> +++ b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h\n> @@ -23,6 +23,12 @@ namespace RPi {\n>  class StaggeredCtrl\n>  {\n>  public:\n> +\tstruct CtrlInitParams {\n> +\t\tunsigned int id;\n> +\t\tunsigned int delay;\n> +\t\tbool priorityWrite;\n> +\t};\n> +\n>  \tStaggeredCtrl()\n>  \t\t: init_(false), setCount_(0), getCount_(0), maxDelay_(0)\n>  \t{\n> @@ -34,7 +40,7 @@ public:\n>  \t}\n>\n>  \tvoid init(V4L2VideoDevice *dev,\n> -\t\t  std::initializer_list<std::pair<const uint32_t, uint8_t>> delayList);\n> +\t\t  std::initializer_list<CtrlInitParams> ctrlList);\n>  \tvoid reset();\n>\n>  \tvoid get(std::unordered_map<uint32_t, int32_t> &ctrl, uint8_t offset = 0);\n> @@ -79,12 +85,17 @@ private:\n>  \t\t}\n>  \t};\n>\n> +\tstruct CtrlParams {\n> +\t\tunsigned int delay;\n> +\t\tbool priorityWrite;\n> +\t};\n> +\n>  \tbool init_;\n>  \tuint32_t setCount_;\n>  \tuint32_t getCount_;\n> -\tuint8_t maxDelay_;\n> +\tunsigned int maxDelay_;\n>  \tV4L2VideoDevice *dev_;\n> -\tstd::unordered_map<uint32_t, uint8_t> delay_;\n> +\tstd::unordered_map<uint32_t, CtrlParams> ctrlParams_;\n>  \tstd::unordered_map<uint32_t, CircularArray> ctrl_;\n>  \tstd::mutex lock_;\n>  };\n> --\n> 2.25.1\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 CB166BD808\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 29 Jan 2021 10:09:00 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6626C6839F;\n\tFri, 29 Jan 2021 11:09:00 +0100 (CET)","from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net\n\t[217.70.183.193])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 99EC56839C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 29 Jan 2021 11:08:59 +0100 (CET)","from uno.localdomain (93-34-118-233.ip49.fastwebnet.it\n\t[93.34.118.233]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay1-d.mail.gandi.net (Postfix) with ESMTPSA id F320F24000D;\n\tFri, 29 Jan 2021 10:08:58 +0000 (UTC)"],"X-Originating-IP":"93.34.118.233","Date":"Fri, 29 Jan 2021 11:09:19 +0100","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Naushir Patuck <naush@raspberrypi.com>","Message-ID":"<20210129100919.fqez2vgect6kshti@uno.localdomain>","References":"<20210128091050.881815-1-naush@raspberrypi.com>\n\t<20210128091050.881815-6-naush@raspberrypi.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20210128091050.881815-6-naush@raspberrypi.com>","Subject":"Re: [libcamera-devel] [PATCH v3 5/5] pipeline: raspberrypi: Add\n\tnotion of priority write to StaggeredCtrl","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":14853,"web_url":"https://patchwork.libcamera.org/comment/14853/","msgid":"<CAEmqJPpnE+Q-oGxXdAErDFv6maVi6nzJQPhfgqoMm0jMdGVYgw@mail.gmail.com>","date":"2021-01-29T10:20:45","subject":"Re: [libcamera-devel] [PATCH v3 5/5] pipeline: raspberrypi: Add\n\tnotion of priority write to StaggeredCtrl","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"Hi Jacopo,\n\nThank you for your review feedback.\n\nOn Fri, 29 Jan 2021 at 10:08, Jacopo Mondi <jacopo@jmondi.org> wrote:\n\n> Hi Naush,\n>\n> On Thu, Jan 28, 2021 at 09:10:50AM +0000, Naushir Patuck wrote:\n> > If an exposure time change adjusts the vblanking limits, and we write\n> > both VBLANK and EXPOSURE controls as a set, the latter may fail if the\n> > value is outside of the limits calculated by the old VBLANK value. This\n> > is a limitation in V4L2 and cannot be fixed by writing VBLANK before\n> > EXPOSURE.\n> >\n> > The workaround here is to have the StaggeredCtrl mark the\n> > VBLANK control as \"priority write\", which then write VBLANK separately\n> > from (and ahead of) any other controls. This way, the sensor driver will\n> > update the EXPOSURE control with new limits before the new values is\n> > presented, and will thus be seen as valid.\n> >\n> > In addition to this, the following changes have also been made to\n> > the module:\n> >\n> > - The initializer list passed into init() now uses a structure type\n> >   instead of a std::pair.\n> > - Use unsigned int to store control delays to avoid unnecessary casts.\n> >\n> > StaggeredCtrl is due to be deprecated and replaced by DelayedCtrl, so\n> > this change serves more a working proof-of-concept on the workaround,\n> > and not much care has been taken to provide a nice new API for applying\n> > this \"priority write\" flag to the control. A similar workaround must be\n> > available to DelayedCtrl eventually.\n> >\n> > Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> > ---\n> >  src/ipa/raspberrypi/raspberrypi.cpp           |  5 ++-\n> >  .../pipeline/raspberrypi/raspberrypi.cpp      | 12 ++++--\n> >  .../pipeline/raspberrypi/staggered_ctrl.cpp   | 41 +++++++++++++------\n> >  .../pipeline/raspberrypi/staggered_ctrl.h     | 17 ++++++--\n> >  4 files changed, 54 insertions(+), 21 deletions(-)\n> >\n> > diff --git a/src/ipa/raspberrypi/raspberrypi.cpp\n> b/src/ipa/raspberrypi/raspberrypi.cpp\n> > index 8c0e699184f6..2ad7b7dabb3e 100644\n> > --- a/src/ipa/raspberrypi/raspberrypi.cpp\n> > +++ b/src/ipa/raspberrypi/raspberrypi.cpp\n> > @@ -1038,8 +1038,9 @@ void IPARPi::applyAGC(const struct AgcStatus\n> *agcStatus, ControlList &ctrls)\n> >\n> >       /*\n> >        * Due to the behavior of V4L2, the current value of VBLANK could\n> clip the\n> > -      * exposure time without us knowing. The next time though this\n> function should\n> > -      * clip exposure correctly.\n> > +      * exposure time without us knowing. We get around this by\n> ensuring the\n> > +      * staggered write component submits VBLANK separately from, and\n> before the\n> > +      * EXPOSURE control.\n> >        */\n> >       ctrls.set(V4L2_CID_VBLANK, vblanking);\n> >       ctrls.set(V4L2_CID_EXPOSURE, exposureLines);\n> > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > index 524cc960dd37..2118f2e72486 100644\n> > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > @@ -1229,12 +1229,18 @@ int RPiCameraData::configureIPA(const\n> CameraConfiguration *config)\n> >               /*\n> >                * Setup our staggered control writer with the sensor\n> default\n> >                * gain and exposure delays.\n> > +              *\n> > +              * VBLANK must be flagged as \"priority write\" to allow it\n> to\n> > +              * be set ahead of (and separate from) all other controls\n> that\n> > +              * are batched together. This is needed so that any update\n> to the\n> > +              * EXPOSURE control will be validated based on the new\n> VBLANK\n> > +              * control value.\n> >                */\n> >               if (!staggeredCtrl_) {\n> >                       staggeredCtrl_.init(unicam_[Unicam::Image].dev(),\n> > -                                         { { V4L2_CID_ANALOGUE_GAIN,\n> result.data[resultIdx++] },\n> > -                                           { V4L2_CID_EXPOSURE,\n> result.data[resultIdx++] },\n> > -                                           { V4L2_CID_VBLANK,\n> result.data[resultIdx++] } });\n> > +                                         { { V4L2_CID_ANALOGUE_GAIN,\n> result.data[resultIdx++], false },\n> > +                                           { V4L2_CID_EXPOSURE,\n> result.data[resultIdx++], false },\n> > +                                           { V4L2_CID_VBLANK,\n> result.data[resultIdx++], true } });\n> >                       sensorMetadata_ = result.data[resultIdx++];\n> >               }\n> >       }\n> > diff --git a/src/libcamera/pipeline/raspberrypi/staggered_ctrl.cpp\n> b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.cpp\n> > index 62605c0fceee..498cd65b4cb6 100644\n> > --- a/src/libcamera/pipeline/raspberrypi/staggered_ctrl.cpp\n> > +++ b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.cpp\n> > @@ -22,21 +22,23 @@ LOG_DEFINE_CATEGORY(RPI_S_W)\n> >  namespace RPi {\n> >\n> >  void StaggeredCtrl::init(V4L2VideoDevice *dev,\n> > -       std::initializer_list<std::pair<const uint32_t, uint8_t>>\n> delayList)\n> > +                      std::initializer_list<CtrlInitParams> ctrlList)\n> >  {\n> >       std::lock_guard<std::mutex> lock(lock_);\n> >\n> >       dev_ = dev;\n> > -     delay_ = delayList;\n> > +     ctrlParams_.clear();\n> >       ctrl_.clear();\n> >\n> > -     /* Find the largest delay across all controls. */\n> >       maxDelay_ = 0;\n> > -     for (auto const &p : delay_) {\n> > +     for (auto const &c : ctrlList) {\n> >               LOG(RPI_S_W, Info) << \"Init ctrl \"\n> > -                                << utils::hex(p.first) << \" with delay \"\n> > -                                << static_cast<int>(p.second);\n> > -             maxDelay_ = std::max(maxDelay_, p.second);\n> > +                                << utils::hex(c.id) << \" with delay \"\n> > +                                << static_cast<int>(c.delay);\n> > +\n> > +             ctrlParams_[c.id] = { c.delay, c.priorityWrite };\n> > +             /* Find the largest delay across all controls. */\n> > +             maxDelay_ = std::max(maxDelay_, c.delay);\n> >       }\n> >\n> >       init_ = true;\n> > @@ -67,7 +69,7 @@ bool StaggeredCtrl::set(uint32_t ctrl, int32_t value)\n> >       std::lock_guard<std::mutex> lock(lock_);\n> >\n> >       /* Can we find this ctrl as one that is registered? */\n> > -     if (delay_.find(ctrl) == delay_.end())\n> > +     if (ctrlParams_.find(ctrl) == ctrlParams_.end())\n> >               return false;\n> >\n> >       ctrl_[ctrl][setCount_].value = value;\n> > @@ -82,7 +84,7 @@ bool\n> StaggeredCtrl::set(std::initializer_list<std::pair<const uint32_t, int32_t>\n> >\n> >       for (auto const &p : ctrlList) {\n> >               /* Can we find this ctrl? */\n> > -             if (delay_.find(p.first) == delay_.end())\n> > +             if (ctrlParams_.find(p.first) == ctrlParams_.end())\n> >                       return false;\n> >\n> >               ctrl_[p.first][setCount_] = CtrlInfo(p.second);\n> > @@ -97,7 +99,7 @@ bool StaggeredCtrl::set(const ControlList &controls)\n> >\n> >       for (auto const &p : controls) {\n> >               /* Can we find this ctrl? */\n> > -             if (delay_.find(p.first) == delay_.end())\n> > +             if (ctrlParams_.find(p.first) == ctrlParams_.end())\n> >                       return false;\n> >\n> >               ctrl_[p.first][setCount_] =\n> CtrlInfo(p.second.get<int32_t>());\n> > @@ -117,12 +119,25 @@ int StaggeredCtrl::write()\n> >       ControlList controls(dev_->controls());\n> >\n> >       for (auto &p : ctrl_) {\n> > -             int delayDiff = maxDelay_ - delay_[p.first];\n> > +             int delayDiff = maxDelay_ - ctrlParams_[p.first].delay;\n> >               int index = std::max<int>(0, setCount_ - delayDiff);\n> >\n> >               if (p.second[index].updated) {\n> > -                     /* We need to write this value out. */\n> > -                     controls.set(p.first, p.second[index].value);\n> > +                     if (ctrlParams_[p.first].priorityWrite) {\n> > +                             /*\n> > +                              * This control must be written now, it\n> could\n> > +                              * affect validity of the other controls.\n> > +                              */\n> > +                             ControlList immediate(dev_->controls());\n> > +                             immediate.set(p.first,\n> p.second[index].value);\n> > +                             dev_->setControls(&immediate);\n> > +                     } else {\n> > +                             /*\n> > +                              * Batch up the list of controls and write\n> them\n> > +                              * at the end of the function.\n> > +                              */\n> > +                             controls.set(p.first,\n> p.second[index].value);\n> > +                     }\n> >                       p.second[index].updated = false;\n>\n> Won't nextFrame() set updated to false ?\n> Anyway, this was here already and it's really minor. Feel free to\n> leave it as it is.\n>\n\nSlightly different - the above line is clearing the updated flag for the\ncurrent control index.  In nextFrame(), we are clearing the update fag for\nthe next-control-to-be-written index.  I do get your point that you only\nneed one of these statements though :-)\nI'll leave it as it is, on account of this being deprecated soon, and it is\nslightly unrelated to this patch subject.\n\n\n>\n> The patch looks *unfortunately* reasonable. And I say unfortunately as\n> you're really working around a limitation of the kernel API,\n>\n\nIndeed.  It does fix the problem, but in a bit of an ugly way :-(\n\nRegards,\nNaush\n\n\n>\n> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n>\n> Thanks\n>   j\n>\n> >                       LOG(RPI_S_W, Debug) << \"Writing ctrl \"\n> >                                           << utils::hex(p.first) << \" to\n> \"\n> > diff --git a/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h\n> b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h\n> > index 382fa31a6853..637629c0d9a8 100644\n> > --- a/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h\n> > +++ b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h\n> > @@ -23,6 +23,12 @@ namespace RPi {\n> >  class StaggeredCtrl\n> >  {\n> >  public:\n> > +     struct CtrlInitParams {\n> > +             unsigned int id;\n> > +             unsigned int delay;\n> > +             bool priorityWrite;\n> > +     };\n> > +\n> >       StaggeredCtrl()\n> >               : init_(false), setCount_(0), getCount_(0), maxDelay_(0)\n> >       {\n> > @@ -34,7 +40,7 @@ public:\n> >       }\n> >\n> >       void init(V4L2VideoDevice *dev,\n> > -               std::initializer_list<std::pair<const uint32_t,\n> uint8_t>> delayList);\n> > +               std::initializer_list<CtrlInitParams> ctrlList);\n> >       void reset();\n> >\n> >       void get(std::unordered_map<uint32_t, int32_t> &ctrl, uint8_t\n> offset = 0);\n> > @@ -79,12 +85,17 @@ private:\n> >               }\n> >       };\n> >\n> > +     struct CtrlParams {\n> > +             unsigned int delay;\n> > +             bool priorityWrite;\n> > +     };\n> > +\n> >       bool init_;\n> >       uint32_t setCount_;\n> >       uint32_t getCount_;\n> > -     uint8_t maxDelay_;\n> > +     unsigned int maxDelay_;\n> >       V4L2VideoDevice *dev_;\n> > -     std::unordered_map<uint32_t, uint8_t> delay_;\n> > +     std::unordered_map<uint32_t, CtrlParams> ctrlParams_;\n> >       std::unordered_map<uint32_t, CircularArray> ctrl_;\n> >       std::mutex lock_;\n> >  };\n> > --\n> > 2.25.1\n> >\n> > _______________________________________________\n> > libcamera-devel mailing list\n> > libcamera-devel@lists.libcamera.org\n> > https://lists.libcamera.org/listinfo/libcamera-devel\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 16296C33BB\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 29 Jan 2021 10:21:04 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7F117683A5;\n\tFri, 29 Jan 2021 11:21:03 +0100 (CET)","from mail-qk1-x72a.google.com (mail-qk1-x72a.google.com\n\t[IPv6:2607:f8b0:4864:20::72a])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B0D736839C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 29 Jan 2021 11:21:02 +0100 (CET)","by mail-qk1-x72a.google.com with SMTP id t63so8206808qkc.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 29 Jan 2021 02:21:02 -0800 (PST)"],"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=\"R2pfve7+\"; 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=za1JcZnGPeFFsXCHdr+2UlWCEO2ri/WqgNSAITebPXE=;\n\tb=R2pfve7+Tth8nRTUK0PI/LJ2R8njvRFzY1e0b7/Bw0DXFnKdp5D1r13au2eNhlKQs9\n\tqhW3c8F23+uae9ub3Aqdtu3zO87N59/Na1EL1DN/4EW5539cEL4owVy0Oui7llXn3azB\n\thYPanUBSkOjpsnEpLOsSaDBfPysVdyRz2e+Sejfb5B87+Q883LKoxqJDhE5324QOjQaK\n\tFe9T3nJsAUBDEtnDlSyDaJvQVMfoTE34O096rgVeg4sY4Dy0rIP0TgWS3nRp9W1Q+Hv3\n\tbQtm65snjU0ruytS6pLFZu+5zEkaG8KSrdMx/zcpWMX8i2Yn4MRyTwtaPM+m8YRsMEN1\n\tImjw==","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=za1JcZnGPeFFsXCHdr+2UlWCEO2ri/WqgNSAITebPXE=;\n\tb=HPbDxX8HUUnmjipoz8YS3oHHfz+hA2+JNfoJ9xt28GWKGnm+lFjHFUK7dVYivZe004\n\tqpERvYXY0UehKYjKz2vnE0zjB3TMgHB18nxJUkyddNOtFax7AhdBfUO5IwiS2zbuyM+O\n\tTU8o2PMbUUJoG0qeCRJtQqw8WUYJsU6uTQByojqE9wqITaUrDQ0NMG87ETNe6w6L14bW\n\tF+nz8MOXqkORMmssMAtnnXJ+LD5lO6x3q6SFxa82xrSuDbRWcOO5+AtrZvnzQfRWsMyz\n\tSbzawvFziiRLBxJkXqWhwZEyloKNL2yLwdscbTmN9gXUwjKxqUWKPNs89qYEr04lo0Zn\n\tcIlg==","X-Gm-Message-State":"AOAM530h/sQD9DDoU9cDeH579ZIPPz8d/HTdj3XdYlylCEfwgdZn5pYn\n\tYVmKtBM7Ma9fiycIFrEwx0PY445VbMI8YZavDXRFel9RF8ibMg==","X-Google-Smtp-Source":"ABdhPJwuDUze9Fr/s+yIenYfHnW1n/HDbBY5QK5iRXo26FE6INRrShiZlqxs46IeCv5qvwh8wgWrabtgSkQXd3xqRBc=","X-Received":"by 2002:a37:bd01:: with SMTP id n1mr3337329qkf.469.1611915661286;\n\tFri, 29 Jan 2021 02:21:01 -0800 (PST)","MIME-Version":"1.0","References":"<20210128091050.881815-1-naush@raspberrypi.com>\n\t<20210128091050.881815-6-naush@raspberrypi.com>\n\t<20210129100919.fqez2vgect6kshti@uno.localdomain>","In-Reply-To":"<20210129100919.fqez2vgect6kshti@uno.localdomain>","From":"Naushir Patuck <naush@raspberrypi.com>","Date":"Fri, 29 Jan 2021 10:20:45 +0000","Message-ID":"<CAEmqJPpnE+Q-oGxXdAErDFv6maVi6nzJQPhfgqoMm0jMdGVYgw@mail.gmail.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Subject":"Re: [libcamera-devel] [PATCH v3 5/5] pipeline: raspberrypi: Add\n\tnotion of priority write to StaggeredCtrl","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 <libcamera-devel@lists.libcamera.org>","Content-Type":"multipart/mixed;\n\tboundary=\"===============7145714705225661409==\"","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]