From 96c0eb338e5e9168147538736b688601c00b87f9 Mon Sep 17 00:00:00 2001 From: Naushir Patuck Date: Thu, 4 Mar 2021 08:17:22 +0000 Subject: libcamera: delayed_controls: Add notion of priority write If an exposure time change adjusts the vblanking limits, and we set both VBLANK and EXPOSURE controls through the VIDIOC_S_EXT_CTRLS ioctl, 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 setting VBLANK before EXPOSURE in a single VIDIOC_S_EXT_CTRLS ioctl. The workaround here is to have the DelayedControls object mark the VBLANK control as "priority 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. To support this, a new struct DelayedControls::ControlParams is used in the constructor to provide the control delay value as well as the priority write flag. Signed-off-by: Naushir Patuck Tested-by: David Plowman Reviewed-by: Paul Elder Tested-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham [Kieran: Fix up trivial comments, merge conflicts] Signed-off-by: Kieran Bingham --- src/libcamera/pipeline/ipu3/ipu3.cpp | 8 ++++---- src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 13 ++++++------- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 8 ++++---- 3 files changed, 14 insertions(+), 15 deletions(-) (limited to 'src/libcamera/pipeline') diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 00da2bb2..2ea13ec9 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -1058,14 +1058,14 @@ int PipelineHandlerIPU3::registerCameras() * a sensor database. For now use generic values taken from * the Raspberry Pi and listed as 'generic values'. */ - std::unordered_map delays = { - { V4L2_CID_ANALOGUE_GAIN, 1 }, - { V4L2_CID_EXPOSURE, 2 }, + std::unordered_map params = { + { V4L2_CID_ANALOGUE_GAIN, { 1, false } }, + { V4L2_CID_EXPOSURE, { 2, false } }, }; data->delayedCtrls_ = std::make_unique(cio2->sensor()->device(), - delays); + params); data->cio2_.frameStart().connect(data->delayedCtrls_.get(), &DelayedControls::applyControls); diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 0f01ce8f..41f1cbff 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -1260,16 +1260,15 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config) if (result.params & ipa::RPi::ConfigSensorParams) { /* * Setup our delayed control writer with the sensor default - * gain and exposure delays. + * gain and exposure delays. Mark VBLANK for priority write. */ - std::unordered_map delays = { - { V4L2_CID_ANALOGUE_GAIN, result.sensorConfig.gainDelay }, - { V4L2_CID_EXPOSURE, result.sensorConfig.exposureDelay }, - { V4L2_CID_VBLANK, result.sensorConfig.vblankDelay } + std::unordered_map params = { + { V4L2_CID_ANALOGUE_GAIN, { result.sensorConfig.gainDelay, false } }, + { V4L2_CID_EXPOSURE, { result.sensorConfig.exposureDelay, false } }, + { V4L2_CID_VBLANK, { result.sensorConfig.vblankDelay, true } } }; - delayedCtrls_ = std::make_unique(unicam_[Unicam::Image].dev(), delays); - + delayedCtrls_ = std::make_unique(unicam_[Unicam::Image].dev(), params); sensorMetadata_ = result.sensorConfig.sensorMetadata; } diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 4376d720..03757327 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -945,14 +945,14 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) * a sensor database. For now use generic values taken from * the Raspberry Pi and listed as generic values. */ - std::unordered_map delays = { - { V4L2_CID_ANALOGUE_GAIN, 1 }, - { V4L2_CID_EXPOSURE, 2 }, + std::unordered_map params = { + { V4L2_CID_ANALOGUE_GAIN, { 1, false } }, + { V4L2_CID_EXPOSURE, { 2, false } }, }; data->delayedCtrls_ = std::make_unique(data->sensor_->device(), - delays); + params); isp_->frameStart.connect(data->delayedCtrls_.get(), &DelayedControls::applyControls); -- cgit v1.2.1