diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp
index a474287..c02b5ec 100644
--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp
+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp
@@ -221,6 +221,18 @@ void Agc::SetConstraintMode(std::string const &constraint_mode_name)
 	constraint_mode_name_ = constraint_mode_name;
 }
 
+void Agc::SwitchMode(CameraMode const &camera_mode, Metadata *metadata)
+{
+	// On a mode switch, it's possible the exposure profile could change,
+	// so we run through the dividing up of exposure/gain again and
+	// write the results into the metadata we've been given.
+	if (status_.total_exposure_value) {
+		housekeepConfig();
+		divvyupExposure();
+		writeAndFinish(metadata, false);
+	}
+}
+
 void Agc::Prepare(Metadata *image_metadata)
 {
 	AgcStatus status;
diff --git a/src/ipa/raspberrypi/controller/rpi/agc.hpp b/src/ipa/raspberrypi/controller/rpi/agc.hpp
index dbcefba..9a7e89c 100644
--- a/src/ipa/raspberrypi/controller/rpi/agc.hpp
+++ b/src/ipa/raspberrypi/controller/rpi/agc.hpp
@@ -75,6 +75,7 @@ public:
 	void SetMeteringMode(std::string const &metering_mode_name) override;
 	void SetExposureMode(std::string const &exposure_mode_name) override;
 	void SetConstraintMode(std::string const &contraint_mode_name) override;
+	void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override;
 	void Prepare(Metadata *image_metadata) override;
 	void Process(StatisticsPtr &stats, Metadata *image_metadata) override;
 
diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp
index d6fd3df..42c84b1 100644
--- a/src/ipa/raspberrypi/raspberrypi.cpp
+++ b/src/ipa/raspberrypi/raspberrypi.cpp
@@ -247,29 +247,30 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,
 		mistrust_count_ = helper_->MistrustFramesStartup();
 	}
 
+	struct AgcStatus agcStatus;
+	/* These zero values mean not program anything (unless overwritten). */
+	agcStatus.shutter_time = 0.0;
+	agcStatus.analogue_gain = 0.0;
+
 	if (!controllerInit_) {
 		/* Load the tuning file for this sensor. */
 		controller_.Read(tuningFile_.c_str());
 		controller_.Initialise();
 		controllerInit_ = true;
 
-		/* Calculate initial values for gain and exposure. */
-		int32_t gain_code = helper_->GainCode(DEFAULT_ANALOGUE_GAIN);
-		int32_t exposure_lines = helper_->ExposureLines(DEFAULT_EXPOSURE_TIME);
-
-		ControlList ctrls(unicam_ctrls_);
-		ctrls.set(V4L2_CID_ANALOGUE_GAIN, gain_code);
-		ctrls.set(V4L2_CID_EXPOSURE, exposure_lines);
-
-		IPAOperationData op;
-		op.operation = RPI_IPA_ACTION_V4L2_SET_STAGGERED;
-		op.controls.push_back(ctrls);
-		queueFrameAction.emit(0, op);
+		/* Supply initial values for gain and exposure. */
+		agcStatus.shutter_time = DEFAULT_EXPOSURE_TIME;
+		agcStatus.analogue_gain = DEFAULT_ANALOGUE_GAIN;
 	}
 
 	RPi::Metadata metadata;
 	controller_.SwitchMode(mode_, &metadata);
 
+	/* SwitchMode may supply updated exposure/gain values to use. */
+	metadata.Get("agc.status", agcStatus);
+	if (agcStatus.shutter_time != 0.0 && agcStatus.analogue_gain != 0.0)
+		applyAGC(&agcStatus);
+
 	lastMode_ = mode_;
 }
 
