Home | History | Annotate | Download | only in fb
      1 /*
      2 * Copyright (c) 2014 - 2016, 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 <stdio.h>
     33 #include <ctype.h>
     34 #include <math.h>
     35 #include <fcntl.h>
     36 #include <unistd.h>
     37 #include <string.h>
     38 #include <inttypes.h>
     39 #include <sys/types.h>
     40 #include <sys/stat.h>
     41 #include <sys/ioctl.h>
     42 #include <linux/fb.h>
     43 #include <utils/constants.h>
     44 #include <utils/debug.h>
     45 #include <utils/sys.h>
     46 #include <vector>
     47 #include <algorithm>
     48 #include <string>
     49 
     50 #include "hw_device.h"
     51 #include "hw_info_interface.h"
     52 
     53 #define __CLASS__ "HWDevice"
     54 
     55 using std::string;
     56 using std::to_string;
     57 using std::fstream;
     58 
     59 namespace sdm {
     60 
     61 HWDevice::HWDevice(BufferSyncHandler *buffer_sync_handler)
     62   : fb_node_index_(-1), fb_path_("/sys/devices/virtual/graphics/fb"),
     63     buffer_sync_handler_(buffer_sync_handler), synchronous_commit_(false) {
     64 }
     65 
     66 DisplayError HWDevice::Init() {
     67   char device_name[64] = {0};
     68 
     69   // Read the fb node index
     70   fb_node_index_ = GetFBNodeIndex(device_type_);
     71   if (fb_node_index_ == -1) {
     72     DLOGE("%s should be present", device_name_);
     73     return kErrorHardware;
     74   }
     75 
     76   // Populate Panel Info (Used for Partial Update)
     77   PopulateHWPanelInfo();
     78   // Populate HW Capabilities
     79   hw_resource_ = HWResourceInfo();
     80   hw_info_intf_->GetHWResourceInfo(&hw_resource_);
     81 
     82   snprintf(device_name, sizeof(device_name), "%s%d", "/dev/graphics/fb", fb_node_index_);
     83   device_fd_ = Sys::open_(device_name, O_RDWR);
     84   if (device_fd_ < 0) {
     85     DLOGE("open %s failed err = %d errstr = %s", device_name, errno,  strerror(errno));
     86     return kErrorResources;
     87   }
     88 
     89   return HWScale::Create(&hw_scale_, hw_resource_.has_qseed3);
     90 }
     91 
     92 DisplayError HWDevice::Deinit() {
     93   HWScale::Destroy(hw_scale_);
     94 
     95   if (device_fd_ >= 0) {
     96     Sys::close_(device_fd_);
     97     device_fd_ = -1;
     98   }
     99 
    100   return kErrorNone;
    101 }
    102 
    103 DisplayError HWDevice::GetActiveConfig(uint32_t *active_config) {
    104   *active_config = 0;
    105   return kErrorNone;
    106 }
    107 
    108 DisplayError HWDevice::GetNumDisplayAttributes(uint32_t *count) {
    109   *count = 1;
    110   return kErrorNone;
    111 }
    112 
    113 DisplayError HWDevice::GetDisplayAttributes(uint32_t index,
    114                                             HWDisplayAttributes *display_attributes) {
    115   return kErrorNone;
    116 }
    117 
    118 DisplayError HWDevice::GetHWPanelInfo(HWPanelInfo *panel_info) {
    119   *panel_info = hw_panel_info_;
    120   return kErrorNone;
    121 }
    122 
    123 DisplayError HWDevice::SetDisplayAttributes(uint32_t index) {
    124   return kErrorNone;
    125 }
    126 
    127 DisplayError HWDevice::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
    128   return kErrorNotSupported;
    129 }
    130 
    131 DisplayError HWDevice::GetConfigIndex(uint32_t mode, uint32_t *index) {
    132   return kErrorNone;
    133 }
    134 
    135 DisplayError HWDevice::PowerOn() {
    136   DTRACE_SCOPED();
    137 
    138   if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
    139     if (errno == ESHUTDOWN) {
    140       DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
    141       return kErrorShutDown;
    142     }
    143     IOCTL_LOGE(FB_BLANK_UNBLANK, device_type_);
    144     return kErrorHardware;
    145   }
    146 
    147   return kErrorNone;
    148 }
    149 
    150 DisplayError HWDevice::PowerOff() {
    151   return kErrorNone;
    152 }
    153 
    154 DisplayError HWDevice::Doze() {
    155   return kErrorNone;
    156 }
    157 
    158 DisplayError HWDevice::DozeSuspend() {
    159   return kErrorNone;
    160 }
    161 
    162 DisplayError HWDevice::Standby() {
    163   return kErrorNone;
    164 }
    165 
    166 DisplayError HWDevice::Validate(HWLayers *hw_layers) {
    167   DTRACE_SCOPED();
    168 
    169   DisplayError error = kErrorNone;
    170 
    171   HWLayersInfo &hw_layer_info = hw_layers->info;
    172   LayerStack *stack = hw_layer_info.stack;
    173 
    174   DLOGV_IF(kTagDriverConfig, "************************** %s Validate Input ***********************",
    175            device_name_);
    176   DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
    177 
    178   mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
    179   uint32_t &mdp_layer_count = mdp_commit.input_layer_cnt;
    180 
    181   DLOGI_IF(kTagDriverConfig, "left_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.left_roi.x,
    182     mdp_commit.left_roi.y, mdp_commit.left_roi.w, mdp_commit.left_roi.h);
    183   DLOGI_IF(kTagDriverConfig, "right_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.right_roi.x,
    184     mdp_commit.right_roi.y, mdp_commit.right_roi.w, mdp_commit.right_roi.h);
    185 
    186   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
    187     uint32_t layer_index = hw_layer_info.index[i];
    188     Layer *layer = stack->layers.at(layer_index);
    189     LayerBuffer *input_buffer = layer->input_buffer;
    190     HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
    191     HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
    192     HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
    193     bool is_rotator_used = (hw_rotator_session->hw_block_count != 0);
    194     bool is_cursor_pipe_used = (hw_layer_info.use_hw_cursor & layer->flags.cursor);
    195 
    196     for (uint32_t count = 0; count < 2; count++) {
    197       HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
    198       HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
    199 
    200       if (hw_rotate_info->valid) {
    201         input_buffer = &hw_rotator_session->output_buffer;
    202       }
    203 
    204       if (pipe_info->valid) {
    205         mdp_input_layer &mdp_layer = mdp_in_layers_[mdp_layer_count];
    206         mdp_layer_buffer &mdp_buffer = mdp_layer.buffer;
    207 
    208         mdp_buffer.width = input_buffer->width;
    209         mdp_buffer.height = input_buffer->height;
    210         mdp_buffer.comp_ratio.denom = 1000;
    211         mdp_buffer.comp_ratio.numer = UINT32(hw_layers->config[i].compression * 1000);
    212 
    213         if (layer->flags.solid_fill) {
    214           mdp_buffer.format = MDP_ARGB_8888;
    215         } else {
    216           error = SetFormat(input_buffer->format, &mdp_buffer.format);
    217           if (error != kErrorNone) {
    218             return error;
    219           }
    220         }
    221         mdp_layer.alpha = layer->plane_alpha;
    222         mdp_layer.z_order = UINT16(pipe_info->z_order);
    223         mdp_layer.transp_mask = 0xffffffff;
    224         SetBlending(layer->blending, &mdp_layer.blend_op);
    225         mdp_layer.pipe_ndx = pipe_info->pipe_id;
    226         mdp_layer.horz_deci = pipe_info->horizontal_decimation;
    227         mdp_layer.vert_deci = pipe_info->vertical_decimation;
    228 
    229         SetRect(pipe_info->src_roi, &mdp_layer.src_rect);
    230         SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
    231         SetMDPFlags(layer, is_rotator_used, is_cursor_pipe_used, &mdp_layer.flags);
    232         SetCSC(layer->input_buffer->csc, &mdp_layer.color_space);
    233         if (pipe_info->flags & kIGC) {
    234           SetIGC(layer->input_buffer, mdp_layer_count);
    235         }
    236         if (pipe_info->flags & kMultiRect) {
    237           mdp_layer.flags |= MDP_LAYER_MULTIRECT_ENABLE;
    238           if (pipe_info->flags & kMultiRectParallelMode) {
    239             mdp_layer.flags |= MDP_LAYER_MULTIRECT_PARALLEL_MODE;
    240           }
    241         }
    242         mdp_layer.bg_color = layer->solid_fill_color;
    243 
    244         // HWScaleData to MDP driver
    245         hw_scale_->SetHWScaleData(pipe_info->scale_data, mdp_layer_count, &mdp_commit,
    246                                   pipe_info->sub_block_type);
    247         mdp_layer.scale = hw_scale_->GetScaleDataRef(mdp_layer_count, pipe_info->sub_block_type);
    248 
    249         mdp_layer_count++;
    250 
    251         DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
    252                  i, count ? "Right" : "Left");
    253         DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d", mdp_buffer.width, mdp_buffer.height,
    254                  mdp_buffer.format);
    255         DLOGV_IF(kTagDriverConfig, "plane_alpha %d, zorder %d, blending %d, horz_deci %d, "
    256                  "vert_deci %d, pipe_id = 0x%x, mdp_flags 0x%x", mdp_layer.alpha, mdp_layer.z_order,
    257                  mdp_layer.blend_op, mdp_layer.horz_deci, mdp_layer.vert_deci, mdp_layer.pipe_ndx,
    258                  mdp_layer.flags);
    259         DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_layer.src_rect.x,
    260                  mdp_layer.src_rect.y, mdp_layer.src_rect.w, mdp_layer.src_rect.h);
    261         DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_layer.dst_rect.x,
    262                  mdp_layer.dst_rect.y, mdp_layer.dst_rect.w, mdp_layer.dst_rect.h);
    263         hw_scale_->DumpScaleData(mdp_layer.scale);
    264         DLOGV_IF(kTagDriverConfig, "*************************************************************");
    265       }
    266     }
    267   }
    268 
    269   // TODO(user): This block should move to the derived class
    270   if (device_type_ == kDeviceVirtual) {
    271     LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
    272     mdp_out_layer_.writeback_ndx = hw_resource_.writeback_index;
    273     mdp_out_layer_.buffer.width = output_buffer->width;
    274     mdp_out_layer_.buffer.height = output_buffer->height;
    275     if (output_buffer->flags.secure) {
    276       mdp_out_layer_.flags |= MDP_LAYER_SECURE_SESSION;
    277     }
    278     mdp_out_layer_.buffer.comp_ratio.denom = 1000;
    279     mdp_out_layer_.buffer.comp_ratio.numer = UINT32(hw_layers->output_compression * 1000);
    280 #ifdef OUT_LAYER_COLOR_SPACE
    281     SetCSC(output_buffer->csc, &mdp_out_layer_.color_space);
    282 #endif
    283     SetFormat(output_buffer->format, &mdp_out_layer_.buffer.format);
    284 
    285     DLOGI_IF(kTagDriverConfig, "********************* Output buffer Info ************************");
    286     DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d",
    287              mdp_out_layer_.buffer.width, mdp_out_layer_.buffer.height,
    288              mdp_out_layer_.buffer.format, mdp_out_layer_.writeback_ndx);
    289     DLOGI_IF(kTagDriverConfig, "*****************************************************************");
    290   }
    291 
    292   uint32_t index = 0;
    293   for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
    294     DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i);
    295 
    296     if (it == hw_layer_info.dest_scale_info_map.end()) {
    297       continue;
    298     }
    299 
    300     HWDestScaleInfo *dest_scale_info = it->second;
    301 
    302     mdp_destination_scaler_data *dest_scalar_data = &mdp_dest_scalar_data_[index];
    303     hw_scale_->SetHWScaleData(dest_scale_info->scale_data, index, &mdp_commit,
    304                               kHWDestinationScalar);
    305 
    306     if (dest_scale_info->scale_update) {
    307       dest_scalar_data->flags |= MDP_DESTSCALER_SCALE_UPDATE;
    308     }
    309 
    310     dest_scalar_data->dest_scaler_ndx = i;
    311     dest_scalar_data->lm_width = dest_scale_info->mixer_width;
    312     dest_scalar_data->lm_height = dest_scale_info->mixer_height;
    313     dest_scalar_data->scale = reinterpret_cast <uint64_t>
    314       (hw_scale_->GetScaleDataRef(index, kHWDestinationScalar));
    315 
    316     index++;
    317 
    318     DLOGV_IF(kTagDriverConfig, "************************ DestScalar[%d] **************************",
    319              dest_scalar_data->dest_scaler_ndx);
    320     DLOGV_IF(kTagDriverConfig, "Mixer WxH %dx%d", dest_scalar_data->lm_width,
    321              dest_scalar_data->lm_height);
    322     DLOGI_IF(kTagDriverConfig, "*****************************************************************");
    323   }
    324   mdp_commit.dest_scaler_cnt = UINT32(hw_layer_info.dest_scale_info_map.size());
    325 
    326   mdp_commit.flags |= MDP_VALIDATE_LAYER;
    327   if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) {
    328     if (errno == ESHUTDOWN) {
    329       DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
    330       return kErrorShutDown;
    331     }
    332     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
    333     DumpLayerCommit(mdp_disp_commit_);
    334     return kErrorHardware;
    335   }
    336 
    337   return kErrorNone;
    338 }
    339 
    340 void HWDevice::DumpLayerCommit(const mdp_layer_commit &layer_commit) {
    341   const mdp_layer_commit_v1 &mdp_commit = layer_commit.commit_v1;
    342   const mdp_input_layer *mdp_layers = mdp_commit.input_layers;
    343   const mdp_rect &l_roi = mdp_commit.left_roi;
    344   const mdp_rect &r_roi = mdp_commit.right_roi;
    345 
    346   DLOGI("mdp_commit: flags = %x, release fence = %x", mdp_commit.flags, mdp_commit.release_fence);
    347   DLOGI("left_roi: x = %d, y = %d, w = %d, h = %d", l_roi.x, l_roi.y, l_roi.w, l_roi.h);
    348   DLOGI("right_roi: x = %d, y = %d, w = %d, h = %d", r_roi.x, r_roi.y, r_roi.w, r_roi.h);
    349   for (uint32_t i = 0; i < mdp_commit.input_layer_cnt; i++) {
    350     const mdp_input_layer &layer = mdp_layers[i];
    351     const mdp_rect &src_rect = layer.src_rect;
    352     const mdp_rect &dst_rect = layer.dst_rect;
    353     DLOGI("layer = %d, pipe_ndx = %x, z = %d, flags = %x",
    354       i, layer.pipe_ndx, layer.z_order, layer.flags);
    355     DLOGI("src_rect: x = %d, y = %d, w = %d, h = %d",
    356       src_rect.x, src_rect.y, src_rect.w, src_rect.h);
    357     DLOGI("dst_rect: x = %d, y = %d, w = %d, h = %d",
    358       dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h);
    359   }
    360 }
    361 
    362 DisplayError HWDevice::Commit(HWLayers *hw_layers) {
    363   DTRACE_SCOPED();
    364 
    365   HWLayersInfo &hw_layer_info = hw_layers->info;
    366   LayerStack *stack = hw_layer_info.stack;
    367 
    368   DLOGV_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
    369            device_name_);
    370   DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
    371 
    372   mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
    373   uint32_t mdp_layer_index = 0;
    374 
    375   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
    376     uint32_t layer_index = hw_layer_info.index[i];
    377     LayerBuffer *input_buffer = stack->layers.at(layer_index)->input_buffer;
    378     HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
    379     HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
    380     HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
    381 
    382     for (uint32_t count = 0; count < 2; count++) {
    383       HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
    384       HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
    385 
    386       if (hw_rotate_info->valid) {
    387         input_buffer = &hw_rotator_session->output_buffer;
    388       }
    389 
    390       if (pipe_info->valid) {
    391         mdp_layer_buffer &mdp_buffer = mdp_in_layers_[mdp_layer_index].buffer;
    392         mdp_input_layer &mdp_layer = mdp_in_layers_[mdp_layer_index];
    393         if (input_buffer->planes[0].fd >= 0) {
    394           mdp_buffer.plane_count = 1;
    395           mdp_buffer.planes[0].fd = input_buffer->planes[0].fd;
    396           mdp_buffer.planes[0].offset = input_buffer->planes[0].offset;
    397           SetStride(device_type_, input_buffer->format, input_buffer->planes[0].stride,
    398                     &mdp_buffer.planes[0].stride);
    399         } else {
    400           mdp_buffer.plane_count = 0;
    401         }
    402 
    403         mdp_buffer.fence = input_buffer->acquire_fence_fd;
    404         mdp_layer_index++;
    405 
    406         DLOGV_IF(kTagDriverConfig, "****************** Layer[%d] %s pipe Input *******************",
    407                  i, count ? "Right" : "Left");
    408         DLOGI_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d, horz_deci %d, vert_deci %d",
    409                  mdp_buffer.width, mdp_buffer.height, mdp_buffer.format, mdp_layer.horz_deci,
    410                  mdp_layer.vert_deci);
    411         DLOGI_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_buf_stride %d, " \
    412                  "in_plane_count %d, in_fence %d, layer count %d", mdp_buffer.planes[0].fd,
    413                  mdp_buffer.planes[0].offset, mdp_buffer.planes[0].stride, mdp_buffer.plane_count,
    414                  mdp_buffer.fence, mdp_commit.input_layer_cnt);
    415         DLOGV_IF(kTagDriverConfig, "*************************************************************");
    416       }
    417     }
    418   }
    419 
    420   // TODO(user): Move to derived class
    421   if (device_type_ == kDeviceVirtual) {
    422     LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
    423 
    424     if (output_buffer->planes[0].fd >= 0) {
    425       mdp_out_layer_.buffer.planes[0].fd = output_buffer->planes[0].fd;
    426       mdp_out_layer_.buffer.planes[0].offset = output_buffer->planes[0].offset;
    427       SetStride(device_type_, output_buffer->format, output_buffer->planes[0].stride,
    428                 &mdp_out_layer_.buffer.planes[0].stride);
    429       mdp_out_layer_.buffer.plane_count = 1;
    430     } else {
    431       DLOGE("Invalid output buffer fd");
    432       return kErrorParameters;
    433     }
    434 
    435     mdp_out_layer_.buffer.fence = output_buffer->acquire_fence_fd;
    436 
    437     DLOGI_IF(kTagDriverConfig, "********************** Output buffer Info ***********************");
    438     DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, acquire_fence %d",
    439              mdp_out_layer_.buffer.planes[0].fd, mdp_out_layer_.buffer.planes[0].offset,
    440              mdp_out_layer_.buffer.planes[0].stride,  mdp_out_layer_.buffer.fence);
    441     DLOGI_IF(kTagDriverConfig, "*****************************************************************");
    442   }
    443 
    444   mdp_commit.release_fence = -1;
    445   mdp_commit.flags &= UINT32(~MDP_VALIDATE_LAYER);
    446   if (synchronous_commit_) {
    447     mdp_commit.flags |= MDP_COMMIT_WAIT_FOR_FINISH;
    448   }
    449   if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) {
    450     if (errno == ESHUTDOWN) {
    451       DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
    452       return kErrorShutDown;
    453     }
    454     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
    455     DumpLayerCommit(mdp_disp_commit_);
    456     synchronous_commit_ = false;
    457     return kErrorHardware;
    458   }
    459 
    460   stack->retire_fence_fd = mdp_commit.retire_fence;
    461 
    462   // MDP returns only one release fence for the entire layer stack. Duplicate this fence into all
    463   // layers being composed by MDP.
    464 
    465   std::vector<uint32_t> fence_dup_flag;
    466   fence_dup_flag.clear();
    467 
    468   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
    469     uint32_t layer_index = hw_layer_info.index[i];
    470     LayerBuffer *input_buffer = stack->layers.at(layer_index)->input_buffer;
    471     HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
    472 
    473     if (hw_rotator_session->hw_block_count) {
    474       input_buffer = &hw_rotator_session->output_buffer;
    475     }
    476 
    477     // Make sure the release fence is duplicated only once for each buffer.
    478     if (std::find(fence_dup_flag.begin(), fence_dup_flag.end(), layer_index) ==
    479         fence_dup_flag.end()) {
    480       input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence);
    481       fence_dup_flag.push_back(layer_index);
    482     }
    483   }
    484   fence_dup_flag.clear();
    485 
    486   hw_layer_info.sync_handle = Sys::dup_(mdp_commit.release_fence);
    487 
    488   DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
    489            device_name_);
    490   DLOGI_IF(kTagDriverConfig, "retire_fence_fd %d", stack->retire_fence_fd);
    491   DLOGI_IF(kTagDriverConfig, "*******************************************************************");
    492 
    493   if (mdp_commit.release_fence >= 0) {
    494     Sys::close_(mdp_commit.release_fence);
    495   }
    496 
    497   if (synchronous_commit_) {
    498     // A synchronous commit can be requested when changing the display mode so we need to update
    499     // panel info.
    500     PopulateHWPanelInfo();
    501     synchronous_commit_ = false;
    502   }
    503 
    504   return kErrorNone;
    505 }
    506 
    507 DisplayError HWDevice::Flush() {
    508   ResetDisplayParams();
    509   mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
    510   mdp_commit.input_layer_cnt = 0;
    511   mdp_commit.output_layer = NULL;
    512 
    513   mdp_commit.flags &= UINT32(~MDP_VALIDATE_LAYER);
    514   if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) {
    515     if (errno == ESHUTDOWN) {
    516       DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
    517       return kErrorShutDown;
    518     }
    519     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
    520     DumpLayerCommit(mdp_disp_commit_);
    521     return kErrorHardware;
    522   }
    523   return kErrorNone;
    524 }
    525 
    526 DisplayError HWDevice::SetFormat(const LayerBufferFormat &source, uint32_t *target) {
    527   switch (source) {
    528   case kFormatARGB8888:                 *target = MDP_ARGB_8888;         break;
    529   case kFormatRGBA8888:                 *target = MDP_RGBA_8888;         break;
    530   case kFormatBGRA8888:                 *target = MDP_BGRA_8888;         break;
    531   case kFormatRGBX8888:                 *target = MDP_RGBX_8888;         break;
    532   case kFormatBGRX8888:                 *target = MDP_BGRX_8888;         break;
    533   case kFormatRGBA5551:                 *target = MDP_RGBA_5551;         break;
    534   case kFormatRGBA4444:                 *target = MDP_RGBA_4444;         break;
    535   case kFormatRGB888:                   *target = MDP_RGB_888;           break;
    536   case kFormatBGR888:                   *target = MDP_BGR_888;           break;
    537   case kFormatRGB565:                   *target = MDP_RGB_565;           break;
    538   case kFormatBGR565:                   *target = MDP_BGR_565;           break;
    539   case kFormatYCbCr420Planar:           *target = MDP_Y_CB_CR_H2V2;      break;
    540   case kFormatYCrCb420Planar:           *target = MDP_Y_CR_CB_H2V2;      break;
    541   case kFormatYCrCb420PlanarStride16:   *target = MDP_Y_CR_CB_GH2V2;     break;
    542   case kFormatYCbCr420SemiPlanar:       *target = MDP_Y_CBCR_H2V2;       break;
    543   case kFormatYCrCb420SemiPlanar:       *target = MDP_Y_CRCB_H2V2;       break;
    544   case kFormatYCbCr422H1V2SemiPlanar:   *target = MDP_Y_CBCR_H1V2;       break;
    545   case kFormatYCrCb422H1V2SemiPlanar:   *target = MDP_Y_CRCB_H1V2;       break;
    546   case kFormatYCbCr422H2V1SemiPlanar:   *target = MDP_Y_CBCR_H2V1;       break;
    547   case kFormatYCrCb422H2V1SemiPlanar:   *target = MDP_Y_CRCB_H2V1;       break;
    548   case kFormatYCbCr422H2V1Packed:       *target = MDP_YCBYCR_H2V1;       break;
    549   case kFormatYCbCr420SemiPlanarVenus:  *target = MDP_Y_CBCR_H2V2_VENUS; break;
    550   case kFormatRGBA8888Ubwc:             *target = MDP_RGBA_8888_UBWC;    break;
    551   case kFormatRGBX8888Ubwc:             *target = MDP_RGBX_8888_UBWC;    break;
    552   case kFormatBGR565Ubwc:               *target = MDP_RGB_565_UBWC;      break;
    553   case kFormatYCbCr420SPVenusUbwc:      *target = MDP_Y_CBCR_H2V2_UBWC;  break;
    554   case kFormatRGBA1010102:              *target = MDP_RGBA_1010102;      break;
    555   case kFormatARGB2101010:              *target = MDP_ARGB_2101010;      break;
    556   case kFormatRGBX1010102:              *target = MDP_RGBX_1010102;      break;
    557   case kFormatXRGB2101010:              *target = MDP_XRGB_2101010;      break;
    558   case kFormatBGRA1010102:              *target = MDP_BGRA_1010102;      break;
    559   case kFormatABGR2101010:              *target = MDP_ABGR_2101010;      break;
    560   case kFormatBGRX1010102:              *target = MDP_BGRX_1010102;      break;
    561   case kFormatXBGR2101010:              *target = MDP_XBGR_2101010;      break;
    562   case kFormatRGBA1010102Ubwc:          *target = MDP_RGBA_1010102_UBWC; break;
    563   case kFormatRGBX1010102Ubwc:          *target = MDP_RGBX_1010102_UBWC; break;
    564   case kFormatYCbCr420P010:             *target = MDP_Y_CBCR_H2V2_P010;  break;
    565   case kFormatYCbCr420TP10Ubwc:         *target = MDP_Y_CBCR_H2V2_TP10_UBWC; break;
    566   default:
    567     DLOGE("Unsupported format type %d", source);
    568     return kErrorParameters;
    569   }
    570 
    571   return kErrorNone;
    572 }
    573 
    574 DisplayError HWDevice::SetStride(HWDeviceType device_type, LayerBufferFormat format,
    575                                       uint32_t width, uint32_t *target) {
    576   // TODO(user): This SetStride function is a workaround to satisfy the driver expectation for
    577   // rotator and virtual devices. Eventually this will be taken care in the driver.
    578   if (device_type != kDeviceRotator && device_type != kDeviceVirtual) {
    579     *target = width;
    580     return kErrorNone;
    581   }
    582 
    583   switch (format) {
    584   case kFormatARGB8888:
    585   case kFormatRGBA8888:
    586   case kFormatBGRA8888:
    587   case kFormatRGBX8888:
    588   case kFormatBGRX8888:
    589   case kFormatRGBA8888Ubwc:
    590   case kFormatRGBX8888Ubwc:
    591   case kFormatRGBA1010102:
    592   case kFormatARGB2101010:
    593   case kFormatRGBX1010102:
    594   case kFormatXRGB2101010:
    595   case kFormatBGRA1010102:
    596   case kFormatABGR2101010:
    597   case kFormatBGRX1010102:
    598   case kFormatXBGR2101010:
    599   case kFormatRGBA1010102Ubwc:
    600   case kFormatRGBX1010102Ubwc:
    601     *target = width * 4;
    602     break;
    603   case kFormatRGB888:
    604   case kFormatBGR888:
    605     *target = width * 3;
    606     break;
    607   case kFormatRGB565:
    608   case kFormatBGR565:
    609   case kFormatBGR565Ubwc:
    610     *target = width * 2;
    611     break;
    612   case kFormatYCbCr420SemiPlanarVenus:
    613   case kFormatYCbCr420SPVenusUbwc:
    614   case kFormatYCbCr420Planar:
    615   case kFormatYCrCb420Planar:
    616   case kFormatYCrCb420PlanarStride16:
    617   case kFormatYCbCr420SemiPlanar:
    618   case kFormatYCrCb420SemiPlanar:
    619   case kFormatYCbCr420P010:
    620   case kFormatYCbCr420TP10Ubwc:
    621     *target = width;
    622     break;
    623   case kFormatYCbCr422H2V1Packed:
    624   case kFormatYCrCb422H2V1SemiPlanar:
    625   case kFormatYCrCb422H1V2SemiPlanar:
    626   case kFormatYCbCr422H2V1SemiPlanar:
    627   case kFormatYCbCr422H1V2SemiPlanar:
    628   case kFormatRGBA5551:
    629   case kFormatRGBA4444:
    630     *target = width * 2;
    631     break;
    632   default:
    633     DLOGE("Unsupported format type %d", format);
    634     return kErrorParameters;
    635   }
    636 
    637   return kErrorNone;
    638 }
    639 
    640 void HWDevice::SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target) {
    641   switch (source) {
    642   case kBlendingPremultiplied:  *target = BLEND_OP_PREMULTIPLIED;   break;
    643   case kBlendingOpaque:         *target = BLEND_OP_OPAQUE;          break;
    644   case kBlendingCoverage:       *target = BLEND_OP_COVERAGE;        break;
    645   default:                      *target = BLEND_OP_NOT_DEFINED;     break;
    646   }
    647 }
    648 
    649 void HWDevice::SetRect(const LayerRect &source, mdp_rect *target) {
    650   target->x = UINT32(source.left);
    651   target->y = UINT32(source.top);
    652   target->w = UINT32(source.right) - target->x;
    653   target->h = UINT32(source.bottom) - target->y;
    654 }
    655 
    656 void HWDevice::SetMDPFlags(const Layer *layer, const bool &is_rotator_used,
    657                            bool is_cursor_pipe_used, uint32_t *mdp_flags) {
    658   const LayerBuffer *input_buffer = layer->input_buffer;
    659 
    660   // Flips will be taken care by rotator, if layer uses rotator for downscale/rotation. So ignore
    661   // flip flags for MDP.
    662   if (!is_rotator_used) {
    663     if (layer->transform.flip_vertical) {
    664       *mdp_flags |= MDP_LAYER_FLIP_UD;
    665     }
    666 
    667     if (layer->transform.flip_horizontal) {
    668       *mdp_flags |= MDP_LAYER_FLIP_LR;
    669     }
    670 
    671     if (input_buffer->flags.interlace) {
    672       *mdp_flags |= MDP_LAYER_DEINTERLACE;
    673     }
    674   }
    675 
    676   if (input_buffer->flags.secure) {
    677     *mdp_flags |= MDP_LAYER_SECURE_SESSION;
    678   }
    679 
    680   if (input_buffer->flags.secure_display) {
    681     *mdp_flags |= MDP_LAYER_SECURE_DISPLAY_SESSION;
    682   }
    683 
    684   if (layer->flags.solid_fill) {
    685     *mdp_flags |= MDP_LAYER_SOLID_FILL;
    686   }
    687 
    688   if (hw_panel_info_.mode != kModeCommand && layer->flags.cursor && is_cursor_pipe_used) {
    689     // command mode panels does not support async position update
    690     *mdp_flags |= MDP_LAYER_ASYNC;
    691   }
    692 }
    693 
    694 int HWDevice::GetFBNodeIndex(HWDeviceType device_type) {
    695   for (int i = 0; i <= kDeviceVirtual; i++) {
    696     HWPanelInfo panel_info;
    697     GetHWPanelInfoByNode(i, &panel_info);
    698     switch (device_type) {
    699     case kDevicePrimary:
    700       if (panel_info.is_primary_panel) {
    701         return i;
    702       }
    703       break;
    704     case kDeviceHDMI:
    705       if (panel_info.is_pluggable == true) {
    706         return i;
    707       }
    708       break;
    709     case kDeviceVirtual:
    710       if (panel_info.port == kPortWriteBack) {
    711         return i;
    712       }
    713       break;
    714     default:
    715       break;
    716     }
    717   }
    718   return -1;
    719 }
    720 
    721 void HWDevice::PopulateHWPanelInfo() {
    722   hw_panel_info_ = HWPanelInfo();
    723   GetHWPanelInfoByNode(fb_node_index_, &hw_panel_info_);
    724   DLOGI("Device type = %d, Display Port = %d, Display Mode = %d, Device Node = %d, Is Primary = %d",
    725         device_type_, hw_panel_info_.port, hw_panel_info_.mode, fb_node_index_,
    726         hw_panel_info_.is_primary_panel);
    727   DLOGI("Partial Update = %d, Dynamic FPS = %d",
    728         hw_panel_info_.partial_update, hw_panel_info_.dynamic_fps);
    729   DLOGI("Align: left = %d, width = %d, top = %d, height = %d",
    730         hw_panel_info_.left_align, hw_panel_info_.width_align,
    731         hw_panel_info_.top_align, hw_panel_info_.height_align);
    732   DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d",
    733         hw_panel_info_.min_roi_width, hw_panel_info_.min_roi_height,
    734         hw_panel_info_.needs_roi_merge);
    735   DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps);
    736   DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split,
    737         hw_panel_info_.split_info.right_split);
    738 }
    739 
    740 void HWDevice::GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info) {
    741   string file_name = fb_path_ + to_string(device_node) + "/msm_fb_panel_info";
    742 
    743   Sys::fstream fs(file_name, fstream::in);
    744   if (!fs.is_open()) {
    745     DLOGW("Failed to open msm_fb_panel_info node device node %d", device_node);
    746     return;
    747   }
    748 
    749   string line;
    750   while (Sys::getline_(fs, line)) {
    751     uint32_t token_count = 0;
    752     const uint32_t max_count = 10;
    753     char *tokens[max_count] = { NULL };
    754     if (!ParseLine(line.c_str(), "=\n", tokens, max_count, &token_count)) {
    755       if (!strncmp(tokens[0], "panel_name", strlen("panel_name"))) {
    756         snprintf(panel_info->panel_name, sizeof(panel_info->panel_name), "%s", tokens[1]);
    757         break;
    758       }
    759     }
    760   }
    761 }
    762 
    763 void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) {
    764   string file_name = fb_path_ + to_string(device_node) + "/msm_fb_panel_info";
    765 
    766   Sys::fstream fs(file_name, fstream::in);
    767   if (!fs.is_open()) {
    768     DLOGW("Failed to open msm_fb_panel_info node device node %d", device_node);
    769     return;
    770   }
    771 
    772   string line;
    773   while (Sys::getline_(fs, line)) {
    774     uint32_t token_count = 0;
    775     const uint32_t max_count = 10;
    776     char *tokens[max_count] = { NULL };
    777     if (!ParseLine(line.c_str(), tokens, max_count, &token_count)) {
    778       if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
    779         panel_info->partial_update = atoi(tokens[1]);
    780       } else if (!strncmp(tokens[0], "xstart", strlen("xstart"))) {
    781         panel_info->left_align = atoi(tokens[1]);
    782       } else if (!strncmp(tokens[0], "walign", strlen("walign"))) {
    783         panel_info->width_align = atoi(tokens[1]);
    784       } else if (!strncmp(tokens[0], "ystart", strlen("ystart"))) {
    785         panel_info->top_align = atoi(tokens[1]);
    786       } else if (!strncmp(tokens[0], "halign", strlen("halign"))) {
    787         panel_info->height_align = atoi(tokens[1]);
    788       } else if (!strncmp(tokens[0], "min_w", strlen("min_w"))) {
    789         panel_info->min_roi_width = atoi(tokens[1]);
    790       } else if (!strncmp(tokens[0], "min_h", strlen("min_h"))) {
    791         panel_info->min_roi_height = atoi(tokens[1]);
    792       } else if (!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
    793         panel_info->needs_roi_merge = atoi(tokens[1]);
    794       } else if (!strncmp(tokens[0], "dyn_fps_en", strlen("dyn_fps_en"))) {
    795         panel_info->dynamic_fps = atoi(tokens[1]);
    796       } else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
    797         panel_info->min_fps = UINT32(atoi(tokens[1]));
    798       } else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
    799         panel_info->max_fps = UINT32(atoi(tokens[1]));
    800       } else if (!strncmp(tokens[0], "primary_panel", strlen("primary_panel"))) {
    801         panel_info->is_primary_panel = atoi(tokens[1]);
    802       } else if (!strncmp(tokens[0], "is_pluggable", strlen("is_pluggable"))) {
    803         panel_info->is_pluggable = atoi(tokens[1]);
    804       }
    805     }
    806   }
    807 
    808   GetHWDisplayPortAndMode(device_node, &panel_info->port, &panel_info->mode);
    809   GetSplitInfo(device_node, panel_info);
    810   GetHWPanelNameByNode(device_node, panel_info);
    811   GetHWPanelMaxBrightnessFromNode(panel_info);
    812 }
    813 
    814 void HWDevice::GetHWDisplayPortAndMode(int device_node, HWDisplayPort *port, HWDisplayMode *mode) {
    815   *port = kPortDefault;
    816   *mode = kModeDefault;
    817 
    818   string file_name = fb_path_ + to_string(device_node) + "/msm_fb_type";
    819 
    820   Sys::fstream fs(file_name, fstream::in);
    821   if (!fs.is_open()) {
    822     DLOGW("File not found %s", file_name.c_str());
    823     return;
    824   }
    825 
    826   string line;
    827   if (!Sys::getline_(fs, line)) {
    828     return;
    829   }
    830 
    831   if ((strncmp(line.c_str(), "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
    832     *port = kPortDSI;
    833     *mode = kModeCommand;
    834   } else if ((strncmp(line.c_str(), "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
    835     *port = kPortDSI;
    836     *mode = kModeVideo;
    837   } else if ((strncmp(line.c_str(), "lvds panel", strlen("lvds panel")) == 0)) {
    838     *port = kPortLVDS;
    839     *mode = kModeVideo;
    840   } else if ((strncmp(line.c_str(), "edp panel", strlen("edp panel")) == 0)) {
    841     *port = kPortEDP;
    842     *mode = kModeVideo;
    843   } else if ((strncmp(line.c_str(), "dtv panel", strlen("dtv panel")) == 0)) {
    844     *port = kPortDTv;
    845     *mode = kModeVideo;
    846   } else if ((strncmp(line.c_str(), "writeback panel", strlen("writeback panel")) == 0)) {
    847     *port = kPortWriteBack;
    848     *mode = kModeCommand;
    849   }
    850 
    851   return;
    852 }
    853 
    854 void HWDevice::GetSplitInfo(int device_node, HWPanelInfo *panel_info) {
    855   // Split info - for MDSS Version 5 - No need to check version here
    856   string file_name = fb_path_ + to_string(device_node) + "/msm_fb_split";
    857 
    858   Sys::fstream fs(file_name, fstream::in);
    859   if (!fs.is_open()) {
    860     DLOGW("File not found %s", file_name.c_str());
    861     return;
    862   }
    863 
    864   // Format "left right" space as delimiter
    865   uint32_t token_count = 0;
    866   const uint32_t max_count = 10;
    867   char *tokens[max_count] = { NULL };
    868   string line;
    869   if (Sys::getline_(fs, line)) {
    870     if (!ParseLine(line.c_str(), tokens, max_count, &token_count)) {
    871       panel_info->split_info.left_split = UINT32(atoi(tokens[0]));
    872       panel_info->split_info.right_split = UINT32(atoi(tokens[1]));
    873     }
    874   }
    875 }
    876 
    877 void HWDevice::GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info) {
    878   char brightness[kMaxStringLength] = { 0 };
    879   char kMaxBrightnessNode[64] = { 0 };
    880 
    881   snprintf(kMaxBrightnessNode, sizeof(kMaxBrightnessNode), "%s",
    882            "/sys/class/leds/lcd-backlight/max_brightness");
    883 
    884   panel_info->panel_max_brightness = 0;
    885   int fd = Sys::open_(kMaxBrightnessNode, O_RDONLY);
    886   if (fd < 0) {
    887     DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode,
    888           strerror(errno));
    889     return;
    890   }
    891 
    892   if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
    893     panel_info->panel_max_brightness = atoi(brightness);
    894     DLOGI("Max brightness level = %d", panel_info->panel_max_brightness);
    895   } else {
    896     DLOGW("Failed to read max brightness level. error = %s", strerror(errno));
    897   }
    898   Sys::close_(fd);
    899 }
    900 
    901 int HWDevice::ParseLine(const char *input, char *tokens[], const uint32_t max_token,
    902                         uint32_t *count) {
    903   char *tmp_token = NULL;
    904   char *temp_ptr;
    905   uint32_t index = 0;
    906   const char *delim = ", =\n";
    907   if (!input) {
    908     return -1;
    909   }
    910   tmp_token = strtok_r(const_cast<char *>(input), delim, &temp_ptr);
    911   while (tmp_token && index < max_token) {
    912     tokens[index++] = tmp_token;
    913     tmp_token = strtok_r(NULL, delim, &temp_ptr);
    914   }
    915   *count = index;
    916 
    917   return 0;
    918 }
    919 
    920 int HWDevice::ParseLine(const char *input, const char *delim, char *tokens[],
    921                         const uint32_t max_token, uint32_t *count) {
    922   char *tmp_token = NULL;
    923   char *temp_ptr;
    924   uint32_t index = 0;
    925   if (!input) {
    926     return -1;
    927   }
    928   tmp_token = strtok_r(const_cast<char *>(input), delim, &temp_ptr);
    929   while (tmp_token && index < max_token) {
    930     tokens[index++] = tmp_token;
    931     tmp_token = strtok_r(NULL, delim, &temp_ptr);
    932   }
    933   *count = index;
    934 
    935   return 0;
    936 }
    937 
    938 bool HWDevice::EnableHotPlugDetection(int enable) {
    939   char hpdpath[kMaxStringLength];
    940   int hdmi_node_index = GetFBNodeIndex(kDeviceHDMI);
    941   if (hdmi_node_index < 0) {
    942     return false;
    943   }
    944 
    945   snprintf(hpdpath , sizeof(hpdpath), "%s%d/hpd", fb_path_, hdmi_node_index);
    946 
    947   char value = enable ? '1' : '0';
    948   ssize_t length = SysFsWrite(hpdpath, &value, sizeof(value));
    949   if (length <= 0) {
    950     return false;
    951   }
    952 
    953   return true;
    954 }
    955 
    956 void HWDevice::ResetDisplayParams() {
    957   memset(&mdp_disp_commit_, 0, sizeof(mdp_disp_commit_));
    958   memset(&mdp_in_layers_, 0, sizeof(mdp_in_layers_));
    959   memset(&mdp_out_layer_, 0, sizeof(mdp_out_layer_));
    960   mdp_out_layer_.buffer.fence = -1;
    961   hw_scale_->ResetScaleParams();
    962   memset(&pp_params_, 0, sizeof(pp_params_));
    963   memset(&igc_lut_data_, 0, sizeof(igc_lut_data_));
    964 
    965   for (size_t i = 0; i < mdp_dest_scalar_data_.size(); i++) {
    966     mdp_dest_scalar_data_[i] = {};
    967   }
    968 
    969   for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
    970     mdp_in_layers_[i].buffer.fence = -1;
    971   }
    972 
    973   mdp_disp_commit_.version = MDP_COMMIT_VERSION_1_0;
    974   mdp_disp_commit_.commit_v1.input_layers = mdp_in_layers_;
    975   mdp_disp_commit_.commit_v1.output_layer = &mdp_out_layer_;
    976   mdp_disp_commit_.commit_v1.release_fence = -1;
    977   mdp_disp_commit_.commit_v1.retire_fence = -1;
    978   mdp_disp_commit_.commit_v1.dest_scaler = mdp_dest_scalar_data_.data();
    979 }
    980 
    981 void HWDevice::SetCSC(LayerCSC source, mdp_color_space *color_space) {
    982   switch (source) {
    983   case kCSCLimitedRange601:    *color_space = MDP_CSC_ITU_R_601;      break;
    984   case kCSCFullRange601:       *color_space = MDP_CSC_ITU_R_601_FR;   break;
    985   case kCSCLimitedRange709:    *color_space = MDP_CSC_ITU_R_709;      break;
    986   }
    987 }
    988 
    989 void HWDevice::SetIGC(const LayerBuffer *layer_buffer, uint32_t index) {
    990   mdp_input_layer &mdp_layer = mdp_in_layers_[index];
    991   mdp_overlay_pp_params &pp_params = pp_params_[index];
    992   mdp_igc_lut_data_v1_7 &igc_lut_data = igc_lut_data_[index];
    993 
    994   switch (layer_buffer->igc) {
    995   case kIGCsRGB:
    996     igc_lut_data.table_fmt = mdp_igc_srgb;
    997     pp_params.igc_cfg.ops = MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE;
    998     break;
    999 
   1000   default:
   1001     pp_params.igc_cfg.ops = MDP_PP_OPS_DISABLE;
   1002     break;
   1003   }
   1004 
   1005   pp_params.config_ops = MDP_OVERLAY_PP_IGC_CFG;
   1006   pp_params.igc_cfg.version = mdp_igc_v1_7;
   1007   pp_params.igc_cfg.cfg_payload = &igc_lut_data;
   1008 
   1009   mdp_layer.pp_info = &pp_params;
   1010   mdp_layer.flags |= MDP_LAYER_PP;
   1011 }
   1012 
   1013 DisplayError HWDevice::SetCursorPosition(HWLayers *hw_layers, int x, int y) {
   1014   DTRACE_SCOPED();
   1015 
   1016   HWLayersInfo &hw_layer_info = hw_layers->info;
   1017   uint32_t count = hw_layer_info.count;
   1018   uint32_t cursor_index = count - 1;
   1019   HWPipeInfo *left_pipe = &hw_layers->config[cursor_index].left_pipe;
   1020 
   1021   mdp_async_layer async_layer = {};
   1022   async_layer.flags = MDP_LAYER_ASYNC;
   1023   async_layer.pipe_ndx = left_pipe->pipe_id;
   1024   async_layer.src.x = UINT32(left_pipe->src_roi.left);
   1025   async_layer.src.y = UINT32(left_pipe->src_roi.top);
   1026   async_layer.dst.x = UINT32(x);
   1027   async_layer.dst.y = UINT32(y);
   1028 
   1029   mdp_position_update pos_update = {};
   1030   pos_update.input_layer_cnt = 1;
   1031   pos_update.input_layers = &async_layer;
   1032   if (Sys::ioctl_(device_fd_, INT(MSMFB_ASYNC_POSITION_UPDATE), &pos_update) < 0) {
   1033     if (errno == ESHUTDOWN) {
   1034       DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
   1035       return kErrorShutDown;
   1036     }
   1037     IOCTL_LOGE(MSMFB_ASYNC_POSITION_UPDATE, device_type_);
   1038     return kErrorHardware;
   1039   }
   1040 
   1041   return kErrorNone;
   1042 }
   1043 
   1044 DisplayError HWDevice::GetPPFeaturesVersion(PPFeatureVersion *vers) {
   1045   return kErrorNotSupported;
   1046 }
   1047 
   1048 DisplayError HWDevice::SetPPFeatures(PPFeaturesConfig *feature_list) {
   1049   return kErrorNotSupported;
   1050 }
   1051 
   1052 DisplayError HWDevice::SetVSyncState(bool enable) {
   1053   int vsync_on = enable ? 1 : 0;
   1054   if (Sys::ioctl_(device_fd_, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) < 0) {
   1055     IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, device_type_);
   1056     return kErrorHardware;
   1057   }
   1058   return kErrorNone;
   1059 }
   1060 
   1061 void HWDevice::SetIdleTimeoutMs(uint32_t timeout_ms) {
   1062 }
   1063 
   1064 DisplayError HWDevice::SetDisplayMode(const HWDisplayMode hw_display_mode) {
   1065   return kErrorNotSupported;
   1066 }
   1067 
   1068 DisplayError HWDevice::SetRefreshRate(uint32_t refresh_rate) {
   1069   return kErrorNotSupported;
   1070 }
   1071 
   1072 DisplayError HWDevice::SetPanelBrightness(int level) {
   1073   return kErrorNotSupported;
   1074 }
   1075 
   1076 DisplayError HWDevice::GetHWScanInfo(HWScanInfo *scan_info) {
   1077   return kErrorNotSupported;
   1078 }
   1079 
   1080 DisplayError HWDevice::GetVideoFormat(uint32_t config_index, uint32_t *video_format) {
   1081   return kErrorNotSupported;
   1082 }
   1083 
   1084 DisplayError HWDevice::GetMaxCEAFormat(uint32_t *max_cea_format) {
   1085   return kErrorNotSupported;
   1086 }
   1087 
   1088 DisplayError HWDevice::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
   1089   return kErrorNotSupported;
   1090 }
   1091 
   1092 DisplayError HWDevice::GetPanelBrightness(int *level) {
   1093   return kErrorNotSupported;
   1094 }
   1095 
   1096 ssize_t HWDevice::SysFsWrite(const char* file_node, const char* value, ssize_t length) {
   1097   int fd = Sys::open_(file_node, O_RDWR, 0);
   1098   if (fd < 0) {
   1099     DLOGW("Open failed = %s", file_node);
   1100     return -1;
   1101   }
   1102   ssize_t len = Sys::pwrite_(fd, value, static_cast<size_t>(length), 0);
   1103   if (len <= 0) {
   1104     DLOGE("Write failed for path %s with value %s", file_node, value);
   1105   }
   1106   Sys::close_(fd);
   1107 
   1108   return len;
   1109 }
   1110 
   1111 DisplayError HWDevice::SetS3DMode(HWS3DMode s3d_mode) {
   1112   return kErrorNotSupported;
   1113 }
   1114 
   1115 DisplayError HWDevice::SetScaleLutConfig(HWScaleLutInfo *lut_info) {
   1116   mdp_scale_luts_info mdp_lut_info = {};
   1117   mdp_set_cfg cfg = {};
   1118 
   1119   if (!hw_resource_.has_qseed3) {
   1120     DLOGV_IF(kTagDriverConfig, "No support for QSEED3 luts");
   1121     return kErrorNone;
   1122   }
   1123 
   1124   if (!lut_info->dir_lut_size && !lut_info->dir_lut && !lut_info->cir_lut_size &&
   1125       !lut_info->cir_lut && !lut_info->sep_lut_size && !lut_info->sep_lut) {
   1126       // HWSupports QSEED3, but LutInfo is invalid as scalar is disabled by property or
   1127       // its loading failed. Driver will use default settings/filter
   1128       return kErrorNone;
   1129   }
   1130 
   1131   mdp_lut_info.dir_lut_size = lut_info->dir_lut_size;
   1132   mdp_lut_info.dir_lut = lut_info->dir_lut;
   1133   mdp_lut_info.cir_lut_size = lut_info->cir_lut_size;
   1134   mdp_lut_info.cir_lut = lut_info->cir_lut;
   1135   mdp_lut_info.sep_lut_size = lut_info->sep_lut_size;
   1136   mdp_lut_info.sep_lut = lut_info->sep_lut;
   1137 
   1138   cfg.flags = MDP_QSEED3_LUT_CFG;
   1139   cfg.len = sizeof(mdp_scale_luts_info);
   1140   cfg.payload = reinterpret_cast<uint64_t>(&mdp_lut_info);
   1141 
   1142   if (Sys::ioctl_(device_fd_, MSMFB_MDP_SET_CFG, &cfg) < 0) {
   1143     IOCTL_LOGE(MSMFB_MDP_SET_CFG, device_type_);
   1144     return kErrorHardware;
   1145   }
   1146 
   1147   return kErrorNone;
   1148 }
   1149 
   1150 DisplayError HWDevice::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
   1151   if (!hw_resource_.hw_dest_scalar_info.count) {
   1152     return kErrorNotSupported;
   1153   }
   1154 
   1155   if (mixer_attributes.width > display_attributes_.x_pixels ||
   1156       mixer_attributes.height > display_attributes_.y_pixels) {
   1157     DLOGW("Input resolution exceeds display resolution! input: res %dx%d display: res %dx%d",
   1158           mixer_attributes.width, mixer_attributes.height, display_attributes_.x_pixels,
   1159           display_attributes_.y_pixels);
   1160     return kErrorNotSupported;
   1161   }
   1162 
   1163   uint32_t max_input_width = hw_resource_.hw_dest_scalar_info.max_input_width;
   1164   if (display_attributes_.is_device_split) {
   1165     max_input_width *= 2;
   1166   }
   1167 
   1168   if (mixer_attributes.width > max_input_width) {
   1169     DLOGW("Input width exceeds width limit! input_width %d width_limit %d", mixer_attributes.width,
   1170           max_input_width);
   1171     return kErrorNotSupported;
   1172   }
   1173 
   1174   float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height);
   1175   float display_aspect_ratio =
   1176     FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels);
   1177 
   1178   if (display_aspect_ratio != mixer_aspect_ratio) {
   1179     DLOGW("Aspect ratio mismatch! input: res %dx%d display: res %dx%d", mixer_attributes.width,
   1180           mixer_attributes.height, display_attributes_.x_pixels, display_attributes_.y_pixels);
   1181     return kErrorNotSupported;
   1182   }
   1183 
   1184   float scale_x = FLOAT(display_attributes_.x_pixels) / FLOAT(mixer_attributes.width);
   1185   float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height);
   1186   float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up;
   1187   if (scale_x > max_scale_up || scale_y > max_scale_up) {
   1188     DLOGW("Up scaling ratio exceeds for destination scalar upscale limit scale_x %f scale_y %f " \
   1189           "max_scale_up %f", scale_x, scale_y, max_scale_up);
   1190     return kErrorNotSupported;
   1191   }
   1192 
   1193   float mixer_split_ratio = FLOAT(mixer_attributes_.split_left) / FLOAT(mixer_attributes_.width);
   1194 
   1195   mixer_attributes_ = mixer_attributes;
   1196   mixer_attributes_.split_left = mixer_attributes_.width;
   1197   if (display_attributes_.is_device_split) {
   1198     mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio);
   1199   }
   1200 
   1201   return kErrorNone;
   1202 }
   1203 
   1204 DisplayError HWDevice::GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
   1205   if (!mixer_attributes) {
   1206     return kErrorParameters;
   1207   }
   1208 
   1209   *mixer_attributes = mixer_attributes_;
   1210 
   1211   return kErrorNone;
   1212 }
   1213 
   1214 }  // namespace sdm
   1215 
   1216