about summary refs log tree commit diff
path: root/users/flokli/ipu6-softisp/libcamera
diff options
context:
space:
mode:
Diffstat (limited to 'users/flokli/ipu6-softisp/libcamera')
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0001-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch (renamed from users/flokli/ipu6-softisp/libcamera/0016-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch)108
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0001-libcamera-pipeline-simple-fix-size-adjustment-in-val.patch82
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0002-libcamera-internal-Move-dma_heaps.-h-cpp-to-common-d.patch350
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0002-ov01a1s-HACK.patch (renamed from users/flokli/ipu6-softisp/libcamera/0020-ov01a1s-HACK.patch)42
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0003-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch (renamed from users/flokli/ipu6-softisp/libcamera/0021-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch)26
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0003-libcamera-dma_heaps-extend-DmaHeap-class-to-support-.patch169
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0004-libcamera-internal-Move-SharedMemObject-class-to-a-c.patch69
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0005-libcamera-shared_mem_object-reorganize-the-code-and-.patch403
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0006-libcamera-software_isp-Add-SwStatsCpu-class.patch523
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0007-libcamera-software_isp-Add-Debayer-base-class.patch255
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0008-libcamera-software_isp-Add-DebayerCpu-class.patch825
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0009-libcamera-ipa-add-Soft-IPA.patch506
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0010-libcamera-introduce-SoftwareIsp.patch507
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0011-libcamera-pipeline-simple-rename-converterBuffers_-a.patch240
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch302
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0013-libcamera-swstats_cpu-Add-support-for-8-10-and-12-bp.patch203
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0014-libcamera-debayer_cpu-Add-support-for-8-10-and-12-bp.patch234
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0015-libcamera-debayer_cpu-Add-BGR888-output-support.patch127
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0017-libcamera-Add-Software-ISP-benchmarking-documentatio.patch132
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0018-libcamera-software_isp-Apply-black-level-compensatio.patch396
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0019-libcamera-Soft-IPA-use-CameraSensorHelper-for-analog.patch239
21 files changed, 90 insertions, 5648 deletions
diff --git a/users/flokli/ipu6-softisp/libcamera/0016-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch b/users/flokli/ipu6-softisp/libcamera/0001-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch
index 724b67033ff4..5340901edb94 100644
--- a/users/flokli/ipu6-softisp/libcamera/0016-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch
+++ b/users/flokli/ipu6-softisp/libcamera/0001-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch
@@ -1,7 +1,7 @@
-From e9580d30a1a79fce1ebd72ae74ceb4a3d1cf8fbb Mon Sep 17 00:00:00 2001
+From 0e94883c2f4f6164d40d4ea355449ba0864dc4f9 Mon Sep 17 00:00:00 2001
 From: Hans de Goede <hdegoede@redhat.com>
 Date: Tue, 19 Dec 2023 11:16:26 +0100
-Subject: [PATCH 16/21] libcamera: Add support for IGIG_GBGR_IGIG_GRGB bayer
+Subject: [PATCH 1/3] libcamera: Add support for IGIG_GBGR_IGIG_GRGB bayer
  order DNU
 
 The ov01a1s sensor has the following bayer pattern (4x4 tile repeating):
@@ -23,15 +23,15 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  include/linux/media-bus-format.h          |  4 +++-
  include/linux/videodev2.h                 |  3 +++
  src/libcamera/bayer_format.cpp            |  5 +++++
- src/libcamera/camera_sensor.cpp           |  3 +++
  src/libcamera/formats.cpp                 | 20 ++++++++++++++++++++
  src/libcamera/formats.yaml                |  5 +++++
+ src/libcamera/sensor/camera_sensor.cpp    |  3 +++
  src/libcamera/v4l2_pixelformat.cpp        |  4 ++++
- src/libcamera/v4l2_subdevice.cpp          |  1 +
- 10 files changed, 48 insertions(+), 2 deletions(-)
+ src/libcamera/v4l2_subdevice.cpp          |  7 +++++++
+ 10 files changed, 54 insertions(+), 2 deletions(-)
 
 diff --git a/include/libcamera/internal/bayer_format.h b/include/libcamera/internal/bayer_format.h
-index 78ba3969..e77106c3 100644
+index 5c14bb5f..49b7f417 100644
 --- a/include/libcamera/internal/bayer_format.h
 +++ b/include/libcamera/internal/bayer_format.h
 @@ -27,7 +27,8 @@ public:
@@ -45,10 +45,10 @@ index 78ba3969..e77106c3 100644
  
  	enum class Packing : uint16_t {
 diff --git a/include/linux/drm_fourcc.h b/include/linux/drm_fourcc.h
-index 1496e097..750ae8c9 100644
+index b4e1a092..070696bc 100644
 --- a/include/linux/drm_fourcc.h
 +++ b/include/linux/drm_fourcc.h
-@@ -405,6 +405,8 @@ extern "C" {
+@@ -447,6 +447,8 @@ extern "C" {
  #define DRM_FORMAT_SGRBG10	fourcc_code('B', 'A', '1', '0')
  #define DRM_FORMAT_SGBRG10	fourcc_code('G', 'B', '1', '0')
  #define DRM_FORMAT_SBGGR10	fourcc_code('B', 'G', '1', '0')
@@ -58,19 +58,19 @@ index 1496e097..750ae8c9 100644
  /* 12-bit Bayer formats */
  #define DRM_FORMAT_SRGGB12	fourcc_code('R', 'G', '1', '2')
 diff --git a/include/linux/media-bus-format.h b/include/linux/media-bus-format.h
-index 0dfc11ee..c5fbda0e 100644
+index f05f747e..1b4a65db 100644
 --- a/include/linux/media-bus-format.h
 +++ b/include/linux/media-bus-format.h
-@@ -112,7 +112,7 @@
+@@ -121,7 +121,7 @@
  #define MEDIA_BUS_FMT_YUV16_1X48		0x202a
  #define MEDIA_BUS_FMT_UYYVYY16_0_5X48		0x202b
  
 -/* Bayer - next is	0x3021 */
-+/* Bayer - next is 0x3022 */
++/* Bayer - next is	0x3022 */
  #define MEDIA_BUS_FMT_SBGGR8_1X8		0x3001
  #define MEDIA_BUS_FMT_SGBRG8_1X8		0x3013
  #define MEDIA_BUS_FMT_SGRBG8_1X8		0x3002
-@@ -145,6 +145,8 @@
+@@ -154,6 +154,8 @@
  #define MEDIA_BUS_FMT_SGBRG16_1X16		0x301e
  #define MEDIA_BUS_FMT_SGRBG16_1X16		0x301f
  #define MEDIA_BUS_FMT_SRGGB16_1X16		0x3020
@@ -80,10 +80,10 @@ index 0dfc11ee..c5fbda0e 100644
  /* JPEG compressed formats - next is	0x4002 */
  #define MEDIA_BUS_FMT_JPEG_1X8			0x4001
 diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
-index bfb315d6..13c6c9d3 100644
+index 0b5482a0..a51d6755 100644
 --- a/include/linux/videodev2.h
 +++ b/include/linux/videodev2.h
-@@ -678,6 +678,9 @@ struct v4l2_pix_format {
+@@ -704,6 +704,9 @@ struct v4l2_pix_format {
  #define V4L2_PIX_FMT_SGBRG16 v4l2_fourcc('G', 'B', '1', '6') /* 16  GBGB.. RGRG.. */
  #define V4L2_PIX_FMT_SGRBG16 v4l2_fourcc('G', 'R', '1', '6') /* 16  GRGR.. BGBG.. */
  #define V4L2_PIX_FMT_SRGGB16 v4l2_fourcc('R', 'G', '1', '6') /* 16  RGRG.. GBGB.. */
@@ -94,10 +94,10 @@ index bfb315d6..13c6c9d3 100644
  /* HSV formats */
  #define V4L2_PIX_FMT_HSV24 v4l2_fourcc('H', 'S', 'V', '3')
 diff --git a/src/libcamera/bayer_format.cpp b/src/libcamera/bayer_format.cpp
-index 3bf15fb4..ae227540 100644
+index 014f716d..325887a2 100644
 --- a/src/libcamera/bayer_format.cpp
 +++ b/src/libcamera/bayer_format.cpp
-@@ -108,6 +108,8 @@ const std::map<BayerFormat, Formats, BayerFormatComparator> bayerToFormat{
+@@ -112,6 +112,8 @@ const std::map<BayerFormat, Formats, BayerFormatComparator> bayerToFormat{
  		{ formats::SGRBG10, V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10) } },
  	{ { BayerFormat::RGGB, 10, BayerFormat::Packing::None },
  		{ formats::SRGGB10, V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10) } },
@@ -106,7 +106,7 @@ index 3bf15fb4..ae227540 100644
  	{ { BayerFormat::BGGR, 10, BayerFormat::Packing::CSI2 },
  		{ formats::SBGGR10_CSI2P, V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10P) } },
  	{ { BayerFormat::GBRG, 10, BayerFormat::Packing::CSI2 },
-@@ -116,6 +118,8 @@ const std::map<BayerFormat, Formats, BayerFormatComparator> bayerToFormat{
+@@ -120,6 +122,8 @@ const std::map<BayerFormat, Formats, BayerFormatComparator> bayerToFormat{
  		{ formats::SGRBG10_CSI2P, V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10P) } },
  	{ { BayerFormat::RGGB, 10, BayerFormat::Packing::CSI2 },
  		{ formats::SRGGB10_CSI2P, V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10P) } },
@@ -115,7 +115,7 @@ index 3bf15fb4..ae227540 100644
  	{ { BayerFormat::BGGR, 10, BayerFormat::Packing::IPU3 },
  		{ formats::SBGGR10_IPU3, V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SBGGR10) } },
  	{ { BayerFormat::GBRG, 10, BayerFormat::Packing::IPU3 },
-@@ -193,6 +197,7 @@ const std::unordered_map<unsigned int, BayerFormat> mbusCodeToBayer{
+@@ -211,6 +215,7 @@ const std::unordered_map<unsigned int, BayerFormat> mbusCodeToBayer{
  	{ MEDIA_BUS_FMT_SGBRG10_1X10, { BayerFormat::GBRG, 10, BayerFormat::Packing::None } },
  	{ MEDIA_BUS_FMT_SGRBG10_1X10, { BayerFormat::GRBG, 10, BayerFormat::Packing::None } },
  	{ MEDIA_BUS_FMT_SRGGB10_1X10, { BayerFormat::RGGB, 10, BayerFormat::Packing::None } },
@@ -123,25 +123,11 @@ index 3bf15fb4..ae227540 100644
  	{ MEDIA_BUS_FMT_SBGGR12_1X12, { BayerFormat::BGGR, 12, BayerFormat::Packing::None } },
  	{ MEDIA_BUS_FMT_SGBRG12_1X12, { BayerFormat::GBRG, 12, BayerFormat::Packing::None } },
  	{ MEDIA_BUS_FMT_SGRBG12_1X12, { BayerFormat::GRBG, 12, BayerFormat::Packing::None } },
-diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
-index 0ef78d9c..f19f72ea 100644
---- a/src/libcamera/camera_sensor.cpp
-+++ b/src/libcamera/camera_sensor.cpp
-@@ -510,6 +510,9 @@ int CameraSensor::initProperties()
- 		case BayerFormat::MONO:
- 			cfa = properties::draft::MONO;
- 			break;
-+		case BayerFormat::IGIG_GBGR_IGIG_GRGB:
-+			cfa = properties::draft::RGB;
-+			break;
- 		}
- 
- 		properties_.set(properties::draft::ColorFilterArrangement, cfa);
 diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp
-index 447e6238..aef7d598 100644
+index cf41f2c2..13ac3253 100644
 --- a/src/libcamera/formats.cpp
 +++ b/src/libcamera/formats.cpp
-@@ -599,6 +599,16 @@ const std::map<PixelFormat, PixelFormatInfo> pixelFormatInfo{
+@@ -639,6 +639,16 @@ const std::map<PixelFormat, PixelFormatInfo> pixelFormatInfo{
  		.pixelsPerGroup = 2,
  		.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
  	} },
@@ -158,7 +144,7 @@ index 447e6238..aef7d598 100644
  	{ formats::SBGGR10_CSI2P, {
  		.name = "SBGGR10_CSI2P",
  		.format = formats::SBGGR10_CSI2P,
-@@ -639,6 +649,16 @@ const std::map<PixelFormat, PixelFormatInfo> pixelFormatInfo{
+@@ -679,6 +689,16 @@ const std::map<PixelFormat, PixelFormatInfo> pixelFormatInfo{
  		.pixelsPerGroup = 4,
  		.planes = {{ { 5, 1 }, { 0, 0 }, { 0, 0 } }},
  	} },
@@ -176,10 +162,10 @@ index 447e6238..aef7d598 100644
  		.name = "SBGGR12",
  		.format = formats::SBGGR12,
 diff --git a/src/libcamera/formats.yaml b/src/libcamera/formats.yaml
-index 539ac0b3..0786a900 100644
+index fe027a7c..394f980c 100644
 --- a/src/libcamera/formats.yaml
 +++ b/src/libcamera/formats.yaml
-@@ -100,6 +100,8 @@ formats:
+@@ -107,6 +107,8 @@ formats:
        fourcc: DRM_FORMAT_SGBRG10
    - SBGGR10:
        fourcc: DRM_FORMAT_SBGGR10
@@ -188,7 +174,7 @@ index 539ac0b3..0786a900 100644
  
    - SRGGB12:
        fourcc: DRM_FORMAT_SRGGB12
-@@ -144,6 +146,9 @@ formats:
+@@ -151,6 +153,9 @@ formats:
    - SBGGR10_CSI2P:
        fourcc: DRM_FORMAT_SBGGR10
        mod: MIPI_FORMAT_MOD_CSI2_PACKED
@@ -198,11 +184,25 @@ index 539ac0b3..0786a900 100644
  
    - SRGGB12_CSI2P:
        fourcc: DRM_FORMAT_SRGGB12
+diff --git a/src/libcamera/sensor/camera_sensor.cpp b/src/libcamera/sensor/camera_sensor.cpp
+index c6d7f801..77c396b9 100644
+--- a/src/libcamera/sensor/camera_sensor.cpp
++++ b/src/libcamera/sensor/camera_sensor.cpp
+@@ -526,6 +526,9 @@ int CameraSensor::initProperties()
+ 		case BayerFormat::MONO:
+ 			cfa = properties::draft::MONO;
+ 			break;
++		case BayerFormat::IGIG_GBGR_IGIG_GRGB:
++			cfa = properties::draft::RGB;
++			break;
+ 		}
+ 
+ 		properties_.set(properties::draft::ColorFilterArrangement, cfa);
 diff --git a/src/libcamera/v4l2_pixelformat.cpp b/src/libcamera/v4l2_pixelformat.cpp
-index 5551c62e..53078d99 100644
+index 70568335..a2fbd644 100644
 --- a/src/libcamera/v4l2_pixelformat.cpp
 +++ b/src/libcamera/v4l2_pixelformat.cpp
-@@ -153,6 +153,8 @@ const std::map<V4L2PixelFormat, V4L2PixelFormat::Info> vpf2pf{
+@@ -159,6 +159,8 @@ const std::map<V4L2PixelFormat, V4L2PixelFormat::Info> vpf2pf{
  		{ formats::SGRBG10, "10-bit Bayer GRGR/BGBG" } },
  	{ V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10),
  		{ formats::SRGGB10, "10-bit Bayer RGRG/GBGB" } },
@@ -211,7 +211,7 @@ index 5551c62e..53078d99 100644
  	{ V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10P),
  		{ formats::SBGGR10_CSI2P, "10-bit Bayer BGBG/GRGR Packed" } },
  	{ V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10P),
-@@ -161,6 +163,8 @@ const std::map<V4L2PixelFormat, V4L2PixelFormat::Info> vpf2pf{
+@@ -167,6 +169,8 @@ const std::map<V4L2PixelFormat, V4L2PixelFormat::Info> vpf2pf{
  		{ formats::SGRBG10_CSI2P, "10-bit Bayer GRGR/BGBG Packed" } },
  	{ V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10P),
  		{ formats::SRGGB10_CSI2P, "10-bit Bayer RGRG/GBGB Packed" } },
@@ -221,17 +221,23 @@ index 5551c62e..53078d99 100644
  		{ formats::SBGGR12, "12-bit Bayer BGBG/GRGR" } },
  	{ V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12),
 diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp
-index 15e8206a..4ad37aaf 100644
+index 6da77775..0ba8c0de 100644
 --- a/src/libcamera/v4l2_subdevice.cpp
 +++ b/src/libcamera/v4l2_subdevice.cpp
-@@ -128,6 +128,7 @@ const std::map<uint32_t, V4L2SubdeviceFormatInfo> formatInfoMap = {
- 	{ MEDIA_BUS_FMT_SGBRG10_1X10, { 10, "SGBRG10_1X10", PixelFormatInfo::ColourEncodingRAW } },
- 	{ MEDIA_BUS_FMT_SGRBG10_1X10, { 10, "SGRBG10_1X10", PixelFormatInfo::ColourEncodingRAW } },
- 	{ MEDIA_BUS_FMT_SRGGB10_1X10, { 10, "SRGGB10_1X10", PixelFormatInfo::ColourEncodingRAW } },
-+	{ MEDIA_BUS_FMT_SIGIG_GBGR_IGIG_GRGB10_1X10, { 10, "SIGIG_GBGR_IGIG_GRGB10_1X10", PixelFormatInfo::ColourEncodingRAW } },
- 	{ MEDIA_BUS_FMT_SBGGR12_1X12, { 12, "SBGGR12_1X12", PixelFormatInfo::ColourEncodingRAW } },
- 	{ MEDIA_BUS_FMT_SGBRG12_1X12, { 12, "SGBRG12_1X12", PixelFormatInfo::ColourEncodingRAW } },
- 	{ MEDIA_BUS_FMT_SGRBG12_1X12, { 12, "SGRBG12_1X12", PixelFormatInfo::ColourEncodingRAW } },
+@@ -595,6 +595,13 @@ const std::map<uint32_t, MediaBusFormatInfo> mediaBusFormatInfo{
+ 		.bitsPerPixel = 10,
+ 		.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
+ 	} },
++	{ MEDIA_BUS_FMT_SIGIG_GBGR_IGIG_GRGB10_1X10, {
++		.name = "SIGIG_GBGR_IGIG_GRGB10_1X10",
++		.code = MEDIA_BUS_FMT_SIGIG_GBGR_IGIG_GRGB10_1X10,
++		.type = MediaBusFormatInfo::Type::Image,
++		.bitsPerPixel = 10,
++		.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
++	} },
+ 	{ MEDIA_BUS_FMT_SBGGR12_1X12, {
+ 		.name = "SBGGR12_1X12",
+ 		.code = MEDIA_BUS_FMT_SBGGR12_1X12,
 -- 
-2.43.2
+2.45.2
 
diff --git a/users/flokli/ipu6-softisp/libcamera/0001-libcamera-pipeline-simple-fix-size-adjustment-in-val.patch b/users/flokli/ipu6-softisp/libcamera/0001-libcamera-pipeline-simple-fix-size-adjustment-in-val.patch
deleted file mode 100644
index b640ddaa24cd..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0001-libcamera-pipeline-simple-fix-size-adjustment-in-val.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-From d86746fc1739f678e4bafe43f5047cba9b6b053e Mon Sep 17 00:00:00 2001
-From: Andrey Konovalov <andrey.konovalov@linaro.org>
-Date: Mon, 11 Mar 2024 15:15:05 +0100
-Subject: [PATCH 01/21] libcamera: pipeline: simple: fix size adjustment in
- validate()
-
-SimpleCameraConfiguration::validate() adjusts the configuration of its
-streams (if the size is not in the outputSizes) to the captureSize. But
-the captureSize itself can be not in the outputSizes, and then the
-adjusted configuration won't be valid resulting in camera configuration
-failure.
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- src/libcamera/pipeline/simple/simple.cpp | 37 ++++++++++++++++++++++--
- 1 file changed, 35 insertions(+), 2 deletions(-)
-
-diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
-index 911051b2..a84f6760 100644
---- a/src/libcamera/pipeline/simple/simple.cpp
-+++ b/src/libcamera/pipeline/simple/simple.cpp
-@@ -881,6 +881,30 @@ SimpleCameraConfiguration::SimpleCameraConfiguration(Camera *camera,
- {
- }
- 
-+namespace {
-+
-+static Size adjustSize(const Size &requestedSize, const SizeRange &supportedSizes)
-+{
-+	ASSERT(supportedSizes.min <= supportedSizes.max);
-+
-+	if (supportedSizes.min == supportedSizes.max)
-+		return supportedSizes.max;
-+
-+	unsigned int hStep = supportedSizes.hStep;
-+	unsigned int vStep = supportedSizes.vStep;
-+
-+	if (hStep == 0)
-+		hStep = supportedSizes.max.width - supportedSizes.min.width;
-+	if (vStep == 0)
-+		vStep = supportedSizes.max.height - supportedSizes.min.height;
-+
-+	Size adjusted = requestedSize.boundedTo(supportedSizes.max).expandedTo(supportedSizes.min);
-+
-+	return adjusted.shrunkBy(supportedSizes.min).alignedDownTo(hStep, vStep).grownBy(supportedSizes.min);
-+}
-+
-+} /* namespace */
-+
- CameraConfiguration::Status SimpleCameraConfiguration::validate()
- {
- 	const CameraSensor *sensor = data_->sensor_.get();
-@@ -997,10 +1021,19 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()
- 		}
- 
- 		if (!pipeConfig_->outputSizes.contains(cfg.size)) {
-+			Size adjustedSize = pipeConfig_->captureSize;
-+			/*
-+			 * The converter (when present) may not be able to output
-+			 * a size identical to its input size. The capture size is thus
-+			 * not guaranteed to be a valid output size. In such cases, use
-+			 * the smaller valid output size closest to the requested.
-+			 */
-+			if (!pipeConfig_->outputSizes.contains(adjustedSize))
-+				adjustedSize = adjustSize(cfg.size, pipeConfig_->outputSizes);
- 			LOG(SimplePipeline, Debug)
- 				<< "Adjusting size from " << cfg.size
--				<< " to " << pipeConfig_->captureSize;
--			cfg.size = pipeConfig_->captureSize;
-+				<< " to " << adjustedSize;
-+			cfg.size = adjustedSize;
- 			status = Adjusted;
- 		}
- 
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0002-libcamera-internal-Move-dma_heaps.-h-cpp-to-common-d.patch b/users/flokli/ipu6-softisp/libcamera/0002-libcamera-internal-Move-dma_heaps.-h-cpp-to-common-d.patch
deleted file mode 100644
index 450a0a21f19a..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0002-libcamera-internal-Move-dma_heaps.-h-cpp-to-common-d.patch
+++ /dev/null
@@ -1,350 +0,0 @@
-From 96e50c6a43352a9cb81d558fea27e580f2b26585 Mon Sep 17 00:00:00 2001
-From: Andrey Konovalov <andrey.konovalov@linaro.org>
-Date: Mon, 11 Mar 2024 15:15:06 +0100
-Subject: [PATCH 02/21] libcamera: internal: Move dma_heaps.[h, cpp] to common
- directories
-
-DmaHeap class is useful outside the RPi pipeline handler too.
-
-Move dma_heaps.h and dma_heaps.cpp to common directories. Update
-the build files and RPi vc4 pipeline handler accordingly.
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
----
- .../libcamera/internal}/dma_heaps.h           |   4 -
- include/libcamera/internal/meson.build        |   1 +
- src/libcamera/dma_heaps.cpp                   | 127 ++++++++++++++++++
- src/libcamera/meson.build                     |   1 +
- src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp  |  90 -------------
- src/libcamera/pipeline/rpi/vc4/meson.build    |   1 -
- src/libcamera/pipeline/rpi/vc4/vc4.cpp        |   5 +-
- 7 files changed, 131 insertions(+), 98 deletions(-)
- rename {src/libcamera/pipeline/rpi/vc4 => include/libcamera/internal}/dma_heaps.h (92%)
- create mode 100644 src/libcamera/dma_heaps.cpp
- delete mode 100644 src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
-
-diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h b/include/libcamera/internal/dma_heaps.h
-similarity index 92%
-rename from src/libcamera/pipeline/rpi/vc4/dma_heaps.h
-rename to include/libcamera/internal/dma_heaps.h
-index 0a4a8d86..cff8f140 100644
---- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h
-+++ b/include/libcamera/internal/dma_heaps.h
-@@ -13,8 +13,6 @@
- 
- namespace libcamera {
- 
--namespace RPi {
--
- class DmaHeap
- {
- public:
-@@ -27,6 +25,4 @@ private:
- 	UniqueFD dmaHeapHandle_;
- };
- 
--} /* namespace RPi */
--
- } /* namespace libcamera */
-diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
-index 7f1f3440..33eb0fb3 100644
---- a/include/libcamera/internal/meson.build
-+++ b/include/libcamera/internal/meson.build
-@@ -25,6 +25,7 @@ libcamera_internal_headers = files([
-     'device_enumerator.h',
-     'device_enumerator_sysfs.h',
-     'device_enumerator_udev.h',
-+    'dma_heaps.h',
-     'formats.h',
-     'framebuffer.h',
-     'ipa_manager.h',
-diff --git a/src/libcamera/dma_heaps.cpp b/src/libcamera/dma_heaps.cpp
-new file mode 100644
-index 00000000..38ef175a
---- /dev/null
-+++ b/src/libcamera/dma_heaps.cpp
-@@ -0,0 +1,127 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2020, Raspberry Pi Ltd
-+ *
-+ * dma_heaps.h - Helper class for dma-heap allocations.
-+ */
-+
-+#include "libcamera/internal/dma_heaps.h"
-+
-+#include <array>
-+#include <fcntl.h>
-+#include <sys/ioctl.h>
-+#include <unistd.h>
-+
-+#include <linux/dma-buf.h>
-+#include <linux/dma-heap.h>
-+
-+#include <libcamera/base/log.h>
-+
-+/**
-+ * \file dma_heaps.cpp
-+ * \brief CMA dma-heap allocator
-+ */
-+
-+/*
-+ * /dev/dma_heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma
-+ * to only have to worry about importing.
-+ *
-+ * Annoyingly, should the cma heap size be specified on the kernel command line
-+ * instead of DT, the heap gets named "reserved" instead.
-+ */
-+static constexpr std::array<const char *, 2> heapNames = {
-+	"/dev/dma_heap/linux,cma",
-+	"/dev/dma_heap/reserved"
-+};
-+
-+namespace libcamera {
-+
-+LOG_DEFINE_CATEGORY(DmaHeap)
-+
-+/**
-+ * \class DmaHeap
-+ * \brief Helper class for CMA dma-heap allocations
-+ */
-+
-+/**
-+ * \brief Construct a DmaHeap that owns a CMA dma-heap file descriptor
-+ *
-+ * Goes through the internal list of possible names of the CMA dma-heap devices
-+ * until a CMA dma-heap device is successfully opened. If it fails to open any
-+ * dma-heap device, an invalid DmaHeap object is constructed. A valid DmaHeap
-+ * object owns a wrapped dma-heap file descriptor.
-+ *
-+ * Please check the new DmaHeap object with \ref DmaHeap::isValid before using it.
-+ */
-+DmaHeap::DmaHeap()
-+{
-+	for (const char *name : heapNames) {
-+		int ret = ::open(name, O_RDWR | O_CLOEXEC, 0);
-+		if (ret < 0) {
-+			ret = errno;
-+			LOG(DmaHeap, Debug)
-+				<< "Failed to open " << name << ": "
-+				<< strerror(ret);
-+			continue;
-+		}
-+
-+		dmaHeapHandle_ = UniqueFD(ret);
-+		break;
-+	}
-+
-+	if (!dmaHeapHandle_.isValid())
-+		LOG(DmaHeap, Error) << "Could not open any dmaHeap device";
-+}
-+
-+/**
-+ * \brief Destroy the DmaHeap instance
-+ *
-+ * Destroying a DmaHeap instance which owns a wrapped dma-heap file descriptor
-+ * closes the descriptor automatically.
-+ */
-+DmaHeap::~DmaHeap() = default;
-+
-+/**
-+ * \fn DmaHeap::isValid()
-+ * \brief Check if the DmaHeap instance is valid
-+ * \return True if the DmaHeap is valid, false otherwise
-+ */
-+
-+/**
-+ * \brief Allocate a dma-buf from the DmaHeap
-+ * \param [in] name The name to set for the allocated buffer
-+ * \param [in] size The size of the buffer to allocate
-+ * \return The \ref UniqueFD of the allocated buffer
-+ *
-+ * Allocates a dma-buf with read/write access.
-+ * If the allocation fails returns invalid UniqueFD.
-+ */
-+UniqueFD DmaHeap::alloc(const char *name, std::size_t size)
-+{
-+	int ret;
-+
-+	if (!name)
-+		return {};
-+
-+	struct dma_heap_allocation_data alloc = {};
-+
-+	alloc.len = size;
-+	alloc.fd_flags = O_CLOEXEC | O_RDWR;
-+
-+	ret = ::ioctl(dmaHeapHandle_.get(), DMA_HEAP_IOCTL_ALLOC, &alloc);
-+	if (ret < 0) {
-+		LOG(DmaHeap, Error) << "dmaHeap allocation failure for " << name;
-+		return {};
-+	}
-+
-+	UniqueFD allocFd(alloc.fd);
-+	ret = ::ioctl(allocFd.get(), DMA_BUF_SET_NAME, name);
-+	if (ret < 0) {
-+		LOG(DmaHeap, Error) << "dmaHeap naming failure for " << name;
-+		return {};
-+	}
-+
-+	return allocFd;
-+}
-+
-+} /* namespace libcamera */
-diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
-index 45f63e93..3c5e43df 100644
---- a/src/libcamera/meson.build
-+++ b/src/libcamera/meson.build
-@@ -17,6 +17,7 @@ libcamera_sources = files([
-     'delayed_controls.cpp',
-     'device_enumerator.cpp',
-     'device_enumerator_sysfs.cpp',
-+    'dma_heaps.cpp',
-     'fence.cpp',
-     'formats.cpp',
-     'framebuffer.cpp',
-diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp b/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
-deleted file mode 100644
-index 317b1fc1..00000000
---- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
-+++ /dev/null
-@@ -1,90 +0,0 @@
--/* SPDX-License-Identifier: LGPL-2.1-or-later */
--/*
-- * Copyright (C) 2020, Raspberry Pi Ltd
-- *
-- * dma_heaps.h - Helper class for dma-heap allocations.
-- */
--
--#include "dma_heaps.h"
--
--#include <array>
--#include <fcntl.h>
--#include <linux/dma-buf.h>
--#include <linux/dma-heap.h>
--#include <sys/ioctl.h>
--#include <unistd.h>
--
--#include <libcamera/base/log.h>
--
--/*
-- * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma
-- * to only have to worry about importing.
-- *
-- * Annoyingly, should the cma heap size be specified on the kernel command line
-- * instead of DT, the heap gets named "reserved" instead.
-- */
--static constexpr std::array<const char *, 2> heapNames = {
--	"/dev/dma_heap/linux,cma",
--	"/dev/dma_heap/reserved"
--};
--
--namespace libcamera {
--
--LOG_DECLARE_CATEGORY(RPI)
--
--namespace RPi {
--
--DmaHeap::DmaHeap()
--{
--	for (const char *name : heapNames) {
--		int ret = ::open(name, O_RDWR | O_CLOEXEC, 0);
--		if (ret < 0) {
--			ret = errno;
--			LOG(RPI, Debug) << "Failed to open " << name << ": "
--					<< strerror(ret);
--			continue;
--		}
--
--		dmaHeapHandle_ = UniqueFD(ret);
--		break;
--	}
--
--	if (!dmaHeapHandle_.isValid())
--		LOG(RPI, Error) << "Could not open any dmaHeap device";
--}
--
--DmaHeap::~DmaHeap() = default;
--
--UniqueFD DmaHeap::alloc(const char *name, std::size_t size)
--{
--	int ret;
--
--	if (!name)
--		return {};
--
--	struct dma_heap_allocation_data alloc = {};
--
--	alloc.len = size;
--	alloc.fd_flags = O_CLOEXEC | O_RDWR;
--
--	ret = ::ioctl(dmaHeapHandle_.get(), DMA_HEAP_IOCTL_ALLOC, &alloc);
--	if (ret < 0) {
--		LOG(RPI, Error) << "dmaHeap allocation failure for "
--				<< name;
--		return {};
--	}
--
--	UniqueFD allocFd(alloc.fd);
--	ret = ::ioctl(allocFd.get(), DMA_BUF_SET_NAME, name);
--	if (ret < 0) {
--		LOG(RPI, Error) << "dmaHeap naming failure for "
--				<< name;
--		return {};
--	}
--
--	return allocFd;
--}
--
--} /* namespace RPi */
--
--} /* namespace libcamera */
-diff --git a/src/libcamera/pipeline/rpi/vc4/meson.build b/src/libcamera/pipeline/rpi/vc4/meson.build
-index cdb049c5..386e2296 100644
---- a/src/libcamera/pipeline/rpi/vc4/meson.build
-+++ b/src/libcamera/pipeline/rpi/vc4/meson.build
-@@ -1,7 +1,6 @@
- # SPDX-License-Identifier: CC0-1.0
- 
- libcamera_sources += files([
--    'dma_heaps.cpp',
-     'vc4.cpp',
- ])
- 
-diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
-index 26102ea7..3a42e75e 100644
---- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
-+++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
-@@ -12,12 +12,11 @@
- #include <libcamera/formats.h>
- 
- #include "libcamera/internal/device_enumerator.h"
-+#include "libcamera/internal/dma_heaps.h"
- 
- #include "../common/pipeline_base.h"
- #include "../common/rpi_stream.h"
- 
--#include "dma_heaps.h"
--
- using namespace std::chrono_literals;
- 
- namespace libcamera {
-@@ -87,7 +86,7 @@ public:
- 	RPi::Device<Isp, 4> isp_;
- 
- 	/* DMAHEAP allocation helper. */
--	RPi::DmaHeap dmaHeap_;
-+	DmaHeap dmaHeap_;
- 	SharedFD lsTable_;
- 
- 	struct Config {
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0020-ov01a1s-HACK.patch b/users/flokli/ipu6-softisp/libcamera/0002-ov01a1s-HACK.patch
index 343f04c8502b..61316d10427f 100644
--- a/users/flokli/ipu6-softisp/libcamera/0020-ov01a1s-HACK.patch
+++ b/users/flokli/ipu6-softisp/libcamera/0002-ov01a1s-HACK.patch
@@ -1,30 +1,30 @@
-From 2bde6e420571c6dc0ff25246620b4c987987f6be Mon Sep 17 00:00:00 2001
+From 5895f4ed8163780446665b99b8d5dc31d6f2b791 Mon Sep 17 00:00:00 2001
 From: Hans de Goede <hdegoede@redhat.com>
 Date: Tue, 19 Dec 2023 15:45:51 +0100
-Subject: [PATCH 20/21] ov01a1s HACK
+Subject: [PATCH 2/3] ov01a1s HACK
 
 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
 ---
- src/libcamera/camera_sensor.cpp            | 6 ++++++
- src/libcamera/software_isp/debayer_cpu.cpp | 8 ++++++++
+ src/libcamera/sensor/camera_sensor.cpp     | 6 ++++++
+ src/libcamera/software_isp/debayer_cpu.cpp | 7 +++++++
  src/libcamera/software_isp/swstats_cpu.cpp | 4 ++++
- 3 files changed, 18 insertions(+)
+ 3 files changed, 17 insertions(+)
 
-diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
-index f19f72ea..7ad4b9ef 100644
---- a/src/libcamera/camera_sensor.cpp
-+++ b/src/libcamera/camera_sensor.cpp
-@@ -34,6 +34,9 @@
+diff --git a/src/libcamera/sensor/camera_sensor.cpp b/src/libcamera/sensor/camera_sensor.cpp
+index 77c396b9..628b12f4 100644
+--- a/src/libcamera/sensor/camera_sensor.cpp
++++ b/src/libcamera/sensor/camera_sensor.cpp
+@@ -33,6 +33,9 @@
+  */
  
  namespace libcamera {
- 
++	
 +// HACK HACK
 +bool is_ov01a1s = false;
-+
+ 
  LOG_DEFINE_CATEGORY(CameraSensor)
  
- /**
-@@ -426,6 +429,9 @@ int CameraSensor::initProperties()
+@@ -442,6 +445,9 @@ int CameraSensor::initProperties()
  	model_ = subdev_->model();
  	properties_.set(properties::Model, utils::toAscii(model_));
  
@@ -35,7 +35,7 @@ index f19f72ea..7ad4b9ef 100644
  	int ret = generateId();
  	if (ret)
 diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
-index 3be3cdfe..d6599805 100644
+index 8254bbe9..10ea29b1 100644
 --- a/src/libcamera/software_isp/debayer_cpu.cpp
 +++ b/src/libcamera/software_isp/debayer_cpu.cpp
 @@ -23,6 +23,7 @@
@@ -46,7 +46,7 @@ index 3be3cdfe..d6599805 100644
  /**
   * \class DebayerCpu
   * \brief Class for debayering on the CPU
-@@ -262,6 +263,9 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf
+@@ -275,6 +276,9 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf
  	BayerFormat bayerFormat =
  		BayerFormat::fromPixelFormat(inputFormat);
  
@@ -56,7 +56,7 @@ index 3be3cdfe..d6599805 100644
  	if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) &&
  	    bayerFormat.packing == BayerFormat::Packing::None &&
  	    isStandardBayerOrder(bayerFormat.order)) {
-@@ -330,7 +334,11 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF
+@@ -343,6 +347,9 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF
  	BayerFormat bayerFormat =
  		BayerFormat::fromPixelFormat(inputFormat);
  
@@ -64,12 +64,10 @@ index 3be3cdfe..d6599805 100644
 +		bayerFormat.order = BayerFormat::IGIG_GBGR_IGIG_GRGB;
 +
  	xShift_ = 0;
-+
  	swapRedBlueGains_ = false;
  
- 	switch (outputFormat) {
 diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp
-index be310f56..cda1894a 100644
+index 815c4d4f..0b310f80 100644
 --- a/src/libcamera/software_isp/swstats_cpu.cpp
 +++ b/src/libcamera/software_isp/swstats_cpu.cpp
 @@ -19,6 +19,7 @@
@@ -80,7 +78,7 @@ index be310f56..cda1894a 100644
  /**
   * \class SwStatsCpu
   * \brief Class for gathering statistics on the CPU
-@@ -271,6 +272,9 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
+@@ -367,6 +368,9 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
  	BayerFormat bayerFormat =
  		BayerFormat::fromPixelFormat(inputCfg.pixelFormat);
  
@@ -91,5 +89,5 @@ index be310f56..cda1894a 100644
  	    setupStandardBayerOrder(bayerFormat.order) == 0) {
  		switch (bayerFormat.bitDepth) {
 -- 
-2.43.2
+2.45.2
 
diff --git a/users/flokli/ipu6-softisp/libcamera/0021-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch b/users/flokli/ipu6-softisp/libcamera/0003-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch
index a3af38c93c79..f250617bd3ad 100644
--- a/users/flokli/ipu6-softisp/libcamera/0021-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch
+++ b/users/flokli/ipu6-softisp/libcamera/0003-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch
@@ -1,7 +1,7 @@
-From a21bb26dcfcc00425f031421b87576f9c81e4824 Mon Sep 17 00:00:00 2001
+From 06add438e4fc53faca6e016bd582df0e7ac5a271 Mon Sep 17 00:00:00 2001
 From: Hans de Goede <hdegoede@redhat.com>
 Date: Wed, 24 Jan 2024 20:44:29 +0100
-Subject: [PATCH 21/21] libcamera: debayer_cpu: Make the minimum size 1280x720
+Subject: [PATCH 3/3] libcamera: debayer_cpu: Make the minimum size 1280x720
 
 pipewire + firefox default to what looks like 640x480 if we export
 the entire supported cropping range. Hardcode 720p as minsize for now.
@@ -12,31 +12,31 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  1 file changed, 11 insertions(+), 4 deletions(-)
 
 diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
-index d6599805..5a06b191 100644
+index 10ea29b1..a354138b 100644
 --- a/src/libcamera/software_isp/debayer_cpu.cpp
 +++ b/src/libcamera/software_isp/debayer_cpu.cpp
-@@ -790,10 +790,17 @@ SizeRange DebayerCpu::sizes(PixelFormat inputFormat, const Size &inputSize)
+@@ -805,10 +805,17 @@ SizeRange DebayerCpu::sizes(PixelFormat inputFormat, const Size &inputSize)
  		return {};
  	}
  
--	return SizeRange(Size(pattern_size.width, pattern_size.height),
--			 Size((inputSize.width - 2 * pattern_size.width) & ~(pattern_size.width - 1),
--			      (inputSize.height - 2 * border_height) & ~(pattern_size.height - 1)),
--			 pattern_size.width, pattern_size.height);
+-	return SizeRange(Size(patternSize.width, patternSize.height),
+-			 Size((inputSize.width - 2 * patternSize.width) & ~(patternSize.width - 1),
+-			      (inputSize.height - 2 * borderHeight) & ~(patternSize.height - 1)),
+-			 patternSize.width, patternSize.height);
 +	/*
 +	 * pipewire + firefox default to what looks like 640x480
 +	 * if we export the entire supported cropping range.
 +	 * Hardcode 720p as minsize for now. Minsize should be
-+	 * Size(pattern_size.width, pattern_size.height)
++	 * Size(patternSize.width, patternSize.height)
 +	 */
-+	unsigned int w = (inputSize.width - 2 * pattern_size.width) & ~(pattern_size.width - 1);
-+	unsigned int h = (inputSize.height - 2 * pattern_size.height) & ~(pattern_size.height - 1);
++	unsigned int w = (inputSize.width - 2 * patternSize.width) & ~(patternSize.width - 1);
++	unsigned int h = (inputSize.height - 2 * patternSize.height) & ~(patternSize.height - 1);
 +	return SizeRange(Size(std::min(w, 1280u), std::min(h, 720u)),
 +	                 Size(w, h),
-+	                 pattern_size.width, pattern_size.height);
++	                 patternSize.width, patternSize.height);
  }
  
  } /* namespace libcamera */
 -- 
-2.43.2
+2.45.2
 
diff --git a/users/flokli/ipu6-softisp/libcamera/0003-libcamera-dma_heaps-extend-DmaHeap-class-to-support-.patch b/users/flokli/ipu6-softisp/libcamera/0003-libcamera-dma_heaps-extend-DmaHeap-class-to-support-.patch
deleted file mode 100644
index 6e5ef9445a4b..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0003-libcamera-dma_heaps-extend-DmaHeap-class-to-support-.patch
+++ /dev/null
@@ -1,169 +0,0 @@
-From 5df9bc3b2a3d86bcc8504896cc87d7fcb5aea3a4 Mon Sep 17 00:00:00 2001
-From: Andrey Konovalov <andrey.konovalov@linaro.org>
-Date: Mon, 11 Mar 2024 15:15:07 +0100
-Subject: [PATCH 03/21] libcamera: dma_heaps: extend DmaHeap class to support
- system heap
-
-Add an argument to the constructor to specify dma heaps type(s)
-to use. Can be DmaHeapFlag::Cma and/or DmaHeapFlag::System.
-By default DmaHeapFlag::Cma is used. If both DmaHeapFlag::Cma and
-DmaHeapFlag::System are set, CMA heap is tried first.
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- include/libcamera/internal/dma_heaps.h | 12 ++++-
- src/libcamera/dma_heaps.cpp            | 67 ++++++++++++++++++++------
- 2 files changed, 63 insertions(+), 16 deletions(-)
-
-diff --git a/include/libcamera/internal/dma_heaps.h b/include/libcamera/internal/dma_heaps.h
-index cff8f140..80bf29e7 100644
---- a/include/libcamera/internal/dma_heaps.h
-+++ b/include/libcamera/internal/dma_heaps.h
-@@ -9,6 +9,7 @@
- 
- #include <stddef.h>
- 
-+#include <libcamera/base/flags.h>
- #include <libcamera/base/unique_fd.h>
- 
- namespace libcamera {
-@@ -16,7 +17,14 @@ namespace libcamera {
- class DmaHeap
- {
- public:
--	DmaHeap();
-+	enum class DmaHeapFlag {
-+		Cma = 1 << 0,
-+		System = 1 << 1,
-+	};
-+
-+	using DmaHeapFlags = Flags<DmaHeapFlag>;
-+
-+	DmaHeap(DmaHeapFlags flags = DmaHeapFlag::Cma);
- 	~DmaHeap();
- 	bool isValid() const { return dmaHeapHandle_.isValid(); }
- 	UniqueFD alloc(const char *name, std::size_t size);
-@@ -25,4 +33,6 @@ private:
- 	UniqueFD dmaHeapHandle_;
- };
- 
-+LIBCAMERA_FLAGS_ENABLE_OPERATORS(DmaHeap::DmaHeapFlag)
-+
- } /* namespace libcamera */
-diff --git a/src/libcamera/dma_heaps.cpp b/src/libcamera/dma_heaps.cpp
-index 38ef175a..d0e33ce6 100644
---- a/src/libcamera/dma_heaps.cpp
-+++ b/src/libcamera/dma_heaps.cpp
-@@ -19,9 +19,11 @@
- 
- /**
-  * \file dma_heaps.cpp
-- * \brief CMA dma-heap allocator
-+ * \brief dma-heap allocator
-  */
- 
-+namespace libcamera {
-+
- /*
-  * /dev/dma_heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma
-  * to only have to worry about importing.
-@@ -29,42 +31,77 @@
-  * Annoyingly, should the cma heap size be specified on the kernel command line
-  * instead of DT, the heap gets named "reserved" instead.
-  */
--static constexpr std::array<const char *, 2> heapNames = {
--	"/dev/dma_heap/linux,cma",
--	"/dev/dma_heap/reserved"
-+
-+/**
-+ * \struct DmaHeapInfo
-+ * \brief Tells what type of dma-heap the dma-heap represented by the device node name is
-+ * \var DmaHeapInfo::flag
-+ * \brief The type of the dma-heap
-+ * \var DmaHeapInfo::name
-+ * \brief The dma-heap's device node name
-+ */
-+struct DmaHeapInfo {
-+	DmaHeap::DmaHeapFlag flag;
-+	const char *name;
- };
- 
--namespace libcamera {
-+static constexpr std::array<DmaHeapInfo, 3> heapInfos = {
-+	{ /* CMA heap names first */
-+	  { DmaHeap::DmaHeapFlag::Cma, "/dev/dma_heap/linux,cma" },
-+	  { DmaHeap::DmaHeapFlag::Cma, "/dev/dma_heap/reserved" },
-+	  { DmaHeap::DmaHeapFlag::System, "/dev/dma_heap/system" } }
-+};
- 
- LOG_DEFINE_CATEGORY(DmaHeap)
- 
- /**
-  * \class DmaHeap
-- * \brief Helper class for CMA dma-heap allocations
-+ * \brief Helper class for dma-heap allocations
-  */
- 
- /**
-- * \brief Construct a DmaHeap that owns a CMA dma-heap file descriptor
-+ * \enum DmaHeap::DmaHeapFlag
-+ * \brief Type of the dma-heap
-+ * \var DmaHeap::Cma
-+ * \brief Allocate from a CMA dma-heap
-+ * \var DmaHeap::System
-+ * \brief Allocate from the system dma-heap
-+ */
-+
-+/**
-+ * \typedef DmaHeap::DmaHeapFlags
-+ * \brief A bitwise combination of DmaHeap::DmaHeapFlag values
-+ */
-+
-+/**
-+ * \brief Construct a DmaHeap that owns a CMA or system dma-heap file descriptor
-+ * \param [in] flags The type(s) of the dma-heap(s) to allocate from
-  *
-- * Goes through the internal list of possible names of the CMA dma-heap devices
-- * until a CMA dma-heap device is successfully opened. If it fails to open any
-- * dma-heap device, an invalid DmaHeap object is constructed. A valid DmaHeap
-- * object owns a wrapped dma-heap file descriptor.
-+ * By default \a flags are set to DmaHeap::DmaHeapFlag::Cma. The constructor goes
-+ * through the internal list of possible names of the CMA and system dma-heap devices
-+ * until the dma-heap device of the requested type is successfully opened. If more
-+ * than one dma-heap type is specified in flags the CMA heap is tried first. If it
-+ * fails to open any dma-heap device an invalid DmaHeap object is constructed.
-+ * A valid DmaHeap object owns a wrapped dma-heap file descriptor.
-  *
-  * Please check the new DmaHeap object with \ref DmaHeap::isValid before using it.
-  */
--DmaHeap::DmaHeap()
-+DmaHeap::DmaHeap(DmaHeapFlags flags)
- {
--	for (const char *name : heapNames) {
--		int ret = ::open(name, O_RDWR | O_CLOEXEC, 0);
-+	for (const auto &info : heapInfos) {
-+		if (!(flags & info.flag))
-+			continue;
-+
-+		int ret = ::open(info.name, O_RDWR | O_CLOEXEC, 0);
- 		if (ret < 0) {
- 			ret = errno;
- 			LOG(DmaHeap, Debug)
--				<< "Failed to open " << name << ": "
-+				<< "Failed to open " << info.name << ": "
- 				<< strerror(ret);
- 			continue;
- 		}
- 
-+		LOG(DmaHeap, Debug) << "Using " << info.name;
- 		dmaHeapHandle_ = UniqueFD(ret);
- 		break;
- 	}
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0004-libcamera-internal-Move-SharedMemObject-class-to-a-c.patch b/users/flokli/ipu6-softisp/libcamera/0004-libcamera-internal-Move-SharedMemObject-class-to-a-c.patch
deleted file mode 100644
index 48f10aa47a99..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0004-libcamera-internal-Move-SharedMemObject-class-to-a-c.patch
+++ /dev/null
@@ -1,69 +0,0 @@
-From a6777760a2121f02808baecea504ac0e242f860b Mon Sep 17 00:00:00 2001
-From: Andrey Konovalov <andrey.konovalov@linaro.org>
-Date: Mon, 11 Mar 2024 15:15:08 +0100
-Subject: [PATCH 04/21] libcamera: internal: Move SharedMemObject class to a
- common directory
-
-Move SharedMemObject class out of RPi namespace and put it into
-include/libcamera/internal so that everyone could use it.
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
----
- include/libcamera/internal/meson.build                      | 1 +
- .../libcamera/internal}/shared_mem_object.h                 | 6 +-----
- 2 files changed, 2 insertions(+), 5 deletions(-)
- rename {src/libcamera/pipeline/rpi/common => include/libcamera/internal}/shared_mem_object.h (97%)
-
-diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
-index 33eb0fb3..5807dfd9 100644
---- a/include/libcamera/internal/meson.build
-+++ b/include/libcamera/internal/meson.build
-@@ -39,6 +39,7 @@ libcamera_internal_headers = files([
-     'process.h',
-     'pub_key.h',
-     'request.h',
-+    'shared_mem_object.h',
-     'source_paths.h',
-     'sysfs.h',
-     'v4l2_device.h',
-diff --git a/src/libcamera/pipeline/rpi/common/shared_mem_object.h b/include/libcamera/internal/shared_mem_object.h
-similarity index 97%
-rename from src/libcamera/pipeline/rpi/common/shared_mem_object.h
-rename to include/libcamera/internal/shared_mem_object.h
-index aa56c220..98636b44 100644
---- a/src/libcamera/pipeline/rpi/common/shared_mem_object.h
-+++ b/include/libcamera/internal/shared_mem_object.h
-@@ -6,8 +6,8 @@
-  */
- #pragma once
- 
--#include <cstddef>
- #include <fcntl.h>
-+#include <stddef.h>
- #include <string>
- #include <sys/mman.h>
- #include <sys/stat.h>
-@@ -19,8 +19,6 @@
- 
- namespace libcamera {
- 
--namespace RPi {
--
- template<class T>
- class SharedMemObject
- {
-@@ -123,6 +121,4 @@ private:
- 	T *obj_;
- };
- 
--} /* namespace RPi */
--
- } /* namespace libcamera */
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0005-libcamera-shared_mem_object-reorganize-the-code-and-.patch b/users/flokli/ipu6-softisp/libcamera/0005-libcamera-shared_mem_object-reorganize-the-code-and-.patch
deleted file mode 100644
index d2143febf740..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0005-libcamera-shared_mem_object-reorganize-the-code-and-.patch
+++ /dev/null
@@ -1,403 +0,0 @@
-From f94af21adc1889706127d07c5425f44c9cec9a95 Mon Sep 17 00:00:00 2001
-From: Andrei Konovalov <andrey.konovalov.ynk@gmail.com>
-Date: Mon, 11 Mar 2024 15:15:09 +0100
-Subject: [PATCH 05/21] libcamera: shared_mem_object: reorganize the code and
- document the SharedMemObject class
-
-Split the parts which doesn't otherwise depend on the type T or
-arguments Args out of the SharedMemObject class into a new
-SharedMem class.
-
-Doxygen documentation by Dennis Bonke and Andrei Konovalov.
-
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Co-developed-by: Dennis Bonke <admin@dennisbonke.com>
-Signed-off-by: Dennis Bonke <admin@dennisbonke.com>
-Signed-off-by: Andrei Konovalov <andrey.konovalov.ynk@gmail.com>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
----
- .../libcamera/internal/shared_mem_object.h    | 101 ++++++----
- src/libcamera/meson.build                     |   1 +
- src/libcamera/shared_mem_object.cpp           | 190 ++++++++++++++++++
- 3 files changed, 253 insertions(+), 39 deletions(-)
- create mode 100644 src/libcamera/shared_mem_object.cpp
-
-diff --git a/include/libcamera/internal/shared_mem_object.h b/include/libcamera/internal/shared_mem_object.h
-index 98636b44..43b07c9d 100644
---- a/include/libcamera/internal/shared_mem_object.h
-+++ b/include/libcamera/internal/shared_mem_object.h
-@@ -6,12 +6,9 @@
-  */
- #pragma once
- 
--#include <fcntl.h>
- #include <stddef.h>
- #include <string>
- #include <sys/mman.h>
--#include <sys/stat.h>
--#include <unistd.h>
- #include <utility>
- 
- #include <libcamera/base/class.h>
-@@ -19,58 +16,92 @@
- 
- namespace libcamera {
- 
-+class SharedMem
-+{
-+public:
-+	SharedMem()
-+		: mem_(nullptr)
-+	{
-+	}
-+
-+	SharedMem(const std::string &name, std::size_t size);
-+
-+	SharedMem(SharedMem &&rhs)
-+	{
-+		this->name_ = std::move(rhs.name_);
-+		this->fd_ = std::move(rhs.fd_);
-+		this->mem_ = rhs.mem_;
-+		rhs.mem_ = nullptr;
-+	}
-+
-+	virtual ~SharedMem()
-+	{
-+		if (mem_)
-+			munmap(mem_, size_);
-+	}
-+
-+	/* Make SharedMem non-copyable for now. */
-+	LIBCAMERA_DISABLE_COPY(SharedMem)
-+
-+	SharedMem &operator=(SharedMem &&rhs)
-+	{
-+		this->name_ = std::move(rhs.name_);
-+		this->fd_ = std::move(rhs.fd_);
-+		this->mem_ = rhs.mem_;
-+		rhs.mem_ = nullptr;
-+		return *this;
-+	}
-+
-+	const SharedFD &fd() const
-+	{
-+		return fd_;
-+	}
-+
-+	void *mem() const
-+	{
-+		return mem_;
-+	}
-+
-+private:
-+	std::string name_;
-+	SharedFD fd_;
-+	size_t size_;
-+protected:
-+	void *mem_;
-+};
-+
- template<class T>
--class SharedMemObject
-+class SharedMemObject : public SharedMem
- {
- public:
- 	static constexpr std::size_t SIZE = sizeof(T);
- 
- 	SharedMemObject()
--		: obj_(nullptr)
-+		: SharedMem(), obj_(nullptr)
- 	{
- 	}
- 
- 	template<class... Args>
- 	SharedMemObject(const std::string &name, Args &&...args)
--		: name_(name), obj_(nullptr)
-+		: SharedMem(name, SIZE), obj_(nullptr)
- 	{
--		void *mem;
--		int ret;
--
--		ret = memfd_create(name_.c_str(), MFD_CLOEXEC);
--		if (ret < 0)
--			return;
--
--		fd_ = SharedFD(std::move(ret));
--		if (!fd_.isValid())
--			return;
--
--		ret = ftruncate(fd_.get(), SIZE);
--		if (ret < 0)
-+		if (mem_ == nullptr)
- 			return;
- 
--		mem = mmap(nullptr, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
--			   fd_.get(), 0);
--		if (mem == MAP_FAILED)
--			return;
--
--		obj_ = new (mem) T(std::forward<Args>(args)...);
-+		obj_ = new (mem_) T(std::forward<Args>(args)...);
- 	}
- 
- 	SharedMemObject(SharedMemObject<T> &&rhs)
-+		: SharedMem(std::move(rhs))
- 	{
--		this->name_ = std::move(rhs.name_);
--		this->fd_ = std::move(rhs.fd_);
- 		this->obj_ = rhs.obj_;
- 		rhs.obj_ = nullptr;
- 	}
- 
- 	~SharedMemObject()
- 	{
--		if (obj_) {
-+		if (obj_)
- 			obj_->~T();
--			munmap(obj_, SIZE);
--		}
- 	}
- 
- 	/* Make SharedMemObject non-copyable for now. */
-@@ -78,8 +109,7 @@ public:
- 
- 	SharedMemObject<T> &operator=(SharedMemObject<T> &&rhs)
- 	{
--		this->name_ = std::move(rhs.name_);
--		this->fd_ = std::move(rhs.fd_);
-+		SharedMem::operator=(std::move(rhs));
- 		this->obj_ = rhs.obj_;
- 		rhs.obj_ = nullptr;
- 		return *this;
-@@ -105,19 +135,12 @@ public:
- 		return *obj_;
- 	}
- 
--	const SharedFD &fd() const
--	{
--		return fd_;
--	}
--
- 	explicit operator bool() const
- 	{
- 		return !!obj_;
- 	}
- 
- private:
--	std::string name_;
--	SharedFD fd_;
- 	T *obj_;
- };
- 
-diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
-index 3c5e43df..94a95ae3 100644
---- a/src/libcamera/meson.build
-+++ b/src/libcamera/meson.build
-@@ -41,6 +41,7 @@ libcamera_sources = files([
-     'process.cpp',
-     'pub_key.cpp',
-     'request.cpp',
-+    'shared_mem_object.cpp',
-     'source_paths.cpp',
-     'stream.cpp',
-     'sysfs.cpp',
-diff --git a/src/libcamera/shared_mem_object.cpp b/src/libcamera/shared_mem_object.cpp
-new file mode 100644
-index 00000000..44fe74c2
---- /dev/null
-+++ b/src/libcamera/shared_mem_object.cpp
-@@ -0,0 +1,190 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2023, Raspberry Pi Ltd
-+ *
-+ * shared_mem_object.cpp - Helper class for shared memory allocations
-+ */
-+
-+#include "libcamera/internal/shared_mem_object.h"
-+
-+#include <sys/types.h>
-+#include <unistd.h>
-+
-+/**
-+ * \file shared_mem_object.cpp
-+ * \brief Helper class for shared memory allocations
-+ */
-+
-+namespace libcamera {
-+
-+/**
-+ * \class SharedMem
-+ * \brief Helper class for allocating shared memory
-+ *
-+ * Memory is allocated and exposed as a SharedFD for use across IPC boundaries.
-+ *
-+ * SharedMem allocates the shared memory of the given size and maps it.
-+ * To check that the shared memory was allocated and mapped successfully, one
-+ * needs to verify that the pointer to the shared memory returned by SharedMem::mem()
-+ * is not nullptr.
-+ *
-+ * To access the shared memory from another process the SharedFD should be passed
-+ * to that process, and then the shared memory should be mapped into that process
-+ * address space by calling mmap().
-+ *
-+ * A single memfd is created for every SharedMem. If there is a need to allocate
-+ * a large number of objects in shared memory, these objects should be grouped
-+ * together and use the shared memory allocated by a single SharedMem object if
-+ * possible. This will help to minimize the number of created memfd's.
-+ */
-+
-+/**
-+ * \fn SharedMem::SharedMem(const std::string &name, std::size_t size)
-+ * \brief Constructor for the SharedMem
-+ * \param[in] name Name of the SharedMem
-+ * \param[in] size Size of the shared memory to allocate and map
-+ */
-+
-+/**
-+ * \fn SharedMem::SharedMem(SharedMem &&rhs)
-+ * \brief Move constructor for SharedMem
-+ * \param[in] rhs The object to move
-+ */
-+
-+/**
-+ * \fn SharedMem::~SharedMem()
-+ * \brief SharedMem destructor
-+ *
-+ * Unmaps the allocated shared memory. Decrements the shared memory descriptor use
-+ * count.
-+ */
-+
-+/**
-+ * \fn SharedMem &SharedMem::operator=(SharedMem &&rhs)
-+ * \brief Move constructor for SharedMem
-+ * \param[in] rhs The object to move
-+ */
-+
-+/**
-+ * \fn const SharedFD &SharedMem::fd() const
-+ * \brief Gets the file descriptor for the underlying shared memory
-+ * \return The file descriptor
-+ */
-+
-+/**
-+ * \fn void *SharedMem::mem() const
-+ * \brief Gets the pointer to the underlying shared memory
-+ * \return The pointer to the shared memory
-+ */
-+
-+SharedMem::SharedMem(const std::string &name, std::size_t size)
-+	: name_(name), size_(size), mem_(nullptr)
-+{
-+	int fd = memfd_create(name_.c_str(), MFD_CLOEXEC);
-+	if (fd < 0)
-+		return;
-+
-+	fd_ = SharedFD(std::move(fd));
-+	if (!fd_.isValid())
-+		return;
-+
-+	if (ftruncate(fd_.get(), size_) < 0)
-+		return;
-+
-+	mem_ = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED,
-+		    fd_.get(), 0);
-+	if (mem_ == MAP_FAILED)
-+		mem_ = nullptr;
-+}
-+
-+/**
-+ * \var SharedMem::mem_
-+ * \brief Pointer to the shared memory allocated
-+ */
-+
-+/**
-+ * \class SharedMemObject
-+ * \brief Helper class for allocating objects in shared memory
-+ *
-+ * Memory is allocated and exposed as a SharedFD for use across IPC boundaries.
-+ *
-+ * Given the type of the object to be created in shared memory and the arguments
-+ * to pass to this object's constructor, SharedMemObject allocates the shared memory
-+ * of the size of the object and constructs the object in this memory. To ensure
-+ * that the SharedMemObject was created successfully, one needs to verify that the
-+ * overloaded bool() operator returns true. The object created in the shared memory
-+ * can be accessed using the SharedMemObject::operator*() indirection operator. Its
-+ * members can be accessed with the SharedMemObject::operator->() member of pointer
-+ * operator.
-+ *
-+ * To access the object from another process the SharedFD should be passed to that
-+ * process, and the shared memory should be mapped by calling mmap().
-+ *
-+ * A single memfd is created for every SharedMemObject. If there is a need to allocate
-+ * a large number of objects in shared memory, these objects should be grouped into a
-+ * single large object to keep the number of created memfd's reasonably small.
-+ */
-+
-+/**
-+ * \var SharedMemObject::SIZE
-+ * \brief The size of the object that is going to be stored here
-+ */
-+
-+/**
-+ * \fn SharedMemObject< T >::SharedMemObject(const std::string &name, Args &&...args)
-+ * \brief Constructor for the SharedMemObject
-+ * \param[in] name Name of the SharedMemObject
-+ * \param[in] args Args to pass to the constructor of the object in shared memory
-+ */
-+
-+/**
-+ * \fn SharedMemObject::SharedMemObject(SharedMemObject<T> &&rhs)
-+ * \brief Move constructor for SharedMemObject
-+ * \param[in] rhs The object to move
-+ */
-+
-+/**
-+ * \fn SharedMemObject::~SharedMemObject()
-+ * \brief SharedMemObject destructor
-+ *
-+ * Destroys the object created in the shared memory and then unmaps the shared memory.
-+ * Decrements the shared memory descriptor use count.
-+ */
-+
-+/**
-+ * \fn SharedMemObject::operator=(SharedMemObject<T> &&rhs)
-+ * \brief Operator= for SharedMemObject
-+ * \param[in] rhs The SharedMemObject object to take the data from
-+ */
-+
-+/**
-+ * \fn SharedMemObject::operator->()
-+ * \brief Operator-> for SharedMemObject
-+ * \return The pointer to the object
-+ */
-+
-+/**
-+ * \fn const T *SharedMemObject::operator->() const
-+ * \brief Operator-> for SharedMemObject
-+ * \return The pointer to the const object
-+ */
-+
-+/**
-+ * \fn SharedMemObject::operator*()
-+ * \brief Operator* for SharedMemObject
-+ * \return The reference to the object
-+ */
-+
-+/**
-+ * \fn const T &SharedMemObject::operator*() const
-+ * \brief Operator* for SharedMemObject
-+ * \return Const reference to the object
-+ */
-+
-+/**
-+ * \fn SharedMemObject::operator bool()
-+ * \brief Operator bool() for SharedMemObject
-+ * \return True if the object was created OK in the shared memory, false otherwise
-+ */
-+
-+} // namespace libcamera
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0006-libcamera-software_isp-Add-SwStatsCpu-class.patch b/users/flokli/ipu6-softisp/libcamera/0006-libcamera-software_isp-Add-SwStatsCpu-class.patch
deleted file mode 100644
index 9f80b69f168c..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0006-libcamera-software_isp-Add-SwStatsCpu-class.patch
+++ /dev/null
@@ -1,523 +0,0 @@
-From 4259b01930333c6666a185d923e6e68ec915a4fd Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Mon, 11 Mar 2024 15:15:10 +0100
-Subject: [PATCH 06/21] libcamera: software_isp: Add SwStatsCpu class
-
-Add a CPU based SwStats implementation for SoftwareISP / SoftIPA use.
-
-This implementation offers a configure function + functions to gather
-statistics on a line by line basis. This allows CPU based software
-debayering to call into interlace debayering and statistics gathering
-on a line by line bases while the input data is still hot in the cache.
-
-This implementation also allows specifying a window over which to gather
-statistics instead of processing the whole frame.
-
-Doxygen documentation by Dennis Bonke.
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
-Co-developed-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Co-developed-by: Pavel Machek <pavel@ucw.cz>
-Signed-off-by: Pavel Machek <pavel@ucw.cz>
-Co-developed-by: Dennis Bonke <admin@dennisbonke.com>
-Signed-off-by: Dennis Bonke <admin@dennisbonke.com>
-Co-developed-by: Marttico <g.martti@gmail.com>
-Signed-off-by: Marttico <g.martti@gmail.com>
-Co-developed-by: Toon Langendam <t.langendam@gmail.com>
-Signed-off-by: Toon Langendam <t.langendam@gmail.com>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- include/libcamera/internal/meson.build        |   1 +
- .../internal/software_isp/meson.build         |   5 +
- .../internal/software_isp/swisp_stats.h       |  38 ++++
- src/libcamera/meson.build                     |   1 +
- src/libcamera/software_isp/meson.build        |  12 +
- src/libcamera/software_isp/swstats_cpu.cpp    | 208 ++++++++++++++++++
- src/libcamera/software_isp/swstats_cpu.h      | 159 +++++++++++++
- 7 files changed, 424 insertions(+)
- create mode 100644 include/libcamera/internal/software_isp/meson.build
- create mode 100644 include/libcamera/internal/software_isp/swisp_stats.h
- create mode 100644 src/libcamera/software_isp/meson.build
- create mode 100644 src/libcamera/software_isp/swstats_cpu.cpp
- create mode 100644 src/libcamera/software_isp/swstats_cpu.h
-
-diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
-index 5807dfd9..160fdc37 100644
---- a/include/libcamera/internal/meson.build
-+++ b/include/libcamera/internal/meson.build
-@@ -50,3 +50,4 @@ libcamera_internal_headers = files([
- ])
- 
- subdir('converter')
-+subdir('software_isp')
-diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build
-new file mode 100644
-index 00000000..66c9c3fb
---- /dev/null
-+++ b/include/libcamera/internal/software_isp/meson.build
-@@ -0,0 +1,5 @@
-+# SPDX-License-Identifier: CC0-1.0
-+
-+libcamera_internal_headers += files([
-+    'swisp_stats.h',
-+])
-diff --git a/include/libcamera/internal/software_isp/swisp_stats.h b/include/libcamera/internal/software_isp/swisp_stats.h
-new file mode 100644
-index 00000000..afe42c9a
---- /dev/null
-+++ b/include/libcamera/internal/software_isp/swisp_stats.h
-@@ -0,0 +1,38 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2023, Linaro Ltd
-+ *
-+ * swisp_stats.h - Statistics data format used by the software ISP and software IPA
-+ */
-+
-+#pragma once
-+
-+namespace libcamera {
-+
-+/**
-+ * \brief Struct that holds the statistics for the Software ISP.
-+ */
-+struct SwIspStats {
-+	/**
-+	 * \brief Holds the sum of all sampled red pixels.
-+	 */
-+	unsigned long sumR_;
-+	/**
-+	 * \brief Holds the sum of all sampled green pixels.
-+	 */
-+	unsigned long sumG_;
-+	/**
-+	 * \brief Holds the sum of all sampled blue pixels.
-+	 */
-+	unsigned long sumB_;
-+	/**
-+	 * \brief Number of bins in the yHistogram.
-+	 */
-+	static constexpr unsigned int kYHistogramSize = 16;
-+	/**
-+	 * \brief A histogram of luminance values.
-+	 */
-+	std::array<unsigned int, kYHistogramSize> yHistogram;
-+};
-+
-+} /* namespace libcamera */
-diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
-index 94a95ae3..91e4cc60 100644
---- a/src/libcamera/meson.build
-+++ b/src/libcamera/meson.build
-@@ -71,6 +71,7 @@ subdir('converter')
- subdir('ipa')
- subdir('pipeline')
- subdir('proxy')
-+subdir('software_isp')
- 
- null_dep = dependency('', required : false)
- 
-diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build
-new file mode 100644
-index 00000000..fcfff74a
---- /dev/null
-+++ b/src/libcamera/software_isp/meson.build
-@@ -0,0 +1,12 @@
-+# SPDX-License-Identifier: CC0-1.0
-+
-+softisp_enabled = pipelines.contains('simple')
-+summary({'SoftISP support' : softisp_enabled}, section : 'Configuration')
-+
-+if not (softisp_enabled)
-+    subdir_done()
-+endif
-+
-+libcamera_sources += files([
-+    'swstats_cpu.cpp',
-+])
-diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp
-new file mode 100644
-index 00000000..448d0e4c
---- /dev/null
-+++ b/src/libcamera/software_isp/swstats_cpu.cpp
-@@ -0,0 +1,208 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2023, Linaro Ltd
-+ * Copyright (C) 2023, Red Hat Inc.
-+ *
-+ * Authors:
-+ * Hans de Goede <hdegoede@redhat.com>
-+ *
-+ * swstats_cpu.cpp - CPU based software statistics implementation
-+ */
-+
-+#include "swstats_cpu.h"
-+
-+#include <libcamera/base/log.h>
-+
-+#include <libcamera/stream.h>
-+
-+#include "libcamera/internal/bayer_format.h"
-+
-+namespace libcamera {
-+
-+/**
-+ * \class SwStatsCpu
-+ * \brief Class for gathering statistics on the CPU
-+ *
-+ * CPU based software ISP statistics implementation.
-+ *
-+ * This class offers a configure function + functions to gather statistics
-+ * on a line by line basis. This allows CPU based software debayering to
-+ * interlace debayering and statistics gathering on a line by line basis
-+ * while the input data is still hot in the cache.
-+ *
-+ * It is also possible to specify a window over which to gather
-+ * statistics instead of processing the whole frame.
-+ */
-+
-+LOG_DEFINE_CATEGORY(SwStatsCpu)
-+
-+SwStatsCpu::SwStatsCpu()
-+{
-+	sharedStats_ = SharedMemObject<SwIspStats>("softIsp_stats");
-+	if (!sharedStats_.fd().isValid())
-+		LOG(SwStatsCpu, Error)
-+			<< "Failed to create shared memory for statistics";
-+}
-+
-+static const unsigned int kRedYMul = 77; /* 0.299 * 256 */
-+static const unsigned int kGreenYMul = 150; /* 0.587 * 256 */
-+static const unsigned int kBlueYMul = 29; /* 0.114 * 256 */
-+
-+#define SWSTATS_START_LINE_STATS(pixel_t) \
-+	pixel_t r, g, g2, b;              \
-+	unsigned int yVal;                \
-+                                          \
-+	unsigned int sumR = 0;            \
-+	unsigned int sumG = 0;            \
-+	unsigned int sumB = 0;
-+
-+#define SWSTATS_ACCUMULATE_LINE_STATS(div) \
-+	sumR += r;                         \
-+	sumG += g;                         \
-+	sumB += b;                         \
-+                                           \
-+	yVal = r * kRedYMul;               \
-+	yVal += g * kGreenYMul;            \
-+	yVal += b * kBlueYMul;             \
-+	stats_.yHistogram[yVal * SwIspStats::kYHistogramSize / (256 * 256 * (div))]++;
-+
-+#define SWSTATS_FINISH_LINE_STATS() \
-+	stats_.sumR_ += sumR;       \
-+	stats_.sumG_ += sumG;       \
-+	stats_.sumB_ += sumB;
-+
-+void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src[])
-+{
-+	const uint8_t *src0 = src[1] + window_.x * 5 / 4;
-+	const uint8_t *src1 = src[2] + window_.x * 5 / 4;
-+	const int widthInBytes = window_.width * 5 / 4;
-+
-+	if (swapLines_)
-+		std::swap(src0, src1);
-+
-+	SWSTATS_START_LINE_STATS(uint8_t)
-+
-+	/* x += 5 sample every other 2x2 block */
-+	for (int x = 0; x < widthInBytes; x += 5) {
-+		/* BGGR */
-+		b = src0[x];
-+		g = src0[x + 1];
-+		g2 = src1[x];
-+		r = src1[x + 1];
-+		g = (g + g2) / 2;
-+		/* Data is already 8 bits, divide by 1 */
-+		SWSTATS_ACCUMULATE_LINE_STATS(1)
-+	}
-+
-+	SWSTATS_FINISH_LINE_STATS()
-+}
-+
-+void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src[])
-+{
-+	const uint8_t *src0 = src[1] + window_.x * 5 / 4;
-+	const uint8_t *src1 = src[2] + window_.x * 5 / 4;
-+	const int widthInBytes = window_.width * 5 / 4;
-+
-+	if (swapLines_)
-+		std::swap(src0, src1);
-+
-+	SWSTATS_START_LINE_STATS(uint8_t)
-+
-+	/* x += 5 sample every other 2x2 block */
-+	for (int x = 0; x < widthInBytes; x += 5) {
-+		/* GBRG */
-+		g = src0[x];
-+		b = src0[x + 1];
-+		r = src1[x];
-+		g2 = src1[x + 1];
-+		g = (g + g2) / 2;
-+		/* Data is already 8 bits, divide by 1 */
-+		SWSTATS_ACCUMULATE_LINE_STATS(1)
-+	}
-+
-+	SWSTATS_FINISH_LINE_STATS()
-+}
-+
-+/**
-+ * \brief Reset state to start statistics gathering for a new frame.
-+ *
-+ * This may only be called after a successful setWindow() call.
-+ */
-+void SwStatsCpu::startFrame(void)
-+{
-+	stats_.sumR_ = 0;
-+	stats_.sumB_ = 0;
-+	stats_.sumG_ = 0;
-+	stats_.yHistogram.fill(0);
-+}
-+
-+/**
-+ * \brief Finish statistics calculation for the current frame.
-+ *
-+ * This may only be called after a successful setWindow() call.
-+ */
-+void SwStatsCpu::finishFrame(void)
-+{
-+	*sharedStats_ = stats_;
-+	statsReady.emit(0);
-+}
-+
-+/**
-+ * \brief Configure the statistics object for the passed in input format.
-+ * \param[in] inputCfg The input format
-+ *
-+ * \return 0 on success, a negative errno value on failure
-+ */
-+int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
-+{
-+	BayerFormat bayerFormat =
-+		BayerFormat::fromPixelFormat(inputCfg.pixelFormat);
-+
-+	if (bayerFormat.bitDepth == 10 &&
-+	    bayerFormat.packing == BayerFormat::Packing::CSI2) {
-+		patternSize_.height = 2;
-+		patternSize_.width = 4; /* 5 bytes per *4* pixels */
-+		/* Skip every 3th and 4th line, sample every other 2x2 block */
-+		ySkipMask_ = 0x02;
-+		xShift_ = 0;
-+
-+		switch (bayerFormat.order) {
-+		case BayerFormat::BGGR:
-+		case BayerFormat::GRBG:
-+			stats0_ = &SwStatsCpu::statsBGGR10PLine0;
-+			swapLines_ = bayerFormat.order == BayerFormat::GRBG;
-+			return 0;
-+		case BayerFormat::GBRG:
-+		case BayerFormat::RGGB:
-+			stats0_ = &SwStatsCpu::statsGBRG10PLine0;
-+			swapLines_ = bayerFormat.order == BayerFormat::RGGB;
-+			return 0;
-+		default:
-+			break;
-+		}
-+	}
-+
-+	LOG(SwStatsCpu, Info)
-+		<< "Unsupported input format " << inputCfg.pixelFormat.toString();
-+	return -EINVAL;
-+}
-+
-+/**
-+ * \brief Specify window coordinates over which to gather statistics.
-+ * \param[in] window The window object.
-+ */
-+void SwStatsCpu::setWindow(Rectangle window)
-+{
-+	window_ = window;
-+
-+	window_.x &= ~(patternSize_.width - 1);
-+	window_.x += xShift_;
-+	window_.y &= ~(patternSize_.height - 1);
-+
-+	/* width_ - xShift_ to make sure the window fits */
-+	window_.width -= xShift_;
-+	window_.width &= ~(patternSize_.width - 1);
-+	window_.height &= ~(patternSize_.height - 1);
-+}
-+
-+} /* namespace libcamera */
-diff --git a/src/libcamera/software_isp/swstats_cpu.h b/src/libcamera/software_isp/swstats_cpu.h
-new file mode 100644
-index 00000000..0ac9ae71
---- /dev/null
-+++ b/src/libcamera/software_isp/swstats_cpu.h
-@@ -0,0 +1,159 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2023, Linaro Ltd
-+ * Copyright (C) 2023, Red Hat Inc.
-+ *
-+ * Authors:
-+ * Hans de Goede <hdegoede@redhat.com>
-+ *
-+ * swstats_cpu.h - CPU based software statistics implementation
-+ */
-+
-+#pragma once
-+
-+#include <stdint.h>
-+
-+#include <libcamera/base/signal.h>
-+
-+#include <libcamera/geometry.h>
-+
-+#include "libcamera/internal/shared_mem_object.h"
-+#include "libcamera/internal/software_isp/swisp_stats.h"
-+
-+namespace libcamera {
-+
-+class PixelFormat;
-+struct StreamConfiguration;
-+
-+class SwStatsCpu
-+{
-+public:
-+	SwStatsCpu();
-+	~SwStatsCpu() = default;
-+
-+	/**
-+	 * \brief Gets whether the statistics object is valid.
-+	 *
-+	 * \return true if it's valid, false otherwise
-+	 */
-+	bool isValid() const { return sharedStats_.fd().isValid(); }
-+
-+	/**
-+	 * \brief Get the file descriptor for the statistics.
-+	 *
-+	 * \return the file descriptor
-+	 */
-+	const SharedFD &getStatsFD() { return sharedStats_.fd(); }
-+
-+	/**
-+	 * \brief Get the pattern size.
-+	 *
-+	 * For some input-formats, e.g. Bayer data, processing is done multiple lines
-+	 * and/or columns at a time. Get width and height at which the (bayer) pattern
-+	 * repeats. Window values are rounded down to a multiple of this and the height
-+	 * also indicates if processLine2() should be called or not.
-+	 * This may only be called after a successful configure() call.
-+	 *
-+	 * \return the pattern size
-+	 */
-+	const Size &patternSize() { return patternSize_; }
-+
-+	int configure(const StreamConfiguration &inputCfg);
-+	void setWindow(Rectangle window);
-+	void startFrame();
-+	void finishFrame();
-+
-+	/**
-+	 * \brief Process line 0.
-+	 * \param[in] y The y coordinate.
-+	 * \param[in] src The input data.
-+	 *
-+	 * This function processes line 0 for input formats with patternSize height == 1.
-+	 * It'll process line 0 and 1 for input formats with patternSize height >= 2.
-+	 * This function may only be called after a successful setWindow() call.
-+	 */
-+	void processLine0(unsigned int y, const uint8_t *src[])
-+	{
-+		if ((y & ySkipMask_) || y < (unsigned int)window_.y ||
-+		    y >= (window_.y + window_.height))
-+			return;
-+
-+		(this->*stats0_)(src);
-+	}
-+
-+	/**
-+	 * \brief Process line 2 and 3.
-+	 * \param[in] y The y coordinate.
-+	 * \param[in] src The input data.
-+	 *
-+	 * This function processes line 2 and 3 for input formats with patternSize height == 4.
-+	 * This function may only be called after a successful setWindow() call.
-+	 */
-+	void processLine2(unsigned int y, const uint8_t *src[])
-+	{
-+		if ((y & ySkipMask_) || y < (unsigned int)window_.y ||
-+		    y >= (window_.y + window_.height))
-+			return;
-+
-+		(this->*stats2_)(src);
-+	}
-+
-+	/**
-+	 * \brief Signals that the statistics are ready.
-+	 *
-+	 * The int parameter isn't actually used.
-+	 */
-+	Signal<int> statsReady;
-+
-+private:
-+	/**
-+	 * \brief Called when there is data to get statistics from.
-+	 * \param[in] src The input data
-+	 *
-+	 * These functions take an array of (patternSize_.height + 1) src
-+	 * pointers each pointing to a line in the source image. The middle
-+	 * element of the array will point to the actual line being processed.
-+	 * Earlier element(s) will point to the previous line(s) and later
-+	 * element(s) to the next line(s).
-+	 *
-+	 * See the documentation of DebayerCpu::debayerFn for more details.
-+	 */
-+	using statsProcessFn = void (SwStatsCpu::*)(const uint8_t *src[]);
-+
-+	void statsBGGR10PLine0(const uint8_t *src[]);
-+	void statsGBRG10PLine0(const uint8_t *src[]);
-+
-+	/* Variables set by configure(), used every line */
-+	statsProcessFn stats0_;
-+	statsProcessFn stats2_;
-+	bool swapLines_;
-+
-+	/**
-+	 * \brief Skip lines where this bitmask is set in y.
-+	 */
-+	unsigned int ySkipMask_;
-+
-+	/**
-+	 * \brief Statistics window, set by setWindow(), used ever line.
-+	 */
-+	Rectangle window_;
-+
-+	/**
-+	 * \brief The size of the bayer pattern.
-+	 *
-+	 * Valid sizes are: 2x2, 4x2 or 4x4.
-+	 */
-+	Size patternSize_;
-+
-+	/**
-+	 * \brief The offset of x, applied to window_.x for bayer variants.
-+	 *
-+	 * This can either be 0 or 1.
-+	 */
-+	unsigned int xShift_;
-+
-+	SharedMemObject<SwIspStats> sharedStats_;
-+	SwIspStats stats_;
-+};
-+
-+} /* namespace libcamera */
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0007-libcamera-software_isp-Add-Debayer-base-class.patch b/users/flokli/ipu6-softisp/libcamera/0007-libcamera-software_isp-Add-Debayer-base-class.patch
deleted file mode 100644
index 7c7170989666..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0007-libcamera-software_isp-Add-Debayer-base-class.patch
+++ /dev/null
@@ -1,255 +0,0 @@
-From 25e6893e46bd2174f6913eea79817988d9280706 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Mon, 11 Mar 2024 15:15:11 +0100
-Subject: [PATCH 07/21] libcamera: software_isp: Add Debayer base class
-
-Add a base class for debayer implementations. This is intended to be
-suitable for both GPU (or otherwise) accelerated debayer implementations
-as well as CPU based debayering.
-
-Doxygen documentation by Dennis Bonke.
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
-Co-developed-by: Dennis Bonke <admin@dennisbonke.com>
-Signed-off-by: Dennis Bonke <admin@dennisbonke.com>
-Co-developed-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- .../internal/software_isp/debayer_params.h    |  48 ++++++++
- .../internal/software_isp/meson.build         |   1 +
- src/libcamera/software_isp/debayer.cpp        |  29 +++++
- src/libcamera/software_isp/debayer.h          | 104 ++++++++++++++++++
- src/libcamera/software_isp/meson.build        |   1 +
- 5 files changed, 183 insertions(+)
- create mode 100644 include/libcamera/internal/software_isp/debayer_params.h
- create mode 100644 src/libcamera/software_isp/debayer.cpp
- create mode 100644 src/libcamera/software_isp/debayer.h
-
-diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h
-new file mode 100644
-index 00000000..98965fa1
---- /dev/null
-+++ b/include/libcamera/internal/software_isp/debayer_params.h
-@@ -0,0 +1,48 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2023, Red Hat Inc.
-+ *
-+ * Authors:
-+ * Hans de Goede <hdegoede@redhat.com>
-+ *
-+ * debayer_params.h - DebayerParams header
-+ */
-+
-+#pragma once
-+
-+namespace libcamera {
-+
-+/**
-+ * \brief Struct to hold the debayer parameters.
-+ */
-+struct DebayerParams {
-+	/**
-+	 * \brief const value for 1.0 gain
-+	 */
-+	static constexpr unsigned int kGain10 = 256;
-+
-+	/**
-+	 * \brief Red Gain
-+	 *
-+	 * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.
-+	 */
-+	unsigned int gainR;
-+	/**
-+	 * \brief Green Gain
-+	 *
-+	 * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.
-+	 */
-+	unsigned int gainG;
-+	/**
-+	 * \brief Blue Gain
-+	 *
-+	 * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.
-+	 */
-+	unsigned int gainB;
-+	/**
-+	 * \brief Gamma correction, 1.0 is no correction
-+	 */
-+	float gamma;
-+};
-+
-+} /* namespace libcamera */
-diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build
-index 66c9c3fb..a620e16d 100644
---- a/include/libcamera/internal/software_isp/meson.build
-+++ b/include/libcamera/internal/software_isp/meson.build
-@@ -1,5 +1,6 @@
- # SPDX-License-Identifier: CC0-1.0
- 
- libcamera_internal_headers += files([
-+    'debayer_params.h',
-     'swisp_stats.h',
- ])
-diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp
-new file mode 100644
-index 00000000..64f0b5a0
---- /dev/null
-+++ b/src/libcamera/software_isp/debayer.cpp
-@@ -0,0 +1,29 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2023, Linaro Ltd
-+ * Copyright (C) 2023, Red Hat Inc.
-+ *
-+ * Authors:
-+ * Hans de Goede <hdegoede@redhat.com>
-+ *
-+ * debayer.cpp - debayer base class
-+ */
-+
-+#include "debayer.h"
-+
-+namespace libcamera {
-+
-+/**
-+ * \class Debayer
-+ * \brief Base debayering class
-+ *
-+ * Base class that provides functions for setting up the debayering process.
-+ */
-+
-+LOG_DEFINE_CATEGORY(Debayer)
-+
-+Debayer::~Debayer()
-+{
-+}
-+
-+} /* namespace libcamera */
-diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h
-new file mode 100644
-index 00000000..8880ff99
---- /dev/null
-+++ b/src/libcamera/software_isp/debayer.h
-@@ -0,0 +1,104 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2023, Linaro Ltd
-+ * Copyright (C) 2023, Red Hat Inc.
-+ *
-+ * Authors:
-+ * Hans de Goede <hdegoede@redhat.com>
-+ *
-+ * debayer.h - debayering base class
-+ */
-+
-+#pragma once
-+
-+#include <stdint.h>
-+
-+#include <libcamera/base/log.h>
-+#include <libcamera/base/signal.h>
-+
-+#include <libcamera/geometry.h>
-+#include <libcamera/stream.h>
-+
-+#include "libcamera/internal/software_isp/debayer_params.h"
-+
-+namespace libcamera {
-+
-+class FrameBuffer;
-+
-+LOG_DECLARE_CATEGORY(Debayer)
-+
-+class Debayer
-+{
-+public:
-+	virtual ~Debayer() = 0;
-+
-+	/**
-+	 * \brief Configure the debayer object according to the passed in parameters.
-+	 * \param[in] inputCfg The input configuration.
-+	 * \param[in] outputCfgs The output configurations.
-+	 *
-+	 * \return 0 on success, a negative errno on failure.
-+	 */
-+	virtual int configure(const StreamConfiguration &inputCfg,
-+			      const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs) = 0;
-+
-+	/**
-+	 * \brief Get the width and height at which the bayer pattern repeats.
-+	 * \param[in] inputFormat The input format.
-+	 *
-+	 * Valid sizes are: 2x2, 4x2 or 4x4.
-+	 *
-+	 * \return pattern size or an empty size for unsupported inputFormats.
-+	 */
-+	virtual Size patternSize(PixelFormat inputFormat) = 0;
-+
-+	/**
-+	 * \brief Get the supported output formats.
-+	 * \param[in] inputFormat The input format.
-+	 *
-+	 * \return all supported output formats or an empty vector if there are none.
-+	 */
-+	virtual std::vector<PixelFormat> formats(PixelFormat inputFormat) = 0;
-+
-+	/**
-+	 * \brief Get the stride and the frame size.
-+	 * \param[in] outputFormat The output format.
-+	 * \param[in] size The output size.
-+	 *
-+	 * \return a tuple of the stride and the frame size, or a tuple with 0,0 if there is no valid output config.
-+	 */
-+	virtual std::tuple<unsigned int, unsigned int>
-+	strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) = 0;
-+
-+	/**
-+	 * \brief Process the bayer data into the requested format.
-+	 * \param[in] input The input buffer.
-+	 * \param[in] output The output buffer.
-+	 * \param[in] params The parameters to be used in debayering.
-+	 *
-+	 * \note DebayerParams is passed by value deliberately so that a copy is passed
-+	 * when this is run in another thread by invokeMethod().
-+	 */
-+	virtual void process(FrameBuffer *input, FrameBuffer *output, DebayerParams params) = 0;
-+
-+	/**
-+	 * \brief Get the supported output sizes for the given input format and size.
-+	 * \param[in] inputFormat The input format.
-+	 * \param[in] inputSize The input size.
-+	 *
-+	 * \return The valid size ranges or an empty range if there are none.
-+	 */
-+	virtual SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) = 0;
-+
-+	/**
-+	 * \brief Signals when the input buffer is ready.
-+	 */
-+	Signal<FrameBuffer *> inputBufferReady;
-+
-+	/**
-+	 * \brief Signals when the output buffer is ready.
-+	 */
-+	Signal<FrameBuffer *> outputBufferReady;
-+};
-+
-+} /* namespace libcamera */
-diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build
-index fcfff74a..62095f61 100644
---- a/src/libcamera/software_isp/meson.build
-+++ b/src/libcamera/software_isp/meson.build
-@@ -8,5 +8,6 @@ if not (softisp_enabled)
- endif
- 
- libcamera_sources += files([
-+    'debayer.cpp',
-     'swstats_cpu.cpp',
- ])
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0008-libcamera-software_isp-Add-DebayerCpu-class.patch b/users/flokli/ipu6-softisp/libcamera/0008-libcamera-software_isp-Add-DebayerCpu-class.patch
deleted file mode 100644
index f549769f2fde..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0008-libcamera-software_isp-Add-DebayerCpu-class.patch
+++ /dev/null
@@ -1,825 +0,0 @@
-From 5f57a52ea1054cac73344d83ff605cba0df0d279 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Mon, 11 Mar 2024 15:15:12 +0100
-Subject: [PATCH 08/21] libcamera: software_isp: Add DebayerCpu class
-
-Add CPU based debayering implementation. This initial implementation
-only supports debayering packed 10 bits per pixel bayer data in
-the 4 standard bayer orders.
-
-Doxygen documentation by Dennis Bonke.
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Co-developed-by: Dennis Bonke <admin@dennisbonke.com>
-Signed-off-by: Dennis Bonke <admin@dennisbonke.com>
-Co-developed-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Co-developed-by: Pavel Machek <pavel@ucw.cz>
-Signed-off-by: Pavel Machek <pavel@ucw.cz>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
----
- src/libcamera/software_isp/debayer_cpu.cpp | 626 +++++++++++++++++++++
- src/libcamera/software_isp/debayer_cpu.h   | 143 +++++
- src/libcamera/software_isp/meson.build     |   1 +
- 3 files changed, 770 insertions(+)
- create mode 100644 src/libcamera/software_isp/debayer_cpu.cpp
- create mode 100644 src/libcamera/software_isp/debayer_cpu.h
-
-diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
-new file mode 100644
-index 00000000..f932362c
---- /dev/null
-+++ b/src/libcamera/software_isp/debayer_cpu.cpp
-@@ -0,0 +1,626 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2023, Linaro Ltd
-+ * Copyright (C) 2023, Red Hat Inc.
-+ *
-+ * Authors:
-+ * Hans de Goede <hdegoede@redhat.com>
-+ *
-+ * debayer_cpu.cpp - CPU based debayering class
-+ */
-+
-+#include "debayer_cpu.h"
-+
-+#include <math.h>
-+#include <stdlib.h>
-+#include <time.h>
-+
-+#include <libcamera/formats.h>
-+
-+#include "libcamera/internal/bayer_format.h"
-+#include "libcamera/internal/framebuffer.h"
-+#include "libcamera/internal/mapped_framebuffer.h"
-+
-+namespace libcamera {
-+
-+/**
-+ * \class DebayerCpu
-+ * \brief Class for debayering on the CPU
-+ *
-+ * Implementation for CPU based debayering
-+ */
-+
-+/**
-+ * \brief Constructs a DebayerCpu object.
-+ * \param[in] stats Pointer to the stats object to use.
-+ */
-+DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats)
-+	: stats_(std::move(stats)), gamma_correction_(1.0)
-+{
-+#ifdef __x86_64__
-+	enableInputMemcpy_ = false;
-+#else
-+	enableInputMemcpy_ = true;
-+#endif
-+	/* Initialize gamma to 1.0 curve */
-+	for (unsigned int i = 0; i < kGammaLookupSize; i++)
-+		gamma_[i] = i / (kGammaLookupSize / kRGBLookupSize);
-+
-+	for (unsigned int i = 0; i < kMaxLineBuffers; i++)
-+		lineBuffers_[i] = nullptr;
-+}
-+
-+DebayerCpu::~DebayerCpu()
-+{
-+	for (unsigned int i = 0; i < kMaxLineBuffers; i++)
-+		free(lineBuffers_[i]);
-+}
-+
-+// RGR
-+// GBG
-+// RGR
-+#define BGGR_BGR888(p, n, div)                                                                \
-+	*dst++ = blue_[curr[x] / (div)];                                                      \
-+	*dst++ = green_[(prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div))];       \
-+	*dst++ = red_[(prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div))]; \
-+	x++;
-+
-+// GBG
-+// RGR
-+// GBG
-+#define GRBG_BGR888(p, n, div)                                    \
-+	*dst++ = blue_[(prev[x] + next[x]) / (2 * (div))];        \
-+	*dst++ = green_[curr[x] / (div)];                         \
-+	*dst++ = red_[(curr[x - p] + curr[x + n]) / (2 * (div))]; \
-+	x++;
-+
-+// GRG
-+// BGB
-+// GRG
-+#define GBRG_BGR888(p, n, div)                                     \
-+	*dst++ = blue_[(curr[x - p] + curr[x + n]) / (2 * (div))]; \
-+	*dst++ = green_[curr[x] / (div)];                          \
-+	*dst++ = red_[(prev[x] + next[x]) / (2 * (div))];          \
-+	x++;
-+
-+// BGB
-+// GRG
-+// BGB
-+#define RGGB_BGR888(p, n, div)                                                                 \
-+	*dst++ = blue_[(prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div))]; \
-+	*dst++ = green_[(prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div))];        \
-+	*dst++ = red_[curr[x] / (div)];                                                        \
-+	x++;
-+
-+void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
-+{
-+	const int width_in_bytes = window_.width * 5 / 4;
-+	const uint8_t *prev = (const uint8_t *)src[0];
-+	const uint8_t *curr = (const uint8_t *)src[1];
-+	const uint8_t *next = (const uint8_t *)src[2];
-+
-+	/*
-+	 * For the first pixel getting a pixel from the previous column uses
-+	 * x - 2 to skip the 5th byte with least-significant bits for 4 pixels.
-+	 * Same for last pixel (uses x + 2) and looking at the next column.
-+	 */
-+	for (int x = 0; x < width_in_bytes;) {
-+		/* First pixel */
-+		BGGR_BGR888(2, 1, 1)
-+		/* Second pixel BGGR -> GBRG */
-+		GBRG_BGR888(1, 1, 1)
-+		/* Same thing for third and fourth pixels */
-+		BGGR_BGR888(1, 1, 1)
-+		GBRG_BGR888(1, 2, 1)
-+		/* Skip 5th src byte with 4 x 2 least-significant-bits */
-+		x++;
-+	}
-+}
-+
-+void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
-+{
-+	const int width_in_bytes = window_.width * 5 / 4;
-+	const uint8_t *prev = (const uint8_t *)src[0];
-+	const uint8_t *curr = (const uint8_t *)src[1];
-+	const uint8_t *next = (const uint8_t *)src[2];
-+
-+	for (int x = 0; x < width_in_bytes;) {
-+		/* First pixel */
-+		GRBG_BGR888(2, 1, 1)
-+		/* Second pixel GRBG -> RGGB */
-+		RGGB_BGR888(1, 1, 1)
-+		/* Same thing for third and fourth pixels */
-+		GRBG_BGR888(1, 1, 1)
-+		RGGB_BGR888(1, 2, 1)
-+		/* Skip 5th src byte with 4 x 2 least-significant-bits */
-+		x++;
-+	}
-+}
-+
-+void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[])
-+{
-+	const int width_in_bytes = window_.width * 5 / 4;
-+	const uint8_t *prev = (const uint8_t *)src[0];
-+	const uint8_t *curr = (const uint8_t *)src[1];
-+	const uint8_t *next = (const uint8_t *)src[2];
-+
-+	for (int x = 0; x < width_in_bytes;) {
-+		/* Even pixel */
-+		GBRG_BGR888(2, 1, 1)
-+		/* Odd pixel GBGR -> BGGR */
-+		BGGR_BGR888(1, 1, 1)
-+		/* Same thing for next 2 pixels */
-+		GBRG_BGR888(1, 1, 1)
-+		BGGR_BGR888(1, 2, 1)
-+		/* Skip 5th src byte with 4 x 2 least-significant-bits */
-+		x++;
-+	}
-+}
-+
-+void DebayerCpu::debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[])
-+{
-+	const int width_in_bytes = window_.width * 5 / 4;
-+	const uint8_t *prev = (const uint8_t *)src[0];
-+	const uint8_t *curr = (const uint8_t *)src[1];
-+	const uint8_t *next = (const uint8_t *)src[2];
-+
-+	for (int x = 0; x < width_in_bytes;) {
-+		/* Even pixel */
-+		RGGB_BGR888(2, 1, 1)
-+		/* Odd pixel RGGB -> GRBG */
-+		GRBG_BGR888(1, 1, 1)
-+		/* Same thing for next 2 pixels */
-+		RGGB_BGR888(1, 1, 1)
-+		GRBG_BGR888(1, 2, 1)
-+		/* Skip 5th src byte with 4 x 2 least-significant-bits */
-+		x++;
-+	}
-+}
-+
-+static bool isStandardBayerOrder(BayerFormat::Order order)
-+{
-+	return order == BayerFormat::BGGR || order == BayerFormat::GBRG ||
-+	       order == BayerFormat::GRBG || order == BayerFormat::RGGB;
-+}
-+
-+/*
-+ * Setup the Debayer object according to the passed in parameters.
-+ * Return 0 on success, a negative errno value on failure
-+ * (unsupported parameters).
-+ */
-+int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config)
-+{
-+	BayerFormat bayerFormat =
-+		BayerFormat::fromPixelFormat(inputFormat);
-+
-+	if (bayerFormat.bitDepth == 10 &&
-+	    bayerFormat.packing == BayerFormat::Packing::CSI2 &&
-+	    isStandardBayerOrder(bayerFormat.order)) {
-+		config.bpp = 10;
-+		config.patternSize.width = 4; /* 5 bytes per *4* pixels */
-+		config.patternSize.height = 2;
-+		config.outputFormats = std::vector<PixelFormat>({ formats::RGB888 });
-+		return 0;
-+	}
-+
-+	LOG(Debayer, Info)
-+		<< "Unsupported input format " << inputFormat.toString();
-+	return -EINVAL;
-+}
-+
-+int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config)
-+{
-+	if (outputFormat == formats::RGB888) {
-+		config.bpp = 24;
-+		return 0;
-+	}
-+
-+	LOG(Debayer, Info)
-+		<< "Unsupported output format " << outputFormat.toString();
-+	return -EINVAL;
-+}
-+
-+/* TODO: this ignores outputFormat since there is only 1 supported outputFormat for now */
-+int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] PixelFormat outputFormat)
-+{
-+	BayerFormat bayerFormat =
-+		BayerFormat::fromPixelFormat(inputFormat);
-+
-+	if (bayerFormat.bitDepth == 10 &&
-+	    bayerFormat.packing == BayerFormat::Packing::CSI2) {
-+		switch (bayerFormat.order) {
-+		case BayerFormat::BGGR:
-+			debayer0_ = &DebayerCpu::debayer10P_BGBG_BGR888;
-+			debayer1_ = &DebayerCpu::debayer10P_GRGR_BGR888;
-+			return 0;
-+		case BayerFormat::GBRG:
-+			debayer0_ = &DebayerCpu::debayer10P_GBGB_BGR888;
-+			debayer1_ = &DebayerCpu::debayer10P_RGRG_BGR888;
-+			return 0;
-+		case BayerFormat::GRBG:
-+			debayer0_ = &DebayerCpu::debayer10P_GRGR_BGR888;
-+			debayer1_ = &DebayerCpu::debayer10P_BGBG_BGR888;
-+			return 0;
-+		case BayerFormat::RGGB:
-+			debayer0_ = &DebayerCpu::debayer10P_RGRG_BGR888;
-+			debayer1_ = &DebayerCpu::debayer10P_GBGB_BGR888;
-+			return 0;
-+		default:
-+			break;
-+		}
-+	}
-+
-+	LOG(Debayer, Error) << "Unsupported input output format combination";
-+	return -EINVAL;
-+}
-+
-+int DebayerCpu::configure(const StreamConfiguration &inputCfg,
-+			  const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs)
-+{
-+	if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0)
-+		return -EINVAL;
-+
-+	if (stats_->configure(inputCfg) != 0)
-+		return -EINVAL;
-+
-+	const Size &stats_pattern_size = stats_->patternSize();
-+	if (inputConfig_.patternSize.width != stats_pattern_size.width ||
-+	    inputConfig_.patternSize.height != stats_pattern_size.height) {
-+		LOG(Debayer, Error)
-+			<< "mismatching stats and debayer pattern sizes for "
-+			<< inputCfg.pixelFormat.toString();
-+		return -EINVAL;
-+	}
-+
-+	inputConfig_.stride = inputCfg.stride;
-+
-+	if (outputCfgs.size() != 1) {
-+		LOG(Debayer, Error)
-+			<< "Unsupported number of output streams: "
-+			<< outputCfgs.size();
-+		return -EINVAL;
-+	}
-+
-+	const StreamConfiguration &outputCfg = outputCfgs[0];
-+	SizeRange outSizeRange = sizes(inputCfg.pixelFormat, inputCfg.size);
-+	std::tie(outputConfig_.stride, outputConfig_.frameSize) =
-+		strideAndFrameSize(outputCfg.pixelFormat, outputCfg.size);
-+
-+	if (!outSizeRange.contains(outputCfg.size) || outputConfig_.stride != outputCfg.stride) {
-+		LOG(Debayer, Error)
-+			<< "Invalid output size/stride: "
-+			<< "\n  " << outputCfg.size << " (" << outSizeRange << ")"
-+			<< "\n  " << outputCfg.stride << " (" << outputConfig_.stride << ")";
-+		return -EINVAL;
-+	}
-+
-+	if (setDebayerFunctions(inputCfg.pixelFormat, outputCfg.pixelFormat) != 0)
-+		return -EINVAL;
-+
-+	window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) &
-+		    ~(inputConfig_.patternSize.width - 1);
-+	window_.y = ((inputCfg.size.height - outputCfg.size.height) / 2) &
-+		    ~(inputConfig_.patternSize.height - 1);
-+	window_.width = outputCfg.size.width;
-+	window_.height = outputCfg.size.height;
-+
-+	/* Don't pass x,y since process() already adjusts src before passing it */
-+	stats_->setWindow(Rectangle(window_.size()));
-+
-+	/* pad with patternSize.Width on both left and right side */
-+	lineBufferPadding_ = inputConfig_.patternSize.width * inputConfig_.bpp / 8;
-+	lineBufferLength_ = window_.width * inputConfig_.bpp / 8 +
-+			    2 * lineBufferPadding_;
-+	for (unsigned int i = 0;
-+	     i < (inputConfig_.patternSize.height + 1) && enableInputMemcpy_;
-+	     i++) {
-+		free(lineBuffers_[i]);
-+		lineBuffers_[i] = (uint8_t *)malloc(lineBufferLength_);
-+		if (!lineBuffers_[i])
-+			return -ENOMEM;
-+	}
-+
-+	measuredFrames_ = 0;
-+	frameProcessTime_ = 0;
-+
-+	return 0;
-+}
-+
-+/*
-+ * Get width and height at which the bayer-pattern repeats.
-+ * Return pattern-size or an empty Size for an unsupported inputFormat.
-+ */
-+Size DebayerCpu::patternSize(PixelFormat inputFormat)
-+{
-+	DebayerCpu::DebayerInputConfig config;
-+
-+	if (getInputConfig(inputFormat, config) != 0)
-+		return {};
-+
-+	return config.patternSize;
-+}
-+
-+std::vector<PixelFormat> DebayerCpu::formats(PixelFormat inputFormat)
-+{
-+	DebayerCpu::DebayerInputConfig config;
-+
-+	if (getInputConfig(inputFormat, config) != 0)
-+		return std::vector<PixelFormat>();
-+
-+	return config.outputFormats;
-+}
-+
-+std::tuple<unsigned int, unsigned int>
-+DebayerCpu::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size)
-+{
-+	DebayerCpu::DebayerOutputConfig config;
-+
-+	if (getOutputConfig(outputFormat, config) != 0)
-+		return std::make_tuple(0, 0);
-+
-+	/* round up to multiple of 8 for 64 bits alignment */
-+	unsigned int stride = (size.width * config.bpp / 8 + 7) & ~7;
-+
-+	return std::make_tuple(stride, stride * size.height);
-+}
-+
-+void DebayerCpu::setupInputMemcpy(const uint8_t *linePointers[])
-+{
-+	const unsigned int patternHeight = inputConfig_.patternSize.height;
-+
-+	if (!enableInputMemcpy_)
-+		return;
-+
-+	for (unsigned int i = 0; i < patternHeight; i++) {
-+		memcpy(lineBuffers_[i], linePointers[i + 1] - lineBufferPadding_,
-+		       lineBufferLength_);
-+		linePointers[i + 1] = lineBuffers_[i] + lineBufferPadding_;
-+	}
-+
-+	/* Point lineBufferIndex_ to first unused lineBuffer */
-+	lineBufferIndex_ = patternHeight;
-+}
-+
-+void DebayerCpu::shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src)
-+{
-+	const unsigned int patternHeight = inputConfig_.patternSize.height;
-+
-+	for (unsigned int i = 0; i < patternHeight; i++)
-+		linePointers[i] = linePointers[i + 1];
-+
-+	linePointers[patternHeight] = src +
-+				      (patternHeight / 2) * (int)inputConfig_.stride;
-+}
-+
-+void DebayerCpu::memcpyNextLine(const uint8_t *linePointers[])
-+{
-+	const unsigned int patternHeight = inputConfig_.patternSize.height;
-+
-+	if (!enableInputMemcpy_)
-+		return;
-+
-+	memcpy(lineBuffers_[lineBufferIndex_], linePointers[patternHeight] - lineBufferPadding_,
-+	       lineBufferLength_);
-+	linePointers[patternHeight] = lineBuffers_[lineBufferIndex_] + lineBufferPadding_;
-+
-+	lineBufferIndex_ = (lineBufferIndex_ + 1) % (patternHeight + 1);
-+}
-+
-+void DebayerCpu::process2(const uint8_t *src, uint8_t *dst)
-+{
-+	unsigned int y_end = window_.y + window_.height;
-+	/* Holds [0] previous- [1] current- [2] next-line */
-+	const uint8_t *linePointers[3];
-+
-+	/* Adjust src to top left corner of the window */
-+	src += window_.y * inputConfig_.stride + window_.x * inputConfig_.bpp / 8;
-+
-+	/* [x] becomes [x - 1] after initial shiftLinePointers() call */
-+	if (window_.y) {
-+		linePointers[1] = src - inputConfig_.stride; /* previous-line */
-+		linePointers[2] = src;
-+	} else {
-+		/* window_.y == 0, use the next line as prev line */
-+		linePointers[1] = src + inputConfig_.stride;
-+		linePointers[2] = src;
-+		/* Last 2 lines also need special handling */
-+		y_end -= 2;
-+	}
-+
-+	setupInputMemcpy(linePointers);
-+
-+	for (unsigned int y = window_.y; y < y_end; y += 2) {
-+		shiftLinePointers(linePointers, src);
-+		memcpyNextLine(linePointers);
-+		stats_->processLine0(y, linePointers);
-+		(this->*debayer0_)(dst, linePointers);
-+		src += inputConfig_.stride;
-+		dst += outputConfig_.stride;
-+
-+		shiftLinePointers(linePointers, src);
-+		memcpyNextLine(linePointers);
-+		(this->*debayer1_)(dst, linePointers);
-+		src += inputConfig_.stride;
-+		dst += outputConfig_.stride;
-+	}
-+
-+	if (window_.y == 0) {
-+		shiftLinePointers(linePointers, src);
-+		memcpyNextLine(linePointers);
-+		stats_->processLine0(y_end, linePointers);
-+		(this->*debayer0_)(dst, linePointers);
-+		src += inputConfig_.stride;
-+		dst += outputConfig_.stride;
-+
-+		shiftLinePointers(linePointers, src);
-+		/* next line may point outside of src, use prev. */
-+		linePointers[2] = linePointers[0];
-+		(this->*debayer1_)(dst, linePointers);
-+		src += inputConfig_.stride;
-+		dst += outputConfig_.stride;
-+	}
-+}
-+
-+void DebayerCpu::process4(const uint8_t *src, uint8_t *dst)
-+{
-+	const unsigned int y_end = window_.y + window_.height;
-+	/*
-+	 * This holds pointers to [0] 2-lines-up [1] 1-line-up [2] current-line
-+	 * [3] 1-line-down [4] 2-lines-down.
-+	 */
-+	const uint8_t *linePointers[5];
-+
-+	/* Adjust src to top left corner of the window */
-+	src += window_.y * inputConfig_.stride + window_.x * inputConfig_.bpp / 8;
-+
-+	/* [x] becomes [x - 1] after initial shiftLinePointers() call */
-+	linePointers[1] = src - 2 * inputConfig_.stride;
-+	linePointers[2] = src - inputConfig_.stride;
-+	linePointers[3] = src;
-+	linePointers[4] = src + inputConfig_.stride;
-+
-+	setupInputMemcpy(linePointers);
-+
-+	for (unsigned int y = window_.y; y < y_end; y += 4) {
-+		shiftLinePointers(linePointers, src);
-+		memcpyNextLine(linePointers);
-+		stats_->processLine0(y, linePointers);
-+		(this->*debayer0_)(dst, linePointers);
-+		src += inputConfig_.stride;
-+		dst += outputConfig_.stride;
-+
-+		shiftLinePointers(linePointers, src);
-+		memcpyNextLine(linePointers);
-+		(this->*debayer1_)(dst, linePointers);
-+		src += inputConfig_.stride;
-+		dst += outputConfig_.stride;
-+
-+		shiftLinePointers(linePointers, src);
-+		memcpyNextLine(linePointers);
-+		stats_->processLine2(y, linePointers);
-+		(this->*debayer2_)(dst, linePointers);
-+		src += inputConfig_.stride;
-+		dst += outputConfig_.stride;
-+
-+		shiftLinePointers(linePointers, src);
-+		memcpyNextLine(linePointers);
-+		(this->*debayer3_)(dst, linePointers);
-+		src += inputConfig_.stride;
-+		dst += outputConfig_.stride;
-+	}
-+}
-+
-+static inline int64_t timeDiff(timespec &after, timespec &before)
-+{
-+	return (after.tv_sec - before.tv_sec) * 1000000000LL +
-+	       (int64_t)after.tv_nsec - (int64_t)before.tv_nsec;
-+}
-+
-+void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams params)
-+{
-+	timespec frameStartTime;
-+
-+	if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure) {
-+		frameStartTime = {};
-+		clock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime);
-+	}
-+
-+	/* Apply DebayerParams */
-+	if (params.gamma != gamma_correction_) {
-+		for (unsigned int i = 0; i < kGammaLookupSize; i++)
-+			gamma_[i] = UINT8_MAX * powf(i / (kGammaLookupSize - 1.0), params.gamma);
-+
-+		gamma_correction_ = params.gamma;
-+	}
-+
-+	for (unsigned int i = 0; i < kRGBLookupSize; i++) {
-+		constexpr unsigned int div =
-+			kRGBLookupSize * DebayerParams::kGain10 / kGammaLookupSize;
-+		unsigned int idx;
-+
-+		/* Apply gamma after gain! */
-+		idx = std::min({ i * params.gainR / div, (kGammaLookupSize - 1) });
-+		red_[i] = gamma_[idx];
-+
-+		idx = std::min({ i * params.gainG / div, (kGammaLookupSize - 1) });
-+		green_[i] = gamma_[idx];
-+
-+		idx = std::min({ i * params.gainB / div, (kGammaLookupSize - 1) });
-+		blue_[i] = gamma_[idx];
-+	}
-+
-+	/* Copy metadata from the input buffer */
-+	FrameMetadata &metadata = output->_d()->metadata();
-+	metadata.status = input->metadata().status;
-+	metadata.sequence = input->metadata().sequence;
-+	metadata.timestamp = input->metadata().timestamp;
-+
-+	MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read);
-+	MappedFrameBuffer out(output, MappedFrameBuffer::MapFlag::Write);
-+	if (!in.isValid() || !out.isValid()) {
-+		LOG(Debayer, Error) << "mmap-ing buffer(s) failed";
-+		metadata.status = FrameMetadata::FrameError;
-+		return;
-+	}
-+
-+	stats_->startFrame();
-+
-+	if (inputConfig_.patternSize.height == 2)
-+		process2(in.planes()[0].data(), out.planes()[0].data());
-+	else
-+		process4(in.planes()[0].data(), out.planes()[0].data());
-+
-+	metadata.planes()[0].bytesused = out.planes()[0].size();
-+
-+	/* Measure before emitting signals */
-+	if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure &&
-+	    ++measuredFrames_ > DebayerCpu::kFramesToSkip) {
-+		timespec frameEndTime = {};
-+		clock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime);
-+		frameProcessTime_ += timeDiff(frameEndTime, frameStartTime);
-+		if (measuredFrames_ == DebayerCpu::kLastFrameToMeasure) {
-+			const unsigned int measuredFrames = DebayerCpu::kLastFrameToMeasure -
-+							    DebayerCpu::kFramesToSkip;
-+			LOG(Debayer, Info)
-+				<< "Processed " << measuredFrames
-+				<< " frames in " << frameProcessTime_ / 1000 << "us, "
-+				<< frameProcessTime_ / (1000 * measuredFrames)
-+				<< " us/frame";
-+		}
-+	}
-+
-+	stats_->finishFrame();
-+	outputBufferReady.emit(output);
-+	inputBufferReady.emit(input);
-+}
-+
-+SizeRange DebayerCpu::sizes(PixelFormat inputFormat, const Size &inputSize)
-+{
-+	Size pattern_size = patternSize(inputFormat);
-+	unsigned int border_height = pattern_size.height;
-+
-+	if (pattern_size.isNull())
-+		return {};
-+
-+	/* No need for top/bottom border with a pattern height of 2 */
-+	if (pattern_size.height == 2)
-+		border_height = 0;
-+
-+	/*
-+	 * For debayer interpolation a border is kept around the entire image
-+	 * and the minimum output size is pattern-height x pattern-width.
-+	 */
-+	if (inputSize.width < (3 * pattern_size.width) ||
-+	    inputSize.height < (2 * border_height + pattern_size.height)) {
-+		LOG(Debayer, Warning)
-+			<< "Input format size too small: " << inputSize.toString();
-+		return {};
-+	}
-+
-+	return SizeRange(Size(pattern_size.width, pattern_size.height),
-+			 Size((inputSize.width - 2 * pattern_size.width) & ~(pattern_size.width - 1),
-+			      (inputSize.height - 2 * border_height) & ~(pattern_size.height - 1)),
-+			 pattern_size.width, pattern_size.height);
-+}
-+
-+} /* namespace libcamera */
-diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h
-new file mode 100644
-index 00000000..8a51ed85
---- /dev/null
-+++ b/src/libcamera/software_isp/debayer_cpu.h
-@@ -0,0 +1,143 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2023, Linaro Ltd
-+ * Copyright (C) 2023, Red Hat Inc.
-+ *
-+ * Authors:
-+ * Hans de Goede <hdegoede@redhat.com>
-+ *
-+ * debayer_cpu.h - CPU based debayering header
-+ */
-+
-+#pragma once
-+
-+#include <memory>
-+#include <stdint.h>
-+#include <vector>
-+
-+#include <libcamera/base/object.h>
-+
-+#include "debayer.h"
-+#include "swstats_cpu.h"
-+
-+namespace libcamera {
-+
-+class DebayerCpu : public Debayer, public Object
-+{
-+public:
-+	DebayerCpu(std::unique_ptr<SwStatsCpu> stats);
-+	~DebayerCpu();
-+
-+	int configure(const StreamConfiguration &inputCfg,
-+		      const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs);
-+	Size patternSize(PixelFormat inputFormat);
-+	std::vector<PixelFormat> formats(PixelFormat input);
-+	std::tuple<unsigned int, unsigned int>
-+	strideAndFrameSize(const PixelFormat &outputFormat, const Size &size);
-+	void process(FrameBuffer *input, FrameBuffer *output, DebayerParams params);
-+	SizeRange sizes(PixelFormat inputFormat, const Size &inputSize);
-+
-+	/**
-+	 * \brief Get the file descriptor for the statistics.
-+	 *
-+	 * \return the file descriptor pointing to the statistics.
-+	 */
-+	const SharedFD &getStatsFD() { return stats_->getStatsFD(); }
-+
-+	/**
-+	 * \brief Get the output frame size.
-+	 *
-+	 * \return The output frame size.
-+	 */
-+	unsigned int frameSize() { return outputConfig_.frameSize; }
-+
-+private:
-+	/**
-+	 * \brief Called to debayer 1 line of Bayer input data to output format
-+	 * \param[out] dst Pointer to the start of the output line to write
-+	 * \param[in] src The input data
-+	 *
-+	 * Input data is an array of (patternSize_.height + 1) src
-+	 * pointers each pointing to a line in the Bayer source. The middle
-+	 * element of the array will point to the actual line being processed.
-+	 * Earlier element(s) will point to the previous line(s) and later
-+	 * element(s) to the next line(s).
-+	 *
-+	 * These functions take an array of src pointers, rather than
-+	 * a single src pointer + a stride for the source, so that when the src
-+	 * is slow uncached memory it can be copied to faster memory before
-+	 * debayering. Debayering a standard 2x2 Bayer pattern requires access
-+	 * to the previous and next src lines for interpolating the missing
-+	 * colors. To allow copying the src lines only once 3 temporary buffers
-+	 * each holding a single line are used, re-using the oldest buffer for
-+	 * the next line and the pointers are swizzled so that:
-+	 * src[0] = previous-line, src[1] = currrent-line, src[2] = next-line.
-+	 * This way the 3 pointers passed to the debayer functions form
-+	 * a sliding window over the src avoiding the need to copy each
-+	 * line more than once.
-+	 *
-+	 * Similarly for bayer patterns which repeat every 4 lines, 5 src
-+	 * pointers are passed holding: src[0] = 2-lines-up, src[1] = 1-line-up
-+	 * src[2] = current-line, src[3] = 1-line-down, src[4] = 2-lines-down.
-+	 */
-+	using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]);
-+
-+	/* CSI-2 packed 10-bit raw bayer format (all the 4 orders) */
-+	void debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
-+	void debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
-+	void debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]);
-+	void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]);
-+
-+	struct DebayerInputConfig {
-+		Size patternSize;
-+		unsigned int bpp; /* Memory used per pixel, not precision */
-+		unsigned int stride;
-+		std::vector<PixelFormat> outputFormats;
-+	};
-+
-+	struct DebayerOutputConfig {
-+		unsigned int bpp; /* Memory used per pixel, not precision */
-+		unsigned int stride;
-+		unsigned int frameSize;
-+	};
-+
-+	int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config);
-+	int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config);
-+	int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat);
-+	void setupInputMemcpy(const uint8_t *linePointers[]);
-+	void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);
-+	void memcpyNextLine(const uint8_t *linePointers[]);
-+	void process2(const uint8_t *src, uint8_t *dst);
-+	void process4(const uint8_t *src, uint8_t *dst);
-+
-+	static constexpr unsigned int kGammaLookupSize = 1024;
-+	static constexpr unsigned int kRGBLookupSize = 256;
-+	/* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */
-+	static constexpr unsigned int kMaxLineBuffers = 5;
-+
-+	std::array<uint8_t, kGammaLookupSize> gamma_;
-+	std::array<uint8_t, kRGBLookupSize> red_;
-+	std::array<uint8_t, kRGBLookupSize> green_;
-+	std::array<uint8_t, kRGBLookupSize> blue_;
-+	debayerFn debayer0_;
-+	debayerFn debayer1_;
-+	debayerFn debayer2_;
-+	debayerFn debayer3_;
-+	Rectangle window_;
-+	DebayerInputConfig inputConfig_;
-+	DebayerOutputConfig outputConfig_;
-+	std::unique_ptr<SwStatsCpu> stats_;
-+	uint8_t *lineBuffers_[kMaxLineBuffers];
-+	unsigned int lineBufferLength_;
-+	unsigned int lineBufferPadding_;
-+	unsigned int lineBufferIndex_;
-+	bool enableInputMemcpy_;
-+	float gamma_correction_;
-+	unsigned int measuredFrames_;
-+	int64_t frameProcessTime_;
-+	/* Skip 30 frames for things to stabilize then measure 30 frames */
-+	static constexpr unsigned int kFramesToSkip = 30;
-+	static constexpr unsigned int kLastFrameToMeasure = 60;
-+};
-+
-+} /* namespace libcamera */
-diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build
-index 62095f61..71b46539 100644
---- a/src/libcamera/software_isp/meson.build
-+++ b/src/libcamera/software_isp/meson.build
-@@ -9,5 +9,6 @@ endif
- 
- libcamera_sources += files([
-     'debayer.cpp',
-+    'debayer_cpu.cpp',
-     'swstats_cpu.cpp',
- ])
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0009-libcamera-ipa-add-Soft-IPA.patch b/users/flokli/ipu6-softisp/libcamera/0009-libcamera-ipa-add-Soft-IPA.patch
deleted file mode 100644
index 40f9403ba984..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0009-libcamera-ipa-add-Soft-IPA.patch
+++ /dev/null
@@ -1,506 +0,0 @@
-From 5261c801d8425fa82bcbd3da0199d06153eb5bd7 Mon Sep 17 00:00:00 2001
-From: Andrey Konovalov <andrey.konovalov@linaro.org>
-Date: Mon, 11 Mar 2024 15:15:13 +0100
-Subject: [PATCH 09/21] libcamera: ipa: add Soft IPA
-
-Define the Soft IPA main and event interfaces, add the Soft IPA
-implementation.
-
-The current src/ipa/meson.build assumes the IPA name to match the
-pipeline name. For this reason "-Dipas=simple" is used for the
-Soft IPA module.
-
-Auto exposure/gain and AWB implementation by Dennis, Toon and Martti.
-
-Auto exposure/gain targets a Mean Sample Value of 2.5 following
-the MSV calculation algorithm from:
-https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Co-developed-by: Dennis Bonke <admin@dennisbonke.com>
-Signed-off-by: Dennis Bonke <admin@dennisbonke.com>
-Co-developed-by: Marttico <g.martti@gmail.com>
-Signed-off-by: Marttico <g.martti@gmail.com>
-Co-developed-by: Toon Langendam <t.langendam@gmail.com>
-Signed-off-by: Toon Langendam <t.langendam@gmail.com>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- Documentation/Doxyfile.in         |   1 +
- include/libcamera/ipa/meson.build |   1 +
- include/libcamera/ipa/soft.mojom  |  28 +++
- meson_options.txt                 |   2 +-
- src/ipa/simple/data/meson.build   |   9 +
- src/ipa/simple/data/soft.conf     |   3 +
- src/ipa/simple/meson.build        |  25 +++
- src/ipa/simple/soft_simple.cpp    | 326 ++++++++++++++++++++++++++++++
- 8 files changed, 394 insertions(+), 1 deletion(-)
- create mode 100644 include/libcamera/ipa/soft.mojom
- create mode 100644 src/ipa/simple/data/meson.build
- create mode 100644 src/ipa/simple/data/soft.conf
- create mode 100644 src/ipa/simple/meson.build
- create mode 100644 src/ipa/simple/soft_simple.cpp
-
-diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in
-index a86ea6c1..2be8d47b 100644
---- a/Documentation/Doxyfile.in
-+++ b/Documentation/Doxyfile.in
-@@ -44,6 +44,7 @@ EXCLUDE                = @TOP_SRCDIR@/include/libcamera/base/span.h \
-                          @TOP_SRCDIR@/src/libcamera/pipeline/ \
-                          @TOP_SRCDIR@/src/libcamera/tracepoints.cpp \
-                          @TOP_BUILDDIR@/include/libcamera/internal/tracepoints.h \
-+                         @TOP_BUILDDIR@/include/libcamera/ipa/soft_ipa_interface.h \
-                          @TOP_BUILDDIR@/src/libcamera/proxy/
- 
- EXCLUDE_PATTERNS       = @TOP_BUILDDIR@/include/libcamera/ipa/*_serializer.h \
-diff --git a/include/libcamera/ipa/meson.build b/include/libcamera/ipa/meson.build
-index f3b4881c..3352d08f 100644
---- a/include/libcamera/ipa/meson.build
-+++ b/include/libcamera/ipa/meson.build
-@@ -65,6 +65,7 @@ pipeline_ipa_mojom_mapping = {
-     'ipu3': 'ipu3.mojom',
-     'rkisp1': 'rkisp1.mojom',
-     'rpi/vc4': 'raspberrypi.mojom',
-+    'simple': 'soft.mojom',
-     'vimc': 'vimc.mojom',
- }
- 
-diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom
-new file mode 100644
-index 00000000..c249bd75
---- /dev/null
-+++ b/include/libcamera/ipa/soft.mojom
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+
-+/*
-+ * \todo Document the interface and remove the related EXCLUDE_PATTERNS entry.
-+ */
-+
-+module ipa.soft;
-+
-+import "include/libcamera/ipa/core.mojom";
-+
-+interface IPASoftInterface {
-+	init(libcamera.IPASettings settings,
-+	     libcamera.SharedFD fdStats,
-+	     libcamera.SharedFD fdParams,
-+	     libcamera.ControlInfoMap sensorCtrlInfoMap)
-+		=> (int32 ret);
-+	start() => (int32 ret);
-+	stop();
-+	configure(libcamera.ControlInfoMap sensorCtrlInfoMap)
-+		=> (int32 ret);
-+
-+	[async] processStats(libcamera.ControlList sensorControls);
-+};
-+
-+interface IPASoftEventInterface {
-+	setSensorControls(libcamera.ControlList sensorControls);
-+	setIspParams(int32 dummy);
-+};
-diff --git a/meson_options.txt b/meson_options.txt
-index 5fdc7be8..94372e47 100644
---- a/meson_options.txt
-+++ b/meson_options.txt
-@@ -27,7 +27,7 @@ option('gstreamer',
- 
- option('ipas',
-         type : 'array',
--        choices : ['ipu3', 'rkisp1', 'rpi/vc4', 'vimc'],
-+        choices : ['ipu3', 'rkisp1', 'rpi/vc4', 'simple', 'vimc'],
-         description : 'Select which IPA modules to build')
- 
- option('lc-compliance',
-diff --git a/src/ipa/simple/data/meson.build b/src/ipa/simple/data/meson.build
-new file mode 100644
-index 00000000..33548cc6
---- /dev/null
-+++ b/src/ipa/simple/data/meson.build
-@@ -0,0 +1,9 @@
-+# SPDX-License-Identifier: CC0-1.0
-+
-+conf_files = files([
-+    'soft.conf',
-+])
-+
-+install_data(conf_files,
-+             install_dir : ipa_data_dir / 'soft',
-+             install_tag : 'runtime')
-diff --git a/src/ipa/simple/data/soft.conf b/src/ipa/simple/data/soft.conf
-new file mode 100644
-index 00000000..0c70e7c0
---- /dev/null
-+++ b/src/ipa/simple/data/soft.conf
-@@ -0,0 +1,3 @@
-+# SPDX-License-Identifier: LGPL-2.1-or-later
-+#
-+# Dummy configuration file for the soft IPA.
-diff --git a/src/ipa/simple/meson.build b/src/ipa/simple/meson.build
-new file mode 100644
-index 00000000..3e863db7
---- /dev/null
-+++ b/src/ipa/simple/meson.build
-@@ -0,0 +1,25 @@
-+# SPDX-License-Identifier: CC0-1.0
-+
-+ipa_name = 'ipa_soft_simple'
-+
-+mod = shared_module(ipa_name,
-+                    ['soft_simple.cpp', libcamera_generated_ipa_headers],
-+                    name_prefix : '',
-+                    include_directories : [ipa_includes, libipa_includes],
-+                    dependencies : libcamera_private,
-+                    link_with : libipa,
-+                    install : true,
-+                    install_dir : ipa_install_dir)
-+
-+if ipa_sign_module
-+    custom_target(ipa_name + '.so.sign',
-+                  input : mod,
-+                  output : ipa_name + '.so.sign',
-+                  command : [ipa_sign, ipa_priv_key, '@INPUT@', '@OUTPUT@'],
-+                  install : false,
-+                  build_by_default : true)
-+endif
-+
-+subdir('data')
-+
-+ipa_names += ipa_name
-diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp
-new file mode 100644
-index 00000000..312df4ba
---- /dev/null
-+++ b/src/ipa/simple/soft_simple.cpp
-@@ -0,0 +1,326 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2023, Linaro Ltd
-+ *
-+ * soft_simple.cpp - Simple Software Image Processing Algorithm module
-+ */
-+
-+#include <sys/mman.h>
-+
-+#include <libcamera/base/file.h>
-+#include <libcamera/base/log.h>
-+#include <libcamera/base/shared_fd.h>
-+
-+#include <libcamera/control_ids.h>
-+#include <libcamera/controls.h>
-+
-+#include <libcamera/ipa/ipa_interface.h>
-+#include <libcamera/ipa/ipa_module_info.h>
-+#include <libcamera/ipa/soft_ipa_interface.h>
-+
-+#include "libcamera/internal/camera_sensor.h"
-+#include "libcamera/internal/software_isp/debayer_params.h"
-+#include "libcamera/internal/software_isp/swisp_stats.h"
-+
-+namespace libcamera {
-+
-+LOG_DEFINE_CATEGORY(IPASoft)
-+
-+namespace ipa::soft {
-+
-+class IPASoftSimple : public ipa::soft::IPASoftInterface
-+{
-+public:
-+	IPASoftSimple()
-+		: params_(static_cast<DebayerParams *>(MAP_FAILED)),
-+		  stats_(static_cast<SwIspStats *>(MAP_FAILED)), ignore_updates_(0)
-+	{
-+	}
-+
-+	~IPASoftSimple()
-+	{
-+		if (stats_ != MAP_FAILED)
-+			munmap(stats_, sizeof(SwIspStats));
-+		if (params_ != MAP_FAILED)
-+			munmap(params_, sizeof(DebayerParams));
-+	}
-+
-+	int init(const IPASettings &settings,
-+		 const SharedFD &fdStats,
-+		 const SharedFD &fdParams,
-+		 const ControlInfoMap &sensorInfoMap) override;
-+	int configure(const ControlInfoMap &sensorInfoMap) override;
-+
-+	int start() override;
-+	void stop() override;
-+
-+	void processStats(const ControlList &sensorControls) override;
-+
-+private:
-+	void updateExposure(double exposureMSV);
-+
-+	SharedFD fdStats_;
-+	SharedFD fdParams_;
-+	DebayerParams *params_;
-+	SwIspStats *stats_;
-+
-+	int32_t exposure_min_, exposure_max_;
-+	int32_t again_min_, again_max_;
-+	int32_t again_, exposure_;
-+	unsigned int ignore_updates_;
-+};
-+
-+int IPASoftSimple::init([[maybe_unused]] const IPASettings &settings,
-+			const SharedFD &fdStats,
-+			const SharedFD &fdParams,
-+			const ControlInfoMap &sensorInfoMap)
-+{
-+	fdStats_ = fdStats;
-+	if (!fdStats_.isValid()) {
-+		LOG(IPASoft, Error) << "Invalid Statistics handle";
-+		return -ENODEV;
-+	}
-+
-+	fdParams_ = fdParams;
-+	if (!fdParams_.isValid()) {
-+		LOG(IPASoft, Error) << "Invalid Parameters handle";
-+		return -ENODEV;
-+	}
-+
-+	params_ = static_cast<DebayerParams *>(mmap(nullptr, sizeof(DebayerParams),
-+						    PROT_WRITE, MAP_SHARED,
-+						    fdParams_.get(), 0));
-+	if (params_ == MAP_FAILED) {
-+		LOG(IPASoft, Error) << "Unable to map Parameters";
-+		return -errno;
-+	}
-+
-+	stats_ = static_cast<SwIspStats *>(mmap(nullptr, sizeof(SwIspStats),
-+						PROT_READ, MAP_SHARED,
-+						fdStats_.get(), 0));
-+	if (stats_ == MAP_FAILED) {
-+		LOG(IPASoft, Error) << "Unable to map Statistics";
-+		return -errno;
-+	}
-+
-+	if (sensorInfoMap.find(V4L2_CID_EXPOSURE) == sensorInfoMap.end()) {
-+		LOG(IPASoft, Error) << "Don't have exposure control";
-+		return -EINVAL;
-+	}
-+
-+	if (sensorInfoMap.find(V4L2_CID_ANALOGUE_GAIN) == sensorInfoMap.end()) {
-+		LOG(IPASoft, Error) << "Don't have gain control";
-+		return -EINVAL;
-+	}
-+
-+	return 0;
-+}
-+
-+int IPASoftSimple::configure(const ControlInfoMap &sensorInfoMap)
-+{
-+	const ControlInfo &exposure_info = sensorInfoMap.find(V4L2_CID_EXPOSURE)->second;
-+	const ControlInfo &gain_info = sensorInfoMap.find(V4L2_CID_ANALOGUE_GAIN)->second;
-+
-+	exposure_min_ = exposure_info.min().get<int32_t>();
-+	exposure_max_ = exposure_info.max().get<int32_t>();
-+	if (!exposure_min_) {
-+		LOG(IPASoft, Warning) << "Minimum exposure is zero, that can't be linear";
-+		exposure_min_ = 1;
-+	}
-+
-+	again_min_ = gain_info.min().get<int32_t>();
-+	again_max_ = gain_info.max().get<int32_t>();
-+	/*
-+	 * The camera sensor gain (g) is usually not equal to the value written
-+	 * into the gain register (x). But the way how the AGC algorithm changes
-+	 * the gain value to make the total exposure closer to the optimum assumes
-+	 * that g(x) is not too far from linear function. If the minimal gain is 0,
-+	 * the g(x) is likely to be far from the linear, like g(x) = a / (b * x + c).
-+	 * To avoid unexpected changes to the gain by the AGC algorithm (abrupt near
-+	 * one edge, and very small near the other) we limit the range of the gain
-+	 * values used.
-+	 */
-+	if (!again_min_) {
-+		LOG(IPASoft, Warning) << "Minimum gain is zero, that can't be linear";
-+		again_min_ = std::min(100, again_min_ / 2 + again_max_ / 2);
-+	}
-+
-+	LOG(IPASoft, Info) << "Exposure " << exposure_min_ << "-" << exposure_max_
-+			   << ", gain " << again_min_ << "-" << again_max_;
-+
-+	return 0;
-+}
-+
-+int IPASoftSimple::start()
-+{
-+	return 0;
-+}
-+
-+void IPASoftSimple::stop()
-+{
-+}
-+
-+/*
-+ * The number of bins to use for the optimal exposure calculations.
-+ */
-+static constexpr unsigned int kExposureBinsCount = 5;
-+/*
-+ * The exposure is optimal when the mean sample value of the histogram is
-+ * in the middle of the range.
-+ */
-+static constexpr float kExposureOptimal = kExposureBinsCount / 2.0;
-+/*
-+ * The below value implements the hysteresis for the exposure adjustment.
-+ * It is small enough to have the exposure close to the optimal, and is big
-+ * enough to prevent the exposure from wobbling around the optimal value.
-+ */
-+static constexpr float kExposureSatisfactory = 0.2;
-+
-+void IPASoftSimple::processStats(const ControlList &sensorControls)
-+{
-+	/*
-+	 * Calculate red and blue gains for AWB.
-+	 * Clamp max gain at 4.0, this also avoids 0 division.
-+	 */
-+	if (stats_->sumR_ <= stats_->sumG_ / 4)
-+		params_->gainR = 1024;
-+	else
-+		params_->gainR = 256 * stats_->sumG_ / stats_->sumR_;
-+
-+	if (stats_->sumB_ <= stats_->sumG_ / 4)
-+		params_->gainB = 1024;
-+	else
-+		params_->gainB = 256 * stats_->sumG_ / stats_->sumB_;
-+
-+	/* Green gain and gamma values are fixed */
-+	params_->gainG = 256;
-+	params_->gamma = 0.5;
-+
-+	setIspParams.emit(0);
-+
-+	/*
-+	 * AE / AGC, use 2 frames delay to make sure that the exposure and
-+	 * the gain set have applied to the camera sensor.
-+	 */
-+	if (ignore_updates_ > 0) {
-+		--ignore_updates_;
-+		return;
-+	}
-+
-+	/*
-+	 * Calculate Mean Sample Value (MSV) according to formula from:
-+	 * https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf
-+	 */
-+	constexpr unsigned int yHistValsPerBin =
-+		SwIspStats::kYHistogramSize / kExposureBinsCount;
-+	constexpr unsigned int yHistValsPerBinMod =
-+		SwIspStats::kYHistogramSize /
-+		(SwIspStats::kYHistogramSize % kExposureBinsCount + 1);
-+	int ExposureBins[kExposureBinsCount] = {};
-+	unsigned int denom = 0;
-+	unsigned int num = 0;
-+
-+	for (unsigned int i = 0; i < SwIspStats::kYHistogramSize; i++) {
-+		unsigned int idx = (i - (i / yHistValsPerBinMod)) / yHistValsPerBin;
-+		ExposureBins[idx] += stats_->yHistogram[i];
-+	}
-+
-+	for (unsigned int i = 0; i < kExposureBinsCount; i++) {
-+		LOG(IPASoft, Debug) << i << ": " << ExposureBins[i];
-+		denom += ExposureBins[i];
-+		num += ExposureBins[i] * (i + 1);
-+	}
-+
-+	float exposureMSV = (float)num / denom;
-+
-+	/* sanity check */
-+	if (!sensorControls.contains(V4L2_CID_EXPOSURE) ||
-+	    !sensorControls.contains(V4L2_CID_ANALOGUE_GAIN)) {
-+		LOG(IPASoft, Error) << "Control(s) missing";
-+		return;
-+	}
-+
-+	ControlList ctrls(sensorControls);
-+
-+	exposure_ = ctrls.get(V4L2_CID_EXPOSURE).get<int32_t>();
-+	again_ = ctrls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>();
-+
-+	updateExposure(exposureMSV);
-+
-+	ctrls.set(V4L2_CID_EXPOSURE, exposure_);
-+	ctrls.set(V4L2_CID_ANALOGUE_GAIN, again_);
-+
-+	ignore_updates_ = 2;
-+
-+	setSensorControls.emit(ctrls);
-+
-+	LOG(IPASoft, Debug) << "exposureMSV " << exposureMSV
-+			    << " exp " << exposure_ << " again " << again_
-+			    << " gain R/B " << params_->gainR << "/" << params_->gainB;
-+}
-+
-+void IPASoftSimple::updateExposure(double exposureMSV)
-+{
-+	/* DENOMINATOR of 10 gives ~10% increment/decrement; DENOMINATOR of 5 - about ~20% */
-+	static constexpr uint8_t kExpDenominator = 10;
-+	static constexpr uint8_t kExpNumeratorUp = kExpDenominator + 1;
-+	static constexpr uint8_t kExpNumeratorDown = kExpDenominator - 1;
-+
-+	int next;
-+
-+	if (exposureMSV < kExposureOptimal - kExposureSatisfactory) {
-+		next = exposure_ * kExpNumeratorUp / kExpDenominator;
-+		if (next - exposure_ < 1)
-+			exposure_ += 1;
-+		else
-+			exposure_ = next;
-+		if (exposure_ >= exposure_max_) {
-+			next = again_ * kExpNumeratorUp / kExpDenominator;
-+			if (next - again_ < 1)
-+				again_ += 1;
-+			else
-+				again_ = next;
-+		}
-+	}
-+
-+	if (exposureMSV > kExposureOptimal + kExposureSatisfactory) {
-+		if (exposure_ == exposure_max_ && again_ != again_min_) {
-+			next = again_ * kExpNumeratorDown / kExpDenominator;
-+			if (again_ - next < 1)
-+				again_ -= 1;
-+			else
-+				again_ = next;
-+		} else {
-+			next = exposure_ * kExpNumeratorDown / kExpDenominator;
-+			if (exposure_ - next < 1)
-+				exposure_ -= 1;
-+			else
-+				exposure_ = next;
-+		}
-+	}
-+
-+	exposure_ = std::clamp(exposure_, exposure_min_, exposure_max_);
-+	again_ = std::clamp(again_, again_min_, again_max_);
-+}
-+
-+} /* namespace ipa::soft */
-+
-+/*
-+ * External IPA module interface
-+ */
-+extern "C" {
-+const struct IPAModuleInfo ipaModuleInfo = {
-+	IPA_MODULE_API_VERSION,
-+	0,
-+	"SimplePipelineHandler",
-+	"simple",
-+};
-+
-+IPAInterface *ipaCreate()
-+{
-+	return new ipa::soft::IPASoftSimple();
-+}
-+
-+} /* extern "C" */
-+
-+} /* namespace libcamera */
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0010-libcamera-introduce-SoftwareIsp.patch b/users/flokli/ipu6-softisp/libcamera/0010-libcamera-introduce-SoftwareIsp.patch
deleted file mode 100644
index 9f2d66c2f8b6..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0010-libcamera-introduce-SoftwareIsp.patch
+++ /dev/null
@@ -1,507 +0,0 @@
-From ad41ea12fe4b8ca0ace20781c775a63ed0d66f4c Mon Sep 17 00:00:00 2001
-From: Andrey Konovalov <andrey.konovalov@linaro.org>
-Date: Mon, 11 Mar 2024 15:15:14 +0100
-Subject: [PATCH 10/21] libcamera: introduce SoftwareIsp
-
-Doxygen documentation by Dennis Bonke.
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Co-developed-by: Dennis Bonke <admin@dennisbonke.com>
-Signed-off-by: Dennis Bonke <admin@dennisbonke.com>
-Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- .../internal/software_isp/meson.build         |   1 +
- .../internal/software_isp/software_isp.h      |  98 +++++
- src/libcamera/software_isp/meson.build        |   1 +
- src/libcamera/software_isp/software_isp.cpp   | 349 ++++++++++++++++++
- 4 files changed, 449 insertions(+)
- create mode 100644 include/libcamera/internal/software_isp/software_isp.h
- create mode 100644 src/libcamera/software_isp/software_isp.cpp
-
-diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build
-index a620e16d..508ddddc 100644
---- a/include/libcamera/internal/software_isp/meson.build
-+++ b/include/libcamera/internal/software_isp/meson.build
-@@ -2,5 +2,6 @@
- 
- libcamera_internal_headers += files([
-     'debayer_params.h',
-+    'software_isp.h',
-     'swisp_stats.h',
- ])
-diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h
-new file mode 100644
-index 00000000..8d25e979
---- /dev/null
-+++ b/include/libcamera/internal/software_isp/software_isp.h
-@@ -0,0 +1,98 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2023, Linaro Ltd
-+ *
-+ * software_isp.h - Simple software ISP implementation
-+ */
-+
-+#pragma once
-+
-+#include <functional>
-+#include <initializer_list>
-+#include <map>
-+#include <memory>
-+#include <string>
-+#include <tuple>
-+#include <vector>
-+
-+#include <libcamera/base/class.h>
-+#include <libcamera/base/log.h>
-+#include <libcamera/base/signal.h>
-+#include <libcamera/base/thread.h>
-+
-+#include <libcamera/geometry.h>
-+#include <libcamera/pixel_format.h>
-+
-+#include <libcamera/ipa/soft_ipa_interface.h>
-+#include <libcamera/ipa/soft_ipa_proxy.h>
-+
-+#include "libcamera/internal/dma_heaps.h"
-+#include "libcamera/internal/pipeline_handler.h"
-+#include "libcamera/internal/shared_mem_object.h"
-+#include "libcamera/internal/software_isp/debayer_params.h"
-+
-+namespace libcamera {
-+
-+class DebayerCpu;
-+class FrameBuffer;
-+class PixelFormat;
-+struct StreamConfiguration;
-+
-+LOG_DECLARE_CATEGORY(SoftwareIsp)
-+
-+class SoftwareIsp
-+{
-+public:
-+	SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorControls);
-+	~SoftwareIsp();
-+
-+	int loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; }
-+
-+	bool isValid() const;
-+
-+	std::vector<PixelFormat> formats(PixelFormat input);
-+
-+	SizeRange sizes(PixelFormat inputFormat, const Size &inputSize);
-+
-+	std::tuple<unsigned int, unsigned int>
-+	strideAndFrameSize(const PixelFormat &outputFormat, const Size &size);
-+
-+	int configure(const StreamConfiguration &inputCfg,
-+		      const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs,
-+		      const ControlInfoMap &sensorControls);
-+
-+	int exportBuffers(unsigned int output, unsigned int count,
-+			  std::vector<std::unique_ptr<FrameBuffer>> *buffers);
-+
-+	void processStats(const ControlList &sensorControls);
-+
-+	int start();
-+	void stop();
-+
-+	int queueBuffers(FrameBuffer *input,
-+			 const std::map<unsigned int, FrameBuffer *> &outputs);
-+
-+	void process(FrameBuffer *input, FrameBuffer *output);
-+
-+	Signal<FrameBuffer *> inputBufferReady;
-+	Signal<FrameBuffer *> outputBufferReady;
-+	Signal<int> ispStatsReady;
-+	Signal<const ControlList &> setSensorControls;
-+
-+private:
-+	void saveIspParams(int dummy);
-+	void setSensorCtrls(const ControlList &sensorControls);
-+	void statsReady(int dummy);
-+	void inputReady(FrameBuffer *input);
-+	void outputReady(FrameBuffer *output);
-+
-+	std::unique_ptr<DebayerCpu> debayer_;
-+	Thread ispWorkerThread_;
-+	SharedMemObject<DebayerParams> sharedParams_;
-+	DebayerParams debayerParams_;
-+	DmaHeap dmaHeap_;
-+
-+	std::unique_ptr<ipa::soft::IPAProxySoft> ipa_;
-+};
-+
-+} /* namespace libcamera */
-diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build
-index 71b46539..e9266e54 100644
---- a/src/libcamera/software_isp/meson.build
-+++ b/src/libcamera/software_isp/meson.build
-@@ -10,5 +10,6 @@ endif
- libcamera_sources += files([
-     'debayer.cpp',
-     'debayer_cpu.cpp',
-+    'software_isp.cpp',
-     'swstats_cpu.cpp',
- ])
-diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp
-new file mode 100644
-index 00000000..388b4496
---- /dev/null
-+++ b/src/libcamera/software_isp/software_isp.cpp
-@@ -0,0 +1,349 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2023, Linaro Ltd
-+ *
-+ * software_isp.cpp - Simple software ISP implementation
-+ */
-+
-+#include "libcamera/internal/software_isp/software_isp.h"
-+
-+#include <sys/mman.h>
-+#include <sys/types.h>
-+#include <unistd.h>
-+
-+#include <libcamera/formats.h>
-+#include <libcamera/stream.h>
-+
-+#include "libcamera/internal/bayer_format.h"
-+#include "libcamera/internal/framebuffer.h"
-+#include "libcamera/internal/ipa_manager.h"
-+#include "libcamera/internal/mapped_framebuffer.h"
-+
-+#include "debayer_cpu.h"
-+
-+/**
-+ * \file software_isp.cpp
-+ * \brief Simple software ISP implementation
-+ */
-+
-+namespace libcamera {
-+
-+LOG_DEFINE_CATEGORY(SoftwareIsp)
-+
-+/**
-+ * \class SoftwareIsp
-+ * \brief Class for the Software ISP
-+ */
-+
-+/**
-+ * \var SoftwareIsp::inputBufferReady
-+ * \brief A signal emitted when the input frame buffer completes
-+ */
-+
-+/**
-+ * \var SoftwareIsp::outputBufferReady
-+ * \brief A signal emitted when the output frame buffer completes
-+ */
-+
-+/**
-+ * \var SoftwareIsp::ispStatsReady
-+ * \brief A signal emitted when the statistics for IPA are ready
-+ *
-+ * The int parameter isn't actually used.
-+ */
-+
-+/**
-+ * \var SoftwareIsp::setSensorControls
-+ * \brief A signal emitted when the values to write to the sensor controls are ready
-+ */
-+
-+/**
-+ * \brief Constructs SoftwareIsp object
-+ * \param[in] pipe The pipeline handler in use
-+ * \param[in] sensorControls ControlInfoMap describing the controls supported by the sensor
-+ */
-+SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorControls)
-+	: debayer_(nullptr),
-+	  debayerParams_{ DebayerParams::kGain10, DebayerParams::kGain10, DebayerParams::kGain10, 0.5f },
-+	  dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System)
-+{
-+	if (!dmaHeap_.isValid()) {
-+		LOG(SoftwareIsp, Error) << "Failed to create DmaHeap object";
-+		return;
-+	}
-+
-+	sharedParams_ = SharedMemObject<DebayerParams>("softIsp_params");
-+	if (!sharedParams_) {
-+		LOG(SoftwareIsp, Error) << "Failed to create shared memory for parameters";
-+		return;
-+	}
-+
-+	auto stats = std::make_unique<SwStatsCpu>();
-+	if (!stats->isValid()) {
-+		LOG(SoftwareIsp, Error) << "Failed to create SwStatsCpu object";
-+		return;
-+	}
-+	stats->statsReady.connect(this, &SoftwareIsp::statsReady);
-+
-+	debayer_ = std::make_unique<DebayerCpu>(std::move(stats));
-+	debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady);
-+	debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady);
-+
-+	ipa_ = IPAManager::createIPA<ipa::soft::IPAProxySoft>(pipe, 0, 0);
-+	if (!ipa_) {
-+		LOG(SoftwareIsp, Error)
-+			<< "Creating IPA for software ISP failed";
-+		debayer_.reset();
-+		return;
-+	}
-+
-+	int ret = ipa_->init(IPASettings{ "No cfg file", "No sensor model" },
-+			     debayer_->getStatsFD(),
-+			     sharedParams_.fd(),
-+			     sensorControls);
-+	if (ret) {
-+		LOG(SoftwareIsp, Error) << "IPA init failed";
-+		debayer_.reset();
-+		return;
-+	}
-+
-+	ipa_->setIspParams.connect(this, &SoftwareIsp::saveIspParams);
-+	ipa_->setSensorControls.connect(this, &SoftwareIsp::setSensorCtrls);
-+
-+	debayer_->moveToThread(&ispWorkerThread_);
-+}
-+
-+SoftwareIsp::~SoftwareIsp()
-+{
-+	/* make sure to destroy the DebayerCpu before the ispWorkerThread_ is gone */
-+	debayer_.reset();
-+}
-+
-+/**
-+ * \fn int SoftwareIsp::loadConfiguration([[maybe_unused]] const std::string &filename)
-+ * \brief Load a configuration from a file
-+ * \param[in] filename The file to load the configuration data from
-+ *
-+ * Currently is a stub doing nothing and always returning "success".
-+ *
-+ * \return 0 on success
-+ */
-+
-+/**
-+ * \brief Process the statistics gathered
-+ * \param[in] sensorControls The sensor controls
-+ *
-+ * Requests the IPA to calculate new parameters for ISP and new control
-+ * values for the sensor.
-+ */
-+void SoftwareIsp::processStats(const ControlList &sensorControls)
-+{
-+	ASSERT(ipa_);
-+	ipa_->processStats(sensorControls);
-+}
-+
-+/**
-+ * \brief Check the validity of Software Isp object
-+ * \return True if Software Isp is valid, false otherwise
-+ */
-+bool SoftwareIsp::isValid() const
-+{
-+	return !!debayer_;
-+}
-+
-+/**
-+  * \brief Get the output formats supported for the given input format
-+  * \param[in] inputFormat The input format
-+  * \return All the supported output formats or an empty vector if there are none
-+  */
-+std::vector<PixelFormat> SoftwareIsp::formats(PixelFormat inputFormat)
-+{
-+	ASSERT(debayer_ != nullptr);
-+
-+	return debayer_->formats(inputFormat);
-+}
-+
-+/**
-+ * \brief Get the supported output sizes for the given input format and size
-+ * \param[in] inputFormat The input format
-+ * \param[in] inputSize The input frame size
-+ * \return The valid size range or an empty range if there are none
-+ */
-+SizeRange SoftwareIsp::sizes(PixelFormat inputFormat, const Size &inputSize)
-+{
-+	ASSERT(debayer_ != nullptr);
-+
-+	return debayer_->sizes(inputFormat, inputSize);
-+}
-+
-+/**
-+ * Get the output stride and the frame size in bytes for the given output format and size
-+ * \param[in] outputFormat The output format
-+ * \param[in] size The output size (width and height in pixels)
-+ * \return A tuple of the stride and the frame size in bytes, or a tuple of 0,0
-+ * if there is no valid output config
-+ */
-+std::tuple<unsigned int, unsigned int>
-+SoftwareIsp::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size)
-+{
-+	ASSERT(debayer_ != nullptr);
-+
-+	return debayer_->strideAndFrameSize(outputFormat, size);
-+}
-+
-+/**
-+ * \brief Configure the SoftwareIsp object according to the passed in parameters
-+ * \param[in] inputCfg The input configuration
-+ * \param[in] outputCfgs The output configurations
-+ * \param[in] sensorControls ControlInfoMap of the controls supported by the sensor
-+ * \return 0 on success, a negative errno on failure
-+ */
-+int SoftwareIsp::configure(const StreamConfiguration &inputCfg,
-+			   const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs,
-+			   const ControlInfoMap &sensorControls)
-+{
-+	ASSERT(ipa_ != nullptr && debayer_ != nullptr);
-+
-+	int ret = ipa_->configure(sensorControls);
-+	if (ret < 0)
-+		return ret;
-+
-+	return debayer_->configure(inputCfg, outputCfgs);
-+}
-+
-+/**
-+ * \brief Export the buffers from the Software ISP
-+ * \param[in] output Output stream index exporting the buffers
-+ * \param[in] count Number of buffers to allocate
-+ * \param[out] buffers Vector to store the allocated buffers
-+ * \return The number of allocated buffers on success or a negative error code
-+ * otherwise
-+ */
-+int SoftwareIsp::exportBuffers(unsigned int output, unsigned int count,
-+			       std::vector<std::unique_ptr<FrameBuffer>> *buffers)
-+{
-+	ASSERT(debayer_ != nullptr);
-+
-+	/* single output for now */
-+	if (output >= 1)
-+		return -EINVAL;
-+
-+	for (unsigned int i = 0; i < count; i++) {
-+		const std::string name = "frame-" + std::to_string(i);
-+		const size_t frameSize = debayer_->frameSize();
-+
-+		FrameBuffer::Plane outPlane;
-+		outPlane.fd = SharedFD(dmaHeap_.alloc(name.c_str(), frameSize));
-+		if (!outPlane.fd.isValid()) {
-+			LOG(SoftwareIsp, Error)
-+				<< "failed to allocate a dma_buf";
-+			return -ENOMEM;
-+		}
-+		outPlane.offset = 0;
-+		outPlane.length = frameSize;
-+
-+		std::vector<FrameBuffer::Plane> planes{ outPlane };
-+		buffers->emplace_back(std::make_unique<FrameBuffer>(std::move(planes)));
-+	}
-+
-+	return count;
-+}
-+
-+/**
-+ * \brief Queue buffers to Software ISP
-+ * \param[in] input The input framebuffer
-+ * \param[in] outputs The container holding the output stream indexes and
-+ * their respective frame buffer outputs
-+ * \return 0 on success, a negative errno on failure
-+ */
-+int SoftwareIsp::queueBuffers(FrameBuffer *input,
-+			      const std::map<unsigned int, FrameBuffer *> &outputs)
-+{
-+	unsigned int mask = 0;
-+
-+	/*
-+	 * Validate the outputs as a sanity check: at least one output is
-+	 * required, all outputs must reference a valid stream and no two
-+	 * outputs can reference the same stream.
-+	 */
-+	if (outputs.empty())
-+		return -EINVAL;
-+
-+	for (auto [index, buffer] : outputs) {
-+		if (!buffer)
-+			return -EINVAL;
-+		if (index >= 1) /* only single stream atm */
-+			return -EINVAL;
-+		if (mask & (1 << index))
-+			return -EINVAL;
-+
-+		mask |= 1 << index;
-+	}
-+
-+	process(input, outputs.at(0));
-+
-+	return 0;
-+}
-+
-+/**
-+ * \brief Starts the Software ISP streaming operation
-+ * \return 0 on success, any other value indicates an error
-+ */
-+int SoftwareIsp::start()
-+{
-+	int ret = ipa_->start();
-+	if (ret)
-+		return ret;
-+
-+	ispWorkerThread_.start();
-+	return 0;
-+}
-+
-+/**
-+ * \brief Stops the Software ISP streaming operation
-+ */
-+void SoftwareIsp::stop()
-+{
-+	ispWorkerThread_.exit();
-+	ispWorkerThread_.wait();
-+
-+	ipa_->stop();
-+}
-+
-+/**
-+ * \brief Passes the input framebuffer to the ISP worker to process
-+ * \param[in] input The input framebuffer
-+ * \param[out] output The framebuffer to write the processed frame to
-+ */
-+void SoftwareIsp::process(FrameBuffer *input, FrameBuffer *output)
-+{
-+	debayer_->invokeMethod(&DebayerCpu::process,
-+			       ConnectionTypeQueued, input, output, debayerParams_);
-+}
-+
-+void SoftwareIsp::saveIspParams([[maybe_unused]] int dummy)
-+{
-+	debayerParams_ = *sharedParams_;
-+}
-+
-+void SoftwareIsp::setSensorCtrls(const ControlList &sensorControls)
-+{
-+	setSensorControls.emit(sensorControls);
-+}
-+
-+void SoftwareIsp::statsReady(int dummy)
-+{
-+	ispStatsReady.emit(dummy);
-+}
-+
-+void SoftwareIsp::inputReady(FrameBuffer *input)
-+{
-+	inputBufferReady.emit(input);
-+}
-+
-+void SoftwareIsp::outputReady(FrameBuffer *output)
-+{
-+	outputBufferReady.emit(output);
-+}
-+
-+} /* namespace libcamera */
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0011-libcamera-pipeline-simple-rename-converterBuffers_-a.patch b/users/flokli/ipu6-softisp/libcamera/0011-libcamera-pipeline-simple-rename-converterBuffers_-a.patch
deleted file mode 100644
index 5c2237a8eb01..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0011-libcamera-pipeline-simple-rename-converterBuffers_-a.patch
+++ /dev/null
@@ -1,240 +0,0 @@
-From 050440eed6ab90686df217f5ff7dea0b241e3898 Mon Sep 17 00:00:00 2001
-From: Andrey Konovalov <andrey.konovalov@linaro.org>
-Date: Mon, 11 Mar 2024 15:15:15 +0100
-Subject: [PATCH 11/21] libcamera: pipeline: simple: rename converterBuffers_
- and related vars
-
-The converterBuffers_ and the converterQueue_ are not that specific
-to the Converter, and could be used by another entity doing the format
-conversion.
-
-Rename converterBuffers_, converterQueue_, and useConverter_ to
-conversionBuffers_, conversionQueue_ and useConversion_ to
-disassociate them from the Converter.
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- src/libcamera/pipeline/simple/simple.cpp | 63 ++++++++++++------------
- 1 file changed, 32 insertions(+), 31 deletions(-)
-
-diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
-index a84f6760..78854ef8 100644
---- a/src/libcamera/pipeline/simple/simple.cpp
-+++ b/src/libcamera/pipeline/simple/simple.cpp
-@@ -269,17 +269,18 @@ public:
- 	std::vector<Configuration> configs_;
- 	std::map<PixelFormat, std::vector<const Configuration *>> formats_;
- 
-+	std::vector<std::unique_ptr<FrameBuffer>> conversionBuffers_;
-+	std::queue<std::map<unsigned int, FrameBuffer *>> conversionQueue_;
-+	bool useConversion_;
-+
- 	std::unique_ptr<Converter> converter_;
--	std::vector<std::unique_ptr<FrameBuffer>> converterBuffers_;
--	bool useConverter_;
--	std::queue<std::map<unsigned int, FrameBuffer *>> converterQueue_;
- 
- private:
- 	void tryPipeline(unsigned int code, const Size &size);
- 	static std::vector<const MediaPad *> routedSourcePads(MediaPad *sink);
- 
--	void converterInputDone(FrameBuffer *buffer);
--	void converterOutputDone(FrameBuffer *buffer);
-+	void conversionInputDone(FrameBuffer *buffer);
-+	void conversionOutputDone(FrameBuffer *buffer);
- };
- 
- class SimpleCameraConfiguration : public CameraConfiguration
-@@ -503,8 +504,8 @@ int SimpleCameraData::init()
- 				<< "Failed to create converter, disabling format conversion";
- 			converter_.reset();
- 		} else {
--			converter_->inputBufferReady.connect(this, &SimpleCameraData::converterInputDone);
--			converter_->outputBufferReady.connect(this, &SimpleCameraData::converterOutputDone);
-+			converter_->inputBufferReady.connect(this, &SimpleCameraData::conversionInputDone);
-+			converter_->outputBufferReady.connect(this, &SimpleCameraData::conversionOutputDone);
- 		}
- 	}
- 
-@@ -740,7 +741,7 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)
- 	 * point converting an erroneous buffer.
- 	 */
- 	if (buffer->metadata().status != FrameMetadata::FrameSuccess) {
--		if (!useConverter_) {
-+		if (!useConversion_) {
- 			/* No conversion, just complete the request. */
- 			Request *request = buffer->request();
- 			pipe->completeBuffer(request, buffer);
-@@ -756,16 +757,16 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)
- 		if (buffer->metadata().status != FrameMetadata::FrameCancelled)
- 			video_->queueBuffer(buffer);
- 
--		if (converterQueue_.empty())
-+		if (conversionQueue_.empty())
- 			return;
- 
- 		Request *request = nullptr;
--		for (auto &item : converterQueue_.front()) {
-+		for (auto &item : conversionQueue_.front()) {
- 			FrameBuffer *outputBuffer = item.second;
- 			request = outputBuffer->request();
- 			pipe->completeBuffer(request, outputBuffer);
- 		}
--		converterQueue_.pop();
-+		conversionQueue_.pop();
- 
- 		if (request)
- 			pipe->completeRequest(request);
-@@ -782,9 +783,9 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)
- 	 */
- 	Request *request = buffer->request();
- 
--	if (useConverter_ && !converterQueue_.empty()) {
-+	if (useConversion_ && !conversionQueue_.empty()) {
- 		const std::map<unsigned int, FrameBuffer *> &outputs =
--			converterQueue_.front();
-+			conversionQueue_.front();
- 		if (!outputs.empty()) {
- 			FrameBuffer *outputBuffer = outputs.begin()->second;
- 			if (outputBuffer)
-@@ -801,14 +802,14 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)
- 	 * conversion is needed. If there's no queued request, just requeue the
- 	 * captured buffer for capture.
- 	 */
--	if (useConverter_) {
--		if (converterQueue_.empty()) {
-+	if (useConversion_) {
-+		if (conversionQueue_.empty()) {
- 			video_->queueBuffer(buffer);
- 			return;
- 		}
- 
--		converter_->queueBuffers(buffer, converterQueue_.front());
--		converterQueue_.pop();
-+		converter_->queueBuffers(buffer, conversionQueue_.front());
-+		conversionQueue_.pop();
- 		return;
- 	}
- 
-@@ -817,13 +818,13 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)
- 	pipe->completeRequest(request);
- }
- 
--void SimpleCameraData::converterInputDone(FrameBuffer *buffer)
-+void SimpleCameraData::conversionInputDone(FrameBuffer *buffer)
- {
- 	/* Queue the input buffer back for capture. */
- 	video_->queueBuffer(buffer);
- }
- 
--void SimpleCameraData::converterOutputDone(FrameBuffer *buffer)
-+void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer)
- {
- 	SimplePipelineHandler *pipe = SimpleCameraData::pipe();
- 
-@@ -1189,14 +1190,14 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)
- 
- 	/* Configure the converter if needed. */
- 	std::vector<std::reference_wrapper<StreamConfiguration>> outputCfgs;
--	data->useConverter_ = config->needConversion();
-+	data->useConversion_ = config->needConversion();
- 
- 	for (unsigned int i = 0; i < config->size(); ++i) {
- 		StreamConfiguration &cfg = config->at(i);
- 
- 		cfg.setStream(&data->streams_[i]);
- 
--		if (data->useConverter_)
-+		if (data->useConversion_)
- 			outputCfgs.push_back(cfg);
- 	}
- 
-@@ -1222,7 +1223,7 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,
- 	 * Export buffers on the converter or capture video node, depending on
- 	 * whether the converter is used or not.
- 	 */
--	if (data->useConverter_)
-+	if (data->useConversion_)
- 		return data->converter_->exportBuffers(data->streamIndex(stream),
- 						       count, buffers);
- 	else
-@@ -1243,13 +1244,13 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL
- 		return -EBUSY;
- 	}
- 
--	if (data->useConverter_) {
-+	if (data->useConversion_) {
- 		/*
- 		 * When using the converter allocate a fixed number of internal
- 		 * buffers.
- 		 */
- 		ret = video->allocateBuffers(kNumInternalBuffers,
--					     &data->converterBuffers_);
-+					     &data->conversionBuffers_);
- 	} else {
- 		/* Otherwise, prepare for using buffers from the only stream. */
- 		Stream *stream = &data->streams_[0];
-@@ -1268,7 +1269,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL
- 		return ret;
- 	}
- 
--	if (data->useConverter_) {
-+	if (data->useConversion_) {
- 		ret = data->converter_->start();
- 		if (ret < 0) {
- 			stop(camera);
-@@ -1276,7 +1277,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL
- 		}
- 
- 		/* Queue all internal buffers for capture. */
--		for (std::unique_ptr<FrameBuffer> &buffer : data->converterBuffers_)
-+		for (std::unique_ptr<FrameBuffer> &buffer : data->conversionBuffers_)
- 			video->queueBuffer(buffer.get());
- 	}
- 
-@@ -1288,7 +1289,7 @@ void SimplePipelineHandler::stopDevice(Camera *camera)
- 	SimpleCameraData *data = cameraData(camera);
- 	V4L2VideoDevice *video = data->video_;
- 
--	if (data->useConverter_)
-+	if (data->useConversion_)
- 		data->converter_->stop();
- 
- 	video->streamOff();
-@@ -1296,7 +1297,7 @@ void SimplePipelineHandler::stopDevice(Camera *camera)
- 
- 	video->bufferReady.disconnect(data, &SimpleCameraData::bufferReady);
- 
--	data->converterBuffers_.clear();
-+	data->conversionBuffers_.clear();
- 
- 	releasePipeline(data);
- }
-@@ -1314,7 +1315,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request)
- 		 * queue, it will be handed to the converter in the capture
- 		 * completion handler.
- 		 */
--		if (data->useConverter_) {
-+		if (data->useConversion_) {
- 			buffers.emplace(data->streamIndex(stream), buffer);
- 		} else {
- 			ret = data->video_->queueBuffer(buffer);
-@@ -1323,8 +1324,8 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request)
- 		}
- 	}
- 
--	if (data->useConverter_)
--		data->converterQueue_.push(std::move(buffers));
-+	if (data->useConversion_)
-+		data->conversionQueue_.push(std::move(buffers));
- 
- 	return 0;
- }
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch b/users/flokli/ipu6-softisp/libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch
deleted file mode 100644
index 378a43604f9a..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch
+++ /dev/null
@@ -1,302 +0,0 @@
-From d64b0fca22ef25b8a14d7fc97dfab64eb1c4f21a Mon Sep 17 00:00:00 2001
-From: Andrey Konovalov <andrey.konovalov@linaro.org>
-Date: Mon, 11 Mar 2024 15:15:16 +0100
-Subject: [PATCH 12/21] libcamera: pipeline: simple: enable use of Soft ISP and
- Soft IPA
-
-To enable the Simple Soft ISP and Soft IPA for simple pipeline handler
-configure the build with:
-  -Dpipelines=simple -Dipas=simple
-
-Also using the Soft ISP for the particular hardware platform must
-be enabled in the supportedDevices[] table.
-
-If the pipeline uses Converter, Soft ISP and Soft IPA aren't
-available.
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- src/libcamera/pipeline/simple/simple.cpp | 137 ++++++++++++++++++-----
- 1 file changed, 109 insertions(+), 28 deletions(-)
-
-diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
-index 78854ef8..c3ebb7b7 100644
---- a/src/libcamera/pipeline/simple/simple.cpp
-+++ b/src/libcamera/pipeline/simple/simple.cpp
-@@ -34,6 +34,7 @@
- #include "libcamera/internal/device_enumerator.h"
- #include "libcamera/internal/media_device.h"
- #include "libcamera/internal/pipeline_handler.h"
-+#include "libcamera/internal/software_isp/software_isp.h"
- #include "libcamera/internal/v4l2_subdevice.h"
- #include "libcamera/internal/v4l2_videodevice.h"
- 
-@@ -185,17 +186,22 @@ struct SimplePipelineInfo {
- 	 * and the number of streams it supports.
- 	 */
- 	std::vector<std::pair<const char *, unsigned int>> converters;
-+	/*
-+	 * Using Software ISP is to be enabled per driver.
-+	 * The Software ISP can't be used together with the converters.
-+	 */
-+	bool swIspEnabled;
- };
- 
- namespace {
- 
- static const SimplePipelineInfo supportedDevices[] = {
--	{ "dcmipp", {} },
--	{ "imx7-csi", { { "pxp", 1 } } },
--	{ "j721e-csi2rx", {} },
--	{ "mxc-isi", {} },
--	{ "qcom-camss", {} },
--	{ "sun6i-csi", {} },
-+	{ "dcmipp", {}, false },
-+	{ "imx7-csi", { { "pxp", 1 } }, false },
-+	{ "j721e-csi2rx", {}, false },
-+	{ "mxc-isi", {}, false },
-+	{ "qcom-camss", {}, true },
-+	{ "sun6i-csi", {}, false },
- };
- 
- } /* namespace */
-@@ -274,6 +280,7 @@ public:
- 	bool useConversion_;
- 
- 	std::unique_ptr<Converter> converter_;
-+	std::unique_ptr<SoftwareIsp> swIsp_;
- 
- private:
- 	void tryPipeline(unsigned int code, const Size &size);
-@@ -281,6 +288,9 @@ private:
- 
- 	void conversionInputDone(FrameBuffer *buffer);
- 	void conversionOutputDone(FrameBuffer *buffer);
-+
-+	void ispStatsReady(int dummy);
-+	void setSensorControls(const ControlList &sensorControls);
- };
- 
- class SimpleCameraConfiguration : public CameraConfiguration
-@@ -332,6 +342,7 @@ public:
- 	V4L2VideoDevice *video(const MediaEntity *entity);
- 	V4L2Subdevice *subdev(const MediaEntity *entity);
- 	MediaDevice *converter() { return converter_; }
-+	bool swIspEnabled() { return swIspEnabled_; }
- 
- protected:
- 	int queueRequestDevice(Camera *camera, Request *request) override;
-@@ -360,6 +371,7 @@ private:
- 	std::map<const MediaEntity *, EntityData> entities_;
- 
- 	MediaDevice *converter_;
-+	bool swIspEnabled_;
- };
- 
- /* -----------------------------------------------------------------------------
-@@ -509,6 +521,29 @@ int SimpleCameraData::init()
- 		}
- 	}
- 
-+	/*
-+	 * Instantiate Soft ISP if this is enabled for the given driver and no converter is used.
-+	 */
-+	if (!converter_ && pipe->swIspEnabled()) {
-+		swIsp_ = std::make_unique<SoftwareIsp>(pipe, sensor_->controls());
-+		if (!swIsp_->isValid()) {
-+			LOG(SimplePipeline, Warning)
-+				<< "Failed to create software ISP, disabling software debayering";
-+			swIsp_.reset();
-+		} else {
-+			/*
-+			 * \todo explain why SimpleCameraData::conversionInputDone() can't be directly
-+			 * connected to inputBufferReady signal.
-+			 */
-+			swIsp_->inputBufferReady.connect(pipe, [this](FrameBuffer *buffer) {
-+				this->conversionInputDone(buffer);
-+			});
-+			swIsp_->outputBufferReady.connect(this, &SimpleCameraData::conversionOutputDone);
-+			swIsp_->ispStatsReady.connect(this, &SimpleCameraData::ispStatsReady);
-+			swIsp_->setSensorControls.connect(this, &SimpleCameraData::setSensorControls);
-+		}
-+	}
-+
- 	video_ = pipe->video(entities_.back().entity);
- 	ASSERT(video_);
- 
-@@ -599,12 +634,21 @@ void SimpleCameraData::tryPipeline(unsigned int code, const Size &size)
- 		config.captureFormat = pixelFormat;
- 		config.captureSize = format.size;
- 
--		if (!converter_) {
-+
-+		if (converter_) {
-+ 			config.outputFormats = converter_->formats(pixelFormat);
-+ 			config.outputSizes = converter_->sizes(format.size);
-+		} else if (swIsp_) {
-+			config.outputFormats = swIsp_->formats(pixelFormat);
-+			config.outputSizes = swIsp_->sizes(pixelFormat, format.size);
-+			if (config.outputFormats.empty()) {
-+				/* Do not use swIsp for unsupported pixelFormat's: */
-+				config.outputFormats = { pixelFormat };
-+				config.outputSizes = config.captureSize;
-+			}
-+		} else {
- 			config.outputFormats = { pixelFormat };
- 			config.outputSizes = config.captureSize;
--		} else {
--			config.outputFormats = converter_->formats(pixelFormat);
--			config.outputSizes = converter_->sizes(format.size);
- 		}
- 
- 		configs_.push_back(config);
-@@ -750,9 +794,9 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)
- 		}
- 
- 		/*
--		 * The converter is in use. Requeue the internal buffer for
--		 * capture (unless the stream is being stopped), and complete
--		 * the request with all the user-facing buffers.
-+		 * The converter or Software ISP is in use. Requeue the internal
-+		 * buffer for capture (unless the stream is being stopped), and
-+		 * complete the request with all the user-facing buffers.
- 		 */
- 		if (buffer->metadata().status != FrameMetadata::FrameCancelled)
- 			video_->queueBuffer(buffer);
-@@ -798,9 +842,9 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)
- 					buffer->metadata().timestamp);
- 
- 	/*
--	 * Queue the captured and the request buffer to the converter if format
--	 * conversion is needed. If there's no queued request, just requeue the
--	 * captured buffer for capture.
-+	 * Queue the captured and the request buffer to the converter or Software
-+	 * ISP if format conversion is needed. If there's no queued request, just
-+	 * requeue the captured buffer for capture.
- 	 */
- 	if (useConversion_) {
- 		if (conversionQueue_.empty()) {
-@@ -808,7 +852,11 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)
- 			return;
- 		}
- 
--		converter_->queueBuffers(buffer, conversionQueue_.front());
-+		if (converter_)
-+			converter_->queueBuffers(buffer, conversionQueue_.front());
-+		else
-+			swIsp_->queueBuffers(buffer, conversionQueue_.front());
-+
- 		conversionQueue_.pop();
- 		return;
- 	}
-@@ -834,6 +882,18 @@ void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer)
- 		pipe->completeRequest(request);
- }
- 
-+void SimpleCameraData::ispStatsReady([[maybe_unused]] int dummy)
-+{
-+	swIsp_->processStats(sensor_->getControls({ V4L2_CID_ANALOGUE_GAIN,
-+						    V4L2_CID_EXPOSURE }));
-+}
-+
-+void SimpleCameraData::setSensorControls(const ControlList &sensorControls)
-+{
-+	ControlList ctrls(sensorControls);
-+	sensor_->setControls(&ctrls);
-+}
-+
- /* Retrieve all source pads connected to a sink pad through active routes. */
- std::vector<const MediaPad *> SimpleCameraData::routedSourcePads(MediaPad *sink)
- {
-@@ -1046,8 +1106,10 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()
- 		/* Set the stride, frameSize and bufferCount. */
- 		if (needConversion_) {
- 			std::tie(cfg.stride, cfg.frameSize) =
--				data_->converter_->strideAndFrameSize(cfg.pixelFormat,
--								      cfg.size);
-+				(data_->converter_) ? data_->converter_->strideAndFrameSize(cfg.pixelFormat,
-+											    cfg.size)
-+						    : data_->swIsp_->strideAndFrameSize(cfg.pixelFormat,
-+											cfg.size);
- 			if (cfg.stride == 0)
- 				return Invalid;
- 		} else {
-@@ -1210,7 +1272,9 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)
- 	inputCfg.stride = captureFormat.planes[0].bpl;
- 	inputCfg.bufferCount = kNumInternalBuffers;
- 
--	return data->converter_->configure(inputCfg, outputCfgs);
-+	return (data->converter_) ? data->converter_->configure(inputCfg, outputCfgs)
-+				  : data->swIsp_->configure(inputCfg, outputCfgs,
-+							    data->sensor_->controls());
- }
- 
- int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,
-@@ -1224,8 +1288,10 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,
- 	 * whether the converter is used or not.
- 	 */
- 	if (data->useConversion_)
--		return data->converter_->exportBuffers(data->streamIndex(stream),
--						       count, buffers);
-+		return (data->converter_) ? data->converter_->exportBuffers(data->streamIndex(stream),
-+									    count, buffers)
-+					  : data->swIsp_->exportBuffers(data->streamIndex(stream),
-+									count, buffers);
- 	else
- 		return data->video_->exportBuffers(count, buffers);
- }
-@@ -1270,10 +1336,18 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL
- 	}
- 
- 	if (data->useConversion_) {
--		ret = data->converter_->start();
--		if (ret < 0) {
--			stop(camera);
--			return ret;
-+		if (data->converter_) {
-+			ret = data->converter_->start();
-+			if (ret < 0) {
-+				stop(camera);
-+				return ret;
-+			}
-+		} else if (data->swIsp_) {
-+			ret = data->swIsp_->start();
-+			if (ret < 0) {
-+				stop(camera);
-+				return ret;
-+			}
- 		}
- 
- 		/* Queue all internal buffers for capture. */
-@@ -1289,8 +1363,13 @@ void SimplePipelineHandler::stopDevice(Camera *camera)
- 	SimpleCameraData *data = cameraData(camera);
- 	V4L2VideoDevice *video = data->video_;
- 
--	if (data->useConversion_)
--		data->converter_->stop();
-+	if (data->useConversion_) {
-+		if (data->converter_)
-+			data->converter_->stop();
-+		else if (data->swIsp_) {
-+			data->swIsp_->stop();
-+		}
-+	}
- 
- 	video->streamOff();
- 	video->releaseBuffers();
-@@ -1452,6 +1531,8 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
- 		}
- 	}
- 
-+  swIspEnabled_ = info->swIspEnabled;
-+
- 	/* Locate the sensors. */
- 	std::vector<MediaEntity *> sensors = locateSensors();
- 	if (sensors.empty()) {
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0013-libcamera-swstats_cpu-Add-support-for-8-10-and-12-bp.patch b/users/flokli/ipu6-softisp/libcamera/0013-libcamera-swstats_cpu-Add-support-for-8-10-and-12-bp.patch
deleted file mode 100644
index 1a57d690ff91..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0013-libcamera-swstats_cpu-Add-support-for-8-10-and-12-bp.patch
+++ /dev/null
@@ -1,203 +0,0 @@
-From aabc53453d542495d9da25411f57308c01f2bc28 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Mon, 11 Mar 2024 15:15:17 +0100
-Subject: [PATCH 13/21] libcamera: swstats_cpu: Add support for 8, 10 and 12
- bpp unpacked bayer input
-
-Add support for 8, 10 and 12 bpp unpacked bayer input for all 4 standard
-bayer orders.
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- src/libcamera/software_isp/swstats_cpu.cpp | 128 +++++++++++++++++++++
- src/libcamera/software_isp/swstats_cpu.h   |   9 ++
- 2 files changed, 137 insertions(+)
-
-diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp
-index 448d0e4c..be310f56 100644
---- a/src/libcamera/software_isp/swstats_cpu.cpp
-+++ b/src/libcamera/software_isp/swstats_cpu.cpp
-@@ -71,6 +71,83 @@ static const unsigned int kBlueYMul = 29; /* 0.114 * 256 */
- 	stats_.sumG_ += sumG;       \
- 	stats_.sumB_ += sumB;
- 
-+void SwStatsCpu::statsBGGR8Line0(const uint8_t *src[])
-+{
-+	const uint8_t *src0 = src[1] + window_.x;
-+	const uint8_t *src1 = src[2] + window_.x;
-+
-+	SWSTATS_START_LINE_STATS(uint8_t)
-+
-+	if (swapLines_)
-+		std::swap(src0, src1);
-+
-+	/* x += 4 sample every other 2x2 block */
-+	for (int x = 0; x < (int)window_.width; x += 4) {
-+		b = src0[x];
-+		g = src0[x + 1];
-+		g2 = src1[x];
-+		r = src1[x + 1];
-+
-+		g = (g + g2) / 2;
-+
-+		SWSTATS_ACCUMULATE_LINE_STATS(1)
-+	}
-+
-+	SWSTATS_FINISH_LINE_STATS()
-+}
-+
-+void SwStatsCpu::statsBGGR10Line0(const uint8_t *src[])
-+{
-+	const uint16_t *src0 = (const uint16_t *)src[1] + window_.x;
-+	const uint16_t *src1 = (const uint16_t *)src[2] + window_.x;
-+
-+	SWSTATS_START_LINE_STATS(uint16_t)
-+
-+	if (swapLines_)
-+		std::swap(src0, src1);
-+
-+	/* x += 4 sample every other 2x2 block */
-+	for (int x = 0; x < (int)window_.width; x += 4) {
-+		b = src0[x];
-+		g = src0[x + 1];
-+		g2 = src1[x];
-+		r = src1[x + 1];
-+
-+		g = (g + g2) / 2;
-+
-+		/* divide Y by 4 for 10 -> 8 bpp value */
-+		SWSTATS_ACCUMULATE_LINE_STATS(4)
-+	}
-+
-+	SWSTATS_FINISH_LINE_STATS()
-+}
-+
-+void SwStatsCpu::statsBGGR12Line0(const uint8_t *src[])
-+{
-+	const uint16_t *src0 = (const uint16_t *)src[1] + window_.x;
-+	const uint16_t *src1 = (const uint16_t *)src[2] + window_.x;
-+
-+	SWSTATS_START_LINE_STATS(uint16_t)
-+
-+	if (swapLines_)
-+		std::swap(src0, src1);
-+
-+	/* x += 4 sample every other 2x2 block */
-+	for (int x = 0; x < (int)window_.width; x += 4) {
-+		b = src0[x];
-+		g = src0[x + 1];
-+		g2 = src1[x];
-+		r = src1[x + 1];
-+
-+		g = (g + g2) / 2;
-+
-+		/* divide Y by 16 for 12 -> 8 bpp value */
-+		SWSTATS_ACCUMULATE_LINE_STATS(16)
-+	}
-+
-+	SWSTATS_FINISH_LINE_STATS()
-+}
-+
- void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src[])
- {
- 	const uint8_t *src0 = src[1] + window_.x * 5 / 4;
-@@ -147,6 +224,42 @@ void SwStatsCpu::finishFrame(void)
- 	statsReady.emit(0);
- }
- 
-+/**
-+ * \brief Setup SwStatsCpu object for standard Bayer orders
-+ * \param[in] order The Bayer order
-+ *
-+ * Check if order is a standard Bayer order and setup xShift_ and swapLines_
-+ * so that a single BGGR stats function can be used for all 4 standard orders.
-+ */
-+int SwStatsCpu::setupStandardBayerOrder(BayerFormat::Order order)
-+{
-+	switch (order) {
-+	case BayerFormat::BGGR:
-+		xShift_ = 0;
-+		swapLines_ = false;
-+		break;
-+	case BayerFormat::GBRG:
-+		xShift_ = 1; /* BGGR -> GBRG */
-+		swapLines_ = false;
-+		break;
-+	case BayerFormat::GRBG:
-+		xShift_ = 0;
-+		swapLines_ = true; /* BGGR -> GRBG */
-+		break;
-+	case BayerFormat::RGGB:
-+		xShift_ = 1; /* BGGR -> GBRG */
-+		swapLines_ = true; /* GBRG -> RGGB */
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	patternSize_.height = 2;
-+	patternSize_.width = 2;
-+	ySkipMask_ = 0x02; /* Skip every 3th and 4th line */
-+	return 0;
-+}
-+
- /**
-  * \brief Configure the statistics object for the passed in input format.
-  * \param[in] inputCfg The input format
-@@ -158,6 +271,21 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
- 	BayerFormat bayerFormat =
- 		BayerFormat::fromPixelFormat(inputCfg.pixelFormat);
- 
-+	if (bayerFormat.packing == BayerFormat::Packing::None &&
-+	    setupStandardBayerOrder(bayerFormat.order) == 0) {
-+		switch (bayerFormat.bitDepth) {
-+		case 8:
-+			stats0_ = &SwStatsCpu::statsBGGR8Line0;
-+			return 0;
-+		case 10:
-+			stats0_ = &SwStatsCpu::statsBGGR10Line0;
-+			return 0;
-+		case 12:
-+			stats0_ = &SwStatsCpu::statsBGGR12Line0;
-+			return 0;
-+		}
-+	}
-+
- 	if (bayerFormat.bitDepth == 10 &&
- 	    bayerFormat.packing == BayerFormat::Packing::CSI2) {
- 		patternSize_.height = 2;
-diff --git a/src/libcamera/software_isp/swstats_cpu.h b/src/libcamera/software_isp/swstats_cpu.h
-index 0ac9ae71..bbbcf69b 100644
---- a/src/libcamera/software_isp/swstats_cpu.h
-+++ b/src/libcamera/software_isp/swstats_cpu.h
-@@ -17,6 +17,7 @@
- 
- #include <libcamera/geometry.h>
- 
-+#include "libcamera/internal/bayer_format.h"
- #include "libcamera/internal/shared_mem_object.h"
- #include "libcamera/internal/software_isp/swisp_stats.h"
- 
-@@ -120,6 +121,14 @@ private:
- 	 */
- 	using statsProcessFn = void (SwStatsCpu::*)(const uint8_t *src[]);
- 
-+	int setupStandardBayerOrder(BayerFormat::Order order);
-+	/* Bayer 8 bpp unpacked */
-+	void statsBGGR8Line0(const uint8_t *src[]);
-+	/* Bayer 10 bpp unpacked */
-+	void statsBGGR10Line0(const uint8_t *src[]);
-+	/* Bayer 12 bpp unpacked */
-+	void statsBGGR12Line0(const uint8_t *src[]);
-+	/* Bayer 10 bpp packed */
- 	void statsBGGR10PLine0(const uint8_t *src[]);
- 	void statsGBRG10PLine0(const uint8_t *src[]);
- 
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0014-libcamera-debayer_cpu-Add-support-for-8-10-and-12-bp.patch b/users/flokli/ipu6-softisp/libcamera/0014-libcamera-debayer_cpu-Add-support-for-8-10-and-12-bp.patch
deleted file mode 100644
index c7edf498280e..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0014-libcamera-debayer_cpu-Add-support-for-8-10-and-12-bp.patch
+++ /dev/null
@@ -1,234 +0,0 @@
-From 5f3647bd4f12dd62256a425c49fd18a0f5990930 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Mon, 11 Mar 2024 15:15:18 +0100
-Subject: [PATCH 14/21] libcamera: debayer_cpu: Add support for 8, 10 and 12
- bpp unpacked bayer input
-
-Add support for 8, 10 and 12 bpp unpacked bayer input for all 4 standard
-bayer orders.
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
-Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- src/libcamera/software_isp/debayer_cpu.cpp | 128 +++++++++++++++++++++
- src/libcamera/software_isp/debayer_cpu.h   |  13 +++
- 2 files changed, 141 insertions(+)
-
-diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
-index f932362c..eb1c2718 100644
---- a/src/libcamera/software_isp/debayer_cpu.cpp
-+++ b/src/libcamera/software_isp/debayer_cpu.cpp
-@@ -56,6 +56,11 @@ DebayerCpu::~DebayerCpu()
- 		free(lineBuffers_[i]);
- }
- 
-+#define DECLARE_SRC_POINTERS(pixel_t)                            \
-+	const pixel_t *prev = (const pixel_t *)src[0] + xShift_; \
-+	const pixel_t *curr = (const pixel_t *)src[1] + xShift_; \
-+	const pixel_t *next = (const pixel_t *)src[2] + xShift_;
-+
- // RGR
- // GBG
- // RGR
-@@ -92,6 +97,70 @@ DebayerCpu::~DebayerCpu()
- 	*dst++ = red_[curr[x] / (div)];                                                        \
- 	x++;
- 
-+void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
-+{
-+	DECLARE_SRC_POINTERS(uint8_t)
-+
-+	for (int x = 0; x < (int)window_.width;) {
-+		BGGR_BGR888(1, 1, 1)
-+		GBRG_BGR888(1, 1, 1)
-+	}
-+}
-+
-+void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
-+{
-+	DECLARE_SRC_POINTERS(uint8_t)
-+
-+	for (int x = 0; x < (int)window_.width;) {
-+		GRBG_BGR888(1, 1, 1)
-+		RGGB_BGR888(1, 1, 1)
-+	}
-+}
-+
-+void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
-+{
-+	DECLARE_SRC_POINTERS(uint16_t)
-+
-+	for (int x = 0; x < (int)window_.width;) {
-+		/* divide values by 4 for 10 -> 8 bpp value */
-+		BGGR_BGR888(1, 1, 4)
-+		GBRG_BGR888(1, 1, 4)
-+	}
-+}
-+
-+void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
-+{
-+	DECLARE_SRC_POINTERS(uint16_t)
-+
-+	for (int x = 0; x < (int)window_.width;) {
-+		/* divide values by 4 for 10 -> 8 bpp value */
-+		GRBG_BGR888(1, 1, 4)
-+		RGGB_BGR888(1, 1, 4)
-+	}
-+}
-+
-+void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
-+{
-+	DECLARE_SRC_POINTERS(uint16_t)
-+
-+	for (int x = 0; x < (int)window_.width;) {
-+		/* divide values by 16 for 12 -> 8 bpp value */
-+		BGGR_BGR888(1, 1, 16)
-+		GBRG_BGR888(1, 1, 16)
-+	}
-+}
-+
-+void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
-+{
-+	DECLARE_SRC_POINTERS(uint16_t)
-+
-+	for (int x = 0; x < (int)window_.width;) {
-+		/* divide values by 16 for 12 -> 8 bpp value */
-+		GRBG_BGR888(1, 1, 16)
-+		RGGB_BGR888(1, 1, 16)
-+	}
-+}
-+
- void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
- {
- 	const int width_in_bytes = window_.width * 5 / 4;
-@@ -193,6 +262,16 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf
- 	BayerFormat bayerFormat =
- 		BayerFormat::fromPixelFormat(inputFormat);
- 
-+	if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) &&
-+	    bayerFormat.packing == BayerFormat::Packing::None &&
-+	    isStandardBayerOrder(bayerFormat.order)) {
-+		config.bpp = (bayerFormat.bitDepth + 7) & ~7;
-+		config.patternSize.width = 2;
-+		config.patternSize.height = 2;
-+		config.outputFormats = std::vector<PixelFormat>({ formats::RGB888 });
-+		return 0;
-+	}
-+
- 	if (bayerFormat.bitDepth == 10 &&
- 	    bayerFormat.packing == BayerFormat::Packing::CSI2 &&
- 	    isStandardBayerOrder(bayerFormat.order)) {
-@@ -220,12 +299,61 @@ int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &c
- 	return -EINVAL;
- }
- 
-+/*
-+ * Check for standard Bayer orders and set xShift_ and swap debayer0/1, so that
-+ * a single pair of BGGR debayer functions can be used for all 4 standard orders.
-+ */
-+int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order)
-+{
-+	switch (order) {
-+	case BayerFormat::BGGR:
-+		break;
-+	case BayerFormat::GBRG:
-+		xShift_ = 1; /* BGGR -> GBRG */
-+		break;
-+	case BayerFormat::GRBG:
-+		std::swap(debayer0_, debayer1_); /* BGGR -> GRBG */
-+		break;
-+	case BayerFormat::RGGB:
-+		xShift_ = 1; /* BGGR -> GBRG */
-+		std::swap(debayer0_, debayer1_); /* GBRG -> RGGB */
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	return 0;
-+}
-+
- /* TODO: this ignores outputFormat since there is only 1 supported outputFormat for now */
- int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] PixelFormat outputFormat)
- {
- 	BayerFormat bayerFormat =
- 		BayerFormat::fromPixelFormat(inputFormat);
- 
-+	xShift_ = 0;
-+
-+	if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) &&
-+	    bayerFormat.packing == BayerFormat::Packing::None &&
-+	    isStandardBayerOrder(bayerFormat.order)) {
-+		switch (bayerFormat.bitDepth) {
-+		case 8:
-+			debayer0_ = &DebayerCpu::debayer8_BGBG_BGR888;
-+			debayer1_ = &DebayerCpu::debayer8_GRGR_BGR888;
-+			break;
-+		case 10:
-+			debayer0_ = &DebayerCpu::debayer10_BGBG_BGR888;
-+			debayer1_ = &DebayerCpu::debayer10_GRGR_BGR888;
-+			break;
-+		case 12:
-+			debayer0_ = &DebayerCpu::debayer12_BGBG_BGR888;
-+			debayer1_ = &DebayerCpu::debayer12_GRGR_BGR888;
-+			break;
-+		}
-+		setupStandardBayerOrder(bayerFormat.order);
-+		return 0;
-+	}
-+
- 	if (bayerFormat.bitDepth == 10 &&
- 	    bayerFormat.packing == BayerFormat::Packing::CSI2) {
- 		switch (bayerFormat.order) {
-diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h
-index 8a51ed85..fd1fa180 100644
---- a/src/libcamera/software_isp/debayer_cpu.h
-+++ b/src/libcamera/software_isp/debayer_cpu.h
-@@ -17,6 +17,8 @@
- 
- #include <libcamera/base/object.h>
- 
-+#include "libcamera/internal/bayer_format.h"
-+
- #include "debayer.h"
- #include "swstats_cpu.h"
- 
-@@ -82,6 +84,15 @@ private:
- 	 */
- 	using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]);
- 
-+	/* 8-bit raw bayer format */
-+	void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
-+	void debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
-+	/* unpacked 10-bit raw bayer format */
-+	void debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
-+	void debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
-+	/* unpacked 12-bit raw bayer format */
-+	void debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
-+	void debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
- 	/* CSI-2 packed 10-bit raw bayer format (all the 4 orders) */
- 	void debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
- 	void debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
-@@ -103,6 +114,7 @@ private:
- 
- 	int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config);
- 	int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config);
-+	int setupStandardBayerOrder(BayerFormat::Order order);
- 	int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat);
- 	void setupInputMemcpy(const uint8_t *linePointers[]);
- 	void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);
-@@ -131,6 +143,7 @@ private:
- 	unsigned int lineBufferLength_;
- 	unsigned int lineBufferPadding_;
- 	unsigned int lineBufferIndex_;
-+	unsigned int xShift_; /* Offset of 0/1 applied to window_.x */
- 	bool enableInputMemcpy_;
- 	float gamma_correction_;
- 	unsigned int measuredFrames_;
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0015-libcamera-debayer_cpu-Add-BGR888-output-support.patch b/users/flokli/ipu6-softisp/libcamera/0015-libcamera-debayer_cpu-Add-BGR888-output-support.patch
deleted file mode 100644
index 0abca2ea82d9..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0015-libcamera-debayer_cpu-Add-BGR888-output-support.patch
+++ /dev/null
@@ -1,127 +0,0 @@
-From 186db51d54bcbd4d5096bea1e4396966c2dad001 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Mon, 11 Mar 2024 15:15:19 +0100
-Subject: [PATCH 15/21] libcamera: debayer_cpu: Add BGR888 output support
-
-BGR888 is RGB888 with the red and blue pixels swapped, adjust
-the debayering to swap the red and blue pixels in the bayer pattern
-to add support for writing formats::BGR888.
-
-Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
-Tested-by: Pavel Machek <pavel@ucw.cz>
-Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
----
- src/libcamera/software_isp/debayer_cpu.cpp | 42 +++++++++++++++++++---
- src/libcamera/software_isp/debayer_cpu.h   |  1 +
- 2 files changed, 38 insertions(+), 5 deletions(-)
-
-diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
-index eb1c2718..a1692693 100644
---- a/src/libcamera/software_isp/debayer_cpu.cpp
-+++ b/src/libcamera/software_isp/debayer_cpu.cpp
-@@ -268,7 +268,7 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf
- 		config.bpp = (bayerFormat.bitDepth + 7) & ~7;
- 		config.patternSize.width = 2;
- 		config.patternSize.height = 2;
--		config.outputFormats = std::vector<PixelFormat>({ formats::RGB888 });
-+		config.outputFormats = std::vector<PixelFormat>({ formats::RGB888, formats::BGR888 });
- 		return 0;
- 	}
- 
-@@ -278,7 +278,7 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf
- 		config.bpp = 10;
- 		config.patternSize.width = 4; /* 5 bytes per *4* pixels */
- 		config.patternSize.height = 2;
--		config.outputFormats = std::vector<PixelFormat>({ formats::RGB888 });
-+		config.outputFormats = std::vector<PixelFormat>({ formats::RGB888, formats::BGR888 });
- 		return 0;
- 	}
- 
-@@ -289,7 +289,7 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf
- 
- int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config)
- {
--	if (outputFormat == formats::RGB888) {
-+	if (outputFormat == formats::RGB888 || outputFormat == formats::BGR888) {
- 		config.bpp = 24;
- 		return 0;
- 	}
-@@ -325,13 +325,41 @@ int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order)
- 	return 0;
- }
- 
--/* TODO: this ignores outputFormat since there is only 1 supported outputFormat for now */
--int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] PixelFormat outputFormat)
-+int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat)
- {
- 	BayerFormat bayerFormat =
- 		BayerFormat::fromPixelFormat(inputFormat);
- 
- 	xShift_ = 0;
-+	swapRedBlueGains_ = false;
-+
-+	switch (outputFormat) {
-+	case formats::RGB888:
-+		break;
-+	case formats::BGR888:
-+		/* Swap R and B in bayer order to generate BGR888 instead of RGB888 */
-+		swapRedBlueGains_ = true;
-+
-+		switch (bayerFormat.order) {
-+		case BayerFormat::BGGR:
-+			bayerFormat.order = BayerFormat::RGGB;
-+			break;
-+		case BayerFormat::GBRG:
-+			bayerFormat.order = BayerFormat::GRBG;
-+			break;
-+		case BayerFormat::GRBG:
-+			bayerFormat.order = BayerFormat::GBRG;
-+			break;
-+		case BayerFormat::RGGB:
-+			bayerFormat.order = BayerFormat::BGGR;
-+			break;
-+		default:
-+			goto invalid_fmt;
-+		}
-+		break;
-+	default:
-+		goto invalid_fmt;
-+	}
- 
- 	if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) &&
- 	    bayerFormat.packing == BayerFormat::Packing::None &&
-@@ -378,6 +406,7 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] Pi
- 		}
- 	}
- 
-+invalid_fmt:
- 	LOG(Debayer, Error) << "Unsupported input output format combination";
- 	return -EINVAL;
- }
-@@ -661,6 +690,9 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams
- 		gamma_correction_ = params.gamma;
- 	}
- 
-+	if (swapRedBlueGains_)
-+		std::swap(params.gainR, params.gainB);
-+
- 	for (unsigned int i = 0; i < kRGBLookupSize; i++) {
- 		constexpr unsigned int div =
- 			kRGBLookupSize * DebayerParams::kGain10 / kGammaLookupSize;
-diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h
-index fd1fa180..5f44fc65 100644
---- a/src/libcamera/software_isp/debayer_cpu.h
-+++ b/src/libcamera/software_isp/debayer_cpu.h
-@@ -145,6 +145,7 @@ private:
- 	unsigned int lineBufferIndex_;
- 	unsigned int xShift_; /* Offset of 0/1 applied to window_.x */
- 	bool enableInputMemcpy_;
-+	bool swapRedBlueGains_;
- 	float gamma_correction_;
- 	unsigned int measuredFrames_;
- 	int64_t frameProcessTime_;
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0017-libcamera-Add-Software-ISP-benchmarking-documentatio.patch b/users/flokli/ipu6-softisp/libcamera/0017-libcamera-Add-Software-ISP-benchmarking-documentatio.patch
deleted file mode 100644
index 2343e9c46fe8..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0017-libcamera-Add-Software-ISP-benchmarking-documentatio.patch
+++ /dev/null
@@ -1,132 +0,0 @@
-From 6c509a3d144d46a11454d32d128d16e16602b50f Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Mon, 11 Mar 2024 15:15:20 +0100
-Subject: [PATCH 17/21] libcamera: Add "Software ISP benchmarking"
- documentation
-
-Add a "Software ISP benchmarking" documentation section which describes
-the performance/power consumption measurements used during
-the Software ISP's development.
-
-Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
----
- Documentation/index.rst                     |  1 +
- Documentation/meson.build                   |  1 +
- Documentation/software-isp-benchmarking.rst | 82 +++++++++++++++++++++
- 3 files changed, 84 insertions(+)
- create mode 100644 Documentation/software-isp-benchmarking.rst
-
-diff --git a/Documentation/index.rst b/Documentation/index.rst
-index 63fac72d..5442ae75 100644
---- a/Documentation/index.rst
-+++ b/Documentation/index.rst
-@@ -24,3 +24,4 @@
-    Lens driver requirements <lens_driver_requirements>
-    Python Bindings <python-bindings>
-    Camera Sensor Model <camera-sensor-model>
-+   SoftwareISP Benchmarking <software-isp-benchmarking>
-diff --git a/Documentation/meson.build b/Documentation/meson.build
-index 7a58fec8..3872e0a8 100644
---- a/Documentation/meson.build
-+++ b/Documentation/meson.build
-@@ -80,6 +80,7 @@ if sphinx.found()
-         'lens_driver_requirements.rst',
-         'python-bindings.rst',
-         'sensor_driver_requirements.rst',
-+        'software-isp-benchmarking.rst',
-        '../README.rst',
-     ]
- 
-diff --git a/Documentation/software-isp-benchmarking.rst b/Documentation/software-isp-benchmarking.rst
-new file mode 100644
-index 00000000..b2803953
---- /dev/null
-+++ b/Documentation/software-isp-benchmarking.rst
-@@ -0,0 +1,82 @@
-+.. SPDX-License-Identifier: CC-BY-SA-4.0
-+
-+.. _software-isp-benchmarking:
-+
-+Software ISP benchmarking
-+=========================
-+
-+The Software ISP is particularly sensitive to performance regressions
-+therefore it is a good idea to always benchmark the Software ISP
-+before and after making changes to it and ensure that there are
-+no performance regressions.
-+
-+DebayerCpu class builtin benchmark
-+----------------------------------
-+
-+The DebayerCpu class has a builtin benchmark. This benchmark
-+measures the time spent on processing (collecting statistics
-+and debayering) only, it does not measure the time spent on
-+capturing or outputting the frames.
-+
-+The builtin benchmark always runs. So this can be used by simply
-+running "cam" or "qcam" with a pipeline using the Software ISP.
-+
-+When it runs it will skip measuring the first 30 frames to
-+allow the caches and the CPU temperature (turbo-ing) to warm-up
-+and then it measures 30 fps and shows the total and per frame
-+processing time using an info level log message:
-+
-+.. code-block:: text
-+
-+   INFO Debayer debayer_cpu.cpp:907 Processed 30 frames in 244317us, 8143 us/frame
-+
-+To get stable measurements it is advised to disable any other processes which
-+may cause significant CPU usage (e.g. disable wifi, bluetooth and browsers).
-+When possible it is also advisable to disable CPU turbo-ing and
-+frequency-scaling.
-+
-+For example when benchmarking on a Lenovo ThinkPad X1 Yoga Gen 8, with
-+the charger plugged in, the CPU can be fixed to run at 2 GHz using:
-+
-+.. code-block:: shell
-+
-+   sudo x86_energy_perf_policy --turbo-enable 0
-+   sudo cpupower frequency-set -d 2GHz -u 2GHz
-+
-+with these settings the builtin bench reports a processing time of ~7.8ms/frame
-+on this laptop for FHD SGRBG10 (unpacked) bayer data.
-+
-+Measuring power consumption
-+---------------------------
-+
-+Since the Software ISP is often used on mobile devices it is also
-+important to measure power consumption and ensure that that does
-+not regress.
-+
-+For example to measure power consumption on a Lenovo ThinkPad X1 Yoga Gen 8
-+it needs to be running on battery and it should be configured with its
-+platform-profile (/sys/firmware/acpi/platform_profile) set to balanced and
-+with its default turbo and frequency-scaling behavior to match real world usage.
-+
-+Then start qcam to capture a FHD picture at 30 fps and position the qcam window
-+so that it is fully visible. After this run the following command to monitor
-+the power consumption:
-+
-+.. code-block:: shell
-+
-+   watch -n 10 cat /sys/class/power_supply/BAT0/power_now /sys/class/hwmon/hwmon6/fan?_input
-+
-+Note this not only measures the power consumption in µW it also monitors
-+the speed of this laptop's 2 fans. This is important because depending on
-+the ambient temperature the 2 fans may spin up while testing and this
-+will cause an additional power consumption of approx. 0.5 W messing up
-+the measurement.
-+
-+After starting qcam + the watch command let the laptop sit without using
-+it for 2 minutes for the readings to stabilize. Then check that the fans
-+have not turned on and manually take a couple of consecutive power readings
-+and avarage these.
-+
-+On the example Lenovo ThinkPad X1 Yoga Gen 8 laptop this results in
-+a measured power consumption of approx. 13 W while running qcam versus
-+approx. 4-5 W while setting idle with its OLED panel on.
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0018-libcamera-software_isp-Apply-black-level-compensatio.patch b/users/flokli/ipu6-softisp/libcamera/0018-libcamera-software_isp-Apply-black-level-compensatio.patch
deleted file mode 100644
index c746b74dba67..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0018-libcamera-software_isp-Apply-black-level-compensatio.patch
+++ /dev/null
@@ -1,396 +0,0 @@
-From bb608d177135d74e3c98b8a61fb459ebe254bca5 Mon Sep 17 00:00:00 2001
-From: Milan Zamazal <mzamazal@redhat.com>
-Date: Mon, 11 Mar 2024 15:15:21 +0100
-Subject: [PATCH 18/21] libcamera: software_isp: Apply black level compensation
-
-Black may not be represented as 0 pixel value for given hardware, it may be
-higher.  If this is not compensated then various problems may occur such as low
-contrast or suboptimal exposure.
-
-The black pixel value can be either retrieved from a tuning file for the given
-hardware, or automatically on fly.  The former is the right and correct method,
-while the latter can be used when a tuning file is not available for the given
-hardware.  Since there is currently no support for tuning files in software ISP,
-the automatic, hardware independent way, is always used.  Support for tuning
-files should be added in future but it will require more work than this patch.
-
-The patch looks at the image histogram and assumes that black starts when pixel
-values start occurring on the left.  A certain amount of the darkest pixels is
-ignored; it doesn't matter whether they represent various kinds of noise or are
-real, they are better to omit in any case to make the image looking better.  It
-also doesn't matter whether the darkest pixels occur around the supposed black
-level or are spread between 0 and the black level, the difference is not
-important.
-
-An arbitrary threshold of 2% darkest pixels is applied; there is no magic about
-that value.
-
-The patch assumes that the black values for different colors are the same and
-doesn't attempt any other non-primitive enhancements.  It cannot completely
-replace tuning files and simplicity, while providing visible benefit, is its
-goal.  Anything more sophisticated is left for future patches.
-
-A possible cheap enhancement, if needed, could be setting exposure + gain to
-minimum values temporarily, before setting the black level.  In theory, the
-black level should be fixed but it may not be reached in all images.  For this
-reason, the patch updates black level only if the observed value is lower than
-the current one; it should be never increased.
-
-The purpose of the patch is to compensate for hardware properties.  General
-image contrast enhancements are out of scope of this patch.
-
-Stats are still gathered as an uncorrected histogram, to avoid any confusion and
-to represent the raw image data.  Exposure must be determined after the black
-level correction -- it has no influence on the sub-black area and must be
-correct after applying the black level correction.  The granularity of the
-histogram is increased from 16 to 64 to provide a better precision (there is no
-theory behind either of those numbers).
-
-Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- .../internal/software_isp/debayer_params.h    |  4 +
- .../internal/software_isp/swisp_stats.h       | 10 ++-
- src/ipa/simple/black_level.cpp                | 86 +++++++++++++++++++
- src/ipa/simple/black_level.h                  | 28 ++++++
- src/ipa/simple/meson.build                    |  7 +-
- src/ipa/simple/soft_simple.cpp                | 28 ++++--
- src/libcamera/software_isp/debayer_cpu.cpp    | 13 ++-
- src/libcamera/software_isp/debayer_cpu.h      |  1 +
- src/libcamera/software_isp/software_isp.cpp   |  2 +-
- 9 files changed, 162 insertions(+), 17 deletions(-)
- create mode 100644 src/ipa/simple/black_level.cpp
- create mode 100644 src/ipa/simple/black_level.h
-
-diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h
-index 98965fa1..5e38e08b 100644
---- a/include/libcamera/internal/software_isp/debayer_params.h
-+++ b/include/libcamera/internal/software_isp/debayer_params.h
-@@ -43,6 +43,10 @@ struct DebayerParams {
- 	 * \brief Gamma correction, 1.0 is no correction
- 	 */
- 	float gamma;
-+	/**
-+	 * \brief Level of the black point, 0..255, 0 is no correction.
-+	 */
-+	unsigned int blackLevel;
- };
- 
- } /* namespace libcamera */
-diff --git a/include/libcamera/internal/software_isp/swisp_stats.h b/include/libcamera/internal/software_isp/swisp_stats.h
-index afe42c9a..25cd5abd 100644
---- a/include/libcamera/internal/software_isp/swisp_stats.h
-+++ b/include/libcamera/internal/software_isp/swisp_stats.h
-@@ -7,6 +7,8 @@
- 
- #pragma once
- 
-+#include <array>
-+
- namespace libcamera {
- 
- /**
-@@ -28,11 +30,15 @@ struct SwIspStats {
- 	/**
- 	 * \brief Number of bins in the yHistogram.
- 	 */
--	static constexpr unsigned int kYHistogramSize = 16;
-+	static constexpr unsigned int kYHistogramSize = 64;
-+	/**
-+	 * \brief Type of the histogram.
-+	 */
-+	using histogram = std::array<unsigned int, kYHistogramSize>;
- 	/**
- 	 * \brief A histogram of luminance values.
- 	 */
--	std::array<unsigned int, kYHistogramSize> yHistogram;
-+	histogram yHistogram;
- };
- 
- } /* namespace libcamera */
-diff --git a/src/ipa/simple/black_level.cpp b/src/ipa/simple/black_level.cpp
-new file mode 100644
-index 00000000..8d52201b
---- /dev/null
-+++ b/src/ipa/simple/black_level.cpp
-@@ -0,0 +1,86 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2024, Red Hat Inc.
-+ *
-+ * black_level.cpp - black level handling
-+ */
-+
-+#include "black_level.h"
-+
-+#include <numeric>
-+
-+#include <libcamera/base/log.h>
-+
-+namespace libcamera {
-+
-+LOG_DEFINE_CATEGORY(IPASoftBL)
-+
-+/**
-+ * \class BlackLevel
-+ * \brief Object providing black point level for software ISP
-+ *
-+ * Black level can be provided in hardware tuning files or, if no tuning file is
-+ * available for the given hardware, guessed automatically, with less accuracy.
-+ * As tuning files are not yet implemented for software ISP, BlackLevel
-+ * currently provides only guessed black levels.
-+ *
-+ * This class serves for tracking black level as a property of the underlying
-+ * hardware, not as means of enhancing a particular scene or image.
-+ *
-+ * The class is supposed to be instantiated for the given camera stream.
-+ * The black level can be retrieved using BlackLevel::get() method. It is
-+ * initially 0 and may change when updated using BlackLevel::update() method.
-+ */
-+
-+BlackLevel::BlackLevel()
-+	: blackLevel_(255), blackLevelSet_(false)
-+{
-+}
-+
-+/**
-+ * \brief Return the current black level
-+ *
-+ * \return The black level, in the range from 0 (minimum) to 255 (maximum).
-+ * If the black level couldn't be determined yet, return 0.
-+ */
-+unsigned int BlackLevel::get() const
-+{
-+	return blackLevelSet_ ? blackLevel_ : 0;
-+}
-+
-+/**
-+ * \brief Update black level from the provided histogram
-+ * \param[in] yHistogram The histogram to be used for updating black level
-+ *
-+ * The black level is property of the given hardware, not image. It is updated
-+ * only if it has not been yet set or if it is lower than the lowest value seen
-+ * so far.
-+ */
-+void BlackLevel::update(SwIspStats::histogram &yHistogram)
-+{
-+	// The constant is selected to be "good enough", not overly conservative or
-+	// aggressive. There is no magic about the given value.
-+	constexpr float ignoredPercentage_ = 0.02;
-+	const unsigned int total =
-+		std::accumulate(begin(yHistogram), end(yHistogram), 0);
-+	const unsigned int pixelThreshold = ignoredPercentage_ * total;
-+	const unsigned int currentBlackIdx =
-+		blackLevel_ / (256 / SwIspStats::kYHistogramSize);
-+
-+	for (unsigned int i = 0, seen = 0;
-+	     i < currentBlackIdx && i < SwIspStats::kYHistogramSize;
-+	     i++) {
-+		seen += yHistogram[i];
-+		if (seen >= pixelThreshold) {
-+			blackLevel_ = i * (256 / SwIspStats::kYHistogramSize);
-+			blackLevelSet_ = true;
-+			LOG(IPASoftBL, Debug)
-+				<< "Auto-set black level: "
-+				<< i << "/" << SwIspStats::kYHistogramSize
-+				<< " (" << 100 * (seen - yHistogram[i]) / total << "% below, "
-+				<< 100 * seen / total << "% at or below)";
-+			break;
-+		}
-+	};
-+}
-+} // namespace libcamera
-diff --git a/src/ipa/simple/black_level.h b/src/ipa/simple/black_level.h
-new file mode 100644
-index 00000000..b3785db0
---- /dev/null
-+++ b/src/ipa/simple/black_level.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: LGPL-2.1-or-later */
-+/*
-+ * Copyright (C) 2024, Red Hat Inc.
-+ *
-+ * black_level.h - black level handling
-+ */
-+
-+#pragma once
-+
-+#include <array>
-+
-+#include "libcamera/internal/software_isp/swisp_stats.h"
-+
-+namespace libcamera {
-+
-+class BlackLevel
-+{
-+public:
-+	BlackLevel();
-+	unsigned int get() const;
-+	void update(std::array<unsigned int, SwIspStats::kYHistogramSize> &yHistogram);
-+
-+private:
-+	unsigned int blackLevel_;
-+	bool blackLevelSet_;
-+};
-+
-+} // namespace libcamera
-diff --git a/src/ipa/simple/meson.build b/src/ipa/simple/meson.build
-index 3e863db7..44b5f1d7 100644
---- a/src/ipa/simple/meson.build
-+++ b/src/ipa/simple/meson.build
-@@ -2,8 +2,13 @@
- 
- ipa_name = 'ipa_soft_simple'
- 
-+soft_simple_sources = files([
-+    'soft_simple.cpp',
-+    'black_level.cpp',
-+])
-+
- mod = shared_module(ipa_name,
--                    ['soft_simple.cpp', libcamera_generated_ipa_headers],
-+                    [soft_simple_sources, libcamera_generated_ipa_headers],
-                     name_prefix : '',
-                     include_directories : [ipa_includes, libipa_includes],
-                     dependencies : libcamera_private,
-diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp
-index 312df4ba..ac027568 100644
---- a/src/ipa/simple/soft_simple.cpp
-+++ b/src/ipa/simple/soft_simple.cpp
-@@ -22,6 +22,8 @@
- #include "libcamera/internal/software_isp/debayer_params.h"
- #include "libcamera/internal/software_isp/swisp_stats.h"
- 
-+#include "black_level.h"
-+
- namespace libcamera {
- 
- LOG_DEFINE_CATEGORY(IPASoft)
-@@ -33,7 +35,8 @@ class IPASoftSimple : public ipa::soft::IPASoftInterface
- public:
- 	IPASoftSimple()
- 		: params_(static_cast<DebayerParams *>(MAP_FAILED)),
--		  stats_(static_cast<SwIspStats *>(MAP_FAILED)), ignore_updates_(0)
-+		  stats_(static_cast<SwIspStats *>(MAP_FAILED)),
-+		  blackLevel_(BlackLevel()), ignore_updates_(0)
- 	{
- 	}
- 
-@@ -63,6 +66,7 @@ private:
- 	SharedFD fdParams_;
- 	DebayerParams *params_;
- 	SwIspStats *stats_;
-+	BlackLevel blackLevel_;
- 
- 	int32_t exposure_min_, exposure_max_;
- 	int32_t again_min_, again_max_;
-@@ -196,6 +200,10 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)
- 	params_->gainG = 256;
- 	params_->gamma = 0.5;
- 
-+	if (ignore_updates_ > 0)
-+		blackLevel_.update(stats_->yHistogram);
-+	params_->blackLevel = blackLevel_.get();
-+
- 	setIspParams.emit(0);
- 
- 	/*
-@@ -211,18 +219,19 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)
- 	 * Calculate Mean Sample Value (MSV) according to formula from:
- 	 * https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf
- 	 */
--	constexpr unsigned int yHistValsPerBin =
--		SwIspStats::kYHistogramSize / kExposureBinsCount;
--	constexpr unsigned int yHistValsPerBinMod =
--		SwIspStats::kYHistogramSize /
--		(SwIspStats::kYHistogramSize % kExposureBinsCount + 1);
-+	const unsigned int blackLevelHistIdx =
-+		params_->blackLevel / (256 / SwIspStats::kYHistogramSize);
-+	const unsigned int histogramSize = SwIspStats::kYHistogramSize - blackLevelHistIdx;
-+	const unsigned int yHistValsPerBin = histogramSize / kExposureBinsCount;
-+	const unsigned int yHistValsPerBinMod =
-+		histogramSize / (histogramSize % kExposureBinsCount + 1);
- 	int ExposureBins[kExposureBinsCount] = {};
- 	unsigned int denom = 0;
- 	unsigned int num = 0;
- 
--	for (unsigned int i = 0; i < SwIspStats::kYHistogramSize; i++) {
-+	for (unsigned int i = 0; i < histogramSize; i++) {
- 		unsigned int idx = (i - (i / yHistValsPerBinMod)) / yHistValsPerBin;
--		ExposureBins[idx] += stats_->yHistogram[i];
-+		ExposureBins[idx] += stats_->yHistogram[blackLevelHistIdx + i];
- 	}
- 
- 	for (unsigned int i = 0; i < kExposureBinsCount; i++) {
-@@ -256,7 +265,8 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)
- 
- 	LOG(IPASoft, Debug) << "exposureMSV " << exposureMSV
- 			    << " exp " << exposure_ << " again " << again_
--			    << " gain R/B " << params_->gainR << "/" << params_->gainB;
-+			    << " gain R/B " << params_->gainR << "/" << params_->gainB
-+			    << " black level " << params_->blackLevel;
- }
- 
- void IPASoftSimple::updateExposure(double exposureMSV)
-diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
-index a1692693..3be3cdfe 100644
---- a/src/libcamera/software_isp/debayer_cpu.cpp
-+++ b/src/libcamera/software_isp/debayer_cpu.cpp
-@@ -35,7 +35,7 @@ namespace libcamera {
-  * \param[in] stats Pointer to the stats object to use.
-  */
- DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats)
--	: stats_(std::move(stats)), gamma_correction_(1.0)
-+	: stats_(std::move(stats)), gamma_correction_(1.0), blackLevel_(0)
- {
- #ifdef __x86_64__
- 	enableInputMemcpy_ = false;
-@@ -683,11 +683,16 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams
- 	}
- 
- 	/* Apply DebayerParams */
--	if (params.gamma != gamma_correction_) {
--		for (unsigned int i = 0; i < kGammaLookupSize; i++)
--			gamma_[i] = UINT8_MAX * powf(i / (kGammaLookupSize - 1.0), params.gamma);
-+	if (params.gamma != gamma_correction_ || params.blackLevel != blackLevel_) {
-+		const unsigned int blackIndex =
-+			params.blackLevel * kGammaLookupSize / 256;
-+		std::fill(gamma_.begin(), gamma_.begin() + blackIndex, 0);
-+		const float divisor = kGammaLookupSize - blackIndex - 1.0;
-+		for (unsigned int i = blackIndex; i < kGammaLookupSize; i++)
-+			gamma_[i] = UINT8_MAX * powf((i - blackIndex) / divisor, params.gamma);
- 
- 		gamma_correction_ = params.gamma;
-+		blackLevel_ = params.blackLevel;
- 	}
- 
- 	if (swapRedBlueGains_)
-diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h
-index 5f44fc65..ea02f909 100644
---- a/src/libcamera/software_isp/debayer_cpu.h
-+++ b/src/libcamera/software_isp/debayer_cpu.h
-@@ -147,6 +147,7 @@ private:
- 	bool enableInputMemcpy_;
- 	bool swapRedBlueGains_;
- 	float gamma_correction_;
-+	unsigned int blackLevel_;
- 	unsigned int measuredFrames_;
- 	int64_t frameProcessTime_;
- 	/* Skip 30 frames for things to stabilize then measure 30 frames */
-diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp
-index 388b4496..9b49be41 100644
---- a/src/libcamera/software_isp/software_isp.cpp
-+++ b/src/libcamera/software_isp/software_isp.cpp
-@@ -64,7 +64,7 @@ LOG_DEFINE_CATEGORY(SoftwareIsp)
-  */
- SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorControls)
- 	: debayer_(nullptr),
--	  debayerParams_{ DebayerParams::kGain10, DebayerParams::kGain10, DebayerParams::kGain10, 0.5f },
-+	  debayerParams_{ DebayerParams::kGain10, DebayerParams::kGain10, DebayerParams::kGain10, 0.5f, 0 },
- 	  dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System)
- {
- 	if (!dmaHeap_.isValid()) {
--- 
-2.43.2
-
diff --git a/users/flokli/ipu6-softisp/libcamera/0019-libcamera-Soft-IPA-use-CameraSensorHelper-for-analog.patch b/users/flokli/ipu6-softisp/libcamera/0019-libcamera-Soft-IPA-use-CameraSensorHelper-for-analog.patch
deleted file mode 100644
index 5b562c603c52..000000000000
--- a/users/flokli/ipu6-softisp/libcamera/0019-libcamera-Soft-IPA-use-CameraSensorHelper-for-analog.patch
+++ /dev/null
@@ -1,239 +0,0 @@
-From b0c07674abecb05dc0af93a4b749971f057bc3c6 Mon Sep 17 00:00:00 2001
-From: Andrei Konovalov <andrey.konovalov.ynk@gmail.com>
-Date: Mon, 11 Mar 2024 15:15:22 +0100
-Subject: [PATCH 19/21] libcamera: Soft IPA: use CameraSensorHelper for
- analogue gain
-
-Use CameraSensorHelper to convert the analogue gain code read from the
-camera sensor into real analogue gain value. In the future this makes
-it possible to use faster AE/AGC algorithm. For now the same AE/AGC
-algorithm is used, but even then the CameraSensorHelper lets us use the
-full range of analogue gain values.
-
-If there is no CameraSensorHelper for the camera sensor in use, a
-warning log message is printed, and the AE/AGC works exactly as before
-this change.
-
-Signed-off-by: Andrei Konovalov <andrey.konovalov.ynk@gmail.com>
-Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
----
- .../internal/software_isp/software_isp.h      |  3 +-
- src/ipa/simple/soft_simple.cpp                | 77 ++++++++++++-------
- src/libcamera/pipeline/simple/simple.cpp      |  2 +-
- src/libcamera/software_isp/software_isp.cpp   |  8 +-
- 4 files changed, 57 insertions(+), 33 deletions(-)
-
-diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h
-index 8d25e979..2a6db7ba 100644
---- a/include/libcamera/internal/software_isp/software_isp.h
-+++ b/include/libcamera/internal/software_isp/software_isp.h
-@@ -26,6 +26,7 @@
- #include <libcamera/ipa/soft_ipa_interface.h>
- #include <libcamera/ipa/soft_ipa_proxy.h>
- 
-+#include "libcamera/internal/camera_sensor.h"
- #include "libcamera/internal/dma_heaps.h"
- #include "libcamera/internal/pipeline_handler.h"
- #include "libcamera/internal/shared_mem_object.h"
-@@ -43,7 +44,7 @@ LOG_DECLARE_CATEGORY(SoftwareIsp)
- class SoftwareIsp
- {
- public:
--	SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorControls);
-+	SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor);
- 	~SoftwareIsp();
- 
- 	int loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; }
-diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp
-index ac027568..e4d64762 100644
---- a/src/ipa/simple/soft_simple.cpp
-+++ b/src/ipa/simple/soft_simple.cpp
-@@ -22,6 +22,8 @@
- #include "libcamera/internal/software_isp/debayer_params.h"
- #include "libcamera/internal/software_isp/swisp_stats.h"
- 
-+#include "libipa/camera_sensor_helper.h"
-+
- #include "black_level.h"
- 
- namespace libcamera {
-@@ -67,18 +69,27 @@ private:
- 	DebayerParams *params_;
- 	SwIspStats *stats_;
- 	BlackLevel blackLevel_;
-+	std::unique_ptr<CameraSensorHelper> camHelper_;
- 
- 	int32_t exposure_min_, exposure_max_;
--	int32_t again_min_, again_max_;
--	int32_t again_, exposure_;
-+	int32_t exposure_;
-+	double again_min_, again_max_, againMinStep_;
-+	double again_;
- 	unsigned int ignore_updates_;
- };
- 
--int IPASoftSimple::init([[maybe_unused]] const IPASettings &settings,
-+int IPASoftSimple::init(const IPASettings &settings,
- 			const SharedFD &fdStats,
- 			const SharedFD &fdParams,
- 			const ControlInfoMap &sensorInfoMap)
- {
-+	camHelper_ = CameraSensorHelperFactoryBase::create(settings.sensorModel);
-+	if (camHelper_ == nullptr) {
-+		LOG(IPASoft, Warning)
-+			<< "Failed to create camera sensor helper for "
-+			<< settings.sensorModel;
-+	}
-+
- 	fdStats_ = fdStats;
- 	if (!fdStats_.isValid()) {
- 		LOG(IPASoft, Error) << "Invalid Statistics handle";
-@@ -132,25 +143,35 @@ int IPASoftSimple::configure(const ControlInfoMap &sensorInfoMap)
- 		exposure_min_ = 1;
- 	}
- 
--	again_min_ = gain_info.min().get<int32_t>();
--	again_max_ = gain_info.max().get<int32_t>();
--	/*
--	 * The camera sensor gain (g) is usually not equal to the value written
--	 * into the gain register (x). But the way how the AGC algorithm changes
--	 * the gain value to make the total exposure closer to the optimum assumes
--	 * that g(x) is not too far from linear function. If the minimal gain is 0,
--	 * the g(x) is likely to be far from the linear, like g(x) = a / (b * x + c).
--	 * To avoid unexpected changes to the gain by the AGC algorithm (abrupt near
--	 * one edge, and very small near the other) we limit the range of the gain
--	 * values used.
--	 */
--	if (!again_min_) {
--		LOG(IPASoft, Warning) << "Minimum gain is zero, that can't be linear";
--		again_min_ = std::min(100, again_min_ / 2 + again_max_ / 2);
-+	int32_t again_min = gain_info.min().get<int32_t>();
-+	int32_t again_max = gain_info.max().get<int32_t>();
-+
-+	if (camHelper_) {
-+		again_min_ = camHelper_->gain(again_min);
-+		again_max_ = camHelper_->gain(again_max);
-+		againMinStep_ = (again_max_ - again_min_) / 100.0;
-+	} else {
-+		/*
-+		 * The camera sensor gain (g) is usually not equal to the value written
-+		 * into the gain register (x). But the way how the AGC algorithm changes
-+		 * the gain value to make the total exposure closer to the optimum assumes
-+		 * that g(x) is not too far from linear function. If the minimal gain is 0,
-+		 * the g(x) is likely to be far from the linear, like g(x) = a / (b * x + c).
-+		 * To avoid unexpected changes to the gain by the AGC algorithm (abrupt near
-+		 * one edge, and very small near the other) we limit the range of the gain
-+		 * values used.
-+		 */
-+		again_max_ = again_max;
-+		if (!again_min) {
-+			LOG(IPASoft, Warning) << "Minimum gain is zero, that can't be linear";
-+			again_min_ = std::min(100, again_min / 2 + again_max / 2);
-+		}
-+		againMinStep_ = 1.0;
- 	}
- 
- 	LOG(IPASoft, Info) << "Exposure " << exposure_min_ << "-" << exposure_max_
--			   << ", gain " << again_min_ << "-" << again_max_;
-+			   << ", gain " << again_min_ << "-" << again_max_
-+			   << " (" << againMinStep_ << ")";
- 
- 	return 0;
- }
-@@ -252,12 +273,14 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)
- 	ControlList ctrls(sensorControls);
- 
- 	exposure_ = ctrls.get(V4L2_CID_EXPOSURE).get<int32_t>();
--	again_ = ctrls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>();
-+	int32_t again = ctrls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>();
-+	again_ = camHelper_ ? camHelper_->gain(again) : again;
- 
- 	updateExposure(exposureMSV);
- 
- 	ctrls.set(V4L2_CID_EXPOSURE, exposure_);
--	ctrls.set(V4L2_CID_ANALOGUE_GAIN, again_);
-+	ctrls.set(V4L2_CID_ANALOGUE_GAIN,
-+		  static_cast<int32_t>(camHelper_ ? camHelper_->gainCode(again_) : again_));
- 
- 	ignore_updates_ = 2;
- 
-@@ -276,7 +299,7 @@ void IPASoftSimple::updateExposure(double exposureMSV)
- 	static constexpr uint8_t kExpNumeratorUp = kExpDenominator + 1;
- 	static constexpr uint8_t kExpNumeratorDown = kExpDenominator - 1;
- 
--	int next;
-+	double next;
- 
- 	if (exposureMSV < kExposureOptimal - kExposureSatisfactory) {
- 		next = exposure_ * kExpNumeratorUp / kExpDenominator;
-@@ -286,18 +309,18 @@ void IPASoftSimple::updateExposure(double exposureMSV)
- 			exposure_ = next;
- 		if (exposure_ >= exposure_max_) {
- 			next = again_ * kExpNumeratorUp / kExpDenominator;
--			if (next - again_ < 1)
--				again_ += 1;
-+			if (next - again_ < againMinStep_)
-+				again_ += againMinStep_;
- 			else
- 				again_ = next;
- 		}
- 	}
- 
- 	if (exposureMSV > kExposureOptimal + kExposureSatisfactory) {
--		if (exposure_ == exposure_max_ && again_ != again_min_) {
-+		if (exposure_ == exposure_max_ && again_ > again_min_) {
- 			next = again_ * kExpNumeratorDown / kExpDenominator;
--			if (again_ - next < 1)
--				again_ -= 1;
-+			if (again_ - next < againMinStep_)
-+				again_ -= againMinStep_;
- 			else
- 				again_ = next;
- 		} else {
-diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
-index c3ebb7b7..7e932a14 100644
---- a/src/libcamera/pipeline/simple/simple.cpp
-+++ b/src/libcamera/pipeline/simple/simple.cpp
-@@ -525,7 +525,7 @@ int SimpleCameraData::init()
- 	 * Instantiate Soft ISP if this is enabled for the given driver and no converter is used.
- 	 */
- 	if (!converter_ && pipe->swIspEnabled()) {
--		swIsp_ = std::make_unique<SoftwareIsp>(pipe, sensor_->controls());
-+		swIsp_ = std::make_unique<SoftwareIsp>(pipe, sensor_.get());
- 		if (!swIsp_->isValid()) {
- 			LOG(SimplePipeline, Warning)
- 				<< "Failed to create software ISP, disabling software debayering";
-diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp
-index 9b49be41..ea4d96e4 100644
---- a/src/libcamera/software_isp/software_isp.cpp
-+++ b/src/libcamera/software_isp/software_isp.cpp
-@@ -60,9 +60,9 @@ LOG_DEFINE_CATEGORY(SoftwareIsp)
- /**
-  * \brief Constructs SoftwareIsp object
-  * \param[in] pipe The pipeline handler in use
-- * \param[in] sensorControls ControlInfoMap describing the controls supported by the sensor
-+ * \param[in] sensor Pointer to the CameraSensor instance owned by the pipeline handler
-  */
--SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorControls)
-+SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor)
- 	: debayer_(nullptr),
- 	  debayerParams_{ DebayerParams::kGain10, DebayerParams::kGain10, DebayerParams::kGain10, 0.5f, 0 },
- 	  dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System)
-@@ -97,10 +97,10 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorCont
- 		return;
- 	}
- 
--	int ret = ipa_->init(IPASettings{ "No cfg file", "No sensor model" },
-+	int ret = ipa_->init(IPASettings{ "No cfg file", sensor->model() },
- 			     debayer_->getStatsFD(),
- 			     sharedParams_.fd(),
--			     sensorControls);
-+			     sensor->controls());
- 	if (ret) {
- 		LOG(SoftwareIsp, Error) << "IPA init failed";
- 		debayer_.reset();
--- 
-2.43.2
-