summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-06-28 18:46:59 -0600
committerLinux Build Service Account <lnxbuild@localhost>2016-06-28 18:46:59 -0600
commita9a43857334b27654eb7ddf375cff2eb7e9ceaba (patch)
treeec5296a310e0351e5a728abed85863316706d953
parent04eaf5ff8fd2482faced448936d34737df8cbd83 (diff)
parentf392f6cd99c29eb9225cea56683152d3b3c299ed (diff)
downloadhardware_qcom_display-a9a43857334b27654eb7ddf375cff2eb7e9ceaba.tar.gz
hardware_qcom_display-a9a43857334b27654eb7ddf375cff2eb7e9ceaba.tar.bz2
hardware_qcom_display-a9a43857334b27654eb7ddf375cff2eb7e9ceaba.zip
Promotion of display.lnx.2.0-00038.
CRs Change ID Subject -------------------------------------------------------------------------------------------------------------- 1032036 I4bdd418964f4b41e25ee166abba2e828707dd4ce sdm: Add binder support to force set HDMI framerate 1028406 If4a1ce2a518dd427c5680e6408ce7276457c66ca libmemtrack: Update the parsing of flags field 1032036 I46e58d745a9601b71d02b6d91b226616c6cb7a52 sdm: Add mode chose for dynamic framerate switch 1020517 Ib5c91ce5d4d8ff7cd5c57080e9084502d2d25599 sdm: Power on HDMI panel when pluged in 1017762 I8cd8c16cdb83196c1ea115621ae52be74ab43b09 sdm: Limit composed layers for non primary displays Change-Id: Ie63df62d6dbc067ccc39e5d9f22d029330cfbd66 CRs-Fixed: 1020517, 1032036, 1017762, 1028406
-rw-r--r--libmemtrack/kgsl.c4
-rw-r--r--sdm/libs/core/comp_manager.cpp7
-rw-r--r--sdm/libs/core/comp_manager.h3
-rw-r--r--sdm/libs/core/fb/hw_hdmi.cpp117
-rw-r--r--sdm/libs/core/fb/hw_hdmi.h22
-rw-r--r--sdm/libs/core/strategy.cpp2
-rw-r--r--sdm/libs/hwc/hwc_display.h8
-rw-r--r--sdm/libs/hwc/hwc_display_external.cpp63
-rw-r--r--sdm/libs/hwc/hwc_display_external.h3
-rw-r--r--sdm/libs/hwc/hwc_session.cpp10
10 files changed, 217 insertions, 22 deletions
diff --git a/libmemtrack/kgsl.c b/libmemtrack/kgsl.c
index 5a6b07529..11c7e8a2f 100644
--- a/libmemtrack/kgsl.c
+++ b/libmemtrack/kgsl.c
@@ -85,7 +85,7 @@ int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type,
while (1) {
unsigned long size, mapsize;
char line_type[7];
- char flags[8];
+ char flags[9];
char line_usage[19];
int ret;
@@ -97,7 +97,7 @@ int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type,
* gpuaddr useraddr size id flags type usage sglen mapsize
* 545ba000 545ba000 4096 1 -----pY gpumem arraybuffer 1 4096
*/
- ret = sscanf(line, "%*x %*x %lu %*d %7s %6s %18s %*d %lu\n",
+ ret = sscanf(line, "%*x %*x %lu %*d %8s %6s %18s %*d %lu\n",
&size, flags, line_type, line_usage, &mapsize);
if (ret != 5) {
continue;
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index afbb8f361..93060a12a 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -106,11 +106,12 @@ DisplayError CompManager::RegisterDisplay(DisplayType type, const HWDisplayAttri
}
SET_BIT(registered_displays_, type);
+ display_comp_ctx->is_primary_panel = hw_panel_info.is_primary_panel;
display_comp_ctx->display_type = type;
*display_ctx = display_comp_ctx;
// New non-primary display device has been added, so move the composition mode to safe mode until
// resources for the added display is configured properly.
- if (type != kPrimary) {
+ if (!display_comp_ctx->is_primary_panel) {
safe_mode_ = true;
}
@@ -207,8 +208,8 @@ void CompManager::PrepareStrategyConstraints(Handle comp_handle, HWLayers *hw_la
constraints->use_cursor = false;
constraints->max_layers = max_layers_;
- // Limit 2 layer SDE Comp on HDMI/Virtual
- if (display_comp_ctx->display_type != kPrimary) {
+ // Limit 2 layer SDE Comp if its not a Primary Display
+ if (!display_comp_ctx->is_primary_panel) {
constraints->max_layers = 2;
}
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 77440700b..9eb5fc44f 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -80,6 +80,9 @@ class CompManager : public DumpImpl {
bool idle_fallback = false;
bool fallback_ = false;
uint32_t partial_update_enable = true;
+ // Using primary panel flag of hw panel to configure Constraints. We do not need other hw
+ // panel parameters for now.
+ bool is_primary_panel = false;
};
Locker locker_;
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index 5fe9bc1f1..ec76b4170 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -698,13 +698,103 @@ DisplayError HWHDMI::SetS3DMode(HWS3DMode s3d_mode) {
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_mode_count_; 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_mode_count_) {
+ return kErrorNotSupported;
+ }
+
+ dst = cur;
+ pre_refresh_rate_diff = static_cast<int>(dst->refresh_rate) - static_cast<int>(refresh_rate);
+
+ for (i = 0; i < hdmi_mode_count_; 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 (dst == NULL) {
+ DLOGE("can't find timing mode switch to");
+ return kErrorUndefined;
+ }
+
+ 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_);
@@ -712,7 +802,7 @@ DisplayError HWHDMI::SetRefreshRate(uint32_t refresh_rate) {
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;
}
@@ -734,8 +824,14 @@ DisplayError HWHDMI::SetRefreshRate(uint32_t refresh_rate) {
}
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", refresh_rate);
+ DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", refresh_rate);
+ } 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));
@@ -744,12 +840,21 @@ DisplayError HWHDMI::SetRefreshRate(uint32_t refresh_rate) {
}
Sys::close_(fd_node);
- DisplayError error = ReadTimingInfo();
+ error = ReadTimingInfo();
if (error != kErrorNone) {
return error;
}
+// 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 aa5e2a09e..28adc39e6 100644
--- a/sdm/libs/core/fb/hw_hdmi.h
+++ b/sdm/libs/core/fb/hw_hdmi.h
@@ -49,9 +49,29 @@ class HWHDMI : public HWDevice {
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();
@@ -84,6 +104,8 @@ class HWHDMI : public HWDevice {
HWDisplayAttributes *attrib);
bool IsSupportedS3DMode(HWS3DMode s3d_mode);
+ DisplayError GetDynamicFrameRateMode(uint32_t refresh_rate, uint32_t*mode,
+ DynamicFPSData *data, uint32_t *config_index);
uint32_t hdmi_mode_count_;
uint32_t hdmi_modes_[256];
// Holds the hdmi timing information. Ex: resolution, fps etc.,
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index 924047a21..aaa1ebbd7 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -169,7 +169,7 @@ void Strategy::GenerateROI() {
if (!hw_resource_info_.is_src_split &&
((disp_x_res > hw_resource_info_.max_mixer_width) ||
- ((display_type_ == kPrimary) && hw_panel_info_.split_info.right_split))) {
+ ((hw_panel_info_.is_primary_panel) && hw_panel_info_.split_info.right_split))) {
split_display = true;
}
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index 60b350084..ff0f7f14f 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -48,6 +48,14 @@ enum DisplayClass {
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 43160c3a6..47fb2e5fb 100644
--- a/sdm/libs/hwc/hwc_display_external.cpp
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -126,16 +126,15 @@ int HWCDisplayExternal::Prepare(hwc_display_contents_1_t *content_list) {
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_);
- }
-
- if (error == kErrorNone) {
- // On success, set current refresh rate to new refresh rate
- current_refresh_rate_ = 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;
+ }
}
-
status = PrepareLayerStack(content_list);
if (status) {
return status;
@@ -239,6 +238,11 @@ uint32_t HWCDisplayExternal::RoundToStandardFPS(float fps) {
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.
@@ -260,10 +264,51 @@ uint32_t HWCDisplayExternal::RoundToStandardFPS(float fps) {
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_;
+ }
+
+ return max_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 c54f7380a..8708e9143 100644
--- a/sdm/libs/hwc/hwc_display_external.h
+++ b/sdm/libs/hwc/hwc_display_external.h
@@ -40,6 +40,7 @@ class HWCDisplayExternal : public HWCDisplay {
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);
@@ -52,6 +53,8 @@ class HWCDisplayExternal : public HWCDisplay {
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_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 55b41305b..77b9affee 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -1354,6 +1354,7 @@ void HWCSession::ResetPanel() {
int HWCSession::HotPlugHandler(bool connected) {
int status = 0;
bool notify_hotplug = false;
+ bool refresh_screen = false;
// To prevent sending events to client while a lock is held, acquire scope locks only within
// below scope so that those get automatically unlocked after the scope ends.
@@ -1397,6 +1398,12 @@ int HWCSession::HotPlugHandler(bool connected) {
return -1;
}
+ DLOGI("Powering on primary");
+ status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_NORMAL);
+ if (status) {
+ DLOGE("power-on on primary failed with error = %d", status);
+ }
+
is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY);
// Next, go ahead and enable vsync on external display. This is expliclity required
@@ -1409,6 +1416,7 @@ int HWCSession::HotPlugHandler(bool connected) {
}
// Don't do hotplug notification for HDMI as primary case for now
notify_hotplug = false;
+ refresh_screen = true;
} else {
if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
DLOGE("HDMI is already connected");
@@ -1467,7 +1475,7 @@ int HWCSession::HotPlugHandler(bool connected) {
}
}
- if (connected && notify_hotplug) {
+ if (connected && (notify_hotplug || refresh_screen)) {
// trigger screen refresh to ensure sufficient resources are available to process new
// new display connection.
hwc_procs_->invalidate(hwc_procs_);