Snap for 10447354 from c10c1f3fe74ca56262577066afc7e2693eb946f7 to mainline-wifi-release

Change-Id: Ibab1b0e63e11d6d7aafb4713c4b30363b8e055a4
diff --git a/include/gs101/displaycolor/displaycolor_gs101.h b/include/gs101/displaycolor/displaycolor_gs101.h
index 5c89d76..e339e2f 100644
--- a/include/gs101/displaycolor/displaycolor_gs101.h
+++ b/include/gs101/displaycolor/displaycolor_gs101.h
@@ -47,6 +47,31 @@
     };
 
    public:
+    /// LUT with programmable X and Y
+    template <typename XT, typename YT, size_t N>
+    struct TransferFunctionData {
+        std::array<XT, N> posx;
+        std::array<YT, N> posy;
+    };
+
+    template <typename XType, typename YType, size_t N>
+    struct FlexLutConfigType {
+        // keep XContainer, YContainer and kLutLen for backward compatibility.
+        using XContainer = XType;
+        using YContainer = YType;
+        static constexpr size_t kLutLen = N;
+
+        TransferFunctionData<XContainer, YContainer, kLutLen> tf_data;
+    };
+
+    template <typename DType, size_t N>
+    struct MatrixConfigType {
+        using Container = DType;
+        static constexpr size_t kDimensions = N;
+
+        MatrixData<Container, kDimensions> matrix_data;
+    };
+
     /**
      * @brief Interface for accessing data for DPP stages.
      *
@@ -55,211 +80,219 @@
      * identical, with one caveat: While all G2D layers support display tone
      * mapping (DTM) for HDR10+, only DPP layers L1/L3/L5 support this stage.
      */
-    struct IDpp {
-     private:
-        /// Register data for transfer function LUTs in DPP)
-        template <typename XT, typename YT, size_t N>
-        struct TransferFunctionData {
+    struct IDppData {
+        struct IEotfData {
+            /// Register data for the EOTF LUT in DPP.
+            using EotfData = DisplayStage<FlexLutConfigType<uint16_t, uint32_t, 129>>;
+
+            /// Get data for the EOTF LUT.
+            virtual const EotfData& EotfLut() const = 0;
+            virtual ~IEotfData() {}
+        };
+
+        struct IGmData {
+           public:
+            /// Register data for the gamut mapping (GM) matrix in DPP.
+            using GmData = DisplayStage<MatrixConfigType<uint32_t, 3>>;
+
+            /// Get data for the gamut mapping (GM) matrix.
+            virtual const GmData& Gm() const = 0;
+            virtual ~IGmData() {}
+        };
+
+        struct IDtmData {
+           private:
+            struct Rgb2YData {
+                uint16_t coeff_r;    // DPP_HDR_LSI_L#_TM_COEF[COEFR] #(1, 3, 5)
+                uint16_t coeff_g;    // DPP_HDR_LSI_L#_TM_COEF[COEFG] #(1, 3, 5)
+                uint16_t coeff_b;    // DPP_HDR_LSI_L#_TM_COEF[COEFB] #(1, 3, 5)
+                uint16_t rng_x_min;  // DPP_HDR_LSI_L#_TM_RNGX[MINX] #(1, 3, 5)
+                uint16_t rng_x_max;  // DPP_HDR_LSI_L#_TM_RNGX[MAXX] #(1, 3, 5)
+                uint16_t rng_y_min;  // DPP_HDR_LSI_L#_TM_RNGY[MINY] #(1, 3, 5)
+                uint16_t rng_y_max;  // DPP_HDR_LSI_L#_TM_RNGY[MAXY] #(1, 3, 5)
+            };
+
+            // To avoid updating legacy source code after separate lut and rgb2y,
+            // use inheritance instead of composition.
+            struct DtmConfigType : public FlexLutConfigType<uint16_t, uint32_t, 33>,
+                                   public Rgb2YData {};
+
+           public:
             /**
-             * DPP_HDR_LSI_L#_EOTF_POSX0~64[POSXn], #(0..5), n(0..1)
-             * DPP_HDR_LSI_L#_OETF_POSX0~16[POSXn], #(0..5), n(0..1)
-             * DPP_HDR_LSI_L#_TM_POSX0~16[POSXn], #(1, 3, 5), n(0..1)
+             * @brief Register data for the DTM stage in DPP.
+             *
+             * Note that this data is only applicable to DPP in layers L1/L3/L5
+             * and G2D layers. Other DPPs do not support DTM. DTM data will be
+             * provided for any layer whose DisplayScene::LayerColorData
+             * contains HDR dynamic metadata. It is the caller's (typically
+             * HWComposer) responsibility to validate layers and HW capabilities
+             * correctly, before calling this API.
              */
-            std::array<XT, N> posx;
+            using DtmData = DisplayStage<DtmConfigType>;
+
             /**
-             * DPP_HDR_LSI_L#_EOTF_POSY0~128[POSY0], #(0..5)
-             * DPP_HDR_LSI_L#_OETF_POSY0~16[POSYn] #(0..5), n(0..1)
-             * DPP_HDR_LSI_L#_TM_POSY0~32[POSY0], #(1, 3, 5)
+             * @brief Get data for the DTM LUT. Only used for HDR10+, and only
+             * applicable to DPPs that support this functionality.
              */
-            std::array<YT, N> posy;
+            virtual const DtmData& Dtm() const = 0;
+            virtual ~IDtmData() {}
         };
 
-        struct EotfConfigType {
-            using XContainer = uint16_t;
-            using YContainer = uint32_t;
-            static constexpr size_t kLutLen = 129;
+        struct IOetfData {
+            /// Register data for the OETF LUT in DPP.
+            using OetfData = DisplayStage<FlexLutConfigType<uint32_t, uint16_t, 33>>;
 
-            TransferFunctionData<XContainer, YContainer, kLutLen> tf_data;
+            /// Get data for the OETF LUT.
+            virtual const OetfData& OetfLut() const = 0;
+            virtual ~IOetfData() {}
         };
+    };
 
-        struct GmConfigType {
-            using Container = uint32_t;
-            static constexpr size_t kDimensions = 3;
-
-            MatrixData<Container, kDimensions> matrix_data;
-        };
-
-        struct DtmConfigType {
-            using XContainer = uint16_t;
-            using YContainer = uint32_t;
-            static constexpr size_t kLutLen = 33;
-
-            TransferFunctionData<XContainer, YContainer, kLutLen> tf_data;
-            uint16_t coeff_r;    // DPP_HDR_LSI_L#_TM_COEF[COEFR] #(1, 3, 5)
-            uint16_t coeff_g;    // DPP_HDR_LSI_L#_TM_COEF[COEFG] #(1, 3, 5)
-            uint16_t coeff_b;    // DPP_HDR_LSI_L#_TM_COEF[COEFB] #(1, 3, 5)
-            uint16_t rng_x_min;  // DPP_HDR_LSI_L#_TM_RNGX[MINX] #(1, 3, 5)
-            uint16_t rng_x_max;  // DPP_HDR_LSI_L#_TM_RNGX[MAXX] #(1, 3, 5)
-            uint16_t rng_y_min;  // DPP_HDR_LSI_L#_TM_RNGY[MINY] #(1, 3, 5)
-            uint16_t rng_y_max;  // DPP_HDR_LSI_L#_TM_RNGY[MAXY] #(1, 3, 5)
-        };
-
-        struct OetfConfigType {
-            using XContainer = uint32_t;
-            using YContainer = uint16_t;
-            static constexpr size_t kLutLen = 33;
-
-            TransferFunctionData<XContainer, YContainer, kLutLen> tf_data;
-        };
-
-     public:
-        /// Register data for the EOTF LUT in DPP.
-        using EotfData = DisplayStage<EotfConfigType>;
-
-        /// Register data for the gamut mapping (GM) matrix in DPP.
-        using GmData = DisplayStage<GmConfigType>;
-
-        /**
-         * @brief Register data for the DTM stage in DPP.
-         *
-         * Note that this data is only applicable to DPP in layers L1/L3/L5 and
-         * G2D layers. Other DPPs do not support DTM. DTM data will be provided
-         * for any layer whose DisplayScene::LayerColorData contains HDR dynamic
-         * metadata. It is the caller's (typically HWComposer) responsibility to
-         * validate layers and HW capabilities correctly, before calling this
-         * API.
-         */
-        using DtmData = DisplayStage<DtmConfigType>;
-
-        /// Register data for the OETF LUT in DPP.
-        using OetfData = DisplayStage<OetfConfigType>;
-
-        /// Get data for the EOTF LUT.
-        virtual const EotfData& EotfLut() const = 0;
-
-        /// Get data for the gamut mapping (GM) matrix.
-        virtual const GmData& Gm() const = 0;
-
-        /**
-         * @brief Get data for the DTM LUT. Only used for HDR10+, and only
-         * applicable to DPPs that support this functionality.
-         */
-        virtual const DtmData& Dtm() const = 0;
-
-        /// Get data for the OETF LUT.
-        virtual const OetfData& OetfLut() const = 0;
+    struct IDpp
+        : public IStageDataCollection<IDppData::IEotfData, IDppData::IGmData,
+                                      IDppData::IDtmData, IDppData::IOetfData> {
+        /// Get the solid color
+        virtual const Color SolidColor() const = 0;
 
         virtual ~IDpp() {}
     };
 
     /// Interface for accessing data for DQE stages.
-    struct IDqe {
-     private:
-        /// 32-bit DQE dither register, same definition as in uapi
-        struct DitherConfigType {
-            uint8_t en : 1;
-            uint8_t mode : 1;
-            uint8_t frame_con : 1;
-            uint8_t frame_offset : 2;
-            uint8_t table_sel_r : 1;
-            uint8_t table_sel_g : 1;
-            uint8_t table_sel_b : 1;
-            uint32_t reserved : 24;
-        };
-
-        struct DqeControlConfigType {
-            /// DQE force 10bpc mode
-            bool force_10bpc = false;
-
-            /// flag to use cgc_dither
-            bool cgc_dither_override = false;
-            /// CGC dither register value
-            union {
-                DitherConfigType cgc_dither_reg = {};
-                uint8_t cgc_dither; // only lowest 8 bit is used
+    struct IDqeData {
+       public:
+        struct IDqeControlData {
+           private:
+            /// 32-bit DQE dither register, same definition as in uapi
+            struct DitherConfigType {
+                uint8_t en : 1;
+                uint8_t mode : 1;
+                uint8_t frame_con : 1;
+                uint8_t frame_offset : 2;
+                uint8_t table_sel_r : 1;
+                uint8_t table_sel_g : 1;
+                uint8_t table_sel_b : 1;
+                uint32_t reserved : 24;
             };
 
-            /// flag to use disp_dither
-            bool disp_dither_override = false;
-            /// Display dither register value
-            union {
-                DitherConfigType disp_dither_reg = {};
-                uint8_t disp_dither; // only lowest 8 bit is used
+            struct DqeControlConfigType {
+                /// DQE force 10bpc mode
+                bool force_10bpc = false;
+
+                /// flag to use cgc_dither
+                bool cgc_dither_override = false;
+                /// CGC dither register value
+                union {
+                    DitherConfigType cgc_dither_reg = {};
+                    uint8_t cgc_dither;  // only lowest 8 bit is used
+                };
+
+                /// flag to use disp_dither
+                bool disp_dither_override = false;
+                /// Display dither register value
+                union {
+                    DitherConfigType disp_dither_reg = {};
+                    uint8_t disp_dither;  // only lowest 8 bit is used
+                };
             };
+
+           public:
+            /// DQE control data
+            using DqeControlData = DisplayStage<DqeControlConfigType>;
+
+            /// Get DQE control data
+            virtual const DqeControlData& DqeControl() const = 0;
+            virtual ~IDqeControlData() {}
         };
 
-        struct DqeMatrixConfigType {
-            using Container = uint16_t;
-            static constexpr size_t kDimensions = 3;
+        struct IGammaMatrixData {
+            /// Register data for the gamma and linear matrices in DQE.
+            using DqeMatrixData = DisplayStage<MatrixConfigType<uint16_t, 3>>;
 
-            struct MatrixData<Container, kDimensions> matrix_data;
+            /// Get data for the gamma-space matrix.
+            virtual const DqeMatrixData& GammaMatrix() const = 0;
+            virtual ~IGammaMatrixData() {}
         };
 
-        struct DegammaConfigType {
-            using Container = uint16_t;
-            static constexpr size_t kLutLen = 65;
+        struct IDegammaLutData {
+           private:
+            struct DegammaConfigType {
+                using Container = uint16_t;
+                static constexpr size_t kLutLen = 65;
 
-            std::array<Container, kLutLen> values;
+                std::array<Container, kLutLen> values;
+            };
+
+           public:
+            /// Register data for the degamma LUT in DQE.
+            using DegammaLutData = DisplayStage<DegammaConfigType>;
+
+            /// Get data for the 1D de-gamma LUT (EOTF).
+            virtual const DegammaLutData& DegammaLut() const = 0;
+            virtual ~IDegammaLutData() {}
         };
 
-        struct CgcConfigType {
-            using Container = uint32_t;
-            static constexpr size_t kChannelLutLen = 2457;
+        struct ILinearMatrixData {
+            /// Register data for the gamma and linear matrices in DQE.
+            using DqeMatrixData = DisplayStage<MatrixConfigType<uint16_t, 3>>;
 
-            /// DQE0_CGC_LUT_R_N{0-2456} (8 bit: 0~2047, 10 bit: 0~8191)
-            std::array<Container, kChannelLutLen> r_values{};
-            /// DQE0_CGC_LUT_G_N{0-2456} (8 bit: 0~2047, 10 bit: 0~8191)
-            std::array<Container, kChannelLutLen> g_values{};
-            /// DQE0_CGC_LUT_B_N{0-2456} (8 bit: 0~2047, 10 bit: 0~8191)
-            std::array<Container, kChannelLutLen> b_values{};
+            /// Get data for the linear-space matrix.
+            virtual const DqeMatrixData& LinearMatrix() const = 0;
+            virtual ~ILinearMatrixData() {}
         };
 
-        struct RegammaConfigType {
-            using Container = uint16_t;
-            static constexpr size_t kChannelLutLen = 65;
+        struct ICgcData {
+           private:
+            struct CgcConfigType {
+                using Container = uint32_t;
+                static constexpr size_t kChannelLutLen = 2457;
+                // nodes number at each dimension of this 3d lut
+                static constexpr size_t kVirtualChanelLen = 17;
 
-            /// REGAMMA LUT_R_{00-64} (8 bit: 0~1024, 10 bit: 0~4096)
-            std::array<Container, kChannelLutLen> r_values{};
-            /// REGAMMA LUT_G_{00-64} (8 bit: 0~1024, 10 bit: 0~4096)
-            std::array<Container, kChannelLutLen> g_values{};
-            /// REGAMMA LUT_B_{00-64} (8 bit: 0~1024, 10 bit: 0~4096)
-            std::array<Container, kChannelLutLen> b_values{};
+                /// DQE0_CGC_LUT_R_N{0-2456} (8 bit: 0~2047, 10 bit: 0~8191)
+                std::array<Container, kChannelLutLen> r_values{};
+                /// DQE0_CGC_LUT_G_N{0-2456} (8 bit: 0~2047, 10 bit: 0~8191)
+                std::array<Container, kChannelLutLen> g_values{};
+                /// DQE0_CGC_LUT_B_N{0-2456} (8 bit: 0~2047, 10 bit: 0~8191)
+                std::array<Container, kChannelLutLen> b_values{};
+            };
+
+           public:
+            /// Register data for CGC.
+            using CgcData = DisplayStage<CgcConfigType>;
+
+            /// Get data for the Color Gamut Conversion stage (3D LUT).
+            virtual const CgcData& Cgc() const = 0;
+            virtual ~ICgcData() {}
         };
 
-     public:
-        /// DQE control data
-        using DqeControlData = DisplayStage<DqeControlConfigType>;
+        struct IRegammaLutData {
+           private:
+            struct RegammaConfigType {
+                using Container = uint16_t;
+                static constexpr size_t kChannelLutLen = 65;
 
-        /// Register data for the gamma and linear matrices in DQE.
-        using DqeMatrixData = DisplayStage<DqeMatrixConfigType>;
+                /// REGAMMA LUT_R_{00-64} (8 bit: 0~1024, 10 bit: 0~4096)
+                std::array<Container, kChannelLutLen> r_values{};
+                /// REGAMMA LUT_G_{00-64} (8 bit: 0~1024, 10 bit: 0~4096)
+                std::array<Container, kChannelLutLen> g_values{};
+                /// REGAMMA LUT_B_{00-64} (8 bit: 0~1024, 10 bit: 0~4096)
+                std::array<Container, kChannelLutLen> b_values{};
+            };
 
-        /// Register data for the degamma LUT in DQE.
-        using DegammaLutData = DisplayStage<DegammaConfigType>;
+           public:
+            /// Register data for the regamma LUT.
+            using RegammaLutData = DisplayStage<RegammaConfigType>;
 
-        /// Register data for CGC.
-        using CgcData = DisplayStage<CgcConfigType>;
+            /// Get data for the 3x1D re-gamma LUTa (OETF).
+            virtual const RegammaLutData& RegammaLut() const = 0;
+            virtual ~IRegammaLutData() {}
+        };
+    };
 
-        /// Register data for the regamma LUT.
-        using RegammaLutData = DisplayStage<RegammaConfigType>;
-
-        /// Get DQE control data
-        virtual const DqeControlData& DqeControl() const = 0;
-
-        /// Get data for the gamma-space matrix.
-        virtual const DqeMatrixData& GammaMatrix() const = 0;
-
-        /// Get data for the 1D de-gamma LUT (EOTF).
-        virtual const DegammaLutData& DegammaLut() const = 0;
-
-        /// Get data for the linear-space matrix.
-        virtual const DqeMatrixData& LinearMatrix() const = 0;
-
-        /// Get data for the Color Gamut Conversion stage (3D LUT).
-        virtual const CgcData& Cgc() const = 0;
-
-        /// Get data for the 3x1D re-gamma LUTa (OETF).
-        virtual const RegammaLutData& RegammaLut() const = 0;
-
+    struct IDqe : public IStageDataCollection<
+                      IDqeData::IDqeControlData, IDqeData::IGammaMatrixData,
+                      IDqeData::IDegammaLutData, IDqeData::ILinearMatrixData,
+                      IDqeData::ICgcData, IDqeData::IRegammaLutData> {
         virtual ~IDqe() {}
     };
 
diff --git a/include/gs101/histogram/histogram.h b/include/gs101/histogram/histogram.h
deleted file mode 100644
index 07a1de1..0000000
--- a/include/gs101/histogram/histogram.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HISTOGRAM_H_
-#define HISTOGRAM_H_
-
-typedef enum {
-    HISTOGRAM_CONTROL_INVALID = 0,
-    HISTOGRAM_CONTROL_REQUEST = 1,
-    HISTOGRAM_CONTROL_CANCEL = 2,
-} hidl_histogram_control_t;
-
-namespace gs101 {
-
-class HistogramInfo {
-public:
-    enum Histogram_Type { HISTOGRAM_SAMPLING, HISTOGRAM_HIDL, HISTOGRAM_TYPE_NUM };
-    /// Histogram ROI information, same definition as in uapi
-    struct HistogramROI {
-        uint16_t start_x;
-        uint16_t start_y;
-        uint16_t hsize;
-        uint16_t vsize;
-    };
-    /// Histogram Weights information, same definition as in uapi
-    struct HistogramWeights {
-        uint16_t weight_r;
-        uint16_t weight_g;
-        uint16_t weight_b;
-    };
-
-    void setHistogramROI(uint16_t x, uint16_t y, uint16_t h, uint16_t v) {
-        mHistogramROI.start_x = x;
-        mHistogramROI.start_y = y;
-        mHistogramROI.hsize = h;
-        mHistogramROI.vsize = v;
-    };
-    const struct HistogramROI& getHistogramROI() { return mHistogramROI; }
-
-    void setHistogramWeights(uint16_t r, uint16_t g, uint16_t b) {
-        mHistogramWeights.weight_r = r;
-        mHistogramWeights.weight_g = g;
-        mHistogramWeights.weight_b = b;
-    };
-    const struct HistogramWeights& getHistogramWeights() { return mHistogramWeights; }
-
-    void setHistogramThreshold(uint32_t t) { mHistogramThreshold = t; }
-    uint32_t getHistogramThreshold() { return mHistogramThreshold; }
-
-    Histogram_Type getHistogramType() { return mHistogramType; }
-
-    HistogramInfo(Histogram_Type type) { mHistogramType = type; }
-    virtual ~HistogramInfo() {}
-
-private:
-    Histogram_Type mHistogramType = HISTOGRAM_TYPE_NUM;
-    struct HistogramROI mHistogramROI;
-    struct HistogramWeights mHistogramWeights;
-    uint32_t mHistogramThreshold = 0;
-};
-
-class SamplingHistogram : public HistogramInfo {
-public:
-    SamplingHistogram() : HistogramInfo(HISTOGRAM_SAMPLING) {}
-    virtual ~SamplingHistogram() {}
-};
-
-class HIDLHistogram : public HistogramInfo {
-public:
-    HIDLHistogram() : HistogramInfo(HISTOGRAM_HIDL) {}
-    virtual ~HIDLHistogram() {}
-
-    virtual void CallbackHistogram(void* bin) = 0;
-};
-
-} // namespace gs101
-
-#endif // HISTOGRAM_H_
diff --git a/include/histogram/HistogramInfo.h b/include/histogram/HistogramInfo.h
new file mode 100644
index 0000000..34eada3
--- /dev/null
+++ b/include/histogram/HistogramInfo.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HISTOGRAMINFO_H_
+#define HISTOGRAMINFO_H_
+#include <aidl/com/google/hardware/pixel/display/HistogramPos.h>
+#include <drm/samsung_drm.h>
+
+#include <mutex>
+
+using HistogramPos = ::aidl::com::google::hardware::pixel::display::HistogramPos;
+
+class HistogramInfo {
+public:
+    enum class HistogramType { HISTOGRAM_SAMPLING = 0, HISTOGRAM_HIDL, HISTOGRAM_TYPE_NUM };
+    void setHistogramROI(uint16_t x, uint16_t y, uint16_t h, uint16_t v) {
+        std::unique_lock<std::mutex> lk(mSetHistInfoMutex);
+        mHistogramROI.start_x = x;
+        mHistogramROI.start_y = y;
+        mHistogramROI.hsize = h;
+        mHistogramROI.vsize = v;
+    };
+    const struct histogram_roi& getHistogramROI() { return mHistogramROI; }
+
+    void setHistogramWeights(uint16_t r, uint16_t g, uint16_t b) {
+        std::unique_lock<std::mutex> lk(mSetHistInfoMutex);
+        mHistogramWeights.weight_r = r;
+        mHistogramWeights.weight_g = g;
+        mHistogramWeights.weight_b = b;
+    };
+    const struct histogram_weights& getHistogramWeights() { return mHistogramWeights; }
+
+    void setHistogramThreshold(uint32_t t) {
+        std::unique_lock<std::mutex> lk(mSetHistInfoMutex);
+        mHistogramThreshold = t;
+    }
+
+    uint32_t getHistogramThreshold() {
+        std::unique_lock<std::mutex> lk(mSetHistInfoMutex);
+        return mHistogramThreshold;
+    }
+
+    HistogramType getHistogramType() { return mHistogramType; }
+
+    HistogramInfo(HistogramType type) { mHistogramType = type; }
+    virtual ~HistogramInfo() {}
+    virtual void setHistogramPos(HistogramPos pos) = 0;
+    virtual void callbackHistogram(char16_t* bin) = 0;
+    std::mutex mSetHistInfoMutex;
+
+private:
+    HistogramType mHistogramType = HistogramType::HISTOGRAM_TYPE_NUM;
+    struct histogram_roi mHistogramROI;
+    struct histogram_weights mHistogramWeights;
+    uint32_t mHistogramThreshold = 0;
+};
+
+#endif // HISTOGRAM_H_
diff --git a/include/histogram/histogram.h b/include/histogram/histogram.h
new file mode 100644
index 0000000..7e7693d
--- /dev/null
+++ b/include/histogram/histogram.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HISTOGRAM_H_
+#define HISTOGRAM_H_
+
+#include <aidl/com/google/hardware/pixel/display/HistogramPos.h>
+
+#include "histogram/HistogramInfo.h"
+#include "histogram/histogram_control.h"
+using HistogramPos = ::aidl::com::google::hardware::pixel::display::HistogramPos;
+
+class IDLHistogram : public HistogramInfo {
+public:
+    IDLHistogram() : HistogramInfo(HistogramType::HISTOGRAM_HIDL) {}
+    virtual ~IDLHistogram() {}
+    virtual void setHistogramPos(HistogramPos pos) {}
+};
+
+#endif // HISTOGRAM_H_
diff --git a/include/histogram/histogram_control.h b/include/histogram/histogram_control.h
new file mode 100644
index 0000000..ef2abae
--- /dev/null
+++ b/include/histogram/histogram_control.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HISTOGRAMCONTROL_H_
+#define HISTOGRAMCONTROL_H_
+
+enum class hidl_histogram_control_t {
+    HISTOGRAM_CONTROL_INVALID = 0,
+    HISTOGRAM_CONTROL_REQUEST = 1,
+    HISTOGRAM_CONTROL_CANCEL = 2,
+};
+
+#endif // HISTOGRAMCONTROL_H_
diff --git a/libcap/acrylic_capability.h b/libcap/acrylic_capability.h
new file mode 100644
index 0000000..3cc1715
--- /dev/null
+++ b/libcap/acrylic_capability.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstring>
+
+#include <log/log.h>
+
+#include <exynos_format.h> // hardware/smasung_slsi/exynos/include
+#include <mali_gralloc_formats.h>
+
+static uint32_t all_fimg2d_gs101_formats[] = {
+    HAL_PIXEL_FORMAT_RGBA_8888,
+    HAL_PIXEL_FORMAT_BGRA_8888,
+    HAL_PIXEL_FORMAT_RGBA_1010102,
+    HAL_PIXEL_FORMAT_RGBX_8888,
+    HAL_PIXEL_FORMAT_RGB_888,
+    HAL_PIXEL_FORMAT_RGB_565,
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P,
+    HAL_PIXEL_FORMAT_YCrCb_420_SP,                  // NV21 (YVU420 semi-planar)
+    HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M,         // NV21 on multi-buffer
+    HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL,    // NV21 on multi-buffer
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP,           // NV12 (YUV420 semi-planar)
+    HAL_PIXEL_FORMAT_GOOGLE_NV12_SP,                // NV12 (YUV420 semi-planar)
+    MALI_GRALLOC_FORMAT_INTERNAL_YUV420_8BIT_I,     // NV12 AFBC
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN,          // NV12 with MFC alignment constraints
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M,
+    // NV12M with MFC alignment constraints on multi-buffer
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV,
+    // NV12M with MFC alignment constraints on multi-buffer
+    HAL_PIXEL_FORMAT_YCbCr_422_SP,                  // YUV422 2P (YUV422 semi-planar)
+    HAL_PIXEL_FORMAT_YCBCR_P010,
+    HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B,
+    MALI_GRALLOC_FORMAT_INTERNAL_YUV420_10BIT_I,
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_SPN,
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M,
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC,
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC,
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC,
+    HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC,
+    HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC,
+    HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC,
+};
+
+static int all_hwc_gs101_dataspaces[] = {
+    HAL_DATASPACE_STANDARD_BT709,
+    HAL_DATASPACE_STANDARD_BT709 | HAL_DATASPACE_RANGE_FULL,
+    HAL_DATASPACE_STANDARD_BT709 | HAL_DATASPACE_RANGE_LIMITED,
+    HAL_DATASPACE_STANDARD_BT2020,
+    HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_RANGE_FULL,
+    HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_RANGE_LIMITED,
+    HAL_DATASPACE_STANDARD_BT601_625,
+    HAL_DATASPACE_STANDARD_BT601_625 | HAL_DATASPACE_RANGE_FULL,
+    HAL_DATASPACE_STANDARD_BT601_625 | HAL_DATASPACE_RANGE_LIMITED,
+    HAL_DATASPACE_STANDARD_BT601_525,
+    HAL_DATASPACE_STANDARD_BT601_525 | HAL_DATASPACE_RANGE_FULL,
+    HAL_DATASPACE_STANDARD_BT601_525 | HAL_DATASPACE_RANGE_LIMITED,
+    HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED,
+    HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED | HAL_DATASPACE_RANGE_FULL,
+    HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED | HAL_DATASPACE_RANGE_LIMITED,
+    HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED,
+    HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED | HAL_DATASPACE_RANGE_FULL,
+    HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED | HAL_DATASPACE_RANGE_LIMITED,
+    HAL_DATASPACE_STANDARD_DCI_P3,
+    HAL_DATASPACE_STANDARD_DCI_P3 | HAL_DATASPACE_RANGE_FULL,
+    HAL_DATASPACE_STANDARD_DCI_P3 | HAL_DATASPACE_RANGE_LIMITED,
+    HAL_DATASPACE_STANDARD_FILM,
+    HAL_DATASPACE_STANDARD_FILM | HAL_DATASPACE_RANGE_FULL,
+    HAL_DATASPACE_STANDARD_FILM | HAL_DATASPACE_RANGE_LIMITED,
+    // 0 should be treated as BT709 Limited range
+    0,
+    HAL_DATASPACE_RANGE_FULL,
+    HAL_DATASPACE_RANGE_LIMITED,
+    // Deprecated legacy dataspace definitions
+    HAL_DATASPACE_SRGB,
+    HAL_DATASPACE_JFIF,
+    HAL_DATASPACE_BT601_525,
+    HAL_DATASPACE_BT601_625,
+    HAL_DATASPACE_BT709,
+};
+
+const static stHW2DCapability __capability_g2d_gs101 = {
+    .max_upsampling_num = {8, 8},
+    .max_downsampling_factor = {4, 4},
+    .max_upsizing_num = {8, 8},
+    .max_downsizing_factor = {4, 4},
+    .min_src_dimension = {1, 1},
+    .max_src_dimension = {8192, 8192},
+    .min_dst_dimension = {1, 1},
+    .max_dst_dimension = {8192, 8192},
+    .min_pix_align = {1, 1},
+    .rescaling_count = 0,
+    .compositing_mode = HW2DCapability::BLEND_NONE | HW2DCapability::BLEND_SRC_COPY
+	                 | HW2DCapability::BLEND_SRC_OVER,
+    .transform_type = HW2DCapability::TRANSFORM_ALL,
+    .auxiliary_feature = HW2DCapability::FEATURE_PLANE_ALPHA | HW2DCapability::FEATURE_UORDER_WRITE
+                         | HW2DCapability::FEATURE_AFBC_ENCODE | HW2DCapability::FEATURE_AFBC_DECODE
+                         | HW2DCapability::FEATURE_SOLIDCOLOR,
+    .num_formats = ARRSIZE(all_fimg2d_gs101_formats),
+    .num_dataspaces = ARRSIZE(all_hwc_gs101_dataspaces),
+    .max_layers = 4,
+    .pixformats = all_fimg2d_gs101_formats,
+    .dataspaces = all_hwc_gs101_dataspaces,
+    .base_align = 1,
+};
+
+static const HW2DCapability capability_fimg2d_gs101(__capability_g2d_gs101);
+
+inline Acrylic *createAcrylicCompositorG2D(const char *spec)
+{
+    Acrylic *compositor = nullptr;
+
+    if (strcmp(spec, "fimg2d_gs101") == 0) {
+        compositor = new AcrylicCompositorG2D(capability_fimg2d_gs101, /*halfmt_to_g2dfmt*/ true);
+    }
+    return compositor;
+}
diff --git a/libhwc2.1/Android.mk b/libhwc2.1/Android.mk
index b29122c..de43986 100644
--- a/libhwc2.1/Android.mk
+++ b/libhwc2.1/Android.mk
@@ -13,6 +13,7 @@
 # limitations under the License.
 
 LOCAL_SRC_FILES += \
+	../../$(TARGET_BOARD_PLATFORM)/libhwc2.1/libcolormanager/DisplayColorModule.cpp \
 	../../$(TARGET_BOARD_PLATFORM)/libhwc2.1/libdevice/ExynosDeviceModule.cpp \
 	../../$(TARGET_BOARD_PLATFORM)/libhwc2.1/libmaindisplay/ExynosPrimaryDisplayModule.cpp \
 	../../$(TARGET_BOARD_PLATFORM)/libhwc2.1/libresource/ExynosMPPModule.cpp \
diff --git a/libhwc2.1/ExynosHWCModule.h b/libhwc2.1/ExynosHWCModule.h
index d879edb..a20c398 100644
--- a/libhwc2.1/ExynosHWCModule.h
+++ b/libhwc2.1/ExynosHWCModule.h
@@ -20,7 +20,6 @@
 #include <array>
 
 #include "ExynosHWC.h"
-#include "DeconHeader.h"
 
 #define G2D_MAX_SRC_NUM 3
 
@@ -33,8 +32,6 @@
 #define BRIGHTNESS_SYSFS_NODE "/sys/class/backlight/panel%d-backlight/brightness"
 #define MAX_BRIGHTNESS_SYSFS_NODE "/sys/class/backlight/panel%d-backlight/max_brightness"
 
-#define EARLY_WAKUP_NODE_0_BASE "/sys/devices/platform/1c300000.drmdecon/early_wakeup"
-
 #define IDMA(x) static_cast<decon_idma_type>(x)
 
 #define MPP_G2D_CAPACITY    3.5
@@ -43,31 +40,6 @@
     HWC_DISPLAY_NONE_BIT = 0
 };
 
-/*
- * pre_assign_info: all display_descriptors that want to reserve
- */
-struct exynos_mpp_t {
-    int physicalType;
-    int logicalType;
-    char name[16];
-    uint32_t physical_index;
-    uint32_t logical_index;
-    uint32_t pre_assign_info;
-};
-
-const dpp_channel_map_t IDMA_CHANNEL_MAP[] = {
-    /* GF physical index is switched to change assign order */
-    /* DECON_IDMA is not used */
-    {MPP_DPP_GF,     0, IDMA(0),   IDMA(0)},
-    {MPP_DPP_VGRFS,  0, IDMA(1),   IDMA(1)},
-    {MPP_DPP_GF,     1, IDMA(2),   IDMA(2)},
-    {MPP_DPP_VGRFS,  1, IDMA(3),   IDMA(3)},
-    {MPP_DPP_GF,     2, IDMA(4),   IDMA(4)},
-    {MPP_DPP_VGRFS,  2, IDMA(5),   IDMA(5)},
-    {MPP_P_TYPE_MAX, 0, IDMA(6),   IDMA(6)}, // not idma but..
-    {static_cast<mpp_phycal_type_t>(MAX_DECON_DMA_TYPE), 0, MAX_DECON_DMA_TYPE, IDMA(7)}
-};
-
 #define MAX_NAME_SIZE   32
 struct exynos_display_t {
     uint32_t type;
@@ -126,23 +98,44 @@
     HWC_DISPLAY_SECONDARY_BIT = 1 << (SECOND_DISPLAY_START_BIT + HWC_DISPLAY_PRIMARY),
 };
 
-const exynos_mpp_t AVAILABLE_OTF_MPP_UNITS[] = {
-    {MPP_DPP_GF, MPP_LOGICAL_DPP_GF, "DPP_GF0", 0, 0, HWC_DISPLAY_PRIMARY_BIT},
-    {MPP_DPP_GF, MPP_LOGICAL_DPP_GF, "DPP_GF1", 1, 0, HWC_DISPLAY_PRIMARY_BIT},
-    {MPP_DPP_GF, MPP_LOGICAL_DPP_GF, "DPP_GF2", 2, 0, HWC_DISPLAY_SECONDARY_BIT},
-    {MPP_DPP_VGRFS, MPP_LOGICAL_DPP_VGRFS, "DPP_VGRFS0", 0, 0, HWC_DISPLAY_PRIMARY_BIT},
-    {MPP_DPP_VGRFS, MPP_LOGICAL_DPP_VGRFS, "DPP_VGRFS1", 1, 0, HWC_DISPLAY_PRIMARY_BIT},
-    {MPP_DPP_VGRFS, MPP_LOGICAL_DPP_VGRFS, "DPP_VGRFS2", 2, 0, HWC_DISPLAY_PRIMARY_BIT}
+namespace gs101 {
+
+static const char *early_wakeup_node_0_base =
+    "/sys/devices/platform/1c300000.drmdecon/early_wakeup";
+
+static const dpp_channel_map_t idma_channel_map[] = {
+    /* GF physical index is switched to change assign order */
+    /* DECON_IDMA is not used */
+    {MPP_DPP_GF,     0, IDMA(0),   IDMA(0)},
+    {MPP_DPP_VGRFS,  0, IDMA(1),   IDMA(1)},
+    {MPP_DPP_GF,     1, IDMA(2),   IDMA(2)},
+    {MPP_DPP_VGRFS,  1, IDMA(3),   IDMA(3)},
+    {MPP_DPP_GF,     2, IDMA(4),   IDMA(4)},
+    {MPP_DPP_VGRFS,  2, IDMA(5),   IDMA(5)},
+    {MPP_P_TYPE_MAX, 0, IDMA(6),   IDMA(6)}, // not idma but..
+    {static_cast<mpp_phycal_type_t>(MAX_DECON_DMA_TYPE), 0, MAX_DECON_DMA_TYPE, IDMA(7)}
 };
 
+static const exynos_mpp_t available_otf_mpp_units[] = {
+    {MPP_DPP_GF, MPP_LOGICAL_DPP_GF, "DPP_GF0", 0, 0, HWC_DISPLAY_PRIMARY_BIT, 0, 0},
+    {MPP_DPP_GF, MPP_LOGICAL_DPP_GF, "DPP_GF1", 1, 0, HWC_DISPLAY_PRIMARY_BIT, 0, 0},
+    {MPP_DPP_GF, MPP_LOGICAL_DPP_GF, "DPP_GF2", 2, 0, HWC_DISPLAY_SECONDARY_BIT, 0, 0},
+    {MPP_DPP_VGRFS, MPP_LOGICAL_DPP_VGRFS, "DPP_VGRFS0", 0, 0, HWC_DISPLAY_PRIMARY_BIT, 0, 0},
+    {MPP_DPP_VGRFS, MPP_LOGICAL_DPP_VGRFS, "DPP_VGRFS1", 1, 0, HWC_DISPLAY_PRIMARY_BIT, 0, 0},
+    {MPP_DPP_VGRFS, MPP_LOGICAL_DPP_VGRFS, "DPP_VGRFS2", 2, 0, HWC_DISPLAY_PRIMARY_BIT, 0, 0}
+};
+
+} // namespace gs101
+
+
 const exynos_mpp_t AVAILABLE_M2M_MPP_UNITS[] = {
 #ifndef DISABLE_M2M_MPPS
-    {MPP_G2D, MPP_LOGICAL_G2D_YUV, "G2D0-YUV_PRI", 0, 0, HWC_DISPLAY_PRIMARY_BIT},
-    {MPP_G2D, MPP_LOGICAL_G2D_YUV, "G2D0-YUV_PRI", 0, 1, HWC_DISPLAY_PRIMARY_BIT},
-    {MPP_G2D, MPP_LOGICAL_G2D_YUV, "G2D0-YUV_EXT", 0, 2, HWC_DISPLAY_EXTERNAL_BIT},
-    {MPP_G2D, MPP_LOGICAL_G2D_RGB, "G2D0-RGB_PRI", 0, 3, HWC_DISPLAY_PRIMARY_BIT},
-    {MPP_G2D, MPP_LOGICAL_G2D_RGB, "G2D0-RGB_EXT", 0, 4, HWC_DISPLAY_EXTERNAL_BIT},
-    {MPP_G2D, MPP_LOGICAL_G2D_COMBO, "G2D0-COMBO_VIR", 0, 5, HWC_DISPLAY_VIRTUAL_BIT}
+    {MPP_G2D, MPP_LOGICAL_G2D_YUV, "G2D0-YUV_PRI", 0, 0, HWC_DISPLAY_PRIMARY_BIT, 0, 0},
+    {MPP_G2D, MPP_LOGICAL_G2D_YUV, "G2D0-YUV_PRI", 0, 1, HWC_DISPLAY_PRIMARY_BIT, 0, 0},
+    {MPP_G2D, MPP_LOGICAL_G2D_YUV, "G2D0-YUV_EXT", 0, 2, HWC_DISPLAY_EXTERNAL_BIT, 0, 0},
+    {MPP_G2D, MPP_LOGICAL_G2D_RGB, "G2D0-RGB_PRI", 0, 3, HWC_DISPLAY_PRIMARY_BIT, 0, 0},
+    {MPP_G2D, MPP_LOGICAL_G2D_RGB, "G2D0-RGB_EXT", 0, 4, HWC_DISPLAY_EXTERNAL_BIT, 0, 0},
+    {MPP_G2D, MPP_LOGICAL_G2D_COMBO, "G2D0-COMBO_VIR", 0, 5, HWC_DISPLAY_VIRTUAL_BIT, 0, 0}
 #endif
 };
 
diff --git a/libhwc2.1/ExynosResourceRestriction.h b/libhwc2.1/ExynosResourceRestriction.h
index bcb15ef..de896d9 100644
--- a/libhwc2.1/ExynosResourceRestriction.h
+++ b/libhwc2.1/ExynosResourceRestriction.h
@@ -24,11 +24,10 @@
  * ****************************************************************/
 #define RESTRICTION_NONE 0
 
-#define USE_MODULE_ATTR
+namespace gs101 {
 
 /* Basic supported features */
-static feature_support_t feature_table[] =
-{
+static feature_support_t feature_table[] = {
     {MPP_DPP_GF,
         MPP_ATTR_AFBC | MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE |
         MPP_ATTR_FLIP_H | MPP_ATTR_FLIP_V |
@@ -90,8 +89,7 @@
 };
 *************************************************************************************/
 
-const restriction_key_t restriction_format_table[] =
-{
+static const restriction_key_t restriction_format_table[] = {
     {MPP_DPP_GF, NODE_NONE, HAL_PIXEL_FORMAT_RGB_565, 0},
     {MPP_DPP_GF, NODE_NONE, HAL_PIXEL_FORMAT_RGBA_8888, 0},
     {MPP_DPP_GF, NODE_NONE, HAL_PIXEL_FORMAT_RGBX_8888, 0},
@@ -158,6 +156,7 @@
     {MPP_DPP_VGRFS, NODE_NONE, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B, 0},
     {MPP_DPP_VGRFS, NODE_NONE, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B, 0},
     {MPP_DPP_VGRFS, NODE_NONE, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M, 0},
+    {MPP_DPP_VGRFS, NODE_NONE, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_SPN, 0},
     {MPP_DPP_VGRFS, NODE_NONE, HAL_PIXEL_FORMAT_YCBCR_P010, 0},
     {MPP_DPP_VGRFS, NODE_NONE, HAL_PIXEL_FORMAT_GOOGLE_NV12_SP, 0},
     {MPP_DPP_VGRFS, NODE_NONE, HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B, 0},
@@ -176,12 +175,15 @@
     {MPP_G2D, NODE_NONE, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B, 0},
     {MPP_G2D, NODE_NONE, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B, 0},
     {MPP_G2D, NODE_NONE, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M, 0},
+    {MPP_G2D, NODE_NONE, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_SPN, 0},
     {MPP_G2D, NODE_NONE, HAL_PIXEL_FORMAT_YCrCb_420_SP, 0},
     {MPP_G2D, NODE_NONE, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_TILED, 0},
     {MPP_G2D, NODE_NONE, HAL_PIXEL_FORMAT_GOOGLE_NV12_SP, 0},
     {MPP_G2D, NODE_NONE, HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B, 0},
 };
 
+} // namespace gs101
+
 const restriction_size_element restriction_size_table_rgb[] =
         {{{MPP_DPP_GF, NODE_SRC, HAL_PIXEL_FORMAT_NONE, 0},
           {{1, 1, 65535, 8191, 16, 16, 1, 1, 4096, 4096, 16, 16, 1, 1, 1, 1}}},
diff --git a/libhwc2.1/libcolormanager/DisplayColorModule.cpp b/libhwc2.1/libcolormanager/DisplayColorModule.cpp
new file mode 100644
index 0000000..496caf6
--- /dev/null
+++ b/libhwc2.1/libcolormanager/DisplayColorModule.cpp
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <drm/samsung_drm.h>
+#include "DisplayColorModule.h"
+
+using namespace android;
+namespace gs {
+
+template <typename T, typename M>
+int32_t convertDqeMatrixDataToDrmMatrix(T &colorMatrix, M &mat, uint32_t dimension) {
+    if (colorMatrix.coeffs.size() != (dimension * dimension)) {
+        ALOGE("Invalid coeff size(%zu)",
+                colorMatrix.coeffs.size());
+        return -EINVAL;
+    }
+    if (colorMatrix.offsets.size() != dimension) {
+        ALOGE("Invalid offset size(%zu)",
+                colorMatrix.offsets.size());
+        return -EINVAL;
+    }
+    for (uint32_t i = 0; i < (dimension * dimension); i++) {
+        mat.coeffs[i] = colorMatrix.coeffs[i];
+    }
+
+    for (uint32_t i = 0; i < dimension; i++) {
+        mat.offsets[i] = colorMatrix.offsets[i];
+    }
+    return NO_ERROR;
+}
+
+int32_t ColorDrmBlobFactory::eotf(const GsInterfaceType::IDpp::EotfData::ConfigType *config,
+                                  DrmDevice *drm, uint32_t &blobId) {
+    struct hdr_eotf_lut eotfLut;
+
+    if (config == nullptr) {
+        ALOGE("no dpp eotf config");
+        return -EINVAL;
+    }
+
+    if ((config->tf_data.posx.size() != DRM_SAMSUNG_HDR_EOTF_LUT_LEN) ||
+        (config->tf_data.posy.size() != DRM_SAMSUNG_HDR_EOTF_LUT_LEN)) {
+        ALOGE("%s: eotf pos size (%zu, %zu)", __func__, config->tf_data.posx.size(),
+              config->tf_data.posy.size());
+        return -EINVAL;
+    }
+
+    for (uint32_t i = 0; i < DRM_SAMSUNG_HDR_EOTF_LUT_LEN; i++) {
+        eotfLut.posx[i] = config->tf_data.posx[i];
+        eotfLut.posy[i] = config->tf_data.posy[i];
+    }
+    int ret = drm->CreatePropertyBlob(&eotfLut, sizeof(eotfLut), &blobId);
+    if (ret) {
+        ALOGE("Failed to create eotf lut blob %d", ret);
+        return ret;
+    }
+    return NO_ERROR;
+}
+
+int32_t ColorDrmBlobFactory::gm(const GsInterfaceType::IDpp::GmData::ConfigType *config,
+                                DrmDevice *drm, uint32_t &blobId) {
+    int ret = 0;
+    struct hdr_gm_data gmMatrix;
+
+    if (config == nullptr) {
+        ALOGE("no dpp GM config");
+        return -EINVAL;
+    }
+
+    if ((ret = convertDqeMatrixDataToDrmMatrix(config->matrix_data, gmMatrix,
+                                            DRM_SAMSUNG_HDR_GM_DIMENS)) != NO_ERROR) {
+        ALOGE("Failed to convert gm matrix");
+        return ret;
+    }
+    ret = drm->CreatePropertyBlob(&gmMatrix, sizeof(gmMatrix), &blobId);
+    if (ret) {
+        ALOGE("Failed to create gm matrix blob %d", ret);
+        return ret;
+    }
+    return NO_ERROR;
+}
+
+int32_t ColorDrmBlobFactory::dtm(const GsInterfaceType::IDpp::DtmData::ConfigType *config,
+                                 DrmDevice *drm, uint32_t &blobId) {
+    struct hdr_tm_data tmData;
+
+    if (config == nullptr) {
+        ALOGE("no dpp DTM config");
+        return -EINVAL;
+    }
+
+    if ((config->tf_data.posx.size() != DRM_SAMSUNG_HDR_TM_LUT_LEN) ||
+        (config->tf_data.posy.size() != DRM_SAMSUNG_HDR_TM_LUT_LEN)) {
+        ALOGE("%s: dtm pos size (%zu, %zu)", __func__, config->tf_data.posx.size(),
+              config->tf_data.posy.size());
+        return -EINVAL;
+    }
+
+    for (uint32_t i = 0; i < DRM_SAMSUNG_HDR_TM_LUT_LEN; i++) {
+        tmData.posx[i] = config->tf_data.posx[i];
+        tmData.posy[i] = config->tf_data.posy[i];
+    }
+
+    tmData.coeff_r = config->coeff_r;
+    tmData.coeff_g = config->coeff_g;
+    tmData.coeff_b = config->coeff_b;
+    tmData.rng_x_min = config->rng_x_min;
+    tmData.rng_x_max = config->rng_x_max;
+    tmData.rng_y_min = config->rng_y_min;
+    tmData.rng_y_max = config->rng_y_max;
+
+    int ret = drm->CreatePropertyBlob(&tmData, sizeof(tmData), &blobId);
+    if (ret) {
+        ALOGE("Failed to create tmData blob %d", ret);
+        return ret;
+    }
+
+    return NO_ERROR;
+}
+
+int32_t ColorDrmBlobFactory::oetf(const GsInterfaceType::IDpp::OetfData::ConfigType *config,
+                                  DrmDevice *drm, uint32_t &blobId) {
+    struct hdr_oetf_lut oetfLut;
+
+    if (config == nullptr) {
+        ALOGE("no dpp OETF config");
+        return -EINVAL;
+    }
+
+    if ((config->tf_data.posx.size() != DRM_SAMSUNG_HDR_OETF_LUT_LEN) ||
+        (config->tf_data.posy.size() != DRM_SAMSUNG_HDR_OETF_LUT_LEN)) {
+        ALOGE("%s: oetf pos size (%zu, %zu)", __func__, config->tf_data.posx.size(),
+              config->tf_data.posy.size());
+        return -EINVAL;
+    }
+
+    for (uint32_t i = 0; i < DRM_SAMSUNG_HDR_OETF_LUT_LEN; i++) {
+        oetfLut.posx[i] = config->tf_data.posx[i];
+        oetfLut.posy[i] = config->tf_data.posy[i];
+    }
+    int ret = drm->CreatePropertyBlob(&oetfLut, sizeof(oetfLut), &blobId);
+    if (ret) {
+        ALOGE("Failed to create oetf lut blob %d", ret);
+        return ret;
+    }
+    return NO_ERROR;
+}
+
+int32_t ColorDrmBlobFactory::gammaMatrix(
+        const GsInterfaceType::IDqe::DqeMatrixData::ConfigType *config, DrmDevice *drm,
+        uint32_t &blobId) {
+    int ret = 0;
+    struct exynos_matrix gammaMatrix;
+    if ((ret = convertDqeMatrixDataToDrmMatrix(config->matrix_data, gammaMatrix,
+                                            DRM_SAMSUNG_MATRIX_DIMENS)) != NO_ERROR) {
+        ALOGE("Failed to convert gamma matrix");
+        return ret;
+    }
+    ret = drm->CreatePropertyBlob(&gammaMatrix, sizeof(gammaMatrix), &blobId);
+    if (ret) {
+        ALOGE("Failed to create gamma matrix blob %d", ret);
+        return ret;
+    }
+
+    return NO_ERROR;
+}
+
+int32_t ColorDrmBlobFactory::degamma(const uint64_t drmLutSize,
+        const GsInterfaceType::IDqe::DegammaLutData::ConfigType *config, DrmDevice *drm,
+        uint32_t &blobId) {
+    if (config == nullptr) {
+        ALOGE("no degamma config");
+        return -EINVAL;
+    }
+    using ConfigType = typename GsInterfaceType::IDqe::DegammaLutData::ConfigType;
+    if (drmLutSize != ConfigType::kLutLen) {
+        ALOGE("degamma lut size mismatch");
+        return -EINVAL;
+    }
+
+    struct drm_color_lut colorLut[ConfigType::kLutLen];
+    for (uint32_t i = 0; i < ConfigType::kLutLen; i++) {
+        colorLut[i].red = config->values[i];
+    }
+    int ret = drm->CreatePropertyBlob(colorLut, sizeof(colorLut), &blobId);
+    if (ret) {
+        ALOGE("Failed to create degamma lut blob %d", ret);
+        return ret;
+    }
+    return NO_ERROR;
+}
+
+int32_t ColorDrmBlobFactory::linearMatrix(
+        const GsInterfaceType::IDqe::DqeMatrixData::ConfigType *config, DrmDevice *drm,
+        uint32_t &blobId) {
+    int ret = 0;
+    struct exynos_matrix linear_matrix;
+    if ((ret = convertDqeMatrixDataToDrmMatrix(config->matrix_data, linear_matrix,
+                                            DRM_SAMSUNG_MATRIX_DIMENS)) != NO_ERROR) {
+        ALOGE("Failed to convert linear matrix");
+        return ret;
+    }
+    ret = drm->CreatePropertyBlob(&linear_matrix, sizeof(linear_matrix), &blobId);
+    if (ret) {
+        ALOGE("Failed to create linear matrix blob %d", ret);
+        return ret;
+    }
+
+    return NO_ERROR;
+}
+
+int32_t ColorDrmBlobFactory::cgc(const GsInterfaceType::IDqe::CgcData::ConfigType *config,
+                                 DrmDevice *drm, uint32_t &blobId) {
+    struct cgc_lut cgc;
+    if (config == nullptr) {
+        ALOGE("no CGC config");
+        return -EINVAL;
+    }
+
+    if ((config->r_values.size() != DRM_SAMSUNG_CGC_LUT_REG_CNT) ||
+        (config->g_values.size() != DRM_SAMSUNG_CGC_LUT_REG_CNT) ||
+        (config->b_values.size() != DRM_SAMSUNG_CGC_LUT_REG_CNT)) {
+        ALOGE("CGC data size is not same (r: %zu, g: %zu: b: %zu)", config->r_values.size(),
+              config->g_values.size(), config->b_values.size());
+        return -EINVAL;
+    }
+
+    for (uint32_t i = 0; i < DRM_SAMSUNG_CGC_LUT_REG_CNT; i++) {
+        cgc.r_values[i] = config->r_values[i];
+        cgc.g_values[i] = config->g_values[i];
+        cgc.b_values[i] = config->b_values[i];
+    }
+    int ret = drm->CreatePropertyBlob(&cgc, sizeof(cgc_lut), &blobId);
+    if (ret) {
+        ALOGE("Failed to create cgc blob %d", ret);
+        return ret;
+    }
+    return NO_ERROR;
+}
+
+int32_t ColorDrmBlobFactory::cgcDither(
+        const GsInterfaceType::IDqe::DqeControlData::ConfigType *config, DrmDevice *drm,
+        uint32_t &blobId) {
+    int ret = 0;
+    if (config->cgc_dither_override == false) {
+        blobId = 0;
+        return ret;
+    }
+
+    ret = drm->CreatePropertyBlob((void *)&config->cgc_dither_reg, sizeof(config->cgc_dither_reg),
+                                  &blobId);
+    if (ret) {
+        ALOGE("Failed to create disp dither blob %d", ret);
+        return ret;
+    }
+    return NO_ERROR;
+}
+
+int32_t ColorDrmBlobFactory::regamma(
+        const uint64_t drmLutSize,
+        const GsInterfaceType::IDqe::RegammaLutData::ConfigType *config, DrmDevice *drm,
+        uint32_t &blobId) {
+    if (config == nullptr) {
+        ALOGE("no regamma config");
+        return -EINVAL;
+    }
+
+    using ConfigType = typename GsInterfaceType::IDqe::RegammaLutData::ConfigType;
+    if (drmLutSize != ConfigType::kChannelLutLen) {
+        ALOGE("gamma lut size mismatch");
+        return -EINVAL;
+    }
+
+    struct drm_color_lut colorLut[ConfigType::kChannelLutLen];
+    for (uint32_t i = 0; i < ConfigType::kChannelLutLen; i++) {
+        colorLut[i].red = config->r_values[i];
+        colorLut[i].green = config->g_values[i];
+        colorLut[i].blue = config->b_values[i];
+    }
+    int ret = drm->CreatePropertyBlob(colorLut, sizeof(colorLut), &blobId);
+    if (ret) {
+        ALOGE("Failed to create gamma lut blob %d", ret);
+        return ret;
+    }
+    return NO_ERROR;
+}
+
+int32_t ColorDrmBlobFactory::displayDither(
+        const GsInterfaceType::IDqe::DqeControlData::ConfigType *config, DrmDevice *drm,
+        uint32_t &blobId) {
+    int ret = 0;
+    if (config->disp_dither_override == false) {
+        blobId = 0;
+        return ret;
+    }
+
+    ret = drm->CreatePropertyBlob((void *)&config->disp_dither_reg, sizeof(config->disp_dither_reg),
+                                  &blobId);
+    if (ret) {
+        ALOGE("Failed to create disp dither blob %d", ret);
+        return ret;
+    }
+
+    return NO_ERROR;
+}
+
+} // namespace gs
diff --git a/libhwc2.1/libcolormanager/DisplayColorModule.h b/libhwc2.1/libcolormanager/DisplayColorModule.h
new file mode 100644
index 0000000..f59009d
--- /dev/null
+++ b/libhwc2.1/libcolormanager/DisplayColorModule.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gs101/displaycolor/displaycolor_gs101.h>
+#include "DisplayColorLoader.h"
+#include "drmdevice.h"
+
+namespace gs {
+
+static constexpr char kGsEntry[] = "GetDisplayColorGS101";
+class ColorDrmBlobFactory {
+ public:
+     using GsInterfaceType = displaycolor::IDisplayColorGS101;
+     using DcLoaderType = DisplayColorLoader<GsInterfaceType, kGsEntry>;
+
+     static int32_t eotf(const GsInterfaceType::IDpp::EotfData::ConfigType *config,
+                         android::DrmDevice *drm, uint32_t &blobId);
+     static int32_t gm(const GsInterfaceType::IDpp::GmData::ConfigType *config,
+                       android::DrmDevice *drm, uint32_t &blobId);
+     static int32_t dtm(const GsInterfaceType::IDpp::DtmData::ConfigType *config,
+                        android::DrmDevice *drm, uint32_t &blobId);
+     static int32_t oetf(const GsInterfaceType::IDpp::OetfData::ConfigType *config,
+                         android::DrmDevice *drm, uint32_t &blobId);
+     static int32_t gammaMatrix(const GsInterfaceType::IDqe::DqeMatrixData::ConfigType *config,
+                                android::DrmDevice *drm, uint32_t &blobId);
+     static int32_t degamma(const uint64_t drmLutSize,
+                            const GsInterfaceType::IDqe::DegammaLutData::ConfigType *config,
+                            android::DrmDevice *drm, uint32_t &blobId);
+     static int32_t linearMatrix(const GsInterfaceType::IDqe::DqeMatrixData::ConfigType *config,
+                                 android::DrmDevice *drm, uint32_t &blobId);
+     static int32_t cgc(const GsInterfaceType::IDqe::CgcData::ConfigType *config,
+                        android::DrmDevice *drm, uint32_t &blobId);
+     static int32_t cgcDither(const GsInterfaceType::IDqe::DqeControlData::ConfigType *config,
+                              android::DrmDevice *drm, uint32_t &blobId);
+     static int32_t regamma(const uint64_t drmLutSize,
+                            const GsInterfaceType::IDqe::RegammaLutData::ConfigType *config,
+                            android::DrmDevice *drm, uint32_t &blobId);
+     static int32_t displayDither(const GsInterfaceType::IDqe::DqeControlData::ConfigType *config,
+                                  android::DrmDevice *drm, uint32_t &blobId);
+};
+
+} // namespace gs
diff --git a/libhwc2.1/libdevice/ExynosDeviceModule.cpp b/libhwc2.1/libdevice/ExynosDeviceModule.cpp
index 678c474..2e01693 100644
--- a/libhwc2.1/libdevice/ExynosDeviceModule.cpp
+++ b/libhwc2.1/libdevice/ExynosDeviceModule.cpp
@@ -43,7 +43,7 @@
 
 int ExynosDeviceModule::initDisplayColor(
         const std::vector<displaycolor::DisplayInfo>& display_info) {
-    mDisplayColorInterface = mDisplayColorLoader.GetDisplayColorGS101(display_info);
+    mDisplayColorInterface = mDisplayColorLoader.GetDisplayColor(display_info);
     if (mDisplayColorInterface == nullptr) {
         ALOGW("%s failed to load displaycolor", __func__);
     }
diff --git a/libhwc2.1/libdevice/ExynosDeviceModule.h b/libhwc2.1/libdevice/ExynosDeviceModule.h
index ba37e29..6c772b6 100644
--- a/libhwc2.1/libdevice/ExynosDeviceModule.h
+++ b/libhwc2.1/libdevice/ExynosDeviceModule.h
@@ -17,9 +17,7 @@
 #ifndef EXYNOS_DEVICE_MODULE_H
 #define EXYNOS_DEVICE_MODULE_H
 
-#include <gs101/displaycolor/displaycolor_gs101.h>
-
-#include "DisplayColorLoader.h"
+#include "DisplayColorModule.h"
 #include "ExynosDevice.h"
 
 using namespace displaycolor;
@@ -27,19 +25,20 @@
 namespace gs101 {
 
 class ExynosDeviceModule : public ExynosDevice {
+    using GsInterfaceType = gs::ColorDrmBlobFactory::GsInterfaceType;
     public:
         ExynosDeviceModule();
         virtual ~ExynosDeviceModule();
 
-        IDisplayColorGS101* getDisplayColorInterface() { return mDisplayColorInterface; }
+        GsInterfaceType* getDisplayColorInterface() { return mDisplayColorInterface; }
         void setActiveDisplay(uint32_t index) { mActiveDisplay = index; }
         uint32_t getActiveDisplay() const { return mActiveDisplay; }
 
     private:
         int initDisplayColor(const std::vector<displaycolor::DisplayInfo>& display_info);
 
-        IDisplayColorGS101* mDisplayColorInterface;
-        DisplayColorLoader mDisplayColorLoader;
+        GsInterfaceType * mDisplayColorInterface;
+        gs::ColorDrmBlobFactory::DcLoaderType mDisplayColorLoader;
         uint32_t mActiveDisplay;
 };
 
diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.cpp b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.cpp
index bfe8eaa..e2b751a 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.cpp
+++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.cpp
@@ -21,29 +21,6 @@
 
 using BrightnessRange = BrightnessController::BrightnessRange;
 
-template <typename T, typename M>
-int32_t convertDqeMatrixDataToMatrix(T &colorMatrix, M &mat,
-                                     uint32_t dimension) {
-    if (colorMatrix.coeffs.size() != (dimension * dimension)) {
-        HWC_LOGE(nullptr, "Invalid coeff size(%zu)",
-                colorMatrix.coeffs.size());
-        return -EINVAL;
-    }
-    for (uint32_t i = 0; i < (dimension * dimension); i++) {
-        mat.coeffs[i] = colorMatrix.coeffs[i];
-    }
-
-    if (colorMatrix.offsets.size() != dimension) {
-        HWC_LOGE(nullptr, "Invalid offset size(%zu)",
-                colorMatrix.offsets.size());
-        return -EINVAL;
-    }
-    for (uint32_t i = 0; i < dimension; i++) {
-        mat.offsets[i] = colorMatrix.offsets[i];
-    }
-    return NO_ERROR;
-}
-
 using namespace gs101;
 
 /////////////////////////////////////////////////// ExynosDisplayDrmInterfaceModule //////////////////////////////////////////////////////////////////
@@ -100,321 +77,12 @@
     oldBlobs.clear();
 }
 
-int32_t ExynosDisplayDrmInterfaceModule::createCgcBlobFromIDqe(
-        const IDisplayColorGS101::IDqe &dqe, uint32_t &blobId)
-{
-    struct cgc_lut cgc;
-    const IDisplayColorGS101::IDqe::CgcData &cgcData = dqe.Cgc();
-
-    if (cgcData.config == nullptr) {
-        ALOGE("no CGC config");
-        return -EINVAL;
-    }
-
-    if ((cgcData.config->r_values.size() != DRM_SAMSUNG_CGC_LUT_REG_CNT) ||
-        (cgcData.config->g_values.size() != DRM_SAMSUNG_CGC_LUT_REG_CNT) ||
-        (cgcData.config->b_values.size() != DRM_SAMSUNG_CGC_LUT_REG_CNT)) {
-        ALOGE("CGC data size is not same (r: %zu, g: %zu: b: %zu)",
-                cgcData.config->r_values.size(),
-                cgcData.config->g_values.size(),
-                cgcData.config->b_values.size());
-        return -EINVAL;
-    }
-
-    for (uint32_t i = 0; i < DRM_SAMSUNG_CGC_LUT_REG_CNT; i++) {
-        cgc.r_values[i] = cgcData.config->r_values[i];
-        cgc.g_values[i] = cgcData.config->g_values[i];
-        cgc.b_values[i] = cgcData.config->b_values[i];
-    }
-    int ret = mDrmDevice->CreatePropertyBlob(&cgc, sizeof(cgc_lut), &blobId);
-    if (ret) {
-        HWC_LOGE(mExynosDisplay, "Failed to create cgc blob %d", ret);
-        return ret;
-    }
-    return NO_ERROR;
-}
-
-int32_t ExynosDisplayDrmInterfaceModule::createDegammaLutBlobFromIDqe(
-        const IDisplayColorGS101::IDqe &dqe, uint32_t &blobId)
-{
-    int ret = 0;
-    uint64_t lut_size = 0;
-
-    if (dqe.DegammaLut().config == nullptr) {
-        ALOGE("no degamma config");
-        return -EINVAL;
-    }
-
-    std::tie(ret, lut_size) = mDrmCrtc->degamma_lut_size_property().value();
-    if (ret < 0) {
-         HWC_LOGE(mExynosDisplay, "%s: there is no degamma_lut_size (ret = %d)",
-                 __func__, ret);
-         return ret;
-    }
-    if (lut_size != IDisplayColorGS101::IDqe::DegammaLutData::ConfigType::kLutLen) {
-        HWC_LOGE(mExynosDisplay, "%s: invalid lut size (%" PRId64 ")",
-                __func__, lut_size);
-        return -EINVAL;
-    }
-
-    struct drm_color_lut color_lut[IDisplayColorGS101::IDqe::DegammaLutData::ConfigType::kLutLen];
-    for (uint32_t i = 0; i < lut_size; i++) {
-        color_lut[i].red = dqe.DegammaLut().config->values[i];
-    }
-    ret = mDrmDevice->CreatePropertyBlob(color_lut, sizeof(color_lut), &blobId);
-    if (ret) {
-        HWC_LOGE(mExynosDisplay, "Failed to create degamma lut blob %d", ret);
-        return ret;
-    }
-    return NO_ERROR;
-}
-
-int32_t ExynosDisplayDrmInterfaceModule::createRegammaLutBlobFromIDqe(
-        const IDisplayColorGS101::IDqe &dqe, uint32_t &blobId)
-{
-    int ret = 0;
-    uint64_t lut_size = 0;
-
-    if (dqe.RegammaLut().config == nullptr) {
-        ALOGE("no regamma config");
-        return -EINVAL;
-    }
-
-    std::tie(ret, lut_size) = mDrmCrtc->gamma_lut_size_property().value();
-    if (ret < 0) {
-         HWC_LOGE(mExynosDisplay, "%s: there is no gamma_lut_size (ret = %d)",
-                 __func__, ret);
-         return ret;
-    }
-    if (lut_size != IDisplayColorGS101::IDqe::DegammaLutData::ConfigType::kLutLen) {
-        HWC_LOGE(mExynosDisplay, "%s: invalid lut size (%" PRId64 ")",
-                __func__, lut_size);
-        return -EINVAL;
-    }
-
-    struct drm_color_lut color_lut[IDisplayColorGS101::IDqe::DegammaLutData::ConfigType::kLutLen];
-    for (uint32_t i = 0; i < lut_size; i++) {
-        color_lut[i].red = dqe.RegammaLut().config->r_values[i];
-        color_lut[i].green = dqe.RegammaLut().config->g_values[i];
-        color_lut[i].blue = dqe.RegammaLut().config->b_values[i];
-    }
-    ret = mDrmDevice->CreatePropertyBlob(color_lut, sizeof(color_lut), &blobId);
-    if (ret) {
-        HWC_LOGE(mExynosDisplay, "Failed to create gamma lut blob %d", ret);
-        return ret;
-    }
-    return NO_ERROR;
-}
-
-int32_t ExynosDisplayDrmInterfaceModule::createGammaMatBlobFromIDqe(
-        const IDisplayColorGS101::IDqe &dqe, uint32_t &blobId)
-{
-    int ret = 0;
-    struct exynos_matrix gamma_matrix;
-    if ((ret = convertDqeMatrixDataToMatrix(
-                    dqe.GammaMatrix().config->matrix_data, gamma_matrix, DRM_SAMSUNG_MATRIX_DIMENS)) != NO_ERROR)
-    {
-        HWC_LOGE(mExynosDisplay, "Failed to convert gamma matrix");
-        return ret;
-    }
-    ret = mDrmDevice->CreatePropertyBlob(&gamma_matrix, sizeof(gamma_matrix), &blobId);
-    if (ret) {
-        HWC_LOGE(mExynosDisplay, "Failed to create gamma matrix blob %d", ret);
-        return ret;
-    }
-
-    return NO_ERROR;
-}
-
-int32_t ExynosDisplayDrmInterfaceModule::createLinearMatBlobFromIDqe(
-        const IDisplayColorGS101::IDqe &dqe, uint32_t &blobId)
-{
-    int ret = 0;
-    struct exynos_matrix linear_matrix;
-    if ((ret = convertDqeMatrixDataToMatrix(
-                    dqe.LinearMatrix().config->matrix_data, linear_matrix, DRM_SAMSUNG_MATRIX_DIMENS)) != NO_ERROR)
-    {
-        HWC_LOGE(mExynosDisplay, "Failed to convert linear matrix");
-        return ret;
-    }
-    ret = mDrmDevice->CreatePropertyBlob(&linear_matrix, sizeof(linear_matrix), &blobId);
-    if (ret) {
-        HWC_LOGE(mExynosDisplay, "Failed to create linear matrix blob %d", ret);
-        return ret;
-    }
-
-    return NO_ERROR;
-}
-
-int32_t ExynosDisplayDrmInterfaceModule::createDispDitherBlobFromIDqe(
-        const IDisplayColorGS101::IDqe &dqe, uint32_t &blobId)
-{
-    int ret = 0;
-    const IDisplayColorGS101::IDqe::DqeControlData& dqeControl = dqe.DqeControl();
-    if (dqeControl.config->disp_dither_override == false) {
-        blobId = 0;
-        return ret;
-    }
-
-    ret = mDrmDevice->CreatePropertyBlob((void*)&dqeControl.config->disp_dither_reg,
-            sizeof(dqeControl.config->disp_dither_reg), &blobId);
-    if (ret) {
-        HWC_LOGE(mExynosDisplay, "Failed to create disp dither blob %d", ret);
-        return ret;
-    }
-
-    return NO_ERROR;
-}
-
-int32_t ExynosDisplayDrmInterfaceModule::createCgcDitherBlobFromIDqe(
-        const IDisplayColorGS101::IDqe &dqe, uint32_t &blobId)
-{
-    int ret = 0;
-    const IDisplayColorGS101::IDqe::DqeControlData& dqeControl = dqe.DqeControl();
-    if (dqeControl.config->cgc_dither_override == false) {
-        blobId = 0;
-        return ret;
-    }
-
-    ret = mDrmDevice->CreatePropertyBlob((void*)&dqeControl.config->cgc_dither_reg,
-            sizeof(dqeControl.config->cgc_dither_reg), &blobId);
-    if (ret) {
-        HWC_LOGE(mExynosDisplay, "Failed to create disp dither blob %d", ret);
-        return ret;
-    }
-    return NO_ERROR;
-}
-
-int32_t ExynosDisplayDrmInterfaceModule::createEotfBlobFromIDpp(
-        const IDisplayColorGS101::IDpp &dpp, uint32_t &blobId)
-{
-    struct hdr_eotf_lut eotf_lut;
-
-    if (dpp.EotfLut().config == nullptr) {
-        ALOGE("no dpp eotf config");
-        return -EINVAL;
-    }
-
-    if ((dpp.EotfLut().config->tf_data.posx.size() != DRM_SAMSUNG_HDR_EOTF_LUT_LEN) ||
-        (dpp.EotfLut().config->tf_data.posy.size() != DRM_SAMSUNG_HDR_EOTF_LUT_LEN)) {
-        HWC_LOGE(mExynosDisplay, "%s: eotf pos size (%zu, %zu)",
-                __func__, dpp.EotfLut().config->tf_data.posx.size(),
-                dpp.EotfLut().config->tf_data.posy.size());
-        return -EINVAL;
-    }
-
-    for (uint32_t i = 0; i < DRM_SAMSUNG_HDR_EOTF_LUT_LEN; i++) {
-        eotf_lut.posx[i] = dpp.EotfLut().config->tf_data.posx[i];
-        eotf_lut.posy[i] = dpp.EotfLut().config->tf_data.posy[i];
-    }
-    int ret = mDrmDevice->CreatePropertyBlob(&eotf_lut, sizeof(eotf_lut), &blobId);
-    if (ret) {
-        HWC_LOGE(mExynosDisplay, "Failed to create eotf lut blob %d", ret);
-        return ret;
-    }
-    return NO_ERROR;
-}
-
-int32_t ExynosDisplayDrmInterfaceModule::createGmBlobFromIDpp(
-        const IDisplayColorGS101::IDpp &dpp, uint32_t &blobId)
-{
-    int ret = 0;
-    struct hdr_gm_data gm_matrix;
-
-    if (dpp.Gm().config == nullptr) {
-        ALOGE("no dpp GM config");
-        return -EINVAL;
-    }
-
-    if ((ret = convertDqeMatrixDataToMatrix(dpp.Gm().config->matrix_data, gm_matrix,
-                                            DRM_SAMSUNG_HDR_GM_DIMENS)) != NO_ERROR)
-    {
-        HWC_LOGE(mExynosDisplay, "Failed to convert gm matrix");
-        return ret;
-    }
-    ret = mDrmDevice->CreatePropertyBlob(&gm_matrix, sizeof(gm_matrix), &blobId);
-    if (ret) {
-        HWC_LOGE(mExynosDisplay, "Failed to create gm matrix blob %d", ret);
-        return ret;
-    }
-    return NO_ERROR;
-}
-
-int32_t ExynosDisplayDrmInterfaceModule::createDtmBlobFromIDpp(
-        const IDisplayColorGS101::IDpp &dpp, uint32_t &blobId)
-{
-    struct hdr_tm_data tm_data;
-
-    if (dpp.Dtm().config == nullptr) {
-        ALOGE("no dpp DTM config");
-        return -EINVAL;
-    }
-
-    if ((dpp.Dtm().config->tf_data.posx.size() != DRM_SAMSUNG_HDR_TM_LUT_LEN) ||
-        (dpp.Dtm().config->tf_data.posy.size() != DRM_SAMSUNG_HDR_TM_LUT_LEN)) {
-        HWC_LOGE(mExynosDisplay, "%s: dtm pos size (%zu, %zu)",
-                __func__, dpp.Dtm().config->tf_data.posx.size(),
-                dpp.Dtm().config->tf_data.posy.size());
-        return -EINVAL;
-    }
-
-    for (uint32_t i = 0; i < DRM_SAMSUNG_HDR_TM_LUT_LEN; i++) {
-        tm_data.posx[i] = dpp.Dtm().config->tf_data.posx[i];
-        tm_data.posy[i] = dpp.Dtm().config->tf_data.posy[i];
-    }
-
-    tm_data.coeff_r = dpp.Dtm().config->coeff_r;
-    tm_data.coeff_g = dpp.Dtm().config->coeff_g;
-    tm_data.coeff_b = dpp.Dtm().config->coeff_b;
-    tm_data.rng_x_min = dpp.Dtm().config->rng_x_min;
-    tm_data.rng_x_max = dpp.Dtm().config->rng_x_max;
-    tm_data.rng_y_min = dpp.Dtm().config->rng_y_min;
-    tm_data.rng_y_max = dpp.Dtm().config->rng_y_max;
-
-    int ret = mDrmDevice->CreatePropertyBlob(&tm_data, sizeof(tm_data), &blobId);
-    if (ret) {
-        HWC_LOGE(mExynosDisplay, "Failed to create tm_data blob %d", ret);
-        return ret;
-    }
-
-    return NO_ERROR;
-}
-int32_t ExynosDisplayDrmInterfaceModule::createOetfBlobFromIDpp(
-        const IDisplayColorGS101::IDpp &dpp, uint32_t &blobId)
-{
-    struct hdr_oetf_lut oetf_lut;
-
-    if (dpp.OetfLut().config == nullptr) {
-        ALOGE("no dpp OETF config");
-        return -EINVAL;
-    }
-
-    if ((dpp.OetfLut().config->tf_data.posx.size() != DRM_SAMSUNG_HDR_OETF_LUT_LEN) ||
-        (dpp.OetfLut().config->tf_data.posy.size() != DRM_SAMSUNG_HDR_OETF_LUT_LEN)) {
-        HWC_LOGE(mExynosDisplay, "%s: oetf pos size (%zu, %zu)",
-                __func__, dpp.OetfLut().config->tf_data.posx.size(),
-                dpp.OetfLut().config->tf_data.posy.size());
-        return -EINVAL;
-    }
-
-    for (uint32_t i = 0; i < DRM_SAMSUNG_HDR_OETF_LUT_LEN; i++) {
-        oetf_lut.posx[i] = dpp.OetfLut().config->tf_data.posx[i];
-        oetf_lut.posy[i] = dpp.OetfLut().config->tf_data.posy[i];
-    }
-    int ret = mDrmDevice->CreatePropertyBlob(&oetf_lut, sizeof(oetf_lut), &blobId);
-    if (ret) {
-        HWC_LOGE(mExynosDisplay, "Failed to create oetf lut blob %d", ret);
-        return ret;
-    }
-    return NO_ERROR;
-}
-
 template<typename StageDataType>
 int32_t ExynosDisplayDrmInterfaceModule::setDisplayColorBlob(
         const DrmProperty &prop,
         const uint32_t type,
         const StageDataType &stage,
-        const IDisplayColorGS101::IDqe &dqe,
+        const typename GsInterfaceType::IDqe &dqe,
         ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq)
 {
     /* dirty bit is valid only if enable is true */
@@ -425,29 +93,47 @@
 
     int32_t ret = 0;
     uint32_t blobId = 0;
+    uint64_t lutSize;
 
     if (stage.enable) {
         switch (type) {
             case DqeBlobs::CGC:
-                ret = createCgcBlobFromIDqe(dqe, blobId);
+                ret = gs::ColorDrmBlobFactory::cgc(dqe.Cgc().config, mDrmDevice, blobId);
                 break;
             case DqeBlobs::DEGAMMA_LUT:
-                ret = createDegammaLutBlobFromIDqe(dqe, blobId);
+                std::tie(ret, lutSize) = mDrmCrtc->degamma_lut_size_property().value();
+                if (ret < 0) {
+                    HWC_LOGE(mExynosDisplay, "%s: there is no degamma_lut_size (ret = %d)",
+                             __func__, ret);
+                } else {
+                    ret = gs::ColorDrmBlobFactory::degamma(lutSize, dqe.DegammaLut().config,
+                                                           mDrmDevice, blobId);
+                }
                 break;
             case DqeBlobs::REGAMMA_LUT:
-                ret = createRegammaLutBlobFromIDqe(dqe, blobId);
+                std::tie(ret, lutSize) = mDrmCrtc->gamma_lut_size_property().value();
+                if (ret < 0) {
+                    HWC_LOGE(mExynosDisplay, "%s: there is no gamma_lut_size (ret = %d)", __func__,
+                             ret);
+                } else {
+                    ret = gs::ColorDrmBlobFactory::regamma(lutSize, dqe.RegammaLut().config,
+                                                           mDrmDevice, blobId);
+                }
                 break;
             case DqeBlobs::GAMMA_MAT:
-                ret = createGammaMatBlobFromIDqe(dqe, blobId);
+                ret = gs::ColorDrmBlobFactory::gammaMatrix(dqe.GammaMatrix().config, mDrmDevice,
+                                                        blobId);
                 break;
             case DqeBlobs::LINEAR_MAT:
-                ret = createLinearMatBlobFromIDqe(dqe, blobId);
+                ret = gs::ColorDrmBlobFactory::linearMatrix(dqe.LinearMatrix().config, mDrmDevice,
+                                                         blobId);
                 break;
             case DqeBlobs::DISP_DITHER:
-                ret = createDispDitherBlobFromIDqe(dqe, blobId);
+                ret = gs::ColorDrmBlobFactory::displayDither(dqe.DqeControl().config, mDrmDevice,
+                                                          blobId);
                 break;
             case DqeBlobs::CGC_DITHER:
-                ret = createCgcDitherBlobFromIDqe(dqe, blobId);
+                ret = gs::ColorDrmBlobFactory::cgcDither(dqe.DqeControl().config, mDrmDevice, blobId);
                 break;
             default:
                 ret = -EINVAL;
@@ -488,7 +174,7 @@
         (ExynosPrimaryDisplayModule*)mExynosDisplay;
 
     int ret = NO_ERROR;
-    const IDisplayColorGS101::IDqe &dqe = display->getDqe();
+    const typename GsInterfaceType::IDqe &dqe = display->getDqe();
 
     if ((mDrmCrtc->cgc_lut_property().id() != 0) &&
         (ret = setDisplayColorBlob(mDrmCrtc->cgc_lut_property(),
@@ -563,7 +249,7 @@
         const DrmProperty &prop,
         const uint32_t type,
         const StageDataType &stage,
-        const IDisplayColorGS101::IDpp &dpp,
+        const typename GsInterfaceType::IDpp &dpp,
         const uint32_t dppIndex,
         ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq,
         bool forceUpdate)
@@ -590,16 +276,16 @@
     if (stage.enable) {
         switch (type) {
             case DppBlobs::EOTF:
-                ret = createEotfBlobFromIDpp(dpp, blobId);
+                ret = gs::ColorDrmBlobFactory::eotf(dpp.EotfLut().config, mDrmDevice, blobId);
                 break;
             case DppBlobs::GM:
-                ret = createGmBlobFromIDpp(dpp, blobId);
+                ret = gs::ColorDrmBlobFactory::gm(dpp.Gm().config, mDrmDevice, blobId);
                 break;
             case DppBlobs::DTM:
-                ret = createDtmBlobFromIDpp(dpp, blobId);
+                ret = gs::ColorDrmBlobFactory::dtm(dpp.Dtm().config, mDrmDevice, blobId);
                 break;
             case DppBlobs::OETF:
-                ret = createOetfBlobFromIDpp(dpp, blobId);
+                ret = gs::ColorDrmBlobFactory::oetf(dpp.OetfLut().config, mDrmDevice, blobId);
                 break;
             default:
                 ret = -EINVAL;
@@ -629,7 +315,7 @@
 int32_t ExynosDisplayDrmInterfaceModule::setPlaneColorSetting(
         ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq,
         const std::unique_ptr<DrmPlane> &plane,
-        const exynos_win_config_data &config)
+        const exynos_win_config_data &config, uint32_t &solidColor)
 {
     if ((mColorSettingChanged == false) ||
         (isPrimary() == false))
@@ -681,10 +367,14 @@
         }
     }
 
-    const IDisplayColorGS101::IDpp &dpp = display->getDppForLayer(mppSource);
+    const typename GsInterfaceType::IDpp &dpp = display->getDppForLayer(mppSource);
     const uint32_t dppIndex = static_cast<uint32_t>(display->getDppIndexForLayer(mppSource));
     bool planeChanged = display->checkAndSaveLayerPlaneId(mppSource, plane->id());
 
+    auto &color = dpp.SolidColor();
+    // exynos_win_config_data.color ARGB
+    solidColor = (color.a << 24) | (color.r << 16) | (color.g << 8) | color.b;
+
     int ret = 0;
     if ((ret = setPlaneColorBlob(plane, plane->eotf_lut_property(),
                 static_cast<uint32_t>(DppBlobs::EOTF),
@@ -793,6 +483,7 @@
 int32_t ExynosDisplayDrmInterfaceModule::createHistoRoiBlob(uint32_t &blobId) {
     struct histogram_roi histo_roi;
 
+    std::unique_lock<std::mutex> lk((mHistogramInfo->mSetHistInfoMutex));
     histo_roi.start_x = mHistogramInfo->getHistogramROI().start_x;
     histo_roi.start_y = mHistogramInfo->getHistogramROI().start_y;
     histo_roi.hsize = mHistogramInfo->getHistogramROI().hsize;
@@ -810,6 +501,7 @@
 int32_t ExynosDisplayDrmInterfaceModule::createHistoWeightsBlob(uint32_t &blobId) {
     struct histogram_weights histo_weights;
 
+    std::unique_lock<std::mutex> lk((mHistogramInfo->mSetHistInfoMutex));
     histo_weights.weight_r = mHistogramInfo->getHistogramWeights().weight_r;
     histo_weights.weight_g = mHistogramInfo->getHistogramWeights().weight_g;
     histo_weights.weight_b = mHistogramInfo->getHistogramWeights().weight_b;
@@ -860,7 +552,7 @@
 
 int32_t ExynosDisplayDrmInterfaceModule::setDisplayHistogramSetting(
         ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq) {
-    if ((mHistogramInfoRegistered == false) || (isPrimary() == false)) return NO_ERROR;
+    if ((isHistogramInfoRegistered() == false) || (isPrimary() == false)) return NO_ERROR;
 
     int ret = NO_ERROR;
 
@@ -889,18 +581,16 @@
     return NO_ERROR;
 }
 
-int32_t ExynosDisplayDrmInterfaceModule::setHistogramControl(int32_t control) {
-    if ((mHistogramInfoRegistered == false) || (isPrimary() == false)) return NO_ERROR;
+int32_t ExynosDisplayDrmInterfaceModule::setHistogramControl(hidl_histogram_control_t control) {
+    if ((isHistogramInfoRegistered() == false) || (isPrimary() == false)) return NO_ERROR;
 
     int ret = NO_ERROR;
     uint32_t crtc_id = mDrmCrtc->id();
 
-    if (control == HISTOGRAM_CONTROL_REQUEST) {
+    if (control == hidl_histogram_control_t::HISTOGRAM_CONTROL_REQUEST) {
         ret = mDrmDevice->CallVendorIoctl(DRM_IOCTL_EXYNOS_HISTOGRAM_REQUEST, (void *)&crtc_id);
-        ALOGD("Histogram Requested");
-    } else if (control == HISTOGRAM_CONTROL_CANCEL) {
+    } else if (control == hidl_histogram_control_t::HISTOGRAM_CONTROL_CANCEL) {
         ret = mDrmDevice->CallVendorIoctl(DRM_IOCTL_EXYNOS_HISTOGRAM_CANCEL, (void *)&crtc_id);
-        ALOGD("Histogram Canceled");
     }
 
     return ret;
@@ -912,14 +602,15 @@
     /*
      * There are two handling methods.
      * For ContentSampling in HWC_2.3 API, histogram bin needs to be accumulated.
-     * For Histogram HIDL, histogram bin need to be sent to HIDL block.
+     * For Histogram IDL, histogram bin need to be sent to IDL block.
      */
-    if (mHistogramInfo->getHistogramType() == HistogramInfo::Histogram_Type::HISTOGRAM_HIDL) {
-        static_cast<HIDLHistogram *>(mHistogramInfo.get())->CallbackHistogram(bin);
+    if (mHistogramInfo->getHistogramType() == HistogramInfo::HistogramType::HISTOGRAM_HIDL) {
+        (mHistogramInfo.get())->callbackHistogram((char16_t *)bin);
     } else {
-    /*
-     * ContentSampling in HWC2.3 API is not supported
-     */
+        /*
+         * ContentSampling in HWC2.3 API is not supported
+         */
+        return -ENOTSUP;
     }
 
     return NO_ERROR;
diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.h b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.h
index b72f2a7..70e963b 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.h
+++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,9 +17,8 @@
 #ifndef EXYNOS_DISPLAY_DRM_INTERFACE_MODULE_H
 #define EXYNOS_DISPLAY_DRM_INTERFACE_MODULE_H
 
-#include <gs101/displaycolor/displaycolor_gs101.h>
-#include <gs101/histogram/histogram.h>
-
+#include <histogram/histogram.h>
+#include "DisplayColorModule.h"
 #include "ExynosDisplayDrmInterface.h"
 
 namespace gs101 {
@@ -27,6 +26,7 @@
 using namespace displaycolor;
 
 class ExynosDisplayDrmInterfaceModule : public ExynosDisplayDrmInterface {
+    using GsInterfaceType = gs::ColorDrmBlobFactory::GsInterfaceType;
     public:
         ExynosDisplayDrmInterfaceModule(ExynosDisplay *exynosDisplay);
         virtual ~ExynosDisplayDrmInterfaceModule();
@@ -37,37 +37,13 @@
         virtual int32_t setPlaneColorSetting(
                 ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq,
                 const std::unique_ptr<DrmPlane> &plane,
-                const exynos_win_config_data &config);
+                const exynos_win_config_data &config,
+                uint32_t &solidColor);
         void setColorSettingChanged(bool changed, bool forceDisplay = false) {
             mColorSettingChanged = changed;
             mForceDisplayColorSetting = forceDisplay;
         };
         void destroyOldBlobs(std::vector<uint32_t> &oldBlobs);
-
-        int32_t createCgcBlobFromIDqe(const IDisplayColorGS101::IDqe &dqe,
-                uint32_t &blobId);
-        int32_t createDegammaLutBlobFromIDqe(const IDisplayColorGS101::IDqe &dqe,
-                uint32_t &blobId);
-        int32_t createRegammaLutBlobFromIDqe(const IDisplayColorGS101::IDqe &dqe,
-                uint32_t &blobId);
-        int32_t createGammaMatBlobFromIDqe(const IDisplayColorGS101::IDqe &dqe,
-                uint32_t &blobId);
-        int32_t createLinearMatBlobFromIDqe(const IDisplayColorGS101::IDqe &dqe,
-                uint32_t &blobId);
-        int32_t createDispDitherBlobFromIDqe(const IDisplayColorGS101::IDqe &dqe,
-                uint32_t &blobId);
-        int32_t createCgcDitherBlobFromIDqe(const IDisplayColorGS101::IDqe &dqe,
-                uint32_t &blobId);
-
-        int32_t createEotfBlobFromIDpp(const IDisplayColorGS101::IDpp &dpp,
-                uint32_t &blobId);
-        int32_t createGmBlobFromIDpp(const IDisplayColorGS101::IDpp &dpp,
-                uint32_t &blobId);
-        int32_t createDtmBlobFromIDpp(const IDisplayColorGS101::IDpp &dpp,
-                uint32_t &blobId);
-        int32_t createOetfBlobFromIDpp(const IDisplayColorGS101::IDpp &dpp,
-                uint32_t &blobId);
-
         void getDisplayInfo(std::vector<displaycolor::DisplayInfo> &display_info);
 
         /* For Histogram */
@@ -77,18 +53,11 @@
         virtual int32_t setDisplayHistogramSetting(
                 ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq);
 
-        void registerHistogramInfo(HistogramInfo *info) {
-            if (info)
-                mHistogramInfo.reset(info);
-            else
-                mHistogramInfo.reset();
-
-            if (mHistogramInfo.get())
-                mHistogramInfoRegistered = true;
-            else
-                mHistogramInfoRegistered = false;
+        virtual void registerHistogramInfo(const std::shared_ptr<IDLHistogram> &info) {
+            mHistogramInfo = info;
         }
-        int32_t setHistogramControl(int32_t enabled);
+        bool isHistogramInfoRegistered() { return mHistogramInfo != nullptr; }
+        int32_t setHistogramControl(hidl_histogram_control_t enabled);
         virtual int32_t setHistogramData(void *bin);
 
     protected:
@@ -140,7 +109,7 @@
                 const DrmProperty &prop,
                 const uint32_t type,
                 const StageDataType &stage,
-                const IDisplayColorGS101::IDqe &dqe,
+                const typename GsInterfaceType::IDqe &dqe,
                 ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq);
         template<typename StageDataType>
         int32_t setPlaneColorBlob(
@@ -148,7 +117,7 @@
                 const DrmProperty &prop,
                 const uint32_t type,
                 const StageDataType &stage,
-                const IDisplayColorGS101::IDpp &dpp,
+                const typename GsInterfaceType::IDpp &dpp,
                 const uint32_t dppIndex,
                 ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq,
                 bool forceUpdate);
@@ -183,8 +152,7 @@
                                     ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq);
         HistoBlobs mOldHistoBlobs;
 
-        std::shared_ptr<HistogramInfo> mHistogramInfo;
-        bool mHistogramInfoRegistered = false;
+        std::shared_ptr<IDLHistogram> mHistogramInfo;
 
     private:
         const std::string GetPanelInfo(const std::string &sysfs_rel, char delim);
diff --git a/libhwc2.1/libexternaldisplay/ExynosExternalDisplayModule.cpp b/libhwc2.1/libexternaldisplay/ExynosExternalDisplayModule.cpp
index 7b3be9f..c26c317 100644
--- a/libhwc2.1/libexternaldisplay/ExynosExternalDisplayModule.cpp
+++ b/libhwc2.1/libexternaldisplay/ExynosExternalDisplayModule.cpp
@@ -28,11 +28,9 @@
 
 using namespace gs101;
 
-ExynosExternalDisplayModule::ExynosExternalDisplayModule(uint32_t index, ExynosDevice *device)
-    :    ExynosExternalDisplay(index, device)
-{
-
-}
+ExynosExternalDisplayModule::ExynosExternalDisplayModule(uint32_t index, ExynosDevice *device,
+                                                         const std::string &displayName)
+      : ExynosExternalDisplay(index, device, displayName) {}
 
 ExynosExternalDisplayModule::~ExynosExternalDisplayModule ()
 {
diff --git a/libhwc2.1/libexternaldisplay/ExynosExternalDisplayModule.h b/libhwc2.1/libexternaldisplay/ExynosExternalDisplayModule.h
index d2db8e6..3d2667d 100644
--- a/libhwc2.1/libexternaldisplay/ExynosExternalDisplayModule.h
+++ b/libhwc2.1/libexternaldisplay/ExynosExternalDisplayModule.h
@@ -23,7 +23,8 @@
 
 class ExynosExternalDisplayModule : public ExynosExternalDisplay {
     public:
-        ExynosExternalDisplayModule(uint32_t index, ExynosDevice *device);
+        ExynosExternalDisplayModule(uint32_t index, ExynosDevice* device,
+                                    const std::string& displayName);
         ~ExynosExternalDisplayModule();
         virtual int32_t validateWinConfigData();
 };
diff --git a/libhwc2.1/libmaindisplay/DisplayColorLoader.h b/libhwc2.1/libmaindisplay/DisplayColorLoader.h
deleted file mode 100644
index e5a241d..0000000
--- a/libhwc2.1/libmaindisplay/DisplayColorLoader.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef DISPLAY_COLOR_LOADER_H
-#define DISPLAY_COLOR_LOADER_H
-
-#include <dlfcn.h>
-#include <gs101/displaycolor/displaycolor_gs101.h>
-#include <log/log.h>
-#include <string>
-#include <vector>
-
-namespace gs101 {
-
-class DisplayColorLoader {
-    public:
-      DisplayColorLoader(const char *lib_name) {
-          lib_handle = dlopen(lib_name, RTLD_LAZY);
-
-          if (lib_handle != nullptr) {
-              const displaycolor::DisplayColorIntfVer *(*get_version)();
-              get_version = (decltype(get_version))
-                                    dlsym(lib_handle, "GetInterfaceVersion");
-              if (get_version == nullptr) {
-                  ALOGE("%s: prebuilt lib is not versioned", __func__);
-              } else {
-                  auto intf_ver = get_version();
-
-                  if (intf_ver != nullptr &&
-                      displaycolor::kInterfaceVersion.Compatible(*intf_ver)) {
-                      get_display_color_gs101 =
-                              (decltype(get_display_color_gs101))dlsym(lib_handle,
-                                                                       "GetDisplayColorGS101");
-
-                      if (get_display_color_gs101 == nullptr) {
-                          ALOGE("%s: failed to get GetDisplayColorGS101\n", __func__);
-                      } else if (!(displaycolor::kInterfaceVersion == *intf_ver)) {
-                          ALOGW("%s: different hwc/displaycolor patch level %u.%u.%u/%u",
-                                __func__,
-                                intf_ver->major,
-                                intf_ver->minor,
-                                displaycolor::kInterfaceVersion.patch,
-                                intf_ver->patch);
-                      }
-                  } else {
-                      if (intf_ver != nullptr) {
-                          ALOGE("%s: prebuilt lib version %u.%u.%u expected %u.%u.%u",
-                                __func__,
-                                intf_ver->major,
-                                intf_ver->minor,
-                                intf_ver->patch,
-                                displaycolor::kInterfaceVersion.major,
-                                displaycolor::kInterfaceVersion.minor,
-                                displaycolor::kInterfaceVersion.patch);
-                      } else {
-                          ALOGE("%s: prebult lib get_version returns null", __func__);
-                      }
-                  }
-              }
-          } else {
-              ALOGE("%s: failed to load library %s\n", __func__, lib_name);
-              get_display_color_gs101 = nullptr;
-          }
-      }
-
-      displaycolor::IDisplayColorGS101 *GetDisplayColorGS101(
-              const std::vector<displaycolor::DisplayInfo> &display_info) {
-          if (get_display_color_gs101 != nullptr) {
-              return get_display_color_gs101(display_info);
-          }
-
-          return nullptr;
-      }
-
-      ~DisplayColorLoader() {
-          if (lib_handle != nullptr) {
-              dlclose(lib_handle);
-          }
-      }
-
-    private:
-      void *lib_handle;
-      displaycolor::IDisplayColorGS101 *(*get_display_color_gs101)(
-              const std::vector<displaycolor::DisplayInfo> &);
-};
-
-}  // namespace gs101
-
-#endif //DISPLAY_COLOR_LOADER_H
diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplayModule.cpp b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplayModule.cpp
index a6ec3c1..2bf949f 100644
--- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplayModule.cpp
+++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplayModule.cpp
@@ -30,26 +30,27 @@
 extern exynos_hwc_control exynosHWCControl;
 #endif
 
+using namespace gs101;
+
 mpp_phycal_type_t getMPPTypeFromDPPChannel(uint32_t channel) {
 
     for (int i=0; i < MAX_DECON_DMA_TYPE; i++){
-        if(IDMA_CHANNEL_MAP[i].channel == channel)
-            return IDMA_CHANNEL_MAP[i].type;
+        if(idma_channel_map[i].channel == channel)
+            return idma_channel_map[i].type;
     }
 
     return MPP_P_TYPE_MAX;
 }
 
-using namespace gs101;
-
 // enable map layerDataMappingInfo comparison in needDisplayColorSetting()
 inline bool operator==(const ExynosPrimaryDisplayModule::DisplaySceneInfo::LayerMappingInfo &lm1,
                        const ExynosPrimaryDisplayModule::DisplaySceneInfo::LayerMappingInfo &lm2) {
     return lm1.dppIdx == lm2.dppIdx && lm1.planeId == lm2.planeId;
 }
 
-ExynosPrimaryDisplayModule::ExynosPrimaryDisplayModule(uint32_t index, ExynosDevice* device)
-      : ExynosPrimaryDisplay(index, device) {
+ExynosPrimaryDisplayModule::ExynosPrimaryDisplayModule(uint32_t index, ExynosDevice* device,
+                                                       const std::string& displayName)
+      : ExynosPrimaryDisplay(index, device, displayName) {
 #ifdef FORCE_GPU_COMPOSITION
     exynosHWCControl.forceGpu = true;
 #endif
@@ -123,7 +124,7 @@
 int32_t ExynosPrimaryDisplayModule::getColorModes(
         uint32_t* outNumModes, int32_t* outModes)
 {
-    IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
     const DisplayType display = getDisplayTypeFromIndex(mIndex);
     const ColorModesMap colorModeMap = displayColorInterface == nullptr
             ? ColorModesMap()
@@ -153,7 +154,7 @@
 int32_t ExynosPrimaryDisplayModule::setColorMode(int32_t mode)
 {
     ALOGD("%s: mode(%d)", __func__, mode);
-    IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
     const DisplayType display = getDisplayTypeFromIndex(mIndex);
     const ColorModesMap colorModeMap = displayColorInterface == nullptr
             ? ColorModesMap()
@@ -177,7 +178,7 @@
 int32_t ExynosPrimaryDisplayModule::getRenderIntents(int32_t mode,
         uint32_t* outNumIntents, int32_t* outIntents)
 {
-    IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
     const DisplayType display = getDisplayTypeFromIndex(mIndex);
     const ColorModesMap colorModeMap = displayColorInterface == nullptr
             ? ColorModesMap()
@@ -214,7 +215,7 @@
 int32_t ExynosPrimaryDisplayModule::setColorModeWithRenderIntent(int32_t mode,
         int32_t intent)
 {
-    IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
     const DisplayType display = getDisplayTypeFromIndex(mIndex);
     const ColorModesMap colorModeMap = displayColorInterface == nullptr
             ? ColorModesMap()
@@ -256,9 +257,10 @@
     if ((hint < HAL_COLOR_TRANSFORM_IDENTITY) ||
         (hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA))
         return HWC2_ERROR_BAD_PARAMETER;
-    ALOGI("%s:: %d, %d", __func__, mColorTransformHint, hint);
-    if (mColorTransformHint != hint)
+    if (mColorTransformHint != hint) {
+        ALOGI("%s:: %d -> %d", __func__, mColorTransformHint, hint);
         setGeometryChanged(GEOMETRY_DISPLAY_COLOR_TRANSFORM_CHANGED);
+    }
     mColorTransformHint = hint;
 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
     mDisplaySceneInfo.setColorTransform(matrix);
@@ -270,7 +272,7 @@
 int32_t ExynosPrimaryDisplayModule::getClientTargetProperty(
         hwc_client_target_property_t* outClientTargetProperty,
         HwcDimmingStage *outDimmingStage) {
-    IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
     if (displayColorInterface == nullptr) {
         ALOGI("%s dc interface not created", __func__);
         return ExynosDisplay::getClientTargetProperty(outClientTargetProperty);
@@ -361,7 +363,7 @@
 
 bool ExynosPrimaryDisplayModule::hasDppForLayer(ExynosMPPSource* layer)
 {
-    IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
     if (displayColorInterface == nullptr) {
         return false;
     }
@@ -380,10 +382,10 @@
     return true;
 }
 
-const IDisplayColorGS101::IDpp& ExynosPrimaryDisplayModule::getDppForLayer(ExynosMPPSource* layer)
-{
+const ExynosPrimaryDisplayModule::GsInterfaceType::IDpp& ExynosPrimaryDisplayModule::getDppForLayer(
+        ExynosMPPSource* layer) {
     uint32_t index = mDisplaySceneInfo.layerDataMappingInfo[layer].dppIdx;
-    IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
     const DisplayType display = getDisplayTypeFromIndex(mIndex);
     return displayColorInterface->GetPipelineData(display)->Dpp()[index].get();
 }
@@ -402,7 +404,7 @@
     int ret = 0;
     ExynosDisplayDrmInterfaceModule *moduleDisplayInterface =
         (ExynosDisplayDrmInterfaceModule*)(mDisplayInterface.get());
-    IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
 
     bool forceDisplayColorSetting = false;
     if (!mDisplaySceneInfo.displaySettingDelivered || isForceColorUpdate())
@@ -450,7 +452,7 @@
     }
     // if assigned displaycolor dppIdx changes, do not reuse it (force plane color update).
     uint32_t oldPlaneId = prev_layerDataMappingInfo.count(layer) != 0 &&
-                    prev_layerDataMappingInfo[layer].dppIdx != index
+                    prev_layerDataMappingInfo[layer].dppIdx == index
             ? prev_layerDataMappingInfo[layer].planeId
             : UINT_MAX;
     layerDataMappingInfo.insert(std::make_pair(layer, LayerMappingInfo{ index, oldPlaneId }));
@@ -538,34 +540,31 @@
         layerColorData.dynamic_metadata.is_valid = true;
     }
     updateInfoSingleVal(layerColorData.dynamic_metadata.display_maximum_luminance,
-            exynosHdrDynamicInfo.data.display_maximum_luminance);
+                        exynosHdrDynamicInfo.data.targeted_system_display_maximum_luminance);
 
     if (!std::equal(layerColorData.dynamic_metadata.maxscl.begin(),
-                layerColorData.dynamic_metadata.maxscl.end(),
-                exynosHdrDynamicInfo.data.maxscl)) {
+                    layerColorData.dynamic_metadata.maxscl.end(),
+                    exynosHdrDynamicInfo.data.maxscl[0])) {
         colorSettingChanged = true;
         for (uint32_t i = 0 ; i < layerColorData.dynamic_metadata.maxscl.size(); i++) {
-            layerColorData.dynamic_metadata.maxscl[i] =
-                exynosHdrDynamicInfo.data.maxscl[i];
+          layerColorData.dynamic_metadata.maxscl[i] = exynosHdrDynamicInfo.data.maxscl[0][i];
         }
     }
     static constexpr uint32_t DYNAMIC_META_DAT_SIZE = 15;
 
     updateInfoVectorVal(layerColorData.dynamic_metadata.maxrgb_percentages,
-            exynosHdrDynamicInfo.data.maxrgb_percentages,
-            DYNAMIC_META_DAT_SIZE);
+                        exynosHdrDynamicInfo.data.maxrgb_percentages[0], DYNAMIC_META_DAT_SIZE);
     updateInfoVectorVal(layerColorData.dynamic_metadata.maxrgb_percentiles,
-            exynosHdrDynamicInfo.data.maxrgb_percentiles,
-            DYNAMIC_META_DAT_SIZE);
+                        exynosHdrDynamicInfo.data.maxrgb_percentiles[0], DYNAMIC_META_DAT_SIZE);
     updateInfoSingleVal(layerColorData.dynamic_metadata.tm_flag,
-            exynosHdrDynamicInfo.data.tone_mapping.tone_mapping_flag);
+                        exynosHdrDynamicInfo.data.tone_mapping.tone_mapping_flag[0]);
     updateInfoSingleVal(layerColorData.dynamic_metadata.tm_knee_x,
-            exynosHdrDynamicInfo.data.tone_mapping.knee_point_x);
+                        exynosHdrDynamicInfo.data.tone_mapping.knee_point_x[0]);
     updateInfoSingleVal(layerColorData.dynamic_metadata.tm_knee_y,
-            exynosHdrDynamicInfo.data.tone_mapping.knee_point_y);
+                        exynosHdrDynamicInfo.data.tone_mapping.knee_point_y[0]);
     updateInfoVectorVal(layerColorData.dynamic_metadata.bezier_curve_anchors,
-            exynosHdrDynamicInfo.data.tone_mapping.bezier_curve_anchors,
-            DYNAMIC_META_DAT_SIZE);
+                        exynosHdrDynamicInfo.data.tone_mapping.bezier_curve_anchors[0],
+                        DYNAMIC_META_DAT_SIZE);
 }
 
 int32_t ExynosPrimaryDisplayModule::DisplaySceneInfo::setClientCompositionColorData(
@@ -602,6 +601,11 @@
 int32_t ExynosPrimaryDisplayModule::DisplaySceneInfo::setLayerColorData(
         LayerColorData& layerData, ExynosLayer* layer, float dimSdrRatio)
 {
+    layerData.is_solid_color_layer = layer->isDimLayer();
+    layerData.solid_color.r = layer->mColor.r;
+    layerData.solid_color.g = layer->mColor.g;
+    layerData.solid_color.b = layer->mColor.b;
+    layerData.solid_color.a = layer->mColor.a;
     layerData.dim_ratio = layer->mPreprocessedInfo.sdrDimRatio;
     setLayerDataspace(layerData,
             static_cast<hwc::Dataspace>(layer->mDataSpace));
@@ -674,7 +678,7 @@
 int32_t ExynosPrimaryDisplayModule::updateColorConversionInfo()
 {
     int ret = 0;
-    IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
     if (displayColorInterface == nullptr) {
         return ret;
     }
@@ -709,7 +713,7 @@
 int32_t ExynosPrimaryDisplayModule::updatePresentColorConversionInfo()
 {
     int ret = NO_ERROR;
-    IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
     if (displayColorInterface == nullptr) {
         return ret;
     }
@@ -734,7 +738,7 @@
 }
 
 int32_t ExynosPrimaryDisplayModule::getColorAdjustedDbv(uint32_t &dbv_adj) {
-    IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
     if (displayColorInterface == nullptr) {
         return NO_ERROR;
     }
@@ -891,6 +895,10 @@
     return true;
 }
 
+bool ExynosPrimaryDisplayModule::isLbeSupported() {
+    return mLbeSupported;
+}
+
 void ExynosPrimaryDisplayModule::initLbe() {
     if (!parseAtcProfile()) {
         ALOGD("Failed to parseAtcMode");
@@ -910,6 +918,7 @@
         mAtcSubSetting[it->first.c_str()].node = String8::format(it->second.c_str(), mIndex);
         mAtcSubSetting[it->first.c_str()].value.set_dirty();
     }
+    mLbeSupported = true;
 }
 
 uint32_t ExynosPrimaryDisplayModule::getAtcLuxMapIndex(std::vector<atc_lux_map> map, uint32_t lux) {
@@ -986,6 +995,7 @@
             ALOGE("Fail to set atc enable = %d", enable);
             return -EPERM;
         }
+        mPendingAtcOff = false;
     }
 
     mCurrentAtcModeName = enable ? mode_name : "NULL";
@@ -1006,11 +1016,14 @@
             break;
         case LbeState::HIGH_BRIGHTNESS:
             modeStr = kAtcModeHbmStr;
-            enhanced_hbm = true;
             break;
         case LbeState::POWER_SAVE:
             modeStr = kAtcModePowerSaveStr;
             break;
+        case LbeState::HIGH_BRIGHTNESS_ENHANCE:
+            modeStr = kAtcModeHbmStr;
+            enhanced_hbm = true;
+            break;
         default:
             ALOGE("Lbe state not support");
             return;
@@ -1019,9 +1032,11 @@
     if (setAtcMode(modeStr) != NO_ERROR) return;
 
     mBrightnessController->processEnhancedHbm(enhanced_hbm);
+    mBrightnessController->setOutdoorVisibility(state);
+
     if (mCurrentLbeState != state) {
         mCurrentLbeState = state;
-        mDevice->onRefresh();
+        mDevice->onRefresh(mDisplayId);
     }
     ALOGI("Lbe state %hhd", mCurrentLbeState);
 }
@@ -1049,7 +1064,7 @@
 
     if (mAtcLuxMapIndex != index) {
         mAtcLuxMapIndex = index;
-        mDevice->onRefresh();
+        mDevice->onRefresh(mDisplayId);
     }
     mCurrentLux = value;
 }
@@ -1134,11 +1149,11 @@
         ALOGI("atc enable is off (pending off=false)");
     }
 
-    mDevice->onRefresh();
+    mDevice->onRefresh(mDisplayId);
 }
 
 int32_t ExynosPrimaryDisplayModule::setPowerMode(int32_t mode) {
-    hwc2_power_mode_t prevPowerModeState = mPowerModeState;
+    hwc2_power_mode_t prevPowerModeState = mPowerModeState.value_or(HWC2_POWER_MODE_OFF);
     int32_t ret;
 
     ret = ExynosPrimaryDisplay::setPowerMode(mode);
@@ -1161,6 +1176,6 @@
 
 bool ExynosPrimaryDisplayModule::isColorCalibratedByDevice() {
     const DisplayType display = getDisplayTypeFromIndex(mIndex);
-    IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
     return displayColorInterface->GetCalibrationInfo(display).factory_cal_loaded;
 };
diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplayModule.h b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplayModule.h
index ada69f6..c60bcfd 100644
--- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplayModule.h
+++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplayModule.h
@@ -16,8 +16,6 @@
 #ifndef EXYNOS_DISPLAY_MODULE_H
 #define EXYNOS_DISPLAY_MODULE_H
 
-#include <gs101/displaycolor/displaycolor_gs101.h>
-
 #include "ExynosDeviceModule.h"
 #include "ExynosDisplay.h"
 #include "ExynosLayer.h"
@@ -96,8 +94,10 @@
 using namespace displaycolor;
 
 class ExynosPrimaryDisplayModule : public ExynosPrimaryDisplay {
+    using GsInterfaceType = gs::ColorDrmBlobFactory::GsInterfaceType;
     public:
-        ExynosPrimaryDisplayModule(uint32_t index, ExynosDevice *device);
+        ExynosPrimaryDisplayModule(uint32_t index, ExynosDevice* device,
+                                   const std::string& displayName);
         ~ExynosPrimaryDisplayModule();
         void usePreDefinedWindow(bool use);
         virtual int32_t validateWinConfigData();
@@ -119,7 +119,7 @@
         virtual int32_t updatePresentColorConversionInfo();
         virtual bool checkRrCompensationEnabled() {
             const DisplayType display = getDisplayTypeFromIndex(mIndex);
-            IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+            GsInterfaceType* displayColorInterface = getDisplayColorInterface();
             return displayColorInterface
                 ? displayColorInterface->IsRrCompensationEnabled(display)
                 : false;
@@ -130,6 +130,7 @@
         virtual int32_t getColorAdjustedDbv(uint32_t &dbv_adj);
 
         virtual void initLbe();
+        virtual bool isLbeSupported();
         virtual void setLbeState(LbeState state);
         virtual void setLbeAmbientLight(int value);
         virtual LbeState getLbeState();
@@ -228,13 +229,13 @@
         };
 
         bool hasDisplayColor() {
-            IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+            GsInterfaceType* displayColorInterface = getDisplayColorInterface();
             return displayColorInterface != nullptr;
         }
 
         /* Call getDppForLayer() only if hasDppForLayer() is true */
         bool hasDppForLayer(ExynosMPPSource* layer);
-        const IDisplayColorGS101::IDpp& getDppForLayer(ExynosMPPSource* layer);
+        const GsInterfaceType::IDpp& getDppForLayer(ExynosMPPSource* layer);
         int32_t getDppIndexForLayer(ExynosMPPSource* layer);
         /* Check if layer's assigned plane id has changed, save the new planeId.
          * call only if hasDppForLayer is true */
@@ -247,14 +248,14 @@
 
         size_t getNumOfDpp() {
             const DisplayType display = getDisplayTypeFromIndex(mIndex);
-            IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+            GsInterfaceType* displayColorInterface = getDisplayColorInterface();
             return displayColorInterface->GetPipelineData(display)->Dpp().size();
         };
 
-        const IDisplayColorGS101::IDqe& getDqe()
+        const GsInterfaceType::IDqe& getDqe()
         {
             const DisplayType display = getDisplayTypeFromIndex(mIndex);
-            IDisplayColorGS101* displayColorInterface = getDisplayColorInterface();
+            GsInterfaceType* displayColorInterface = getDisplayColorInterface();
             return displayColorInterface->GetPipelineData(display)->Dqe();
         };
 
@@ -297,12 +298,7 @@
                 return false;
         };
 
-        DisplayType getDisplayTypeFromIndex(uint32_t index) {
-            return (index >= DisplayType::DISPLAY_MAX) ? DisplayType::DISPLAY_PRIMARY
-                                                       : DisplayType(mIndex);
-        };
-
-        IDisplayColorGS101* getDisplayColorInterface() {
+        GsInterfaceType* getDisplayColorInterface() {
             ExynosDeviceModule* device = (ExynosDeviceModule*)mDevice;
             return device->getDisplayColorInterface();
         }
@@ -328,6 +324,7 @@
         Mutex mAtcStMutex;
         bool mPendingAtcOff;
         bool mForceColorUpdate = false;
+        bool mLbeSupported = false;
 
     protected:
         virtual int32_t setPowerMode(int32_t mode) override;
diff --git a/libhwc2.1/libresource/ExynosMPPModule.cpp b/libhwc2.1/libresource/ExynosMPPModule.cpp
index bc435ad..357c61a 100644
--- a/libhwc2.1/libresource/ExynosMPPModule.cpp
+++ b/libhwc2.1/libresource/ExynosMPPModule.cpp
@@ -77,10 +77,8 @@
         }
         MPP_LOGD(eDebugColorManagement,
                 "%s, src: 0x%8x", __func__, mppSource->mSrcImg.dataSpace);
-        const IDisplayColorGS101::IDpp& dpp =
-            primaryDisplay->getDppForLayer(layer);
-        mppLayer->setLayerData((void *)&dpp,
-                sizeof(IDisplayColorGS101::IDpp));
+        const auto& dpp = primaryDisplay->getDppForLayer(layer);
+        mppLayer->setLayerData((void *)&dpp, sizeof(dpp));
     }
     return NO_ERROR;
 }
diff --git a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplayModule.cpp b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplayModule.cpp
index a74312b..826f48e 100644
--- a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplayModule.cpp
+++ b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplayModule.cpp
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 #undef LOG_TAG
-#define LOG_TAG "virtualdisplaymodule"
+#define LOG_TAG "hwc-virt-display"
 
 #include "ExynosVirtualDisplayModule.h"
 
 using namespace gs101;
 
-ExynosVirtualDisplayModule::ExynosVirtualDisplayModule(uint32_t index, ExynosDevice *device)
-    :   ExynosVirtualDisplay(index, device)
-{
+ExynosVirtualDisplayModule::ExynosVirtualDisplayModule(uint32_t index, ExynosDevice* device,
+                                                       const std::string& displayName)
+      : ExynosVirtualDisplay(index, device, displayName) {
     mGLESFormat = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M;
 
     if (device == NULL) {
diff --git a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplayModule.h b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplayModule.h
index 9d68c2d..efd66a7 100644
--- a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplayModule.h
+++ b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplayModule.h
@@ -23,7 +23,8 @@
 
 class ExynosVirtualDisplayModule : public ExynosVirtualDisplay {
 public:
-    ExynosVirtualDisplayModule(uint32_t displayId, ExynosDevice *device);
+    ExynosVirtualDisplayModule(uint32_t index, ExynosDevice* device,
+                               const std::string& displayName);
     ~ExynosVirtualDisplayModule();
 
     /* getDisplayAttribute(..., config, attribute, outValue)