/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2019, Google Inc.
*
* rkisp1.cpp - Pipeline handler for Rockchip ISP1
*/
#include <algorithm>
#include <array>
#include <iomanip>
#include <memory>
#include <numeric>
#include <queue>
#include <linux/media-bus-format.h>
#include <libcamera/buffer.h>
#include <libcamera/camera.h>
#include <libcamera/control_ids.h>
#include <libcamera/formats.h>
#include <libcamera/ipa/rkisp1.h>
#include <libcamera/request.h>
#include <libcamera/span.h>
#include <libcamera/stream.h>
#include "libcamera/internal/camera_sensor.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"
#include "libcamera/internal/utils.h"
#include "libcamera/internal/v4l2_subdevice.h"
#include "libcamera/internal/v4l2_videodevice.h"
#include "timeline.h"
namespace libcamera {
LOG_DEFINE_CATEGORY(RkISP1)
namespace {
constexpr Size RKISP1_RSZ_MP_SRC_MIN{ 32, 16 };
constexpr Size RKISP1_RSZ_MP_SRC_MAX{ 4416, 3312 };
constexpr std::array<PixelFormat, 7> RKISP1_RSZ_MP_FORMATS{
formats::YUYV,
formats::YVYU,
formats::VYUY,
formats::NV16,
formats::NV61,
formats::NV21,
formats::NV12,
/* \todo Add support for 8-bit greyscale to DRM formats */
};
constexpr Size RKISP1_RSZ_SP_SRC_MIN{ 32, 16 };
constexpr Size RKISP1_RSZ_SP_SRC_MAX{ 1920, 1920 };
constexpr std::array<PixelFormat, 7> RKISP1_RSZ_SP_FORMATS{
formats::YUYV,
formats::YVYU,
formats::VYUY,
formats::NV16,
formats::NV61,
formats::NV21,
formats::NV12,
/* \todo Add support for BGR888 and RGB565 */
};
} /* namespace */
class PipelineHandlerRkISP1;
class RkISP1ActionQueueBuffers;
class RkISP1CameraData;
enum RkISP1ActionType {
SetSensor,
SOE,
QueueBuffers,
};
struct RkISP1FrameInfo {
unsigned int frame;
Request *request;
FrameBuffer *paramBuffer;
FrameBuffer *statBuffer;
FrameBuffer *mainPathBuffer;
FrameBuffer *selfPathBuffer;
bool paramFilled;
bool paramDequeued;
bool metadataProcessed;
};
class RkISP1Frames
{
public:
RkISP1Frames(PipelineHandler *pipe);
RkISP1FrameInfo *create(const RkISP1CameraData *data, Request *request);
int destroy(unsigned int frame);
void clear();
RkISP1FrameInfo *find(unsigned int frame);
RkISP1FrameInfo *find(FrameBuffer *buffer);
RkISP1FrameInfo *find(Request *request);
private:
PipelineHandlerRkISP1 *pipe_;
std::map<unsigned int, RkISP1FrameInfo *> frameInfo_;
};
class RkISP1Timeline : public Timeline
{
public:
RkISP1Timeline()
: Timeline()
{
setDelay(SetSensor, -1, 5);
setDelay(SOE, 0, -1);
setDelay(QueueBuffers, -1, 10);
}
void bufferReady(FrameBuffer *buffer)
{
/*
* Calculate SOE by taking the end of DMA set by the kernel and applying
* the time offsets provideprovided by the IPA to find the best estimate
* of SOE.
*/
ASSERT(frameOffset(SOE) == 0);
utils::time_point soe = std::chrono::time_point<utils::clock>()
+ std::chrono::nanoseconds(buffer->metadata().timestamp)
+ timeOffset(SOE);
notifyStartOfExposure(buffer->metadata().sequence, soe);
}
void setDelay(unsigned int type, int frame, int msdelay)
{
utils::duration delay = std::chrono::milliseconds(msdelay);
setRawDelay(type, frame, delay);
}
};
class RkISP1CameraData : public CameraData
{
public:
RkISP1CameraData(PipelineHandler *pipe, V4L2VideoDevice *mainPathVideo,
V4L2VideoDevice *selfPathVideo)
: CameraData(pipe), sensor_(nullptr), frame_(0),
frameInfo_(pipe), mainPathVideo_(mainPathVideo),
selfPathVideo_(selfPathVideo), mainPathActive_(false),
selfPathActive_(false)
{
}
~RkISP1CameraData()
{
delete sensor_;
}
int loadIPA();
Stream mainPathStream_;
Stream selfPathStream_;
CameraSensor *sensor_;
unsigned int frame_;
std::vector<IPABuffer> ipaBuffers_;
RkISP1Frames frameInfo_;
RkISP1Timeline timeline_;
V4L2VideoDevice *mainPathVideo_;
V4L2VideoDevice *selfPathVideo_;
bool mainPathActive_;
bool selfPathActive_;
private:
void queueFrameAction(unsigned int frame,
const IPAOperationData &action);
void metadataReady(unsigned int frame, const ControlList &metadata);
};
class RkISP1CameraConfiguration : public CameraConfiguration
{
public:
RkISP1CameraConfiguration(Camera *camera, RkISP1CameraData *data);
Status validate() override;
const V4L2SubdeviceFormat &sensorFormat() { return sensorFormat_; }
private:
static constexpr unsigned int RKISP1_BUFFER_COUNT = 4;
CameraConfiguration::Status validatePath(StreamConfiguration *cfg,
const Span<const PixelFormat> &formats,
const Size &min, const Size &max,
V4L2VideoDevice *video);
CameraConfiguration::Status validateMainPath(StreamConfiguration *cfg);
CameraConfiguration::Status validateSelfPath(StreamConfiguration *cfg);
bool fitsAllPaths(const StreamConfiguration &cfg);
/*
* The RkISP1CameraData instance is guaranteed to be valid as long as the
* corresponding Camera instance is valid. In order to borrow a
* reference to the camera data, store a new reference to the camera.
*/
std::shared_ptr<Camera> camera_;
const RkISP1CameraData *data_;
V4L2SubdeviceFormat sensorFormat_;
};
class PipelineHandlerRkISP1 : public PipelineHandler
{
public:
PipelineHandlerRkISP1(CameraManager *manager);
~PipelineHandlerRkISP1();
|