[libcamera-devel,v3,3/5] ipa: rkisp1: Add support of Lens Shading Correction control
diff mbox series

Message ID 20220726143635.518227-4-fsylvestre@baylibre.com
State Accepted
Headers show
Series
  • Add GSL, LSC and DPCC tuning support for rkisp1
Related show

Commit Message

Florian Sylvestre July 26, 2022, 2:36 p.m. UTC
The Lens Shading Correction algorithm applies multipliers to all pixels
to compensate for the lens shading effect. The coefficients are
specified in a downscaled table in the YAML tuning file.

Signed-off-by: Florian Sylvestre <fsylvestre@baylibre.com>
---
 src/ipa/rkisp1/algorithms/lsc.cpp     | 195 ++++++++++++++++++++++++++
 src/ipa/rkisp1/algorithms/lsc.h       |  38 +++++
 src/ipa/rkisp1/algorithms/meson.build |   1 +
 src/ipa/rkisp1/data/ov5640.yaml       |  79 +++++++++++
 src/ipa/rkisp1/ipa_context.cpp        |   3 +
 src/ipa/rkisp1/ipa_context.h          |   1 +
 src/ipa/rkisp1/rkisp1.cpp             |   1 +
 7 files changed, 318 insertions(+)
 create mode 100644 src/ipa/rkisp1/algorithms/lsc.cpp
 create mode 100644 src/ipa/rkisp1/algorithms/lsc.h

Comments

Laurent Pinchart July 27, 2022, 3:23 a.m. UTC | #1
Hi Florian,

Thank you for the patch.

On Tue, Jul 26, 2022 at 04:36:33PM +0200, Florian Sylvestre via libcamera-devel wrote:
> The Lens Shading Correction algorithm applies multipliers to all pixels
> to compensate for the lens shading effect. The coefficients are
> specified in a downscaled table in the YAML tuning file.
> 
> Signed-off-by: Florian Sylvestre <fsylvestre@baylibre.com>
> ---
>  src/ipa/rkisp1/algorithms/lsc.cpp     | 195 ++++++++++++++++++++++++++
>  src/ipa/rkisp1/algorithms/lsc.h       |  38 +++++
>  src/ipa/rkisp1/algorithms/meson.build |   1 +
>  src/ipa/rkisp1/data/ov5640.yaml       |  79 +++++++++++
>  src/ipa/rkisp1/ipa_context.cpp        |   3 +
>  src/ipa/rkisp1/ipa_context.h          |   1 +
>  src/ipa/rkisp1/rkisp1.cpp             |   1 +
>  7 files changed, 318 insertions(+)
>  create mode 100644 src/ipa/rkisp1/algorithms/lsc.cpp
>  create mode 100644 src/ipa/rkisp1/algorithms/lsc.h
> 
> diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp
> new file mode 100644
> index 00000000..5809e154
> --- /dev/null
> +++ b/src/ipa/rkisp1/algorithms/lsc.cpp
> @@ -0,0 +1,195 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2021-2022, Ideas On Board
> + *
> + * lsc.cpp - RkISP1 Lens Shading Correction control
> + */
> +
> +#include "lsc.h"
> +
> +#include <cmath>
> +#include <numeric>
> +
> +#include <libcamera/base/log.h>
> +
> +#include "libcamera/internal/yaml_parser.h"
> +
> +#include "linux/rkisp1-config.h"
> +
> +/**
> + * \file lsc.h
> + */
> +
> +namespace libcamera {
> +
> +namespace ipa::rkisp1::algorithms {
> +
> +/**
> + * \class LensShadingCorrection
> + * \brief RkISP1 Lens Shading Correction control
> + *
> + * Due to the optical characteristics of the lens, the light intensity received
> + * by the sensor is not uniform.
> + *
> + * The Lens Shading Correction algorithm applies multipliers to all pixels
> + * to compensate for the lens shading effect. The coefficients are
> + * specified in a downscaled table in the YAML tuning file.
> + */
> +
> +LOG_DEFINE_CATEGORY(RkISP1Lsc)
> +
> +LensShadingCorrection::LensShadingCorrection()
> +	: initialized_(false)
> +{
> +}
> +
> +/**
> + * \copydoc libcamera::ipa::Algorithm::init
> + */
> +int LensShadingCorrection::init([[maybe_unused]] IPAContext &context,
> +				const YamlObject &tuningData)
> +{
> +	static constexpr unsigned int kLscNumSamples =
> +		RKISP1_CIF_ISP_LSC_SAMPLES_MAX * RKISP1_CIF_ISP_LSC_SAMPLES_MAX;
> +	float sum;
> +
> +	xSize_ = tuningData["x-size"].getList<double>();
> +	if (xSize_.size() != RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE) {
> +		LOG(RkISP1Lsc, Error)
> +			<< "Invalid 'x-size' values: expected "
> +			<< RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE
> +			<< " elements, got " << xSize_.size();
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * Check that the sum of elements is the expected one with a tolerance
> +	 * of 1%.
> +	 */
> +	sum = std::accumulate(xSize_.begin(), xSize_.end(), 0.0f);
> +	if (sum < 0.495 || sum > 0.505) {
> +		LOG(RkISP1Lsc, Error)
> +			<< "Invalid 'x-size' values: sum of the elements should"
> +			<< " be 0.5 , got " << sum;
> +		return -EINVAL;
> +	}
> +
> +	ySize_ = tuningData["y-size"].getList<double>();
> +	if (ySize_.size() != RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE) {
> +		LOG(RkISP1Lsc, Error)
> +			<< "Invalid 'y-size' values: expected "
> +			<< RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE
> +			<< " elements, got " << ySize_.size();
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * Check that the sum of elements is the expected one with a tolerance
> +	 * of 1%.
> +	 */
> +	sum = std::accumulate(ySize_.begin(), ySize_.end(), 0.0f);
> +	if (sum < 0.495 || sum > 0.505) {
> +		LOG(RkISP1Lsc, Error)
> +			<< "Invalid 'y-size' values: sum of the elements should"
> +			<< " be 0.5 , got " << sum;
> +		return -EINVAL;
> +	}

Let's avoid code duplication:

static std::vector<double> parseSizes(const YamlObject &tuningData,
				      const char *prop)
{
	std::vector<double> sizes = tuningData["prop"].getList<double>();
	if (sizes.size() != RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE) {
		LOG(RkISP1Lsc, Error)
			<< "Invalid '" << prop << "' values: expected "
			<< RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE
			<< " elements, got " << sizes.size();
		return {};
	}

	/*
	 * The sum of all elements must be 0.5 to satisfy hardware constraints.
	 * Validate it here, allowing a 1% tolerance as rounding errors may
	 * prevent an exact match (further adjustements will be performed in
	 * LensShadingCorrection::prepare()).
	 */
	float sum = std::accumulate(sizes.begin(), sizes.end(), 0.0f);
	if (sum < 0.495 || sum > 0.505) {
		LOG(RkISP1Lsc, Error)
			<< "Invalid '" << prop << "' values: sum of the elements"
			<< " should be 0.5, got " << sum;
		return {};
	}

	return sizes;
}

/**
 * \copydoc libcamera::ipa::Algorithm::init
 */
int LensShadingCorrection::init([[maybe_unused]] IPAContext &context,
				const YamlObject &tuningData)
{
	xSize_ = parseSizes(tuningData, "x-size");
	ySize_ = parseSizes(tuningData, "y-size");

	if (xSize_.empty() || ySize_.empty())
		return -EINVAL;

	static constexpr unsigned int kLscNumSamples =
		RKISP1_CIF_ISP_LSC_SAMPLES_MAX * RKISP1_CIF_ISP_LSC_SAMPLES_MAX;

	...
}

> +
> +	rData_ = tuningData["r"].getList<uint16_t>();
> +	if (rData_.size() != kLscNumSamples) {
> +		LOG(RkISP1Lsc, Error)
> +			<< "Invalid 'r' values: expected "
> +			<< kLscNumSamples
> +			<< " elements, got " << rData_.size();
> +		return -EINVAL;
> +	}
> +
> +	grData_ = tuningData["gr"].getList<uint16_t>();
> +	if (grData_.size() != kLscNumSamples) {
> +		LOG(RkISP1Lsc, Error)
> +			<< "Invalid 'gr' values: expected "
> +			<< kLscNumSamples
> +			<< " elements, got " << grData_.size();
> +		return -EINVAL;
> +	}
> +
> +	gbData_ = tuningData["gb"].getList<uint16_t>();
> +	if (gbData_.size() != kLscNumSamples) {
> +		LOG(RkISP1Lsc, Error)
> +			<< "Invalid 'gb' values: expected "
> +			<< kLscNumSamples
> +			<< " elements, got " << gbData_.size();
> +		return -EINVAL;
> +	}
> +
> +	bData_ = tuningData["b"].getList<uint16_t>();
> +	if (bData_.size() != kLscNumSamples) {
> +		LOG(RkISP1Lsc, Error)
> +			<< "Invalid 'b' values: expected "
> +			<< kLscNumSamples
> +			<< " elements, got " << bData_.size();
> +		return -EINVAL;
> +	}

And you could do the same for these too, with a parseTable() function.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +
> +	initialized_ = true;
> +
> +	return 0;
> +}
> +
> +/**
> + * \copydoc libcamera::ipa::Algorithm::prepare
> + */
> +void LensShadingCorrection::prepare(IPAContext &context,
> +				    rkisp1_params_cfg *params)
> +{
> +	if (context.frameContext.frameCount > 0)
> +		return;
> +
> +	if (!initialized_)
> +		return;
> +
> +	struct rkisp1_cif_isp_lsc_config &config = params->others.lsc_config;
> +	const Size &size = context.configuration.sensor.size;
> +	Size totalSize{};
> +
> +	for (unsigned int i = 0; i < RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE; ++i) {
> +		config.x_size_tbl[i] = xSize_[i] * size.width;
> +		config.y_size_tbl[i] = ySize_[i] * size.height;
> +
> +		/*
> +		 * To prevent unexpected behavior of the ISP, the sum of x_size_tbl and
> +		 * y_size_tbl items shall be equal to respectively size.width/2 and
> +		 * size.height/2. Enforce it by computing the last tables value to avoid
> +		 * rounding-induced errors.
> +		 */
> +		if (i == RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE - 1) {
> +			config.x_size_tbl[i] = size.width / 2 - totalSize.width;
> +			config.y_size_tbl[i] = size.height / 2 - totalSize.height;
> +		}
> +
> +		totalSize.width += config.x_size_tbl[i];
> +		totalSize.height += config.y_size_tbl[i];
> +
> +		config.x_grad_tbl[i] = std::round(32768 / config.x_size_tbl[i]);
> +		config.y_grad_tbl[i] = std::round(32768 / config.y_size_tbl[i]);
> +	}
> +
> +	std::copy(rData_.begin(), rData_.end(),
> +		  &params->others.lsc_config.r_data_tbl[0][0]);
> +	std::copy(grData_.begin(), grData_.end(),
> +		  &params->others.lsc_config.gr_data_tbl[0][0]);
> +	std::copy(gbData_.begin(), gbData_.end(),
> +		  &params->others.lsc_config.gb_data_tbl[0][0]);
> +	std::copy(bData_.begin(), bData_.end(),
> +		  &params->others.lsc_config.b_data_tbl[0][0]);
> +
> +	params->module_en_update |= RKISP1_CIF_ISP_MODULE_LSC;
> +	params->module_ens |= RKISP1_CIF_ISP_MODULE_LSC;
> +	params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_LSC;
> +}
> +
> +REGISTER_IPA_ALGORITHM(LensShadingCorrection, "LensShadingCorrection")
> +
> +} /* namespace ipa::rkisp1::algorithms */
> +
> +} /* namespace libcamera */
> diff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h
> new file mode 100644
> index 00000000..fdb2ec1d
> --- /dev/null
> +++ b/src/ipa/rkisp1/algorithms/lsc.h
> @@ -0,0 +1,38 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2021-2022, Ideas On Board
> + *
> + * lsc.h - RkISP1 Lens Shading Correction control
> + */
> +
> +#pragma once
> +
> +#include "algorithm.h"
> +
> +namespace libcamera {
> +
> +namespace ipa::rkisp1::algorithms {
> +
> +class LensShadingCorrection : public Algorithm
> +{
> +public:
> +	LensShadingCorrection();
> +	~LensShadingCorrection() = default;
> +
> +	int init(IPAContext &context, const YamlObject &tuningData) override;
> +	void prepare(IPAContext &context, rkisp1_params_cfg *params) override;
> +
> +private:
> +	bool initialized_;
> +
> +	std::vector<uint16_t> rData_;
> +	std::vector<uint16_t> grData_;
> +	std::vector<uint16_t> gbData_;
> +	std::vector<uint16_t> bData_;
> +
> +	std::vector<double> xSize_;
> +	std::vector<double> ySize_;
> +};
> +
> +} /* namespace ipa::rkisp1::algorithms */
> +} /* namespace libcamera */
> diff --git a/src/ipa/rkisp1/algorithms/meson.build b/src/ipa/rkisp1/algorithms/meson.build
> index 0597c353..64e11dce 100644
> --- a/src/ipa/rkisp1/algorithms/meson.build
> +++ b/src/ipa/rkisp1/algorithms/meson.build
> @@ -5,4 +5,5 @@ rkisp1_ipa_algorithms = files([
>      'awb.cpp',
>      'blc.cpp',
>      'gsl.cpp',
> +    'lsc.cpp',
>  ])
> diff --git a/src/ipa/rkisp1/data/ov5640.yaml b/src/ipa/rkisp1/data/ov5640.yaml
> index 13f76412..fa2ae436 100644
> --- a/src/ipa/rkisp1/data/ov5640.yaml
> +++ b/src/ipa/rkisp1/data/ov5640.yaml
> @@ -16,4 +16,83 @@ algorithms:
>          red:   [ 0, 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4095 ]
>          green: [ 0, 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4095 ]
>          blue:  [ 0, 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4095 ]
> +  - LensShadingCorrection:
> +      x-size: [ 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625 ]
> +      y-size: [ 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625 ]
> +      r:  [
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +          ]
> +      gr: [
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +          ]
> +      gb: [
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +          ]
> +      b:  [
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
> +          ]
>  ...
> diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp
> index 1559d3ff..30bb87a9 100644
> --- a/src/ipa/rkisp1/ipa_context.cpp
> +++ b/src/ipa/rkisp1/ipa_context.cpp
> @@ -95,6 +95,9 @@ namespace libcamera::ipa::rkisp1 {
>   *
>   * \var IPASessionConfiguration::sensor.lineDuration
>   * \brief Line duration in microseconds
> + *
> + * \var IPASessionConfiguration::sensor.size
> + * \brief Sensor output resolution
>   */
>  
>  /**
> diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
> index f387cace..3bfb262c 100644
> --- a/src/ipa/rkisp1/ipa_context.h
> +++ b/src/ipa/rkisp1/ipa_context.h
> @@ -33,6 +33,7 @@ struct IPASessionConfiguration {
>  
>  	struct {
>  		utils::Duration lineDuration;
> +		Size size;
>  	} sensor;
>  
>  	struct {
> diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
> index 4018265c..e5010f6a 100644
> --- a/src/ipa/rkisp1/rkisp1.cpp
> +++ b/src/ipa/rkisp1/rkisp1.cpp
> @@ -211,6 +211,7 @@ int IPARkISP1::configure([[maybe_unused]] const IPACameraSensorInfo &info,
>  	/* Set the hardware revision for the algorithms. */
>  	context_.configuration.hw.revision = hwRevision_;
>  
> +	context_.configuration.sensor.size = info.outputSize;
>  	context_.configuration.sensor.lineDuration = info.lineLength * 1.0s / info.pixelRate;
>  
>  	/*

Patch
diff mbox series

diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp
new file mode 100644
index 00000000..5809e154
--- /dev/null
+++ b/src/ipa/rkisp1/algorithms/lsc.cpp
@@ -0,0 +1,195 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2021-2022, Ideas On Board
+ *
+ * lsc.cpp - RkISP1 Lens Shading Correction control
+ */
+
+#include "lsc.h"
+
+#include <cmath>
+#include <numeric>
+
+#include <libcamera/base/log.h>
+
+#include "libcamera/internal/yaml_parser.h"
+
+#include "linux/rkisp1-config.h"
+
+/**
+ * \file lsc.h
+ */
+
+namespace libcamera {
+
+namespace ipa::rkisp1::algorithms {
+
+/**
+ * \class LensShadingCorrection
+ * \brief RkISP1 Lens Shading Correction control
+ *
+ * Due to the optical characteristics of the lens, the light intensity received
+ * by the sensor is not uniform.
+ *
+ * The Lens Shading Correction algorithm applies multipliers to all pixels
+ * to compensate for the lens shading effect. The coefficients are
+ * specified in a downscaled table in the YAML tuning file.
+ */
+
+LOG_DEFINE_CATEGORY(RkISP1Lsc)
+
+LensShadingCorrection::LensShadingCorrection()
+	: initialized_(false)
+{
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::init
+ */
+int LensShadingCorrection::init([[maybe_unused]] IPAContext &context,
+				const YamlObject &tuningData)
+{
+	static constexpr unsigned int kLscNumSamples =
+		RKISP1_CIF_ISP_LSC_SAMPLES_MAX * RKISP1_CIF_ISP_LSC_SAMPLES_MAX;
+	float sum;
+
+	xSize_ = tuningData["x-size"].getList<double>();
+	if (xSize_.size() != RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE) {
+		LOG(RkISP1Lsc, Error)
+			<< "Invalid 'x-size' values: expected "
+			<< RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE
+			<< " elements, got " << xSize_.size();
+		return -EINVAL;
+	}
+
+	/*
+	 * Check that the sum of elements is the expected one with a tolerance
+	 * of 1%.
+	 */
+	sum = std::accumulate(xSize_.begin(), xSize_.end(), 0.0f);
+	if (sum < 0.495 || sum > 0.505) {
+		LOG(RkISP1Lsc, Error)
+			<< "Invalid 'x-size' values: sum of the elements should"
+			<< " be 0.5 , got " << sum;
+		return -EINVAL;
+	}
+
+	ySize_ = tuningData["y-size"].getList<double>();
+	if (ySize_.size() != RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE) {
+		LOG(RkISP1Lsc, Error)
+			<< "Invalid 'y-size' values: expected "
+			<< RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE
+			<< " elements, got " << ySize_.size();
+		return -EINVAL;
+	}
+
+	/*
+	 * Check that the sum of elements is the expected one with a tolerance
+	 * of 1%.
+	 */
+	sum = std::accumulate(ySize_.begin(), ySize_.end(), 0.0f);
+	if (sum < 0.495 || sum > 0.505) {
+		LOG(RkISP1Lsc, Error)
+			<< "Invalid 'y-size' values: sum of the elements should"
+			<< " be 0.5 , got " << sum;
+		return -EINVAL;
+	}
+
+	rData_ = tuningData["r"].getList<uint16_t>();
+	if (rData_.size() != kLscNumSamples) {
+		LOG(RkISP1Lsc, Error)
+			<< "Invalid 'r' values: expected "
+			<< kLscNumSamples
+			<< " elements, got " << rData_.size();
+		return -EINVAL;
+	}
+
+	grData_ = tuningData["gr"].getList<uint16_t>();
+	if (grData_.size() != kLscNumSamples) {
+		LOG(RkISP1Lsc, Error)
+			<< "Invalid 'gr' values: expected "
+			<< kLscNumSamples
+			<< " elements, got " << grData_.size();
+		return -EINVAL;
+	}
+
+	gbData_ = tuningData["gb"].getList<uint16_t>();
+	if (gbData_.size() != kLscNumSamples) {
+		LOG(RkISP1Lsc, Error)
+			<< "Invalid 'gb' values: expected "
+			<< kLscNumSamples
+			<< " elements, got " << gbData_.size();
+		return -EINVAL;
+	}
+
+	bData_ = tuningData["b"].getList<uint16_t>();
+	if (bData_.size() != kLscNumSamples) {
+		LOG(RkISP1Lsc, Error)
+			<< "Invalid 'b' values: expected "
+			<< kLscNumSamples
+			<< " elements, got " << bData_.size();
+		return -EINVAL;
+	}
+
+	initialized_ = true;
+
+	return 0;
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::prepare
+ */
+void LensShadingCorrection::prepare(IPAContext &context,
+				    rkisp1_params_cfg *params)
+{
+	if (context.frameContext.frameCount > 0)
+		return;
+
+	if (!initialized_)
+		return;
+
+	struct rkisp1_cif_isp_lsc_config &config = params->others.lsc_config;
+	const Size &size = context.configuration.sensor.size;
+	Size totalSize{};
+
+	for (unsigned int i = 0; i < RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE; ++i) {
+		config.x_size_tbl[i] = xSize_[i] * size.width;
+		config.y_size_tbl[i] = ySize_[i] * size.height;
+
+		/*
+		 * To prevent unexpected behavior of the ISP, the sum of x_size_tbl and
+		 * y_size_tbl items shall be equal to respectively size.width/2 and
+		 * size.height/2. Enforce it by computing the last tables value to avoid
+		 * rounding-induced errors.
+		 */
+		if (i == RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE - 1) {
+			config.x_size_tbl[i] = size.width / 2 - totalSize.width;
+			config.y_size_tbl[i] = size.height / 2 - totalSize.height;
+		}
+
+		totalSize.width += config.x_size_tbl[i];
+		totalSize.height += config.y_size_tbl[i];
+
+		config.x_grad_tbl[i] = std::round(32768 / config.x_size_tbl[i]);
+		config.y_grad_tbl[i] = std::round(32768 / config.y_size_tbl[i]);
+	}
+
+	std::copy(rData_.begin(), rData_.end(),
+		  &params->others.lsc_config.r_data_tbl[0][0]);
+	std::copy(grData_.begin(), grData_.end(),
+		  &params->others.lsc_config.gr_data_tbl[0][0]);
+	std::copy(gbData_.begin(), gbData_.end(),
+		  &params->others.lsc_config.gb_data_tbl[0][0]);
+	std::copy(bData_.begin(), bData_.end(),
+		  &params->others.lsc_config.b_data_tbl[0][0]);
+
+	params->module_en_update |= RKISP1_CIF_ISP_MODULE_LSC;
+	params->module_ens |= RKISP1_CIF_ISP_MODULE_LSC;
+	params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_LSC;
+}
+
+REGISTER_IPA_ALGORITHM(LensShadingCorrection, "LensShadingCorrection")
+
+} /* namespace ipa::rkisp1::algorithms */
+
+} /* namespace libcamera */
diff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h
new file mode 100644
index 00000000..fdb2ec1d
--- /dev/null
+++ b/src/ipa/rkisp1/algorithms/lsc.h
@@ -0,0 +1,38 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2021-2022, Ideas On Board
+ *
+ * lsc.h - RkISP1 Lens Shading Correction control
+ */
+
+#pragma once
+
+#include "algorithm.h"
+
+namespace libcamera {
+
+namespace ipa::rkisp1::algorithms {
+
+class LensShadingCorrection : public Algorithm
+{
+public:
+	LensShadingCorrection();
+	~LensShadingCorrection() = default;
+
+	int init(IPAContext &context, const YamlObject &tuningData) override;
+	void prepare(IPAContext &context, rkisp1_params_cfg *params) override;
+
+private:
+	bool initialized_;
+
+	std::vector<uint16_t> rData_;
+	std::vector<uint16_t> grData_;
+	std::vector<uint16_t> gbData_;
+	std::vector<uint16_t> bData_;
+
+	std::vector<double> xSize_;
+	std::vector<double> ySize_;
+};
+
+} /* namespace ipa::rkisp1::algorithms */
+} /* namespace libcamera */
diff --git a/src/ipa/rkisp1/algorithms/meson.build b/src/ipa/rkisp1/algorithms/meson.build
index 0597c353..64e11dce 100644
--- a/src/ipa/rkisp1/algorithms/meson.build
+++ b/src/ipa/rkisp1/algorithms/meson.build
@@ -5,4 +5,5 @@  rkisp1_ipa_algorithms = files([
     'awb.cpp',
     'blc.cpp',
     'gsl.cpp',
+    'lsc.cpp',
 ])
diff --git a/src/ipa/rkisp1/data/ov5640.yaml b/src/ipa/rkisp1/data/ov5640.yaml
index 13f76412..fa2ae436 100644
--- a/src/ipa/rkisp1/data/ov5640.yaml
+++ b/src/ipa/rkisp1/data/ov5640.yaml
@@ -16,4 +16,83 @@  algorithms:
         red:   [ 0, 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4095 ]
         green: [ 0, 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4095 ]
         blue:  [ 0, 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4095 ]
+  - LensShadingCorrection:
+      x-size: [ 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625 ]
+      y-size: [ 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625 ]
+      r:  [
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+          ]
+      gr: [
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+          ]
+      gb: [
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+          ]
+      b:  [
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+            1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+          ]
 ...
diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp
index 1559d3ff..30bb87a9 100644
--- a/src/ipa/rkisp1/ipa_context.cpp
+++ b/src/ipa/rkisp1/ipa_context.cpp
@@ -95,6 +95,9 @@  namespace libcamera::ipa::rkisp1 {
  *
  * \var IPASessionConfiguration::sensor.lineDuration
  * \brief Line duration in microseconds
+ *
+ * \var IPASessionConfiguration::sensor.size
+ * \brief Sensor output resolution
  */
 
 /**
diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
index f387cace..3bfb262c 100644
--- a/src/ipa/rkisp1/ipa_context.h
+++ b/src/ipa/rkisp1/ipa_context.h
@@ -33,6 +33,7 @@  struct IPASessionConfiguration {
 
 	struct {
 		utils::Duration lineDuration;
+		Size size;
 	} sensor;
 
 	struct {
diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
index 4018265c..e5010f6a 100644
--- a/src/ipa/rkisp1/rkisp1.cpp
+++ b/src/ipa/rkisp1/rkisp1.cpp
@@ -211,6 +211,7 @@  int IPARkISP1::configure([[maybe_unused]] const IPACameraSensorInfo &info,
 	/* Set the hardware revision for the algorithms. */
 	context_.configuration.hw.revision = hwRevision_;
 
+	context_.configuration.sensor.size = info.outputSize;
 	context_.configuration.sensor.lineDuration = info.lineLength * 1.0s / info.pixelRate;
 
 	/*