diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
index 471c3e2e6e47..a7670b449b31 100644
--- a/src/libcamera/camera_sensor.cpp
+++ b/src/libcamera/camera_sensor.cpp
@@ -248,14 +248,12 @@ int CameraSensor::setFormat(V4L2SubdeviceFormat *format)
 }
 
 /**
- * \brief Retrieve information about a control
- * \param[in] id The control ID
- * \return A pointer to the V4L2ControlInfo for control \a id, or nullptr
- * if the sensor doesn't have such a control
+ * \brief Retrieve the supported V4L2 controls and their information
+ * \return A map of the V4L2 controls supported by the sensor
  */
-const V4L2ControlInfo *CameraSensor::getControlInfo(unsigned int id) const
+const V4L2ControlInfoMap &CameraSensor::controls() const
 {
-	return subdev_->getControlInfo(id);
+	return subdev_->controls();
 }
 
 /**
diff --git a/src/libcamera/include/camera_sensor.h b/src/libcamera/include/camera_sensor.h
index b42e7b8e1343..fe033fb374c1 100644
--- a/src/libcamera/include/camera_sensor.h
+++ b/src/libcamera/include/camera_sensor.h
@@ -13,12 +13,11 @@
 #include <libcamera/geometry.h>
 
 #include "log.h"
+#include "v4l2_controls.h"
 
 namespace libcamera {
 
 class MediaEntity;
-class V4L2ControlInfo;
-class V4L2ControlList;
 class V4L2Subdevice;
 
 struct V4L2SubdeviceFormat;
@@ -43,7 +42,7 @@ public:
 				      const Size &size) const;
 	int setFormat(V4L2SubdeviceFormat *format);
 
-	const V4L2ControlInfo *getControlInfo(unsigned int id) const;
+	const V4L2ControlInfoMap &controls() const;
 	int getControls(V4L2ControlList *ctrls);
 	int setControls(V4L2ControlList *ctrls);
 
diff --git a/src/libcamera/include/v4l2_controls.h b/src/libcamera/include/v4l2_controls.h
index 0047efab11fa..10b726504951 100644
--- a/src/libcamera/include/v4l2_controls.h
+++ b/src/libcamera/include/v4l2_controls.h
@@ -8,11 +8,11 @@
 #ifndef __LIBCAMERA_V4L2_CONTROLS_H__
 #define __LIBCAMERA_V4L2_CONTROLS_H__
 
+#include <map>
+#include <stdint.h>
 #include <string>
 #include <vector>
 
-#include <stdint.h>
-
 #include <linux/v4l2-controls.h>
 #include <linux/videodev2.h>
 
@@ -41,6 +41,8 @@ private:
 	int64_t max_;
 };
 
+using V4L2ControlInfoMap = std::map<unsigned int, V4L2ControlInfo>;
+
 class V4L2Control
 {
 public:
diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h
index 24a0134a2cba..e7e9829cb05f 100644
--- a/src/libcamera/include/v4l2_device.h
+++ b/src/libcamera/include/v4l2_device.h
@@ -13,19 +13,18 @@
 #include <linux/videodev2.h>
 
 #include "log.h"
+#include "v4l2_controls.h"
 
 namespace libcamera {
 
-class V4L2ControlInfo;
-class V4L2ControlList;
-
 class V4L2Device : protected Loggable
 {
 public:
 	void close();
 	bool isOpen() const { return fd_ != -1; }
 
-	const V4L2ControlInfo *getControlInfo(unsigned int id) const;
+	const V4L2ControlInfoMap &controls() const { return controls_; }
+
 	int getControls(V4L2ControlList *ctrls);
 	int setControls(V4L2ControlList *ctrls);
 
@@ -48,7 +47,7 @@ private:
 			    const struct v4l2_ext_control *v4l2Ctrls,
 			    unsigned int count);
 
-	std::map<unsigned int, V4L2ControlInfo> controls_;
+	V4L2ControlInfoMap controls_;
 	std::string deviceNode_;
 	int fd_;
 };
diff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp
index af017bce48ba..84258d9954d0 100644
--- a/src/libcamera/v4l2_controls.cpp
+++ b/src/libcamera/v4l2_controls.cpp
@@ -114,6 +114,11 @@ V4L2ControlInfo::V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl)
  * \return The V4L2 control maximum value
  */
 
+/**
+ * \typedef V4L2ControlInfoMap
+ * \brief A map of control ID to V4L2ControlInfo
+ */
+
 /**
  * \class V4L2Control
  * \brief A V4L2 control value
diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp
index 06939dead705..e3ec44a7f156 100644
--- a/src/libcamera/v4l2_device.cpp
+++ b/src/libcamera/v4l2_device.cpp
@@ -111,19 +111,10 @@ void V4L2Device::close()
  */
 
 /**
- * \brief Retrieve information about a control
- * \param[in] id The control ID
- * \return A pointer to the V4L2ControlInfo for control \a id, or nullptr
- * if the device doesn't have such a control
+ * \fn V4L2Device::controls()
+ * \brief Retrieve the supported V4L2 controls and their information
+ * \return A map of the V4L2 controls supported by the device
  */
-const V4L2ControlInfo *V4L2Device::getControlInfo(unsigned int id) const
-{
-	auto it = controls_.find(id);
-	if (it == controls_.end())
-		return nullptr;
-
-	return &it->second;
-}
 
 /**
  * \brief Read controls from the device
@@ -158,13 +149,14 @@ int V4L2Device::getControls(V4L2ControlList *ctrls)
 
 	for (unsigned int i = 0; i < count; ++i) {
 		const V4L2Control *ctrl = ctrls->getByIndex(i);
-		const V4L2ControlInfo *info = getControlInfo(ctrl->id());
-		if (!info) {
+		const auto iter = controls_.find(ctrl->id());
+		if (iter == controls_.end()) {
 			LOG(V4L2, Error)
 				<< "Control '" << ctrl->id() << "' not found";
 			return -EINVAL;
 		}
 
+		const V4L2ControlInfo *info = &iter->second;
 		controlInfo[i] = info;
 		v4l2Ctrls[i].id = info->id();
 	}
@@ -232,13 +224,14 @@ int V4L2Device::setControls(V4L2ControlList *ctrls)
 
 	for (unsigned int i = 0; i < count; ++i) {
 		const V4L2Control *ctrl = ctrls->getByIndex(i);
-		const V4L2ControlInfo *info = getControlInfo(ctrl->id());
-		if (!info) {
+		const auto iter = controls_.find(ctrl->id());
+		if (iter == controls_.end()) {
 			LOG(V4L2, Error)
 				<< "Control '" << ctrl->id() << "' not found";
 			return -EINVAL;
 		}
 
+		const V4L2ControlInfo *info = &iter->second;
 		controlInfo[i] = info;
 		v4l2Ctrls[i].id = info->id();
 
