diff --git a/include/libcamera/internal/converter/converter_dw100_vertexmap.h b/include/libcamera/internal/converter/converter_dw100_vertexmap.h
index 49ecc81678a0..f79274a6098a 100644
--- a/include/libcamera/internal/converter/converter_dw100_vertexmap.h
+++ b/include/libcamera/internal/converter/converter_dw100_vertexmap.h
@@ -42,7 +42,7 @@ public:
 	const Transform &transform() const { return transform_; }
 
 	void setScale(const float scale) { scale_ = scale; }
-	float effectiveScale() const { return (effectiveScaleX_ + effectiveScaleY_) * 0.5; }
+	std::array<float, 2> effectiveScale() const { return { static_cast<float>(effectiveScaleX_), static_cast<float>(effectiveScaleY_) }; }
 
 	void setRotation(const float rotation) { rotation_ = rotation; }
 	float rotation() const { return rotation_; }
diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml
index 3bcb475fd102..e03b570282ba 100644
--- a/src/libcamera/control_ids_core.yaml
+++ b/src/libcamera/control_ids_core.yaml
@@ -1353,4 +1353,54 @@ controls:
         Enable or disable lens dewarping. This control is only available if lens
         dewarp parameters are configured in the tuning file.
 
+  - Dw100ScaleMode:
+      type: int32_t
+      direction: inout
+      description: |
+        Scale mode of the dewarper.
+      enum:
+        - name: Dw100ScaleModeFill
+          value: 0
+          description: |
+            Fills the given output size with the largest rectangle possible.
+            Aspect ratio is not preserved. Dw100Scale is ignored.
+        - name: Dw100ScaleModeCrop
+          value: 1
+          description: |
+            Crops to the given output size. The scale factor can be specified
+            using Dw100Scale. Aspect ratio is preserved.
+
+  - Dw100Scale:
+      type: float
+      direction: inout
+      description: |
+        Scale factor applied to the image when Dw100ScaleMode is set to Crop.
+        This value is clamped, so that all pixels have valid input data.
+        Therefore a value of 0 always provides the largest possible field of
+        view. Scaling happens centered around the center of the ScalerCrop +
+        Dw10Offset.
+
+  - Dw100Rotation:
+      type: float
+      direction: inout
+      description: |
+        Rotates the image by the given angle in degrees in clockwise direction
+        around the center of ScalerCrop + Dw100Offset
+
+  - Dw100Offset:
+      type: Point
+      direction: inout
+      description: |
+        Moves the image by the given values in x and y direction in sensor
+        coordinate space. This is clamped, so that all output pixels contain
+        valid data. The offset is therefore ignored when the Dw100Scale value is
+        too small.
+
+  - Dw100EffectiveScale:
+      type: float
+      direction: out
+      description: |
+        Effective scale
+      size: [2]
+
 ...
diff --git a/src/libcamera/converter/converter_dw100.cpp b/src/libcamera/converter/converter_dw100.cpp
index 7adad1b502f0..b39e4ab23cd6 100644
--- a/src/libcamera/converter/converter_dw100.cpp
+++ b/src/libcamera/converter/converter_dw100.cpp
@@ -346,6 +346,13 @@ void ConverterDW100Module::updateControlInfos(const Stream *stream, ControlInfoM
 	if (dewarpParams_.has_value())
 		controls[&controls::LensDewarpEnable] = ControlInfo(false, true, true);
 
+	controls[&controls::Dw100Scale] = ControlInfo(0.2f, 8.0f, 1.0f);
+	controls[&controls::Dw100Rotation] = ControlInfo(-180.0f, 180.0f, 0.0f);
+	controls[&controls::Dw100Offset] =
+		ControlInfo(Point(-10000, -10000), Point(10000, 10000), Point(0, 0));
+	controls[&controls::Dw100ScaleMode] =
+		ControlInfo(controls::Dw100ScaleModeValues, controls::Dw100ScaleModeFill);
+
 	if (!converter_.supportsRequests())
 		LOG(Converter, Warning)
 			<< "dw100 kernel driver has no requests support."
@@ -369,6 +376,30 @@ void ConverterDW100Module::setControls(const Stream *stream, const ControlList &
 	auto &info = vertexMaps_[stream];
 	auto &vertexMap = info.map;
 
+	const auto &scale = controls.get(controls::Dw100Scale);
+	if (scale) {
+		vertexMap.setScale(*scale);
+		info.update = true;
+	}
+
+	const auto &rotation = controls.get(controls::Dw100Rotation);
+	if (rotation) {
+		vertexMap.setRotation(*rotation);
+		info.update = true;
+	}
+
+	const auto &offset = controls.get(controls::Dw100Offset);
+	if (offset) {
+		vertexMap.setOffset(*offset);
+		info.update = true;
+	}
+
+	const auto &scaleMode = controls.get(controls::Dw100ScaleMode);
+	if (scaleMode) {
+		vertexMap.setMode(static_cast<Dw100VertexMap::ScaleMode>(*scaleMode));
+		info.update = true;
+	}
+
 	const auto &lensDewarpEnable = controls.get(controls::LensDewarpEnable);
 	if (lensDewarpEnable) {
 		vertexMap.setLensDewarpEnable(*lensDewarpEnable);
@@ -402,6 +433,11 @@ void ConverterDW100Module::populateMetadata(const Stream *stream, ControlList &m
 
 	auto &vertexMap = vertexMaps_[stream].map;
 
+	std::array<float, 2> effectiveScale = vertexMap.effectiveScale();
+	meta.set(controls::Dw100EffectiveScale, effectiveScale);
+	meta.set(controls::Dw100Scale, (effectiveScale[0] + effectiveScale[1]) / 2.0);
+	meta.set(controls::Dw100Rotation, vertexMap.rotation());
+	meta.set(controls::Dw100Offset, vertexMap.effectiveOffset());
 	meta.set(controls::ScalerCrop, vertexMap.effectiveScalerCrop());
 
 	if (dewarpParams_.has_value())
