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 35 namespace sdm { 36 37 DisplayPrimary::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 44 DisplayError 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 73 DisplayError DisplayPrimary::Deinit() { 74 SCOPE_LOCK(locker_); 75 76 DisplayError error = DisplayBase::Deinit(); 77 HWPrimary::Destroy(hw_intf_); 78 79 return error; 80 } 81 82 DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) { 83 SCOPE_LOCK(locker_); 84 return DisplayBase::Prepare(layer_stack); 85 } 86 87 DisplayError 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 126 DisplayError DisplayPrimary::Flush() { 127 SCOPE_LOCK(locker_); 128 return DisplayBase::Flush(); 129 } 130 131 DisplayError DisplayPrimary::GetDisplayState(DisplayState *state) { 132 SCOPE_LOCK(locker_); 133 return DisplayBase::GetDisplayState(state); 134 } 135 136 DisplayError DisplayPrimary::GetNumVariableInfoConfigs(uint32_t *count) { 137 SCOPE_LOCK(locker_); 138 return DisplayBase::GetNumVariableInfoConfigs(count); 139 } 140 141 DisplayError DisplayPrimary::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) { 142 SCOPE_LOCK(locker_); 143 return DisplayBase::GetConfig(index, variable_info); 144 } 145 146 DisplayError DisplayPrimary::GetActiveConfig(uint32_t *index) { 147 SCOPE_LOCK(locker_); 148 return DisplayBase::GetActiveConfig(index); 149 } 150 151 DisplayError DisplayPrimary::GetVSyncState(bool *enabled) { 152 SCOPE_LOCK(locker_); 153 return DisplayBase::GetVSyncState(enabled); 154 } 155 156 bool DisplayPrimary::IsUnderscanSupported() { 157 SCOPE_LOCK(locker_); 158 return DisplayBase::IsUnderscanSupported(); 159 } 160 161 DisplayError 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 177 DisplayError DisplayPrimary::SetActiveConfig(DisplayConfigVariableInfo *variable_info) { 178 SCOPE_LOCK(locker_); 179 return kErrorNotSupported; 180 } 181 182 DisplayError DisplayPrimary::SetActiveConfig(uint32_t index) { 183 SCOPE_LOCK(locker_); 184 return DisplayBase::SetActiveConfig(index); 185 } 186 187 DisplayError 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 200 void 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 210 DisplayError DisplayPrimary::SetMaxMixerStages(uint32_t max_mixer_stages) { 211 SCOPE_LOCK(locker_); 212 return DisplayBase::SetMaxMixerStages(max_mixer_stages); 213 } 214 215 DisplayError 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 266 DisplayError DisplayPrimary::SetPanelBrightness(int level) { 267 SCOPE_LOCK(locker_); 268 return hw_intf_->SetPanelBrightness(level); 269 } 270 271 DisplayError DisplayPrimary::IsScalingValid(const LayerRect &crop, const LayerRect &dst, 272 bool rotate90) { 273 SCOPE_LOCK(locker_); 274 return DisplayBase::IsScalingValid(crop, dst, rotate90); 275 } 276 277 DisplayError 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 292 DisplayError 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 326 void DisplayPrimary::AppendDump(char *buffer, uint32_t length) { 327 SCOPE_LOCK(locker_); 328 DisplayBase::AppendDump(buffer, length); 329 } 330 331 DisplayError 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 341 DisplayError DisplayPrimary::SetCursorPosition(int x, int y) { 342 SCOPE_LOCK(locker_); 343 return DisplayBase::SetCursorPosition(x, y); 344 } 345 346 DisplayError DisplayPrimary::Blank(bool blank) { 347 SCOPE_LOCK(locker_); 348 return kErrorNone; 349 } 350 351 void DisplayPrimary::IdleTimeout() { 352 event_handler_->Refresh(); 353 comp_manager_->ProcessIdleTimeout(display_comp_ctx_); 354 } 355 356 void DisplayPrimary::ThermalEvent(int64_t thermal_level) { 357 SCOPE_LOCK(locker_); 358 comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level); 359 } 360 361 DisplayError DisplayPrimary::GetPanelBrightness(int *level) { 362 SCOPE_LOCK(locker_); 363 return hw_intf_->GetPanelBrightness(level); 364 } 365 366 } // namespace sdm 367 368