Merge "sdm: Add support to get/set DSI clk."
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 8cb300a..20e3abc 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -584,6 +584,7 @@
int wmin;
int hmin;
bool roi_merge;
+ uint64_t bit_clk_rate;
};
/* Per Connector Info*/
@@ -610,6 +611,7 @@
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/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..dd3481f 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -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.
@@ -781,6 +787,30 @@
*/
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/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.h b/sdm/libs/core/display_base.h
index 35c07a4..9aee6d3 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -94,6 +94,15 @@
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);
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(¤t_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..d8a82f7 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -687,6 +687,7 @@
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..36f8c3d 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;
}
@@ -404,6 +441,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..ddc1b00 100644
--- a/sdm/libs/hwc2/display_null.h
+++ b/sdm/libs/hwc2/display_null.h
@@ -98,6 +98,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 984489d..ce224aa 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -430,6 +430,8 @@
return -EINVAL;
}
+ UpdateConfigs();
+
tone_mapper_ = new HWCToneMapper(buffer_allocator_);
display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
@@ -448,6 +450,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_);
@@ -863,8 +895,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;
@@ -872,12 +910,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);
@@ -979,6 +1017,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 6e5199e..b901184 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -244,6 +244,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 +320,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);
@@ -371,6 +381,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..0806241 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.cpp
+++ b/sdm/libs/hwc2/hwc_display_builtin.cpp
@@ -41,6 +41,7 @@
#include "hwc_display_builtin.h"
#include "hwc_debugger.h"
+#include "hwc_session.h"
#define __CLASS__ "HWCDisplayBuiltIn"
@@ -779,4 +780,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..946b7ef 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.h
+++ b/sdm/libs/hwc2/hwc_display_builtin.h
@@ -31,6 +31,7 @@
#define __HWC_DISPLAY_BUILTIN_H__
#include <string>
+#include <vector>
#include "cpuhint.h"
#include "hwc_display.h"
@@ -82,6 +83,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_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 5e897a6..07f635b 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -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"
@@ -1518,6 +1517,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;
@@ -2079,6 +2102,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 2c71515..5dd803d 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 {
@@ -271,6 +272,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();
@@ -362,6 +364,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);