libcamera: pipeline: Add Intel IPU3 pipeline
Add a pipeline handler for the Intel IPU3 device. The pipeline handler creates a Camera for each image sensor it finds to be connected to an IPU3 CSI-2 receiver, and enables the link between the two. Tested on Soraka, listing detected cameras on the system, verifying the pipeline handler gets matched and links properly enabled. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
parent
8b8ae52134
commit
93734d7fe0
3 changed files with 190 additions and 0 deletions
185
src/libcamera/pipeline/ipu3/ipu3.cpp
Normal file
185
src/libcamera/pipeline/ipu3/ipu3.cpp
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019, Google Inc.
|
||||||
|
*
|
||||||
|
* ipu3.cpp - Pipeline handler for Intel IPU3
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <libcamera/camera.h>
|
||||||
|
#include <libcamera/camera_manager.h>
|
||||||
|
|
||||||
|
#include "device_enumerator.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "media_device.h"
|
||||||
|
#include "pipeline_handler.h"
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
class PipelineHandlerIPU3 : public PipelineHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PipelineHandlerIPU3();
|
||||||
|
~PipelineHandlerIPU3();
|
||||||
|
|
||||||
|
bool match(CameraManager *manager, DeviceEnumerator *enumerator);
|
||||||
|
|
||||||
|
private:
|
||||||
|
MediaDevice *cio2_;
|
||||||
|
MediaDevice *imgu_;
|
||||||
|
|
||||||
|
void registerCameras(CameraManager *manager);
|
||||||
|
};
|
||||||
|
|
||||||
|
PipelineHandlerIPU3::PipelineHandlerIPU3()
|
||||||
|
: cio2_(nullptr), imgu_(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PipelineHandlerIPU3::~PipelineHandlerIPU3()
|
||||||
|
{
|
||||||
|
if (cio2_)
|
||||||
|
cio2_->release();
|
||||||
|
|
||||||
|
if (imgu_)
|
||||||
|
imgu_->release();
|
||||||
|
|
||||||
|
cio2_ = nullptr;
|
||||||
|
imgu_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PipelineHandlerIPU3::match(CameraManager *manager, DeviceEnumerator *enumerator)
|
||||||
|
{
|
||||||
|
DeviceMatch cio2_dm("ipu3-cio2");
|
||||||
|
cio2_dm.add("ipu3-csi2 0");
|
||||||
|
cio2_dm.add("ipu3-cio2 0");
|
||||||
|
cio2_dm.add("ipu3-csi2 1");
|
||||||
|
cio2_dm.add("ipu3-cio2 1");
|
||||||
|
cio2_dm.add("ipu3-csi2 2");
|
||||||
|
cio2_dm.add("ipu3-cio2 2");
|
||||||
|
cio2_dm.add("ipu3-csi2 3");
|
||||||
|
cio2_dm.add("ipu3-cio2 3");
|
||||||
|
|
||||||
|
DeviceMatch imgu_dm("ipu3-imgu");
|
||||||
|
imgu_dm.add("ipu3-imgu 0");
|
||||||
|
imgu_dm.add("ipu3-imgu 0 input");
|
||||||
|
imgu_dm.add("ipu3-imgu 0 parameters");
|
||||||
|
imgu_dm.add("ipu3-imgu 0 output");
|
||||||
|
imgu_dm.add("ipu3-imgu 0 viewfinder");
|
||||||
|
imgu_dm.add("ipu3-imgu 0 3a stat");
|
||||||
|
imgu_dm.add("ipu3-imgu 1");
|
||||||
|
imgu_dm.add("ipu3-imgu 1 input");
|
||||||
|
imgu_dm.add("ipu3-imgu 1 parameters");
|
||||||
|
imgu_dm.add("ipu3-imgu 1 output");
|
||||||
|
imgu_dm.add("ipu3-imgu 1 viewfinder");
|
||||||
|
imgu_dm.add("ipu3-imgu 1 3a stat");
|
||||||
|
|
||||||
|
cio2_ = enumerator->search(cio2_dm);
|
||||||
|
if (!cio2_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
imgu_ = enumerator->search(imgu_dm);
|
||||||
|
if (!imgu_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It is safe to acquire both media devices at this point as
|
||||||
|
* DeviceEnumerator::search() skips the busy ones for us.
|
||||||
|
*/
|
||||||
|
cio2_->acquire();
|
||||||
|
imgu_->acquire();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable all links that are enabled by default on CIO2, as camera
|
||||||
|
* creation enables all valid links it finds.
|
||||||
|
*
|
||||||
|
* Close the CIO2 media device after, as links are enabled and should
|
||||||
|
* not need to be changed after.
|
||||||
|
*/
|
||||||
|
if (cio2_->open())
|
||||||
|
goto error_release_mdev;
|
||||||
|
|
||||||
|
if (cio2_->disableLinks())
|
||||||
|
goto error_close_cio2;
|
||||||
|
|
||||||
|
registerCameras(manager);
|
||||||
|
|
||||||
|
cio2_->close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error_close_cio2:
|
||||||
|
cio2_->close();
|
||||||
|
|
||||||
|
error_release_mdev:
|
||||||
|
cio2_->release();
|
||||||
|
imgu_->release();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cameras are created associating an image sensor (represented by a
|
||||||
|
* media entity with function MEDIA_ENT_F_CAM_SENSOR) to one of the four
|
||||||
|
* CIO2 CSI-2 receivers.
|
||||||
|
*/
|
||||||
|
void PipelineHandlerIPU3::registerCameras(CameraManager *manager)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* For each CSI-2 receiver on the IPU3, create a Camera if an
|
||||||
|
* image sensor is connected to it.
|
||||||
|
*/
|
||||||
|
unsigned int numCameras = 0;
|
||||||
|
for (unsigned int id = 0; id < 4; ++id) {
|
||||||
|
std::string csi2Name = "ipu3-csi2 " + std::to_string(id);
|
||||||
|
MediaEntity *csi2 = cio2_->getEntityByName(csi2Name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This shall not happen, as the device enumerator matched
|
||||||
|
* all entities described in the cio2_dm DeviceMatch.
|
||||||
|
*
|
||||||
|
* As this check is basically free, better stay safe than sorry.
|
||||||
|
*/
|
||||||
|
if (!csi2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const std::vector<MediaPad *> &pads = csi2->pads();
|
||||||
|
if (pads.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* IPU3 CSI-2 receivers have a single sink pad at index 0. */
|
||||||
|
MediaPad *sink = pads[0];
|
||||||
|
const std::vector<MediaLink *> &links = sink->links();
|
||||||
|
if (links.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify that the receiver is connected to a sensor, enable
|
||||||
|
* the media link between the two, and create a Camera with
|
||||||
|
* a unique name.
|
||||||
|
*/
|
||||||
|
MediaLink *link = links[0];
|
||||||
|
MediaEntity *sensor = link->source()->entity();
|
||||||
|
if (sensor->function() != MEDIA_ENT_F_CAM_SENSOR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (link->setEnabled(true))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string cameraName = sensor->name() + " " + std::to_string(id);
|
||||||
|
std::shared_ptr<Camera> camera = Camera::create(cameraName);
|
||||||
|
manager->addCamera(std::move(camera));
|
||||||
|
|
||||||
|
LOG(Info) << "Registered Camera[" << numCameras << "] \""
|
||||||
|
<< cameraName << "\""
|
||||||
|
<< " connected to CSI-2 receiver " << id;
|
||||||
|
|
||||||
|
numCameras++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3);
|
||||||
|
|
||||||
|
} /* namespace libcamera */
|
3
src/libcamera/pipeline/ipu3/meson.build
Normal file
3
src/libcamera/pipeline/ipu3/meson.build
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
libcamera_sources += files([
|
||||||
|
'ipu3.cpp',
|
||||||
|
])
|
|
@ -1,3 +1,5 @@
|
||||||
libcamera_sources += files([
|
libcamera_sources += files([
|
||||||
'vimc.cpp',
|
'vimc.cpp',
|
||||||
])
|
])
|
||||||
|
|
||||||
|
subdir('ipu3')
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue