diff --git a/include/libcamera/internal/camera_lens.h b/include/libcamera/internal/camera_lens.h
index f347c5e0..f63bcfa2 100644
--- a/include/libcamera/internal/camera_lens.h
+++ b/include/libcamera/internal/camera_lens.h
@@ -27,6 +27,8 @@ public:
 	~CameraLens();
 
 	int init();
+	int open();
+	void close();
 	int setFocusPosition(int32_t position);
 
 	const std::string &model() const { return model_; }
diff --git a/src/libcamera/camera_lens.cpp b/src/libcamera/camera_lens.cpp
index ccc2a6a6..7be5bfd2 100644
--- a/src/libcamera/camera_lens.cpp
+++ b/src/libcamera/camera_lens.cpp
@@ -73,9 +73,47 @@ int CameraLens::init()
 		return ret;
 
 	model_ = subdev_->model();
+
+	/*
+	 * Lens drivers commonly keep the lens powered for as long as the
+	 * subdev is open, and the lens power often depends on the camera
+	 * sensor (e.g. through a runtime PM device link). Close the subdev
+	 * until the lens is actually used, so that a long-lived camera
+	 * manager doesn't keep the lens and the sensor powered.
+	 */
+	subdev_->close();
+
 	return 0;
 }
 
+/**
+ * \brief Open the lens subdev
+ *
+ * Pipeline handlers call this function when the camera starts, to power the
+ * lens for the duration of the capture session. The subdev is also opened on
+ * demand by setFocusPosition().
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int CameraLens::open()
+{
+	if (subdev_->isOpen())
+		return 0;
+
+	return subdev_->open();
+}
+
+/**
+ * \brief Close the lens subdev
+ *
+ * Pipeline handlers call this function when the camera stops, to let the lens
+ * driver power the lens down.
+ */
+void CameraLens::close()
+{
+	subdev_->close();
+}
+
 /**
  * \brief This function sets the focal point of the lens to a specific position.
  * \param[in] position The focal point of the lens
@@ -86,6 +124,10 @@ int CameraLens::init()
  */
 int CameraLens::setFocusPosition(int32_t position)
 {
+	int ret = open();
+	if (ret)
+		return ret;
+
 	ControlList lensCtrls(subdev_->controls());
 	lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, static_cast<int32_t>(position));
 
