|
@@ -0,0 +1,1109 @@
|
|
|
+From 0a7af884c40080461ac59cf6eda86b8d1da035fd Mon Sep 17 00:00:00 2001
|
|
|
+From: sw.multimedia <sw.multimedia@starfivetech.com>
|
|
|
+Date: Sat, 9 Oct 2021 18:09:44 +0800
|
|
|
+Subject: [PATCH] add starfive pipeline
|
|
|
+
|
|
|
+---
|
|
|
+ include/libcamera/internal/v4l2_subdevice.h | 1 +
|
|
|
+ include/linux/v4l2-subdev.h | 9 +
|
|
|
+ meson_options.txt | 2 +-
|
|
|
+ src/gstreamer/gstlibcamera-utils.cpp | 7 +
|
|
|
+ src/gstreamer/gstlibcamerasrc.cpp | 16 +-
|
|
|
+ src/libcamera/pipeline/starfive/meson.build | 5 +
|
|
|
+ src/libcamera/pipeline/starfive/starfive.cpp | 940 +++++++++++++++++++
|
|
|
+ src/libcamera/v4l2_subdevice.cpp | 12 +
|
|
|
+ 8 files changed, 990 insertions(+), 2 deletions(-)
|
|
|
+ create mode 100644 src/libcamera/pipeline/starfive/meson.build
|
|
|
+ create mode 100644 src/libcamera/pipeline/starfive/starfive.cpp
|
|
|
+
|
|
|
+diff --git a/include/libcamera/internal/v4l2_subdevice.h b/include/libcamera/internal/v4l2_subdevice.h
|
|
|
+index 97b89fb9..fe8835bd 100644
|
|
|
+--- a/include/libcamera/internal/v4l2_subdevice.h
|
|
|
++++ b/include/libcamera/internal/v4l2_subdevice.h
|
|
|
+@@ -63,6 +63,7 @@ public:
|
|
|
+
|
|
|
+ static std::unique_ptr<V4L2Subdevice>
|
|
|
+ fromEntityName(const MediaDevice *media, const std::string &entity);
|
|
|
++ int ioctlPrivate(unsigned long request, void *argp);
|
|
|
+
|
|
|
+ protected:
|
|
|
+ std::string logPrefix() const override;
|
|
|
+diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h
|
|
|
+index a38454d9..5f127523 100644
|
|
|
+--- a/include/linux/v4l2-subdev.h
|
|
|
++++ b/include/linux/v4l2-subdev.h
|
|
|
+@@ -206,4 +206,13 @@ struct v4l2_subdev_capability {
|
|
|
+ #define VIDIOC_SUBDEV_QUERY_DV_TIMINGS _IOR('V', 99, struct v4l2_dv_timings)
|
|
|
+ #define VIDIOC_SUBDEV_DV_TIMINGS_CAP _IOWR('V', 100, struct v4l2_dv_timings_cap)
|
|
|
+
|
|
|
++#define STF_ISPFW_FILENAME_MAX_LEN 30
|
|
|
++
|
|
|
++struct stfisp_fw_info {
|
|
|
++ char filename[STF_ISPFW_FILENAME_MAX_LEN];
|
|
|
++};
|
|
|
++
|
|
|
++#define VIDIOC_STFISP_LOAD_FW \
|
|
|
++ _IOW('V', BASE_VIDIOC_PRIVATE + 1, struct stfisp_fw_info)
|
|
|
++
|
|
|
+ #endif
|
|
|
+diff --git a/meson_options.txt b/meson_options.txt
|
|
|
+index 2c80ad8b..14baa7ef 100644
|
|
|
+--- a/meson_options.txt
|
|
|
++++ b/meson_options.txt
|
|
|
+@@ -37,7 +37,7 @@ option('lc-compliance',
|
|
|
+
|
|
|
+ option('pipelines',
|
|
|
+ type : 'array',
|
|
|
+- choices : ['ipu3', 'raspberrypi', 'rkisp1', 'simple', 'uvcvideo', 'vimc'],
|
|
|
++ choices : ['ipu3', 'raspberrypi', 'rkisp1', 'simple', 'uvcvideo', 'vimc', 'starfive'],
|
|
|
+ description : 'Select which pipeline handlers to include')
|
|
|
+
|
|
|
+ option('qcam',
|
|
|
+diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp
|
|
|
+index 0af91c1a..b40b78ae 100644
|
|
|
+--- a/src/gstreamer/gstlibcamera-utils.cpp
|
|
|
++++ b/src/gstreamer/gstlibcamera-utils.cpp
|
|
|
+@@ -126,6 +126,12 @@ gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg
|
|
|
+ "width", G_TYPE_INT, stream_cfg.size.width,
|
|
|
+ "height", G_TYPE_INT, stream_cfg.size.height,
|
|
|
+ nullptr);
|
|
|
++
|
|
|
++ // Add framerate negotiation support
|
|
|
++ // the range will be [ 0/1, 2147483647/1 ] as there is not any args
|
|
|
++ // required from driver for the time being.
|
|
|
++ gst_structure_set(s, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
|
|
|
++
|
|
|
+ gst_caps_append_structure(caps, s);
|
|
|
+
|
|
|
+ return caps;
|
|
|
+@@ -217,6 +223,7 @@ gst_libcamera_resume_task(GstTask *task)
|
|
|
+ /* We only want to resume the task if it's paused. */
|
|
|
+ GLibLocker lock(GST_OBJECT(task));
|
|
|
+ if (GST_TASK_STATE(task) == GST_TASK_PAUSED) {
|
|
|
++ GST_DEBUG("gst_libcamera_resume_task");
|
|
|
+ GST_TASK_STATE(task) = GST_TASK_STARTED;
|
|
|
+ GST_TASK_SIGNAL(task);
|
|
|
+ }
|
|
|
+diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
|
|
|
+index 2be44edd..fab2aa2a 100644
|
|
|
+--- a/src/gstreamer/gstlibcamerasrc.cpp
|
|
|
++++ b/src/gstreamer/gstlibcamerasrc.cpp
|
|
|
+@@ -46,6 +46,7 @@ using namespace libcamera;
|
|
|
+
|
|
|
+ GST_DEBUG_CATEGORY_STATIC(source_debug);
|
|
|
+ #define GST_CAT_DEFAULT source_debug
|
|
|
++#define TASK_PAUSE_COUNT_MAX 2
|
|
|
+
|
|
|
+ struct RequestWrap {
|
|
|
+ RequestWrap(std::unique_ptr<Request> request);
|
|
|
+@@ -125,6 +126,7 @@ struct _GstLibcameraSrc {
|
|
|
+ GstLibcameraSrcState *state;
|
|
|
+ GstLibcameraAllocator *allocator;
|
|
|
+ GstFlowCombiner *flow_combiner;
|
|
|
++ guint task_pause_count;
|
|
|
+ };
|
|
|
+
|
|
|
+ enum {
|
|
|
+@@ -340,8 +342,20 @@ gst_libcamera_src_task_run(gpointer user_data)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+- if (do_pause)
|
|
|
++ if (do_pause){
|
|
|
++ self->task_pause_count ++;
|
|
|
++ GST_DEBUG_OBJECT(self, "task_pause_count: %d'", self->task_pause_count);
|
|
|
++ } else {
|
|
|
++ self->task_pause_count = 0;
|
|
|
++ GST_DEBUG_OBJECT(self, "reset task_pause_count ");
|
|
|
++ }
|
|
|
++
|
|
|
++ if ( self->task_pause_count > TASK_PAUSE_COUNT_MAX)
|
|
|
++ {
|
|
|
++ GST_DEBUG_OBJECT(self, "gst_task_pause");
|
|
|
+ gst_task_pause(self->task);
|
|
|
++ }
|
|
|
++
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+diff --git a/src/libcamera/pipeline/starfive/meson.build b/src/libcamera/pipeline/starfive/meson.build
|
|
|
+new file mode 100644
|
|
|
+index 00000000..2f2d2a75
|
|
|
+--- /dev/null
|
|
|
++++ b/src/libcamera/pipeline/starfive/meson.build
|
|
|
+@@ -0,0 +1,5 @@
|
|
|
++# SPDX-License-Identifier: CC0-1.0
|
|
|
++
|
|
|
++libcamera_sources += files([
|
|
|
++ 'starfive.cpp',
|
|
|
++])
|
|
|
+diff --git a/src/libcamera/pipeline/starfive/starfive.cpp b/src/libcamera/pipeline/starfive/starfive.cpp
|
|
|
+new file mode 100644
|
|
|
+index 00000000..3517679d
|
|
|
+--- /dev/null
|
|
|
++++ b/src/libcamera/pipeline/starfive/starfive.cpp
|
|
|
+@@ -0,0 +1,940 @@
|
|
|
++/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
|
++/*
|
|
|
++ * starfive.cpp - Pipeline handler for starfive devices
|
|
|
++ */
|
|
|
++#include <algorithm>
|
|
|
++#include <assert.h>
|
|
|
++#include <fcntl.h>
|
|
|
++#include <mutex>
|
|
|
++#include <queue>
|
|
|
++#include <sys/mman.h>
|
|
|
++#include <math.h>
|
|
|
++
|
|
|
++#include <libcamera/camera.h>
|
|
|
++#include <libcamera/control_ids.h>
|
|
|
++#include <libcamera/file_descriptor.h>
|
|
|
++#include <libcamera/formats.h>
|
|
|
++#include <libcamera/logging.h>
|
|
|
++#include <libcamera/property_ids.h>
|
|
|
++#include <libcamera/request.h>
|
|
|
++#include <libcamera/stream.h>
|
|
|
++#include <linux/media-bus-format.h>
|
|
|
++
|
|
|
++#include <linux/videodev2.h>
|
|
|
++#include <linux/v4l2-subdev.h>
|
|
|
++
|
|
|
++#include "libcamera/internal/camera.h"
|
|
|
++#include "libcamera/internal/camera_sensor.h"
|
|
|
++#include "libcamera/internal/device_enumerator.h"
|
|
|
++#include "libcamera/internal/ipa_manager.h"
|
|
|
++#include "libcamera/internal/media_device.h"
|
|
|
++#include "libcamera/internal/pipeline_handler.h"
|
|
|
++// #include "libcamera/internal/utils.h"
|
|
|
++// #include "libcamera/internal/v4l2_controls.h"
|
|
|
++#include "libcamera/internal/v4l2_videodevice.h"
|
|
|
++
|
|
|
++#define STF_MAX_CAMERAS 3
|
|
|
++
|
|
|
++namespace libcamera {
|
|
|
++
|
|
|
++LOG_DEFINE_CATEGORY(STARFIVE)
|
|
|
++
|
|
|
++static constexpr unsigned int BUFFER_COUNT = 4;
|
|
|
++static constexpr unsigned int MAX_STREAMS = 2;
|
|
|
++static const Size OUTPUT_MIN_SIZE = { 8, 8 };
|
|
|
++static const Size OUTPUT_MAX_SIZE = { 8192, 8192 };
|
|
|
++
|
|
|
++namespace {
|
|
|
++
|
|
|
++typedef enum {
|
|
|
++ DVP_YUV = 0,
|
|
|
++ MIPICSI0_YUV,
|
|
|
++ MIPICSI1_YUV,
|
|
|
++ DVP_ISP0, // ISP0
|
|
|
++ MIPICSI0_ISP0,
|
|
|
++ MIPICSI1_ISP0,
|
|
|
++ DVP_ISP1, // ISP1
|
|
|
++ MIPICSI0_ISP1,
|
|
|
++ MIPICSI1_ISP1,
|
|
|
++ SENSORTYPE_MAX
|
|
|
++} SensorType;
|
|
|
++
|
|
|
++typedef struct {
|
|
|
++ std::string sensorEntityName_;
|
|
|
++ std::string sensorFwImageName_;
|
|
|
++ SensorType sensorType_;
|
|
|
++} SensorConfig;
|
|
|
++
|
|
|
++const std::vector<SensorConfig> sensorConfigs = {
|
|
|
++ { "imx219 0-0010", "stf_isp0_fw_dump.bin", MIPICSI0_ISP0 },
|
|
|
++ { "imx219 2-0010", "stf_isp0_fw_dump.bin", MIPICSI1_ISP1 },
|
|
|
++};
|
|
|
++
|
|
|
++typedef struct {
|
|
|
++ std::string source;
|
|
|
++ std::string link;
|
|
|
++} PipelineConfigLink;
|
|
|
++
|
|
|
++const std::vector<PipelineConfigLink> dvpyuvConfig = {
|
|
|
++ {"stf_dvp0", "stf_vin0_wr"},
|
|
|
++};
|
|
|
++
|
|
|
++const std::vector<PipelineConfigLink> mipicsi0yuvConfig = {
|
|
|
++ {"stf_csiphy0", "stf_csi0"},
|
|
|
++ {"stf_csi0", "stf_vin0_wr"}
|
|
|
++};
|
|
|
++
|
|
|
++const std::vector<PipelineConfigLink> mipicsi1yuvConfig = {
|
|
|
++ {"stf_csiphy1", "stf_csi1"},
|
|
|
++ {"stf_csi1", "stf_vin0_wr"}
|
|
|
++};
|
|
|
++
|
|
|
++const std::vector<PipelineConfigLink> dvpraw0Config = {
|
|
|
++ {"stf_dvp0", "stf_isp0"},
|
|
|
++ {"stf_isp0", "stf_vin0_isp0"}
|
|
|
++};
|
|
|
++
|
|
|
++const std::vector<PipelineConfigLink> mipicsi0raw0Config = {
|
|
|
++ {"stf_csiphy0", "stf_csi0"},
|
|
|
++ {"stf_csi0", "stf_isp0"},
|
|
|
++ {"stf_isp0", "stf_vin0_isp0"}
|
|
|
++};
|
|
|
++
|
|
|
++const std::vector<PipelineConfigLink> mipicsi1raw0Config = {
|
|
|
++ {"stf_csiphy1", "stf_csi1"},
|
|
|
++ {"stf_csi1", "stf_isp0"},
|
|
|
++ {"stf_isp0", "stf_vin0_isp0"}
|
|
|
++};
|
|
|
++
|
|
|
++const std::vector<PipelineConfigLink> dvpraw1Config = {
|
|
|
++ {"stf_dvp0", "stf_isp1"},
|
|
|
++ {"stf_isp1", "stf_vin0_isp1"}
|
|
|
++};
|
|
|
++
|
|
|
++const std::vector<PipelineConfigLink> mipicsi0raw1Config = {
|
|
|
++ {"stf_csiphy0", "stf_csi0"},
|
|
|
++ {"stf_csi0", "stf_isp1"},
|
|
|
++ {"stf_isp1", "stf_vin0_isp1"}
|
|
|
++};
|
|
|
++
|
|
|
++const std::vector<PipelineConfigLink> mipicsi1raw1Config = {
|
|
|
++ {"stf_csiphy1", "stf_csi1"},
|
|
|
++ {"stf_csi1", "stf_isp1"},
|
|
|
++ {"stf_isp1", "stf_vin0_isp1"}
|
|
|
++};
|
|
|
++
|
|
|
++const std::vector<PipelineConfigLink> pipelineConfigs[SENSORTYPE_MAX] = {
|
|
|
++ dvpyuvConfig,
|
|
|
++ mipicsi0yuvConfig,
|
|
|
++ mipicsi1yuvConfig,
|
|
|
++ dvpraw0Config,
|
|
|
++ mipicsi0raw0Config,
|
|
|
++ mipicsi1raw0Config,
|
|
|
++ dvpraw1Config,
|
|
|
++ mipicsi0raw1Config,
|
|
|
++ mipicsi1raw1Config,
|
|
|
++};
|
|
|
++
|
|
|
++const std::map<uint32_t, PixelFormat> mbusCodesToPixelFormat = {
|
|
|
++ { MEDIA_BUS_FMT_SBGGR10_1X10, formats::SBGGR12 },
|
|
|
++ { MEDIA_BUS_FMT_SGBRG10_1X10, formats::SGBRG12 },
|
|
|
++ { MEDIA_BUS_FMT_SGRBG10_1X10, formats::SGRBG12 },
|
|
|
++ { MEDIA_BUS_FMT_SRGGB10_1X10, formats::SRGGB12 },
|
|
|
++};
|
|
|
++
|
|
|
++} /* namespace */
|
|
|
++
|
|
|
++class StarFiveCameraData : public Camera::Private
|
|
|
++{
|
|
|
++public:
|
|
|
++ StarFiveCameraData(PipelineHandler *pipe, MediaDevice *media,
|
|
|
++ std::string entityName,
|
|
|
++ std::string sensorEntityName)
|
|
|
++ : Camera::Private(pipe), media_(media)
|
|
|
++ {
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++ sensorEntityName_ = sensorEntityName;
|
|
|
++ videoEntityName_ = entityName;
|
|
|
++ if ( videoEntityName_ == "stf_vin0_isp0_video1")
|
|
|
++ ispEntityName_ = "stf_isp0";
|
|
|
++ else if (videoEntityName_ == "stf_vin0_isp1_video2")
|
|
|
++ ispEntityName_ = "stf_isp1";
|
|
|
++ else
|
|
|
++ ispEntityName_ = "unknow";
|
|
|
++
|
|
|
++ video_ = nullptr;
|
|
|
++ raw_ = nullptr;
|
|
|
++ sensor_ = nullptr;
|
|
|
++ ispSubDev_ = nullptr;
|
|
|
++ haveRaw_ = false;
|
|
|
++ rawActive_= false;
|
|
|
++ }
|
|
|
++
|
|
|
++ ~StarFiveCameraData()
|
|
|
++ {
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++ delete sensor_;
|
|
|
++ delete video_;
|
|
|
++ if (raw_ != nullptr)
|
|
|
++ delete raw_;
|
|
|
++ if (ispSubDev_ != nullptr)
|
|
|
++ delete ispSubDev_;
|
|
|
++ }
|
|
|
++
|
|
|
++ int init();
|
|
|
++ void bufferReady(FrameBuffer *buffer);
|
|
|
++ bool haveRaw() const { return haveRaw_; }
|
|
|
++ bool rawActive() const { return rawActive_; }
|
|
|
++ void setRawActive(bool val) { rawActive_ = val; }
|
|
|
++ std::vector<SizeRange> sensorSizes() const;
|
|
|
++ std::vector<PixelFormat> sensorFormats() const;
|
|
|
++ std::vector<PixelFormat> videoFormats() const;
|
|
|
++
|
|
|
++ MediaDevice *media_;
|
|
|
++ V4L2VideoDevice *video_;
|
|
|
++ V4L2VideoDevice *raw_;
|
|
|
++ V4L2Subdevice *ispSubDev_;
|
|
|
++ CameraSensor *sensor_;
|
|
|
++ Stream outStream_;
|
|
|
++ Stream rawStream_;
|
|
|
++
|
|
|
++private:
|
|
|
++ bool haveRaw_;
|
|
|
++ bool rawActive_;
|
|
|
++ std::string videoEntityName_;
|
|
|
++ std::string sensorEntityName_;
|
|
|
++ std::string ispEntityName_;
|
|
|
++ std::string getRawVideoEntityName()
|
|
|
++ {
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++ if ( videoEntityName_ == "stf_vin0_isp0_video1")
|
|
|
++ return "stf_vin0_isp0_raw_video3";
|
|
|
++ else if (videoEntityName_ == "stf_vin0_isp1_video2")
|
|
|
++ return "stf_vin0_isp1_raw_video4";
|
|
|
++ else
|
|
|
++ return "unknow";
|
|
|
++ }
|
|
|
++ int ispLoadFW(const char *filename);
|
|
|
++};
|
|
|
++
|
|
|
++std::vector<PixelFormat> StarFiveCameraData::videoFormats() const
|
|
|
++{
|
|
|
++ if (!video_)
|
|
|
++ return {};
|
|
|
++
|
|
|
++ std::vector<PixelFormat> formats;
|
|
|
++ for (auto it : video_->formats()) {
|
|
|
++ formats.push_back(it.first.toPixelFormat());
|
|
|
++ }
|
|
|
++
|
|
|
++ return formats;
|
|
|
++}
|
|
|
++
|
|
|
++std::vector<PixelFormat> StarFiveCameraData::sensorFormats() const
|
|
|
++{
|
|
|
++ if (!sensor_)
|
|
|
++ return {};
|
|
|
++
|
|
|
++ std::vector<PixelFormat> formats;
|
|
|
++ for (unsigned int code : sensor_->mbusCodes()) {
|
|
|
++ auto it = mbusCodesToPixelFormat.find(code);
|
|
|
++ if (it != mbusCodesToPixelFormat.end())
|
|
|
++ formats.push_back(it->second);
|
|
|
++ }
|
|
|
++
|
|
|
++ return formats;
|
|
|
++}
|
|
|
++
|
|
|
++std::vector<SizeRange> StarFiveCameraData::sensorSizes() const
|
|
|
++{
|
|
|
++ if (!sensor_)
|
|
|
++ return {};
|
|
|
++
|
|
|
++ std::vector<SizeRange> sizes;
|
|
|
++ for (const Size &size : sensor_->sizes(sensor_->mbusCodes().at(0)))
|
|
|
++ sizes.emplace_back(size, size);
|
|
|
++
|
|
|
++ return sizes;
|
|
|
++}
|
|
|
++
|
|
|
++int StarFiveCameraData::ispLoadFW(const char *filename)
|
|
|
++{
|
|
|
++ struct stfisp_fw_info fw_info = {0};
|
|
|
++
|
|
|
++ if (!ispSubDev_)
|
|
|
++ return -ENODEV;
|
|
|
++
|
|
|
++ if (filename && (strlen(filename) < STF_ISPFW_FILENAME_MAX_LEN))
|
|
|
++ memcpy(fw_info.filename, filename, strlen(filename) + 1);
|
|
|
++ else
|
|
|
++ return -EINVAL;
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug)
|
|
|
++ << "VIDIOC_STFISP_LOAD_FW: " << VIDIOC_STFISP_LOAD_FW
|
|
|
++ << " filename: " << filename
|
|
|
++ << " struct size: " << sizeof(struct stfisp_fw_info);
|
|
|
++
|
|
|
++ if (ispSubDev_->ioctlPrivate(VIDIOC_STFISP_LOAD_FW, &fw_info) < 0)
|
|
|
++ LOG(STARFIVE, Error) << "Load ISP fw failed" ;
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++class StarFiveCameraConfiguration : public CameraConfiguration
|
|
|
++{
|
|
|
++public:
|
|
|
++ StarFiveCameraConfiguration(StarFiveCameraData *data);
|
|
|
++
|
|
|
++ Status validate() override;
|
|
|
++
|
|
|
++private:
|
|
|
++ StarFiveCameraData *data_;
|
|
|
++};
|
|
|
++
|
|
|
++int StarFiveCameraData::init()
|
|
|
++{
|
|
|
++ int ret;
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++ if (sensorEntityName_ != "unknow") {
|
|
|
++ sensor_ =
|
|
|
++ new CameraSensor(media_->getEntityByName(sensorEntityName_));
|
|
|
++ ret = sensor_->init();
|
|
|
++ if (ret)
|
|
|
++ return ret;
|
|
|
++ LOG(STARFIVE, Debug) << "sensor id: " << sensor_->id();
|
|
|
++ } else {
|
|
|
++ LOG(STARFIVE, Debug) << " Can't find sensorEntityName!";
|
|
|
++ return -ENODEV;
|
|
|
++ }
|
|
|
++
|
|
|
++ if (ispEntityName_ != "unknow") {
|
|
|
++ ispSubDev_ =
|
|
|
++ new V4L2Subdevice(media_->getEntityByName(ispEntityName_));
|
|
|
++ LOG(STARFIVE, Debug) << "ispEntityName: " << ispEntityName_;
|
|
|
++ if (ispSubDev_->open())
|
|
|
++ return -ENODEV;
|
|
|
++
|
|
|
++ for (SensorConfig it : sensorConfigs) {
|
|
|
++ if (it.sensorEntityName_ == sensorEntityName_) {
|
|
|
++ ispLoadFW(it.sensorFwImageName_.c_str());
|
|
|
++ break;
|
|
|
++ }
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ video_ = new V4L2VideoDevice(media_->getEntityByName(videoEntityName_));
|
|
|
++ LOG(STARFIVE, Debug) << "videoEntityName: " << videoEntityName_;
|
|
|
++ if (video_->open())
|
|
|
++ return -ENODEV;
|
|
|
++
|
|
|
++ video_->bufferReady.connect(this, &StarFiveCameraData::bufferReady);
|
|
|
++ LOG(STARFIVE, Debug) << "driverName: " << video_->driverName();
|
|
|
++
|
|
|
++ std::string rawVideoEntityName = getRawVideoEntityName();
|
|
|
++ if (rawVideoEntityName != "unknow") {
|
|
|
++ raw_ =
|
|
|
++ new V4L2VideoDevice(media_->getEntityByName(rawVideoEntityName));
|
|
|
++ LOG(STARFIVE, Debug)
|
|
|
++ << "rawEntityName: " << rawVideoEntityName;
|
|
|
++ if (raw_->open()) {
|
|
|
++ LOG(STARFIVE, Debug) << "No raw data capture!!!";
|
|
|
++ haveRaw_ = false;
|
|
|
++ } else {
|
|
|
++ haveRaw_ = true;
|
|
|
++ raw_->bufferReady.connect(this,
|
|
|
++ &StarFiveCameraData::bufferReady);
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++class PipelineHandlerStarFive : public PipelineHandler
|
|
|
++{
|
|
|
++public:
|
|
|
++ PipelineHandlerStarFive(CameraManager *manager);
|
|
|
++
|
|
|
++ CameraConfiguration *generateConfiguration(Camera *camera,
|
|
|
++ const StreamRoles &roles) override;
|
|
|
++ int configure(Camera *camera, CameraConfiguration *config) override;
|
|
|
++
|
|
|
++ int exportFrameBuffers(Camera *camera, Stream *stream,
|
|
|
++ std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
|
|
|
++
|
|
|
++ int start(Camera *camera, const ControlList *controls) override;
|
|
|
++ void stop(Camera *camera) override;
|
|
|
++
|
|
|
++ int queueRequestDevice(Camera *camera, Request *request) override;
|
|
|
++
|
|
|
++ bool match(DeviceEnumerator *enumerator) override;
|
|
|
++
|
|
|
++private:
|
|
|
++ int processControls(StarFiveCameraData *data, Request *request);
|
|
|
++
|
|
|
++ StarFiveCameraData *cameraData(Camera *camera)
|
|
|
++ {
|
|
|
++ return static_cast<StarFiveCameraData *>(camera->_d());
|
|
|
++ }
|
|
|
++
|
|
|
++ int registerCameras();
|
|
|
++ std::string getVideoEntityNameById(unsigned int id);
|
|
|
++ std::string findSensorEntityName(std::string entityName);
|
|
|
++ int enableLinks(std::vector<PipelineConfigLink> config);
|
|
|
++
|
|
|
++ MediaDevice *starFiveMediaDev_;
|
|
|
++};
|
|
|
++
|
|
|
++StarFiveCameraConfiguration::StarFiveCameraConfiguration(StarFiveCameraData *data)
|
|
|
++ : CameraConfiguration(), data_(data)
|
|
|
++{
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++}
|
|
|
++
|
|
|
++CameraConfiguration::Status StarFiveCameraConfiguration::validate()
|
|
|
++{
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++ Status status = Valid;
|
|
|
++
|
|
|
++ if (config_.empty())
|
|
|
++ return Invalid;
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug) << "config_.size " << config_.size();
|
|
|
++ /* Cap the number of entries to the available streams. */
|
|
|
++ if (config_.size() > MAX_STREAMS) {
|
|
|
++ config_.resize(MAX_STREAMS);
|
|
|
++ status = Adjusted;
|
|
|
++ }
|
|
|
++
|
|
|
++ for (unsigned int i = 0; i < config_.size(); ++i) {
|
|
|
++ const PixelFormatInfo &info =
|
|
|
++ PixelFormatInfo::info(config_[i].pixelFormat);
|
|
|
++ StreamConfiguration &cfg = config_[i];
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug)
|
|
|
++ << "Validating stream: " << config_[i].toString();
|
|
|
++
|
|
|
++ const Size size = cfg.size;
|
|
|
++
|
|
|
++ cfg.size.width = std::max(OUTPUT_MIN_SIZE.width,
|
|
|
++ std::min(OUTPUT_MAX_SIZE.width, cfg.size.width));
|
|
|
++ cfg.size.height = std::max(OUTPUT_MIN_SIZE.height,
|
|
|
++ std::min(OUTPUT_MAX_SIZE.height, cfg.size.height));
|
|
|
++
|
|
|
++ if (cfg.size != size) {
|
|
|
++ LOG(STARFIVE, Debug)
|
|
|
++ << "Adjusting size to " << cfg.size.toString();
|
|
|
++ status = Adjusted;
|
|
|
++ }
|
|
|
++
|
|
|
++ cfg.bufferCount = BUFFER_COUNT;
|
|
|
++
|
|
|
++ if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW
|
|
|
++ && data_->haveRaw()) {
|
|
|
++ V4L2DeviceFormat format = {};
|
|
|
++ format.fourcc =
|
|
|
++ data_->raw_->toV4L2PixelFormat(cfg.pixelFormat);
|
|
|
++ format.size = cfg.size;
|
|
|
++
|
|
|
++ int ret = data_->raw_->tryFormat(&format);
|
|
|
++ if (ret)
|
|
|
++ return Invalid;
|
|
|
++
|
|
|
++ cfg.stride = format.planes[0].bpl;
|
|
|
++ cfg.frameSize = format.planes[0].size;
|
|
|
++
|
|
|
++ cfg.setStream(&data_->rawStream_);
|
|
|
++ } else {
|
|
|
++ V4L2DeviceFormat format = {};
|
|
|
++ format.fourcc =
|
|
|
++ data_->video_->toV4L2PixelFormat(cfg.pixelFormat);
|
|
|
++ format.size = cfg.size;
|
|
|
++
|
|
|
++ int ret = data_->video_->tryFormat(&format);
|
|
|
++ if (ret)
|
|
|
++ return Invalid;
|
|
|
++
|
|
|
++ cfg.stride = format.planes[0].bpl;
|
|
|
++ cfg.frameSize = format.planes[0].size;
|
|
|
++
|
|
|
++ cfg.setStream(&data_->outStream_);
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ return status;
|
|
|
++}
|
|
|
++
|
|
|
++PipelineHandlerStarFive::PipelineHandlerStarFive(CameraManager *manager)
|
|
|
++ : PipelineHandler(manager)
|
|
|
++{
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++}
|
|
|
++
|
|
|
++CameraConfiguration *
|
|
|
++PipelineHandlerStarFive::generateConfiguration(Camera *camera,
|
|
|
++ const StreamRoles &roles)
|
|
|
++{
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++ StarFiveCameraData *data = cameraData(camera);
|
|
|
++ StarFiveCameraConfiguration *config =
|
|
|
++ new StarFiveCameraConfiguration(data);
|
|
|
++
|
|
|
++ if (roles.empty())
|
|
|
++ return config;
|
|
|
++
|
|
|
++ for (const StreamRole role : roles) {
|
|
|
++ std::map<PixelFormat, std::vector<SizeRange>> streamFormats;
|
|
|
++ unsigned int bufferCount;
|
|
|
++ PixelFormat pixelFormat;
|
|
|
++ Size size;
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug) << "role: " << role;
|
|
|
++ size = data->sensor_->resolution();
|
|
|
++ switch (role) {
|
|
|
++ case StreamRole::StillCapture:
|
|
|
++ case StreamRole::Viewfinder:
|
|
|
++ case StreamRole::VideoRecording:
|
|
|
++ for (const auto &pixelformat : data->videoFormats()) {
|
|
|
++ streamFormats[pixelformat] = data->sensorSizes();
|
|
|
++ }
|
|
|
++ pixelFormat = data->videoFormats().at(0);
|
|
|
++ bufferCount = BUFFER_COUNT;
|
|
|
++
|
|
|
++ break;
|
|
|
++
|
|
|
++ case StreamRole::Raw: {
|
|
|
++ std::vector<unsigned int> mbusCodes =
|
|
|
++ utils::map_keys(mbusCodesToPixelFormat);
|
|
|
++
|
|
|
++ V4L2SubdeviceFormat sensorFormat =
|
|
|
++ data->sensor_->getFormat(mbusCodes, size);
|
|
|
++ if (!sensorFormat.mbus_code) {
|
|
|
++ LOG(STARFIVE, Error)
|
|
|
++ << "Sensor does not support mbus code";
|
|
|
++ break;
|
|
|
++ }
|
|
|
++
|
|
|
++ pixelFormat =
|
|
|
++ mbusCodesToPixelFormat.at(sensorFormat.mbus_code);
|
|
|
++ size = sensorFormat.size;
|
|
|
++ bufferCount = BUFFER_COUNT;
|
|
|
++
|
|
|
++ streamFormats[pixelFormat] = data->sensorSizes();
|
|
|
++
|
|
|
++ break;
|
|
|
++ }
|
|
|
++ default:
|
|
|
++ LOG(STARFIVE, Error)
|
|
|
++ << "Requested stream role not supported: "
|
|
|
++ << role;
|
|
|
++ break;
|
|
|
++ }
|
|
|
++
|
|
|
++ StreamFormats formats(streamFormats);
|
|
|
++ StreamConfiguration cfg(formats);
|
|
|
++ cfg.size = size;
|
|
|
++ cfg.pixelFormat = pixelFormat;
|
|
|
++ cfg.bufferCount = bufferCount;
|
|
|
++ config->addConfiguration(cfg);
|
|
|
++ }
|
|
|
++
|
|
|
++ if (config->validate() == CameraConfiguration::Invalid)
|
|
|
++ return {};
|
|
|
++
|
|
|
++ return config;
|
|
|
++}
|
|
|
++
|
|
|
++int PipelineHandlerStarFive::configure(Camera *camera, CameraConfiguration *c)
|
|
|
++{
|
|
|
++ StarFiveCameraConfiguration *config =
|
|
|
++ static_cast<StarFiveCameraConfiguration *>(c);
|
|
|
++ StarFiveCameraData *data = cameraData(camera);
|
|
|
++ int ret;
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug) << __func__
|
|
|
++ << " config->size: " << config->size();
|
|
|
++
|
|
|
++ for (unsigned int i = 0; i < config->size(); ++i) {
|
|
|
++ StreamConfiguration &cfg = (*config)[i];
|
|
|
++ Stream *stream = cfg.stream();
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug)
|
|
|
++ << "config stream: " << cfg.toString();
|
|
|
++
|
|
|
++ if (stream == &data->rawStream_) {
|
|
|
++ V4L2DeviceFormat format = {};
|
|
|
++ format.fourcc =
|
|
|
++ data->raw_->toV4L2PixelFormat(cfg.pixelFormat);
|
|
|
++ format.size = cfg.size;
|
|
|
++
|
|
|
++ ret = data->raw_->setFormat(&format);
|
|
|
++ if (ret)
|
|
|
++ return ret;
|
|
|
++
|
|
|
++ if (format.size != cfg.size ||
|
|
|
++ format.fourcc !=
|
|
|
++ data->raw_->toV4L2PixelFormat(cfg.pixelFormat))
|
|
|
++ return -EINVAL;
|
|
|
++
|
|
|
++ } else if (stream == &data->outStream_) {
|
|
|
++ V4L2DeviceFormat format = {};
|
|
|
++ format.fourcc =
|
|
|
++ data->video_->toV4L2PixelFormat(cfg.pixelFormat);
|
|
|
++ format.size = cfg.size;
|
|
|
++
|
|
|
++ ret = data->video_->setFormat(&format);
|
|
|
++ if (ret)
|
|
|
++ return ret;
|
|
|
++
|
|
|
++ if (format.size != cfg.size ||
|
|
|
++ format.fourcc !=
|
|
|
++ data->video_->toV4L2PixelFormat(cfg.pixelFormat))
|
|
|
++ return -EINVAL;
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++int PipelineHandlerStarFive::exportFrameBuffers(Camera *camera, Stream *stream,
|
|
|
++ std::vector<std::unique_ptr<FrameBuffer>> *buffers)
|
|
|
++{
|
|
|
++ StarFiveCameraData *data = cameraData(camera);
|
|
|
++ unsigned int count = stream->configuration().bufferCount;
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug) << __func__ << " bufferCount: " << count;
|
|
|
++
|
|
|
++ if (stream == &data->outStream_)
|
|
|
++ return data->video_->exportBuffers(count, buffers);
|
|
|
++ else if (stream == &data->rawStream_)
|
|
|
++ return data->raw_->exportBuffers(count, buffers);
|
|
|
++
|
|
|
++ return -EINVAL;
|
|
|
++}
|
|
|
++
|
|
|
++int PipelineHandlerStarFive::start(Camera *camera, const ControlList *controls)
|
|
|
++{
|
|
|
++ StarFiveCameraData *data = cameraData(camera);
|
|
|
++ unsigned int count = data->outStream_.configuration().bufferCount;
|
|
|
++ int ret = -EINVAL;
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug) << __func__ << " bufferCount: " << count;
|
|
|
++
|
|
|
++ ret = data->video_->importBuffers(count);
|
|
|
++ if (ret < 0)
|
|
|
++ return ret;
|
|
|
++
|
|
|
++ ret = data->video_->streamOn();
|
|
|
++ if (ret < 0)
|
|
|
++ goto error;
|
|
|
++
|
|
|
++ if (data->haveRaw()) {
|
|
|
++ count = data->rawStream_.configuration().bufferCount;
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug) << "rawbufferCount: " << count;
|
|
|
++ if (count) {
|
|
|
++ ret = data->raw_->importBuffers(count);
|
|
|
++ if (ret < 0) {
|
|
|
++ data->setRawActive(false);
|
|
|
++ LOG(STARFIVE, Debug)
|
|
|
++ << "raw video importBuffers failed!";
|
|
|
++ goto error;
|
|
|
++ }
|
|
|
++ ret = data->raw_->streamOn();
|
|
|
++ if (ret < 0) {
|
|
|
++ data->setRawActive(false);
|
|
|
++ data->raw_->releaseBuffers();
|
|
|
++ LOG(STARFIVE, Debug)
|
|
|
++ << "raw video streamOn failed!";
|
|
|
++ goto error;
|
|
|
++ }
|
|
|
++ data->setRawActive(true);
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ return ret;
|
|
|
++error:
|
|
|
++ data->video_->releaseBuffers();
|
|
|
++ return ret;
|
|
|
++}
|
|
|
++
|
|
|
++void PipelineHandlerStarFive::stop(Camera *camera)
|
|
|
++{
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++
|
|
|
++ StarFiveCameraData *data = cameraData(camera);
|
|
|
++ data->video_->streamOff();
|
|
|
++ data->video_->releaseBuffers();
|
|
|
++ if (data->rawActive()) {
|
|
|
++ data->raw_->streamOff();
|
|
|
++ data->raw_->releaseBuffers();
|
|
|
++ data->setRawActive(false);
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
++int PipelineHandlerStarFive::processControls(StarFiveCameraData *data, Request *request)
|
|
|
++{
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++
|
|
|
++ ControlList controls(data->sensor_->controls());
|
|
|
++
|
|
|
++ for (auto it : request->controls()) {
|
|
|
++ unsigned int id = it.first;
|
|
|
++ unsigned int offset;
|
|
|
++ uint32_t cid;
|
|
|
++
|
|
|
++ if (id == controls::Brightness) {
|
|
|
++ cid = V4L2_CID_BRIGHTNESS;
|
|
|
++ offset = 128;
|
|
|
++ } else if (id == controls::Contrast) {
|
|
|
++ cid = V4L2_CID_CONTRAST;
|
|
|
++ offset = 0;
|
|
|
++ } else if (id == controls::Saturation) {
|
|
|
++ cid = V4L2_CID_SATURATION;
|
|
|
++ offset = 0;
|
|
|
++ } else {
|
|
|
++ continue;
|
|
|
++ }
|
|
|
++
|
|
|
++ int32_t value = lroundf(it.second.get<float>() * 128 + offset);
|
|
|
++ controls.set(cid, std::clamp(value, 0, 255));
|
|
|
++ }
|
|
|
++
|
|
|
++ for (const auto &ctrl : controls)
|
|
|
++ LOG(STARFIVE, Debug)
|
|
|
++ << "Setting control " << utils::hex(ctrl.first)
|
|
|
++ << " to " << ctrl.second.toString();
|
|
|
++
|
|
|
++ int ret = data->sensor_->setControls(&controls);
|
|
|
++ if (ret) {
|
|
|
++ LOG(STARFIVE, Debug)
|
|
|
++ << "Failed to set controls: " << ret;
|
|
|
++ return ret < 0 ? ret : -EINVAL;
|
|
|
++ }
|
|
|
++
|
|
|
++ return ret;
|
|
|
++}
|
|
|
++
|
|
|
++int PipelineHandlerStarFive::queueRequestDevice(Camera *camera, Request *request)
|
|
|
++{
|
|
|
++ StarFiveCameraData *data = cameraData(camera);
|
|
|
++ int error = 0;
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++ int ret = processControls(data, request);
|
|
|
++ if (ret < 0)
|
|
|
++ return ret;
|
|
|
++
|
|
|
++ for (auto it : request->buffers()) {
|
|
|
++ const Stream *stream = it.first;
|
|
|
++ FrameBuffer *buffer = it.second;
|
|
|
++ int ret;
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug)
|
|
|
++ << "stream queueBuffer : " << stream->configuration().toString();
|
|
|
++
|
|
|
++ if (stream == &data->outStream_)
|
|
|
++ ret = data->video_->queueBuffer(buffer);
|
|
|
++ else if (stream == &data->rawStream_)
|
|
|
++ ret = data->raw_->queueBuffer(buffer);
|
|
|
++ else
|
|
|
++ continue;
|
|
|
++
|
|
|
++ if (ret < 0)
|
|
|
++ error = ret;
|
|
|
++ }
|
|
|
++
|
|
|
++ return error;
|
|
|
++}
|
|
|
++
|
|
|
++std::string PipelineHandlerStarFive::getVideoEntityNameById(unsigned int id)
|
|
|
++{
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++ switch (id) {
|
|
|
++ case 0:
|
|
|
++ return "stf_vin0_wr_video0";
|
|
|
++ case 1:
|
|
|
++ return "stf_vin0_isp0_video1";
|
|
|
++ case 2:
|
|
|
++ return "stf_vin0_isp1_video2";
|
|
|
++ case 3:
|
|
|
++ return "stf_vin0_isp0_raw_video3";
|
|
|
++ case 4:
|
|
|
++ return "stf_vin0_isp1_raw_video4";
|
|
|
++ default:
|
|
|
++ return "unknow";
|
|
|
++ }
|
|
|
++
|
|
|
++ return "unknow";
|
|
|
++}
|
|
|
++
|
|
|
++std::string PipelineHandlerStarFive::findSensorEntityName(std::string entityName)
|
|
|
++{
|
|
|
++ std::string sensorEntityName;
|
|
|
++ bool found = false;
|
|
|
++ MediaEntity *sensorEntity = starFiveMediaDev_->getEntityByName(entityName);
|
|
|
++
|
|
|
++ while (1) {
|
|
|
++ LOG(STARFIVE, Debug) << "findSensorEntityName: " << sensorEntity->name();
|
|
|
++ const std::vector<MediaPad *> &pads = sensorEntity->pads();
|
|
|
++
|
|
|
++ if (pads.empty())
|
|
|
++ break;
|
|
|
++
|
|
|
++ MediaPad *sink = pads[0];
|
|
|
++ MediaLink *link;
|
|
|
++ bool found_enable_link = false;
|
|
|
++
|
|
|
++ for (MediaLink *it : sink->links()) {
|
|
|
++ if (it->flags() & MEDIA_LNK_FL_ENABLED) {
|
|
|
++ found_enable_link = true;
|
|
|
++ link = it;
|
|
|
++ break;
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ if (!found_enable_link)
|
|
|
++ break;
|
|
|
++
|
|
|
++ sensorEntity = link->source()->entity();
|
|
|
++ if (sensorEntity->function() == MEDIA_ENT_F_CAM_SENSOR) {
|
|
|
++ found = true;
|
|
|
++ break;
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ if (found)
|
|
|
++ sensorEntityName = sensorEntity->name();
|
|
|
++ else
|
|
|
++ sensorEntityName = "unknow";
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug) << "sensorEntityName: " << sensorEntityName;
|
|
|
++ return sensorEntityName;
|
|
|
++}
|
|
|
++
|
|
|
++int PipelineHandlerStarFive::registerCameras()
|
|
|
++{
|
|
|
++ unsigned int numCameras = 0;
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++ for (unsigned int id = 0;
|
|
|
++ id < STF_MAX_CAMERAS
|
|
|
++ && numCameras < STF_MAX_CAMERAS; ++id) {
|
|
|
++ std::string videoEntiryName;
|
|
|
++ videoEntiryName = getVideoEntityNameById(id);
|
|
|
++ if (videoEntiryName == "unknow")
|
|
|
++ continue;
|
|
|
++
|
|
|
++ std::string sensorEntityName;
|
|
|
++ sensorEntityName = findSensorEntityName(videoEntiryName);
|
|
|
++ if (sensorEntityName == "unknow")
|
|
|
++ continue;
|
|
|
++
|
|
|
++ std::unique_ptr<StarFiveCameraData> data =
|
|
|
++ std::make_unique<StarFiveCameraData>(this, starFiveMediaDev_,
|
|
|
++ videoEntiryName, sensorEntityName);
|
|
|
++
|
|
|
++ /* Locate and open the capture video node. */
|
|
|
++ if (data->init())
|
|
|
++ continue;
|
|
|
++
|
|
|
++ /* Create and register the camera. */
|
|
|
++ LOG(STARFIVE, Debug) << "register deviceName: "
|
|
|
++ << videoEntiryName;
|
|
|
++ if (data->haveRaw()) {
|
|
|
++ std::set<Stream *> streams{ &data->outStream_,
|
|
|
++ &data->rawStream_ };
|
|
|
++ std::shared_ptr<Camera> camera =
|
|
|
++ Camera::create(std::move(data), videoEntiryName, streams);
|
|
|
++ registerCamera(std::move(camera));
|
|
|
++ } else {
|
|
|
++ std::set<Stream *> streams{ &data->outStream_ };
|
|
|
++ std::shared_ptr<Camera> camera =
|
|
|
++ Camera::create(std::move(data), videoEntiryName, streams);
|
|
|
++ registerCamera(std::move(camera));
|
|
|
++ }
|
|
|
++ numCameras++;
|
|
|
++ }
|
|
|
++
|
|
|
++ return numCameras;
|
|
|
++}
|
|
|
++
|
|
|
++int PipelineHandlerStarFive::enableLinks(std::vector<PipelineConfigLink> config)
|
|
|
++{
|
|
|
++ int ret = 0;
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++ for (PipelineConfigLink it : config) {
|
|
|
++ MediaLink *link = starFiveMediaDev_->link(it.source, 1, it.link, 0);
|
|
|
++ if (!link)
|
|
|
++ return -ENODEV;
|
|
|
++
|
|
|
++ ret = link->setEnabled(true);
|
|
|
++ if (ret < 0)
|
|
|
++ return ret;
|
|
|
++ }
|
|
|
++
|
|
|
++ return ret;
|
|
|
++}
|
|
|
++
|
|
|
++bool PipelineHandlerStarFive::match(DeviceEnumerator *enumerator)
|
|
|
++{
|
|
|
++ int numCameras = 0;
|
|
|
++
|
|
|
++ DeviceMatch dm("stf-vin");
|
|
|
++ dm.add("stf_vin0_wr_video0");
|
|
|
++ dm.add("stf_vin0_isp0_video1");
|
|
|
++ dm.add("stf_vin0_isp1_video2");
|
|
|
++
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++ starFiveMediaDev_ = acquireMediaDevice(enumerator, dm);
|
|
|
++ if (!starFiveMediaDev_)
|
|
|
++ return false;
|
|
|
++
|
|
|
++ if (starFiveMediaDev_->disableLinks())
|
|
|
++ return false;
|
|
|
++
|
|
|
++ for (SensorConfig it : sensorConfigs) {
|
|
|
++ MediaEntity *sensorEntity =
|
|
|
++ starFiveMediaDev_->getEntityByName(it.sensorEntityName_);
|
|
|
++ int ret;
|
|
|
++
|
|
|
++ if (sensorEntity != nullptr) {
|
|
|
++ if (it.sensorType_ < DVP_YUV
|
|
|
++ || it.sensorType_ >= SENSORTYPE_MAX)
|
|
|
++ continue;
|
|
|
++ ret = enableLinks(pipelineConfigs[it.sensorType_]);
|
|
|
++ if (ret < 0) {
|
|
|
++ LOG(STARFIVE, Error)
|
|
|
++ << it.sensorEntityName_
|
|
|
++ << " enableLinks failed!";
|
|
|
++ continue;
|
|
|
++ }
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ numCameras = registerCameras();
|
|
|
++ if (numCameras)
|
|
|
++ LOG(STARFIVE, Debug)
|
|
|
++ << "StarFive " << numCameras
|
|
|
++ << " Device Identified";
|
|
|
++
|
|
|
++ return numCameras != 0;
|
|
|
++}
|
|
|
++
|
|
|
++void StarFiveCameraData::bufferReady(FrameBuffer *buffer)
|
|
|
++{
|
|
|
++ LOG(STARFIVE, Debug) << __func__;
|
|
|
++ PipelineHandlerStarFive *pipe =
|
|
|
++ static_cast<PipelineHandlerStarFive *>(this->pipe());
|
|
|
++ Request *request = buffer->request();
|
|
|
++
|
|
|
++ if (!pipe->completeBuffer(request, buffer))
|
|
|
++ return;
|
|
|
++
|
|
|
++ pipe->completeRequest(request);
|
|
|
++}
|
|
|
++
|
|
|
++REGISTER_PIPELINE_HANDLER(PipelineHandlerStarFive)
|
|
|
++
|
|
|
++} /* namespace libcamera */
|
|
|
+diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp
|
|
|
+index 8fe5e45b..0bdcf440 100644
|
|
|
+--- a/src/libcamera/v4l2_subdevice.cpp
|
|
|
++++ b/src/libcamera/v4l2_subdevice.cpp
|
|
|
+@@ -524,4 +524,16 @@ std::vector<SizeRange> V4L2Subdevice::enumPadSizes(unsigned int pad,
|
|
|
+ return sizes;
|
|
|
+ }
|
|
|
+
|
|
|
++int V4L2Subdevice::ioctlPrivate(unsigned long request, void *argp)
|
|
|
++{
|
|
|
++ /*
|
|
|
++ * Printing out an error message is usually better performed
|
|
|
++ * in the caller, which can provide more context.
|
|
|
++ */
|
|
|
++ if (V4L2Device::ioctl(request, argp) < 0)
|
|
|
++ return -errno;
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
+ } /* namespace libcamera */
|
|
|
+--
|
|
|
+2.17.1
|
|
|
+
|