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