1/* 2* Copyright (c) 2014 - 2017, 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 37#define __CLASS__ "DisplayPrimary" 38 39namespace sdm { 40 41DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf, 42 BufferSyncHandler *buffer_sync_handler, 43 BufferAllocator *buffer_allocator, CompManager *comp_manager) 44 : DisplayBase(kPrimary, event_handler, kDevicePrimary, buffer_sync_handler, buffer_allocator, 45 comp_manager, hw_info_intf) { 46} 47 48DisplayError DisplayPrimary::Init() { 49 lock_guard<recursive_mutex> obj(recursive_mutex_); 50 51 DisplayError error = HWInterface::Create(kPrimary, hw_info_intf_, buffer_sync_handler_, 52 buffer_allocator_, &hw_intf_); 53 if (error != kErrorNone) { 54 return error; 55 } 56 57 error = DisplayBase::Init(); 58 if (error != kErrorNone) { 59 HWInterface::Destroy(hw_intf_); 60 return error; 61 } 62 63 if (hw_panel_info_.mode == kModeCommand && Debug::IsVideoModeEnabled()) { 64 error = hw_intf_->SetDisplayMode(kModeVideo); 65 if (error != kErrorNone) { 66 DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode, 67 kModeVideo); 68 } 69 } 70 71 avr_prop_disabled_ = Debug::IsAVRDisabled(); 72 73 error = HWEventsInterface::Create(INT(display_type_), this, event_list_, &hw_events_intf_); 74 if (error != kErrorNone) { 75 DLOGE("Failed to create hardware events interface. Error = %d", error); 76 DisplayBase::Deinit(); 77 HWInterface::Destroy(hw_intf_); 78 } 79 80 return error; 81} 82 83DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) { 84 lock_guard<recursive_mutex> obj(recursive_mutex_); 85 DisplayError error = kErrorNone; 86 uint32_t new_mixer_width = 0; 87 uint32_t new_mixer_height = 0; 88 uint32_t display_width = display_attributes_.x_pixels; 89 uint32_t display_height = display_attributes_.y_pixels; 90 91 if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) { 92 error = ReconfigureMixer(new_mixer_width, new_mixer_height); 93 if (error != kErrorNone) { 94 ReconfigureMixer(display_width, display_height); 95 } 96 } 97 98 // Clean hw layers for reuse. 99 hw_layers_ = HWLayers(); 100 hw_layers_.hw_avr_info.enable = NeedsAVREnable(); 101 102 return DisplayBase::Prepare(layer_stack); 103} 104 105DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) { 106 lock_guard<recursive_mutex> obj(recursive_mutex_); 107 DisplayError error = kErrorNone; 108 uint32_t app_layer_count = hw_layers_.info.app_layer_count; 109 110 // Enabling auto refresh is async and needs to happen before commit ioctl 111 if (hw_panel_info_.mode == kModeCommand) { 112 bool enable = (app_layer_count == 1) && layer_stack->flags.single_buffered_layer_present; 113 bool need_refresh = layer_stack->flags.single_buffered_layer_present && (app_layer_count > 1); 114 115 hw_intf_->SetAutoRefresh(enable); 116 if (need_refresh) { 117 event_handler_->Refresh(); 118 } 119 } 120 121 error = DisplayBase::Commit(layer_stack); 122 if (error != kErrorNone) { 123 return error; 124 } 125 126 DisplayBase::ReconfigureDisplay(); 127 128 int idle_time_ms = hw_layers_.info.set_idle_time_ms; 129 if (idle_time_ms >= 0) { 130 hw_intf_->SetIdleTimeoutMs(UINT32(idle_time_ms)); 131 } 132 133 if (switch_to_cmd_) { 134 uint32_t pending; 135 switch_to_cmd_ = false; 136 ControlPartialUpdate(true /* enable */, &pending); 137 } 138 139 return error; 140} 141 142DisplayError DisplayPrimary::SetDisplayState(DisplayState state) { 143 lock_guard<recursive_mutex> obj(recursive_mutex_); 144 DisplayError error = kErrorNone; 145 error = DisplayBase::SetDisplayState(state); 146 if (error != kErrorNone) { 147 return error; 148 } 149 150 // Set vsync enable state to false, as driver disables vsync during display power off. 151 if (state == kStateOff) { 152 vsync_enable_ = false; 153 } 154 155 return kErrorNone; 156} 157 158void DisplayPrimary::SetIdleTimeoutMs(uint32_t active_ms) { 159 lock_guard<recursive_mutex> obj(recursive_mutex_); 160 161 if (comp_manager_->SetIdleTimeoutMs(display_comp_ctx_, active_ms) == kErrorNone) { 162 hw_intf_->SetIdleTimeoutMs(active_ms); 163 } 164} 165 166DisplayError DisplayPrimary::SetDisplayMode(uint32_t mode) { 167 DisplayError error = kErrorNone; 168 169 // Limit scope of mutex to this block 170 { 171 lock_guard<recursive_mutex> obj(recursive_mutex_); 172 HWDisplayMode hw_display_mode = static_cast<HWDisplayMode>(mode); 173 uint32_t pending = 0; 174 175 if (!active_) { 176 DLOGW("Invalid display state = %d. Panel must be on.", state_); 177 return kErrorNotSupported; 178 } 179 180 if (hw_display_mode != kModeCommand && hw_display_mode != kModeVideo) { 181 DLOGW("Invalid panel mode parameters. Requested = %d", hw_display_mode); 182 return kErrorParameters; 183 } 184 185 if (hw_display_mode == hw_panel_info_.mode) { 186 DLOGW("Same display mode requested. Current = %d, Requested = %d", hw_panel_info_.mode, 187 hw_display_mode); 188 return kErrorNone; 189 } 190 191 error = hw_intf_->SetDisplayMode(hw_display_mode); 192 if (error != kErrorNone) { 193 DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode, 194 hw_display_mode); 195 return error; 196 } 197 198 if (mode == kModeVideo) { 199 ControlPartialUpdate(false /* enable */, &pending); 200 } else if (mode == kModeCommand) { 201 // Flush idle timeout value currently set. 202 hw_intf_->SetIdleTimeoutMs(0); 203 switch_to_cmd_ = true; 204 } 205 } 206 207 // Request for a new draw cycle. New display mode will get applied on next draw cycle. 208 // New idle time will get configured as part of this. 209 event_handler_->Refresh(); 210 211 return error; 212} 213 214DisplayError DisplayPrimary::SetPanelBrightness(int level) { 215 lock_guard<recursive_mutex> obj(recursive_mutex_); 216 return hw_intf_->SetPanelBrightness(level); 217} 218 219DisplayError DisplayPrimary::CachePanelBrightness(int level) { 220 lock_guard<recursive_mutex> obj(recursive_mutex_); 221 return hw_intf_->CachePanelBrightness(level); 222} 223 224DisplayError DisplayPrimary::GetRefreshRateRange(uint32_t *min_refresh_rate, 225 uint32_t *max_refresh_rate) { 226 lock_guard<recursive_mutex> obj(recursive_mutex_); 227 DisplayError error = kErrorNone; 228 229 if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) { 230 *min_refresh_rate = hw_panel_info_.min_fps; 231 *max_refresh_rate = hw_panel_info_.max_fps; 232 } else { 233 error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate); 234 } 235 236 return error; 237} 238 239DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate) { 240 lock_guard<recursive_mutex> obj(recursive_mutex_); 241 242 if (!active_ || !hw_panel_info_.dynamic_fps) { 243 return kErrorNotSupported; 244 } 245 246 if (refresh_rate < hw_panel_info_.min_fps || refresh_rate > hw_panel_info_.max_fps) { 247 DLOGE("Invalid Fps = %d request", refresh_rate); 248 return kErrorParameters; 249 } 250 251 DisplayError error = hw_intf_->SetRefreshRate(refresh_rate); 252 if (error != kErrorNone) { 253 return error; 254 } 255 256 return DisplayBase::ReconfigureDisplay(); 257} 258 259DisplayError DisplayPrimary::VSync(int64_t timestamp) { 260 if (vsync_enable_) { 261 DisplayEventVSync vsync; 262 vsync.timestamp = timestamp; 263 event_handler_->VSync(vsync); 264 } 265 266 return kErrorNone; 267} 268 269void DisplayPrimary::IdleTimeout() { 270 event_handler_->Refresh(); 271 comp_manager_->ProcessIdleTimeout(display_comp_ctx_); 272 event_handler_->HandleEvent(kIdleTimeout); 273} 274 275void DisplayPrimary::ThermalEvent(int64_t thermal_level) { 276 lock_guard<recursive_mutex> obj(recursive_mutex_); 277 comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level); 278 event_handler_->HandleEvent(kThermalEvent); 279} 280 281void DisplayPrimary::IdlePowerCollapse() { 282 lock_guard<recursive_mutex> obj(recursive_mutex_); 283 comp_manager_->ProcessIdlePowerCollapse(display_comp_ctx_); 284} 285 286DisplayError DisplayPrimary::GetPanelBrightness(int *level) { 287 lock_guard<recursive_mutex> obj(recursive_mutex_); 288 return hw_intf_->GetPanelBrightness(level); 289} 290 291DisplayError DisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) { 292 lock_guard<recursive_mutex> obj(recursive_mutex_); 293 if (!pending) { 294 return kErrorParameters; 295 } 296 297 if (!hw_panel_info_.partial_update) { 298 // Nothing to be done. 299 DLOGI("partial update is not applicable for display=%d", display_type_); 300 return kErrorNotSupported; 301 } 302 303 *pending = 0; 304 if (enable == partial_update_control_) { 305 DLOGI("Same state transition is requested."); 306 return kErrorNone; 307 } 308 309 partial_update_control_ = enable; 310 311 if (!enable) { 312 // If the request is to turn off feature, new draw call is required to have 313 // the new setting into effect. 314 *pending = 1; 315 } 316 317 return kErrorNone; 318} 319 320DisplayError DisplayPrimary::DisablePartialUpdateOneFrame() { 321 lock_guard<recursive_mutex> obj(recursive_mutex_); 322 disable_pu_one_frame_ = true; 323 324 return kErrorNone; 325} 326 327bool DisplayPrimary::NeedsAVREnable() { 328 if (avr_prop_disabled_) { 329 return false; 330 } 331 332 return (hw_panel_info_.mode == kModeVideo && ((hw_panel_info_.dynamic_fps && 333 hw_panel_info_.dfps_porch_mode) || (!hw_panel_info_.dynamic_fps && 334 hw_panel_info_.min_fps != hw_panel_info_.max_fps))); 335} 336 337} // namespace sdm 338 339