@@ -58,6 +58,7 @@ public:
const ControlInfoMap &controls() const;
ControlList getControls(const std::vector<uint32_t> &ids);
int setControls(ControlList *ctrls);
+ int applyRequestControls(Request *request);
V4L2Subdevice *device() { return subdev_.get(); }
@@ -755,6 +755,40 @@ int CameraSensor::setControls(ControlList *ctrls)
return subdev_->setControls(ctrls);
}
+/**
+ * \brief Apply controls associated with Request
+ * \param[in] request Request that may contain contorls to be applied
+ *
+ * Some controls have to be applied for a capture associated with Request.
+ * This picks up such controls and set the driver them.
+ *
+ * \return 0 on success or an error code otherwise
+ */
+int32_t CameraSensor::applyRequestControls(Request *request)
+{
+ /* Assumes applying the test pattern mode affects immediately. */
+ if (request->controls().contains(controls::draft::TestPatternMode)) {
+ const int32_t testPatternMode = request->controls().get(
+ controls::draft::TestPatternMode);
+
+ LOG(CameraSensor, Debug) << "Apply test pattern mode: "
+ << testPatternMode;
+
+ int ret = setTestPatternMode(
+ static_cast<controls::draft::TestPatternModeEnum>(testPatternMode));
+ if (ret) {
+ LOG(CameraSensor, Error)
+ << "Failed to set test pattern mode: " << ret;
+ return ret;
+ }
+
+ request->metadata().set(controls::draft::TestPatternMode,
+ testPatternMode);
+ }
+
+ return 0;
+}
+
/**
* \fn CameraSensor::device()
* \brief Retrieve the camera sensor device
@@ -59,6 +59,7 @@ public:
void statBufferReady(FrameBuffer *buffer);
void queuePendingRequests();
void cancelPendingRequests();
+ void frameStart(uint32_t sequence);
CIO2Device cio2_;
ImgUDevice *imgu_;
@@ -77,7 +78,10 @@ public:
std::unique_ptr<ipa::ipu3::IPAProxyIPU3> ipa_;
+ /* Requests before queueing cio2 device. */
std::queue<Request *> pendingRequests_;
+ /* Requests queued in cio2 device and before passing imgu device. */
+ std::queue<Request *> processingRequests_;
ControlInfoMap ipaControls_;
@@ -802,6 +806,7 @@ void PipelineHandlerIPU3::stop(Camera *camera)
ret |= data->imgu_->stop();
ret |= data->cio2_.stop();
+
if (ret)
LOG(IPU3, Warning) << "Failed to stop camera " << camera->id();
@@ -822,6 +827,8 @@ void IPU3CameraData::cancelPendingRequests()
pipe()->completeRequest(request);
pendingRequests_.pop();
}
+
+ processingRequests_ = {};
}
void IPU3CameraData::queuePendingRequests()
@@ -852,6 +859,8 @@ void IPU3CameraData::queuePendingRequests()
info->rawBuffer = rawBuffer;
+ processingRequests_.push(request);
+
ipa::ipu3::IPU3Event ev;
ev.op = ipa::ipu3::EventProcessControls;
ev.frame = info->id;
@@ -1131,8 +1140,8 @@ int PipelineHandlerIPU3::registerCameras()
data->delayedCtrls_ =
std::make_unique<DelayedControls>(cio2->sensor()->device(),
params);
- data->cio2_.frameStart().connect(data->delayedCtrls_.get(),
- &DelayedControls::applyControls);
+ data->cio2_.frameStart().connect(data.get(),
+ &IPU3CameraData::frameStart);
/* Convert the sensor rotation to a transformation */
int32_t rotation = 0;
@@ -1423,6 +1432,22 @@ void IPU3CameraData::statBufferReady(FrameBuffer *buffer)
ipa_->processEvent(ev);
}
+void IPU3CameraData::frameStart(uint32_t sequence)
+{
+ if (!processingRequests_.empty()) {
+ /* Handle controls which are to be set ready for the next frame to start. */
+ Request *request = processingRequests_.front();
+ processingRequests_.pop();
+
+ int ret = cio2_.sensor()->applyRequestControls(request);
+ if (ret)
+ LOG(IPU3, Error) << "Failed applying controls: " << ret;
+ }
+
+ /* Controls that don't affect immediately are applied in delayedCtrls. */
+ delayedCtrls_->applyControls(sequence);
+}
+
REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3)
} /* namespace libcamera */