diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp
index 1e43f3fd..ff6591de 100644
--- a/src/ipa/simple/algorithms/awb.cpp
+++ b/src/ipa/simple/algorithms/awb.cpp
@@ -27,7 +27,7 @@ int Awb::init(IPAContext &context,
 	      [[maybe_unused]] const YamlObject &tuningData)
 {
 	auto &gains = context.activeState.gains;
-	gains.red = gains.green = gains.blue = 256;
+	gains.red = gains.green = gains.blue = 1.0;
 
 	return 0;
 }
@@ -40,15 +40,18 @@ void Awb::prepare(IPAContext &context,
 	auto &gains = context.activeState.gains;
 	auto &gammaTable = context.activeState.gamma.gammaTable;
 	for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) {
-		constexpr unsigned int div =
-			static_cast<double>(DebayerParams::kRGBLookupSize) * 256 / kGammaLookupSize;
+		constexpr double div =
+			static_cast<double>(DebayerParams::kRGBLookupSize) / kGammaLookupSize;
 		/* Apply gamma after gain! */
 		unsigned int idx;
-		idx = std::min({ i * gains.red / div, kGammaLookupSize - 1 });
+		idx = std::min({ static_cast<unsigned int>(i * gains.red / div),
+				 kGammaLookupSize - 1 });
 		params->red[i] = gammaTable[idx];
-		idx = std::min({ i * gains.green / div, kGammaLookupSize - 1 });
+		idx = std::min({ static_cast<unsigned int>(i * gains.green / div),
+				 kGammaLookupSize - 1 });
 		params->green[i] = gammaTable[idx];
-		idx = std::min({ i * gains.blue / div, kGammaLookupSize - 1 });
+		idx = std::min({ static_cast<unsigned int>(i * gains.blue / div),
+				 kGammaLookupSize - 1 });
 		params->blue[i] = gammaTable[idx];
 	}
 }
@@ -60,7 +63,7 @@ void Awb::process(IPAContext &context,
 		  [[maybe_unused]] ControlList &metadata)
 {
 	const SwIspStats::Histogram &histogram = stats->yHistogram;
-	const uint8_t blackLevel = context.activeState.black.level;
+	const double blackLevel = context.activeState.black.level;
 
 	/*
 	 * Black level must be subtracted to get the correct AWB ratios, they
@@ -77,12 +80,11 @@ void Awb::process(IPAContext &context,
 	/*
 	 * Calculate red and blue gains for AWB.
 	 * Clamp max gain at 4.0, this also avoids 0 division.
-	 * Gain: 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.
 	 */
 	auto &gains = context.activeState.gains;
-	gains.red = sumR <= sumG / 4 ? 1024 : 256 * sumG / sumR;
-	gains.blue = sumB <= sumG / 4 ? 1024 : 256 * sumG / sumB;
-	/* Green gain is fixed to 256 */
+	gains.red = sumR <= sumG / 4 ? 4.0 : static_cast<double>(sumG) / sumR;
+	gains.blue = sumB <= sumG / 4 ? 4.0 : static_cast<double>(sumG) / sumB;
+	/* Green gain is fixed to 1.0 */
 
 	LOG(IPASoftAwb, Debug) << "gain R/B " << gains.red << "/" << gains.blue;
 }
diff --git a/src/ipa/simple/algorithms/blc.cpp b/src/ipa/simple/algorithms/blc.cpp
index 3b73d830..ab7e7dd9 100644
--- a/src/ipa/simple/algorithms/blc.cpp
+++ b/src/ipa/simple/algorithms/blc.cpp
@@ -24,7 +24,7 @@ BlackLevel::BlackLevel()
 int BlackLevel::init(IPAContext &context,
 		     [[maybe_unused]] const YamlObject &tuningData)
 {
-	context.activeState.black.level = 255;
+	context.activeState.black.level = 1.0;
 	return 0;
 }
 
@@ -44,16 +44,16 @@ void BlackLevel::process(IPAContext &context,
 	const unsigned int total =
 		std::accumulate(begin(histogram), end(histogram), 0);
 	const unsigned int pixelThreshold = ignoredPercentage_ * total;
-	const unsigned int histogramRatio = 256 / SwIspStats::kYHistogramSize;
 	const unsigned int currentBlackIdx =
-		context.activeState.black.level / histogramRatio;
+		context.activeState.black.level * SwIspStats::kYHistogramSize;
 
 	for (unsigned int i = 0, seen = 0;
 	     i < currentBlackIdx && i < SwIspStats::kYHistogramSize;
 	     i++) {
 		seen += histogram[i];
 		if (seen >= pixelThreshold) {
-			context.activeState.black.level = i * histogramRatio;
+			context.activeState.black.level =
+				static_cast<double>(i) / SwIspStats::kYHistogramSize;
 			LOG(IPASoftBL, Debug)
 				<< "Auto-set black level: "
 				<< i << "/" << SwIspStats::kYHistogramSize
diff --git a/src/ipa/simple/algorithms/gamma.cpp b/src/ipa/simple/algorithms/gamma.cpp
index 0b8ec5ee..b03dff25 100644
--- a/src/ipa/simple/algorithms/gamma.cpp
+++ b/src/ipa/simple/algorithms/gamma.cpp
@@ -34,7 +34,7 @@ void Gamma::updateGammaTable(IPAContext &context)
 	auto &gammaTable = context.activeState.gamma.gammaTable;
 	auto blackLevel = context.activeState.black.level;
 	const unsigned int blackIndex =
-		blackLevel * IPAActiveState::kGammaLookupSize / 256;
+		blackLevel * IPAActiveState::kGammaLookupSize;
 	std::fill(gammaTable.begin(), gammaTable.begin() + blackIndex, 0);
 	const float divisor = kGammaLookupSize - blackIndex - 1.0;
 	for (unsigned int i = blackIndex; i < kGammaLookupSize; i++)
diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h
index f8b8834d..28a02475 100644
--- a/src/ipa/simple/ipa_context.h
+++ b/src/ipa/simple/ipa_context.h
@@ -8,7 +8,6 @@
 #pragma once
 
 #include <array>
-#include <stdint.h>
 
 #include <libipa/fc_queue.h>
 
@@ -22,17 +21,17 @@ struct IPASessionConfiguration {
 
 struct IPAActiveState {
 	struct {
-		uint8_t level;
+		double level;
 	} black;
 	struct {
-		unsigned int red;
-		unsigned int green;
-		unsigned int blue;
+		double red;
+		double green;
+		double blue;
 	} gains;
 	static constexpr unsigned int kGammaLookupSize = 1024;
 	struct {
 		std::array<double, kGammaLookupSize> gammaTable;
-		uint8_t blackLevel;
+		double blackLevel;
 	} gamma;
 };
 
