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/drm_fourcc.h>
34#include <drm_lib_loader.h>
35#include <drm_master.h>
36#include <drm_res_mgr.h>
37#include <fcntl.h>
38#include <inttypes.h>
39#include <linux/fb.h>
40#include <math.h>
41#include <stdio.h>
42#include <string.h>
43#include <sys/ioctl.h>
44#include <sys/stat.h>
45#include <sys/types.h>
46#include <unistd.h>
47#include <utils/constants.h>
48#include <utils/debug.h>
49#include <utils/formats.h>
50#include <utils/sys.h>
51#include <private/color_params.h>
52
53#include <algorithm>
54#include <string>
55#include <unordered_map>
56#include <utility>
57#include <vector>
58
59#include "hw_device_drm.h"
60#include "hw_info_interface.h"
61#include "hw_color_manager_drm.h"
62
63#define __CLASS__ "HWDeviceDRM"
64
65#ifndef DRM_FORMAT_MOD_QCOM_COMPRESSED
66#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
67#endif
68#ifndef DRM_FORMAT_MOD_QCOM_DX
69#define DRM_FORMAT_MOD_QCOM_DX fourcc_mod_code(QCOM, 0x2)
70#endif
71#ifndef DRM_FORMAT_MOD_QCOM_TIGHT
72#define DRM_FORMAT_MOD_QCOM_TIGHT fourcc_mod_code(QCOM, 0x4)
73#endif
74
75using std::string;
76using std::to_string;
77using std::fstream;
78using std::unordered_map;
79using drm_utils::DRMMaster;
80using drm_utils::DRMResMgr;
81using drm_utils::DRMLibLoader;
82using drm_utils::DRMBuffer;
83using sde_drm::GetDRMManager;
84using sde_drm::DestroyDRMManager;
85using sde_drm::DRMDisplayType;
86using sde_drm::DRMDisplayToken;
87using sde_drm::DRMConnectorInfo;
88using sde_drm::DRMPPFeatureInfo;
89using sde_drm::DRMRect;
90using sde_drm::DRMRotation;
91using sde_drm::DRMBlendType;
92using sde_drm::DRMSrcConfig;
93using sde_drm::DRMOps;
94using sde_drm::DRMTopology;
95
96namespace sdm {
97
98static void GetDRMFormat(LayerBufferFormat format, uint32_t *drm_format,
99                         uint64_t *drm_format_modifier) {
100  switch (format) {
101    case kFormatRGBA8888:
102      *drm_format = DRM_FORMAT_ABGR8888;
103      break;
104    case kFormatRGBA8888Ubwc:
105      *drm_format = DRM_FORMAT_ABGR8888;
106      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
107      break;
108    case kFormatRGBA5551:
109      *drm_format = DRM_FORMAT_ABGR1555;
110      break;
111    case kFormatRGBA4444:
112      *drm_format = DRM_FORMAT_ABGR4444;
113      break;
114    case kFormatBGRA8888:
115      *drm_format = DRM_FORMAT_ARGB8888;
116      break;
117    case kFormatRGBX8888:
118      *drm_format = DRM_FORMAT_XBGR8888;
119      break;
120    case kFormatRGBX8888Ubwc:
121      *drm_format = DRM_FORMAT_XBGR8888;
122      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
123      break;
124    case kFormatBGRX8888:
125      *drm_format = DRM_FORMAT_XRGB8888;
126      break;
127    case kFormatRGB888:
128      *drm_format = DRM_FORMAT_BGR888;
129      break;
130    case kFormatRGB565:
131      *drm_format = DRM_FORMAT_BGR565;
132      break;
133    case kFormatBGR565:
134      *drm_format = DRM_FORMAT_RGB565;
135      break;
136    case kFormatBGR565Ubwc:
137      *drm_format = DRM_FORMAT_BGR565;
138      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
139      break;
140    case kFormatRGBA1010102:
141      *drm_format = DRM_FORMAT_ABGR2101010;
142      break;
143    case kFormatRGBA1010102Ubwc:
144      *drm_format = DRM_FORMAT_ABGR2101010;
145      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
146      break;
147    case kFormatARGB2101010:
148      *drm_format = DRM_FORMAT_BGRA1010102;
149      break;
150    case kFormatRGBX1010102:
151      *drm_format = DRM_FORMAT_XBGR2101010;
152      break;
153    case kFormatRGBX1010102Ubwc:
154      *drm_format = DRM_FORMAT_XBGR2101010;
155      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
156      break;
157    case kFormatXRGB2101010:
158      *drm_format = DRM_FORMAT_BGRX1010102;
159      break;
160    case kFormatBGRA1010102:
161      *drm_format = DRM_FORMAT_ARGB2101010;
162      break;
163    case kFormatABGR2101010:
164      *drm_format = DRM_FORMAT_RGBA1010102;
165      break;
166    case kFormatBGRX1010102:
167      *drm_format = DRM_FORMAT_XRGB2101010;
168      break;
169    case kFormatXBGR2101010:
170      *drm_format = DRM_FORMAT_RGBX1010102;
171      break;
172    case kFormatYCbCr420SemiPlanar:
173      *drm_format = DRM_FORMAT_NV12;
174      break;
175    case kFormatYCbCr420SemiPlanarVenus:
176      *drm_format = DRM_FORMAT_NV12;
177      break;
178    case kFormatYCbCr420SPVenusUbwc:
179      *drm_format = DRM_FORMAT_NV12;
180      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
181      break;
182    case kFormatYCrCb420SemiPlanar:
183      *drm_format = DRM_FORMAT_NV21;
184      break;
185    case kFormatYCrCb420SemiPlanarVenus:
186      *drm_format = DRM_FORMAT_NV21;
187      break;
188    case kFormatYCbCr420P010:
189      *drm_format = DRM_FORMAT_NV12;
190      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_DX;
191      break;
192    case kFormatYCbCr420P010Ubwc:
193      *drm_format = DRM_FORMAT_NV12;
194      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
195        DRM_FORMAT_MOD_QCOM_DX;
196      break;
197    case kFormatYCbCr420TP10Ubwc:
198      *drm_format = DRM_FORMAT_NV12;
199      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
200        DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_TIGHT;
201      break;
202    case kFormatYCbCr422H2V1SemiPlanar:
203      *drm_format = DRM_FORMAT_NV16;
204      break;
205    case kFormatYCrCb422H2V1SemiPlanar:
206      *drm_format = DRM_FORMAT_NV61;
207      break;
208    case kFormatYCrCb420PlanarStride16:
209      *drm_format = DRM_FORMAT_YVU420;
210      break;
211    default:
212      DLOGW("Unsupported format %s", GetFormatString(format));
213  }
214}
215
216void HWDeviceDRM::Registry::RegisterCurrent(HWLayers *hw_layers) {
217  DRMMaster *master = nullptr;
218  DRMMaster::GetInstance(&master);
219
220  if (!master) {
221    DLOGE("Failed to acquire DRM Master instance");
222    return;
223  }
224
225  HWLayersInfo &hw_layer_info = hw_layers->info;
226  uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
227
228  for (uint32_t i = 0; i < hw_layer_count; i++) {
229    Layer &layer = hw_layer_info.hw_layers.at(i);
230    LayerBuffer *input_buffer = &layer.input_buffer;
231    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
232    HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[0];
233
234    if (hw_rotate_info->valid) {
235      input_buffer = &hw_rotator_session->output_buffer;
236    }
237
238    int fd = input_buffer->planes[0].fd;
239    if (fd >= 0 && hashmap_[current_index_].find(fd) == hashmap_[current_index_].end()) {
240      AllocatedBufferInfo buf_info {};
241      DRMBuffer layout {};
242      buf_info.fd = layout.fd = fd;
243      buf_info.aligned_width = layout.width = input_buffer->width;
244      buf_info.aligned_height = layout.height = input_buffer->height;
245      buf_info.format = input_buffer->format;
246      GetDRMFormat(buf_info.format, &layout.drm_format, &layout.drm_format_modifier);
247      buffer_allocator_->GetBufferLayout(buf_info, layout.stride, layout.offset,
248                                         &layout.num_planes);
249      uint32_t fb_id = 0;
250      int ret = master->CreateFbId(layout, &fb_id);
251      if (ret < 0) {
252        DLOGE("CreateFbId failed. width %d, height %d, format: %s, stride %u, error %d",
253              layout.width, layout.height, GetFormatString(buf_info.format), layout.stride[0],
254              errno);
255      } else {
256        hashmap_[current_index_][fd] = fb_id;
257      }
258    }
259  }
260}
261
262void HWDeviceDRM::Registry::UnregisterNext() {
263  DRMMaster *master = nullptr;
264  DRMMaster::GetInstance(&master);
265
266  if (!master) {
267    DLOGE("Failed to acquire DRM Master instance");
268    return;
269  }
270
271  current_index_ = (current_index_ + 1) % kCycleDelay;
272  auto &curr_map = hashmap_[current_index_];
273  for (auto &pair : curr_map) {
274    uint32_t fb_id = pair.second;
275    int ret = master->RemoveFbId(fb_id);
276    if (ret < 0) {
277      DLOGE("Removing fb_id %d failed with error %d", fb_id, errno);
278    }
279  }
280
281  curr_map.clear();
282}
283
284void HWDeviceDRM::Registry::Clear() {
285  for (int i = 0; i < kCycleDelay; i++) {
286    UnregisterNext();
287  }
288  current_index_ = 0;
289}
290
291uint32_t HWDeviceDRM::Registry::GetFbId(int fd) {
292  auto it = hashmap_[current_index_].find(fd);
293  return (it == hashmap_[current_index_].end()) ? 0 : it->second;
294}
295
296HWDeviceDRM::HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
297                         HWInfoInterface *hw_info_intf)
298    : hw_info_intf_(hw_info_intf), buffer_sync_handler_(buffer_sync_handler),
299      registry_(buffer_allocator) {
300  device_type_ = kDevicePrimary;
301  device_name_ = "Peripheral Display";
302  hw_info_intf_ = hw_info_intf;
303}
304
305DisplayError HWDeviceDRM::Init() {
306  default_mode_ = (DRMLibLoader::GetInstance()->IsLoaded() == false);
307
308  if (!default_mode_) {
309    DRMMaster *drm_master = {};
310    int dev_fd = -1;
311    DRMMaster::GetInstance(&drm_master);
312    drm_master->GetHandle(&dev_fd);
313    DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_);
314    if (drm_mgr_intf_->RegisterDisplay(DRMDisplayType::PERIPHERAL, &token_)) {
315      DLOGE("RegisterDisplay failed");
316      return kErrorResources;
317    }
318
319    drm_mgr_intf_->CreateAtomicReq(token_, &drm_atomic_intf_);
320    drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
321    InitializeConfigs();
322    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, &current_mode_);
323
324    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_OUTPUT_FENCE_OFFSET, token_.crtc_id, 1);
325
326    // TODO(user): Enable this and remove the one in SetupAtomic() onces underruns are fixed
327    // drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
328    // Commit to setup pipeline with mode, which then tells us the topology etc
329    if (drm_atomic_intf_->Commit(true /* synchronous */)) {
330      DLOGE("Setting up CRTC %d, Connector %d for %s failed", token_.crtc_id, token_.conn_id,
331            device_name_);
332      return kErrorResources;
333    }
334
335    // Reload connector info for updated info after 1st commit
336    drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
337    DLOGI("Setup CRTC %d, Connector %d for %s", token_.crtc_id, token_.conn_id, device_name_);
338  }
339
340  PopulateDisplayAttributes();
341  PopulateHWPanelInfo();
342  UpdateMixerAttributes();
343  hw_info_intf_->GetHWResourceInfo(&hw_resource_);
344
345  // TODO(user): In future, remove has_qseed3 member, add version and pass version to constructor
346  if (hw_resource_.has_qseed3) {
347    hw_scale_ = new HWScaleDRM(HWScaleDRM::Version::V2);
348  }
349
350  return kErrorNone;
351}
352
353DisplayError HWDeviceDRM::Deinit() {
354  delete hw_scale_;
355  registry_.Clear();
356  drm_mgr_intf_->DestroyAtomicReq(drm_atomic_intf_);
357  drm_atomic_intf_ = {};
358  drm_mgr_intf_->UnregisterDisplay(token_);
359  return kErrorNone;
360}
361
362void HWDeviceDRM::InitializeConfigs() {
363  // TODO(user): Update modes
364  current_mode_ = connector_info_.modes[0];
365}
366
367DisplayError HWDeviceDRM::PopulateDisplayAttributes() {
368  drmModeModeInfo mode = {};
369  uint32_t mm_width = 0;
370  uint32_t mm_height = 0;
371  DRMTopology topology = DRMTopology::SINGLE_LM;
372
373  if (default_mode_) {
374    DRMResMgr *res_mgr = nullptr;
375    int ret = DRMResMgr::GetInstance(&res_mgr);
376    if (ret < 0) {
377      DLOGE("Failed to acquire DRMResMgr instance");
378      return kErrorResources;
379    }
380
381    res_mgr->GetMode(&mode);
382    res_mgr->GetDisplayDimInMM(&mm_width, &mm_height);
383  } else {
384    mode = current_mode_;
385    mm_width = connector_info_.mmWidth;
386    mm_height = connector_info_.mmHeight;
387    topology = connector_info_.topology;
388  }
389
390  display_attributes_.x_pixels = mode.hdisplay;
391  display_attributes_.y_pixels = mode.vdisplay;
392  display_attributes_.fps = mode.vrefresh;
393  display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps);
394
395  /*
396              Active                 Front           Sync           Back
397              Region                 Porch                          Porch
398     <-----------------------><----------------><-------------><-------------->
399     <----- [hv]display ----->
400     <------------- [hv]sync_start ------------>
401     <--------------------- [hv]sync_end --------------------->
402     <-------------------------------- [hv]total ----------------------------->
403   */
404
405  display_attributes_.v_front_porch = mode.vsync_start - mode.vdisplay;
406  display_attributes_.v_pulse_width = mode.vsync_end - mode.vsync_start;
407  display_attributes_.v_back_porch = mode.vtotal - mode.vsync_end;
408  display_attributes_.v_total = mode.vtotal;
409
410  display_attributes_.h_total = mode.htotal;
411  uint32_t h_blanking = mode.htotal - mode.hdisplay;
412  display_attributes_.is_device_split =
413      (topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_MERGE);
414  display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
415
416  display_attributes_.x_dpi = (FLOAT(mode.hdisplay) * 25.4f) / FLOAT(mm_width);
417  display_attributes_.y_dpi = (FLOAT(mode.vdisplay) * 25.4f) / FLOAT(mm_height);
418
419  return kErrorNone;
420}
421
422void HWDeviceDRM::PopulateHWPanelInfo() {
423  hw_panel_info_ = {};
424
425  snprintf(hw_panel_info_.panel_name, sizeof(hw_panel_info_.panel_name), "%s",
426           connector_info_.panel_name.c_str());
427  hw_panel_info_.split_info.left_split = display_attributes_.x_pixels;
428  if (display_attributes_.is_device_split) {
429    hw_panel_info_.split_info.left_split = hw_panel_info_.split_info.right_split =
430        display_attributes_.x_pixels / 2;
431  }
432
433  hw_panel_info_.partial_update = 0;
434  hw_panel_info_.left_align = 0;
435  hw_panel_info_.width_align = 0;
436  hw_panel_info_.top_align = 0;
437  hw_panel_info_.height_align = 0;
438  hw_panel_info_.min_roi_width = 0;
439  hw_panel_info_.min_roi_height = 0;
440  hw_panel_info_.needs_roi_merge = 0;
441  hw_panel_info_.dynamic_fps = connector_info_.dynamic_fps;
442  hw_panel_info_.min_fps = 60;
443  hw_panel_info_.max_fps = 60;
444  hw_panel_info_.is_primary_panel = connector_info_.is_primary;
445  hw_panel_info_.is_pluggable = 0;
446
447  if (!default_mode_) {
448    hw_panel_info_.needs_roi_merge = (connector_info_.topology == DRMTopology::DUAL_LM_MERGE);
449  }
450
451  GetHWDisplayPortAndMode();
452  GetHWPanelMaxBrightness();
453
454  DLOGI("%s, Panel Interface = %s, Panel Mode = %s, Is Primary = %d", device_name_,
455        interface_str_.c_str(), hw_panel_info_.mode == kModeVideo ? "Video" : "Command",
456        hw_panel_info_.is_primary_panel);
457  DLOGI("Partial Update = %d, Dynamic FPS = %d", hw_panel_info_.partial_update,
458        hw_panel_info_.dynamic_fps);
459  DLOGI("Align: left = %d, width = %d, top = %d, height = %d", hw_panel_info_.left_align,
460        hw_panel_info_.width_align, hw_panel_info_.top_align, hw_panel_info_.height_align);
461  DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d", hw_panel_info_.min_roi_width,
462        hw_panel_info_.min_roi_height, hw_panel_info_.needs_roi_merge);
463  DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps);
464  DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split,
465        hw_panel_info_.split_info.right_split);
466}
467
468void HWDeviceDRM::GetHWDisplayPortAndMode() {
469  hw_panel_info_.port = kPortDefault;
470  hw_panel_info_.mode =
471      (connector_info_.panel_mode == sde_drm::DRMPanelMode::VIDEO) ? kModeVideo : kModeCommand;
472
473  if (default_mode_) {
474    return;
475  }
476
477  switch (connector_info_.type) {
478    case DRM_MODE_CONNECTOR_DSI:
479      hw_panel_info_.port = kPortDSI;
480      interface_str_ = "DSI";
481      break;
482    case DRM_MODE_CONNECTOR_LVDS:
483      hw_panel_info_.port = kPortLVDS;
484      interface_str_ = "LVDS";
485      break;
486    case DRM_MODE_CONNECTOR_eDP:
487      hw_panel_info_.port = kPortEDP;
488      interface_str_ = "EDP";
489      break;
490    case DRM_MODE_CONNECTOR_TV:
491    case DRM_MODE_CONNECTOR_HDMIA:
492    case DRM_MODE_CONNECTOR_HDMIB:
493      hw_panel_info_.port = kPortDTV;
494      interface_str_ = "HDMI";
495      break;
496    case DRM_MODE_CONNECTOR_VIRTUAL:
497      hw_panel_info_.port = kPortWriteBack;
498      interface_str_ = "Virtual";
499      break;
500    case DRM_MODE_CONNECTOR_DisplayPort:
501      // TODO(user): Add when available
502      interface_str_ = "DisplayPort";
503      break;
504  }
505
506  return;
507}
508
509void HWDeviceDRM::GetHWPanelMaxBrightness() {
510  char brightness[kMaxStringLength] = {0};
511  string kMaxBrightnessNode = "/sys/class/backlight/panel0-backlight/max_brightness";
512
513  hw_panel_info_.panel_max_brightness = 255;
514  int fd = Sys::open_(kMaxBrightnessNode.c_str(), O_RDONLY);
515  if (fd < 0) {
516    DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode.c_str(),
517          strerror(errno));
518    return;
519  }
520
521  if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
522    hw_panel_info_.panel_max_brightness = atoi(brightness);
523    DLOGI("Max brightness level = %d", hw_panel_info_.panel_max_brightness);
524  } else {
525    DLOGW("Failed to read max brightness level. error = %s", strerror(errno));
526  }
527
528  Sys::close_(fd);
529}
530
531DisplayError HWDeviceDRM::GetActiveConfig(uint32_t *active_config) {
532  *active_config = 0;
533  return kErrorNone;
534}
535
536DisplayError HWDeviceDRM::GetNumDisplayAttributes(uint32_t *count) {
537  *count = 1;
538  return kErrorNone;
539}
540
541DisplayError HWDeviceDRM::GetDisplayAttributes(uint32_t index,
542                                            HWDisplayAttributes *display_attributes) {
543  *display_attributes = display_attributes_;
544  return kErrorNone;
545}
546
547DisplayError HWDeviceDRM::GetHWPanelInfo(HWPanelInfo *panel_info) {
548  *panel_info = hw_panel_info_;
549  return kErrorNone;
550}
551
552DisplayError HWDeviceDRM::SetDisplayAttributes(uint32_t index) {
553  return kErrorNone;
554}
555
556DisplayError HWDeviceDRM::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
557  return kErrorNotSupported;
558}
559
560DisplayError HWDeviceDRM::GetConfigIndex(uint32_t mode, uint32_t *index) {
561  return kErrorNone;
562}
563
564DisplayError HWDeviceDRM::PowerOn() {
565  DTRACE_SCOPED();
566  return kErrorNone;
567}
568
569DisplayError HWDeviceDRM::PowerOff() {
570  return kErrorNone;
571}
572
573DisplayError HWDeviceDRM::Doze() {
574  return kErrorNone;
575}
576
577DisplayError HWDeviceDRM::DozeSuspend() {
578  return kErrorNone;
579}
580
581DisplayError HWDeviceDRM::Standby() {
582  return kErrorNone;
583}
584
585void HWDeviceDRM::SetupAtomic(HWLayers *hw_layers, bool validate) {
586  if (default_mode_) {
587    return;
588  }
589
590  HWLayersInfo &hw_layer_info = hw_layers->info;
591  uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
592
593  for (uint32_t i = 0; i < hw_layer_count; i++) {
594    Layer &layer = hw_layer_info.hw_layers.at(i);
595    LayerBuffer *input_buffer = &layer.input_buffer;
596    HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
597    HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
598    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
599    bool needs_rotation = false;
600
601    for (uint32_t count = 0; count < 2; count++) {
602      HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
603      HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
604
605      if (hw_rotate_info->valid) {
606        input_buffer = &hw_rotator_session->output_buffer;
607        needs_rotation = true;
608      }
609
610      uint32_t fb_id = registry_.GetFbId(input_buffer->planes[0].fd);
611      if (pipe_info->valid && fb_id) {
612        uint32_t pipe_id = pipe_info->pipe_id;
613        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ALPHA, pipe_id, layer.plane_alpha);
614        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ZORDER, pipe_id, pipe_info->z_order);
615        DRMBlendType blending = {};
616        SetBlending(layer.blending, &blending);
617        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_BLEND_TYPE, pipe_id, blending);
618        DRMRect src = {};
619        SetRect(pipe_info->src_roi, &src);
620        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SRC_RECT, pipe_id, src);
621        DRMRect dst = {};
622        SetRect(pipe_info->dst_roi, &dst);
623        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DST_RECT, pipe_id, dst);
624
625        uint32_t rot_bit_mask = 0;
626        // In case of rotation, rotator handles flips
627        if (!needs_rotation) {
628          if (layer.transform.flip_horizontal) {
629            rot_bit_mask |= UINT32(DRMRotation::FLIP_H);
630          }
631          if (layer.transform.flip_vertical) {
632            rot_bit_mask |= UINT32(DRMRotation::FLIP_V);
633          }
634        }
635
636        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION, pipe_id, rot_bit_mask);
637        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_H_DECIMATION, pipe_id,
638                                  pipe_info->horizontal_decimation);
639        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_V_DECIMATION, pipe_id,
640                                  pipe_info->vertical_decimation);
641        uint32_t config = 0;
642        SetSrcConfig(layer.input_buffer, &config);
643        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SRC_CONFIG, pipe_id, config);;
644        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_FB_ID, pipe_id, fb_id);
645        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_CRTC, pipe_id, token_.crtc_id);
646        if (!validate && input_buffer->acquire_fence_fd >= 0) {
647          drm_atomic_intf_->Perform(DRMOps::PLANE_SET_INPUT_FENCE, pipe_id,
648                                    input_buffer->acquire_fence_fd);
649        }
650        if (hw_scale_) {
651          SDEScaler scaler_output = {};
652          hw_scale_->SetPlaneScaler(pipe_info->scale_data, &scaler_output);
653          // TODO(user): Remove qseed3 and add version check, then send appropriate scaler object
654          if (hw_resource_.has_qseed3) {
655            drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SCALER_CONFIG, pipe_id,
656                                      reinterpret_cast<uint64_t>(&scaler_output.scaler_v2));
657          }
658        }
659      }
660    }
661
662    // TODO(user): Remove this and enable the one in Init() onces underruns are fixed
663    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
664  }
665}
666
667DisplayError HWDeviceDRM::Validate(HWLayers *hw_layers) {
668  DTRACE_SCOPED();
669
670  registry_.RegisterCurrent(hw_layers);
671  SetupAtomic(hw_layers, true /* validate */);
672
673  int ret = drm_atomic_intf_->Validate();
674  if (ret) {
675    DLOGE("%s failed with error %d", __FUNCTION__, ret);
676    return kErrorHardware;
677  }
678
679  return kErrorNone;
680}
681
682DisplayError HWDeviceDRM::Commit(HWLayers *hw_layers) {
683  DTRACE_SCOPED();
684
685  DisplayError err = kErrorNone;
686  registry_.RegisterCurrent(hw_layers);
687
688  if (default_mode_) {
689    err = DefaultCommit(hw_layers);
690  } else {
691    err = AtomicCommit(hw_layers);
692  }
693
694  registry_.UnregisterNext();
695
696  return err;
697}
698
699DisplayError HWDeviceDRM::DefaultCommit(HWLayers *hw_layers) {
700  DTRACE_SCOPED();
701
702  HWLayersInfo &hw_layer_info = hw_layers->info;
703  LayerStack *stack = hw_layer_info.stack;
704
705  stack->retire_fence_fd = -1;
706  for (Layer &layer : hw_layer_info.hw_layers) {
707    layer.input_buffer.release_fence_fd = -1;
708  }
709
710  DRMMaster *master = nullptr;
711  int ret = DRMMaster::GetInstance(&master);
712  if (ret < 0) {
713    DLOGE("Failed to acquire DRMMaster instance");
714    return kErrorResources;
715  }
716
717  DRMResMgr *res_mgr = nullptr;
718  ret = DRMResMgr::GetInstance(&res_mgr);
719  if (ret < 0) {
720    DLOGE("Failed to acquire DRMResMgr instance");
721    return kErrorResources;
722  }
723
724  int dev_fd = -1;
725  master->GetHandle(&dev_fd);
726
727  uint32_t connector_id = 0;
728  res_mgr->GetConnectorId(&connector_id);
729
730  uint32_t crtc_id = 0;
731  res_mgr->GetCrtcId(&crtc_id);
732
733  drmModeModeInfo mode;
734  res_mgr->GetMode(&mode);
735
736  uint32_t fb_id = registry_.GetFbId(hw_layer_info.hw_layers.at(0).input_buffer.planes[0].fd);
737  ret = drmModeSetCrtc(dev_fd, crtc_id, fb_id, 0 /* x */, 0 /* y */, &connector_id,
738                       1 /* num_connectors */, &mode);
739  if (ret < 0) {
740    DLOGE("drmModeSetCrtc failed dev fd %d, fb_id %d, crtc id %d, connector id %d, %s", dev_fd,
741          fb_id, crtc_id, connector_id, strerror(errno));
742    return kErrorHardware;
743  }
744
745  return kErrorNone;
746}
747
748DisplayError HWDeviceDRM::AtomicCommit(HWLayers *hw_layers) {
749  DTRACE_SCOPED();
750  SetupAtomic(hw_layers, false /* validate */);
751
752  int ret = drm_atomic_intf_->Commit(false /* synchronous */);
753  if (ret) {
754    DLOGE("%s failed with error %d", __FUNCTION__, ret);
755    return kErrorHardware;
756  }
757
758  int release_fence = -1;
759  int retire_fence = -1;
760
761  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence);
762  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE, token_.conn_id, &retire_fence);
763
764  HWLayersInfo &hw_layer_info = hw_layers->info;
765  LayerStack *stack = hw_layer_info.stack;
766  stack->retire_fence_fd = retire_fence;
767
768  for (uint32_t i = 0; i < hw_layer_info.hw_layers.size(); i++) {
769    Layer &layer = hw_layer_info.hw_layers.at(i);
770    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
771    if (hw_rotator_session->hw_block_count) {
772      hw_rotator_session->output_buffer.release_fence_fd = Sys::dup_(release_fence);
773    } else {
774      layer.input_buffer.release_fence_fd = Sys::dup_(release_fence);
775    }
776  }
777
778  hw_layer_info.sync_handle = release_fence;
779
780  return kErrorNone;
781}
782
783DisplayError HWDeviceDRM::Flush() {
784  return kErrorNone;
785}
786
787void HWDeviceDRM::SetBlending(const LayerBlending &source, DRMBlendType *target) {
788  switch (source) {
789    case kBlendingPremultiplied:
790      *target = DRMBlendType::PREMULTIPLIED;
791      break;
792    case kBlendingOpaque:
793      *target = DRMBlendType::OPAQUE;
794      break;
795    case kBlendingCoverage:
796      *target = DRMBlendType::COVERAGE;
797      break;
798    default:
799      *target = DRMBlendType::UNDEFINED;
800  }
801}
802
803
804void HWDeviceDRM::SetSrcConfig(const LayerBuffer &input_buffer, uint32_t *config) {
805  if (input_buffer.flags.interlace) {
806    *config |= (0x01 << UINT32(DRMSrcConfig::DEINTERLACE));
807  }
808}
809
810void HWDeviceDRM::SetRect(const LayerRect &source, DRMRect *target) {
811  target->left = UINT32(source.left);
812  target->top = UINT32(source.top);
813  target->right = UINT32(source.right);
814  target->bottom = UINT32(source.bottom);
815}
816
817bool HWDeviceDRM::EnableHotPlugDetection(int enable) {
818  return true;
819}
820
821void HWDeviceDRM::ResetDisplayParams() {}
822
823DisplayError HWDeviceDRM::SetCursorPosition(HWLayers *hw_layers, int x, int y) {
824  DTRACE_SCOPED();
825  return kErrorNone;
826}
827
828DisplayError HWDeviceDRM::GetPPFeaturesVersion(PPFeatureVersion *vers) {
829  struct DRMPPFeatureInfo info = {};
830
831  for (uint32_t i = 0; i < kMaxNumPPFeatures; i++) {
832    memset(&info, 0, sizeof(struct DRMPPFeatureInfo));
833    info.id = HWColorManagerDrm::ToDrmFeatureId(i);
834    if (info.id >= sde_drm::kPPFeaturesMax)
835      continue;
836    // use crtc_id_ = 0 since PP features are same across all CRTCs
837    drm_mgr_intf_->GetCrtcPPInfo(0, info);
838    vers->version[i] = HWColorManagerDrm::GetFeatureVersion(info);
839  }
840  return kErrorNone;
841}
842
843DisplayError HWDeviceDRM::SetPPFeatures(PPFeaturesConfig *feature_list) {
844  int ret = 0;
845  PPFeatureInfo *feature = NULL;
846  DRMPPFeatureInfo kernel_params = {};
847
848  while (true) {
849    ret = feature_list->RetrieveNextFeature(&feature);
850    if (ret)
851      break;
852
853    if (feature) {
854      DLOGV_IF(kTagDriverConfig, "feature_id = %d", feature->feature_id_);
855      if (!HWColorManagerDrm::GetDrmFeature[feature->feature_id_]) {
856        DLOGE("GetDrmFeature is not valid for feature %d", feature->feature_id_);
857        continue;
858      }
859      ret = HWColorManagerDrm::GetDrmFeature[feature->feature_id_](*feature, &kernel_params);
860      if (!ret)
861        drm_atomic_intf_->Perform(DRMOps::CRTC_SET_POST_PROC, token_.crtc_id, &kernel_params);
862      HWColorManagerDrm::FreeDrmFeatureData(&kernel_params);
863    }
864  }
865
866  // Once all features were consumed, then destroy all feature instance from feature_list,
867  feature_list->Reset();
868
869  return kErrorNone;
870}
871
872DisplayError HWDeviceDRM::SetVSyncState(bool enable) {
873  return kErrorNone;
874}
875
876void HWDeviceDRM::SetIdleTimeoutMs(uint32_t timeout_ms) {}
877
878DisplayError HWDeviceDRM::SetDisplayMode(const HWDisplayMode hw_display_mode) {
879  return kErrorNotSupported;
880}
881
882DisplayError HWDeviceDRM::SetRefreshRate(uint32_t refresh_rate) {
883  return kErrorNotSupported;
884}
885
886DisplayError HWDeviceDRM::SetPanelBrightness(int level) {
887  DisplayError err = kErrorNone;
888  char buffer[kMaxSysfsCommandLength] = {0};
889
890  DLOGV_IF(kTagDriverConfig, "Set brightness level to %d", level);
891  int fd = Sys::open_(kBrightnessNode, O_RDWR);
892  if (fd < 0) {
893    DLOGV_IF(kTagDriverConfig, "Failed to open node = %s, error = %s ", kBrightnessNode,
894             strerror(errno));
895    return kErrorFileDescriptor;
896  }
897
898  int32_t bytes = snprintf(buffer, kMaxSysfsCommandLength, "%d\n", level);
899  ssize_t ret = Sys::pwrite_(fd, buffer, static_cast<size_t>(bytes), 0);
900  if (ret <= 0) {
901    DLOGV_IF(kTagDriverConfig, "Failed to write to node = %s, error = %s ", kBrightnessNode,
902             strerror(errno));
903    err = kErrorHardware;
904  }
905
906  Sys::close_(fd);
907
908  return err;
909}
910
911DisplayError HWDeviceDRM::GetPanelBrightness(int *level) {
912  DisplayError err = kErrorNone;
913  char brightness[kMaxStringLength] = {0};
914
915  if (!level) {
916    DLOGV_IF(kTagDriverConfig, "Invalid input, null pointer.");
917    return kErrorParameters;
918  }
919
920  int fd = Sys::open_(kBrightnessNode, O_RDWR);
921  if (fd < 0) {
922    DLOGV_IF(kTagDriverConfig, "Failed to open brightness node = %s, error = %s", kBrightnessNode,
923             strerror(errno));
924    return kErrorFileDescriptor;
925  }
926
927  if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
928    *level = atoi(brightness);
929    DLOGV_IF(kTagDriverConfig, "Brightness level = %d", *level);
930  } else {
931    DLOGV_IF(kTagDriverConfig, "Failed to read panel brightness");
932    err = kErrorHardware;
933  }
934
935  Sys::close_(fd);
936
937  return err;
938}
939
940DisplayError HWDeviceDRM::CachePanelBrightness(int level) {
941  return kErrorNotSupported;
942}
943
944DisplayError HWDeviceDRM::GetHWScanInfo(HWScanInfo *scan_info) {
945  return kErrorNotSupported;
946}
947
948DisplayError HWDeviceDRM::GetVideoFormat(uint32_t config_index, uint32_t *video_format) {
949  return kErrorNotSupported;
950}
951
952DisplayError HWDeviceDRM::GetMaxCEAFormat(uint32_t *max_cea_format) {
953  return kErrorNotSupported;
954}
955
956DisplayError HWDeviceDRM::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
957  return kErrorNotSupported;
958}
959
960DisplayError HWDeviceDRM::SetS3DMode(HWS3DMode s3d_mode) {
961  return kErrorNotSupported;
962}
963
964DisplayError HWDeviceDRM::SetScaleLutConfig(HWScaleLutInfo *lut_info) {
965  sde_drm::DRMScalerLUTInfo drm_lut_info = {};
966  drm_lut_info.cir_lut = lut_info->cir_lut;
967  drm_lut_info.dir_lut = lut_info->dir_lut;
968  drm_lut_info.sep_lut = lut_info->sep_lut;
969  drm_lut_info.cir_lut_size = lut_info->cir_lut_size;
970  drm_lut_info.dir_lut_size = lut_info->dir_lut_size;
971  drm_lut_info.sep_lut_size = lut_info->sep_lut_size;
972  drm_mgr_intf_->SetScalerLUT(drm_lut_info);
973
974  return kErrorNone;
975}
976
977DisplayError HWDeviceDRM::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
978  if (!hw_resource_.hw_dest_scalar_info.count) {
979    return kErrorNotSupported;
980  }
981
982  if (mixer_attributes.width > display_attributes_.x_pixels ||
983      mixer_attributes.height > display_attributes_.y_pixels) {
984    DLOGW("Input resolution exceeds display resolution! input: res %dx%d display: res %dx%d",
985          mixer_attributes.width, mixer_attributes.height, display_attributes_.x_pixels,
986          display_attributes_.y_pixels);
987    return kErrorNotSupported;
988  }
989
990  uint32_t max_input_width = hw_resource_.hw_dest_scalar_info.max_input_width;
991  if (display_attributes_.is_device_split) {
992    max_input_width *= 2;
993  }
994
995  if (mixer_attributes.width > max_input_width) {
996    DLOGW("Input width exceeds width limit! input_width %d width_limit %d", mixer_attributes.width,
997          max_input_width);
998    return kErrorNotSupported;
999  }
1000
1001  float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height);
1002  float display_aspect_ratio =
1003      FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels);
1004
1005  if (display_aspect_ratio != mixer_aspect_ratio) {
1006    DLOGW("Aspect ratio mismatch! input: res %dx%d display: res %dx%d", mixer_attributes.width,
1007          mixer_attributes.height, display_attributes_.x_pixels, display_attributes_.y_pixels);
1008    return kErrorNotSupported;
1009  }
1010
1011  float scale_x = FLOAT(display_attributes_.x_pixels) / FLOAT(mixer_attributes.width);
1012  float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height);
1013  float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up;
1014  if (scale_x > max_scale_up || scale_y > max_scale_up) {
1015    DLOGW(
1016        "Up scaling ratio exceeds for destination scalar upscale limit scale_x %f scale_y %f "
1017        "max_scale_up %f",
1018        scale_x, scale_y, max_scale_up);
1019    return kErrorNotSupported;
1020  }
1021
1022  float mixer_split_ratio = FLOAT(mixer_attributes_.split_left) / FLOAT(mixer_attributes_.width);
1023
1024  mixer_attributes_ = mixer_attributes;
1025  mixer_attributes_.split_left = mixer_attributes_.width;
1026  if (display_attributes_.is_device_split) {
1027    mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio);
1028  }
1029
1030  return kErrorNone;
1031}
1032
1033DisplayError HWDeviceDRM::GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
1034  if (!mixer_attributes) {
1035    return kErrorParameters;
1036  }
1037
1038  mixer_attributes_.width = display_attributes_.x_pixels;
1039  mixer_attributes_.height = display_attributes_.y_pixels;
1040  mixer_attributes_.split_left = display_attributes_.is_device_split
1041                                     ? hw_panel_info_.split_info.left_split
1042                                     : mixer_attributes_.width;
1043  *mixer_attributes = mixer_attributes_;
1044
1045  return kErrorNone;
1046}
1047
1048void HWDeviceDRM::UpdateMixerAttributes() {
1049  mixer_attributes_.width = display_attributes_.x_pixels;
1050  mixer_attributes_.height = display_attributes_.y_pixels;
1051  mixer_attributes_.split_left = display_attributes_.is_device_split
1052                                     ? hw_panel_info_.split_info.left_split
1053                                     : mixer_attributes_.width;
1054}
1055
1056}  // namespace sdm
1057