diff --git a/src/ipa/libipa/lsc_base.cpp b/src/ipa/libipa/lsc_base.cpp
index b055249c066a..7b0216b689c4 100644
--- a/src/ipa/libipa/lsc_base.cpp
+++ b/src/ipa/libipa/lsc_base.cpp
@@ -88,8 +88,8 @@ void Interpolator<lsc::Components>::
  * \fn LscImplementation::sampleForCrop
  * \brief Re-sample the lsc components for \a cropRectangle
  * \param[in] cropRectangle The sensor analogue crop rectangle
- * \param[in] xSizes List of horizontal positions of the lsc grid nodes
- * \param[in] ySizes List of vertical positions of the lsc grid nodes
+ * \param[in] xPos List of horizontal positions of the lsc grid nodes
+ * \param[in] yPos List of vertical positions of the lsc grid nodes
  *
  * Lsc tables have to be re-sampled every time a new sensor configuration is
  * used, as each streaming session might use a different sensor crop rectangle
@@ -98,7 +98,7 @@ void Interpolator<lsc::Components>::
  * \a cropRectangle represents the size of the frame on which the Lsc tables
  * have to be re-sampled on.
  *
- * \a xSizes and \a ySizes represent the position of the grid nodes vertexes in
+ * \a xPos and \a yPos represent the position of the grid nodes vertexes in
  * the [0, 1] interval. In example an equally spaced grid of 16 nodes will have
  * each segment of size 0.0625 and the list of nodes position will be
  * [0, 0.0625, 0.125, 0.1875, ... , 1]. It is expected that the first position
diff --git a/src/ipa/libipa/lsc_base.h b/src/ipa/libipa/lsc_base.h
index 51cc35888209..8d1843a5d4fd 100644
--- a/src/ipa/libipa/lsc_base.h
+++ b/src/ipa/libipa/lsc_base.h
@@ -65,8 +65,7 @@ public:
 
 	virtual lsc::ComponentsMap
 	sampleForCrop(const Rectangle &cropRectangle,
-		      Span<const double> xSizes,
-		      Span<const double> ySizes) = 0;
+		      std::vector<double> xPos, std::vector<double> yPos);
 };
 
 } /* namespace ipa */
diff --git a/src/ipa/libipa/lsc_polynomial.cpp b/src/ipa/libipa/lsc_polynomial.cpp
index 5c4ffc98797e..f39122963019 100644
--- a/src/ipa/libipa/lsc_polynomial.cpp
+++ b/src/ipa/libipa/lsc_polynomial.cpp
@@ -184,8 +184,8 @@ int LscPolynomial::parseLscData(const ValueNode &sets)
 /**
  * \brief Re-sample the lsc components for \a cropRectangle
  * \param[in] cropRectangle The sensor analogue crop rectangle
- * \param[in] xSizes List of horizontal positions of the lsc grid nodes
- * \param[in] ySizes List of vertical positions of the lsc grid nodes
+ * \param[in] xPos List of horizontal positions of the lsc grid nodes
+ * \param[in] yPos List of vertical positions of the lsc grid nodes
  *
  * Lsc tables have to be re-sampled every time a new sensor configuration is
  * used, as each streaming session might use a different sensor crop rectangle.
@@ -197,7 +197,7 @@ int LscPolynomial::parseLscData(const ValueNode &sets)
  * \a cropRectangle represents the size of the frame on which the Lsc tables
  * have to be re-sampled on.
  *
- * \a xSizes and \a ySizes represent the position of the grid nodes vertexes in
+ * \a xPos and \a yPos represent the position of the grid nodes vertexes in
  * the [0, 1] interval. In example an equally spaced grid of 16 nodes will have
  * each segment of size 0.0625 and the list of nodes position will be
  * [0, 0.0625, 0.125, 0.1875, ... , 1]. It is expected that the first position
@@ -205,11 +205,8 @@ int LscPolynomial::parseLscData(const ValueNode &sets)
  */
 lsc::ComponentsMap
 LscPolynomial::sampleForCrop(const Rectangle &cropRectangle,
-			     Span<const double> xSizes,
-			     Span<const double> ySizes)
+			     std::vector<double> xPos, std::vector<double> yPos)
 {
-	std::vector<double> xPos = sizesListToPositions(xSizes);
-	std::vector<double> yPos = sizesListToPositions(ySizes);
 
 	lsc::ComponentsMap components;
 
@@ -259,33 +256,6 @@ LscPolynomial::samplePolynomial(const lsc::Polynomial &poly,
 	return samples;
 }
 
-/*
- * The rkisp1 LSC grid spacing is defined by the cell sizes on the top-left
- * quadrant of the grid. This is then mirrored in hardware to the other
- * quadrants. See parseSizes() for further details. For easier handling, this
- * function converts the cell sizes of half the grid to a list of position of
- * the whole grid (on one axis). Example:
- *
- * input:   | 0.2 | 0.3 |
- * output: 0.0   0.2   0.5   0.8   1.0
- */
-std::vector<double>
-LscPolynomial::sizesListToPositions(Span<const double> sizes)
-{
-	const int half = sizes.size();
-	std::vector<double> positions(half * 2 + 1);
-	double x = 0.0;
-
-	positions[half] = 0.5;
-	for (int i = 1; i <= half; i++) {
-		x += sizes[half - i];
-		positions[half - i] = 0.5 - x;
-		positions[half + i] = 0.5 + x;
-	}
-
-	return positions;
-}
-
 } /* namespace ipa */
 
 #ifndef __DOXYGEN__
diff --git a/src/ipa/libipa/lsc_polynomial.h b/src/ipa/libipa/lsc_polynomial.h
index 17c2c34499f0..d2276ecc6f6b 100644
--- a/src/ipa/libipa/lsc_polynomial.h
+++ b/src/ipa/libipa/lsc_polynomial.h
@@ -71,11 +71,9 @@ public:
 
 	lsc::ComponentsMap
 	sampleForCrop(const Rectangle &cropRectangle,
-		      Span<const double> xSizes,
-		      Span<const double> ySizes) override;
+		      std::vector<double> xPos, std::vector<double> yPos) override;
 
 private:
-	std::vector<double> sizesListToPositions(Span<const double> sizes);
 	std::vector<uint16_t> samplePolynomial(const lsc::Polynomial &poly,
 					       Span<const double> xPositions,
 					       Span<const double> yPositions,
diff --git a/src/ipa/libipa/lsc_table.h b/src/ipa/libipa/lsc_table.h
index 0983b78c3f6b..67c7464ea5b6 100644
--- a/src/ipa/libipa/lsc_table.h
+++ b/src/ipa/libipa/lsc_table.h
@@ -30,8 +30,8 @@ public:
 
 	lsc::ComponentsMap
 	sampleForCrop([[maybe_unused]] const Rectangle &cropRectangle,
-		      [[maybe_unused]] Span<const double> xSizes,
-		      [[maybe_unused]] Span<const double> ySizes) override
+		      [[maybe_unused]] std::vector<double> xPos,
+		      [[maybe_unused]] std::vector<double> yPos) override
 	{
 		LOG(LscTable, Warning)
 			<< "Tabular LSC data doesn't support resampling";
diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp
index 0312ce2f8bb1..f393f101b740 100644
--- a/src/ipa/rkisp1/algorithms/lsc.cpp
+++ b/src/ipa/rkisp1/algorithms/lsc.cpp
@@ -70,6 +70,9 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context,
 	if (xSize_.empty() || ySize_.empty())
 		return -EINVAL;
 
+	xPos_ = sizesListToPositions(xSize_);
+	yPos_ = sizesListToPositions(ySize_);
+
 	/* Get all defined sets to apply. */
 	const ValueNode &sets = tuningData["sets"];
 	if (!sets.isList()) {
@@ -138,6 +141,33 @@ std::vector<double> LensShadingCorrection::parseSizes(const ValueNode &tuningDat
 	return sizes;
 }
 
+/*
+ * The rkisp1 LSC grid spacing is defined by the cell sizes on the top-left
+ * quadrant of the grid. This is then mirrored in hardware to the other
+ * quadrants. See parseSizes() for further details. For easier handling, this
+ * function converts the cell sizes of half the grid to a list of position of
+ * the whole grid (on one axis). Example:
+ *
+ * input:   | 0.2 | 0.3 |
+ * output: 0.0   0.2   0.5   0.8   1.0
+ */
+std::vector<double>
+LensShadingCorrection::sizesListToPositions(Span<const double> sizes)
+{
+	const int half = sizes.size();
+	std::vector<double> positions(half * 2 + 1);
+	double x = 0.0;
+
+	positions[half] = 0.5;
+	for (int i = 1; i <= half; i++) {
+		x += sizes[half - i];
+		positions[half - i] = 0.5 - x;
+		positions[half + i] = 0.5 + x;
+	}
+
+	return positions;
+}
+
 /**
  * \copydoc libcamera::ipa::Algorithm::configure
  */
@@ -171,7 +201,7 @@ int LensShadingCorrection::configure(IPAContext &context,
 
 	LOG(RkISP1Lsc, Debug) << "Sample LSC data for " << configInfo.analogCrop;
 	lsc::ComponentsMap shadingData = algo_->sampleForCrop(configInfo.analogCrop,
-							      xSize_, ySize_);
+							      xPos_, yPos_);
 	sets_.setData(std::move(shadingData));
 
 	context.activeState.lsc.enabled = true;
diff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h
index ee037353bbe4..06aa7a5f133c 100644
--- a/src/ipa/rkisp1/algorithms/lsc.h
+++ b/src/ipa/rkisp1/algorithms/lsc.h
@@ -41,9 +41,12 @@ private:
 	void copyTable(rkisp1_cif_isp_lsc_config &config, const lsc::Components &set0);
 	std::vector<double> parseSizes(const ValueNode &tuningData,
 				       const char *prop);
+	std::vector<double> sizesListToPositions(Span<const double> sizes);
 
 	std::vector<double> xSize_;
 	std::vector<double> ySize_;
+	std::vector<double> xPos_;
+	std::vector<double> yPos_;
 	uint16_t xGrad_[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE];
 	uint16_t yGrad_[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE];
 	uint16_t xSizes_[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE];
