summaryrefslogtreecommitdiff
path: root/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcamera/pipeline/raspberrypi/raspberrypi.cpp')
-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;