Merge "sdm: hwc2: Enable SolidFill"
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index e09959f..7d65e26 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -154,7 +154,7 @@
return error;
}
- return kErrorNone;
+ return DisplayBase::ReconfigureDisplay();
}
bool DisplayHDMI::IsUnderscanSupported() {
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index d9116e6..1ecb7c2 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -695,13 +695,102 @@
return kErrorNone;
}
+DisplayError HWHDMI::GetDynamicFrameRateMode(uint32_t refresh_rate, uint32_t *mode,
+ DynamicFPSData *data, uint32_t *config_index) {
+ msm_hdmi_mode_timing_info *cur = NULL;
+ msm_hdmi_mode_timing_info *dst = NULL;
+ uint32_t i = 0;
+ int pre_refresh_rate_diff = 0;
+ bool pre_unstd_mode = false;
+
+ for (i = 0; i < hdmi_modes_.size(); i++) {
+ msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[i];
+ if (timing_mode->video_format == hdmi_modes_[active_config_index_]) {
+ cur = timing_mode;
+ break;
+ }
+ }
+
+ if (cur == NULL) {
+ DLOGE("can't find timing info for active config index(%d)", active_config_index_);
+ return kErrorUndefined;
+ }
+
+ if (cur->refresh_rate != frame_rate_) {
+ pre_unstd_mode = true;
+ }
+
+ if (i >= hdmi_modes_.size()) {
+ return kErrorNotSupported;
+ }
+
+ dst = cur;
+ pre_refresh_rate_diff = static_cast<int>(dst->refresh_rate) - static_cast<int>(refresh_rate);
+
+ for (i = 0; i < hdmi_modes_.size(); i++) {
+ msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[i];
+ if (cur->active_h == timing_mode->active_h &&
+ cur->active_v == timing_mode->active_v &&
+ cur->pixel_formats == timing_mode->pixel_formats ) {
+ int cur_refresh_rate_diff = static_cast<int>(timing_mode->refresh_rate) -
+ static_cast<int>(refresh_rate);
+ if (abs(pre_refresh_rate_diff) > abs(cur_refresh_rate_diff)) {
+ pre_refresh_rate_diff = cur_refresh_rate_diff;
+ dst = timing_mode;
+ }
+ }
+ }
+
+ if (pre_refresh_rate_diff > kThresholdRefreshRate) {
+ return kErrorNotSupported;
+ }
+
+ GetConfigIndex(dst->video_format, config_index);
+
+ data->hor_front_porch = dst->front_porch_h;
+ data->hor_back_porch = dst->back_porch_h;
+ data->hor_pulse_width = dst->pulse_width_h;
+ data->clk_rate_hz = dst->pixel_freq;
+ data->fps = refresh_rate;
+
+ if (dst->front_porch_h != cur->front_porch_h) {
+ *mode = kModeHFP;
+ }
+
+ if (dst->refresh_rate != refresh_rate || dst->pixel_freq != cur->pixel_freq) {
+ if (*mode == kModeHFP) {
+ if (dst->refresh_rate != refresh_rate) {
+ *mode = kModeHFPCalcClock;
+ } else {
+ *mode = kModeClockHFP;
+ }
+ } else {
+ *mode = kModeClock;
+ }
+ }
+
+ if (pre_unstd_mode && (*mode == kModeHFP)) {
+ *mode = kModeClockHFP;
+ }
+
+ return kErrorNone;
+}
+
DisplayError HWHDMI::SetRefreshRate(uint32_t refresh_rate) {
char mode_path[kMaxStringLength] = {0};
char node_path[kMaxStringLength] = {0};
- uint32_t mode = kModeHFP;
+ uint32_t mode = kModeClock;
+ uint32_t config_index = 0;
+ DynamicFPSData data;
+ DisplayError error = kErrorNone;
if (refresh_rate == frame_rate_) {
- return kErrorNone;
+ return error;
+ }
+
+ error = GetDynamicFrameRateMode(refresh_rate, &mode, &data, &config_index);
+ if (error != kErrorNone) {
+ return error;
}
snprintf(mode_path, sizeof(mode_path), "%s%d/msm_fb_dfps_mode", fb_path_, fb_node_index_);
@@ -709,7 +798,7 @@
int fd_mode = Sys::open_(mode_path, O_WRONLY);
if (fd_mode < 0) {
- DLOGE("Failed to open %s with error %s", node_path, strerror(errno));
+ DLOGE("Failed to open %s with error %s", mode_path, strerror(errno));
return kErrorFileDescriptor;
}
@@ -731,8 +820,14 @@
}
char refresh_rate_string[kMaxStringLength];
- snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", refresh_rate);
- DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", refresh_rate);
+ if (mode == kModeHFP || mode == kModeClock) {
+ snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", data.fps);
+ DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", data.fps);
+ } else {
+ snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d %d %d %d %d",
+ data.hor_front_porch, data.hor_back_porch, data.hor_pulse_width,
+ data.clk_rate_hz, data.fps);
+ }
len = Sys::pwrite_(fd_node, refresh_rate_string, strlen(refresh_rate_string), 0);
if (len < 0) {
DLOGE("Failed to write %d with error %s", refresh_rate, strerror(errno));
@@ -741,15 +836,21 @@
}
Sys::close_(fd_node);
- DisplayError error = ReadTimingInfo();
+ error = ReadTimingInfo();
if (error != kErrorNone) {
return error;
}
- GetDisplayAttributes(active_config_index_, &display_attributes_);
+ GetDisplayAttributes(config_index, &display_attributes_);
UpdateMixerAttributes();
frame_rate_ = refresh_rate;
+ active_config_index_ = config_index;
+
+ DLOGI_IF(kTagDriverConfig, "config_index(%d) Mode(%d) frame_rate(%d)",
+ config_index,
+ mode,
+ frame_rate_);
return kErrorNone;
}
diff --git a/sdm/libs/core/fb/hw_hdmi.h b/sdm/libs/core/fb/hw_hdmi.h
index d2bd658..8cedc93 100644
--- a/sdm/libs/core/fb/hw_hdmi.h
+++ b/sdm/libs/core/fb/hw_hdmi.h
@@ -51,9 +51,29 @@
kModeVFP,
// Switch framerate by tuning horizontal front porch
kModeHFP,
+ // Switch framerate by tuning horizontal front porch and clock
+ kModeClockHFP,
+ // Switch framerate by tuning horizontal front porch and re-caculate clock
+ kModeHFPCalcClock,
kModeMAX
};
+ /**
+ * struct DynamicFPSData - defines dynamic fps related data
+ * @hor_front_porch: horizontal front porch
+ * @hor_back_porch: horizontal back porch
+ * @hor_pulse_width: horizontal pulse width
+ * @clk_rate_hz: panel clock rate in HZ
+ * @fps: frames per second
+ */
+ struct DynamicFPSData {
+ uint32_t hor_front_porch;
+ uint32_t hor_back_porch;
+ uint32_t hor_pulse_width;
+ uint32_t clk_rate_hz;
+ uint32_t fps;
+ };
+
HWHDMI(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
virtual DisplayError Init();
virtual DisplayError Deinit();
@@ -87,6 +107,9 @@
bool IsSupportedS3DMode(HWS3DMode s3d_mode);
void UpdateMixerAttributes();
+ DisplayError GetDynamicFrameRateMode(uint32_t refresh_rate, uint32_t*mode,
+ DynamicFPSData *data, uint32_t *config_index);
+ static const int kThresholdRefreshRate = 1000;
vector<uint32_t> hdmi_modes_;
// Holds the hdmi timing information. Ex: resolution, fps etc.,
vector<msm_hdmi_mode_timing_info> supported_video_modes_;
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index dd6f83a..883f2df 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -1321,7 +1321,12 @@
for (uint i = 0; i < app_layer_count; i++) {
Layer *layer = layer_stack_.layers[i];
- if (layer->flags.updating && (layer->input_buffer->flags.video == true)) {
+ // TODO(user):disable DRC feature in S3D playbacl case.S3D video
+ // need play in dedicate resolution and fps, if DRC switch the
+ // mode to an non S3D supported mode, it would break S3D playback.
+ // Need figure out a way to make S3D and DRC co-exist.
+ if (layer->flags.updating && (layer->input_buffer->flags.video == true) &&
+ (layer->input_buffer->s3d_format == kS3dFormatNone)) {
updating_count++;
}
}
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index 1dfface..df9056e 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -49,6 +49,14 @@
class HWCDisplay : public DisplayEventHandler {
public:
+ enum {
+ SET_METADATA_DYN_REFRESH_RATE,
+ SET_BINDER_DYN_REFRESH_RATE,
+ SET_DISPLAY_MODE,
+ SET_QDCM_SOLID_FILL_INFO,
+ UNSET_QDCM_SOLID_FILL_INFO,
+ };
+
virtual ~HWCDisplay() { }
virtual int Init();
virtual int Deinit();
diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp
index a1ad661..ed916d4 100644
--- a/sdm/libs/hwc/hwc_display_external.cpp
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -51,6 +51,7 @@
uint32_t external_width = 0;
uint32_t external_height = 0;
int drc_enabled = 0;
+ int drc_reset_fps_enabled = 0;
DisplayError error = kErrorNone;
HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, hwc_procs, qservice);
@@ -89,6 +90,10 @@
HWCDebugHandler::Get()->GetProperty("sdm.hdmi.drc_enabled", &(drc_enabled));
reinterpret_cast<HWCDisplayExternal *>(hwc_display_external)->drc_enabled_ = drc_enabled;
+ HWCDebugHandler::Get()->GetProperty("sdm.hdmi.drc_reset_fps", &(drc_reset_fps_enabled));
+ reinterpret_cast<HWCDisplayExternal *>(hwc_display_external)->drc_reset_fps_enabled_ =
+ drc_reset_fps_enabled;
+
*hwc_display = hwc_display_external;
return status;
@@ -131,16 +136,15 @@
bool one_video_updating_layer = SingleVideoLayerUpdating(UINT32(content_list->numHwLayers - 1));
- if (current_refresh_rate_ != metadata_refresh_rate_ && one_video_updating_layer && drc_enabled_) {
- error = display_intf_->SetRefreshRate(metadata_refresh_rate_);
+ uint32_t refresh_rate = GetOptimalRefreshRate(one_video_updating_layer);
+ if (current_refresh_rate_ != refresh_rate) {
+ error = display_intf_->SetRefreshRate(refresh_rate);
+ if (error == kErrorNone) {
+ // On success, set current refresh rate to new refresh rate
+ current_refresh_rate_ = refresh_rate;
+ }
}
- if (error == kErrorNone) {
- // On success, set current refresh rate to new refresh rate
- current_refresh_rate_ = metadata_refresh_rate_;
- }
-
-
status = PrepareLayerStack(content_list);
if (status) {
return status;
@@ -248,6 +252,11 @@
static const uint32_t mapping_fps[] = {59940, 60000, 60000, 59940, 60000, 50000, 59940, 60000};
uint32_t frame_rate = (uint32_t)(fps * 1000);
+ // process non valid
+ if (frame_rate == 0) {
+ return current_refresh_rate_;
+ }
+
int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
for (int i = 0; i < count; i++) {
// Most likely used for video, the fps for frames should be stable from video side.
@@ -269,10 +278,57 @@
void HWCDisplayExternal::PrepareDynamicRefreshRate(Layer *layer) {
if (layer->input_buffer->flags.video) {
- metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
+ if (layer->frame_rate != 0) {
+ metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
+ } else {
+ metadata_refresh_rate_ = current_refresh_rate_;
+ }
layer->frame_rate = current_refresh_rate_;
}
}
+void HWCDisplayExternal::ForceRefreshRate(uint32_t refresh_rate) {
+ if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
+ force_refresh_rate_ == refresh_rate) {
+ // Cannot honor force refresh rate, as its beyond the range or new request is same
+ return;
+ }
+
+ force_refresh_rate_ = refresh_rate;
+}
+
+uint32_t HWCDisplayExternal::GetOptimalRefreshRate(bool one_updating_layer) {
+ if (force_refresh_rate_) {
+ return force_refresh_rate_;
+ } else if (one_updating_layer && drc_enabled_) {
+ return metadata_refresh_rate_;
+ }
+
+ if (drc_reset_fps_enabled_) {
+ DisplayConfigVariableInfo fb_config;
+ display_intf_->GetFrameBufferConfig(&fb_config);
+ return (fb_config.fps * 1000);
+ }
+
+ return current_refresh_rate_;
+}
+
+int HWCDisplayExternal::Perform(uint32_t operation, ...) {
+ va_list args;
+ va_start(args, operation);
+ int val = va_arg(args, int32_t);
+ va_end(args);
+ switch (operation) {
+ case SET_BINDER_DYN_REFRESH_RATE:
+ ForceRefreshRate(UINT32(val));
+ break;
+ default:
+ DLOGW("Invalid operation %d", operation);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display_external.h b/sdm/libs/hwc/hwc_display_external.h
index c54f738..ac70489 100644
--- a/sdm/libs/hwc/hwc_display_external.h
+++ b/sdm/libs/hwc/hwc_display_external.h
@@ -40,11 +40,13 @@
virtual int Prepare(hwc_display_contents_1_t *content_list);
virtual int Commit(hwc_display_contents_1_t *content_list);
virtual void SetSecureDisplay(bool secure_display_active);
+ virtual int Perform(uint32_t operation, ...);
protected:
virtual uint32_t RoundToStandardFPS(float fps);
virtual void PrepareDynamicRefreshRate(Layer *layer);
int drc_enabled_ = 0;
+ int drc_reset_fps_enabled_ = 0;
private:
HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
@@ -52,6 +54,8 @@
void ApplyScanAdjustment(hwc_rect_t *display_frame);
static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
uint32_t *virtual_width, uint32_t *virtual_height);
+ void ForceRefreshRate(uint32_t refresh_rate);
+ uint32_t GetOptimalRefreshRate(bool one_updating_layer);
};
} // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display_primary.h b/sdm/libs/hwc/hwc_display_primary.h
index f25a877..7ae5b53 100644
--- a/sdm/libs/hwc/hwc_display_primary.h
+++ b/sdm/libs/hwc/hwc_display_primary.h
@@ -32,14 +32,6 @@
class HWCDisplayPrimary : public HWCDisplay {
public:
- enum {
- SET_METADATA_DYN_REFRESH_RATE,
- SET_BINDER_DYN_REFRESH_RATE,
- SET_DISPLAY_MODE,
- SET_QDCM_SOLID_FILL_INFO,
- UNSET_QDCM_SOLID_FILL_INFO,
- };
-
static int Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
hwc_procs_t const **hwc_procs, qService::QService *qservice,
HWCDisplay **hwc_display);
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 1c3dd19..b00968c 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -278,7 +278,7 @@
if (hwc_session->color_mgr_) {
HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
- if (primary_display) {
+ if (primary_display && !hwc_session->is_hdmi_primary_) {
int ret = hwc_session->color_mgr_->SolidFillLayersPrepare(displays, primary_display);
if (ret)
return 0;