1 /* 2 * Copyright (c) 2017, The Linux Foundation. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 13 * * Neither the name of The Linux Foundation nor the names of its 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #define __STDC_FORMAT_MACROS 31 32 #include <ctype.h> 33 #include <drm_lib_loader.h> 34 #include <drm_master.h> 35 #include <drm_res_mgr.h> 36 #include <fcntl.h> 37 #include <inttypes.h> 38 #include <linux/fb.h> 39 #include <math.h> 40 #include <stdio.h> 41 #include <string.h> 42 #include <sys/ioctl.h> 43 #include <sys/stat.h> 44 #include <sys/types.h> 45 #include <unistd.h> 46 #include <utils/constants.h> 47 #include <utils/debug.h> 48 #include <utils/sys.h> 49 50 #include <algorithm> 51 #include <string> 52 #include <utility> 53 #include <vector> 54 55 #include "hw_device_drm.h" 56 #include "hw_info_interface.h" 57 58 #define __CLASS__ "HWDeviceDRM" 59 60 using std::string; 61 using std::to_string; 62 using std::fstream; 63 using drm_utils::DRMMaster; 64 using drm_utils::DRMResMgr; 65 using drm_utils::DRMLibLoader; 66 using sde_drm::GetDRMManager; 67 using sde_drm::DestroyDRMManager; 68 using sde_drm::DRMDisplayType; 69 using sde_drm::DRMDisplayToken; 70 using sde_drm::DRMConnectorInfo; 71 using sde_drm::DRMRect; 72 using sde_drm::DRMBlendType; 73 using sde_drm::DRMOps; 74 using sde_drm::DRMTopology; 75 76 namespace sdm { 77 78 HWDeviceDRM::HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf) 79 : hw_info_intf_(hw_info_intf), buffer_sync_handler_(buffer_sync_handler) { 80 device_type_ = kDevicePrimary; 81 device_name_ = "Peripheral Display"; 82 hw_info_intf_ = hw_info_intf; 83 } 84 85 DisplayError HWDeviceDRM::Init() { 86 default_mode_ = (DRMLibLoader::GetInstance()->IsLoaded() == false); 87 88 if (!default_mode_) { 89 DRMMaster *drm_master = {}; 90 int dev_fd = -1; 91 DRMMaster::GetInstance(&drm_master); 92 drm_master->GetHandle(&dev_fd); 93 DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_); 94 if (drm_mgr_intf_->RegisterDisplay(DRMDisplayType::PERIPHERAL, &token_)) { 95 DLOGE("RegisterDisplay failed"); 96 return kErrorResources; 97 } 98 99 drm_mgr_intf_->CreateAtomicReq(token_, &drm_atomic_intf_); 100 drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_); 101 InitializeConfigs(); 102 drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, ¤t_mode_); 103 #ifdef USE_SPECULATIVE_FENCES 104 drm_atomic_intf_->Perform(DRMOps::CRTC_SET_OUTPUT_FENCE_OFFSET, token_.crtc_id, 1); 105 #endif 106 // TODO(user): Enable this and remove the one in SetupAtomic() onces underruns are fixed 107 // drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1); 108 // Commit to setup pipeline with mode, which then tells us the topology etc 109 if (drm_atomic_intf_->Commit(true /* synchronous */)) { 110 DLOGE("Setting up CRTC %d, Connector %d for %s failed", token_.crtc_id, token_.conn_id, 111 device_name_); 112 return kErrorResources; 113 } 114 115 // Reload connector info for updated info after 1st commit 116 drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_); 117 DLOGI("Setup CRTC %d, Connector %d for %s", token_.crtc_id, token_.conn_id, device_name_); 118 } 119 120 PopulateDisplayAttributes(); 121 PopulateHWPanelInfo(); 122 UpdateMixerAttributes(); 123 hw_info_intf_->GetHWResourceInfo(&hw_resource_); 124 125 return kErrorNone; 126 } 127 128 DisplayError HWDeviceDRM::Deinit() { 129 drm_mgr_intf_->DestroyAtomicReq(drm_atomic_intf_); 130 drm_atomic_intf_ = {}; 131 drm_mgr_intf_->UnregisterDisplay(token_); 132 return kErrorNone; 133 } 134 135 void HWDeviceDRM::InitializeConfigs() { 136 // TODO(user): Update modes 137 current_mode_ = connector_info_.modes[0]; 138 } 139 140 DisplayError HWDeviceDRM::PopulateDisplayAttributes() { 141 drmModeModeInfo mode = {}; 142 uint32_t mm_width = 0; 143 uint32_t mm_height = 0; 144 DRMTopology topology = DRMTopology::SINGLE_LM; 145 146 if (default_mode_) { 147 DRMResMgr *res_mgr = nullptr; 148 int ret = DRMResMgr::GetInstance(&res_mgr); 149 if (ret < 0) { 150 DLOGE("Failed to acquire DRMResMgr instance"); 151 return kErrorResources; 152 } 153 154 res_mgr->GetMode(&mode); 155 res_mgr->GetDisplayDimInMM(&mm_width, &mm_height); 156 } else { 157 mode = current_mode_; 158 mm_width = connector_info_.mmWidth; 159 mm_height = connector_info_.mmHeight; 160 topology = connector_info_.topology; 161 } 162 163 display_attributes_.x_pixels = mode.hdisplay; 164 display_attributes_.y_pixels = mode.vdisplay; 165 display_attributes_.fps = mode.vrefresh; 166 display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps); 167 168 /* 169 Active Front Sync Back 170 Region Porch Porch 171 <-----------------------><----------------><-------------><--------------> 172 <----- [hv]display -----> 173 <------------- [hv]sync_start ------------> 174 <--------------------- [hv]sync_end ---------------------> 175 <-------------------------------- [hv]total -----------------------------> 176 */ 177 178 display_attributes_.v_front_porch = mode.vsync_start - mode.vdisplay; 179 display_attributes_.v_pulse_width = mode.vsync_end - mode.vsync_start; 180 display_attributes_.v_back_porch = mode.vtotal - mode.vsync_end; 181 display_attributes_.v_total = mode.vtotal; 182 183 display_attributes_.h_total = mode.htotal; 184 uint32_t h_blanking = mode.htotal - mode.hdisplay; 185 display_attributes_.is_device_split = 186 (topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_MERGE); 187 display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0; 188 189 display_attributes_.x_dpi = (FLOAT(mode.hdisplay) * 25.4f) / FLOAT(mm_width); 190 display_attributes_.y_dpi = (FLOAT(mode.vdisplay) * 25.4f) / FLOAT(mm_height); 191 192 return kErrorNone; 193 } 194 195 void HWDeviceDRM::PopulateHWPanelInfo() { 196 hw_panel_info_ = {}; 197 198 snprintf(hw_panel_info_.panel_name, sizeof(hw_panel_info_.panel_name), "%s", 199 connector_info_.panel_name.c_str()); 200 hw_panel_info_.split_info.left_split = display_attributes_.x_pixels; 201 if (display_attributes_.is_device_split) { 202 hw_panel_info_.split_info.left_split = hw_panel_info_.split_info.right_split = 203 display_attributes_.x_pixels / 2; 204 } 205 206 hw_panel_info_.partial_update = 0; 207 hw_panel_info_.left_align = 0; 208 hw_panel_info_.width_align = 0; 209 hw_panel_info_.top_align = 0; 210 hw_panel_info_.height_align = 0; 211 hw_panel_info_.min_roi_width = 0; 212 hw_panel_info_.min_roi_height = 0; 213 hw_panel_info_.needs_roi_merge = 0; 214 hw_panel_info_.dynamic_fps = connector_info_.dynamic_fps; 215 hw_panel_info_.min_fps = 60; 216 hw_panel_info_.max_fps = 60; 217 hw_panel_info_.is_primary_panel = connector_info_.is_primary; 218 hw_panel_info_.is_pluggable = 0; 219 220 if (!default_mode_) { 221 hw_panel_info_.needs_roi_merge = (connector_info_.topology == DRMTopology::DUAL_LM_MERGE); 222 } 223 224 GetHWDisplayPortAndMode(); 225 GetHWPanelMaxBrightness(); 226 227 DLOGI("%s, Panel Interface = %s, Panel Mode = %s, Is Primary = %d", device_name_, 228 interface_str_.c_str(), hw_panel_info_.mode == kModeVideo ? "Video" : "Command", 229 hw_panel_info_.is_primary_panel); 230 DLOGI("Partial Update = %d, Dynamic FPS = %d", hw_panel_info_.partial_update, 231 hw_panel_info_.dynamic_fps); 232 DLOGI("Align: left = %d, width = %d, top = %d, height = %d", hw_panel_info_.left_align, 233 hw_panel_info_.width_align, hw_panel_info_.top_align, hw_panel_info_.height_align); 234 DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d", hw_panel_info_.min_roi_width, 235 hw_panel_info_.min_roi_height, hw_panel_info_.needs_roi_merge); 236 DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps); 237 DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split, 238 hw_panel_info_.split_info.right_split); 239 } 240 241 void HWDeviceDRM::GetHWDisplayPortAndMode() { 242 hw_panel_info_.port = kPortDefault; 243 hw_panel_info_.mode = 244 (connector_info_.panel_mode == sde_drm::DRMPanelMode::VIDEO) ? kModeVideo : kModeCommand; 245 246 if (default_mode_) { 247 return; 248 } 249 250 switch (connector_info_.type) { 251 case DRM_MODE_CONNECTOR_DSI: 252 hw_panel_info_.port = kPortDSI; 253 interface_str_ = "DSI"; 254 break; 255 case DRM_MODE_CONNECTOR_LVDS: 256 hw_panel_info_.port = kPortLVDS; 257 interface_str_ = "LVDS"; 258 break; 259 case DRM_MODE_CONNECTOR_eDP: 260 hw_panel_info_.port = kPortEDP; 261 interface_str_ = "EDP"; 262 break; 263 case DRM_MODE_CONNECTOR_TV: 264 case DRM_MODE_CONNECTOR_HDMIA: 265 case DRM_MODE_CONNECTOR_HDMIB: 266 hw_panel_info_.port = kPortDTV; 267 interface_str_ = "HDMI"; 268 break; 269 case DRM_MODE_CONNECTOR_VIRTUAL: 270 hw_panel_info_.port = kPortWriteBack; 271 interface_str_ = "Virtual"; 272 break; 273 case DRM_MODE_CONNECTOR_DisplayPort: 274 // TODO(user): Add when available 275 interface_str_ = "DisplayPort"; 276 break; 277 } 278 279 return; 280 } 281 282 void HWDeviceDRM::GetHWPanelMaxBrightness() { 283 char brightness[kMaxStringLength] = {0}; 284 char kMaxBrightnessNode[64] = {0}; 285 286 snprintf(kMaxBrightnessNode, sizeof(kMaxBrightnessNode), "%s", 287 "/sys/class/leds/lcd-backlight/max_brightness"); 288 289 hw_panel_info_.panel_max_brightness = 255; 290 int fd = Sys::open_(kMaxBrightnessNode, O_RDONLY); 291 if (fd < 0) { 292 DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode, 293 strerror(errno)); 294 return; 295 } 296 297 if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) { 298 hw_panel_info_.panel_max_brightness = atoi(brightness); 299 DLOGI("Max brightness level = %d", hw_panel_info_.panel_max_brightness); 300 } else { 301 DLOGW("Failed to read max brightness level. error = %s", strerror(errno)); 302 } 303 304 Sys::close_(fd); 305 } 306 307 DisplayError HWDeviceDRM::GetActiveConfig(uint32_t *active_config) { 308 *active_config = 0; 309 return kErrorNone; 310 } 311 312 DisplayError HWDeviceDRM::GetNumDisplayAttributes(uint32_t *count) { 313 *count = 1; 314 return kErrorNone; 315 } 316 317 DisplayError HWDeviceDRM::GetDisplayAttributes(uint32_t index, 318 HWDisplayAttributes *display_attributes) { 319 *display_attributes = display_attributes_; 320 return kErrorNone; 321 } 322 323 DisplayError HWDeviceDRM::GetHWPanelInfo(HWPanelInfo *panel_info) { 324 *panel_info = hw_panel_info_; 325 return kErrorNone; 326 } 327 328 DisplayError HWDeviceDRM::SetDisplayAttributes(uint32_t index) { 329 return kErrorNone; 330 } 331 332 DisplayError HWDeviceDRM::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) { 333 return kErrorNotSupported; 334 } 335 336 DisplayError HWDeviceDRM::GetConfigIndex(uint32_t mode, uint32_t *index) { 337 return kErrorNone; 338 } 339 340 DisplayError HWDeviceDRM::PowerOn() { 341 DTRACE_SCOPED(); 342 return kErrorNone; 343 } 344 345 DisplayError HWDeviceDRM::PowerOff() { 346 return kErrorNone; 347 } 348 349 DisplayError HWDeviceDRM::Doze() { 350 return kErrorNone; 351 } 352 353 DisplayError HWDeviceDRM::DozeSuspend() { 354 return kErrorNone; 355 } 356 357 DisplayError HWDeviceDRM::Standby() { 358 return kErrorNone; 359 } 360 361 void HWDeviceDRM::SetupAtomic(HWLayers *hw_layers, bool validate) { 362 if (default_mode_) { 363 return; 364 } 365 366 HWLayersInfo &hw_layer_info = hw_layers->info; 367 uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size()); 368 369 for (uint32_t i = 0; i < hw_layer_count; i++) { 370 Layer &layer = hw_layer_info.hw_layers.at(i); 371 LayerBuffer &input_buffer = layer.input_buffer; 372 HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe; 373 HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe; 374 375 // TODO(user): Add support for solid fill 376 if (layer.flags.solid_fill) { 377 continue; 378 } 379 380 for (uint32_t count = 0; count < 2; count++) { 381 HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe; 382 if (pipe_info->valid) { 383 uint32_t pipe_id = pipe_info->pipe_id; 384 if (input_buffer.fb_id == 0) { 385 // We set these to 0 to clear any previous cycle's state from another buffer. 386 // Unfortunately this layer will be skipped from validation because it's dimensions are 387 // tied to fb_id which is not available yet. 388 drm_atomic_intf_->Perform(DRMOps::PLANE_SET_FB_ID, pipe_id, 0); 389 drm_atomic_intf_->Perform(DRMOps::PLANE_SET_CRTC, pipe_id, 0); 390 continue; 391 } 392 drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ALPHA, pipe_id, layer.plane_alpha); 393 drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ZORDER, pipe_id, pipe_info->z_order); 394 DRMBlendType blending = {}; 395 SetBlending(layer.blending, &blending); 396 drm_atomic_intf_->Perform(DRMOps::PLANE_SET_BLEND_TYPE, pipe_id, blending); 397 DRMRect src = {}; 398 SetRect(pipe_info->src_roi, &src); 399 drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SRC_RECT, pipe_id, src); 400 DRMRect dst = {}; 401 SetRect(pipe_info->dst_roi, &dst); 402 drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DST_RECT, pipe_id, dst); 403 uint32_t rot_bit_mask = 0; 404 if (layer.transform.flip_horizontal) { 405 rot_bit_mask |= 1 << DRM_REFLECT_X; 406 } 407 if (layer.transform.flip_vertical) { 408 rot_bit_mask |= 1 << DRM_REFLECT_Y; 409 } 410 411 drm_atomic_intf_->Perform(DRMOps::PLANE_SET_H_DECIMATION, pipe_id, 412 pipe_info->horizontal_decimation); 413 drm_atomic_intf_->Perform(DRMOps::PLANE_SET_V_DECIMATION, pipe_id, 414 pipe_info->vertical_decimation); 415 drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION, pipe_id, rot_bit_mask); 416 drm_atomic_intf_->Perform(DRMOps::PLANE_SET_FB_ID, pipe_id, input_buffer.fb_id); 417 drm_atomic_intf_->Perform(DRMOps::PLANE_SET_CRTC, pipe_id, token_.crtc_id); 418 if (!validate && input_buffer.acquire_fence_fd >= 0) { 419 drm_atomic_intf_->Perform(DRMOps::PLANE_SET_INPUT_FENCE, pipe_id, 420 input_buffer.acquire_fence_fd); 421 } 422 } 423 } 424 425 // TODO(user): Remove this and enable the one in Init() onces underruns are fixed 426 drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1); 427 } 428 } 429 430 DisplayError HWDeviceDRM::Validate(HWLayers *hw_layers) { 431 DTRACE_SCOPED(); 432 SetupAtomic(hw_layers, true /* validate */); 433 434 int ret = drm_atomic_intf_->Validate(); 435 if (ret) { 436 DLOGE("%s failed with error %d", __FUNCTION__, ret); 437 return kErrorHardware; 438 } 439 440 return kErrorNone; 441 } 442 443 DisplayError HWDeviceDRM::Commit(HWLayers *hw_layers) { 444 DTRACE_SCOPED(); 445 if (default_mode_) { 446 return DefaultCommit(hw_layers); 447 } 448 449 return AtomicCommit(hw_layers); 450 } 451 452 DisplayError HWDeviceDRM::DefaultCommit(HWLayers *hw_layers) { 453 DTRACE_SCOPED(); 454 455 HWLayersInfo &hw_layer_info = hw_layers->info; 456 LayerStack *stack = hw_layer_info.stack; 457 458 stack->retire_fence_fd = -1; 459 for (Layer &layer : hw_layer_info.hw_layers) { 460 layer.input_buffer.release_fence_fd = -1; 461 } 462 463 DRMMaster *master = nullptr; 464 int ret = DRMMaster::GetInstance(&master); 465 if (ret < 0) { 466 DLOGE("Failed to acquire DRMMaster instance"); 467 return kErrorResources; 468 } 469 470 DRMResMgr *res_mgr = nullptr; 471 ret = DRMResMgr::GetInstance(&res_mgr); 472 if (ret < 0) { 473 DLOGE("Failed to acquire DRMResMgr instance"); 474 return kErrorResources; 475 } 476 477 int dev_fd = -1; 478 master->GetHandle(&dev_fd); 479 480 uint32_t connector_id = 0; 481 res_mgr->GetConnectorId(&connector_id); 482 483 uint32_t crtc_id = 0; 484 res_mgr->GetCrtcId(&crtc_id); 485 486 drmModeModeInfo mode; 487 res_mgr->GetMode(&mode); 488 489 LayerBuffer &input_buffer = hw_layer_info.hw_layers.at(0).input_buffer; 490 ret = drmModeSetCrtc(dev_fd, crtc_id, input_buffer.fb_id, 0 /* x */, 0 /* y */, &connector_id, 491 1 /* num_connectors */, &mode); 492 if (ret < 0) { 493 DLOGE("drmModeSetCrtc failed dev fd %d, fb_id %d, crtc id %d, connector id %d, %s", dev_fd, 494 input_buffer.fb_id, crtc_id, connector_id, strerror(errno)); 495 return kErrorHardware; 496 } 497 498 return kErrorNone; 499 } 500 501 DisplayError HWDeviceDRM::AtomicCommit(HWLayers *hw_layers) { 502 DTRACE_SCOPED(); 503 SetupAtomic(hw_layers, false /* validate */); 504 505 int ret = drm_atomic_intf_->Commit(false /* synchronous */); 506 if (ret) { 507 DLOGE("%s failed with error %d", __FUNCTION__, ret); 508 return kErrorHardware; 509 } 510 511 int release_fence = -1; 512 int retire_fence = -1; 513 514 drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence); 515 drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE, token_.conn_id, &retire_fence); 516 517 HWLayersInfo &hw_layer_info = hw_layers->info; 518 LayerStack *stack = hw_layer_info.stack; 519 stack->retire_fence_fd = retire_fence; 520 521 for (Layer &layer : hw_layer_info.hw_layers) { 522 layer.input_buffer.release_fence_fd = Sys::dup_(release_fence); 523 } 524 525 hw_layer_info.sync_handle = release_fence; 526 527 return kErrorNone; 528 } 529 530 DisplayError HWDeviceDRM::Flush() { 531 return kErrorNone; 532 } 533 534 void HWDeviceDRM::SetBlending(const LayerBlending &source, DRMBlendType *target) { 535 switch (source) { 536 case kBlendingPremultiplied: 537 *target = DRMBlendType::PREMULTIPLIED; 538 break; 539 case kBlendingOpaque: 540 *target = DRMBlendType::OPAQUE; 541 break; 542 case kBlendingCoverage: 543 *target = DRMBlendType::COVERAGE; 544 break; 545 default: 546 *target = DRMBlendType::UNDEFINED; 547 } 548 } 549 550 void HWDeviceDRM::SetRect(const LayerRect &source, DRMRect *target) { 551 target->left = UINT32(source.left); 552 target->top = UINT32(source.top); 553 target->right = UINT32(source.right); 554 target->bottom = UINT32(source.bottom); 555 } 556 557 bool HWDeviceDRM::EnableHotPlugDetection(int enable) { 558 return true; 559 } 560 561 void HWDeviceDRM::ResetDisplayParams() {} 562 563 DisplayError HWDeviceDRM::SetCursorPosition(HWLayers *hw_layers, int x, int y) { 564 DTRACE_SCOPED(); 565 return kErrorNone; 566 } 567 568 DisplayError HWDeviceDRM::GetPPFeaturesVersion(PPFeatureVersion *vers) { 569 return kErrorNotSupported; 570 } 571 572 DisplayError HWDeviceDRM::SetPPFeatures(PPFeaturesConfig *feature_list) { 573 return kErrorNotSupported; 574 } 575 576 DisplayError HWDeviceDRM::SetVSyncState(bool enable) { 577 return kErrorNone; 578 } 579 580 void HWDeviceDRM::SetIdleTimeoutMs(uint32_t timeout_ms) {} 581 582 DisplayError HWDeviceDRM::SetDisplayMode(const HWDisplayMode hw_display_mode) { 583 return kErrorNotSupported; 584 } 585 586 DisplayError HWDeviceDRM::SetRefreshRate(uint32_t refresh_rate) { 587 return kErrorNotSupported; 588 } 589 590 DisplayError HWDeviceDRM::SetPanelBrightness(int level) { 591 return kErrorNotSupported; 592 } 593 594 DisplayError HWDeviceDRM::GetHWScanInfo(HWScanInfo *scan_info) { 595 return kErrorNotSupported; 596 } 597 598 DisplayError HWDeviceDRM::GetVideoFormat(uint32_t config_index, uint32_t *video_format) { 599 return kErrorNotSupported; 600 } 601 602 DisplayError HWDeviceDRM::GetMaxCEAFormat(uint32_t *max_cea_format) { 603 return kErrorNotSupported; 604 } 605 606 DisplayError HWDeviceDRM::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) { 607 return kErrorNotSupported; 608 } 609 610 DisplayError HWDeviceDRM::GetPanelBrightness(int *level) { 611 return kErrorNotSupported; 612 } 613 614 DisplayError HWDeviceDRM::SetS3DMode(HWS3DMode s3d_mode) { 615 return kErrorNotSupported; 616 } 617 618 DisplayError HWDeviceDRM::SetScaleLutConfig(HWScaleLutInfo *lut_info) { 619 return kErrorNone; 620 } 621 622 DisplayError HWDeviceDRM::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) { 623 if (!hw_resource_.hw_dest_scalar_info.count) { 624 return kErrorNotSupported; 625 } 626 627 if (mixer_attributes.width > display_attributes_.x_pixels || 628 mixer_attributes.height > display_attributes_.y_pixels) { 629 DLOGW("Input resolution exceeds display resolution! input: res %dx%d display: res %dx%d", 630 mixer_attributes.width, mixer_attributes.height, display_attributes_.x_pixels, 631 display_attributes_.y_pixels); 632 return kErrorNotSupported; 633 } 634 635 uint32_t max_input_width = hw_resource_.hw_dest_scalar_info.max_input_width; 636 if (display_attributes_.is_device_split) { 637 max_input_width *= 2; 638 } 639 640 if (mixer_attributes.width > max_input_width) { 641 DLOGW("Input width exceeds width limit! input_width %d width_limit %d", mixer_attributes.width, 642 max_input_width); 643 return kErrorNotSupported; 644 } 645 646 float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height); 647 float display_aspect_ratio = 648 FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels); 649 650 if (display_aspect_ratio != mixer_aspect_ratio) { 651 DLOGW("Aspect ratio mismatch! input: res %dx%d display: res %dx%d", mixer_attributes.width, 652 mixer_attributes.height, display_attributes_.x_pixels, display_attributes_.y_pixels); 653 return kErrorNotSupported; 654 } 655 656 float scale_x = FLOAT(display_attributes_.x_pixels) / FLOAT(mixer_attributes.width); 657 float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height); 658 float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up; 659 if (scale_x > max_scale_up || scale_y > max_scale_up) { 660 DLOGW( 661 "Up scaling ratio exceeds for destination scalar upscale limit scale_x %f scale_y %f " 662 "max_scale_up %f", 663 scale_x, scale_y, max_scale_up); 664 return kErrorNotSupported; 665 } 666 667 float mixer_split_ratio = FLOAT(mixer_attributes_.split_left) / FLOAT(mixer_attributes_.width); 668 669 mixer_attributes_ = mixer_attributes; 670 mixer_attributes_.split_left = mixer_attributes_.width; 671 if (display_attributes_.is_device_split) { 672 mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio); 673 } 674 675 return kErrorNone; 676 } 677 678 DisplayError HWDeviceDRM::GetMixerAttributes(HWMixerAttributes *mixer_attributes) { 679 if (!mixer_attributes) { 680 return kErrorParameters; 681 } 682 683 mixer_attributes_.width = display_attributes_.x_pixels; 684 mixer_attributes_.height = display_attributes_.y_pixels; 685 mixer_attributes_.split_left = display_attributes_.is_device_split 686 ? hw_panel_info_.split_info.left_split 687 : mixer_attributes_.width; 688 *mixer_attributes = mixer_attributes_; 689 690 return kErrorNone; 691 } 692 693 void HWDeviceDRM::UpdateMixerAttributes() { 694 mixer_attributes_.width = display_attributes_.x_pixels; 695 mixer_attributes_.height = display_attributes_.y_pixels; 696 mixer_attributes_.split_left = display_attributes_.is_device_split 697 ? hw_panel_info_.split_info.left_split 698 : mixer_attributes_.width; 699 } 700 701 } // namespace sdm 702