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
This commit is contained in:
Ramkumar Radhakrishnan
2016-07-14 20:29:12 -07:00
parent e1534f237c
commit 14a1fc6de8
13 changed files with 82 additions and 2 deletions

View File

@@ -110,6 +110,11 @@ enum HWPipeFlags {
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 @@ struct HWResourceInfo {
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 @@ struct HWPanelInfo {
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 @@ struct HWPanelInfo {
(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 @@ struct HWDestScaleInfo {
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 @@ struct HWLayers {
float output_compression = 1.0f;
uint32_t bandwidth = 0;
uint32_t clock = 0;
HWAVRInfo hw_avr_info = {};
};
struct HWDisplayAttributes : DisplayConfigVariableInfo {

View File

@@ -74,6 +74,7 @@ class Debug {
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);

View File

@@ -219,8 +219,6 @@ DisplayError DisplayBase::Prepare(LayerStack *layer_stack) {
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;

View File

@@ -114,6 +114,9 @@ DisplayError DisplayHDMI::Prepare(LayerStack *layer_stack) {
SetS3DMode(layer_stack);
// Clean hw layers for reuse.
hw_layers_ = HWLayers();
return DisplayBase::Prepare(layer_stack);
}

View File

@@ -70,6 +70,8 @@ DisplayError DisplayPrimary::Init() {
}
}
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 @@ DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) {
}
}
// Clean hw layers for reuse.
hw_layers_ = HWLayers();
hw_layers_.hw_avr_info.enable = NeedsAVREnable();
return DisplayBase::Prepare(layer_stack);
}
@@ -294,5 +300,15 @@ DisplayError DisplayPrimary::DisablePartialUpdateOneFrame() {
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

View File

@@ -60,9 +60,12 @@ class DisplayPrimary : public DisplayBase, HWEventHandler {
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

View File

@@ -130,5 +130,15 @@ DisplayError DisplayVirtual::SetActiveConfig(DisplayConfigVariableInfo *variable
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

View File

@@ -39,6 +39,7 @@ class DisplayVirtual : public DisplayBase {
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);

View File

@@ -836,6 +836,8 @@ void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) {
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"))) {

View File

@@ -249,6 +249,8 @@ DisplayError HWInfo::GetHWResourceInfo(HWResourceInfo *hw_resource) {
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"))) {

View File

@@ -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 @@ DisplayError HWPrimary::Validate(HWLayers *hw_layers) {
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 @@ void HWPrimary::UpdateMixerAttributes() {
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

View File

@@ -77,6 +77,7 @@ class HWPrimary : public HWDevice {
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_;

View File

@@ -140,6 +140,13 @@ bool Debug::IsUbwcTiledFrameBuffer() {
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;