1/* 2* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. 3* 4* Redistribution and use in source and binary forms, with or without modification, are permitted 5* provided that the following conditions are met: 6* * Redistributions of source code must retain the above copyright notice, this list of 7* conditions and the following disclaimer. 8* * Redistributions in binary form must reproduce the above copyright notice, this list of 9* conditions and the following disclaimer in the documentation and/or other materials provided 10* with the distribution. 11* * Neither the name of The Linux Foundation nor the names of its contributors may be used to 12* endorse or promote products derived from this software without specific prior written 13* permission. 14* 15* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 21* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23*/ 24 25#include <utils/constants.h> 26#include <utils/debug.h> 27#include <utils/rect.h> 28#include <map> 29#include <algorithm> 30#include <functional> 31#include <vector> 32 33#include "display_primary.h" 34#include "hw_interface.h" 35#include "hw_info_interface.h" 36#include "fb/hw_primary.h" 37 38#define __CLASS__ "DisplayPrimary" 39 40namespace sdm { 41 42DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf, 43 BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager, 44 RotatorInterface *rotator_intf) 45 : DisplayBase(kPrimary, event_handler, kDevicePrimary, buffer_sync_handler, comp_manager, 46 rotator_intf, hw_info_intf) { 47} 48 49DisplayError DisplayPrimary::Init() { 50 lock_guard<recursive_mutex> obj(recursive_mutex_); 51 52 DisplayError error = HWPrimary::Create(&hw_intf_, hw_info_intf_, 53 DisplayBase::buffer_sync_handler_); 54 55 if (error != kErrorNone) { 56 return error; 57 } 58 59 error = DisplayBase::Init(); 60 if (error != kErrorNone) { 61 HWPrimary::Destroy(hw_intf_); 62 return error; 63 } 64 65 idle_timeout_ms_ = Debug::GetIdleTimeoutMs(); 66 67 if (hw_panel_info_.mode == kModeCommand && Debug::IsVideoModeEnabled()) { 68 error = hw_intf_->SetDisplayMode(kModeVideo); 69 if (error != kErrorNone) { 70 DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode, 71 kModeVideo); 72 } 73 } 74 75 error = HWEventsInterface::Create(INT(display_type_), this, &event_list_, &hw_events_intf_); 76 if (error != kErrorNone) { 77 DLOGE("Failed to create hardware events interface. Error = %d", error); 78 DisplayBase::Deinit(); 79 HWPrimary::Destroy(hw_intf_); 80 } 81 82 return error; 83} 84 85DisplayError DisplayPrimary::Deinit() { 86 lock_guard<recursive_mutex> obj(recursive_mutex_); 87 88 DisplayError error = DisplayBase::Deinit(); 89 HWPrimary::Destroy(hw_intf_); 90 91 return error; 92} 93 94DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) { 95 lock_guard<recursive_mutex> obj(recursive_mutex_); 96 DisplayError error = kErrorNone; 97 uint32_t new_mixer_width = 0; 98 uint32_t new_mixer_height = 0; 99 uint32_t display_width = display_attributes_.x_pixels; 100 uint32_t display_height = display_attributes_.y_pixels; 101 102 if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) { 103 error = ReconfigureMixer(new_mixer_width, new_mixer_height); 104 if (error != kErrorNone) { 105 ReconfigureMixer(display_width, display_height); 106 } 107 } 108 109 return DisplayBase::Prepare(layer_stack); 110} 111 112DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) { 113 lock_guard<recursive_mutex> obj(recursive_mutex_); 114 DisplayError error = kErrorNone; 115 116 // Enabling auto refresh is async and needs to happen before commit ioctl 117 if (hw_panel_info_.mode == kModeCommand) { 118 hw_intf_->SetAutoRefresh(layer_stack->flags.single_buffered_layer_present); 119 } 120 121 bool set_idle_timeout = comp_manager_->CanSetIdleTimeout(display_comp_ctx_); 122 123 error = DisplayBase::Commit(layer_stack); 124 if (error != kErrorNone) { 125 return error; 126 } 127 128 DisplayBase::ReconfigureDisplay(); 129 130 if (hw_panel_info_.mode == kModeVideo) { 131 if (set_idle_timeout && !layer_stack->flags.single_buffered_layer_present) { 132 hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_); 133 } else { 134 hw_intf_->SetIdleTimeoutMs(0); 135 } 136 } 137 138 return error; 139} 140 141DisplayError DisplayPrimary::SetDisplayState(DisplayState state) { 142 lock_guard<recursive_mutex> obj(recursive_mutex_); 143 DisplayError error = kErrorNone; 144 error = DisplayBase::SetDisplayState(state); 145 if (error != kErrorNone) { 146 return error; 147 } 148 149 // Set vsync enable state to false, as driver disables vsync during display power off. 150 if (state == kStateOff) { 151 vsync_enable_ = false; 152 } 153 154 return kErrorNone; 155} 156 157void DisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) { 158 lock_guard<recursive_mutex> obj(recursive_mutex_); 159 160 // Idle fallback feature is supported only for video mode panel. 161 if (hw_panel_info_.mode == kModeVideo) { 162 hw_intf_->SetIdleTimeoutMs(timeout_ms); 163 } 164 idle_timeout_ms_ = timeout_ms; 165} 166 167DisplayError DisplayPrimary::SetDisplayMode(uint32_t mode) { 168 lock_guard<recursive_mutex> obj(recursive_mutex_); 169 DisplayError error = kErrorNone; 170 HWDisplayMode hw_display_mode = static_cast<HWDisplayMode>(mode); 171 uint32_t pending = 0; 172 173 if (!active_) { 174 DLOGW("Invalid display state = %d. Panel must be on.", state_); 175 return kErrorNotSupported; 176 } 177 178 if (hw_display_mode != kModeCommand && hw_display_mode != kModeVideo) { 179 DLOGW("Invalid panel mode parameters. Requested = %d", hw_display_mode); 180 return kErrorParameters; 181 } 182 183 if (hw_display_mode == hw_panel_info_.mode) { 184 DLOGW("Same display mode requested. Current = %d, Requested = %d", hw_panel_info_.mode, 185 hw_display_mode); 186 return kErrorNone; 187 } 188 189 error = hw_intf_->SetDisplayMode(hw_display_mode); 190 if (error != kErrorNone) { 191 DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode, 192 hw_display_mode); 193 return error; 194 } 195 196 if (mode == kModeVideo) { 197 ControlPartialUpdate(false /* enable */, &pending); 198 hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_); 199 } else if (mode == kModeCommand) { 200 ControlPartialUpdate(true /* enable */, &pending); 201 hw_intf_->SetIdleTimeoutMs(0); 202 } 203 204 return error; 205} 206 207DisplayError DisplayPrimary::SetPanelBrightness(int level) { 208 lock_guard<recursive_mutex> obj(recursive_mutex_); 209 return hw_intf_->SetPanelBrightness(level); 210} 211 212DisplayError DisplayPrimary::GetRefreshRateRange(uint32_t *min_refresh_rate, 213 uint32_t *max_refresh_rate) { 214 lock_guard<recursive_mutex> obj(recursive_mutex_); 215 DisplayError error = kErrorNone; 216 217 if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) { 218 *min_refresh_rate = hw_panel_info_.min_fps; 219 *max_refresh_rate = hw_panel_info_.max_fps; 220 } else { 221 error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate); 222 } 223 224 return error; 225} 226 227DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate) { 228 lock_guard<recursive_mutex> obj(recursive_mutex_); 229 230 if (!active_ || !hw_panel_info_.dynamic_fps) { 231 return kErrorNotSupported; 232 } 233 234 if (refresh_rate < hw_panel_info_.min_fps || refresh_rate > hw_panel_info_.max_fps) { 235 DLOGE("Invalid Fps = %d request", refresh_rate); 236 return kErrorParameters; 237 } 238 239 DisplayError error = hw_intf_->SetRefreshRate(refresh_rate); 240 if (error != kErrorNone) { 241 return error; 242 } 243 244 return DisplayBase::ReconfigureDisplay(); 245} 246 247DisplayError DisplayPrimary::VSync(int64_t timestamp) { 248 if (vsync_enable_) { 249 DisplayEventVSync vsync; 250 vsync.timestamp = timestamp; 251 event_handler_->VSync(vsync); 252 } 253 254 return kErrorNone; 255} 256 257void DisplayPrimary::IdleTimeout() { 258 event_handler_->Refresh(); 259 comp_manager_->ProcessIdleTimeout(display_comp_ctx_); 260 AllDisplaysNeedValidate(); 261} 262 263void DisplayPrimary::ThermalEvent(int64_t thermal_level) { 264 lock_guard<recursive_mutex> obj(recursive_mutex_); 265 comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level); 266 if (thermal_level >= kMaxThermalLevel) { 267 AllDisplaysNeedValidate(); 268 } 269} 270 271DisplayError DisplayPrimary::GetPanelBrightness(int *level) { 272 lock_guard<recursive_mutex> obj(recursive_mutex_); 273 return hw_intf_->GetPanelBrightness(level); 274} 275 276DisplayError DisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) { 277 lock_guard<recursive_mutex> obj(recursive_mutex_); 278 if (!pending) { 279 return kErrorParameters; 280 } 281 282 if (!hw_panel_info_.partial_update) { 283 // Nothing to be done. 284 DLOGI("partial update is not applicable for display=%d", display_type_); 285 return kErrorNotSupported; 286 } 287 288 *pending = 0; 289 if (enable == partial_update_control_) { 290 DLOGI("Same state transition is requested."); 291 return kErrorNone; 292 } 293 294 partial_update_control_ = enable; 295 296 if (!enable) { 297 // If the request is to turn off feature, new draw call is required to have 298 // the new setting into effect. 299 *pending = 1; 300 } 301 302 return kErrorNone; 303} 304 305DisplayError DisplayPrimary::DisablePartialUpdateOneFrame() { 306 lock_guard<recursive_mutex> obj(recursive_mutex_); 307 disable_pu_one_frame_ = true; 308 309 return kErrorNone; 310} 311 312} // namespace sdm 313 314