Home | History | Annotate | Download | only in drm
      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, &current_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