camera: intel: ipu6: fix dual camera/sensor issues

Add dual camera support for face detection
Add multi-sensor module info support

BUG=b:149068439, b:149068672
TEST=Full tested pass for camera functions.

Change-Id: I34ad6421dca663eccde8cbde9068d2180e662e87
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2600370
Tested-by: Zong Li <zong.li@intel.com>
Reviewed-by: Ren-Pei Zeng <kamesan@chromium.org>
Commit-Queue: Ren-Pei Zeng <kamesan@chromium.org>
diff --git a/camera/hal/intel/ipu6/modules/algowrapper/IntelFaceDetection.cpp b/camera/hal/intel/ipu6/modules/algowrapper/IntelFaceDetection.cpp
index a68d870..1cf5078 100644
--- a/camera/hal/intel/ipu6/modules/algowrapper/IntelFaceDetection.cpp
+++ b/camera/hal/intel/ipu6/modules/algowrapper/IntelFaceDetection.cpp
@@ -41,7 +41,7 @@
                "buffer is small");
 
     mMaxFacesNum = std::min(pData->max_face_num, static_cast<unsigned int>(MAX_FACES_DETECTABLE));
-    LOG2("@%s, mMaxFacesNum:%d", __func__, mMaxFacesNum);
+    LOG2("@%s, mMaxFacesNum:%d, cameraId:%d", __func__, mMaxFacesNum, pData->cameraId);
 
     pvl_err faceRet = pvl_face_detection_create(nullptr, &mFDHandle);
     CheckError(faceRet != pvl_success, UNKNOWN_ERROR,
@@ -60,8 +60,11 @@
     return OK;
 }
 
-status_t IntelFaceDetection::deinit() {
-    LOG1("@%s", __func__);
+status_t IntelFaceDetection::deinit(FaceDetectionDeinitParams* pData, int dataSize) {
+    CheckError(!pData, UNKNOWN_ERROR, "pData is nullptr");
+    CheckError(dataSize < static_cast<int>(sizeof(FaceDetectionDeinitParams)), UNKNOWN_ERROR,
+               "buffer is small");
+    LOG1("@%s, cameraId:%d", __func__, pData->cameraId);
 
     if (mFDHandle) {
         pvl_face_detection_destroy(mFDHandle);
diff --git a/camera/hal/intel/ipu6/modules/algowrapper/IntelFaceDetection.h b/camera/hal/intel/ipu6/modules/algowrapper/IntelFaceDetection.h
index da738ef..020c0d9 100644
--- a/camera/hal/intel/ipu6/modules/algowrapper/IntelFaceDetection.h
+++ b/camera/hal/intel/ipu6/modules/algowrapper/IntelFaceDetection.h
@@ -27,8 +27,8 @@
     IntelFaceDetection();
     ~IntelFaceDetection();
 
-    status_t init(FaceDetectionInitParams* initData, int dataSize);
-    status_t deinit();
+    status_t init(FaceDetectionInitParams* pData, int dataSize);
+    status_t deinit(FaceDetectionDeinitParams* pData, int dataSize);
     status_t run(pvl_image* pImage, FaceDetectionResult* fdResults);
     status_t run(FaceDetectionRunParams* fdRunParams, int dataSize, void* addr = nullptr);
     FaceDetectionRunParams* prepareRunBuffer(unsigned int index);
diff --git a/camera/hal/intel/ipu6/modules/sandboxing/IPCIntelFD.cpp b/camera/hal/intel/ipu6/modules/sandboxing/IPCIntelFD.cpp
index 825d072..800d2aa 100644
--- a/camera/hal/intel/ipu6/modules/sandboxing/IPCIntelFD.cpp
+++ b/camera/hal/intel/ipu6/modules/sandboxing/IPCIntelFD.cpp
@@ -31,19 +31,22 @@
     LOG1("@%s", __func__);
 }
 
-bool IPCIntelFD::clientFlattenInit(unsigned int max_face_num, FaceDetectionInitParams* params) {
+bool IPCIntelFD::clientFlattenInit(unsigned int max_face_num, int cameraId,
+                                   FaceDetectionInitParams* params) {
     LOG1("@%s, params:%p", __func__, params);
     CheckError(params == nullptr, false, "@%s, params is nullptr", __func__);
 
     params->max_face_num = max_face_num;
+    params->cameraId = cameraId;
 
     return true;
 }
 
 bool IPCIntelFD::serverUnflattenRun(const FaceDetectionRunParams& inParams, void* imageData,
-                                    pvl_image* image) {
+                                    pvl_image* image, int* cameraId) {
     LOG1("@%s, image:%p", __func__, image);
-    CheckError(image == nullptr, false, "@%s, iamge is nullptr", __func__);
+    CheckError(image == nullptr || cameraId == nullptr, false, "@%s, image or cameraId is nullptr",
+               __func__);
 
     image->size = inParams.size;
     image->width = inParams.width;
@@ -51,6 +54,7 @@
     image->format = inParams.format;
     image->stride = inParams.stride;
     image->rotation = inParams.rotation;
+    *cameraId = inParams.cameraId;
 
     if (imageData) {
         image->data = const_cast<uint8_t*>(static_cast<uint8_t*>(imageData));
diff --git a/camera/hal/intel/ipu6/modules/sandboxing/IPCIntelFD.h b/camera/hal/intel/ipu6/modules/sandboxing/IPCIntelFD.h
index ebfabfa..d27ed7f 100644
--- a/camera/hal/intel/ipu6/modules/sandboxing/IPCIntelFD.h
+++ b/camera/hal/intel/ipu6/modules/sandboxing/IPCIntelFD.h
@@ -25,8 +25,9 @@
     IPCIntelFD();
     virtual ~IPCIntelFD();
 
-    bool clientFlattenInit(unsigned int max_face_num, FaceDetectionInitParams* params);
+    bool clientFlattenInit(unsigned int max_face_num, int cameraId,
+                           FaceDetectionInitParams* params);
     bool serverUnflattenRun(const FaceDetectionRunParams& inParams, void* imageData,
-                            pvl_image* image);
+                            pvl_image* image, int* cameraId);
 };
 } /* namespace icamera */
diff --git a/camera/hal/intel/ipu6/modules/sandboxing/client/IntelFaceDetection.cpp b/camera/hal/intel/ipu6/modules/sandboxing/client/IntelFaceDetection.cpp
index 194be11..56bb71e 100644
--- a/camera/hal/intel/ipu6/modules/sandboxing/client/IntelFaceDetection.cpp
+++ b/camera/hal/intel/ipu6/modules/sandboxing/client/IntelFaceDetection.cpp
@@ -28,7 +28,9 @@
 
     uintptr_t personal = reinterpret_cast<uintptr_t>(this);
     mMems = {{("/faceDetectionInit" + std::to_string(personal) + "Shm"),
-              sizeof(FaceDetectionInitParams), &mMemInit, false}};
+              sizeof(FaceDetectionInitParams), &mMemInit, false},
+              {("/faceDetectionDeinit" + std::to_string(personal) + "Shm"),
+              sizeof(FaceDetectionDeinitParams), &mMemDeinit, false}};
 
     for (int i = 0; i < MAX_STORE_FACE_DATA_BUF_NUM; i++) {
         mMems.push_back(
@@ -62,11 +64,11 @@
 
     unsigned int maxFacesNum =
         std::min(initParams->max_face_num, static_cast<unsigned int>(MAX_FACES_DETECTABLE));
-    LOG2("@%s, maxFacesNum:%d", __func__, maxFacesNum);
+    LOG2("@%s, maxFacesNum:%d, cameraId:%d", __func__, maxFacesNum, initParams->cameraId);
 
     FaceDetectionInitParams* params = static_cast<FaceDetectionInitParams*>(mMemInit.mAddr);
 
-    bool ret = mIpc.clientFlattenInit(maxFacesNum, params);
+    bool ret = mIpc.clientFlattenInit(maxFacesNum, initParams->cameraId, params);
     CheckError(ret == false, UNKNOWN_ERROR, "@%s, clientFlattenInit fails", __func__);
 
     ret = mCommon.requestSync(IPC_FD_INIT, mMemInit.mHandle);
@@ -75,11 +77,16 @@
     return OK;
 }
 
-status_t IntelFaceDetection::deinit() {
+status_t IntelFaceDetection::deinit(FaceDetectionDeinitParams* deinitParams, int dataSize) {
     LOG1("@%s", __func__);
     CheckError(!mInitialized, UNKNOWN_ERROR, "@%s, mInitialized is false", __func__);
+    CheckError(deinitParams == nullptr, UNKNOWN_ERROR, "@%s, deinitParams is nullptr", __func__);
+    CheckError(dataSize < static_cast<int>(sizeof(FaceDetectionDeinitParams)), UNKNOWN_ERROR,
+               "@%s, buffer is small", __func__);
 
-    bool ret = mCommon.requestSync(IPC_FD_DEINIT);
+    FaceDetectionDeinitParams* params = static_cast<FaceDetectionDeinitParams*>(mMemDeinit.mAddr);
+    params->cameraId = deinitParams->cameraId;
+    bool ret = mCommon.requestSync(IPC_FD_DEINIT, mMemDeinit.mHandle);
     CheckError(ret == false, UNKNOWN_ERROR, "@%s, requestSync fails", __func__);
 
     return OK;
diff --git a/camera/hal/intel/ipu6/modules/sandboxing/client/IntelFaceDetection.h b/camera/hal/intel/ipu6/modules/sandboxing/client/IntelFaceDetection.h
index 4f6b567..d029798 100644
--- a/camera/hal/intel/ipu6/modules/sandboxing/client/IntelFaceDetection.h
+++ b/camera/hal/intel/ipu6/modules/sandboxing/client/IntelFaceDetection.h
@@ -31,7 +31,7 @@
     virtual ~IntelFaceDetection();
 
     status_t init(FaceDetectionInitParams* initData, int dataSize);
-    status_t deinit();
+    status_t deinit(FaceDetectionDeinitParams* deinitParams, int dataSize);
     status_t run(FaceDetectionRunParams* runParams, int dataSize, int dmafd = -1);
     FaceDetectionRunParams* prepareRunBuffer(unsigned int index);
 
@@ -42,6 +42,7 @@
     bool mInitialized;
 
     ShmMemInfo mMemInit;
+    ShmMemInfo mMemDeinit;
     ShmMemInfo mMemRunBufs[MAX_STORE_FACE_DATA_BUF_NUM];
     std::vector<ShmMem> mMems;
 };
diff --git a/camera/hal/intel/ipu6/modules/sandboxing/server/IntelCPUAlgoServer.cpp b/camera/hal/intel/ipu6/modules/sandboxing/server/IntelCPUAlgoServer.cpp
index 34af9bf..8f0811c 100644
--- a/camera/hal/intel/ipu6/modules/sandboxing/server/IntelCPUAlgoServer.cpp
+++ b/camera/hal/intel/ipu6/modules/sandboxing/server/IntelCPUAlgoServer.cpp
@@ -83,7 +83,7 @@
             break;
         }
         case IPC_FD_DEINIT:
-            status = mFaceDetection.deinit();
+            status = mFaceDetection.deinit(addr, requestSize);
             break;
         case IPC_GRAPH_ADD_KEY:
             mGraph.addCustomKeyMap();
diff --git a/camera/hal/intel/ipu6/modules/sandboxing/server/IntelFDServer.cpp b/camera/hal/intel/ipu6/modules/sandboxing/server/IntelFDServer.cpp
index 748dbaa..8d2ecfc 100644
--- a/camera/hal/intel/ipu6/modules/sandboxing/server/IntelFDServer.cpp
+++ b/camera/hal/intel/ipu6/modules/sandboxing/server/IntelFDServer.cpp
@@ -25,8 +25,6 @@
 
 namespace icamera {
 IntelFDServer::IntelFDServer() {
-    mFaceDetection = std::unique_ptr<IntelFaceDetection>(new IntelFaceDetection());
-
     LOG1("@%s", __func__);
 }
 
@@ -40,7 +38,13 @@
     CheckError(dataSize < static_cast<int>(sizeof(FaceDetectionInitParams)), UNKNOWN_ERROR,
                "buffer is small");
 
-    return mFaceDetection->init(static_cast<FaceDetectionInitParams*>(pData), dataSize);
+    FaceDetectionInitParams* inParams = static_cast<FaceDetectionInitParams*>(pData);
+    if (mFaceDetection.find(inParams->cameraId) == mFaceDetection.end()) {
+        mFaceDetection[inParams->cameraId] =
+            std::unique_ptr<IntelFaceDetection>(new IntelFaceDetection());
+    }
+
+    return mFaceDetection[inParams->cameraId]->init(inParams, dataSize);
 }
 
 status_t IntelFDServer::run(void* pData, int dataSize, void* imageData) {
@@ -52,14 +56,25 @@
                "buffer is small");
 
     pvl_image image;
+    int cameraId;
     FaceDetectionRunParams* pFdRunParams = static_cast<FaceDetectionRunParams*>(pData);
-    mIpcFD.serverUnflattenRun(*pFdRunParams, imageData, &image);
+    mIpcFD.serverUnflattenRun(*pFdRunParams, imageData, &image, &cameraId);
+    CheckError((mFaceDetection.find(cameraId) == mFaceDetection.end()), UNKNOWN_ERROR,
+               "%s, cameraId:%d, mFaceDetection is nullptr", __func__, cameraId);
 
-    return mFaceDetection->run(&image, &pFdRunParams->results);
+    return mFaceDetection[cameraId]->run(&image, &pFdRunParams->results);
 }
 
-status_t IntelFDServer::deinit() {
-    LOG1("@%s", __func__);
-    return mFaceDetection->deinit();
+status_t IntelFDServer::deinit(void* pData, int dataSize) {
+    LOG1("@%s, pData:%p, dataSize:%d", __func__, pData, dataSize);
+    CheckError(pData == nullptr, UNKNOWN_ERROR, "@%s, pData is nullptr", __func__);
+    CheckError(dataSize < static_cast<int>(sizeof(FaceDetectionDeinitParams)), UNKNOWN_ERROR,
+               "buffer is small");
+
+    FaceDetectionDeinitParams* deinitParams = static_cast<FaceDetectionDeinitParams*>(pData);
+    CheckError((mFaceDetection.find(deinitParams->cameraId) == mFaceDetection.end()), UNKNOWN_ERROR,
+               "%s, cameraId:%d, mFaceDetection is nullptr", __func__, deinitParams->cameraId);
+
+    return mFaceDetection[deinitParams->cameraId]->deinit(deinitParams, dataSize);
 }
 } /* namespace icamera */
diff --git a/camera/hal/intel/ipu6/modules/sandboxing/server/IntelFDServer.h b/camera/hal/intel/ipu6/modules/sandboxing/server/IntelFDServer.h
index 053f5bb..e7d2849 100644
--- a/camera/hal/intel/ipu6/modules/sandboxing/server/IntelFDServer.h
+++ b/camera/hal/intel/ipu6/modules/sandboxing/server/IntelFDServer.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <memory>
+#include <unordered_map>
 
 #include "iutils/Errors.h"
 #include "modules/algowrapper/IntelFaceDetection.h"
@@ -30,10 +31,10 @@
 
     status_t init(void* pData, int dataSize);
     status_t run(void* pData, int dataSize, void* imageData);
-    status_t deinit();
+    status_t deinit(void* pData, int dataSize);
 
  private:
-    std::unique_ptr<IntelFaceDetection> mFaceDetection;
+    std::unordered_map<int, std::unique_ptr<IntelFaceDetection>> mFaceDetection;
     IPCIntelFD mIpcFD;
 };
 } /* namespace icamera */
diff --git a/camera/hal/intel/ipu6/src/fd/FaceBase.h b/camera/hal/intel/ipu6/src/fd/FaceBase.h
index 1405e9c..fa65b72 100644
--- a/camera/hal/intel/ipu6/src/fd/FaceBase.h
+++ b/camera/hal/intel/ipu6/src/fd/FaceBase.h
@@ -54,6 +54,11 @@
 
 struct FaceDetectionInitParams {
     unsigned int max_face_num;
+    int cameraId;
+};
+
+struct FaceDetectionDeinitParams {
+    int cameraId;
 };
 
 #ifdef FACE_DETECTION
@@ -73,6 +78,7 @@
     pvl_image_format format;
     int32_t stride;
     int32_t rotation;
+    int cameraId;
 
     FaceDetectionResult results;
 };
diff --git a/camera/hal/intel/ipu6/src/fd/FaceDetection.cpp b/camera/hal/intel/ipu6/src/fd/FaceDetection.cpp
index d75a666..3a7b242 100644
--- a/camera/hal/intel/ipu6/src/fd/FaceDetection.cpp
+++ b/camera/hal/intel/ipu6/src/fd/FaceDetection.cpp
@@ -93,6 +93,7 @@
     /* init IntelFaceDetection */
     FaceDetectionInitParams params;
     params.max_face_num = maxFaceNum;
+    params.cameraId = mCameraId;
     mFace = std::unique_ptr<IntelFaceDetection>(new IntelFaceDetection());
     ret = mFace->init(&params, sizeof(FaceDetectionInitParams));
     CheckError(ret != OK, VOID_VALUE, "mFace.init fails, ret %d", ret);
@@ -108,11 +109,14 @@
 
 FaceDetection::~FaceDetection() {
     LOG1("@%s", __func__);
-    mFace->deinit();
     requestExit();
 
     AutoMutex l(mRunBufQueueLock);
     mRunCondition.notify_one();
+
+    FaceDetectionDeinitParams params;
+    params.cameraId = mCameraId;
+    mFace->deinit(&params, sizeof(FaceDetectionDeinitParams));
 }
 
 FaceDetectionRunParams *FaceDetection::acquireRunBuf() {
@@ -166,6 +170,7 @@
     params->format = pvl_image_format_nv12;
     params->stride = buffer.s.stride;
     params->bufferHandle = -1;
+    params->cameraId = mCameraId;
 
     nsecs_t startTime = CameraUtils::systemTime();
 
@@ -211,6 +216,7 @@
     params->format = pvl_image_format_gray;
     params->stride = buffer.s.stride;
     params->bufferHandle = -1;
+    params->cameraId = mCameraId;
 
     AutoMutex l(mRunBufQueueLock);
     mRunBufQueue.push(params);
diff --git a/camera/hal/intel/ipu6/src/platformdata/AiqInitData.cpp b/camera/hal/intel/ipu6/src/platformdata/AiqInitData.cpp
index 7f51579..4fde2bf 100644
--- a/camera/hal/intel/ipu6/src/platformdata/AiqInitData.cpp
+++ b/camera/hal/intel/ipu6/src/platformdata/AiqInitData.cpp
@@ -262,8 +262,7 @@
 CpfStore::CpfStore(const std::string& sensorName, const std::string& camCfgDir,
                    const std::vector<TuningConfig>& tuningCfg,
                    const std::vector<LardTagConfig>& lardTagCfg,
-                   const std::string& nvmPath,
-                   std::unordered_map<std::string, std::string> camModuleToAiqbMap,
+                   const std::string& aiqbNameFromModule,
                    ia_binary_data* nvmData)
 {
     LOG1("@%s:Sensor Name = %s", __func__, sensorName.c_str());
@@ -282,15 +281,9 @@
         }
 
         std::string aiqbName(cfg.aiqbName);
-        if (!camModuleToAiqbMap.empty()) {
-            std::string cameraModule;
-            int ret = getCameraModuleFromEEPROM(nvmPath, &cameraModule);
-            if (ret == OK) {
-                if (camModuleToAiqbMap.find(cameraModule) != camModuleToAiqbMap.end()) {
-                    aiqbName.assign(camModuleToAiqbMap[cameraModule]);
-                    LOG1("@%s, aiqb name %s", __func__, aiqbName.c_str());
-                }
-            }
+        if (!aiqbNameFromModule.empty()) {
+            aiqbName.assign(aiqbNameFromModule);
+            LOG1("@%s, aiqb name %s", __func__, aiqbName.c_str());
         }
 
         if (mCpfData.find(aiqbName) == mCpfData.end()) {
@@ -333,45 +326,6 @@
     mCpfData.clear();
 }
 
-int CpfStore::getCameraModuleFromEEPROM(const std::string& nvmPath, std::string* cameraModule)
-{
-    LOG1("@%s, nvmPath %s", __func__, nvmPath.c_str());
-
-    CheckError(nvmPath.empty(), NAME_NOT_FOUND, "nvmPath is empty");
-
-    const int moduleInfoSize = CAMERA_MODULE_INFO_SIZE;
-    const int moduleInfoOffset = CAMERA_MODULE_INFO_OFFSET;
-    struct CameraModuleInfo cameraModuleInfo;
-    CLEAR(cameraModuleInfo);
-    FILE* eepromFile = fopen(nvmPath.c_str(), "rb");
-    CheckError(!eepromFile, UNKNOWN_ERROR, "Failed to open EEPROM file in %s", nvmPath.c_str());
-
-    // file size should be larger than CAMERA_MODULE_INFO_OFFSET
-    fseek(eepromFile, 0, SEEK_END);
-    int nvmDataSize = static_cast<int>(ftell(eepromFile));
-    if (nvmDataSize < moduleInfoOffset) {
-        LOGE("EEPROM data is too small");
-        fclose(eepromFile);
-        return NOT_ENOUGH_DATA;
-    }
-
-    fseek(eepromFile, -1 * moduleInfoOffset, SEEK_END);
-    int ret = fread(&cameraModuleInfo, moduleInfoSize, 1, eepromFile);
-    fclose(eepromFile);
-    CheckError(!ret, UNKNOWN_ERROR, "Failed to read module info %d", ret);
-
-    char tmpName[CAMERA_MODULE_INFO_SIZE];
-    snprintf(tmpName, CAMERA_MODULE_INFO_SIZE, "%c%c%x-%c%c-%d", cameraModuleInfo.mSensorVendor[0],
-             cameraModuleInfo.mSensorVendor[1], cameraModuleInfo.mSensorModel,
-             cameraModuleInfo.mModuleVendor[0], cameraModuleInfo.mModuleVendor[1],
-             cameraModuleInfo.mModuleProduct);
-
-    cameraModule->assign(tmpName);
-    LOG1("%s, aiqb name %s", __func__, cameraModule->c_str());
-
-    return OK;
-}
-
 /**
  * findConfigFile
  *
@@ -502,20 +456,58 @@
     return OK;
 }
 
+int AiqInitData::getCameraModuleFromEEPROM(const std::string& nvmPath, std::string* cameraModule)
+{
+    LOG1("@%s, nvmPath %s", __func__, nvmPath.c_str());
+
+    CheckError(nvmPath.empty(), NAME_NOT_FOUND, "nvmPath is empty");
+
+    const int moduleInfoSize = CAMERA_MODULE_INFO_SIZE;
+    const int moduleInfoOffset = CAMERA_MODULE_INFO_OFFSET;
+    struct CameraModuleInfo cameraModuleInfo;
+    CLEAR(cameraModuleInfo);
+    FILE* eepromFile = fopen(nvmPath.c_str(), "rb");
+    CheckError(!eepromFile, UNKNOWN_ERROR, "Failed to open EEPROM file in %s", nvmPath.c_str());
+
+    // file size should be larger than CAMERA_MODULE_INFO_OFFSET
+    fseek(eepromFile, 0, SEEK_END);
+    int nvmDataSize = static_cast<int>(ftell(eepromFile));
+    if (nvmDataSize < moduleInfoOffset) {
+        LOGE("EEPROM data is too small");
+        fclose(eepromFile);
+        return NOT_ENOUGH_DATA;
+    }
+
+    fseek(eepromFile, -1 * moduleInfoOffset, SEEK_END);
+    int ret = fread(&cameraModuleInfo, moduleInfoSize, 1, eepromFile);
+    fclose(eepromFile);
+    CheckError(!ret, UNKNOWN_ERROR, "Failed to read module info %d", ret);
+
+    char tmpName[CAMERA_MODULE_INFO_SIZE];
+    snprintf(tmpName, CAMERA_MODULE_INFO_SIZE, "%c%c%x-%c%c-%d", cameraModuleInfo.mSensorVendor[0],
+             cameraModuleInfo.mSensorVendor[1], cameraModuleInfo.mSensorModel,
+             cameraModuleInfo.mModuleVendor[0], cameraModuleInfo.mModuleVendor[1],
+             cameraModuleInfo.mModuleProduct);
+
+    cameraModule->assign(tmpName);
+    LOG1("%s, aiqb name %s", __func__, cameraModule->c_str());
+
+    return OK;
+}
+
 AiqInitData::AiqInitData(const std::string& sensorName,
                          const std::string& camCfgDir,
                          const std::vector<TuningConfig>& tuningCfg,
                          const std::vector<LardTagConfig>& lardTagCfg,
                          const std::string& nvmDir,
-                         int maxNvmSize,
-                         const std::unordered_map<std::string, std::string>& camModuleToAiqbMap) :
+                         int maxNvmSize, std::string* camModuleName,
+                         std::unordered_map<std::string, std::string>& camModuleToAiqbMap) :
     mSensorName(sensorName),
     mCamCfgDir(camCfgDir),
     mMaxNvmSize(maxNvmSize),
     mTuningCfg(tuningCfg),
     mLardTagCfg(lardTagCfg),
     mCpfStore(nullptr),
-    mCameraModuleToAiqbMap(camModuleToAiqbMap),
     mNvmDataBuf(nullptr),
     mMakerNote(nullptr)
 {
@@ -531,6 +523,18 @@
 
         mNvmPath.append("eeprom");
         LOG2("NVM data is located in %s", mNvmPath.c_str());
+
+        if (!camModuleToAiqbMap.empty()) {
+            std::string cameraModule;
+            int ret = getCameraModuleFromEEPROM(mNvmPath, &cameraModule);
+            if (ret == OK) {
+                LOG1("@%s, cameraModule %s", __func__, cameraModule.c_str());
+                if (camModuleToAiqbMap.find(cameraModule) != camModuleToAiqbMap.end()) {
+                    mAiqbNameFromModule.assign(camModuleToAiqbMap[cameraModule]);
+                    if (camModuleName) *camModuleName = cameraModule;
+                }
+            }
+        }
     }
 }
 
@@ -552,7 +556,7 @@
     if (!mCpfStore) {
         ia_binary_data* nvmData = getNvm();
         mCpfStore = new CpfStore(mSensorName, mCamCfgDir, mTuningCfg, mLardTagCfg,
-                                 mNvmPath, mCameraModuleToAiqbMap, nvmData);
+                                 mAiqbNameFromModule, nvmData);
     }
     return mCpfStore->getCpfAndCmc(ispData, aiqData, otherData, cmcHandle, mode, cmcData);
 }
diff --git a/camera/hal/intel/ipu6/src/platformdata/AiqInitData.h b/camera/hal/intel/ipu6/src/platformdata/AiqInitData.h
index 3265791..748925c 100644
--- a/camera/hal/intel/ipu6/src/platformdata/AiqInitData.h
+++ b/camera/hal/intel/ipu6/src/platformdata/AiqInitData.h
@@ -170,9 +170,7 @@
     CpfStore(const std::string& sensorName, const std::string& camCfgDir,
              const std::vector<TuningConfig>& tuningCfg,
              const std::vector<LardTagConfig>& lardTagCfg,
-             const std::string& nvmPath,
-             std::unordered_map<std::string, std::string> camModuleToAiqbMap,
-             ia_binary_data* nvmData);
+             const std::string& aiqbNameFromModule, ia_binary_data* nvmData);
     virtual ~CpfStore();
 
     /**
@@ -195,7 +193,6 @@
 private:
     DISALLOW_COPY_AND_ASSIGN(CpfStore);
 
-    int getCameraModuleFromEEPROM(const std::string& nvmPath, std::string* cameraModule);
     int findConfigFile(const std::string& camCfgDir, std::string* cpfPathName);
     int loadConf(const std::string& camCfgDir, const std::string& aiqbName);
 
@@ -215,10 +212,12 @@
                 const std::vector<TuningConfig>& tuningCfg,
                 const std::vector<LardTagConfig>& lardTagCfg,
                 const std::string& nvmDir,
-                int maxNvmSize,
-                const std::unordered_map<std::string, std::string>& camModuleToAiqbMap);
+                int maxNvmSize, std::string* camModuleName,
+                std::unordered_map<std::string, std::string>& camModuleToAiqbMap);
     ~AiqInitData();
 
+    int getCameraModuleFromEEPROM(const std::string& nvmPath, std::string* cameraModule);
+
     // cpf and cmc
     int getCpfAndCmc(ia_binary_data* ispData,
                      ia_binary_data* aiqData,
@@ -252,9 +251,7 @@
     std::vector<LardTagConfig> mLardTagCfg;
     CpfStore* mCpfStore;
 
-    /* key: camera module info, value: aiqb name */
-    std::unordered_map<std::string, std::string> mCameraModuleToAiqbMap;
-
+    std::string mAiqbNameFromModule;
     // NVM data
     std::unique_ptr <char[]> mNvmDataBuf;
     ia_binary_data mNvmData;
diff --git a/camera/hal/intel/ipu6/src/platformdata/CameraParser.cpp b/camera/hal/intel/ipu6/src/platformdata/CameraParser.cpp
index 857a586..893a7b0 100644
--- a/camera/hal/intel/ipu6/src/platformdata/CameraParser.cpp
+++ b/camera/hal/intel/ipu6/src/platformdata/CameraParser.cpp
@@ -1612,7 +1612,7 @@
         mMetadata.update(INTEL_INFO_SENSOR_MOUNT_TYPE, &mountType, 1);
         LOGXML("@%s, sensor mount type: %d", __func__, mountType);
     } else if (strcmp(name, "StaticMetadata") != 0) { // Make sure it doesn't reach the end of StaticMetadata.
-        handleGenericStaticMetaData(name, atts[1]);
+        handleGenericStaticMetaData(name, atts[1], &mMetadata);
     }
 }
 
@@ -1621,9 +1621,12 @@
  *
  * \param name: the element's name.
  * \param src: the element's value, only include data and separator 'x' or ','.
+ * \param metadata: used to save metadata
  */
-void CameraParser::handleGenericStaticMetaData(const char *name, const char *src)
+void CameraParser::handleGenericStaticMetaData(const char* name, const char* src,
+                                               CameraMetadata* metadata)
 {
+    CheckError(!metadata, VOID_VALUE, "metadata is nullptr");
     uint32_t tag = -1;
     if (mGenericStaticMetadataToTag.find(name) != mGenericStaticMetadataToTag.end()) {
         tag = mGenericStaticMetadataToTag[name];
@@ -1683,22 +1686,22 @@
 
     switch (tagType) {
     case ICAMERA_TYPE_BYTE:
-        mMetadata.update(tag, data.u8, index);
+        metadata->update(tag, data.u8, index);
         break;
     case ICAMERA_TYPE_INT32:
-        mMetadata.update(tag, data.i32, index);
+        metadata->update(tag, data.i32, index);
         break;
     case ICAMERA_TYPE_INT64:
-        mMetadata.update(tag, data.i64, index);
+        metadata->update(tag, data.i64, index);
         break;
     case ICAMERA_TYPE_FLOAT:
-        mMetadata.update(tag, data.f, index);
+        metadata->update(tag, data.f, index);
         break;
     case ICAMERA_TYPE_DOUBLE:
-        mMetadata.update(tag, data.d, index);
+        metadata->update(tag, data.d, index);
         break;
     case ICAMERA_TYPE_RATIONAL:
-        mMetadata.update(tag, data.r, index / 2);
+        metadata->update(tag, data.r, index / 2);
         break;
     }
 }
@@ -1728,6 +1731,11 @@
             } else if (strcmp(name, "StaticMetadata") == 0) {
                 profiles->mInStaticMetadata = true;
                 LOGXML("@%s %s, mInStaticMetadata is set to true", __func__, name);
+            } else if (strncmp(name, "CameraModuleInfo_", strlen("CameraModuleInfo_")) == 0) {
+                // tag name like this: CameraModuleInfo_XXX
+                std::string tagName(name);
+                profiles->mCameraModuleName = tagName.substr(strlen("CameraModuleInfo_"));
+                LOGXML("@%s, mCameraModuleInfo %s is set", __func__, name);
             }
 
             if (profiles->mInMediaCtlCfg) {
@@ -1736,6 +1744,9 @@
             } else if (profiles->mInStaticMetadata) {
                 // The StaticMetadata belongs to the sensor segments
                 profiles->handleStaticMetaData(profiles, name, atts);
+            } else if (!profiles->mCameraModuleName.empty()) {
+                // The CameraModuleInfo belongs to the sensor segments
+                profiles->handleGenericStaticMetaData(name, atts[1], &profiles->mCameraModuleMetadata);
             } else {
                 profiles->handleSensor(profiles, name, atts);
             }
@@ -1798,6 +1809,15 @@
         profiles->mInStaticMetadata = false;
     }
 
+    if (strncmp(name, "CameraModuleInfo_", strlen("CameraModuleInfo_")) == 0) {
+        LOGXML("@%s Camera Module Name is %s", __func__, name);
+        if (!profiles->mCameraModuleName.empty()) {
+            profiles->pCurrentCam->mCameraModuleInfoMap[profiles->mCameraModuleName]
+                = mCameraModuleMetadata;
+            profiles->mCameraModuleName.clear();
+        }
+    }
+
     if (strcmp(name, "Common") == 0)
         profiles->mCurrentDataField = FIELD_INVALID;
 }
diff --git a/camera/hal/intel/ipu6/src/platformdata/CameraParser.h b/camera/hal/intel/ipu6/src/platformdata/CameraParser.h
index 8f035c1..05b4433 100644
--- a/camera/hal/intel/ipu6/src/platformdata/CameraParser.h
+++ b/camera/hal/intel/ipu6/src/platformdata/CameraParser.h
@@ -69,6 +69,8 @@
     bool mInStaticMetadata;
     MediaControl* mMC;
     CameraMetadata mMetadata;
+    std::string mCameraModuleName;
+    CameraMetadata mCameraModuleMetadata;
 
     long* mMetadataCache;
     static const int mMetadataCacheSize = 4096;
@@ -103,7 +105,7 @@
 // parse the media controller configuration in xml, the MediaControl MUST be run before the parser to run.
     void handleMediaCtlCfg(CameraParser *profiles, const char *name, const char **atts);
     void handleStaticMetaData(CameraParser *profiles, const char *name, const char **atts);
-    void handleGenericStaticMetaData(const char *name, const char *src);
+    void handleGenericStaticMetaData(const char* name, const char* src, CameraMetadata* metadata);
     void parseMediaCtlConfigElement(CameraParser *profiles, const char *name, const char **atts);
     void storeMcMappForConfig(int mcId, stream_t streamCfg);
     void parseLinkElement(CameraParser *profiles, const char *name, const char **atts);
diff --git a/camera/hal/intel/ipu6/src/platformdata/PlatformData.cpp b/camera/hal/intel/ipu6/src/platformdata/PlatformData.cpp
index 13ecb1f..3e97f3e 100644
--- a/camera/hal/intel/ipu6/src/platformdata/PlatformData.cpp
+++ b/camera/hal/intel/ipu6/src/platformdata/PlatformData.cpp
@@ -91,15 +91,23 @@
 
     StaticCfg *staticCfg = &(getInstance()->mStaticCfg);
     for (size_t i = 0; i < staticCfg->mCameras.size(); i++) {
+        std::string camModuleName;
         AiqInitData* aiqInitData =
             new AiqInitData(staticCfg->mCameras[i].sensorName,
                             getCameraCfgPath(),
                             staticCfg->mCameras[i].mSupportedTuningConfig,
                             staticCfg->mCameras[i].mLardTagsConfig,
                             staticCfg->mCameras[i].mNvmDirectory,
-                            staticCfg->mCameras[i].mMaxNvmDataSize,
+                            staticCfg->mCameras[i].mMaxNvmDataSize, &camModuleName,
                             staticCfg->mCameras[i].mCameraModuleToAiqbMap);
         getInstance()->mAiqInitData.push_back(aiqInitData);
+
+        if (!camModuleName.empty() &&
+            staticCfg->mCameras[i].mCameraModuleInfoMap.find(camModuleName) !=
+            staticCfg->mCameras[i].mCameraModuleInfoMap.end()) {
+            ParameterHelper::merge(staticCfg->mCameras[i].mCameraModuleInfoMap[camModuleName],
+                                  &staticCfg->mCameras[i].mCapability);
+        }
     }
 
     return OK;
diff --git a/camera/hal/intel/ipu6/src/platformdata/PlatformData.h b/camera/hal/intel/ipu6/src/platformdata/PlatformData.h
index dc1604c..1e33187 100644
--- a/camera/hal/intel/ipu6/src/platformdata/PlatformData.h
+++ b/camera/hal/intel/ipu6/src/platformdata/PlatformData.h
@@ -228,8 +228,10 @@
             std::vector<UserToPslOutputMap> mOutputMap;
             int mMaxNvmDataSize;
             std::string mNvmDirectory;
-            /* key: camera module info, value: aiqb name */
+            /* key: camera module name, value: aiqb name */
             std::unordered_map<std::string, std::string> mCameraModuleToAiqbMap;
+            /* key: camera module name, value: camera module info */
+            std::unordered_map<std::string, CameraMetadata> mCameraModuleInfoMap;
             std::vector<IGraphType::ScalerInfo> mScalerInfo;
             int mVideoStreamNum;
             int mTnrExtraFrameNum;