diff --git a/zircon/system/dev/display/astro-display/astro-display.cpp b/zircon/system/dev/display/astro-display/astro-display.cpp
index 88b56dd631d52ebac0cb4f7a6fe2d7cc59d869be..3df1589d174a3cff05a5c742ce7b3af37c15a78e 100644
--- a/zircon/system/dev/display/astro-display/astro-display.cpp
+++ b/zircon/system/dev/display/astro-display/astro-display.cpp
@@ -384,10 +384,31 @@ uint32_t AstroDisplay::DisplayControllerImplCheckConfiguration(
 
     fbl::AutoLock lock(&display_lock_);
 
-    bool success;
-    if (display_configs[0]->layer_count != 1) {
-        success = display_configs[0]->layer_count == 0;
-    } else {
+    bool success = true;
+
+    if (display_configs[0]->layer_count > 1) {
+        // We only support 1 layer
+        success = false;
+    }
+
+    if (success && display_configs[0]->cc_flags) {
+        // Make sure cc values are correct
+        if (display_configs[0]->cc_flags & COLOR_CONVERSION_PREOFFSET) {
+            for (int i = 0; i < 3; i++) {
+                success = success && display_configs[0]->cc_preoffsets[i] > -1;
+                success = success && display_configs[0]->cc_preoffsets[i] < 1;
+            }
+        }
+        if (success && display_configs[0]->cc_flags & COLOR_CONVERSION_POSTOFFSET) {
+            for (int i = 0; i < 3; i++) {
+                success = success && display_configs[0]->cc_postoffsets[i] > -1;
+                success = success && display_configs[0]->cc_postoffsets[i] < 1;
+            }
+        }
+    }
+
+    if (success) {
+        // Make sure ther layer configuration is supported
         const primary_layer_t& layer = display_configs[0]->layer_list[0]->cfg.primary;
         frame_t frame = {
             .x_pos = 0, .y_pos = 0, .width = width_, .height = height_,
@@ -398,7 +419,6 @@ uint32_t AstroDisplay::DisplayControllerImplCheckConfiguration(
                 && layer.image.height == height_
                 && memcmp(&layer.dest_frame, &frame, sizeof(frame_t)) == 0
                 && memcmp(&layer.src_frame, &frame, sizeof(frame_t)) == 0
-                && display_configs[0]->cc_flags == 0
                 && layer.alpha_mode == ALPHA_DISABLE;
     }
     if (!success) {
@@ -406,7 +426,6 @@ uint32_t AstroDisplay::DisplayControllerImplCheckConfiguration(
         for (unsigned i = 1; i < display_configs[0]->layer_count; i++) {
             layer_cfg_results[0][i] = CLIENT_MERGE_SRC;
         }
-        layer_cfg_result_count[0] = display_configs[0]->layer_count;
     }
     return CONFIG_DISPLAY_OK;
 }
@@ -433,7 +452,7 @@ void AstroDisplay::DisplayControllerImplApplyConfiguration(const display_config_
         addr = (uint8_t) (uint64_t) display_configs[0]->layer_list[0]->cfg.primary.image.handle;
         current_image_valid_= true;
         current_image_ = addr;
-        osd_->FlipOnVsync(addr);
+        osd_->FlipOnVsync(display_configs[0]);
     } else {
         current_image_valid_= false;
         if (full_init_done_) {
diff --git a/zircon/system/dev/display/astro-display/osd.cpp b/zircon/system/dev/display/astro-display/osd.cpp
index f9a791be7f8b6776a936a7bb6023b613b9e3e603..382b91efea94e8f555d124253dd0d963e6f40a39 100644
--- a/zircon/system/dev/display/astro-display/osd.cpp
+++ b/zircon/system/dev/display/astro-display/osd.cpp
@@ -9,6 +9,8 @@
 #include <ddk/debug.h>
 #include <ddktl/device.h>
 #include <fbl/auto_lock.h>
+#include <math.h>
+#include <float.h>
 
 namespace astro_display {
 
@@ -143,7 +145,38 @@ zx_status_t Osd::Configure() {
     return ZX_OK;
 }
 
-void Osd::FlipOnVsync(uint8_t idx) {
+//TODO(payamm): Vendor spec does not indicate range. However (-1024 1024) seems
+// to be the correct range based on experimentation.
+uint32_t Osd::FloatToOffset(float f) {
+    uint32_t offset_val = 0;
+    if (f < 0) {
+        offset_val |= (1 << 11);
+        f *= -1;
+    }
+    ZX_DEBUG_ASSERT(0 <= f && f < 1.0f);
+
+    // convert [0 1) --> [0 1024)
+    f *= 1024;
+    offset_val |= static_cast<uint32_t>(f);
+    return offset_val;
+}
+
+//TODO(payamm): Improve performance and accuracy if needed
+uint32_t Osd::FloatToFixed3_10(float f) {
+    uint32_t fixed_num = 0;
+    if (f < 0) {
+        f *= -1;
+        fixed_num |= (1 << 12);
+    }
+    fixed_num |= static_cast<uint32_t>((round(f * (1 << 10))));
+    fixed_num &= 0x1fff;
+    return fixed_num;
+}
+
+void Osd::FlipOnVsync(const display_config_t* config) {
+
+    // extract index
+    uint8_t idx = (uint8_t) config->layer_list[0]->cfg.primary.image.handle;
 
     // Get the first available channel
     int rdma_channel = GetNextAvailableRdmaChannel();
@@ -170,6 +203,67 @@ void Osd::FlipOnVsync(uint8_t idx) {
     SetRdmaTableValue(rdma_channel, IDX_CFG_W0, cfg_w0);
     SetRdmaTableValue(rdma_channel, IDX_CTRL_STAT,
                       vpu_mmio_->Read32(VPU_VIU_OSD1_CTRL_STAT) | (1 << 0));
+
+    // Perform color correction if needed
+    if (config->cc_flags) {
+        // Set enable bit
+        SetRdmaTableValue(rdma_channel, IDX_MATRIX_EN_CTRL,
+                          vpu_mmio_->Read32(VPU_VPP_POST_MATRIX_EN_CTRL) | (1 << 0));
+
+        // Load PreOffset values (or 0 if none entered)
+        SetRdmaTableValue(rdma_channel, IDX_MATRIX_PRE_OFFSET0_1,
+                          config->cc_flags & COLOR_CONVERSION_PREOFFSET ?
+                          (FloatToOffset(config->cc_preoffsets[0]) << 16 |
+                           FloatToOffset(config->cc_preoffsets[1]) << 0) :  0);
+        SetRdmaTableValue(rdma_channel, IDX_MATRIX_PRE_OFFSET2,
+                          config->cc_flags & COLOR_CONVERSION_PREOFFSET ?
+                          (FloatToOffset(config->cc_preoffsets[2]) << 0) : 0);
+
+        // Load PostOffset values (or 0 if none entered)
+        SetRdmaTableValue(rdma_channel, IDX_MATRIX_OFFSET0_1,
+                          config->cc_flags & COLOR_CONVERSION_POSTOFFSET ?
+                          (FloatToOffset(config->cc_postoffsets[0]) << 16 |
+                           FloatToOffset(config->cc_postoffsets[1]) << 0) :  0);
+        SetRdmaTableValue(rdma_channel, IDX_MATRIX_OFFSET2,
+                          config->cc_flags & COLOR_CONVERSION_POSTOFFSET ?
+                          (FloatToOffset(config->cc_postoffsets[2]) << 0) : 0);
+
+        float identity[3][3] = {
+            { 1, 0, 0, },
+            { 0, 1, 0, },
+            { 0, 0, 1, },
+        };
+
+        // This will include either the entered coefficient matrix or the identity matrix
+        float final[3][3] = {};
+
+        for (uint32_t i = 0; i < 3; i++) {
+            for (uint32_t j = 0; j < 3; j++) {
+                final[i][j] = config->cc_flags & COLOR_CONVERSION_COEFFICIENTS ?
+                config->cc_coefficients[i][j] : identity[i][j];
+            }
+        }
+
+        // Load up the coefficient matrix registers
+        SetRdmaTableValue(rdma_channel,IDX_MATRIX_COEF00_01,
+                          FloatToFixed3_10(final[0][0]) << 16 |
+                          FloatToFixed3_10(final[0][1]) << 0);
+        SetRdmaTableValue(rdma_channel,IDX_MATRIX_COEF02_10,
+                          FloatToFixed3_10(final[0][2]) << 16 |
+                          FloatToFixed3_10(final[1][0]) << 0);
+        SetRdmaTableValue(rdma_channel,IDX_MATRIX_COEF11_12,
+                          FloatToFixed3_10(final[1][1]) << 16 |
+                          FloatToFixed3_10(final[1][2]) << 0);
+        SetRdmaTableValue(rdma_channel,IDX_MATRIX_COEF20_21,
+                          FloatToFixed3_10(final[2][0]) << 16 |
+                          FloatToFixed3_10(final[2][1]) << 0);
+        SetRdmaTableValue(rdma_channel,IDX_MATRIX_COEF22,
+                          FloatToFixed3_10(final[2][2]) << 0);
+    } else {
+        // Disable color conversion engine
+        SetRdmaTableValue(rdma_channel, IDX_MATRIX_EN_CTRL,
+                          vpu_mmio_->Read32(VPU_VPP_POST_MATRIX_EN_CTRL) & ~(1 << 0));
+    }
     FlushRdmaTable(rdma_channel);
 
     // Write the start and end address of the table. End address is the last address that the
@@ -349,6 +443,16 @@ void Osd::ResetRdmaTable() {
         RdmaTable* rdma_table = reinterpret_cast<RdmaTable*>(rdma_chnl_container_[i].virt_offset);
         rdma_table[IDX_CFG_W0].reg = (VPU_VIU_OSD1_BLK0_CFG_W0 >> 2);
         rdma_table[IDX_CTRL_STAT].reg = (VPU_VIU_OSD1_CTRL_STAT >> 2);
+        rdma_table[IDX_MATRIX_EN_CTRL].reg = (VPU_VPP_POST_MATRIX_EN_CTRL >> 2);
+        rdma_table[IDX_MATRIX_COEF00_01].reg = (VPU_VPP_POST_MATRIX_COEF00_01 >> 2);
+        rdma_table[IDX_MATRIX_COEF02_10].reg = (VPU_VPP_POST_MATRIX_COEF02_10 >> 2);
+        rdma_table[IDX_MATRIX_COEF11_12].reg = (VPU_VPP_POST_MATRIX_COEF11_12 >> 2);
+        rdma_table[IDX_MATRIX_COEF20_21].reg = (VPU_VPP_POST_MATRIX_COEF20_21 >> 2);
+        rdma_table[IDX_MATRIX_COEF22].reg = (VPU_VPP_POST_MATRIX_COEF22 >> 2);
+        rdma_table[IDX_MATRIX_OFFSET0_1].reg = (VPU_VPP_POST_MATRIX_OFFSET0_1 >> 2);
+        rdma_table[IDX_MATRIX_OFFSET2].reg = (VPU_VPP_POST_MATRIX_OFFSET2 >> 2);
+        rdma_table[IDX_MATRIX_PRE_OFFSET0_1].reg = (VPU_VPP_POST_MATRIX_PRE_OFFSET0_1 >> 2);
+        rdma_table[IDX_MATRIX_PRE_OFFSET2].reg = (VPU_VPP_POST_MATRIX_PRE_OFFSET2 >> 2);
     }
 
 }
@@ -362,7 +466,7 @@ void Osd::SetRdmaTableValue(uint32_t channel, uint32_t idx, uint32_t val) {
 
 void Osd::FlushRdmaTable(uint32_t channel) {
     zx_status_t status = zx_cache_flush(rdma_chnl_container_[channel].virt_offset,
-                                        sizeof(RdmaTable),
+                                        IDX_MAX * sizeof(RdmaTable),
                                         ZX_CACHE_FLUSH_DATA | ZX_CACHE_FLUSH_INVALIDATE);
     if (status != ZX_OK) {
         DISP_ERROR("Could not clean cache %d\n", status);
@@ -634,6 +738,28 @@ void Osd::Dump() {
               vpu_mmio_->Read32(VPU_RDMA_STATUS2));
     DISP_INFO("VPU_RDMA_STATUS3 = 0x%x\n",
               vpu_mmio_->Read32(VPU_RDMA_STATUS3));
+
+    DISP_INFO("Dumping all Color Correction Matrix related Registers\n\n");
+    DISP_INFO("VPU_VPP_POST_MATRIX_COEF00_01 = 0x%x\n",
+              vpu_mmio_->Read32(VPU_VPP_POST_MATRIX_COEF00_01));
+    DISP_INFO("VPU_VPP_POST_MATRIX_COEF02_10 = 0x%x\n",
+              vpu_mmio_->Read32(VPU_VPP_POST_MATRIX_COEF02_10));
+    DISP_INFO("VPU_VPP_POST_MATRIX_COEF11_12 = 0x%x\n",
+              vpu_mmio_->Read32(VPU_VPP_POST_MATRIX_COEF11_12));
+    DISP_INFO("VPU_VPP_POST_MATRIX_COEF20_21 = 0x%x\n",
+              vpu_mmio_->Read32(VPU_VPP_POST_MATRIX_COEF20_21));
+    DISP_INFO("VPU_VPP_POST_MATRIX_COEF22 = 0x%x\n",
+              vpu_mmio_->Read32(VPU_VPP_POST_MATRIX_COEF22));
+    DISP_INFO("VPU_VPP_POST_MATRIX_OFFSET0_1 = 0x%x\n",
+              vpu_mmio_->Read32(VPU_VPP_POST_MATRIX_OFFSET0_1));
+    DISP_INFO("VPU_VPP_POST_MATRIX_OFFSET2 = 0x%x\n",
+              vpu_mmio_->Read32(VPU_VPP_POST_MATRIX_OFFSET2));
+    DISP_INFO("VPU_VPP_POST_MATRIX_PRE_OFFSET0_1 = 0x%x\n",
+              vpu_mmio_->Read32(VPU_VPP_POST_MATRIX_PRE_OFFSET0_1));
+    DISP_INFO("VPU_VPP_POST_MATRIX_PRE_OFFSET2 = 0x%x\n",
+              vpu_mmio_->Read32(VPU_VPP_POST_MATRIX_PRE_OFFSET2));
+    DISP_INFO("VPU_VPP_POST_MATRIX_EN_CTRL = 0x%x\n",
+          vpu_mmio_->Read32(VPU_VPP_POST_MATRIX_EN_CTRL));
 }
 
 void Osd::Release() {
diff --git a/zircon/system/dev/display/astro-display/osd.h b/zircon/system/dev/display/astro-display/osd.h
index 63467a71edfdccbd9456cea7d2d61c04495314a6..eff511d32e775f7d48d4d15efbee08deeb982ada 100644
--- a/zircon/system/dev/display/astro-display/osd.h
+++ b/zircon/system/dev/display/astro-display/osd.h
@@ -7,6 +7,7 @@
 #include <zircon/compiler.h>
 #include <ddk/protocol/platform/device.h>
 #include <ddk/protocol/platform-device-lib.h>
+#include <ddktl/protocol/display/controller.h>
 #include <lib/mmio/mmio.h>
 #include <lib/zx/interrupt.h>
 #include <lib/zx/bti.h>
@@ -25,6 +26,16 @@ struct RdmaTable {
 enum {
     IDX_CFG_W0,
     IDX_CTRL_STAT,
+    IDX_MATRIX_COEF00_01,
+    IDX_MATRIX_COEF02_10,
+    IDX_MATRIX_COEF11_12,
+    IDX_MATRIX_COEF20_21,
+    IDX_MATRIX_COEF22,
+    IDX_MATRIX_OFFSET0_1,
+    IDX_MATRIX_OFFSET2,
+    IDX_MATRIX_PRE_OFFSET0_1,
+    IDX_MATRIX_PRE_OFFSET2,
+    IDX_MATRIX_EN_CTRL,
     IDX_MAX,
 };
 
@@ -53,7 +64,7 @@ public:
     zx_status_t Configure();
     void Disable();
     // This function will apply configuration when VSYNC interrupt occurs using RDMA
-    void FlipOnVsync(uint8_t idx);
+    void FlipOnVsync(const display_config_t* config);
     void Dump();
     void Release();
 
@@ -69,7 +80,9 @@ private:
     void FlushRdmaTable(uint32_t channel);
     int GetNextAvailableRdmaChannel();
     int RdmaThread();
-
+    // This function converts a float into Fixed Point 3.10 format
+    uint32_t FloatToFixed3_10(float f);
+    uint32_t FloatToOffset(float f);
     std::optional<ddk::MmioBuffer>      vpu_mmio_;
     pdev_protocol_t                     pdev_ = {nullptr, nullptr};
     zx::bti                             bti_;
diff --git a/zircon/system/dev/display/astro-display/vpu-regs.h b/zircon/system/dev/display/astro-display/vpu-regs.h
index 5cdae340022b48b346e617dedc2f0d9ece88b6b7..b5e652bcb394e36ab5e55c9a9c3989eb933be767 100644
--- a/zircon/system/dev/display/astro-display/vpu-regs.h
+++ b/zircon/system/dev/display/astro-display/vpu-regs.h
@@ -57,4 +57,15 @@
 #define VPU_RDARB_MODE_L1C1                                 (0x2790 << 2)
 #define VPU_RDARB_MODE_L1C2                                 (0x2799 << 2)
 #define VPU_RDARB_MODE_L2C1                                 (0x279d << 2)
-#define VPU_WRARB_MODE_L2C1                                 (0x27a2 << 2)
\ No newline at end of file
+#define VPU_WRARB_MODE_L2C1                                 (0x27a2 << 2)
+
+#define VPU_VPP_POST_MATRIX_COEF00_01                       (0x32b0 << 2)
+#define VPU_VPP_POST_MATRIX_COEF02_10                       (0x32b1 << 2)
+#define VPU_VPP_POST_MATRIX_COEF11_12                       (0x32b2 << 2)
+#define VPU_VPP_POST_MATRIX_COEF20_21                       (0x32b3 << 2)
+#define VPU_VPP_POST_MATRIX_COEF22                          (0x32b4 << 2)
+#define VPU_VPP_POST_MATRIX_OFFSET0_1                       (0x32b9 << 2)
+#define VPU_VPP_POST_MATRIX_OFFSET2                         (0x32ba << 2)
+#define VPU_VPP_POST_MATRIX_PRE_OFFSET0_1                   (0x32bb << 2)
+#define VPU_VPP_POST_MATRIX_PRE_OFFSET2                     (0x32bc << 2)
+#define VPU_VPP_POST_MATRIX_EN_CTRL                         (0x32bd << 2)
diff --git a/zircon/system/uapp/display-test/main.cpp b/zircon/system/uapp/display-test/main.cpp
index d53ddcc4e782a615466af1248bb1e03fa9b4aa21..1be72f672d619fe3668ff9eacb0ff9beeb1abbd7 100644
--- a/zircon/system/uapp/display-test/main.cpp
+++ b/zircon/system/uapp/display-test/main.cpp
@@ -317,7 +317,12 @@ int main(int argc, const char* argv[]) {
     fbl::Vector<fbl::Vector<uint64_t>> display_layers;
     fbl::Vector<fbl::unique_ptr<VirtualLayer>> layers;
     int32_t num_frames = 120; // default to 120 frames
-    bool isMediaTek = false;
+    enum Platform {
+        INTEL,
+        ARM_MEDIATEK,
+        ARM_AMLOGIC,
+    };
+    Platform platform = INTEL; // default to Intel
 
     if (!bind_display(&displays)) {
         return -1;
@@ -372,7 +377,11 @@ int main(int argc, const char* argv[]) {
             argv += 2;
             argc -= 2;
         } else if (strcmp(argv[0], "--mediatek") == 0) {
-            isMediaTek = true;
+            platform = ARM_MEDIATEK;
+            argv += 1;
+            argc -= 1;
+        } else if (strcmp(argv[0], "--amlogic") == 0) {
+            platform = ARM_AMLOGIC;
             argv += 1;
             argc -= 1;
         } else {
@@ -382,7 +391,7 @@ int main(int argc, const char* argv[]) {
     }
 
     fbl::AllocChecker ac;
-    if (!isMediaTek) {
+    if (platform == INTEL) {
         // Color layer which covers all displays
         fbl::unique_ptr<ColorLayer> layer0 = fbl::make_unique_checked<ColorLayer>(&ac, displays);
         if (!ac.check()) {
@@ -442,7 +451,7 @@ int main(int argc, const char* argv[]) {
         CursorLayer* layer4 = new CursorLayer(displays);
         layers.push_back(std::move(layer4));
 #endif
-    } else {
+    } else if (platform == ARM_MEDIATEK) {
         // Mediatek display test
         uint32_t width = displays[0].mode().horizontal_resolution;
         uint32_t height = displays[0].mode().vertical_resolution;
@@ -487,6 +496,15 @@ int main(int argc, const char* argv[]) {
         }
         layer4->SetAlpha(true, (float)0.3);
         layers.push_back(std::move(layer4));
+    } else if (platform == ARM_AMLOGIC) {
+        // Mediatek display test
+        fbl::unique_ptr<PrimaryLayer> layer1 = fbl::make_unique_checked<PrimaryLayer>(&ac,
+                                                                                      displays);
+        if (!ac.check()) {
+            return ZX_ERR_NO_MEMORY;
+        }
+
+        layers.push_back(std::move(layer1));
     }
 
     printf("Initializing layers\n");