libcamera: pipeline: ipu3: Implement capture support

Replace the buffer allocation, capture start/stop and request queue
stubs with real implementations.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Jacopo Mondi 2019-02-04 19:15:03 +01:00 committed by Laurent Pinchart
parent 7da6b95283
commit edfdace1d5

View file

@ -9,6 +9,7 @@
#include <vector>
#include <libcamera/camera.h>
#include <libcamera/request.h>
#include <libcamera/stream.h>
#include "device_enumerator.h"
@ -97,12 +98,23 @@ PipelineHandlerIPU3::streamConfiguration(Camera *camera,
std::vector<Stream *> &streams)
{
IPU3CameraData *data = cameraData(camera);
std::map<Stream *, StreamConfiguration> configs;
V4L2SubdeviceFormat format = {};
StreamConfiguration config{};
/*
* FIXME: As of now, return the image format reported by the sensor.
* In future good defaults should be provided for each stream.
*/
if (data->sensor_->getFormat(0, &format)) {
LOG(IPU3, Error) << "Failed to create stream configurations";
return configs;
}
LOG(IPU3, Info) << "TODO: Return a good default format";
StreamConfiguration config = {};
config.width = format.width;
config.height = format.height;
config.pixelFormat = V4L2_PIX_FMT_IPU3_SGRBG10;
config.bufferCount = 4;
configs[&data->stream_] = config;
@ -113,38 +125,131 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera,
std::map<Stream *, StreamConfiguration> &config)
{
IPU3CameraData *data = cameraData(camera);
StreamConfiguration *cfg = &config[&data->stream_];
V4L2Subdevice *sensor = data->sensor_;
V4L2Subdevice *csi2 = data->csi2_;
V4L2Device *cio2 = data->cio2_;
V4L2SubdeviceFormat subdevFormat = {};
V4L2DeviceFormat devFormat = {};
int ret;
LOG(IPU3, Info) << "TODO: Configure the camera for resolution "
<< cfg->width << "x" << cfg->height;
/*
* FIXME: as of now, the format gets applied to the sensor and is
* propagated along the pipeline. It should instead be applied on the
* capture device and the sensor format calculated accordingly.
*/
ret = sensor->getFormat(0, &subdevFormat);
if (ret)
return ret;
subdevFormat.width = cfg->width;
subdevFormat.height = cfg->height;
ret = sensor->setFormat(0, &subdevFormat);
if (ret)
return ret;
/* Return error if the requested format cannot be applied to sensor. */
if (subdevFormat.width != cfg->width ||
subdevFormat.height != cfg->height) {
LOG(IPU3, Error)
<< "Failed to apply image format "
<< subdevFormat.width << "x" << subdevFormat.height
<< " - got: " << cfg->width << "x" << cfg->height;
return -EINVAL;
}
ret = csi2->setFormat(0, &subdevFormat);
if (ret)
return ret;
ret = cio2->getFormat(&devFormat);
if (ret)
return ret;
devFormat.width = subdevFormat.width;
devFormat.height = subdevFormat.height;
devFormat.fourcc = cfg->pixelFormat;
ret = cio2->setFormat(&devFormat);
if (ret)
return ret;
LOG(IPU3, Info) << cio2->driverName() << ": "
<< devFormat.width << "x" << devFormat.height
<< "- 0x" << std::hex << devFormat.fourcc << " planes: "
<< devFormat.planes;
return 0;
}
int PipelineHandlerIPU3::allocateBuffers(Camera *camera, Stream *stream)
{
return -ENOTRECOVERABLE;
IPU3CameraData *data = cameraData(camera);
const StreamConfiguration &cfg = stream->configuration();
if (!cfg.bufferCount)
return -EINVAL;
int ret = data->cio2_->exportBuffers(cfg.bufferCount,
&stream->bufferPool());
if (ret) {
LOG(IPU3, Error) << "Failed to request memory";
return ret;
}
return 0;
}
int PipelineHandlerIPU3::freeBuffers(Camera *camera, Stream *stream)
{
IPU3CameraData *data = cameraData(camera);
int ret = data->cio2_->releaseBuffers();
if (ret) {
LOG(IPU3, Error) << "Failed to release memory";
return ret;
}
return 0;
}
int PipelineHandlerIPU3::start(const Camera *camera)
{
LOG(IPU3, Error) << "TODO: start camera";
IPU3CameraData *data = cameraData(camera);
int ret;
ret = data->cio2_->streamOn();
if (ret) {
LOG(IPU3, Info) << "Failed to start camera " << camera->name();
return ret;
}
return 0;
}
void PipelineHandlerIPU3::stop(const Camera *camera)
{
LOG(IPU3, Error) << "TODO: stop camera";
IPU3CameraData *data = cameraData(camera);
if (data->cio2_->streamOff())
LOG(IPU3, Info) << "Failed to stop camera " << camera->name();
}
int PipelineHandlerIPU3::queueRequest(const Camera *camera, Request *request)
{
IPU3CameraData *data = cameraData(camera);
Stream *stream = &data->stream_;
Buffer *buffer = request->findBuffer(stream);
if (!buffer) {
LOG(IPU3, Error)
<< "Attempt to queue request with invalid stream";
return -ENOENT;
}
data->cio2_->queueBuffer(buffer);
return 0;
}