diff --git a/src/libcamera/include/ipa_module.h b/src/libcamera/include/ipa_module.h
index a4c6dbd..58faeca 100644
--- a/src/libcamera/include/ipa_module.h
+++ b/src/libcamera/include/ipa_module.h
@@ -22,11 +22,16 @@ public:
 
 	const struct IPAModuleInfo &info() const;
 
+	bool isAcquired() const;
+	bool acquire();
+	void release();
+
 private:
 	struct IPAModuleInfo info_;
 
 	std::string libPath_;
 	bool valid_;
+	bool acquired_;
 
 	int loadIPAModuleInfo();
 };
diff --git a/src/libcamera/ipa_module.cpp b/src/libcamera/ipa_module.cpp
index 86cbe71..4922e3e 100644
--- a/src/libcamera/ipa_module.cpp
+++ b/src/libcamera/ipa_module.cpp
@@ -176,14 +176,17 @@ int elfLoadSymbol(void *dst, size_t size, void *map, size_t soSize,
  * This structure contains the information of an IPA module. It is loaded,
  * read, and validated before anything else is loaded from the shared object.
  *
- * \var IPAModuleInfo::name
- * \brief The name of the IPA module
+ * \var IPAModuleInfo::ipaAPIVersion
+ * \brief The IPA API version that the IPA module was made with
  *
- * \var IPAModuleInfo::version
- * \brief The version of the IPA module
+ * \var IPAModuleInfo::pipelineVersion
+ * \brief The pipeline version that the IPA module is for
  *
- * \todo abi compatability version
- * \todo pipeline compatability matcher
+ * \var IPAModuleInfo::pipelineName
+ * \brief The name of the pipeline that the IPA module is for
+ *
+ * \var IPAModuleInfo::name
+ * \brief The name of the IPA module
  */
 
 /**
@@ -212,7 +215,7 @@ int elfLoadSymbol(void *dst, size_t size, void *map, size_t soSize,
  * IPAModule instance to verify the validity of the IPAModule.
  */
 IPAModule::IPAModule(const std::string &libPath)
-	: libPath_(libPath), valid_(false)
+	: libPath_(libPath), valid_(false), acquired_(false)
 {
 	if (loadIPAModuleInfo() < 0)
 		return;
@@ -289,4 +292,49 @@ const struct IPAModuleInfo &IPAModule::info() const
 	return info_;
 }
 
+/**
+ * \brief Check if IPA module is in use
+ *
+ * \return true if the IPA module has been claimed for exclusive use, or
+ * false if it is available
+ * \sa acquire(), release()
+ */
+bool IPAModule::isAcquired() const
+{
+	return acquired_;
+}
+
+/**
+ * \brief Claim an IPA module for exclusive use
+ *
+ * Each IPA module is meant to be used by only one pipeline handler.
+ * IPA modules will be acquired through the IPAManager, which will
+ * use this method to claim an IPA module before returning it, and will
+ * skip over already claimed IPA modules.
+ *
+ * When the IPA module is not needed anymore, the release() method should
+ * be called.
+ *
+ * \return true if the IPA module was successfully claimed, or false if
+ * was already claimed
+ * \sa isAcquired(), release()
+ */
+bool IPAModule::acquire()
+{
+	if (acquired_)
+		return false;
+
+	acquired_ = true;
+	return true;
+}
+
+/**
+ * \brief Release an IPA module previously claimed for exclusive use
+ * \sa acquire(), isAcquired()
+ */
+void IPAModule::release()
+{
+	acquired_ = false;
+}
+
 } /* namespace libcamera */
