diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index 943f26ece974..eaf82d0f1097 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -596,11 +596,6 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
 		status = Adjusted;
 	}
 
-	Orientation requestedOrientation = orientation;
-	combinedTransform_ = data_->sensor_->computeTransform(&orientation);
-	if (orientation != requestedOrientation)
-		status = Adjusted;
-
 	/*
 	 * Simultaneous capture of raw and processed streams isn't possible. If
 	 * there is any raw stream, cap the number of streams to one.
@@ -618,9 +613,24 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
 		}
 	}
 
+	/*
+	 * If the dewarper supports orientation adjustments, apply that completely
+	 * there. Even if the sensor supports flips, it is beneficial to do that
+	 * in the dewarper so that lens dewarping happens on the unflipped image
+	 */
+	bool transposeAfterIsp = false;
 	bool useDewarper = false;
-	if (data_->canUseDewarper_ && !isRaw)
+	if (data_->canUseDewarper_ && !isRaw) {
 		useDewarper = true;
+		combinedTransform_ = orientation / data_->sensor_->mountingOrientation();
+		if (!!(combinedTransform_ & Transform::Transpose))
+			transposeAfterIsp = true;
+	} else {
+		Orientation requestedOrientation = orientation;
+		combinedTransform_ = data_->sensor_->computeTransform(&orientation);
+		if (orientation != requestedOrientation)
+			status = Adjusted;
+	}
 
 	/*
 	 * If there are more than one stream in the configuration figure out the
@@ -636,12 +646,18 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
 
 	/*
 	 * Validate the configuration against the desired path and, if the
-	 * platform supports it, the dewarper.
+	 * platform supports it, the dewarper. While iterating over the
+	 * configurations collect the smallest common sensor format.
 	 */
+	Size accumulatedSensorSize;
 	auto validateConfig = [&](StreamConfiguration &cfg, RkISP1Path *path,
 				  Stream *stream, Status expectedStatus) {
 		StreamConfiguration tryCfg = cfg;
 
+		/* Need to validate the path before the transpose */
+		if (transposeAfterIsp)
+			tryCfg.size.transpose();
+
 		Status ret = path->validate(sensor, sensorConfig, &tryCfg);
 		if (ret == Invalid)
 			return false;
@@ -650,6 +666,8 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
 		    (expectedStatus == Valid && ret == Adjusted))
 			return false;
 
+		Size sensorSize = tryCfg.size;
+
 		if (useDewarper) {
 			/*
 			 * The dewarper output is independent of the ISP path.
@@ -672,6 +690,8 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
 
 		cfg = tryCfg;
 		cfg.setStream(stream);
+
+		accumulatedSensorSize = std::max(accumulatedSensorSize, sensorSize);
 		return true;
 	};
 
@@ -722,13 +742,6 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
 		return Invalid;
 	}
 
-	/* Select the sensor format. */
-	Size maxSize;
-
-	for (const StreamConfiguration &cfg : config_) {
-		maxSize = std::max(maxSize, cfg.size);
-	}
-
 	std::vector<unsigned int> mbusCodes;
 
 	if (isRaw) {
@@ -739,7 +752,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
 			       [](const auto &value) { return value.second; });
 	}
 
-	sensorFormat_ = sensor->getFormat(mbusCodes, maxSize,
+	sensorFormat_ = sensor->getFormat(mbusCodes, accumulatedSensorSize,
 					  mainPath->maxResolution());
 
 	if (sensorFormat_.size.isNull())
@@ -774,6 +787,22 @@ PipelineHandlerRkISP1::generateConfiguration(Camera *camera,
 	if (roles.empty())
 		return config;
 
+	Transform transform = Transform::Identity;
+	Size previewSize = kRkISP1PreviewSize;
+	bool transposeAfterIsp = false;
+	if (data->canUseDewarper_) {
+		transform = Orientation::Rotate0 / data->sensor_->mountingOrientation();
+		if (!!(transform & Transform::Transpose))
+			transposeAfterIsp = true;
+	}
+
+	/*
+	 * In case of a transpose transform we need to create a path for the
+	 * transposed size.
+	 */
+	if (transposeAfterIsp)
+		previewSize.transpose();
+
 	/*
 	 * As the ISP can't output different color spaces for the main and self
 	 * path, pick a sensible default color space based on the role of the
@@ -802,7 +831,7 @@ PipelineHandlerRkISP1::generateConfiguration(Camera *camera,
 			if (!colorSpace)
 				colorSpace = ColorSpace::Sycc;
 
-			size = kRkISP1PreviewSize;
+			size = previewSize;
 			break;
 
 		case StreamRole::VideoRecording:
@@ -810,7 +839,7 @@ PipelineHandlerRkISP1::generateConfiguration(Camera *camera,
 			if (!colorSpace)
 				colorSpace = ColorSpace::Rec709;
 
-			size = kRkISP1PreviewSize;
+			size = previewSize;
 			break;
 
 		case StreamRole::Raw:
@@ -852,6 +881,9 @@ PipelineHandlerRkISP1::generateConfiguration(Camera *camera,
 		if (!cfg.pixelFormat.isValid())
 			return nullptr;
 
+		if (transposeAfterIsp && role != StreamRole::Raw)
+			cfg.size.transpose();
+
 		cfg.colorSpace = colorSpace;
 		cfg.bufferCount = kRkISP1MinBufferCount;
 		config->addConfiguration(cfg);
@@ -874,6 +906,19 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)
 	if (ret)
 		return ret;
 
+	const PixelFormat &streamFormat = config->at(0).pixelFormat;
+	const PixelFormatInfo &info = PixelFormatInfo::info(streamFormat);
+	isRaw_ = info.colourEncoding == PixelFormatInfo::ColourEncodingRAW;
+	data->usesDewarper_ = data->canUseDewarper_ && !isRaw_;
+
+	Transform transform = config->combinedTransform();
+	bool transposeAfterIsp = false;
+	if (data->usesDewarper_) {
+		if (!!(transform & Transform::Transpose))
+			transposeAfterIsp = true;
+		transform = Transform::Identity;
+	}
+
 	/*
 	 * Configure the format on the sensor output and propagate it through
 	 * the pipeline.
@@ -883,10 +928,10 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)
 
 	if (config->sensorConfig)
 		ret = sensor->applyConfiguration(*config->sensorConfig,
-						 config->combinedTransform(),
+						 transform,
 						 &format);
 	else
-		ret = sensor->setFormat(&format, config->combinedTransform());
+		ret = sensor->setFormat(&format, transform);
 
 	if (ret < 0)
 		return ret;
@@ -913,10 +958,6 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)
 		<< " crop " << inputCrop;
 
 	Rectangle outputCrop = inputCrop;
-	const PixelFormat &streamFormat = config->at(0).pixelFormat;
-	const PixelFormatInfo &info = PixelFormatInfo::info(streamFormat);
-	isRaw_ = info.colourEncoding == PixelFormatInfo::ColourEncodingRAW;
-	data->usesDewarper_ = dewarper_ && !isRaw_;
 
 	/* YUYV8_2X8 is required on the ISP source path pad for YUV output. */
 	if (!isRaw_)
@@ -1008,15 +1049,19 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)
 					inputCrop, sensorInfo.analogCrop);
 				auto &vertexMap = dewarper_->vertexMap(cfg.stream());
 				vertexMap.setSensorCrop(sensorCrop);
+				vertexMap.setTransform(config->combinedTransform());
 				data->properties_.set(properties::ScalerCropMaximum, sensorCrop);
 
 				/*
 				 * Apply a default sensor crop that keeps the
 				 * aspect ratio.
 				 */
-				Size crop = format.size.boundedToAspectRatio(cfg.size);
-				vertexMap.setScalerCrop(crop.centeredTo(
-					Rectangle(format.size).center()));
+				Size size = cfg.size;
+				if (transposeAfterIsp)
+					size.transpose();
+				size = sensorCrop.size().boundedToAspectRatio(size);
+				vertexMap.setScalerCrop(
+					size.centeredTo(sensorCrop.center()));
 			}
 
 			ret = mainPath_.configure(ispCfg, format);
