From edfdace1d59ef1c9ae33889553d166693462ff7c Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Mon, 4 Feb 2019 19:15:03 +0100 Subject: libcamera: pipeline: ipu3: Implement capture support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the buffer allocation, capture start/stop and request queue stubs with real implementations. Signed-off-by: Jacopo Mondi Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- src/libcamera/pipeline/ipu3/ipu3.cpp | 123 ++++++++++++++++++++++++++++++++--- 1 file changed, 114 insertions(+), 9 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 9629057a..34b03995 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include "device_enumerator.h" @@ -97,12 +98,23 @@ PipelineHandlerIPU3::streamConfiguration(Camera *camera, std::vector &streams) { IPU3CameraData *data = cameraData(camera); - std::map 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 &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; + + /* + * 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) << "TODO: Configure the camera for resolution " - << cfg->width << "x" << cfg->height; + 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; } -- cgit v1.2.1