diff --git a/src/ipa/libipa/agc.cpp b/src/ipa/libipa/agc.cpp
index 51b05e3c2a..e793de832b 100644
--- a/src/ipa/libipa/agc.cpp
+++ b/src/ipa/libipa/agc.cpp
@@ -489,7 +489,7 @@ int AgcAlgorithm::configure(agc::Session &session, agc::ActiveState &state,
 		[&](AgcMSV &) {
 			/* No constraint/exposure mode support. */
 			state.constraintMode = controls::AeConstraintModeEnum::ConstraintNormal;
-			state.exposureMode = controls::AeExposureModeEnum::ExposureNormal;
+			state.exposureMode = controls::AeExposureModeEnum::ExposureMaximize;
 
 			state.automatic.yTarget = 0; /* Not supported. */
 
diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp
index f0e47cc06d..3ecdebd3cf 100644
--- a/src/ipa/libipa/agc_mean_luminance.cpp
+++ b/src/ipa/libipa/agc_mean_luminance.cpp
@@ -281,11 +281,20 @@ int AgcMeanLuminance::parseConstraintModes(const ValueNode &tuningData)
 
 int AgcMeanLuminance::parseExposureModes(const ValueNode &tuningData)
 {
+	static const std::pair<std::string_view, controls::AeExposureModeEnum> modes[] = {
+		{ "ExposureNormal", controls::ExposureNormal },
+		{ "ExposureShort", controls::ExposureShort },
+		{ "ExposureLong", controls::ExposureLong },
+		{ "ExposureCustom", controls::ExposureCustom },
+	};
+
 	const ValueNode &exposureModes = tuningData[controls::AeExposureMode.name()];
 	if (exposureModes.isDictionary()) {
 		for (const auto &[modeName, modeValues] : exposureModes.asDict()) {
-			auto it = AeExposureModeNameValueMap.find(modeName);
-			if (it == AeExposureModeNameValueMap.end()) {
+			auto it = std::find_if(std::begin(modes), std::end(modes), [&name = modeName](const auto &m) {
+				return m.first == name;
+			});
+			if (it == std::end(modes)) {
 				LOG(AgcMeanLuminance, Warning)
 					<< "Skipping unknown exposure mode '" << modeName << "'";
 				continue;
@@ -326,13 +335,11 @@ int AgcMeanLuminance::parseExposureModes(const ValueNode &tuningData)
 		}
 	}
 
-	/*
-	 * If we don't have any exposure modes in the tuning data we create an
-	 * ExposureModeHelper in "maximize" mode.
-	 */
-	if (exposureModeHelpers_.empty())
-		exposureModeHelpers_.try_emplace(controls::ExposureNormal,
-						 ExposureModeHelper::Maximize{});
+	/* These need no configuration, so they are always available. */
+	exposureModeHelpers_.try_emplace(controls::ExposureMaximize,
+					 ExposureModeHelper::Maximize{});
+	exposureModeHelpers_.try_emplace(controls::ExposureMinimize,
+					 ExposureModeHelper::Minimize{});
 
 	return 0;
 }
diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml
index 89991d03d7..c29d9fb1d3 100644
--- a/src/libcamera/control_ids_core.yaml
+++ b/src/libcamera/control_ids_core.yaml
@@ -188,6 +188,12 @@ controls:
         - name: ExposureCustom
           value: 3
           description: Custom exposure mode.
+        - name: ExposureMaximize
+          value: 4
+          description: Maximize exposure time.
+        - name: ExposureMinimize
+          value: 5
+          description: Minimize exposure time.
 
   - ExposureValue:
       type: float
