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