summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNaushir Patuck <naush@raspberrypi.com>2021-07-12 11:02:07 +0100
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2021-07-12 15:57:12 +0300
commit9c0f6a22a2411fe5f21a1d8ac8783d1b6a13500f (patch)
treec25d64a4779d73128681e24272d9507965808d11
parent6d89e33814d6f43873d2f38a13a12528f63a7e0d (diff)
pipeline: raspberrypi: Use priority write for vblank when writing sensor ctrls
When directly writing controls to the sensor device, ensure that VBLANK is written ahead of and before the EXPOSURE control. This is the same priority write mechanism used in DelayedControls. Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: David Plowman <david.plowman@raspberrypi.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--src/libcamera/pipeline/raspberrypi/raspberrypi.cpp43
1 files changed, 32 insertions, 11 deletions
diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
index 4f1a5985..54d3c8ed 100644
--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
@@ -154,6 +154,7 @@ public:
void embeddedComplete(uint32_t bufferId);
void setIspControls(const ControlList &controls);
void setDelayedControls(const ControlList &controls);
+ void setSensorControls(ControlList &controls);
/* bufferComplete signal handlers. */
void unicamBufferDequeue(FrameBuffer *buffer);
@@ -828,7 +829,7 @@ int PipelineHandlerRPi::start(Camera *camera, const ControlList *controls)
/* Apply any gain/exposure settings that the IPA may have passed back. */
if (!startConfig.controls.empty())
- data->unicam_[Unicam::Image].dev()->setControls(&startConfig.controls);
+ data->setSensorControls(startConfig.controls);
/* Configure the number of dropped frames required on startup. */
data->dropFrameCount_ = startConfig.dropFrameCount;
@@ -1075,7 +1076,7 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator)
ControlList ctrls(dev->controls());
ctrls.set(V4L2_CID_HFLIP, 0);
ctrls.set(V4L2_CID_VFLIP, 0);
- dev->setControls(&ctrls);
+ data->setSensorControls(ctrls);
}
/* Look for a valid Bayer format. */
@@ -1294,22 +1295,20 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config)
return -EPIPE;
}
- if (!controls.empty())
- unicam_[Unicam::Image].dev()->setControls(&controls);
-
/*
* Configure the H/V flip controls based on the combination of
* the sensor and user transform.
*/
if (supportsFlips_) {
- ControlList ctrls(unicam_[Unicam::Image].dev()->controls());
- ctrls.set(V4L2_CID_HFLIP,
- static_cast<int32_t>(!!(rpiConfig->combinedTransform_ & Transform::HFlip)));
- ctrls.set(V4L2_CID_VFLIP,
- static_cast<int32_t>(!!(rpiConfig->combinedTransform_ & Transform::VFlip)));
- unicam_[Unicam::Image].dev()->setControls(&ctrls);
+ controls.set(V4L2_CID_HFLIP,
+ static_cast<int32_t>(!!(rpiConfig->combinedTransform_ & Transform::HFlip)));
+ controls.set(V4L2_CID_VFLIP,
+ static_cast<int32_t>(!!(rpiConfig->combinedTransform_ & Transform::VFlip)));
}
+ if (!controls.empty())
+ setSensorControls(controls);
+
return 0;
}
@@ -1379,6 +1378,28 @@ void RPiCameraData::setDelayedControls(const ControlList &controls)
handleState();
}
+void RPiCameraData::setSensorControls(ControlList &controls)
+{
+ /*
+ * We need to ensure that if both VBLANK and EXPOSURE are present, the
+ * former must be written ahead of, and separately from EXPOSURE to avoid
+ * V4L2 rejecting the latter. This is identical to what DelayedControls
+ * does with the priority write flag.
+ *
+ * As a consequence of the below logic, VBLANK gets set twice, and we
+ * rely on the v4l2 framework to not pass the second control set to the
+ * driver as the actual control value has not changed.
+ */
+ if (controls.contains(V4L2_CID_EXPOSURE) && controls.contains(V4L2_CID_VBLANK)) {
+ ControlList vblank_ctrl;
+
+ vblank_ctrl.set(V4L2_CID_VBLANK, controls.get(V4L2_CID_VBLANK));
+ unicam_[Unicam::Image].dev()->setControls(&vblank_ctrl);
+ }
+
+ unicam_[Unicam::Image].dev()->setControls(&controls);
+}
+
void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer)
{
RPi::Stream *stream = nullptr;