diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2016-06-28 18:46:59 -0600 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2016-06-28 18:46:59 -0600 |
commit | a9a43857334b27654eb7ddf375cff2eb7e9ceaba (patch) | |
tree | ec5296a310e0351e5a728abed85863316706d953 | |
parent | 04eaf5ff8fd2482faced448936d34737df8cbd83 (diff) | |
parent | f392f6cd99c29eb9225cea56683152d3b3c299ed (diff) | |
download | hardware_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.c | 4 | ||||
-rw-r--r-- | sdm/libs/core/comp_manager.cpp | 7 | ||||
-rw-r--r-- | sdm/libs/core/comp_manager.h | 3 | ||||
-rw-r--r-- | sdm/libs/core/fb/hw_hdmi.cpp | 117 | ||||
-rw-r--r-- | sdm/libs/core/fb/hw_hdmi.h | 22 | ||||
-rw-r--r-- | sdm/libs/core/strategy.cpp | 2 | ||||
-rw-r--r-- | sdm/libs/hwc/hwc_display.h | 8 | ||||
-rw-r--r-- | sdm/libs/hwc/hwc_display_external.cpp | 63 | ||||
-rw-r--r-- | sdm/libs/hwc/hwc_display_external.h | 3 | ||||
-rw-r--r-- | sdm/libs/hwc/hwc_session.cpp | 10 |
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_); |