diff --git a/src/ipa/libipa/lsc_base.cpp b/src/ipa/libipa/lsc_base.cpp
index d545e9a5f7ed..bddf131b85e2 100644
--- a/src/ipa/libipa/lsc_base.cpp
+++ b/src/ipa/libipa/lsc_base.cpp
@@ -49,6 +49,21 @@ namespace lsc {
 
 } /* namespace lsc */
 
+#ifndef __DOXYGEN__
+template<>
+void Interpolator<lsc::Components>::
+	interpolate(const lsc::Components &a,
+		    const lsc::Components &b,
+		    lsc::Components &dest,
+		    double lambda)
+{
+	interpolateVector(a.r, b.r, dest.r, lambda);
+	interpolateVector(a.gr, b.gr, dest.gr, lambda);
+	interpolateVector(a.gb, b.gb, dest.gb, lambda);
+	interpolateVector(a.b, b.b, dest.b, lambda);
+}
+#endif
+
 /**
  * \class LscImplementation
  * \brief Pure virtual base class for lsc algorithm implementations
diff --git a/src/ipa/libipa/lsc_base.h b/src/ipa/libipa/lsc_base.h
index 93f819d3c2af..51cc35888209 100644
--- a/src/ipa/libipa/lsc_base.h
+++ b/src/ipa/libipa/lsc_base.h
@@ -18,6 +18,8 @@
 
 #include "libcamera/internal/value_node.h"
 
+#include "interpolator.h"
+
 namespace libcamera {
 
 namespace ipa {
@@ -35,6 +37,25 @@ using ComponentsMap = std::map<unsigned int, Components>;
 
 } /* namespace lsc */
 
+#ifndef __DOXYGEN__
+template<typename T>
+void interpolateVector(const std::vector<T> &a, const std::vector<T> &b,
+		       std::vector<T> &dest, double lambda)
+{
+	ASSERT(a.size() == b.size());
+	dest.resize(a.size());
+	for (size_t i = 0; i < a.size(); i++)
+		dest[i] = a[i] * (1.0 - lambda) + b[i] * lambda;
+}
+
+template<>
+void Interpolator<lsc::Components>::
+	interpolate(const lsc::Components &a,
+		    const lsc::Components &b,
+		    lsc::Components &dest,
+		    double lambda);
+#endif /* __DOXYGEN__ */
+
 class LscImplementation
 {
 public:
diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp
index 6c6dce08704c..fec698234583 100644
--- a/src/ipa/rkisp1/algorithms/lsc.cpp
+++ b/src/ipa/rkisp1/algorithms/lsc.cpp
@@ -25,33 +25,6 @@
 
 namespace libcamera {
 
-namespace ipa {
-
-template<typename T>
-void interpolateVector(const std::vector<T> &a, const std::vector<T> &b,
-		       std::vector<T> &dest, double lambda)
-{
-	ASSERT(a.size() == b.size());
-	dest.resize(a.size());
-	for (size_t i = 0; i < a.size(); i++)
-		dest[i] = a[i] * (1.0 - lambda) + b[i] * lambda;
-}
-
-template<>
-void Interpolator<lsc::Components>::
-	interpolate(const lsc::Components &a,
-		    const lsc::Components &b,
-		    lsc::Components &dest,
-		    double lambda)
-{
-	interpolateVector(a.r, b.r, dest.r, lambda);
-	interpolateVector(a.gr, b.gr, dest.gr, lambda);
-	interpolateVector(a.gb, b.gb, dest.gb, lambda);
-	interpolateVector(a.b, b.b, dest.b, lambda);
-}
-
-} /* namespace ipa */
-
 namespace ipa::rkisp1::algorithms {
 
 
