[libcamera-devel,v2,2/4] libcamera: pipeline: vimc: Set media bus formats for sensor and debayer

Message ID 20190807204915.23942-3-niklas.soderlund@ragnatech.se
State Superseded
Headers show
Series
  • libcamera: Fix issues with vimc and Linux v5.2
Related show

Commit Message

Niklas Söderlund Aug. 7, 2019, 8:49 p.m. UTC
Linux commit 85ab1aa1fac17bcd ("media: vimc: deb: fix default sink bayer
format") which is part of v5.2 changes the default media bus format for
the debayer subdevices. This leads to a -EPIPE error when trying to use
the raw capture video device nodes.

Fix this by modifying the camera exposed by vimc to only support bayer
formarts. This allows the pipeline to function both before and after the
upstream change. As a consequence of this change the media bus format of
the subdevices involved needs to be set to avoid a misconfigured media
pipeline. Once upstream is sorted out none bayer formats should be
re-enabled on the vimc pipeline.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
---
 src/libcamera/pipeline/vimc.cpp | 54 ++++++++++++++++++++++++++++-----
 test/camera/buffer_import.cpp   |  6 ++--
 2 files changed, 49 insertions(+), 11 deletions(-)

Patch

diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp
index 3d6808222a8a2c5d..4dc514638da3746d 100644
--- a/src/libcamera/pipeline/vimc.cpp
+++ b/src/libcamera/pipeline/vimc.cpp
@@ -10,6 +10,8 @@ 
 #include <iomanip>
 #include <tuple>
 
+#include <linux/media-bus-format.h>
+
 #include <libcamera/camera.h>
 #include <libcamera/controls.h>
 #include <libcamera/ipa/ipa_interface.h>
@@ -25,6 +27,7 @@ 
 #include "pipeline_handler.h"
 #include "utils.h"
 #include "v4l2_controls.h"
+#include "v4l2_subdevice.h"
 #include "v4l2_videodevice.h"
 
 namespace libcamera {
@@ -35,13 +38,15 @@  class VimcCameraData : public CameraData
 {
 public:
 	VimcCameraData(PipelineHandler *pipe)
-		: CameraData(pipe), video_(nullptr), sensor_(nullptr)
+		: CameraData(pipe), video_(nullptr), debayer_(nullptr),
+		  sensor_(nullptr)
 	{
 	}
 
 	~VimcCameraData()
 	{
 		delete sensor_;
+		delete debayer_;
 		delete video_;
 	}
 
@@ -49,6 +54,7 @@  public:
 	void bufferReady(Buffer *buffer);
 
 	V4L2VideoDevice *video_;
+	V4L2Subdevice *debayer_;
 	CameraSensor *sensor_;
 	Stream stream_;
 };
@@ -101,10 +107,11 @@  VimcCameraConfiguration::VimcCameraConfiguration()
 
 CameraConfiguration::Status VimcCameraConfiguration::validate()
 {
-	static const std::array<unsigned int, 3> formats{
-		V4L2_PIX_FMT_BGR24,
-		V4L2_PIX_FMT_RGB24,
-		V4L2_PIX_FMT_ARGB32,
+	static const std::array<unsigned int, 4> formats{
+		V4L2_PIX_FMT_SBGGR8,
+		V4L2_PIX_FMT_SGBRG8,
+		V4L2_PIX_FMT_SGRBG8,
+		V4L2_PIX_FMT_SRGGB8,
 	};
 
 	Status status = Valid;
@@ -123,8 +130,8 @@  CameraConfiguration::Status VimcCameraConfiguration::validate()
 	/* Adjust the pixel format. */
 	if (std::find(formats.begin(), formats.end(), cfg.pixelFormat) ==
 	    formats.end()) {
-		LOG(VIMC, Debug) << "Adjusting format to RGB24";
-		cfg.pixelFormat = V4L2_PIX_FMT_RGB24;
+		LOG(VIMC, Debug) << "Adjusting format to SBGGR8";
+		cfg.pixelFormat = V4L2_PIX_FMT_SBGGR8;
 		status = Adjusted;
 	}
 
@@ -159,7 +166,7 @@  CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera,
 		return config;
 
 	StreamConfiguration cfg{};
-	cfg.pixelFormat = V4L2_PIX_FMT_RGB24;
+	cfg.pixelFormat = V4L2_PIX_FMT_SBGGR8;
 	cfg.size = { 640, 480 };
 	cfg.bufferCount = 4;
 
@@ -176,6 +183,33 @@  int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration *config)
 	StreamConfiguration &cfg = config->at(0);
 	int ret;
 
+	V4L2SubdeviceFormat subformat = {};
+	subformat.size = cfg.size;
+	switch (cfg.pixelFormat) {
+	case V4L2_PIX_FMT_SBGGR8:
+		subformat.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8;
+		break;
+	case V4L2_PIX_FMT_SGBRG8:
+		subformat.mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8;
+		break;
+	case V4L2_PIX_FMT_SGRBG8:
+		subformat.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8;
+		break;
+	case V4L2_PIX_FMT_SRGGB8:
+		subformat.mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = data->sensor_->setFormat(&subformat);
+	if (ret)
+		return ret;
+
+	ret = data->debayer_->setFormat(0, &subformat);
+	if (ret)
+		return ret;
+
 	V4L2DeviceFormat format = {};
 	format.fourcc = cfg.pixelFormat;
 	format.size = cfg.size;
@@ -340,6 +374,10 @@  int VimcCameraData::init(MediaDevice *media)
 	if (video_->open())
 		return -ENODEV;
 
+	debayer_ = new V4L2Subdevice(media->getEntityByName("Debayer B"));
+	if (debayer_->open())
+		return -ENODEV;
+
 	video_->bufferReady.connect(this, &VimcCameraData::bufferReady);
 
 	sensor_ = new CameraSensor(media->getEntityByName("Sensor B"));
diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp
index 400d02b350c1aa8f..2c29267f22d1ba27 100644
--- a/test/camera/buffer_import.cpp
+++ b/test/camera/buffer_import.cpp
@@ -74,10 +74,10 @@  public:
 
 		format_.size.width = 640;
 		format_.size.height = 480;
-		format_.fourcc = V4L2_PIX_FMT_RGB24;
+		format_.fourcc = V4L2_PIX_FMT_SBGGR8;
 		format_.planesCount = 1;
-		format_.planes[0].size = 640 * 480 * 3;
-		format_.planes[0].bpl = 640 * 3;
+		format_.planes[0].size = 640 * 480;
+		format_.planes[0].bpl = 640;
 
 		if (video_->setFormat(&format_)) {
 			cleanup();