From patchwork Thu Jan 21 11:58:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 10926 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 9F29BC0F2B for ; Thu, 21 Jan 2021 11:59:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 665AA681EE; Thu, 21 Jan 2021 12:59:00 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="bb8/j4pH"; dkim-atps=neutral Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 64B70681F3 for ; Thu, 21 Jan 2021 12:58:58 +0100 (CET) Received: by mail-wr1-x435.google.com with SMTP id a9so1452059wrt.5 for ; Thu, 21 Jan 2021 03:58:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=wbMF+KvzLd6qSkStJhzEh/KUO8Z01x1gWbfkhwWRLzo=; b=bb8/j4pHC+simkj0oyESZxsCbuwNixKXgnt9unOWxq9sj53DvV2DZ4zfM6MVuflXek NZaag/rZ9IAQfwRBBOT2UKJ3JJRIbooKCZiwsm322rbPoaUJWhy4o2Psp7k1YShOzoiF C4TqvQctkwayEme41NrMTdubhgjpqf2nomaWY/jQzCAMrnzuhrbQEU71DJOEHnOzEelP O+blKOIafqCxSGxTBvgGBsriWl1FjRJm0qR/l+Wp0AVwQsMSzDbfS0zxiEo3CERlksjD FCFex0qWbfdpTIgN9sGOmaIbfKIBSyB7kXWpDE1uIlB/GPjEiksIPPbWvry8ZWphSr4s Uk3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=wbMF+KvzLd6qSkStJhzEh/KUO8Z01x1gWbfkhwWRLzo=; b=FHLicJzG9IJQEkdgoU7s2c5FXpDPp3TNknpNM+Io+lpbpZ/93VC8mEQn9hsSEqnz0M 2/HVaIJ4eR52Kq1/dRF6M0kzVLz8P5Vnao2eP6VIrydxNnz8K3Woi8Bn7sUcZ9tSPEvD cv6nN0EaYEjlKlf991//Bfwo5eE0He+U2yaOZ7iVwzyxbZVFAKbnLo1xnD7G3XR/7tlp FXj8BkuY2L4k7O2xGFep6DbrTVrrIGHrOfjDNfo91oUXBtlBPjRq3p2acsjqLYrSQImq 2adcgJddmbypCqfW5LvQI4RCr/bZzCoc09hUzxPccesSQNQmCcxM0RBdYx58WKGaBGO7 8OXQ== X-Gm-Message-State: AOAM531i2ioV/bZ5dZu7Z+L8DnQ3LDKeeFp7g3afhp9bLT7izRDbL4Xa RO5miBFkn4sxHrncTxlHThNpgzK4xgGong== X-Google-Smtp-Source: ABdhPJxeFHal94kBYe1In4wHhNIxCJlINQhRM+l2fqKfY20hNDPuoxB4Qj8j9QzMmQ2zliixMplXFA== X-Received: by 2002:a05:6000:1043:: with SMTP id c3mr13139844wrx.140.1611230337764; Thu, 21 Jan 2021 03:58:57 -0800 (PST) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id h13sm8044930wrm.28.2021.01.21.03.58.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Jan 2021 03:58:56 -0800 (PST) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Thu, 21 Jan 2021 11:58:49 +0000 Message-Id: <20210121115849.682130-5-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210121115849.682130-1-naush@raspberrypi.com> References: <20210121115849.682130-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 4/4] pipeline: raspberrypi: Add notion of immediate write to StaggeredCtrl X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" If an exposure time change adjusts the vblanking limits, and we write both VBLANK and EXPOSURE controls as a set, the latter may fail if the value is outside of the limits calculated by the old VBLANK value. This is a limitation in V4L2 and cannot be fixed by writing VBLANK before EXPOSURE. The workaround here is to have the StaggeredCtrl mark the VBLANK control as "immediate write", which then write VBLANK separately from (and ahead of) any other controls. This way, the sensor driver will update the EXPOSURE control with new limits before the new values is presented, and will thus be seen as valid. StaggeredCtrl is due to be deprecated and replaced by DelayedCtrl, so this change serves more a working proof-of-concept on the workaround, and not much care has been taken to provide a nice new API for applying this immediate write flag to the control. A similar workaround must be available to DelayedCtrl eventually. Signed-off-by: Naushir Patuck --- src/ipa/raspberrypi/raspberrypi.cpp | 5 ++- .../pipeline/raspberrypi/raspberrypi.cpp | 11 ++++-- .../pipeline/raspberrypi/staggered_ctrl.cpp | 39 ++++++++++++++----- .../pipeline/raspberrypi/staggered_ctrl.h | 3 +- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp index 2b71efc63f10..c6a1e8027284 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -1040,8 +1040,9 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls) /* * Due to the behavior of V4L2, the current value of VBLANK could clip the - * exposure time without us knowing. The next time though this function should - * clip exposure correctly. + * exposure time without us knowing. We get around this by ensuring the + * staggered write component submits VBLANK separately from, and before the + * EXPOSURE control. */ ctrls.set(V4L2_CID_VBLANK, vblanking); ctrls.set(V4L2_CID_EXPOSURE, exposureLines); diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 524cc960dd37..1485999ad2a0 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -1229,12 +1229,17 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config) /* * Setup our staggered control writer with the sensor default * gain and exposure delays. + * + * VBLANK must be flagged as "immediate write" to allow it to + * be set immediately instead of being batched with all other + * controls. This is needed so that any update to the EXPOSURE + * control will be validated based on the new VBLANK control value. */ if (!staggeredCtrl_) { staggeredCtrl_.init(unicam_[Unicam::Image].dev(), - { { V4L2_CID_ANALOGUE_GAIN, result.data[resultIdx++] }, - { V4L2_CID_EXPOSURE, result.data[resultIdx++] }, - { V4L2_CID_VBLANK, result.data[resultIdx++] } }); + { { V4L2_CID_ANALOGUE_GAIN, result.data[resultIdx++], false }, + { V4L2_CID_EXPOSURE, result.data[resultIdx++], false }, + { V4L2_CID_VBLANK, result.data[resultIdx++], true } }); sensorMetadata_ = result.data[resultIdx++]; } } diff --git a/src/libcamera/pipeline/raspberrypi/staggered_ctrl.cpp b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.cpp index 62605c0fceee..07f8c95d4f2c 100644 --- a/src/libcamera/pipeline/raspberrypi/staggered_ctrl.cpp +++ b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.cpp @@ -22,21 +22,29 @@ LOG_DEFINE_CATEGORY(RPI_S_W) namespace RPi { void StaggeredCtrl::init(V4L2VideoDevice *dev, - std::initializer_list> delayList) + std::initializer_list> delayList) { std::lock_guard lock(lock_); dev_ = dev; - delay_ = delayList; + delay_.clear(); ctrl_.clear(); - /* Find the largest delay across all controls. */ maxDelay_ = 0; - for (auto const &p : delay_) { + for (auto const &c : delayList) { + uint32_t id = std::get<0>(c); + uint8_t delay = std::get<1>(c); + bool immediateWrite = std::get<2>(c); + + delay_[id] = delay; + immediateWrite_[id] = immediateWrite; + LOG(RPI_S_W, Info) << "Init ctrl " - << utils::hex(p.first) << " with delay " - << static_cast(p.second); - maxDelay_ = std::max(maxDelay_, p.second); + << utils::hex(id) << " with delay " + << static_cast(delay); + + /* Find the largest delay across all controls. */ + maxDelay_ = std::max(maxDelay_, delay); } init_ = true; @@ -121,8 +129,21 @@ int StaggeredCtrl::write() int index = std::max(0, setCount_ - delayDiff); if (p.second[index].updated) { - /* We need to write this value out. */ - controls.set(p.first, p.second[index].value); + if (immediateWrite_[p.first]) { + /* + * This control must be written now, it could + * affect validity of the other controls. + */ + ControlList immediate(dev_->controls()); + immediate.set(p.first, p.second[index].value); + dev_->setControls(&immediate); + } else { + /* + * Batch up the list of controls and write them + * at the end of the function. + */ + controls.set(p.first, p.second[index].value); + } p.second[index].updated = false; LOG(RPI_S_W, Debug) << "Writing ctrl " << utils::hex(p.first) << " to " diff --git a/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h index 382fa31a6853..7c920c3a13c7 100644 --- a/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h +++ b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h @@ -34,7 +34,7 @@ public: } void init(V4L2VideoDevice *dev, - std::initializer_list> delayList); + std::initializer_list> delayList); void reset(); void get(std::unordered_map &ctrl, uint8_t offset = 0); @@ -85,6 +85,7 @@ private: uint8_t maxDelay_; V4L2VideoDevice *dev_; std::unordered_map delay_; + std::unordered_map immediateWrite_; std::unordered_map ctrl_; std::mutex lock_; };