1/* 2* Copyright (c) 2014 - 2015, 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 28#include "display_primary.h" 29#include "hw_interface.h" 30#include "hw_info_interface.h" 31#include "fb/hw_primary.h" 32 33#define __CLASS__ "DisplayPrimary" 34 35namespace sdm { 36 37DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf, 38 BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager, 39 RotatorInterface *rotator_intf) 40 : DisplayBase(kPrimary, event_handler, kDevicePrimary, buffer_sync_handler, comp_manager, 41 rotator_intf, hw_info_intf) { 42} 43 44DisplayError DisplayPrimary::Init() { 45 SCOPE_LOCK(locker_); 46 47 DisplayError error = HWPrimary::Create(&hw_intf_, hw_info_intf_, 48 DisplayBase::buffer_sync_handler_, this); 49 50 if (error != kErrorNone) { 51 return error; 52 } 53 54 error = DisplayBase::Init(); 55 if (error != kErrorNone) { 56 HWPrimary::Destroy(hw_intf_); 57 return error; 58 } 59 60 idle_timeout_ms_ = Debug::GetIdleTimeoutMs(); 61 62 if (hw_panel_info_.mode == kModeCommand && Debug::IsVideoModeEnabled()) { 63 error = hw_intf_->SetDisplayMode(kModeVideo); 64 if (error != kErrorNone) { 65 DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode, 66 kModeVideo); 67 } 68 } 69 70 return error; 71} 72 73DisplayError DisplayPrimary::Deinit() { 74 SCOPE_LOCK(locker_); 75 76 DisplayError error = DisplayBase::Deinit(); 77 HWPrimary::Destroy(hw_intf_); 78 79 return error; 80} 81 82DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) { 83 SCOPE_LOCK(locker_); 84 return DisplayBase::Prepare(layer_stack); 85} 86 87DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) { 88 SCOPE_LOCK(locker_); 89 DisplayError error = kErrorNone; 90 HWPanelInfo panel_info; 91 HWDisplayAttributes display_attributes; 92 uint32_t active_index = 0; 93 94 // Enabling auto refresh is async and needs to happen before commit ioctl 95 if (hw_panel_info_.mode == kModeCommand) { 96 hw_intf_->SetAutoRefresh(layer_stack->flags.single_buffered_layer_present); 97 } 98 99 bool set_idle_timeout = comp_manager_->CanSetIdleTimeout(display_comp_ctx_); 100 101 error = DisplayBase::Commit(layer_stack); 102 if (error != kErrorNone) { 103 return error; 104 } 105 106 hw_intf_->GetHWPanelInfo(&panel_info); 107 hw_intf_->GetActiveConfig(&active_index); 108 hw_intf_->GetDisplayAttributes(active_index, &display_attributes); 109 110 if (panel_info != hw_panel_info_) { 111 error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info); 112 hw_panel_info_ = panel_info; 113 } 114 115 if (hw_panel_info_.mode == kModeVideo) { 116 if (set_idle_timeout && !layer_stack->flags.single_buffered_layer_present) { 117 hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_); 118 } else { 119 hw_intf_->SetIdleTimeoutMs(0); 120 } 121 } 122 123 return error; 124} 125 126DisplayError DisplayPrimary::Flush() { 127 SCOPE_LOCK(locker_); 128 return DisplayBase::Flush(); 129} 130 131DisplayError DisplayPrimary::GetDisplayState(DisplayState *state) { 132 SCOPE_LOCK(locker_); 133 return DisplayBase::GetDisplayState(state); 134} 135 136DisplayError DisplayPrimary::GetNumVariableInfoConfigs(uint32_t *count) { 137 SCOPE_LOCK(locker_); 138 return DisplayBase::GetNumVariableInfoConfigs(count); 139} 140 141DisplayError DisplayPrimary::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) { 142 SCOPE_LOCK(locker_); 143 return DisplayBase::GetConfig(index, variable_info); 144} 145 146DisplayError DisplayPrimary::GetActiveConfig(uint32_t *index) { 147 SCOPE_LOCK(locker_); 148 return DisplayBase::GetActiveConfig(index); 149} 150 151DisplayError DisplayPrimary::GetVSyncState(bool *enabled) { 152 SCOPE_LOCK(locker_); 153 return DisplayBase::GetVSyncState(enabled); 154} 155 156bool DisplayPrimary::IsUnderscanSupported() { 157 SCOPE_LOCK(locker_); 158 return DisplayBase::IsUnderscanSupported(); 159} 160 161DisplayError DisplayPrimary::SetDisplayState(DisplayState state) { 162 SCOPE_LOCK(locker_); 163 DisplayError error = kErrorNone; 164 error = DisplayBase::SetDisplayState(state); 165 if (error != kErrorNone) { 166 return error; 167 } 168 169 // Set vsync enable state to false, as driver disables vsync during display power off. 170 if (state == kStateOff) { 171 vsync_enable_ = false; 172 } 173 174 return kErrorNone; 175} 176 177DisplayError DisplayPrimary::SetActiveConfig(DisplayConfigVariableInfo *variable_info) { 178 SCOPE_LOCK(locker_); 179 return kErrorNotSupported; 180} 181 182DisplayError DisplayPrimary::SetActiveConfig(uint32_t index) { 183 SCOPE_LOCK(locker_); 184 return DisplayBase::SetActiveConfig(index); 185} 186 187DisplayError DisplayPrimary::SetVSyncState(bool enable) { 188 SCOPE_LOCK(locker_); 189 DisplayError error = kErrorNone; 190 if (vsync_enable_ != enable) { 191 error = hw_intf_->SetVSyncState(enable); 192 if (error == kErrorNone) { 193 vsync_enable_ = enable; 194 } 195 } 196 197 return error; 198} 199 200void DisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) { 201 SCOPE_LOCK(locker_); 202 203 // Idle fallback feature is supported only for video mode panel. 204 if (hw_panel_info_.mode == kModeVideo) { 205 hw_intf_->SetIdleTimeoutMs(timeout_ms); 206 } 207 idle_timeout_ms_ = timeout_ms; 208} 209 210DisplayError DisplayPrimary::SetMaxMixerStages(uint32_t max_mixer_stages) { 211 SCOPE_LOCK(locker_); 212 return DisplayBase::SetMaxMixerStages(max_mixer_stages); 213} 214 215DisplayError DisplayPrimary::SetDisplayMode(uint32_t mode) { 216 SCOPE_LOCK(locker_); 217 DisplayError error = kErrorNone; 218 HWDisplayMode hw_display_mode = kModeDefault; 219 220 if (!active_) { 221 DLOGW("Invalid display state = %d. Panel must be on.", state_); 222 return kErrorNotSupported; 223 } 224 225 switch (mode) { 226 case kModeVideo: 227 hw_display_mode = kModeVideo; 228 break; 229 case kModeCommand: 230 hw_display_mode = kModeCommand; 231 break; 232 default: 233 DLOGW("Invalid panel mode parameters. Requested = %d", mode); 234 return kErrorParameters; 235 } 236 237 if (hw_display_mode == hw_panel_info_.mode) { 238 DLOGW("Same display mode requested. Current = %d, Requested = %d", hw_panel_info_.mode, 239 hw_display_mode); 240 return kErrorNone; 241 } 242 243 error = hw_intf_->SetDisplayMode(hw_display_mode); 244 if (error != kErrorNone) { 245 DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode, 246 hw_display_mode); 247 return error; 248 } 249 250 // Disable PU if the previous PU state is on when switching to video mode, and re-enable PU when 251 // switching back to command mode. 252 bool toggle_partial_update = !(hw_display_mode == kModeVideo); 253 if (partial_update_control_) { 254 comp_manager_->ControlPartialUpdate(display_comp_ctx_, toggle_partial_update); 255 } 256 257 if (hw_display_mode == kModeVideo) { 258 hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_); 259 } else if (hw_display_mode == kModeCommand) { 260 hw_intf_->SetIdleTimeoutMs(0); 261 } 262 263 return error; 264} 265 266DisplayError DisplayPrimary::SetPanelBrightness(int level) { 267 SCOPE_LOCK(locker_); 268 return hw_intf_->SetPanelBrightness(level); 269} 270 271DisplayError DisplayPrimary::IsScalingValid(const LayerRect &crop, const LayerRect &dst, 272 bool rotate90) { 273 SCOPE_LOCK(locker_); 274 return DisplayBase::IsScalingValid(crop, dst, rotate90); 275} 276 277DisplayError DisplayPrimary::GetRefreshRateRange(uint32_t *min_refresh_rate, 278 uint32_t *max_refresh_rate) { 279 SCOPE_LOCK(locker_); 280 DisplayError error = kErrorNone; 281 282 if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) { 283 *min_refresh_rate = hw_panel_info_.min_fps; 284 *max_refresh_rate = hw_panel_info_.max_fps; 285 } else { 286 error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate); 287 } 288 289 return error; 290} 291 292DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate) { 293 SCOPE_LOCK(locker_); 294 295 if (!active_ || !hw_panel_info_.dynamic_fps) { 296 return kErrorNotSupported; 297 } 298 299 if (refresh_rate < hw_panel_info_.min_fps || refresh_rate > hw_panel_info_.max_fps) { 300 DLOGE("Invalid Fps = %d request", refresh_rate); 301 return kErrorParameters; 302 } 303 304 DisplayError error = hw_intf_->SetRefreshRate(refresh_rate); 305 if (error != kErrorNone) { 306 return error; 307 } 308 309 HWDisplayAttributes display_attributes; 310 uint32_t active_index = 0; 311 error = hw_intf_->GetActiveConfig(&active_index); 312 if (error != kErrorNone) { 313 return error; 314 } 315 316 error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes); 317 if (error != kErrorNone) { 318 return error; 319 } 320 321 comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info_); 322 323 return kErrorNone; 324} 325 326void DisplayPrimary::AppendDump(char *buffer, uint32_t length) { 327 SCOPE_LOCK(locker_); 328 DisplayBase::AppendDump(buffer, length); 329} 330 331DisplayError DisplayPrimary::VSync(int64_t timestamp) { 332 if (vsync_enable_) { 333 DisplayEventVSync vsync; 334 vsync.timestamp = timestamp; 335 event_handler_->VSync(vsync); 336 } 337 338 return kErrorNone; 339} 340 341DisplayError DisplayPrimary::SetCursorPosition(int x, int y) { 342 SCOPE_LOCK(locker_); 343 return DisplayBase::SetCursorPosition(x, y); 344} 345 346DisplayError DisplayPrimary::Blank(bool blank) { 347 SCOPE_LOCK(locker_); 348 return kErrorNone; 349} 350 351void DisplayPrimary::IdleTimeout() { 352 event_handler_->Refresh(); 353 comp_manager_->ProcessIdleTimeout(display_comp_ctx_); 354} 355 356void DisplayPrimary::ThermalEvent(int64_t thermal_level) { 357 SCOPE_LOCK(locker_); 358 comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level); 359} 360 361DisplayError DisplayPrimary::GetPanelBrightness(int *level) { 362 SCOPE_LOCK(locker_); 363 return hw_intf_->GetPanelBrightness(level); 364} 365 366} // namespace sdm 367 368