Merge "hwc2: Derive dataspace on ClientTarget from ColorMode"
diff --git a/config/talos.mk b/config/talos.mk
index a0f1703..0498f50 100644
--- a/config/talos.mk
+++ b/config/talos.mk
@@ -56,11 +56,9 @@
     vendor.display.disable_inline_rotator=1 \
     vendor.display.disable_decimation=1 \
     vendor.display.disable_excl_rect_partial_fb=1 \
-    vendor.display.enable_rotator_ui=1 \
     vendor.display.enable_null_display=0 \
     vendor.display.disable_excl_rect=0 \
     vendor.display.comp_mask=0 \
-    vendor.display.disable_hw_recovery=1 \
     vendor.display.enable_default_color_mode=1
 
 # This matrix should be in column major order, per SurfaceFlinger requirement
diff --git a/config/trinket.mk b/config/trinket.mk
index ced2b4a..cc71042 100644
--- a/config/trinket.mk
+++ b/config/trinket.mk
@@ -32,7 +32,6 @@
 TARGET_USES_HWC2 := true
 TARGET_USES_QCOM_DISPLAY_BSP := true
 TARGET_USES_COLOR_METADATA := true
-TARGET_HAS_WIDE_COLOR_DISPLAY := true
 
 PRODUCT_PROPERTY_OVERRIDES += \
     persist.demo.hdmirotationlock=false \
@@ -41,7 +40,6 @@
     debug.egl.hw=0 \
     debug.sf.latch_unsignaled=1 \
     debug.mdpcomp.logs=0 \
-    debug.sf.enable_hwc_vds=1 \
     ro.vendor.display.cabl=2 \
     vendor.gralloc.disable_ubwc=0 \
     vendor.display.disable_scaler=0 \
@@ -50,7 +48,6 @@
     vendor.display.enable_null_display=0 \
     vendor.display.disable_excl_rect=0 \
     vendor.display.comp_mask=0 \
-    vendor.display.disable_hw_recovery=1 \
     vendor.display.enable_default_color_mode=1
 
 # This matrix should be in column major order, per SurfaceFlinger requirement
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 8cb300a..4a47469 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -584,6 +584,8 @@
   int wmin;
   int hmin;
   bool roi_merge;
+  uint64_t bit_clk_rate;
+  uint32_t transfer_time_us;
 };
 
 /* Per Connector Info*/
@@ -603,13 +605,13 @@
   uint32_t max_linewidth;
   DRMRotation panel_orientation;
   drm_panel_hdr_properties panel_hdr_prop;
-  uint32_t transfer_time_us;
   drm_msm_ext_hdr_properties ext_hdr_prop;
   bool qsync_support;
   // Connection status of this connector
   bool is_connected;
   bool is_wb_ubwc_supported;
   uint32_t topology_control;
+  bool dyn_bitclk_support;
 };
 
 // All DRM Connectors as map<Connector_id , connector_info>
diff --git a/libmemtrack/kgsl.c b/libmemtrack/kgsl.c
index a292d45..e17c520 100644
--- a/libmemtrack/kgsl.c
+++ b/libmemtrack/kgsl.c
@@ -81,7 +81,6 @@
 
         fp = fopen(syspath, "r");
         if (fp == NULL) {
-            fclose(fp);
             return -errno;
         }
 
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 964640f..fc2e3dc 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -316,6 +316,60 @@
     return panel_brightness;
 }
 
+int setDsiClk(int dpy, uint64_t bitClk) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+
+    if(binder != NULL) {
+        inParcel.writeInt32(dpy);
+        inParcel.writeUint64(bitClk);
+        status_t err = binder->dispatch(IQService::SET_DSI_CLK, &inParcel, &outParcel);
+        if(err) {
+            ALOGE("%s() failed with err %d", __FUNCTION__, err);
+        }
+    }
+    return err;
+}
+
+uint64_t getDsiClk(int dpy) {
+    uint64_t dsi_clk = 0;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+
+    if(binder != NULL) {
+        inParcel.writeInt32(dpy);
+        status_t err = binder->dispatch(IQService::GET_DSI_CLK, &inParcel, &outParcel);
+        if(!err) {
+            dsi_clk = outParcel.readUint64();
+        } else {
+            ALOGE("%s() failed with err %d", __FUNCTION__, err);
+        }
+    }
+    return dsi_clk;
+}
+
+int getSupportedBitClk(int dpy, std::vector<uint64_t>& bit_rates) {
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+
+    if(binder != NULL) {
+        inParcel.writeInt32(dpy);
+        status_t err = binder->dispatch(IQService::GET_SUPPORTED_DSI_CLK, &inParcel, &outParcel);
+        if(err) {
+            ALOGE("%s() failed with err %d", __FUNCTION__, err);
+            return err;
+        }
+    }
+
+    int32_t clk_levels = outParcel.readInt32();
+    while (clk_levels > 0) {
+      bit_rates.push_back(outParcel.readUint64());
+      clk_levels--;
+    }
+    return 0;
+}
+
 }// namespace
 
 // ----------------------------------------------------------------------------
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index 8373c90..c0952b0 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -30,6 +30,8 @@
 #ifndef _DISPLAY_CONFIG_H
 #define _DISPLAY_CONFIG_H
 
+#include <vector>
+
 #include <gralloc_priv.h>
 #include <qdMetaData.h>
 #include <hardware/hwcomposer.h>
@@ -160,6 +162,15 @@
 // Retrieves the current panel brightness value
 int getPanelBrightness();
 
+// Sets the specified bit clk value.
+int setDsiClk(int dpy, uint64_t bitClk);
+
+// Retrieves the current bit clk value.
+uint64_t getDsiClk(int dpy);
+
+// Get supported bit clk values.
+int getSupportedBitClk(int dpy, std::vector<uint64_t>& bit_rates);
+
 }; //namespace
 
 
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 11cbf22..569c4ea 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -81,6 +81,9 @@
         SET_COLOR_MODE_WITH_RENDER_INTENT = 39,
         SET_IDLE_PC = 40, // Enable/disable Idle power collapse
         SET_DPPS_AD4_ROI_CONFIG = 41, // Set ad4 roi config for debug
+        SET_DSI_CLK = 42, // Set DSI Clk.
+        GET_DSI_CLK = 43, // Get DSI Clk.
+        GET_SUPPORTED_DSI_CLK = 44, // Get supported DSI Clk.
         COMMAND_LIST_END = 400,
     };
 
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 899a52f..7ef2f6f 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -204,6 +204,12 @@
   uint32_t fps = 0;               //!< Frame rate per second.
   uint32_t vsync_period_ns = 0;   //!< VSync period in nanoseconds.
   bool is_yuv = false;            //!< If the display output is in YUV format.
+
+  bool operator==(const DisplayConfigVariableInfo& info) const {
+    return ((x_pixels == info.x_pixels) && (y_pixels == info.y_pixels) && (x_dpi == info.x_dpi) &&
+            (y_dpi == info.y_dpi) && (fps == info.fps) && (vsync_period_ns == info.vsync_period_ns)
+            && (is_yuv == info.is_yuv));
+  }
 };
 
 /*! @brief Event data associated with VSync event.
@@ -587,11 +593,21 @@
 
   /*! @brief Method to set the color mode by ID. This method is used for debugging only.
 
-  @param[in] mode_name Mode ID which needs to be set
+  @param[in] Mode ID which needs to be set
 
   @return \link DisplayError \endlink
   */
   virtual DisplayError SetColorModeById(int32_t color_mode_id) = 0;
+
+  /*! @brief Method to get the color mode name.
+
+  @param[in] Mode ID
+  @param[out] Mode name
+
+  @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetColorModeName(int32_t mode_id, std::string *mode_name) = 0;
+
   /*! @brief Method to set the color transform
 
     @param[in] length Mode name which needs to be set
@@ -775,12 +791,42 @@
   */
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) = 0;
 
+  /*! @brief Method to query whether it is supprt sspp tonemap.
+
+    @return true if support sspp tonemap.
+  */
+  virtual bool IsSupportSsppTonemap() = 0;
+
   /*
    * Returns a string consisting of a dump of SDM's display and layer related state
    * as programmed to driver
   */
   virtual std::string Dump() = 0;
 
+  /*! @brief Method to dynamically set DSI clock rate.
+
+    @param[in] bit_clk_rate DSI bit clock rate in HZ.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate) = 0;
+
+  /*! @brief Method to get the current DSI clock rate
+
+    @param[out] bit_clk_rate DSI bit clock rate in HZ
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetDynamicDSIClock(uint64_t *bit_clk_rate) = 0;
+
+  /*! @brief Method to get the supported DSI clock rates
+
+      @param[out] bitclk DSI bit clock in HZ
+
+      @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetSupportedDSIClock(std::vector<uint64_t> *bitclk_rates) = 0;
+
  protected:
   virtual ~DisplayInterface() { }
 };
diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h
index 2527d9d..04237a8 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015-2019, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -57,6 +57,7 @@
   kModeSet = BITMAP(10),
   kMultiDispProc = BITMAP(11),
   kMultiDispGetId = BITMAP(12),
+  kSetModeFromClient = BITMAP(13),
   kGetDetailedEnhancerData = BITMAP(21),
   kNoAction = BITMAP(31),
 };
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 89d00c8..2fcae89 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -378,8 +378,10 @@
   float blackness_level = 0.0f;       // Panel's blackness level
   HWColorPrimaries primaries = {};    // WRGB color primaries
   HWPanelOrientation panel_orientation = {};  // Panel Orientation
-  uint32_t transfer_time_us = 0;      // transfer time in micro seconds to panel's active region
-  bool qsync_support = false;         // Specifies panel supports qsync feature or not.
+  uint32_t transfer_time_us = 0;       // transfer time in micro seconds to panel's active region
+  bool qsync_support = false;          // Specifies panel supports qsync feature or not.
+  bool dyn_bitclk_support = false;     // Bit clk can be updated to avoid RF interference.
+  std::vector<uint64_t> bitclk_rates;  // Supported bit clk levels.
 
   bool operator !=(const HWPanelInfo &panel_info) {
     return ((port != panel_info.port) || (mode != panel_info.mode) ||
@@ -397,7 +399,9 @@
             (left_roi_count != panel_info.left_roi_count) ||
             (right_roi_count != panel_info.right_roi_count) ||
             (transfer_time_us != panel_info.transfer_time_us) ||
-            (qsync_support != panel_info.qsync_support));
+            (qsync_support != panel_info.qsync_support) ||
+            (dyn_bitclk_support != panel_info.dyn_bitclk_support) ||
+            (bitclk_rates != panel_info.bitclk_rates));
   }
 
   bool operator ==(const HWPanelInfo &panel_info) {
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 137e3dc..97eb72b 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -923,6 +923,22 @@
   return error;
 }
 
+DisplayError DisplayBase::GetColorModeName(int32_t mode_id, std::string *mode_name) {
+  if (!mode_name) {
+    DLOGE("Invalid parameters");
+    return kErrorParameters;
+  }
+  for (uint32_t i = 0; i < num_color_modes_; i++) {
+    if (color_modes_[i].id == mode_id) {
+      *mode_name = color_modes_[i].name;
+      return kErrorNone;
+    }
+  }
+
+  DLOGE("Failed to get color mode name for mode id = %d", mode_id);
+  return kErrorUndefined;
+}
+
 DisplayError DisplayBase::GetValueOfModeAttribute(const AttrVal &attr, const std::string &type,
                                                   std::string *value) {
   if (!value) {
@@ -1394,7 +1410,8 @@
   uint32_t hw_layers_count = UINT32(hw_layers_.info.hw_layers.size());
 
   for (uint32_t i = 0; i < hw_layers_count; i++) {
-    Layer *sdm_layer = layer_stack->layers.at(hw_layers_.info.index.at(i));
+    uint32_t sdm_layer_index = hw_layers_.info.index.at(i);
+    Layer *sdm_layer = layer_stack->layers.at(sdm_layer_index);
     Layer &hw_layer = hw_layers_.info.hw_layers.at(i);
 
     hw_layer.input_buffer.planes[0].fd = sdm_layer->input_buffer.planes[0].fd;
@@ -1403,6 +1420,12 @@
     hw_layer.input_buffer.size = sdm_layer->input_buffer.size;
     hw_layer.input_buffer.acquire_fence_fd = sdm_layer->input_buffer.acquire_fence_fd;
     hw_layer.input_buffer.handle_id = sdm_layer->input_buffer.handle_id;
+    // TODO(user): Other FBT layer attributes like surface damage, dataspace, secure camera and
+    // secure display flags are also updated during SetClientTarget() called between validate and
+    // commit. Need to revist this and update it accordingly for FBT layer.
+    if (hw_layers_.info.gpu_target_index == sdm_layer_index) {
+      hw_layer.input_buffer.flags.secure = sdm_layer->input_buffer.flags.secure;
+    }
   }
 
   return;
@@ -1555,6 +1578,14 @@
   return kErrorNone;
 }
 
+bool DisplayBase::IsSupportSsppTonemap() {
+  if (hw_resource_info_.src_tone_map.none()) {
+    return false;
+  } else {
+    return true;
+  }
+}
+
 DisplayError DisplayBase::ValidateScaling(uint32_t width, uint32_t height) {
   uint32_t display_width = display_attributes_.x_pixels;
   uint32_t display_height = display_attributes_.y_pixels;
@@ -1766,7 +1797,7 @@
     } else {
       pt.transfer = Transfer_SMPTE_ST2084;
     }
-  } else if ((color_gamut == kDcip3 && dynamic_range == kSdr)) {
+  } else if (color_gamut == kDcip3) {
     pt.primaries = GetColorPrimariesFromAttribute(color_gamut);
     pt.transfer = Transfer_Gamma2_2;
   }
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 35c07a4..6513b08 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -94,11 +94,21 @@
   virtual DisplayError ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
                                             PPDisplayAPIPayload *out_payload,
                                             PPPendingParams *pending_action);
+  virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError GetDynamicDSIClock(uint64_t *bit_clk_rate) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError GetSupportedDSIClock(std::vector<uint64_t> *bitclk_rates) {
+    return kErrorNotSupported;
+  }
   virtual DisplayError GetColorModeCount(uint32_t *mode_count);
   virtual DisplayError GetColorModes(uint32_t *mode_count, std::vector<std::string> *color_modes);
   virtual DisplayError GetColorModeAttr(const std::string &color_mode, AttrVal *attr);
   virtual DisplayError SetColorMode(const std::string &color_mode);
   virtual DisplayError SetColorModeById(int32_t color_mode_id);
+  virtual DisplayError GetColorModeName(int32_t mode_id, std::string *mode_name);
   virtual DisplayError SetColorTransform(const uint32_t length, const double *color_transform);
   virtual DisplayError GetDefaultColorMode(std::string *color_mode);
   virtual DisplayError ApplyDefaultDisplayMode(void);
@@ -134,6 +144,7 @@
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) {
     return kErrorNotSupported;
   }
+  virtual bool IsSupportSsppTonemap();
 
  protected:
   const char *kBt2020Pq = "bt2020_pq";
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index a28c57b..ab6ec16 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -294,6 +294,9 @@
   if ((current_refresh_rate_ != refresh_rate) || handle_idle_timeout_) {
     DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
     if (error != kErrorNone) {
+      // Attempt to update refresh rate can fail if rf interfenence is detected.
+      // Just drop min fps settting for now.
+      handle_idle_timeout_ = false;
       return error;
     }
   }
@@ -564,5 +567,41 @@
   return hw_intf_->ControlIdlePowerCollapse(enable, synchronous);
 }
 
+DisplayError DisplayBuiltIn::GetSupportedDSIClock(std::vector<uint64_t> *bitclk_rates) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!hw_panel_info_.dyn_bitclk_support) {
+    return kErrorNotSupported;
+  }
+
+  *bitclk_rates = hw_panel_info_.bitclk_rates;
+  return kErrorNone;
+}
+
+DisplayError DisplayBuiltIn::SetDynamicDSIClock(uint64_t bit_clk_rate) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!hw_panel_info_.dyn_bitclk_support) {
+    return kErrorNotSupported;
+  }
+
+  uint64_t current_clk = 0;
+  std::vector<uint64_t> &clk_rates = hw_panel_info_.bitclk_rates;
+  GetDynamicDSIClock(&current_clk);
+  bool valid = std::find(clk_rates.begin(), clk_rates.end(), bit_clk_rate) != clk_rates.end();
+  if (current_clk == bit_clk_rate || !valid) {
+    DLOGI("Invalid setting %d, Clk. already set %d", !valid, (current_clk == bit_clk_rate));
+    return kErrorNone;
+  }
+
+  return hw_intf_->SetDynamicDSIClock(bit_clk_rate);
+}
+
+DisplayError DisplayBuiltIn::GetDynamicDSIClock(uint64_t *bit_clk_rate) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!hw_panel_info_.dyn_bitclk_support) {
+    return kErrorNotSupported;
+  }
+
+  return hw_intf_->GetDynamicDSIClock(bit_clk_rate);
+}
 
 }  // namespace sdm
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index 76aedae..ffebcb3 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -74,6 +74,9 @@
   virtual DisplayError SetDisplayDppsAdROI(void *payload);
   virtual DisplayError SetQSyncMode(QSyncMode qsync_mode);
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous);
+  virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate);
+  virtual DisplayError GetDynamicDSIClock(uint64_t *bit_clk_rate);
+  virtual DisplayError GetSupportedDSIClock(std::vector<uint64_t> *bitclk_rates);
 
   // Implement the HWEventHandlers
   virtual DisplayError VSync(int64_t timestamp);
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 2675f71..7988405 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -648,6 +648,7 @@
   hw_panel_info_.min_roi_width = connector_info_.modes[index].wmin;
   hw_panel_info_.min_roi_height = connector_info_.modes[index].hmin;
   hw_panel_info_.needs_roi_merge = connector_info_.modes[index].roi_merge;
+  hw_panel_info_.transfer_time_us = connector_info_.modes[index].transfer_time_us;
   hw_panel_info_.dynamic_fps = connector_info_.dynamic_fps;
   hw_panel_info_.qsync_support = connector_info_.qsync_support;
   drmModeModeInfo current_mode = connector_info_.modes[current_mode_index_].mode;
@@ -686,7 +687,7 @@
   hw_panel_info_.primaries.green[1] = connector_info_.panel_hdr_prop.display_primaries[5];
   hw_panel_info_.primaries.blue[0] = connector_info_.panel_hdr_prop.display_primaries[6];
   hw_panel_info_.primaries.blue[1] = connector_info_.panel_hdr_prop.display_primaries[7];
-  hw_panel_info_.transfer_time_us = connector_info_.transfer_time_us;
+  hw_panel_info_.dyn_bitclk_support = connector_info_.dyn_bitclk_support;
 
   // no supprt for 90 rotation only flips or 180 supported
   hw_panel_info_.panel_orientation.rotation = 0;
@@ -714,6 +715,7 @@
   DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split,
         hw_panel_info_.split_info.right_split);
   DLOGI("Panel Transfer time = %d us", hw_panel_info_.transfer_time_us);
+  DLOGI("Dynamic Bit Clk Support = %d", hw_panel_info_.dyn_bitclk_support);
 }
 
 void HWDeviceDRM::GetHWDisplayPortAndMode() {
@@ -955,6 +957,7 @@
   DRMSecurityLevel crtc_security_level = DRMSecurityLevel::SECURE_NON_SECURE;
   uint32_t index = current_mode_index_;
   drmModeModeInfo current_mode = connector_info_.modes[index].mode;
+  uint64_t current_bit_clk = connector_info_.modes[index].bit_clk_rate;
 
   solid_fills_.clear();
 
@@ -1110,6 +1113,7 @@
     for (uint32_t mode_index = 0; mode_index < connector_info_.modes.size(); mode_index++) {
       if ((current_mode.vdisplay == connector_info_.modes[mode_index].mode.vdisplay) &&
           (current_mode.hdisplay == connector_info_.modes[mode_index].mode.hdisplay) &&
+          (current_bit_clk == connector_info_.modes[mode_index].bit_clk_rate) &&
           (vrefresh_ == connector_info_.modes[mode_index].mode.vrefresh)) {
         current_mode = connector_info_.modes[mode_index].mode;
         break;
@@ -1117,6 +1121,18 @@
     }
   }
 
+  if (bit_clk_rate_) {
+    for (uint32_t mode_index = 0; mode_index < connector_info_.modes.size(); mode_index++) {
+      if ((current_mode.vdisplay == connector_info_.modes[mode_index].mode.vdisplay) &&
+          (current_mode.hdisplay == connector_info_.modes[mode_index].mode.hdisplay) &&
+          (current_mode.vrefresh == connector_info_.modes[mode_index].mode.vrefresh) &&
+          (bit_clk_rate_ == connector_info_.modes[mode_index].bit_clk_rate)) {
+        current_mode = connector_info_.modes[mode_index].mode;
+        break;
+      }
+    }
+  }
+
   if (first_cycle_) {
     drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_TOPOLOGY_CONTROL, token_.conn_id,
                               topology_control_);
@@ -1306,9 +1322,11 @@
   if (vrefresh_) {
     // Update current mode index if refresh rate is changed
     drmModeModeInfo current_mode = connector_info_.modes[current_mode_index_].mode;
+    uint64_t current_bit_clk = connector_info_.modes[current_mode_index_].bit_clk_rate;
     for (uint32_t mode_index = 0; mode_index < connector_info_.modes.size(); mode_index++) {
       if ((current_mode.vdisplay == connector_info_.modes[mode_index].mode.vdisplay) &&
           (current_mode.hdisplay == connector_info_.modes[mode_index].mode.hdisplay) &&
+          (current_bit_clk == connector_info_.modes[mode_index].bit_clk_rate) &&
           (vrefresh_ == connector_info_.modes[mode_index].mode.vrefresh)) {
         current_mode_index_ = mode_index;
         break;
@@ -1317,6 +1335,21 @@
     vrefresh_ = 0;
   }
 
+  if (bit_clk_rate_) {
+    // Update current mode index if bit clk rate is changed.
+    drmModeModeInfo current_mode = connector_info_.modes[current_mode_index_].mode;
+    for (uint32_t mode_index = 0; mode_index < connector_info_.modes.size(); mode_index++) {
+      if ((current_mode.vdisplay == connector_info_.modes[mode_index].mode.vdisplay) &&
+          (current_mode.hdisplay == connector_info_.modes[mode_index].mode.hdisplay) &&
+          (current_mode.vrefresh == connector_info_.modes[mode_index].mode.vrefresh) &&
+          (bit_clk_rate_ == connector_info_.modes[mode_index].bit_clk_rate)) {
+        current_mode_index_ = mode_index;
+        break;
+      }
+    }
+    bit_clk_rate_ = 0;
+  }
+
   first_cycle_ = false;
   update_mode_ = false;
 
@@ -1519,11 +1552,19 @@
 }
 
 DisplayError HWDeviceDRM::SetRefreshRate(uint32_t refresh_rate) {
+  if (bit_clk_rate_) {
+    // bit rate update pending.
+    // Defer any refresh rate setting.
+    return kErrorNotSupported;
+  }
+
   // Check if requested refresh rate is valid
   drmModeModeInfo current_mode = connector_info_.modes[current_mode_index_].mode;
+  uint64_t current_bit_clk = connector_info_.modes[current_mode_index_].bit_clk_rate;
   for (uint32_t mode_index = 0; mode_index < connector_info_.modes.size(); mode_index++) {
     if ((current_mode.vdisplay == connector_info_.modes[mode_index].mode.vdisplay) &&
         (current_mode.hdisplay == connector_info_.modes[mode_index].mode.hdisplay) &&
+        (current_bit_clk == connector_info_.modes[mode_index].bit_clk_rate) &&
         (refresh_rate == connector_info_.modes[mode_index].mode.vrefresh)) {
       vrefresh_ = refresh_rate;
       DLOGV_IF(kTagDriverConfig, "Set refresh rate to %d", refresh_rate);
@@ -1938,4 +1979,12 @@
   drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_ROI, token_.conn_id, 1, &conn_rects);
 }
 
+DisplayError HWDeviceDRM::SetDynamicDSIClock(uint64_t bit_clk_rate) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::GetDynamicDSIClock(uint64_t *bit_clk_rate) {
+  return kErrorNotSupported;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index a5f88c3..f8ae241 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -120,6 +120,8 @@
     return kErrorNotSupported;
   }
   virtual DisplayError SetDisplayDppsAdROI(void *payload) { return kErrorNotSupported; }
+  virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate);
+  virtual DisplayError GetDynamicDSIClock(uint64_t *bit_clk_rate);
 
   enum {
     kHWEventVSync,
@@ -218,14 +220,15 @@
   uint64_t debug_dump_count_ = 0;
   bool synchronous_commit_ = false;
   uint32_t topology_control_ = 0;
+  uint32_t vrefresh_ = 0;
+  uint64_t bit_clk_rate_ = 0;
+  bool update_mode_ = false;
 
  private:
   std::string interface_str_ = "DSI";
   bool resolution_switch_enabled_ = false;
-  uint32_t vrefresh_ = 0;
   bool autorefresh_ = false;
   std::unique_ptr<HWColorManagerDrm> hw_color_mgr_ = {};
-  bool update_mode_ = false;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index 076cde3..ecd0651 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -62,11 +62,48 @@
 
   scalar_data_.resize(hw_resource_.hw_dest_scalar_info.count);
   dest_scalar_cache_.resize(hw_resource_.hw_dest_scalar_info.count);
+  PopulateBitClkRates();
 
   topology_control_ = UINT32(sde_drm::DRMTopologyControl::DSPP);
   if (hw_panel_info_.is_primary_panel) {
     topology_control_ |= UINT32(sde_drm::DRMTopologyControl::DEST_SCALER);
   }
+
+  return kErrorNone;
+}
+
+void HWPeripheralDRM::PopulateBitClkRates() {
+  if (!hw_panel_info_.dyn_bitclk_support) {
+    return;
+  }
+
+  // Group all bit_clk_rates corresponding to DRM_PREFERRED mode.
+  uint32_t width = connector_info_.modes[current_mode_index_].mode.hdisplay;
+  uint32_t height = connector_info_.modes[current_mode_index_].mode.vdisplay;
+
+  for (auto &mode_info : connector_info_.modes) {
+    auto &mode = mode_info.mode;
+    if (mode.hdisplay == width && mode.vdisplay == height) {
+      bitclk_rates_.push_back(mode_info.bit_clk_rate);
+      DLOGI("Possible bit_clk_rates %d", mode_info.bit_clk_rate);
+    }
+  }
+
+  hw_panel_info_.bitclk_rates = bitclk_rates_;
+  DLOGI("bit_clk_rates Size %d", bitclk_rates_.size());
+}
+
+DisplayError HWPeripheralDRM::SetDynamicDSIClock(uint64_t bit_clk_rate) {
+  bit_clk_rate_ = bit_clk_rate;
+  update_mode_ = true;
+
+  return kErrorNone;
+}
+
+DisplayError HWPeripheralDRM::GetDynamicDSIClock(uint64_t *bit_clk_rate) {
+  // Update bit_rate corresponding to current refresh rate.
+  *bit_clk_rate = (uint32_t)connector_info_.modes[current_mode_index_].bit_clk_rate;
+
   return kErrorNone;
 }
 
@@ -290,6 +327,9 @@
         drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE,
                                   cwb_config_.token.conn_id, fence);
       }
+    } else {
+      // Tear down the Concurrent Writeback topology.
+      drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, cwb_config_.token.conn_id, 0);
     }
   }
 }
@@ -361,9 +401,7 @@
 void HWPeripheralDRM::PostCommitConcurrentWriteback(LayerBuffer *output_buffer) {
   bool enabled = hw_resource_.has_concurrent_writeback && output_buffer;
 
-  if (enabled) {
-    // Tear down the Concurrent Writeback topology.
-    drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, cwb_config_.token.conn_id, 0);
+  if (!enabled) {
     drm_mgr_intf_->UnregisterDisplay(cwb_config_.token);
     cwb_config_.enabled = false;
     registry_.Clear();
@@ -404,6 +442,14 @@
   return kErrorNone;
 }
 
+DisplayError HWPeripheralDRM::SetDisplayAttributes(uint32_t index) {
+  HWDeviceDRM::SetDisplayAttributes(index);
+  // update bit clk rates.
+  hw_panel_info_.bitclk_rates = bitclk_rates_;
+
+  return kErrorNone;
+}
+
 DisplayError HWPeripheralDRM::SetDisplayDppsAdROI(void *payload) {
   DisplayError err = kErrorNone;
   struct sde_drm::DppsFeaturePayload feature_payload = {};
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.h b/sdm/libs/core/drm/hw_peripheral_drm.h
index 00edf2a..12d2e6c 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.h
+++ b/sdm/libs/core/drm/hw_peripheral_drm.h
@@ -57,6 +57,9 @@
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous);
   virtual DisplayError PowerOn(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError SetDisplayDppsAdROI(void *payload);
+  virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate);
+  virtual DisplayError GetDynamicDSIClock(uint64_t *bit_clk_rate);
+  virtual DisplayError SetDisplayAttributes(uint32_t index);
 
  private:
   void SetDestScalarData(HWLayersInfo hw_layer_info, bool validate);
@@ -82,6 +85,8 @@
   std::vector<DestScalarCache> dest_scalar_cache_ = {};
   drm_msm_ad4_roi_cfg ad4_roi_cfg_ = {};
   bool needs_ds_update_ = false;
+  void PopulateBitClkRates();
+  std::vector<uint64_t> bitclk_rates_;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 1cc79f6..faee5a3 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -1406,5 +1406,13 @@
   return kErrorNone;
 }
 
+DisplayError HWDevice::SetDynamicDSIClock(uint64_t bit_clk_rate) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDevice::GetDynamicDSIClock(uint64_t *bit_clk_rate) {
+  return kErrorNotSupported;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index f5714cf..dad5fe5 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -110,6 +110,8 @@
     return kErrorNotSupported;
   }
   virtual DisplayError SetDisplayDppsAdROI(void *payload) { return kErrorNotSupported; }
+  virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate);
+  virtual DisplayError GetDynamicDSIClock(uint64_t *bit_clk_rate);
 
   enum {
     kHWEventVSync,
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 5b38621..119a95f 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -121,6 +121,8 @@
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event, HWLayers *hw_layers) = 0;
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) = 0;
   virtual DisplayError SetDisplayDppsAdROI(void *payload) = 0;
+  virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate) = 0;
+  virtual DisplayError GetDynamicDSIClock(uint64_t *bit_clk_rate) = 0;
 
  protected:
   virtual ~HWInterface() { }
diff --git a/sdm/libs/hwc2/display_null.h b/sdm/libs/hwc2/display_null.h
index 3aa5557..29f31b0 100644
--- a/sdm/libs/hwc2/display_null.h
+++ b/sdm/libs/hwc2/display_null.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -56,6 +56,7 @@
   virtual bool IsUnderscanSupported() { return true; }
   virtual void SetIdleTimeoutMs(uint32_t active_ms) { }
   virtual std::string Dump() { return ""; }
+  virtual bool IsSupportSsppTonemap() { return false; }
 
   MAKE_NO_OP(Commit(LayerStack *))
   MAKE_NO_OP(GetDisplayState(DisplayState *))
@@ -79,6 +80,7 @@
   MAKE_NO_OP(GetColorModeAttr(const std::string &, AttrVal *))
   MAKE_NO_OP(SetColorMode(const std::string &))
   MAKE_NO_OP(SetColorModeById(int32_t))
+  MAKE_NO_OP(GetColorModeName(int32_t, std::string *))
   MAKE_NO_OP(SetColorTransform(const uint32_t, const double *))
   MAKE_NO_OP(GetDefaultColorMode(std::string *))
   MAKE_NO_OP(ApplyDefaultDisplayMode())
@@ -98,6 +100,9 @@
   MAKE_NO_OP(SetQSyncMode(QSyncMode))
   MAKE_NO_OP(ControlIdlePowerCollapse(bool, bool))
   MAKE_NO_OP(SetDisplayDppsAdROI(void *))
+  MAKE_NO_OP(SetDynamicDSIClock(uint64_t bit_clk_rate))
+  MAKE_NO_OP(GetDynamicDSIClock(uint64_t *bit_clk_rate))
+  MAKE_NO_OP(GetSupportedDSIClock(std::vector<uint64_t> *bitclk_rates))
 
   DisplayConfigVariableInfo default_variable_config_ = {};
   DisplayConfigFixedInfo default_fixed_config_ = {};
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 8e4af2b..c7fab21 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -133,7 +133,7 @@
     return HWC2::Error::None;
   }
 
-  auto mode_string = color_mode_map_[mode][intent];
+  auto mode_string = color_mode_map_[mode][intent][kSdrType];
   DisplayError error = display_intf_->SetColorMode(mode_string);
   if (error != kErrorNone) {
     DLOGE("failed for mode = %d intent = %d name = %s", mode, intent, mode_string.c_str());
@@ -166,26 +166,37 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCColorMode::ApplyCurrentColorModeWithRenderIntent() {
+HWC2::Error HWCColorMode::ApplyCurrentColorModeWithRenderIntent(bool hdr_present) {
   if (!apply_mode_) {
-    return HWC2::Error::None;
+    if ((hdr_present && curr_dynamic_range_ == kHdrType) ||
+      (!hdr_present && curr_dynamic_range_ == kSdrType))
+      return HWC2::Error::None;
   }
 
   apply_mode_ = false;
-  auto mode_string = color_mode_map_[current_color_mode_][current_render_intent_];
-  DisplayError error = display_intf_->SetColorMode(mode_string);
-  if (error != kErrorNone) {
-    DLOGE("Failed for mode = %d intent = %d name = %s", current_color_mode_,
-          current_render_intent_, mode_string.c_str());
-    return HWC2::Error::Unsupported;
+  curr_dynamic_range_ = (hdr_present)? kHdrType : kSdrType;
+
+  // select mode according to the blend space and dynamic range
+  std::string mode_string = preferred_mode_[current_color_mode_][curr_dynamic_range_];
+  if (mode_string.empty()) {
+    mode_string = color_mode_map_[current_color_mode_][current_render_intent_][curr_dynamic_range_];
+    if (mode_string.empty() &&
+      current_color_mode_ == ColorMode::DISPLAY_P3 &&
+      curr_dynamic_range_ == kHdrType) {
+      // fall back to display_p3 SDR mode if there is no HDR mode
+      mode_string = color_mode_map_[current_color_mode_][current_render_intent_][kSdrType];
+    }
   }
 
-  // The mode does not have the PCC configured, restore the transform
-  RestoreColorTransform();
-  DLOGV_IF(kTagClient, "Successfully applied mode = %d intent = %d name = %s",
-           current_color_mode_, current_render_intent_, mode_string.c_str());
+  auto error = SetPreferredColorModeInternal(mode_string, false, NULL, NULL);
+  if (error == HWC2::Error::None) {
+    // The mode does not have the PCC configured, restore the transform
+    RestoreColorTransform();
+    DLOGV_IF(kTagClient, "Successfully applied mode = %d intent = %d range = %d name = %s",
+             current_color_mode_, current_render_intent_, curr_dynamic_range_, mode_string.c_str());
+  }
 
-  return HWC2::Error::None;
+  return error;
 }
 
 HWC2::Error HWCColorMode::SetColorModeById(int32_t color_mode_id) {
@@ -198,6 +209,84 @@
   return HWC2::Error::None;
 }
 
+HWC2::Error HWCColorMode::SetPreferredColorModeInternal(const std::string &mode_string,
+              bool from_client, ColorMode *color_mode, DynamicRangeType *dynamic_range) {
+  DisplayError error = kErrorNone;
+  ColorMode mode = ColorMode::NATIVE;
+  DynamicRangeType range = kSdrType;
+
+  if (from_client) {
+    // get blend space and dynamic range of the mode
+    AttrVal attr;
+    std::string color_gamut_string, dynamic_range_string;
+    error = display_intf_->GetColorModeAttr(mode_string, &attr);
+    if (error) {
+      DLOGE("Failed to get mode attributes for mode %d", mode_string.c_str());
+      return HWC2::Error::BadParameter;
+    }
+
+    if (!attr.empty()) {
+      for (auto &it : attr) {
+        if (it.first.find(kColorGamutAttribute) != std::string::npos) {
+          color_gamut_string = it.second;
+        } else if (it.first.find(kDynamicRangeAttribute) != std::string::npos) {
+          dynamic_range_string = it.second;
+        }
+      }
+    }
+
+    if (color_gamut_string.empty() || dynamic_range_string.empty()) {
+      DLOGE("Invalid attributes for mode %s: color_gamut = %s, dynamic_range = %s",
+            mode_string.c_str(), color_gamut_string.c_str(), dynamic_range_string.c_str());
+      return HWC2::Error::BadParameter;
+    }
+
+    if (color_gamut_string == kDcip3) {
+      mode = ColorMode::DISPLAY_P3;
+    } else if (color_gamut_string == kSrgb) {
+      mode = ColorMode::SRGB;
+    }
+    if (dynamic_range_string == kHdr) {
+      range = kHdrType;
+    }
+
+    if (color_mode) {
+      *color_mode = mode;
+    }
+    if (dynamic_range) {
+      *dynamic_range = range;
+    }
+  }
+
+  // apply the mode from client if it matches
+  // the current blend space and dynamic range,
+  // skip the check for the mode from SF.
+  if ((!from_client) || (current_color_mode_ == mode && curr_dynamic_range_ == range)) {
+    DLOGI("Applying mode: %s", mode_string.c_str());
+    error = display_intf_->SetColorMode(mode_string);
+    if (error != kErrorNone) {
+      DLOGE("Failed to apply mode: %s", mode_string.c_str());
+      return HWC2::Error::BadParameter;
+    }
+  }
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCColorMode::SetColorModeFromClientApi(std::string mode_string) {
+  ColorMode mode = ColorMode::NATIVE;
+  DynamicRangeType range = kSdrType;
+
+  auto error = SetPreferredColorModeInternal(mode_string, true, &mode, &range);
+  if (error == HWC2::Error::None) {
+    preferred_mode_[mode][range] = mode_string;
+    DLOGV_IF(kTagClient, "Put mode %s(mode %d, range %d) into preferred_mode",
+             mode_string.c_str(), mode, range);
+  }
+
+  return error;
+}
+
 HWC2::Error HWCColorMode::RestoreColorTransform() {
   DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, color_matrix_);
   if (error != kErrorNone) {
@@ -224,21 +313,14 @@
   return status;
 }
 
-void HWCColorMode::FindRenderIntent(const ColorMode &mode, const std::string &mode_string) {
-  auto intent = RenderIntent::COLORIMETRIC;
-  if (mode_string.find("enhanced") != std::string::npos) {
-    intent = RenderIntent::ENHANCE;
-  }
-  color_mode_map_[mode][intent] = mode_string;
-}
-
 void HWCColorMode::PopulateColorModes() {
   uint32_t color_mode_count = 0;
   // SDM returns modes which have attributes defining mode and rendering intent
   DisplayError error = display_intf_->GetColorModeCount(&color_mode_count);
   if (error != kErrorNone || (color_mode_count == 0)) {
     DLOGW("GetColorModeCount failed, use native color mode");
-    color_mode_map_[ColorMode::NATIVE][RenderIntent::COLORIMETRIC] = "hal_native_identity";
+    color_mode_map_[ColorMode::NATIVE][RenderIntent::COLORIMETRIC]
+                   [kSdrType] = "hal_native_identity";
     return;
   }
 
@@ -268,42 +350,55 @@
       DLOGV_IF(kTagClient, "color_gamut : %s, dynamic_range : %s, pic_quality : %s",
                color_gamut.c_str(), dynamic_range.c_str(), pic_quality.c_str());
       if (color_gamut == kNative) {
-        color_mode_map_[ColorMode::NATIVE][RenderIntent::COLORIMETRIC] = mode_string;
+        color_mode_map_[ColorMode::NATIVE][RenderIntent::COLORIMETRIC][kSdrType] = mode_string;
       }
 
       if (color_gamut == kSrgb && dynamic_range == kSdr) {
         if (pic_quality == kStandard) {
-          color_mode_map_[ColorMode::SRGB][RenderIntent::COLORIMETRIC] = mode_string;
+          color_mode_map_[ColorMode::SRGB][RenderIntent::COLORIMETRIC][kSdrType] = mode_string;
         }
         if (pic_quality == kEnhanced) {
-          color_mode_map_[ColorMode::SRGB][RenderIntent::ENHANCE] = mode_string;
+          color_mode_map_[ColorMode::SRGB][RenderIntent::ENHANCE][kSdrType] = mode_string;
         }
       }
 
       if (color_gamut == kDcip3 && dynamic_range == kSdr) {
         if (pic_quality == kStandard) {
-          color_mode_map_[ColorMode::DISPLAY_P3][RenderIntent::COLORIMETRIC] = mode_string;
+          color_mode_map_[ColorMode::DISPLAY_P3][RenderIntent::COLORIMETRIC]
+                         [kSdrType] = mode_string;
         }
         if (pic_quality == kEnhanced) {
-          color_mode_map_[ColorMode::DISPLAY_P3][RenderIntent::ENHANCE] = mode_string;
+          color_mode_map_[ColorMode::DISPLAY_P3][RenderIntent::ENHANCE]
+                         [kSdrType] = mode_string;
         }
       }
       if (color_gamut == kDcip3 && pic_quality == kStandard && dynamic_range == kHdr) {
-        color_mode_map_[ColorMode::BT2100_PQ][RenderIntent::TONE_MAP_COLORIMETRIC] = mode_string;
-        color_mode_map_[ColorMode::BT2100_HLG][RenderIntent::TONE_MAP_COLORIMETRIC] = mode_string;
+        if (display_intf_->IsSupportSsppTonemap()) {
+          color_mode_map_[ColorMode::DISPLAY_P3][RenderIntent::COLORIMETRIC]
+                         [kHdrType] = mode_string;
+        } else {
+          color_mode_map_[ColorMode::BT2100_PQ][RenderIntent::TONE_MAP_COLORIMETRIC]
+                         [kHdrType] = mode_string;
+          color_mode_map_[ColorMode::BT2100_HLG][RenderIntent::TONE_MAP_COLORIMETRIC]
+                         [kHdrType] = mode_string;
+        }
       } else if (color_gamut == kBt2020) {
         if (transfer == kSt2084) {
-          color_mode_map_[ColorMode::BT2100_PQ][RenderIntent::COLORIMETRIC] = mode_string;
+          color_mode_map_[ColorMode::BT2100_PQ][RenderIntent::COLORIMETRIC]
+                         [kHdrType] = mode_string;
         } else if (transfer == kHlg) {
-          color_mode_map_[ColorMode::BT2100_HLG][RenderIntent::COLORIMETRIC] = mode_string;
+          color_mode_map_[ColorMode::BT2100_HLG][RenderIntent::COLORIMETRIC]
+                         [kHdrType] = mode_string;
         } else if (transfer == kGamma2_2) {
-          color_mode_map_[ColorMode::BT2020][RenderIntent::COLORIMETRIC] = mode_string;
+          color_mode_map_[ColorMode::BT2020][RenderIntent::COLORIMETRIC]
+                         [kHdrType] = mode_string;
         }
       }
     } else {
       // Look at the mode names, if no attributes are found
       if (mode_string.find("hal_native") != std::string::npos) {
-        color_mode_map_[ColorMode::NATIVE][RenderIntent::COLORIMETRIC] = mode_string;
+        color_mode_map_[ColorMode::NATIVE][RenderIntent::COLORIMETRIC]
+                       [kSdrType] = mode_string;
       }
     }
   }
@@ -321,9 +416,11 @@
       // get the default mode corresponding android_color_mode_t
       for (auto &it_mode : color_mode_map_) {
         for (auto &it : it_mode.second) {
-          if (it.second == default_color_mode) {
-            found = true;
-            break;
+          for (auto &it_range : it.second) {
+            if (it_range.second == default_color_mode) {
+              found = true;
+              break;
+            }
           }
         }
         if (found) {
@@ -345,13 +442,22 @@
   *os << "color modes supported: \n";
   for (auto it : color_mode_map_) {
     *os << "mode: " << static_cast<int32_t>(it.first) << " RIs { ";
-    for (auto rit : color_mode_map_[it.first]) {
-      *os << static_cast<int32_t>(rit.first) << " ";
+    for (auto render_intent_it : color_mode_map_[it.first]) {
+      *os << static_cast<int32_t>(render_intent_it.first) << " dynamic_range [ ";
+      for (auto range_it : color_mode_map_[it.first][render_intent_it.first]) {
+        *os << static_cast<int32_t>(range_it.first) << " ";
+      }
+      *os << "] ";
     }
     *os << "} \n";
   }
   *os << "current mode: " << static_cast<uint32_t>(current_color_mode_) << std::endl;
   *os << "current render_intent: " << static_cast<uint32_t>(current_render_intent_) << std::endl;
+  if (curr_dynamic_range_ == kHdrType) {
+    *os << "current dynamic_range: HDR" << std::endl;
+  } else {
+    *os << "current dynamic_range: SDR" << std::endl;
+  }
   *os << "current transform: ";
   for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
     if (i % 4 == 0) {
@@ -430,6 +536,8 @@
     return -EINVAL;
   }
 
+  UpdateConfigs();
+
   tone_mapper_ = new HWCToneMapper(buffer_allocator_);
 
   display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
@@ -448,6 +556,36 @@
   return 0;
 }
 
+void HWCDisplay::UpdateConfigs() {
+  // SF doesnt care about dynamic bit clk support.
+  // Exposing all configs will result in getting/setting of redundant configs.
+
+  // For each config store the corresponding index which client understands.
+  hwc_config_map_.resize(num_configs_);
+
+  for (uint32_t i = 0; i < num_configs_; i++) {
+    DisplayConfigVariableInfo info = {};
+    GetDisplayAttributesForConfig(INT(i), &info);
+    bool config_exists = false;
+    for (auto &config : variable_config_map_) {
+      if (config.second == info) {
+        config_exists = true;
+        hwc_config_map_.at(i) = config.first;
+        break;
+      }
+    }
+
+    if (!config_exists) {
+      variable_config_map_[i] = info;
+      hwc_config_map_.at(i) = i;
+    }
+  }
+
+  // Update num config count.
+  num_configs_ = UINT32(variable_config_map_.size());
+  DLOGI("num_configs = %d", num_configs_);
+}
+
 int HWCDisplay::Deinit() {
   if (null_display_mode_) {
     delete static_cast<DisplayNull *>(display_intf_);
@@ -866,8 +1004,14 @@
   }
 
   *out_num_configs = std::min(*out_num_configs, num_configs_);
-  for (uint32_t i = 0; i < *out_num_configs; i++) {
-    out_configs[i] = i;
+
+  // Expose all unique config ids to cleint.
+  uint32_t i = 0;
+  for (auto &info : variable_config_map_) {
+    if (i == *out_num_configs) {
+      break;
+    }
+    out_configs[i++] = info.first;
   }
 
   return HWC2::Error::None;
@@ -875,12 +1019,12 @@
 
 HWC2::Error HWCDisplay::GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
                                             int32_t *out_value) {
-  DisplayConfigVariableInfo variable_config;
-  if (GetDisplayAttributesForConfig(INT(config), &variable_config) != kErrorNone) {
+  if (variable_config_map_.find(config) == variable_config_map_.end()) {
     DLOGE("Get variable config failed");
     return HWC2::Error::BadDisplay;
   }
 
+  DisplayConfigVariableInfo variable_config = variable_config_map_.at(config);
   switch (attribute) {
     case HWC2::Attribute::VsyncPeriod:
       *out_value = INT32(variable_config.vsync_period_ns);
@@ -982,6 +1126,9 @@
   }
 
   GetActiveDisplayConfig(out_config);
+  if (*out_config < hwc_config_map_.size()) {
+    *out_config = hwc_config_map_.at(*out_config);
+  }
   return HWC2::Error::None;
 }
 
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 8c825ca..3a3401a 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -78,16 +78,16 @@
   HWC2::Error GetRenderIntents(ColorMode mode, uint32_t *out_num_intents, RenderIntent *out_modes);
   HWC2::Error SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
   HWC2::Error SetColorModeById(int32_t color_mode_id);
+  HWC2::Error SetColorModeFromClientApi(std::string mode_string);
   HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint);
   HWC2::Error RestoreColorTransform();
   ColorMode GetCurrentColorMode() { return current_color_mode_; }
-  HWC2::Error ApplyCurrentColorModeWithRenderIntent();
+  HWC2::Error ApplyCurrentColorModeWithRenderIntent(bool hdr_present);
   HWC2::Error CacheColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
 
  private:
   static const uint32_t kColorTransformMatrixCount = 16;
   void PopulateColorModes();
-  void FindRenderIntent(const ColorMode &mode, const std::string &mode_string);
   template <class T>
   void CopyColorTransformMatrix(const T *input_matrix, double *output_matrix) {
     for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
@@ -96,18 +96,23 @@
   }
   HWC2::Error ApplyDefaultColorMode();
   HWC2::Error ValidateColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
+  HWC2::Error SetPreferredColorModeInternal(const std::string &mode_string, bool from_client,
+    ColorMode *color_mode, DynamicRangeType *dynamic_range);
 
   DisplayInterface *display_intf_ = NULL;
   bool apply_mode_ = false;
   ColorMode current_color_mode_ = ColorMode::NATIVE;
   RenderIntent current_render_intent_ = RenderIntent::COLORIMETRIC;
-  typedef std::map<RenderIntent, std::string> RenderIntentMap;
-  // Initialize supported mode/render intent combination
+  DynamicRangeType curr_dynamic_range_ = kSdrType;
+  typedef std::map<DynamicRangeType, std::string> DynamicRangeMap;
+  typedef std::map<RenderIntent, DynamicRangeMap> RenderIntentMap;
+  // Initialize supported mode/render intent/dynamic range combination
   std::map<ColorMode, RenderIntentMap> color_mode_map_ = {};
   double color_matrix_[kColorTransformMatrixCount] = { 1.0, 0.0, 0.0, 0.0, \
                                                        0.0, 1.0, 0.0, 0.0, \
                                                        0.0, 0.0, 1.0, 0.0, \
                                                        0.0, 0.0, 0.0, 1.0 };
+  std::map<ColorMode, DynamicRangeMap> preferred_mode_ = {};
 };
 
 class HWCDisplay : public DisplayEventHandler {
@@ -219,6 +224,9 @@
   bool HWCClientNeedsValidate() {
     return (has_client_composition_ || layer_stack_.flags.single_buffered_layer_present);
   }
+  virtual HWC2::Error SetColorModeFromClientApi(int32_t color_mode_id) {
+    return HWC2::Error::Unsupported;
+  }
 
   // HWC2 APIs
   virtual HWC2::Error AcceptDisplayChanges(void);
@@ -244,6 +252,15 @@
                                                const double *matrix) {
     return HWC2::Error::Unsupported;
   }
+  virtual DisplayError SetDynamicDSIClock(uint64_t bitclk) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError GetDynamicDSIClock(uint64_t *bitclk) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError GetSupportedDSIClock(std::vector<uint64_t> *bitclk) {
+    return kErrorNotSupported;
+  }
   virtual HWC2::Error GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs);
   virtual HWC2::Error GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
                                           int32_t *out_value);
@@ -311,6 +328,7 @@
   const char *GetDisplayString();
   void MarkLayersForGPUBypass(void);
   void MarkLayersForClientComposition(void);
+  void UpdateConfigs();
   virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
   uint32_t GetUpdatingLayersCount(void);
   bool IsLayerUpdating(HWCLayer *layer);
@@ -372,6 +390,8 @@
   bool pending_commit_ = false;
   bool is_cmd_mode_ = false;
   bool partial_update_enabled_ = false;
+  std::map<uint32_t, DisplayConfigVariableInfo> variable_config_map_;
+  std::vector<uint32_t> hwc_config_map_;
 
  private:
   void DumpInputBuffers(void);
diff --git a/sdm/libs/hwc2/hwc_display_builtin.cpp b/sdm/libs/hwc2/hwc_display_builtin.cpp
index a1999c4..dbac21a 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.cpp
+++ b/sdm/libs/hwc2/hwc_display_builtin.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -41,6 +41,7 @@
 
 #include "hwc_display_builtin.h"
 #include "hwc_debugger.h"
+#include "hwc_session.h"
 
 #define __CLASS__ "HWCDisplayBuiltIn"
 
@@ -188,7 +189,8 @@
   SolidFillPrepare();
 
   // Apply current Color Mode and Render Intent.
-  if (color_mode_->ApplyCurrentColorModeWithRenderIntent() != HWC2::Error::None) {
+  if (color_mode_->ApplyCurrentColorModeWithRenderIntent(
+      static_cast<bool>(layer_stack_.flags.hdr_present)) != HWC2::Error::None) {
     // Fallback to GPU Composition, if Color Mode can't be applied.
     MarkLayersForClientComposition();
   }
@@ -303,6 +305,25 @@
   return status;
 }
 
+HWC2::Error HWCDisplayBuiltIn::SetColorModeFromClientApi(int32_t color_mode_id) {
+  DisplayError error = kErrorNone;
+  std::string mode_string;
+
+  error = display_intf_->GetColorModeName(color_mode_id, &mode_string);
+  if (error) {
+    DLOGE("Failed to get mode name for mode %d", color_mode_id);
+    return HWC2::Error::BadParameter;
+  }
+
+  auto status = color_mode_->SetColorModeFromClientApi(mode_string);
+  if (status != HWC2::Error::None) {
+    DLOGE("Failed to set mode = %d", color_mode_id);
+    return status;
+  }
+
+  return status;
+}
+
 HWC2::Error HWCDisplayBuiltIn::RestoreColorTransform() {
   auto status = color_mode_->RestoreColorTransform();
   if (status != HWC2::Error::None) {
@@ -779,4 +800,37 @@
   return error;
 }
 
+DisplayError HWCDisplayBuiltIn::SetDynamicDSIClock(uint64_t bitclk) {
+  {
+    SEQUENCE_WAIT_SCOPE_LOCK(HWCSession::locker_[type_]);
+    DisplayError error = display_intf_->SetDynamicDSIClock(bitclk);
+    if (error != kErrorNone) {
+      DLOGE(" failed: Clk: %llu Error: %d", bitclk, error);
+      return error;
+    }
+  }
+
+  callbacks_->Refresh(id_);
+  validated_ = false;
+
+  return kErrorNone;
+}
+
+DisplayError HWCDisplayBuiltIn::GetDynamicDSIClock(uint64_t *bitclk) {
+  SEQUENCE_WAIT_SCOPE_LOCK(HWCSession::locker_[type_]);
+  if (display_intf_) {
+    return display_intf_->GetDynamicDSIClock(bitclk);
+  }
+
+  return kErrorNotSupported;
+}
+
+DisplayError HWCDisplayBuiltIn::GetSupportedDSIClock(std::vector<uint64_t> *bitclk_rates) {
+  if (display_intf_) {
+    return display_intf_->GetSupportedDSIClock(bitclk_rates);
+  }
+
+  return kErrorNotSupported;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display_builtin.h b/sdm/libs/hwc2/hwc_display_builtin.h
index 9f4f8b5..682e54f 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.h
+++ b/sdm/libs/hwc2/hwc_display_builtin.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -31,6 +31,7 @@
 #define __HWC_DISPLAY_BUILTIN_H__
 
 #include <string>
+#include <vector>
 
 #include "cpuhint.h"
 #include "hwc_display.h"
@@ -62,6 +63,7 @@
                                        RenderIntent *out_intents);
   virtual HWC2::Error SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
   virtual HWC2::Error SetColorModeById(int32_t color_mode_id);
+  virtual HWC2::Error SetColorModeFromClientApi(int32_t color_mode_id);
   virtual HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint);
   virtual HWC2::Error RestoreColorTransform();
   virtual int Perform(uint32_t operation, ...);
@@ -82,6 +84,9 @@
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous);
   virtual HWC2::Error SetDisplayDppsAdROI(uint32_t h_start, uint32_t h_end, uint32_t v_start,
                                           uint32_t v_end, uint32_t factor_in, uint32_t factor_out);
+  virtual DisplayError SetDynamicDSIClock(uint64_t bitclk);
+  virtual DisplayError GetDynamicDSIClock(uint64_t *bitclk);
+  virtual DisplayError GetSupportedDSIClock(std::vector<uint64_t> *bitclk_rates);
 
  private:
   HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
diff --git a/sdm/libs/hwc2/hwc_display_pluggable.cpp b/sdm/libs/hwc2/hwc_display_pluggable.cpp
index 5bdd4ff..3a4f0b6 100644
--- a/sdm/libs/hwc2/hwc_display_pluggable.cpp
+++ b/sdm/libs/hwc2/hwc_display_pluggable.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -134,7 +134,8 @@
   }
 
   // Apply current Color Mode and Render Intent.
-  if (color_mode_->ApplyCurrentColorModeWithRenderIntent() != HWC2::Error::None) {
+  if (color_mode_->ApplyCurrentColorModeWithRenderIntent(
+      static_cast<bool>(layer_stack_.flags.hdr_present)) != HWC2::Error::None) {
     // Fallback to GPU Composition, if Color Mode can't be applied.
     MarkLayersForClientComposition();
   }
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index e9863a8..168fb79 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -42,7 +42,6 @@
 #include <vector>
 
 #include "hwc_buffer_allocator.h"
-#include "hwc_buffer_sync_handler.h"
 #include "hwc_session.h"
 #include "hwc_debugger.h"
 
@@ -956,6 +955,10 @@
   if (int_enabled < HWC2_VSYNC_INVALID || int_enabled > HWC2_VSYNC_DISABLE) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
+  // already mapping taken care by HAL and SF. No need to react for other display.
+  if (display != HWC_DISPLAY_PRIMARY) {
+    return HWC2_ERROR_NONE;
+  }
 
   auto enabled = static_cast<HWC2::Vsync>(int_enabled);
 
@@ -1518,6 +1521,30 @@
       status = SetAd4RoiConfig(input_parcel);
       break;
 
+    case qService::IQService::SET_DSI_CLK:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
+      status = SetDsiClk(input_parcel);
+      break;
+
+    case qService::IQService::GET_DSI_CLK:
+      if (!input_parcel || !output_parcel) {
+        DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
+        break;
+      }
+      status = GetDsiClk(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::GET_SUPPORTED_DSI_CLK:
+      if (!input_parcel || !output_parcel) {
+        DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
+        break;
+      }
+      status = GetSupportedDsiClk(input_parcel, output_parcel);
+      break;
+
     default:
       DLOGW("QService command = %d is not supported.", command);
       break;
@@ -1899,6 +1926,7 @@
   PPDisplayAPIPayload resp_payload, req_payload;
   uint8_t *disp_id = NULL;
   bool invalidate_needed = true;
+  int32_t *mode_id = NULL;
 
   if (!color_mgr_) {
     DLOGW("color_mgr_ not initialized.");
@@ -2029,6 +2057,21 @@
             }
           }
           break;
+        case kSetModeFromClient:
+          {
+            SCOPE_LOCK(locker_[display_id]);
+            mode_id = reinterpret_cast<int32_t *>(resp_payload.payload);
+            if (mode_id) {
+              ret = static_cast<int>(hwc_display_[display_id]->SetColorModeFromClientApi(*mode_id));
+            } else {
+              DLOGE("mode_id is Null");
+              ret = -EINVAL;
+            }
+          }
+          if (!ret) {
+            Refresh(display_id);
+          }
+          break;
         default:
           DLOGW("Invalid pending action = %d!", pending_action.action);
           break;
@@ -2079,6 +2122,47 @@
   return pstr;
 }
 
+android::status_t HWCSession::SetDsiClk(const android::Parcel *input_parcel) {
+  int disp_id = input_parcel->readInt32();
+  uint64_t clk = UINT64(input_parcel->readInt64());
+  if (disp_id < 0 || !hwc_display_[disp_id]) {
+    return -EINVAL;
+  }
+
+  return hwc_display_[disp_id]->SetDynamicDSIClock(clk);
+}
+
+android::status_t HWCSession::GetDsiClk(const android::Parcel *input_parcel,
+                                        android::Parcel *output_parcel) {
+  int disp_id = input_parcel->readInt32();
+  if (disp_id < 0 || !hwc_display_[disp_id]) {
+    return -EINVAL;
+  }
+
+  uint64_t bitrate = 0;
+  hwc_display_[disp_id]->GetDynamicDSIClock(&bitrate);
+  output_parcel->writeUint64(bitrate);
+
+  return 0;
+}
+
+android::status_t HWCSession::GetSupportedDsiClk(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel) {
+  int disp_id = input_parcel->readInt32();
+  if (disp_id < 0 || !hwc_display_[disp_id]) {
+    return -EINVAL;
+  }
+
+  std::vector<uint64_t> bit_rates;
+  hwc_display_[disp_id]->GetSupportedDSIClock(&bit_rates);
+  output_parcel->writeInt32(INT32(bit_rates.size()));
+  for (auto &bit_rate : bit_rates) {
+    output_parcel->writeUint64(bit_rate);
+  }
+
+  return 0;
+}
+
 void HWCSession::UEventHandler(const char *uevent_data, int length) {
   if (strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
     // MST hotplug will not carry connection status/test pattern etc.
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index d1241cd..a03a43d 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -54,6 +54,7 @@
 #include "hwc_color_manager.h"
 #include "hwc_socket_handler.h"
 #include "hwc_display_event_handler.h"
+#include "hwc_buffer_sync_handler.h"
 
 namespace sdm {
 
@@ -273,6 +274,7 @@
   int32_t GetPanelBrightness(int *level);
   int32_t MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level);
   int32_t IsWbUbwcSupported(int *value);
+  int32_t SetDynamicDSIClock(int64_t disp_id, uint32_t bitrate);
 
   // service methods
   void StartServices();
@@ -364,6 +366,10 @@
   android::status_t SetIdlePC(const android::Parcel *input_parcel);
   android::status_t RefreshScreen(const android::Parcel *input_parcel);
   android::status_t SetAd4RoiConfig(const android::Parcel *input_parcel);
+  android::status_t SetDsiClk(const android::Parcel *input_parcel);
+  android::status_t GetDsiClk(const android::Parcel *input_parcel, android::Parcel *output_parcel);
+  android::status_t GetSupportedDsiClk(const android::Parcel *input_parcel,
+                                       android::Parcel *output_parcel);
 
   void Refresh(hwc2_display_t display);
   void HotPlug(hwc2_display_t display, HWC2::Connection state);
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 0469e62..940a55c 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -426,7 +426,7 @@
       break;
     }
 
-    SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
+    SCOPE_LOCK(locker_[disp_id]);
     HWCDisplay *hwc_display = hwc_display_[disp_idx];
     if (!hwc_display) {
       DLOGW("Display = %d is not connected.", disp_idx);
@@ -436,11 +436,14 @@
 
     // query number of hdr types
     uint32_t out_num_types = 0;
-    if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, nullptr, nullptr, nullptr)
-        != HWC2::Error::None) {
+    float out_max_luminance = 0.0f;
+    float out_max_average_luminance = 0.0f;
+    float out_min_luminance = 0.0f;
+    if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, &out_max_luminance,
+                                        &out_max_average_luminance, &out_min_luminance)
+                                        != HWC2::Error::None) {
       break;
     }
-
     if (!out_num_types) {
       error = 0;
       break;
@@ -449,9 +452,6 @@
     // query hdr caps
     hdr_caps.supportedHdrTypes.resize(out_num_types);
 
-    float out_max_luminance = 0.0f;
-    float out_max_average_luminance = 0.0f;
-    float out_min_luminance = 0.0f;
     if (hwc_display->GetHdrCapabilities(&out_num_types, hdr_caps.supportedHdrTypes.data(),
                                         &out_max_luminance, &out_max_average_luminance,
                                         &out_min_luminance) == HWC2::Error::None) {
@@ -693,7 +693,7 @@
 }
 
 Return<bool> HWCSession::isHDRSupported(uint32_t disp_id) {
-  SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+  SCOPE_LOCK(locker_[disp_id]);
   HWCDisplay *hwc_display = hwc_display_[disp_id];
   if (!hwc_display) {
     DLOGW("Display = %d is not connected.", disp_id);
@@ -702,8 +702,12 @@
 
   // query number of hdr types
   uint32_t out_num_types = 0;
-  if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, nullptr, nullptr, nullptr)
-      != HWC2::Error::None) {
+  float out_max_luminance = 0.0f;
+  float out_max_average_luminance = 0.0f;
+  float out_min_luminance = 0.0f;
+  if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, &out_max_luminance,
+                                      &out_max_average_luminance, &out_min_luminance)
+                                      != HWC2::Error::None) {
     return false;
   }