sdm: Add support for adaptive variable refresh feature
1. Populate information about AVR feature support from sysfs node.
2. Initialize AVR information based on display mode and dynamic fps
mode and set corresponding AVR flags.
3. Define debug property sdm.debug.disable_avr to disable avr feature.
Change-Id: I1bfbb9e1f9975468aa9eb6d6b575f317c658480e
CRs-Fixed: 1043833
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index e806d92..daf88ed 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -110,6 +110,11 @@
kMultiRectParallelMode = 0x04,
};
+enum HWAVRModes {
+ kContinuousMode, // Mode to enable AVR feature for every frame.
+ kOneShotMode, // Mode to enable AVR feature for particular frame.
+};
+
typedef std::map<HWSubBlockType, std::vector<LayerBufferFormat>> FormatsMap;
struct HWDynBwLimitInfo {
@@ -188,6 +193,7 @@
FormatsMap supported_formats_map;
HWRotatorInfo hw_rot_info;
HWDestScalarInfo hw_dest_scalar_info;
+ bool has_avr = false;
void Reset() { *this = HWResourceInfo(); }
};
@@ -226,6 +232,7 @@
int min_roi_height = 0; // Min height needed for ROI
bool needs_roi_merge = false; // Merge ROI's of both the DSI's
bool dynamic_fps = false; // Panel Supports dynamic fps
+ bool dfps_porch_mode = false; // dynamic fps VFP or HFP mode
uint32_t min_fps = 0; // Min fps supported by panel
uint32_t max_fps = 0; // Max fps supported by panel
bool is_primary_panel = false; // Panel is primary display
@@ -244,6 +251,7 @@
(min_roi_height != panel_info.min_roi_height) ||
(needs_roi_merge != panel_info.needs_roi_merge) ||
(dynamic_fps != panel_info.dynamic_fps) || (min_fps != panel_info.min_fps) ||
+ (dfps_porch_mode != panel_info.dfps_porch_mode) ||
(max_fps != panel_info.max_fps) || (is_primary_panel != panel_info.is_primary_panel) ||
(split_info != panel_info.split_info) ||
(s3d_mode != panel_info.s3d_mode));
@@ -386,6 +394,11 @@
typedef std::map<uint32_t, HWDestScaleInfo *> DestScaleInfoMap;
+struct HWAVRInfo {
+ bool enable = false; // Flag to Enable AVR feature
+ HWAVRModes mode = kContinuousMode; // Specifies the AVR mode
+};
+
struct HWPipeInfo {
uint32_t pipe_id = 0;
HWSubBlockType sub_block_type = kHWSubBlockMax;
@@ -436,6 +449,7 @@
float output_compression = 1.0f;
uint32_t bandwidth = 0;
uint32_t clock = 0;
+ HWAVRInfo hw_avr_info = {};
};
struct HWDisplayAttributes : DisplayConfigVariableInfo {
diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h
index 23ba181..74d3236 100644
--- a/sdm/include/utils/debug.h
+++ b/sdm/include/utils/debug.h
@@ -74,6 +74,7 @@
static bool IsRotatorSplitDisabled();
static bool IsScalarDisabled();
static bool IsUbwcTiledFrameBuffer();
+ static bool IsAVRDisabled();
static bool GetProperty(const char *property_name, char *value);
static bool SetProperty(const char *property_name, const char *value);
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 1f28e6e..eccc877 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -219,8 +219,6 @@
disable_pu_one_frame_ = false;
}
- // Clean hw layers for reuse.
- hw_layers_ = HWLayers();
hw_layers_.info.stack = layer_stack;
hw_layers_.output_compression = 1.0f;
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index 6e2a7b5..3c3d9f4 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -114,6 +114,9 @@
SetS3DMode(layer_stack);
+ // Clean hw layers for reuse.
+ hw_layers_ = HWLayers();
+
return DisplayBase::Prepare(layer_stack);
}
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 05e5dc3..e8689ea 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -70,6 +70,8 @@
}
}
+ avr_prop_disabled_ = Debug::IsAVRDisabled();
+
error = HWEventsInterface::Create(INT(display_type_), this, &event_list_, &hw_events_intf_);
if (error != kErrorNone) {
DLOGE("Failed to create hardware events interface. Error = %d", error);
@@ -95,6 +97,10 @@
}
}
+ // Clean hw layers for reuse.
+ hw_layers_ = HWLayers();
+ hw_layers_.hw_avr_info.enable = NeedsAVREnable();
+
return DisplayBase::Prepare(layer_stack);
}
@@ -294,5 +300,15 @@
return kErrorNone;
}
+bool DisplayPrimary::NeedsAVREnable() {
+ if (avr_prop_disabled_) {
+ return false;
+ }
+
+ return (hw_panel_info_.mode == kModeVideo && ((hw_panel_info_.dynamic_fps &&
+ hw_panel_info_.dfps_porch_mode) || (!hw_panel_info_.dynamic_fps &&
+ hw_panel_info_.min_fps != hw_panel_info_.max_fps)));
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index c20ff09..7a03005 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -60,9 +60,12 @@
virtual void CECMessage(char *message) { }
private:
+ bool NeedsAVREnable();
+
uint32_t idle_timeout_ms_ = 0;
std::vector<const char *> event_list_ = {"vsync_event", "show_blank_event", "idle_notify",
"msm_fb_thermal_level", "thread_exit"};
+ bool avr_prop_disabled_ = false;
};
} // namespace sdm
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
index 783cacd..6beea5c 100644
--- a/sdm/libs/core/display_virtual.cpp
+++ b/sdm/libs/core/display_virtual.cpp
@@ -130,5 +130,15 @@
return kErrorNone;
}
+DisplayError DisplayVirtual::Prepare(LayerStack *layer_stack) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ // Clean hw layers for reuse.
+ hw_layers_ = HWLayers();
+
+ return DisplayBase::Prepare(layer_stack);
+}
+
+
} // namespace sdm
diff --git a/sdm/libs/core/display_virtual.h b/sdm/libs/core/display_virtual.h
index 20ccc6e..3207ec1 100644
--- a/sdm/libs/core/display_virtual.h
+++ b/sdm/libs/core/display_virtual.h
@@ -39,6 +39,7 @@
BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
RotatorInterface *rotator_intf);
virtual DisplayError Init();
+ virtual DisplayError Prepare(LayerStack *layer_stack);
virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
virtual DisplayError GetActiveConfig(uint32_t *index);
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 0a72c17..79e968c 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -836,6 +836,8 @@
panel_info->needs_roi_merge = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "dyn_fps_en", strlen("dyn_fps_en"))) {
panel_info->dynamic_fps = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "dfps_porch_mode", strlen("dfps_porch_mode"))) {
+ panel_info->dfps_porch_mode = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
panel_info->min_fps = UINT32(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
diff --git a/sdm/libs/core/fb/hw_info.cpp b/sdm/libs/core/fb/hw_info.cpp
index dc01e39..81d81a3 100644
--- a/sdm/libs/core/fb/hw_info.cpp
+++ b/sdm/libs/core/fb/hw_info.cpp
@@ -249,6 +249,8 @@
hw_resource->has_qseed3 = true;
} else if (!strncmp(tokens[i], "concurrent_writeback", strlen("concurrent_writeback"))) {
hw_resource->has_concurrent_writeback = true;
+ } else if (!strncmp(tokens[i], "avr", strlen("avr"))) {
+ hw_resource->has_avr = true;
}
}
} else if (!strncmp(tokens[0], "pipe_count", strlen("pipe_count"))) {
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index 8fce14b..c475423 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -57,6 +57,14 @@
#define MDP_COMMIT_CWB_DSPP 0x1000
#endif
+#ifndef MDP_COMMIT_AVR_EN
+#define MDP_COMMIT_AVR_EN 0x08
+#endif
+
+#ifndef MDP_COMMIT_AVR_ONE_SHOT_MODE
+#define MDP_COMMIT_AVR_ONE_SHOT_MODE 0x10
+#endif
+
namespace sdm {
using std::string;
@@ -389,6 +397,10 @@
DLOGI_IF(kTagDriverConfig, "****************************************************************");
}
+ if (hw_resource_.has_avr) {
+ SetAVRFlags(hw_layers->hw_avr_info, &mdp_commit.flags);
+ }
+
return HWDevice::Validate(hw_layers);
}
@@ -620,5 +632,15 @@
hw_panel_info_.split_info.left_split : mixer_attributes_.width;
}
+void HWPrimary::SetAVRFlags(const HWAVRInfo &hw_avr_info, uint32_t *avr_flags) {
+ if (hw_avr_info.enable) {
+ *avr_flags |= MDP_COMMIT_AVR_EN;
+ }
+
+ if (hw_avr_info.mode == kOneShotMode) {
+ *avr_flags |= MDP_COMMIT_AVR_ONE_SHOT_MODE;
+ }
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h
index a517b06..ae45318 100644
--- a/sdm/libs/core/fb/hw_primary.h
+++ b/sdm/libs/core/fb/hw_primary.h
@@ -77,6 +77,7 @@
bool IsResolutionSwitchEnabled() { return !display_configs_.empty(); }
bool GetCurrentModeFromSysfs(size_t *curr_x_pixels, size_t *curr_y_pixels);
void UpdateMixerAttributes();
+ void SetAVRFlags(const HWAVRInfo &hw_avr_info, uint32_t *avr_flags);
std::vector<DisplayConfigVariableInfo> display_configs_;
std::vector<std::string> display_config_strings_;
diff --git a/sdm/libs/utils/debug.cpp b/sdm/libs/utils/debug.cpp
index b91cdf4..d6417d3 100644
--- a/sdm/libs/utils/debug.cpp
+++ b/sdm/libs/utils/debug.cpp
@@ -140,6 +140,13 @@
return (ubwc_framebuffer == 1);
}
+bool Debug::IsAVRDisabled() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty("sdm.debug.disable_avr", &value);
+
+ return (value == 1);
+}
+
bool Debug::GetProperty(const char* property_name, char* value) {
if (debug_.debug_handler_->GetProperty(property_name, value) != kErrorNone) {
return false;