summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNiklas Söderlund <niklas.soderlund@ragnatech.se>2020-11-04 02:20:22 +0100
committerNiklas Söderlund <niklas.soderlund@ragnatech.se>2021-02-05 01:20:32 +0100
commit9cdad8461e61e815ddb7378e87cb047ab168d290 (patch)
treec72db3fa2b1e5a1742c06f3aecc76585d6923e89 /src
parent0a7000cc96ad26e01efc4b204d90ce3a9734ea06 (diff)
libcamera: ipu3: Attach to an IPA and allow it to set sensor controls
Attach to the IPA and allow it to push V4L2 controls that apply to the camera sensor. The IPA is not fully integrated in the pipeline as statistics and parameters buffers are not yet allocated, processed by the IPA nor queued to the hardware. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src')
-rw-r--r--src/libcamera/pipeline/ipu3/ipu3.cpp91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 184986fc..13af8600 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -14,11 +14,14 @@
#include <libcamera/camera.h>
#include <libcamera/control_ids.h>
#include <libcamera/formats.h>
+#include <libcamera/ipa/ipu3.h>
#include <libcamera/request.h>
#include <libcamera/stream.h>
#include "libcamera/internal/camera_sensor.h"
+#include "libcamera/internal/delayed_controls.h"
#include "libcamera/internal/device_enumerator.h"
+#include "libcamera/internal/ipa_manager.h"
#include "libcamera/internal/log.h"
#include "libcamera/internal/media_device.h"
#include "libcamera/internal/pipeline_handler.h"
@@ -54,6 +57,8 @@ public:
{
}
+ int loadIPA();
+
void imguOutputBufferReady(FrameBuffer *buffer);
void cio2BufferReady(FrameBuffer *buffer);
@@ -65,6 +70,10 @@ public:
Stream rawStream_;
uint32_t exposureTime_;
+ std::unique_ptr<DelayedControls> delayedCtrls_;
+
+private:
+ void queueFrameAction(unsigned int id, const IPAOperationData &op);
};
class IPU3CameraConfiguration : public CameraConfiguration
@@ -594,6 +603,13 @@ int PipelineHandlerIPU3::start(Camera *camera, [[maybe_unused]] ControlList *con
IPU3CameraData *data = cameraData(camera);
CIO2Device *cio2 = &data->cio2_;
ImgUDevice *imgu = data->imgu_;
+
+ CameraSensorInfo sensorInfo = {};
+ std::map<unsigned int, IPAStream> streamConfig;
+ std::map<unsigned int, const ControlInfoMap &> entityControls;
+ IPAOperationData ipaConfig;
+ IPAOperationData result = {};
+
int ret;
/* Allocate buffers for internal pipeline usage. */
@@ -601,6 +617,11 @@ int PipelineHandlerIPU3::start(Camera *camera, [[maybe_unused]] ControlList *con
if (ret)
return ret;
+ IPAOperationData ipaData = {};
+ ret = data->ipa_->start(ipaData, nullptr);
+ if (ret)
+ goto error;
+
/*
* Start the ImgU video devices, buffers will be queued to the
* ImgU output and viewfinder when requests will be queued.
@@ -613,11 +634,31 @@ int PipelineHandlerIPU3::start(Camera *camera, [[maybe_unused]] ControlList *con
if (ret)
goto error;
+ /* Inform IPA of stream configuration and sensor controls. */
+ ret = data->cio2_.sensor()->sensorInfo(&sensorInfo);
+ if (ret)
+ goto error;
+
+ streamConfig[0] = {
+ .pixelFormat = data->outStream_.configuration().pixelFormat,
+ .size = data->outStream_.configuration().size,
+ };
+ streamConfig[1] = {
+ .pixelFormat = data->vfStream_.configuration().pixelFormat,
+ .size = data->vfStream_.configuration().size,
+ };
+
+ entityControls.emplace(0, data->cio2_.sensor()->controls());
+
+ data->ipa_->configure(sensorInfo, streamConfig, entityControls,
+ ipaConfig, &result);
+
return 0;
error:
imgu->stop();
cio2->stop();
+ data->ipa_->stop();
freeBuffers(camera);
LOG(IPU3, Error) << "Failed to start camera " << camera->id();
@@ -634,6 +675,8 @@ void PipelineHandlerIPU3::stop(Camera *camera)
if (ret)
LOG(IPU3, Warning) << "Failed to stop camera " << camera->id();
+ data->ipa_->stop();
+
freeBuffers(camera);
}
@@ -883,6 +926,10 @@ int PipelineHandlerIPU3::registerCameras()
if (ret)
continue;
+ ret = data->loadIPA();
+ if (ret)
+ continue;
+
/* Initialize the camera properties. */
data->properties_ = cio2->sensor()->properties();
@@ -890,6 +937,22 @@ int PipelineHandlerIPU3::registerCameras()
if (ret)
continue;
+ /*
+ * \todo Read delay values from the sensor itself or from a
+ * a sensor database. For now use generic values taken from
+ * the Raspberry Pi and listed as 'generic values'.
+ */
+ std::unordered_map<uint32_t, unsigned int> delays = {
+ { V4L2_CID_ANALOGUE_GAIN, 1 },
+ { V4L2_CID_EXPOSURE, 2 },
+ };
+
+ data->delayedCtrls_ =
+ std::make_unique<DelayedControls>(cio2->sensor()->device(),
+ delays);
+ data->cio2_.frameStart().connect(data->delayedCtrls_.get(),
+ &DelayedControls::applyControls);
+
/**
* \todo Dynamically assign ImgU and output devices to each
* stream and camera; as of now, limit support to two cameras
@@ -933,6 +996,34 @@ int PipelineHandlerIPU3::registerCameras()
return numCameras ? 0 : -ENODEV;
}
+int IPU3CameraData::loadIPA()
+{
+ ipa_ = IPAManager::createIPA(pipe_, 1, 1);
+ if (!ipa_)
+ return -ENOENT;
+
+ ipa_->queueFrameAction.connect(this, &IPU3CameraData::queueFrameAction);
+
+ ipa_->init(IPASettings{});
+
+ return 0;
+}
+
+void IPU3CameraData::queueFrameAction([[maybe_unused]] unsigned int id,
+ const IPAOperationData &action)
+{
+ switch (action.operation) {
+ case IPU3_IPA_ACTION_SET_SENSOR_CONTROLS: {
+ const ControlList &controls = action.controls[0];
+ delayedCtrls_->push(controls);
+ break;
+ }
+ default:
+ LOG(IPU3, Error) << "Unknown action " << action.operation;
+ break;
+ }
+}
+
/* -----------------------------------------------------------------------------
* Buffer Ready slots
*/