diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h
index b1b73367e874..458b84e8fa8c 100644
--- a/include/libcamera/controls.h
+++ b/include/libcamera/controls.h
@@ -114,10 +114,12 @@ class ControlRange
 {
 public:
 	explicit ControlRange(const ControlValue &min = 0,
-			      const ControlValue &max = 0);
+			      const ControlValue &max = 0,
+			      const ControlValue &def = 0);
 
 	const ControlValue &min() const { return min_; }
 	const ControlValue &max() const { return max_; }
+	const ControlValue &def() const { return def_; }
 
 	std::string toString() const;
 
@@ -134,6 +136,7 @@ public:
 private:
 	ControlValue min_;
 	ControlValue max_;
+	ControlValue def_;
 };
 
 using ControlIdMap = std::unordered_map<unsigned int, const ControlId *>;
diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp
index 7d8a0e97ee3a..123a6f19974a 100644
--- a/src/libcamera/controls.cpp
+++ b/src/libcamera/controls.cpp
@@ -357,10 +357,12 @@ Control<int64_t>::Control(unsigned int id, const char *name)
  * \brief Construct a ControlRange with minimum and maximum range parameters
  * \param[in] min The control minimum value
  * \param[in] max The control maximum value
+ * \param[in] def The control default value
  */
 ControlRange::ControlRange(const ControlValue &min,
-			   const ControlValue &max)
-	: min_(min), max_(max)
+			   const ControlValue &max,
+			   const ControlValue &def)
+	: min_(min), max_(max), def_(def)
 {
 }
 
@@ -376,6 +378,12 @@ ControlRange::ControlRange(const ControlValue &min,
  * \return A ControlValue with the maximum value for the control
  */
 
+/**
+ * \fn ControlRange::def()
+ * \brief Retrieve the default value of the control
+ * \return A ControlValue with the default value for the control
+ */
+
 /**
  * \brief Provide a string representation of the ControlRange
  */
diff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp
index b6547a7c627c..7446c3880330 100644
--- a/src/libcamera/v4l2_controls.cpp
+++ b/src/libcamera/v4l2_controls.cpp
@@ -121,17 +121,20 @@ V4L2ControlRange::V4L2ControlRange(const struct v4l2_query_ext_ctrl &ctrl)
 	switch (ctrl.type) {
 	case V4L2_CTRL_TYPE_BOOLEAN:
 		ControlRange::operator=(ControlRange(static_cast<bool>(ctrl.minimum),
-						     static_cast<bool>(ctrl.maximum)));
+						     static_cast<bool>(ctrl.maximum),
+						     static_cast<bool>(ctrl.default_value)));
 		break;
 
 	case V4L2_CTRL_TYPE_INTEGER64:
 		ControlRange::operator=(ControlRange(static_cast<int64_t>(ctrl.minimum),
-						     static_cast<int64_t>(ctrl.maximum)));
+						     static_cast<int64_t>(ctrl.maximum),
+						     static_cast<int64_t>(ctrl.default_value)));
 		break;
 
 	default:
 		ControlRange::operator=(ControlRange(static_cast<int32_t>(ctrl.minimum),
-						     static_cast<int32_t>(ctrl.maximum)));
+						     static_cast<int32_t>(ctrl.maximum),
+						     static_cast<int32_t>(ctrl.default_value)));
 		break;
 	}
 }
