Home | History | Annotate | Download | only in fb
      1 /*
      2 * Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
      3 *
      4 * Redistribution and use in source and binary forms, with or without
      5 * modification, are permitted provided that the following conditions are
      6 * met:
      7 *     * Redistributions of source code must retain the above copyright
      8 *       notice, this list of conditions and the following disclaimer.
      9 *     * Redistributions in binary form must reproduce the above
     10 *       copyright notice, this list of conditions and the following
     11 *       disclaimer in the documentation and/or other materials provided
     12 *       with the distribution.
     13 *     * Neither the name of The Linux Foundation nor the names of its
     14 *       contributors may be used to endorse or promote products derived
     15 *       from this software without specific prior written permission.
     16 *
     17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 */
     29 
     30 #include <stdio.h>
     31 #include <unistd.h>
     32 #include <string.h>
     33 #include <sys/ioctl.h>
     34 #include <ctype.h>
     35 #include <fcntl.h>
     36 #include <linux/videodev2.h>
     37 #include <utils/debug.h>
     38 #include <utils/sys.h>
     39 #include <utils/formats.h>
     40 
     41 #include <vector>
     42 #include <map>
     43 #include <utility>
     44 
     45 #include "hw_hdmi.h"
     46 
     47 #define __CLASS__ "HWHDMI"
     48 
     49 #define  MIN_HDR_RESET_WAITTIME_SEC 2
     50 
     51 namespace sdm {
     52 
     53 #ifdef MDP_HDR_STREAM
     54 static int32_t GetEOTF(const GammaTransfer &transfer) {
     55   int32_t mdp_transfer = -1;
     56 
     57   switch (transfer) {
     58   case Transfer_SMPTE_ST2084:
     59     mdp_transfer = MDP_HDR_EOTF_SMTPE_ST2084;
     60     break;
     61   case Transfer_HLG:
     62     mdp_transfer = MDP_HDR_EOTF_HLG;
     63     break;
     64   default:
     65     DLOGW("Unknown Transfer: %d", transfer);
     66   }
     67 
     68   return mdp_transfer;
     69 }
     70 
     71 static int32_t GetColoriMetry(const LayerBuffer & layer_buffer) {
     72   bool is_yuv = layer_buffer.flags.video;
     73   int32_t colorimetry = -1;
     74 
     75   if (is_yuv) {
     76     switch (layer_buffer.color_metadata.colorPrimaries) {
     77     case ColorPrimaries_BT601_6_525:
     78     case ColorPrimaries_BT601_6_625:
     79       colorimetry = MDP_COLORIMETRY_YCBCR_ITU_R_BT_601;
     80       break;
     81     case ColorPrimaries_BT709_5:
     82       colorimetry = MDP_COLORIMETRY_YCBCR_ITU_R_BT_709;
     83       break;
     84     case ColorPrimaries_BT2020:
     85       colorimetry = MDP_COLORIMETRY_YCBCR_ITU_R_BT_2020_YCBCR;
     86       break;
     87     default:
     88       DLOGW("Unknown color primary = %d for YUV", layer_buffer.color_metadata.colorPrimaries);
     89     }
     90   }
     91 
     92   return colorimetry;
     93 }
     94 
     95 static int32_t GetPixelEncoding(const LayerBuffer &layer_buffer) {
     96   bool is_yuv = layer_buffer.flags.video;
     97   int32_t mdp_pixel_encoding = -1;
     98   mdp_pixel_encoding = MDP_PIXEL_ENCODING_RGB;  // set RGB as default
     99 
    100   if (is_yuv) {
    101     switch (layer_buffer.format) {
    102     case kFormatYCbCr420SemiPlanarVenus:
    103     case kFormatYCbCr420SPVenusUbwc:
    104     case kFormatYCbCr420Planar:
    105     case kFormatYCrCb420Planar:
    106     case kFormatYCrCb420PlanarStride16:
    107     case kFormatYCbCr420SemiPlanar:
    108     case kFormatYCrCb420SemiPlanar:
    109     case kFormatYCbCr420P010:
    110     case kFormatYCbCr420TP10Ubwc:
    111       mdp_pixel_encoding = MDP_PIXEL_ENCODING_YCBCR_420;
    112       break;
    113     case kFormatYCbCr422H2V1Packed:
    114     case kFormatYCrCb422H2V1SemiPlanar:
    115     case kFormatYCrCb422H1V2SemiPlanar:
    116     case kFormatYCbCr422H2V1SemiPlanar:
    117     case kFormatYCbCr422H1V2SemiPlanar:
    118       mdp_pixel_encoding = MDP_PIXEL_ENCODING_YCBCR_422;
    119       break;
    120     default:  // other yuv formats
    121       DLOGW("New YUV format = %d, need to add support", layer_buffer.format);
    122       break;
    123     }
    124   }
    125 
    126   return mdp_pixel_encoding;
    127 }
    128 static int32_t GetBitsPerComponent(const LayerBuffer &layer_buffer) {
    129   bool is_yuv = layer_buffer.flags.video;
    130   bool is_10_bit = Is10BitFormat(layer_buffer.format);
    131   int32_t mdp_bpc = -1;
    132 
    133   if (is_yuv) {
    134     mdp_bpc = is_10_bit ? MDP_YUV_10_BPC : MDP_YUV_8_BPC;
    135   } else {
    136     mdp_bpc = is_10_bit ? MDP_RGB_10_BPC : MDP_RGB_8_BPC;
    137   }
    138 
    139   return mdp_bpc;
    140 }
    141 
    142 static uint32_t GetRange(const ColorRange &range) {
    143   return ((range == Range_Full) ? MDP_DYNAMIC_RANGE_VESA : MDP_DYNAMIC_RANGE_CEA);
    144 }
    145 
    146 static uint32_t GetContentType(const LayerBuffer &layer_buffer) {
    147   return (layer_buffer.flags.video ? MDP_CONTENT_TYPE_VIDEO : MDP_CONTENT_TYPE_GRAPHICS);
    148 }
    149 #endif
    150 
    151 static bool MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode,
    152                                  fb_var_screeninfo *info) {
    153   if (!mode || !info) {
    154     return false;
    155   }
    156 
    157   info->reserved[0] = 0;
    158   info->reserved[1] = 0;
    159   info->reserved[2] = 0;
    160   info->reserved[3] = (info->reserved[3] & 0xFFFF) | (mode->video_format << 16);
    161   info->xoffset = 0;
    162   info->yoffset = 0;
    163   info->xres = mode->active_h;
    164   info->yres = mode->active_v;
    165   info->pixclock = (mode->pixel_freq) * 1000;
    166   info->vmode = mode->interlaced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
    167   info->right_margin = mode->front_porch_h;
    168   info->hsync_len = mode->pulse_width_h;
    169   info->left_margin = mode->back_porch_h;
    170   info->lower_margin = mode->front_porch_v;
    171   info->vsync_len = mode->pulse_width_v;
    172   info->upper_margin = mode->back_porch_v;
    173 
    174   info->grayscale = V4L2_PIX_FMT_RGB24;
    175   // If the mode supports YUV420 set grayscale to the FOURCC value for YUV420.
    176   std::bitset<32> pixel_formats = mode->pixel_formats;
    177   if (pixel_formats[1]) {
    178     info->grayscale = V4L2_PIX_FMT_NV12;
    179   }
    180 
    181   if (!mode->active_low_h) {
    182     info->sync |= (uint32_t)FB_SYNC_HOR_HIGH_ACT;
    183   } else {
    184     info->sync &= (uint32_t)~FB_SYNC_HOR_HIGH_ACT;
    185   }
    186 
    187   if (!mode->active_low_v) {
    188     info->sync |= (uint32_t)FB_SYNC_VERT_HIGH_ACT;
    189   } else {
    190     info->sync &= (uint32_t)~FB_SYNC_VERT_HIGH_ACT;
    191   }
    192 
    193   return true;
    194 }
    195 
    196 HWHDMI::HWHDMI(BufferSyncHandler *buffer_sync_handler,  HWInfoInterface *hw_info_intf)
    197   : HWDevice(buffer_sync_handler), hw_scan_info_(), active_config_index_(0) {
    198   HWDevice::device_type_ = kDeviceHDMI;
    199   HWDevice::device_name_ = "HDMI Display Device";
    200   HWDevice::hw_info_intf_ = hw_info_intf;
    201   (void)hdr_reset_start_;
    202   (void)hdr_reset_end_;
    203   (void)reset_hdr_flag_;
    204   (void)cdm_color_space_;
    205 }
    206 
    207 DisplayError HWHDMI::Init() {
    208   DisplayError error = kErrorNone;
    209 
    210   SetSourceProductInformation("vendor_name", "ro.product.manufacturer");
    211   SetSourceProductInformation("product_description", "ro.product.name");
    212 
    213   error = HWDevice::Init();
    214   if (error != kErrorNone) {
    215     return error;
    216   }
    217 
    218   mdp_dest_scalar_data_.resize(hw_resource_.hw_dest_scalar_info.count);
    219 
    220   error = ReadEDIDInfo();
    221   if (error != kErrorNone) {
    222     Deinit();
    223     return error;
    224   }
    225 
    226   if (!IsResolutionFilePresent()) {
    227     Deinit();
    228     return kErrorHardware;
    229   }
    230 
    231   error = ReadTimingInfo();
    232   if (error != kErrorNone) {
    233     Deinit();
    234     return error;
    235   }
    236 
    237   ReadScanInfo();
    238 
    239   GetPanelS3DMode();
    240 
    241   s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
    242                              (kS3DModeNone, HDMI_S3D_NONE));
    243   s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
    244                              (kS3DModeLR, HDMI_S3D_SIDE_BY_SIDE));
    245   s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
    246                              (kS3DModeRL, HDMI_S3D_SIDE_BY_SIDE));
    247   s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
    248                              (kS3DModeTB, HDMI_S3D_TOP_AND_BOTTOM));
    249   s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
    250                              (kS3DModeFP, HDMI_S3D_FRAME_PACKING));
    251 
    252   return error;
    253 }
    254 
    255 DisplayError HWHDMI::GetNumDisplayAttributes(uint32_t *count) {
    256   *count = UINT32(hdmi_modes_.size());
    257   if (*count <= 0) {
    258     return kErrorHardware;
    259   }
    260 
    261   return kErrorNone;
    262 }
    263 
    264 DisplayError HWHDMI::GetActiveConfig(uint32_t *active_config_index) {
    265   *active_config_index = active_config_index_;
    266   return kErrorNone;
    267 }
    268 
    269 DisplayError HWHDMI::ReadEDIDInfo() {
    270   ssize_t length = -1;
    271   char edid_str[kPageSize] = {'\0'};
    272   char edid_path[kMaxStringLength] = {'\0'};
    273   snprintf(edid_path, sizeof(edid_path), "%s%d/edid_modes", fb_path_, fb_node_index_);
    274   int edid_file = Sys::open_(edid_path, O_RDONLY);
    275   if (edid_file < 0) {
    276     DLOGE("EDID file open failed.");
    277     return kErrorHardware;
    278   }
    279 
    280   length = Sys::pread_(edid_file, edid_str, sizeof(edid_str)-1, 0);
    281   if (length <= 0) {
    282     DLOGE("%s: edid_modes file empty");
    283     return kErrorHardware;
    284   }
    285   Sys::close_(edid_file);
    286 
    287   DLOGI("EDID mode string: %s", edid_str);
    288   while (length > 1 && isspace(edid_str[length-1])) {
    289     --length;
    290   }
    291   edid_str[length] = '\0';
    292 
    293   if (length > 0) {
    294     // Get EDID modes from the EDID string
    295     char *ptr = edid_str;
    296     const uint32_t edid_count_max = 128;
    297     char *tokens[edid_count_max] = { NULL };
    298     uint32_t hdmi_mode_count = 0;
    299 
    300     ParseLine(ptr, tokens, edid_count_max, &hdmi_mode_count);
    301 
    302     supported_video_modes_.resize(hdmi_mode_count);
    303 
    304     hdmi_modes_.resize(hdmi_mode_count);
    305     for (uint32_t i = 0; i < hdmi_mode_count; i++) {
    306       hdmi_modes_[i] = UINT32(atoi(tokens[i]));
    307     }
    308   }
    309 
    310   return kErrorNone;
    311 }
    312 
    313 DisplayError HWHDMI::GetDisplayAttributes(uint32_t index,
    314                                           HWDisplayAttributes *display_attributes) {
    315   DTRACE_SCOPED();
    316 
    317   if (index >= hdmi_modes_.size()) {
    318     return kErrorNotSupported;
    319   }
    320 
    321   // Get the resolution info from the look up table
    322   msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[0];
    323   for (uint32_t i = 0; i < hdmi_modes_.size(); i++) {
    324     msm_hdmi_mode_timing_info *cur = &supported_video_modes_[i];
    325     if (cur->video_format == hdmi_modes_[index]) {
    326       timing_mode = cur;
    327       break;
    328     }
    329   }
    330   display_attributes->x_pixels = timing_mode->active_h;
    331   display_attributes->y_pixels = timing_mode->active_v;
    332   display_attributes->v_front_porch = timing_mode->front_porch_v;
    333   display_attributes->v_back_porch = timing_mode->back_porch_v;
    334   display_attributes->v_pulse_width = timing_mode->pulse_width_v;
    335   uint32_t h_blanking = timing_mode->front_porch_h + timing_mode->back_porch_h +
    336       timing_mode->pulse_width_h;
    337   display_attributes->h_total = timing_mode->active_h + h_blanking;
    338   display_attributes->x_dpi = 0;
    339   display_attributes->y_dpi = 0;
    340   display_attributes->fps = timing_mode->refresh_rate / 1000;
    341   display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
    342   display_attributes->is_device_split = false;
    343   if (display_attributes->x_pixels > hw_resource_.max_mixer_width) {
    344     display_attributes->is_device_split = true;
    345     display_attributes->h_total += h_blanking;
    346   }
    347 
    348   GetDisplayS3DSupport(index, display_attributes);
    349   std::bitset<32> pixel_formats = timing_mode->pixel_formats;
    350 
    351   display_attributes->is_yuv = pixel_formats[1];
    352 
    353   return kErrorNone;
    354 }
    355 
    356 DisplayError HWHDMI::SetDisplayAttributes(uint32_t index) {
    357   DTRACE_SCOPED();
    358 
    359   if (index > hdmi_modes_.size()) {
    360     return kErrorNotSupported;
    361   }
    362 
    363   // Variable screen info
    364   fb_var_screeninfo vscreeninfo = {};
    365   if (Sys::ioctl_(device_fd_, FBIOGET_VSCREENINFO, &vscreeninfo) < 0) {
    366     IOCTL_LOGE(FBIOGET_VSCREENINFO, device_type_);
    367     return kErrorHardware;
    368   }
    369 
    370   DLOGI("GetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3],
    371         vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
    372         vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
    373         vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
    374 
    375   msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[0];
    376   for (uint32_t i = 0; i < hdmi_modes_.size(); i++) {
    377     msm_hdmi_mode_timing_info *cur = &supported_video_modes_[i];
    378     if (cur->video_format == hdmi_modes_[index]) {
    379       timing_mode = cur;
    380       break;
    381     }
    382   }
    383 
    384   if (MapHDMIDisplayTiming(timing_mode, &vscreeninfo) == false) {
    385     return kErrorParameters;
    386   }
    387 
    388   msmfb_metadata metadata = {};
    389   metadata.op = metadata_op_vic;
    390   metadata.data.video_info_code = timing_mode->video_format;
    391   if (Sys::ioctl_(device_fd_, MSMFB_METADATA_SET, &metadata) < 0) {
    392     IOCTL_LOGE(MSMFB_METADATA_SET, device_type_);
    393     return kErrorHardware;
    394   }
    395 
    396   DLOGI("SetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3] & 0xFF00,
    397         vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
    398         vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
    399         vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
    400 
    401   vscreeninfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
    402   if (Sys::ioctl_(device_fd_, FBIOPUT_VSCREENINFO, &vscreeninfo) < 0) {
    403     IOCTL_LOGE(FBIOPUT_VSCREENINFO, device_type_);
    404     return kErrorHardware;
    405   }
    406 
    407   active_config_index_ = index;
    408 
    409   frame_rate_ = timing_mode->refresh_rate;
    410 
    411   // Get the display attributes for current active config index
    412   GetDisplayAttributes(active_config_index_, &display_attributes_);
    413   UpdateMixerAttributes();
    414 
    415   supported_s3d_modes_.clear();
    416   supported_s3d_modes_.push_back(kS3DModeNone);
    417   for (uint32_t mode = kS3DModeNone + 1; mode < kS3DModeMax; mode ++) {
    418     if (display_attributes_.s3d_config[(HWS3DMode)mode]) {
    419       supported_s3d_modes_.push_back((HWS3DMode)mode);
    420     }
    421   }
    422 
    423   SetS3DMode(kS3DModeNone);
    424 
    425   return kErrorNone;
    426 }
    427 
    428 DisplayError HWHDMI::GetConfigIndex(uint32_t mode, uint32_t *index) {
    429   // Check if the mode is valid and return corresponding index
    430   for (uint32_t i = 0; i < hdmi_modes_.size(); i++) {
    431     if (hdmi_modes_[i] == mode) {
    432       *index = i;
    433       DLOGI("Index = %d for config = %d", *index, mode);
    434       return kErrorNone;
    435     }
    436   }
    437 
    438   DLOGE("Config = %d not supported", mode);
    439   return kErrorNotSupported;
    440 }
    441 
    442 DisplayError HWHDMI::Validate(HWLayers *hw_layers) {
    443   HWDevice::ResetDisplayParams();
    444   return HWDevice::Validate(hw_layers);
    445 }
    446 
    447 DisplayError HWHDMI::Commit(HWLayers *hw_layers) {
    448   DisplayError error = UpdateHDRMetaData(hw_layers);
    449   if (error != kErrorNone) {
    450     return error;
    451   }
    452   if (cdm_color_space_commit_) {
    453 #ifdef MDP_COMMIT_UPDATE_CDM_COLOR_SPACE
    454     mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
    455     mdp_commit.cdm_color_space = cdm_color_space_;
    456     mdp_commit.flags |= MDP_COMMIT_UPDATE_CDM_COLOR_SPACE;
    457 #endif
    458   }
    459 
    460   error = HWDevice::Commit(hw_layers);
    461   if (cdm_color_space_commit_)
    462     cdm_color_space_commit_ = false;
    463 
    464   return error;
    465 }
    466 
    467 DisplayError HWHDMI::GetHWScanInfo(HWScanInfo *scan_info) {
    468   if (!scan_info) {
    469     return kErrorParameters;
    470   }
    471   *scan_info = hw_scan_info_;
    472   return kErrorNone;
    473 }
    474 
    475 DisplayError HWHDMI::GetVideoFormat(uint32_t config_index, uint32_t *video_format) {
    476   if (config_index > hdmi_modes_.size()) {
    477     return kErrorNotSupported;
    478   }
    479 
    480   *video_format = hdmi_modes_[config_index];
    481 
    482   return kErrorNone;
    483 }
    484 
    485 DisplayError HWHDMI::GetMaxCEAFormat(uint32_t *max_cea_format) {
    486   *max_cea_format = HDMI_VFRMT_END;
    487 
    488   return kErrorNone;
    489 }
    490 
    491 DisplayError HWHDMI::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
    492   DisplayError error = kErrorNone;
    493   int fd = -1;
    494   char data[kMaxStringLength] = {'\0'};
    495 
    496   snprintf(data, sizeof(data), "%s%d/hdcp2p2/min_level_change", fb_path_, fb_node_index_);
    497 
    498   fd = Sys::open_(data, O_WRONLY);
    499   if (fd < 0) {
    500     DLOGW("File '%s' could not be opened.", data);
    501     return kErrorHardware;
    502   }
    503 
    504   snprintf(data, sizeof(data), "%d", min_enc_level);
    505 
    506   ssize_t err = Sys::pwrite_(fd, data, strlen(data), 0);
    507   if (err <= 0) {
    508     DLOGE("Write failed, Error = %s", strerror(errno));
    509     error = kErrorHardware;
    510   }
    511 
    512   Sys::close_(fd);
    513 
    514   return error;
    515 }
    516 
    517 HWScanSupport HWHDMI::MapHWScanSupport(uint32_t value) {
    518   switch (value) {
    519   // TODO(user): Read the scan type from driver defined values instead of hardcoding
    520   case 0:
    521     return kScanNotSupported;
    522   case 1:
    523     return kScanAlwaysOverscanned;
    524   case 2:
    525     return kScanAlwaysUnderscanned;
    526   case 3:
    527     return kScanBoth;
    528   default:
    529     return kScanNotSupported;
    530     break;
    531   }
    532 }
    533 
    534 void HWHDMI::ReadScanInfo() {
    535   int scan_info_file = -1;
    536   ssize_t len = -1;
    537   char data[kPageSize] = {'\0'};
    538 
    539   snprintf(data, sizeof(data), "%s%d/scan_info", fb_path_, fb_node_index_);
    540   scan_info_file = Sys::open_(data, O_RDONLY);
    541   if (scan_info_file < 0) {
    542     DLOGW("File '%s' not found.", data);
    543     return;
    544   }
    545 
    546   memset(&data[0], 0, sizeof(data));
    547   len = Sys::pread_(scan_info_file, data, sizeof(data) - 1, 0);
    548   if (len <= 0) {
    549     Sys::close_(scan_info_file);
    550     DLOGW("File %s%d/scan_info is empty.", fb_path_, fb_node_index_);
    551     return;
    552   }
    553   data[len] = '\0';
    554   Sys::close_(scan_info_file);
    555 
    556   const uint32_t scan_info_max_count = 3;
    557   uint32_t scan_info_count = 0;
    558   char *tokens[scan_info_max_count] = { NULL };
    559   ParseLine(data, tokens, scan_info_max_count, &scan_info_count);
    560   if (scan_info_count != scan_info_max_count) {
    561     DLOGW("Failed to parse scan info string %s", data);
    562     return;
    563   }
    564 
    565   hw_scan_info_.pt_scan_support = MapHWScanSupport(UINT32(atoi(tokens[0])));
    566   hw_scan_info_.it_scan_support = MapHWScanSupport(UINT32(atoi(tokens[1])));
    567   hw_scan_info_.cea_scan_support = MapHWScanSupport(UINT32(atoi(tokens[2])));
    568   DLOGI("PT %d IT %d CEA %d", hw_scan_info_.pt_scan_support, hw_scan_info_.it_scan_support,
    569         hw_scan_info_.cea_scan_support);
    570 }
    571 
    572 int HWHDMI::OpenResolutionFile(int file_mode) {
    573   char file_path[kMaxStringLength];
    574   memset(file_path, 0, sizeof(file_path));
    575   snprintf(file_path , sizeof(file_path), "%s%d/res_info", fb_path_, fb_node_index_);
    576 
    577   int fd = Sys::open_(file_path, file_mode);
    578 
    579   if (fd < 0) {
    580     DLOGE("file '%s' not found : ret = %d err str: %s", file_path, fd, strerror(errno));
    581   }
    582 
    583   return fd;
    584 }
    585 
    586 // Method to request HDMI driver to write a new page of timing info into res_info node
    587 void HWHDMI::RequestNewPage(uint32_t page_number) {
    588   char page_string[kPageSize];
    589   int fd = OpenResolutionFile(O_WRONLY);
    590   if (fd < 0) {
    591     return;
    592   }
    593 
    594   snprintf(page_string, sizeof(page_string), "%d", page_number);
    595 
    596   DLOGI_IF(kTagDriverConfig, "page=%s", page_string);
    597 
    598   ssize_t err = Sys::pwrite_(fd, page_string, sizeof(page_string), 0);
    599   if (err <= 0) {
    600     DLOGE("Write to res_info failed (%s)", strerror(errno));
    601   }
    602 
    603   Sys::close_(fd);
    604 }
    605 
    606 // Reads the contents of res_info node into a buffer if the file is not empty
    607 bool HWHDMI::ReadResolutionFile(char *config_buffer) {
    608   ssize_t bytes_read = 0;
    609   int fd = OpenResolutionFile(O_RDONLY);
    610   if (fd >= 0) {
    611     bytes_read = Sys::pread_(fd, config_buffer, kPageSize, 0);
    612     Sys::close_(fd);
    613   }
    614 
    615   DLOGI_IF(kTagDriverConfig, "bytes_read = %d", bytes_read);
    616 
    617   return (bytes_read > 0);
    618 }
    619 
    620 // Populates the internal timing info structure with the timing info obtained
    621 // from the HDMI driver
    622 DisplayError HWHDMI::ReadTimingInfo() {
    623   uint32_t config_index = 0;
    624   uint32_t page_number = MSM_HDMI_INIT_RES_PAGE;
    625   uint32_t size = sizeof(msm_hdmi_mode_timing_info);
    626 
    627   while (true) {
    628     char config_buffer[kPageSize] = {0};
    629     msm_hdmi_mode_timing_info *info = reinterpret_cast<msm_hdmi_mode_timing_info *>(config_buffer);
    630     RequestNewPage(page_number);
    631 
    632     if (!ReadResolutionFile(config_buffer)) {
    633       break;
    634     }
    635 
    636     while (info->video_format && size < kPageSize && config_index < hdmi_modes_.size()) {
    637       supported_video_modes_[config_index] = *info;
    638       size += sizeof(msm_hdmi_mode_timing_info);
    639 
    640       DLOGI_IF(kTagDriverConfig, "Config=%d Mode %d: (%dx%d) @ %d, pixel formats %d",
    641                config_index,
    642                supported_video_modes_[config_index].video_format,
    643                supported_video_modes_[config_index].active_h,
    644                supported_video_modes_[config_index].active_v,
    645                supported_video_modes_[config_index].refresh_rate,
    646                supported_video_modes_[config_index].pixel_formats);
    647 
    648       info++;
    649       config_index++;
    650     }
    651 
    652     size = sizeof(msm_hdmi_mode_timing_info);
    653     // Request HDMI driver to populate res_info with more
    654     // timing information
    655     page_number++;
    656   }
    657 
    658   if (page_number == MSM_HDMI_INIT_RES_PAGE || config_index == 0) {
    659     DLOGE("No timing information found.");
    660     return kErrorHardware;
    661   }
    662 
    663   return kErrorNone;
    664 }
    665 
    666 bool HWHDMI::IsResolutionFilePresent() {
    667   bool is_file_present = false;
    668   int fd = OpenResolutionFile(O_RDONLY);
    669   if (fd >= 0) {
    670     is_file_present = true;
    671     Sys::close_(fd);
    672   }
    673 
    674   return is_file_present;
    675 }
    676 
    677 void HWHDMI::SetSourceProductInformation(const char *node, const char *name) {
    678   char property_value[kMaxStringLength];
    679   char sys_fs_path[kMaxStringLength];
    680   int hdmi_node_index = GetFBNodeIndex(kDeviceHDMI);
    681   if (hdmi_node_index < 0) {
    682     return;
    683   }
    684 
    685   ssize_t length = 0;
    686   bool prop_read_success = Debug::GetProperty(name, property_value);
    687   if (!prop_read_success) {
    688     return;
    689   }
    690 
    691   snprintf(sys_fs_path , sizeof(sys_fs_path), "%s%d/%s", fb_path_, hdmi_node_index, node);
    692   length = HWDevice::SysFsWrite(sys_fs_path, property_value,
    693                                 static_cast<ssize_t>(strlen(property_value)));
    694   if (length <= 0) {
    695     DLOGW("Failed to write %s = %s", node, property_value);
    696   }
    697 }
    698 
    699 DisplayError HWHDMI::GetDisplayS3DSupport(uint32_t index,
    700                                           HWDisplayAttributes *attrib) {
    701   ssize_t length = -1;
    702   char edid_s3d_str[kPageSize] = {'\0'};
    703   char edid_s3d_path[kMaxStringLength] = {'\0'};
    704   snprintf(edid_s3d_path, sizeof(edid_s3d_path), "%s%d/edid_3d_modes", fb_path_, fb_node_index_);
    705 
    706   if (index > hdmi_modes_.size()) {
    707     return kErrorNotSupported;
    708   }
    709 
    710   attrib->s3d_config[kS3DModeNone] = 1;
    711 
    712   // Three level inception!
    713   // The string looks like 16=SSH,4=FP:TAB:SSH,5=FP:SSH,32=FP:TAB:SSH
    714   // Initialize all the pointers to NULL to avoid crash in function strtok_r()
    715   char *saveptr_l1 = NULL, *saveptr_l2 = NULL, *saveptr_l3 = NULL;
    716   char *l1 = NULL, *l2 = NULL, *l3 = NULL;
    717 
    718   int edid_s3d_node = Sys::open_(edid_s3d_path, O_RDONLY);
    719   if (edid_s3d_node < 0) {
    720     DLOGW("%s could not be opened : %s", edid_s3d_path, strerror(errno));
    721     return kErrorNotSupported;
    722   }
    723 
    724   length = Sys::pread_(edid_s3d_node, edid_s3d_str, sizeof(edid_s3d_str)-1, 0);
    725   if (length <= 0) {
    726     Sys::close_(edid_s3d_node);
    727     return kErrorNotSupported;
    728   }
    729 
    730   l1 = strtok_r(edid_s3d_str, ",", &saveptr_l1);
    731   while (l1 != NULL) {
    732     l2 = strtok_r(l1, "=", &saveptr_l2);
    733     if (l2 != NULL) {
    734       if (hdmi_modes_[index] == (uint32_t)atoi(l2)) {
    735           l3 = strtok_r(saveptr_l2, ":", &saveptr_l3);
    736           while (l3 != NULL) {
    737             if (strncmp("SSH", l3, strlen("SSH")) == 0) {
    738               attrib->s3d_config[kS3DModeLR] = 1;
    739               attrib->s3d_config[kS3DModeRL] = 1;
    740             } else if (strncmp("TAB", l3, strlen("TAB")) == 0) {
    741               attrib->s3d_config[kS3DModeTB] = 1;
    742             } else if (strncmp("FP", l3, strlen("FP")) == 0) {
    743               attrib->s3d_config[kS3DModeFP] = 1;
    744             }
    745             l3 = strtok_r(NULL, ":", &saveptr_l3);
    746           }
    747       }
    748     }
    749     l1 = strtok_r(NULL, ",", &saveptr_l1);
    750   }
    751 
    752   Sys::close_(edid_s3d_node);
    753   return kErrorNone;
    754 }
    755 
    756 bool HWHDMI::IsSupportedS3DMode(HWS3DMode s3d_mode) {
    757   for (uint32_t i = 0; i < supported_s3d_modes_.size(); i++) {
    758     if (supported_s3d_modes_[i] == s3d_mode) {
    759       return true;
    760     }
    761   }
    762   return false;
    763 }
    764 
    765 DisplayError HWHDMI::SetS3DMode(HWS3DMode s3d_mode) {
    766   if (!IsSupportedS3DMode(s3d_mode)) {
    767     DLOGW("S3D mode is not supported s3d_mode = %d", s3d_mode);
    768     return kErrorNotSupported;
    769   }
    770 
    771   std::map<HWS3DMode, msm_hdmi_s3d_mode>::iterator it = s3d_mode_sdm_to_mdp_.find(s3d_mode);
    772   if (it == s3d_mode_sdm_to_mdp_.end()) {
    773     return kErrorNotSupported;
    774   }
    775   msm_hdmi_s3d_mode s3d_mdp_mode = it->second;
    776 
    777   if (active_mdp_s3d_mode_ == s3d_mdp_mode) {
    778     // HDMI_S3D_SIDE_BY_SIDE is an mdp mapping for kS3DModeLR and kS3DModeRL s3d modes. So no need
    779     // to update the s3d_mode node. hw_panel_info needs to be updated to differentiate these two s3d
    780     // modes in strategy
    781     hw_panel_info_.s3d_mode = s3d_mode;
    782     return kErrorNone;
    783   }
    784 
    785   ssize_t length = -1;
    786   char s3d_mode_path[kMaxStringLength] = {'\0'};
    787   char s3d_mode_string[kMaxStringLength] = {'\0'};
    788   snprintf(s3d_mode_path, sizeof(s3d_mode_path), "%s%d/s3d_mode", fb_path_, fb_node_index_);
    789 
    790   int s3d_mode_node = Sys::open_(s3d_mode_path, O_RDWR);
    791   if (s3d_mode_node < 0) {
    792     DLOGW("%s could not be opened : %s", s3d_mode_path, strerror(errno));
    793     return kErrorNotSupported;
    794   }
    795 
    796   snprintf(s3d_mode_string, sizeof(s3d_mode_string), "%d", s3d_mdp_mode);
    797   length = Sys::pwrite_(s3d_mode_node, s3d_mode_string, sizeof(s3d_mode_string), 0);
    798   if (length <= 0) {
    799     DLOGW("Failed to write into s3d node: %s", strerror(errno));
    800     Sys::close_(s3d_mode_node);
    801     return kErrorNotSupported;
    802   }
    803 
    804   active_mdp_s3d_mode_ = s3d_mdp_mode;
    805   hw_panel_info_.s3d_mode = s3d_mode;
    806   Sys::close_(s3d_mode_node);
    807 
    808   DLOGI_IF(kTagDriverConfig, "Set s3d mode %d", hw_panel_info_.s3d_mode);
    809   return kErrorNone;
    810 }
    811 
    812 DisplayError HWHDMI::GetPanelS3DMode() {
    813   ssize_t length = -1;
    814   char s3d_mode_path[kMaxStringLength] = {'\0'};
    815   char s3d_mode_string[kMaxStringLength] = {'\0'};
    816   snprintf(s3d_mode_path, sizeof(s3d_mode_path), "%s%d/s3d_mode", fb_path_, fb_node_index_);
    817   int panel_s3d_mode = 0;
    818 
    819   int s3d_mode_node = Sys::open_(s3d_mode_path, O_RDWR);
    820   if (s3d_mode_node < 0) {
    821     DLOGE("%s could not be opened : %s", s3d_mode_path, strerror(errno));
    822     return kErrorNotSupported;
    823   }
    824 
    825   length = Sys::pread_(s3d_mode_node, s3d_mode_string, sizeof(s3d_mode_string), 0);
    826   if (length <= 0) {
    827     DLOGE("Failed read s3d node: %s", strerror(errno));
    828     Sys::close_(s3d_mode_node);
    829     return kErrorNotSupported;
    830   }
    831 
    832   panel_s3d_mode = atoi(s3d_mode_string);
    833   if (panel_s3d_mode < HDMI_S3D_NONE || panel_s3d_mode >= HDMI_S3D_MAX) {
    834     Sys::close_(s3d_mode_node);
    835     DLOGW("HDMI panel S3D mode is not supported panel_s3d_mode = %d", panel_s3d_mode);
    836     return kErrorUndefined;
    837   }
    838 
    839   active_mdp_s3d_mode_  = static_cast<msm_hdmi_s3d_mode>(panel_s3d_mode);
    840   Sys::close_(s3d_mode_node);
    841 
    842   DLOGI_IF(kTagDriverConfig, "Get HDMI panel s3d mode %d", active_mdp_s3d_mode_);
    843   return kErrorNone;
    844 }
    845 
    846 DisplayError HWHDMI::GetDynamicFrameRateMode(uint32_t refresh_rate, uint32_t *mode,
    847                                              DynamicFPSData *data, uint32_t *config_index) {
    848   msm_hdmi_mode_timing_info *cur = NULL;
    849   msm_hdmi_mode_timing_info *dst = NULL;
    850   uint32_t i = 0;
    851   int pre_refresh_rate_diff = 0;
    852   bool pre_unstd_mode = false;
    853 
    854   for (i = 0; i < hdmi_modes_.size(); i++) {
    855     msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[i];
    856     if (timing_mode->video_format == hdmi_modes_[active_config_index_]) {
    857       cur = timing_mode;
    858       break;
    859     }
    860   }
    861 
    862   if (cur == NULL) {
    863     DLOGE("can't find timing info for active config index(%d)", active_config_index_);
    864     return kErrorUndefined;
    865   }
    866 
    867   if (cur->refresh_rate != frame_rate_) {
    868     pre_unstd_mode = true;
    869   }
    870 
    871   if (i >= hdmi_modes_.size()) {
    872     return kErrorNotSupported;
    873   }
    874 
    875   dst = cur;
    876   pre_refresh_rate_diff = static_cast<int>(dst->refresh_rate) - static_cast<int>(refresh_rate);
    877 
    878   for (i = 0; i < hdmi_modes_.size(); i++) {
    879     msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[i];
    880     if (cur->active_h == timing_mode->active_h &&
    881        cur->active_v == timing_mode->active_v &&
    882        cur->pixel_formats == timing_mode->pixel_formats ) {
    883       int cur_refresh_rate_diff = static_cast<int>(timing_mode->refresh_rate) -
    884                                   static_cast<int>(refresh_rate);
    885       if (abs(pre_refresh_rate_diff) > abs(cur_refresh_rate_diff)) {
    886         pre_refresh_rate_diff = cur_refresh_rate_diff;
    887         dst = timing_mode;
    888       }
    889     }
    890   }
    891 
    892   if (pre_refresh_rate_diff > kThresholdRefreshRate) {
    893     return kErrorNotSupported;
    894   }
    895 
    896   GetConfigIndex(dst->video_format, config_index);
    897 
    898   data->hor_front_porch = dst->front_porch_h;
    899   data->hor_back_porch = dst->back_porch_h;
    900   data->hor_pulse_width = dst->pulse_width_h;
    901   data->clk_rate_hz = dst->pixel_freq;
    902   data->fps = refresh_rate;
    903 
    904   if (dst->front_porch_h != cur->front_porch_h) {
    905     *mode = kModeHFP;
    906   }
    907 
    908   if (dst->refresh_rate != refresh_rate || dst->pixel_freq != cur->pixel_freq) {
    909     if (*mode == kModeHFP) {
    910       if (dst->refresh_rate != refresh_rate) {
    911         *mode = kModeHFPCalcClock;
    912       } else {
    913         *mode = kModeClockHFP;
    914       }
    915     } else {
    916         *mode = kModeClock;
    917     }
    918   }
    919 
    920   if (pre_unstd_mode && (*mode == kModeHFP)) {
    921     *mode = kModeClockHFP;
    922   }
    923 
    924   return kErrorNone;
    925 }
    926 
    927 DisplayError HWHDMI::SetRefreshRate(uint32_t refresh_rate) {
    928   char mode_path[kMaxStringLength] = {0};
    929   char node_path[kMaxStringLength] = {0};
    930   uint32_t mode = kModeClock;
    931   uint32_t config_index = 0;
    932   DynamicFPSData data;
    933   DisplayError error = kErrorNone;
    934 
    935   if (refresh_rate == frame_rate_) {
    936     return error;
    937   }
    938 
    939   error = GetDynamicFrameRateMode(refresh_rate, &mode, &data, &config_index);
    940   if (error != kErrorNone) {
    941     return error;
    942   }
    943 
    944   snprintf(mode_path, sizeof(mode_path), "%s%d/msm_fb_dfps_mode", fb_path_, fb_node_index_);
    945   snprintf(node_path, sizeof(node_path), "%s%d/dynamic_fps", fb_path_, fb_node_index_);
    946 
    947   int fd_mode = Sys::open_(mode_path, O_WRONLY);
    948   if (fd_mode < 0) {
    949     DLOGE("Failed to open %s with error %s", mode_path, strerror(errno));
    950     return kErrorFileDescriptor;
    951   }
    952 
    953   char dfps_mode[kMaxStringLength];
    954   snprintf(dfps_mode, sizeof(dfps_mode), "%d", mode);
    955   DLOGI_IF(kTagDriverConfig, "Setting dfps_mode  = %d", mode);
    956   ssize_t len = Sys::pwrite_(fd_mode, dfps_mode, strlen(dfps_mode), 0);
    957   if (len < 0) {
    958     DLOGE("Failed to enable dfps mode %d with error %s", mode, strerror(errno));
    959     Sys::close_(fd_mode);
    960     return kErrorUndefined;
    961   }
    962   Sys::close_(fd_mode);
    963 
    964   int fd_node = Sys::open_(node_path, O_WRONLY);
    965   if (fd_node < 0) {
    966     DLOGE("Failed to open %s with error %s", node_path, strerror(errno));
    967     return kErrorFileDescriptor;
    968   }
    969 
    970   char refresh_rate_string[kMaxStringLength];
    971   if (mode == kModeHFP || mode == kModeClock) {
    972     snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", data.fps);
    973     DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", data.fps);
    974   } else {
    975     snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d %d %d %d %d",
    976              data.hor_front_porch, data.hor_back_porch, data.hor_pulse_width,
    977              data.clk_rate_hz, data.fps);
    978   }
    979   len = Sys::pwrite_(fd_node, refresh_rate_string, strlen(refresh_rate_string), 0);
    980   if (len < 0) {
    981     DLOGE("Failed to write %d with error %s", refresh_rate, strerror(errno));
    982     Sys::close_(fd_node);
    983     return kErrorUndefined;
    984   }
    985   Sys::close_(fd_node);
    986 
    987   error = ReadTimingInfo();
    988   if (error != kErrorNone) {
    989     return error;
    990   }
    991 
    992   GetDisplayAttributes(config_index, &display_attributes_);
    993   UpdateMixerAttributes();
    994 
    995   frame_rate_ = refresh_rate;
    996   active_config_index_ = config_index;
    997 
    998   DLOGI_IF(kTagDriverConfig, "config_index(%d) Mode(%d) frame_rate(%d)",
    999            config_index,
   1000            mode,
   1001            frame_rate_);
   1002 
   1003   return kErrorNone;
   1004 }
   1005 
   1006 void HWHDMI::UpdateMixerAttributes() {
   1007   mixer_attributes_.width = display_attributes_.x_pixels;
   1008   mixer_attributes_.height = display_attributes_.y_pixels;
   1009   mixer_attributes_.split_left = display_attributes_.is_device_split ?
   1010       (display_attributes_.x_pixels / 2) : mixer_attributes_.width;
   1011 }
   1012 
   1013 DisplayError HWHDMI::UpdateHDRMetaData(HWLayers *hw_layers) {
   1014   if (!hw_panel_info_.hdr_enabled) {
   1015     return kErrorNone;
   1016   }
   1017 
   1018   DisplayError error = kErrorNone;
   1019 
   1020 #ifdef MDP_HDR_STREAM
   1021   const HWHDRLayerInfo &hdr_layer_info = hw_layers->info.hdr_layer_info;
   1022   char hdr_stream_path[kMaxStringLength] = {};
   1023   snprintf(hdr_stream_path, sizeof(hdr_stream_path), "%s%d/hdr_stream", fb_path_, fb_node_index_);
   1024 
   1025   Layer hdr_layer = {};
   1026   if (hdr_layer_info.operation == HWHDRLayerInfo::kSet && hdr_layer_info.layer_index > -1) {
   1027     hdr_layer = *(hw_layers->info.stack->layers.at(UINT32(hdr_layer_info.layer_index)));
   1028   }
   1029 
   1030   const LayerBuffer *layer_buffer = &hdr_layer.input_buffer;
   1031   const MasteringDisplay &mastering_display = layer_buffer->color_metadata.masteringDisplayInfo;
   1032   const ContentLightLevel &light_level = layer_buffer->color_metadata.contentLightLevel;
   1033   const Primaries &primaries = mastering_display.primaries;
   1034 
   1035   mdp_hdr_stream_ctrl hdr_ctrl = {};
   1036   if (hdr_layer_info.operation == HWHDRLayerInfo::kSet) {
   1037     int32_t eotf = GetEOTF(layer_buffer->color_metadata.transfer);
   1038     hdr_ctrl.hdr_stream.eotf = (eotf < 0) ? 0 : UINT32(eotf);
   1039     hdr_ctrl.hdr_stream.white_point_x = primaries.whitePoint[0];
   1040     hdr_ctrl.hdr_stream.white_point_y = primaries.whitePoint[1];
   1041     hdr_ctrl.hdr_stream.display_primaries_x[0] = primaries.rgbPrimaries[0][0];
   1042     hdr_ctrl.hdr_stream.display_primaries_y[0] = primaries.rgbPrimaries[0][1];
   1043     hdr_ctrl.hdr_stream.display_primaries_x[1] = primaries.rgbPrimaries[1][0];
   1044     hdr_ctrl.hdr_stream.display_primaries_y[1] = primaries.rgbPrimaries[1][1];
   1045     hdr_ctrl.hdr_stream.display_primaries_x[2] = primaries.rgbPrimaries[2][0];
   1046     hdr_ctrl.hdr_stream.display_primaries_y[2] = primaries.rgbPrimaries[2][1];
   1047     hdr_ctrl.hdr_stream.min_luminance = mastering_display.minDisplayLuminance;
   1048     hdr_ctrl.hdr_stream.max_luminance = mastering_display.maxDisplayLuminance/10000;
   1049     hdr_ctrl.hdr_stream.max_content_light_level = light_level.maxContentLightLevel;
   1050     hdr_ctrl.hdr_stream.max_average_light_level = light_level.minPicAverageLightLevel;
   1051     hdr_ctrl.hdr_state = HDR_ENABLE;
   1052     reset_hdr_flag_ = false;
   1053 #ifdef MDP_COMMIT_UPDATE_CDM_COLOR_SPACE
   1054     HWDevice::SetCSC(layer_buffer->color_metadata, &cdm_color_space_);
   1055     cdm_color_space_commit_ = true;
   1056 #endif
   1057     // DP related
   1058     int32_t pixel_encoding = GetPixelEncoding(hdr_layer.input_buffer);
   1059     hdr_ctrl.hdr_stream.pixel_encoding = (pixel_encoding < 0) ? 0 : UINT32(pixel_encoding);
   1060     int32_t colorimetry = GetColoriMetry(hdr_layer.input_buffer);
   1061     hdr_ctrl.hdr_stream.colorimetry = (colorimetry < 0) ? 0 : UINT32(colorimetry);
   1062     hdr_ctrl.hdr_stream.range = GetRange(hdr_layer.input_buffer.color_metadata.range);
   1063     int32_t bits_per_component = GetBitsPerComponent(hdr_layer.input_buffer);
   1064     hdr_ctrl.hdr_stream.bits_per_component =
   1065                            (bits_per_component  < 0) ? 0 : UINT32(bits_per_component);
   1066     hdr_ctrl.hdr_stream.content_type = GetContentType(hdr_layer.input_buffer);
   1067 
   1068     DLOGD_IF(kTagDriverConfig, "kSet: HDR Stream : MaxDisplayLuminance = %d\n"
   1069       "MinDisplayLuminance = %d MaxContentLightLevel = %d MaxAverageLightLevel = %d\n"
   1070       "Red_x = %d Red_y = %d Green_x = %d Green_y = %d Blue_x = %d Blue_y = %d\n"
   1071       "WhitePoint_x = %d WhitePoint_y = %d EOTF = %d PixelEncoding = %d Colorimetry = %d\n"
   1072       "Range = %d BPC = %d ContentType = %d hdr_state = %d",
   1073       hdr_ctrl.hdr_stream.max_luminance, hdr_ctrl.hdr_stream.min_luminance,
   1074       hdr_ctrl.hdr_stream.max_content_light_level, hdr_ctrl.hdr_stream.max_average_light_level,
   1075       hdr_ctrl.hdr_stream.display_primaries_x[0], hdr_ctrl.hdr_stream.display_primaries_y[0],
   1076       hdr_ctrl.hdr_stream.display_primaries_x[1], hdr_ctrl.hdr_stream.display_primaries_y[1],
   1077       hdr_ctrl.hdr_stream.display_primaries_x[2], hdr_ctrl.hdr_stream.display_primaries_y[2],
   1078       hdr_ctrl.hdr_stream.white_point_x, hdr_ctrl.hdr_stream.white_point_x,
   1079       hdr_ctrl.hdr_stream.eotf, hdr_ctrl.hdr_stream.pixel_encoding,
   1080       hdr_ctrl.hdr_stream.colorimetry, hdr_ctrl.hdr_stream.range,
   1081       hdr_ctrl.hdr_stream.bits_per_component, hdr_ctrl.hdr_stream.content_type,
   1082       hdr_ctrl.hdr_state);
   1083   } else if (hdr_layer_info.operation == HWHDRLayerInfo::kReset) {
   1084     memset(&hdr_ctrl.hdr_stream, 0, sizeof(hdr_ctrl.hdr_stream));
   1085     hdr_ctrl.hdr_state = HDR_RESET;
   1086     reset_hdr_flag_ = true;
   1087     hdr_reset_start_ = time(NULL);
   1088 #ifdef MDP_COMMIT_UPDATE_CDM_COLOR_SPACE
   1089     cdm_color_space_ = (mdp_color_space) MDP_CSC_DEFAULT;
   1090     cdm_color_space_commit_ = true;
   1091 #endif
   1092     DLOGD_IF(kTagDriverConfig, "kReset: HDR Stream: HDR_RESET");
   1093   } else if (hdr_layer_info.operation == HWHDRLayerInfo::kNoOp) {
   1094      if (reset_hdr_flag_) {
   1095        hdr_reset_end_ = time(NULL);
   1096 
   1097        if ((hdr_reset_end_ - hdr_reset_start_) >= MIN_HDR_RESET_WAITTIME_SEC) {
   1098           reset_hdr_flag_ = false;
   1099           memset(&hdr_ctrl.hdr_stream, 0, sizeof(hdr_ctrl.hdr_stream));
   1100           hdr_ctrl.hdr_state = HDR_DISABLE;
   1101           DLOGD_IF(kTagDriverConfig, "kNoOp: HDR Stream: HDR_DISABLE");
   1102        } else {
   1103           return kErrorNone;
   1104        }
   1105      } else {
   1106         return kErrorNone;
   1107      }
   1108   }
   1109 
   1110   int fd = Sys::open_(hdr_stream_path, O_WRONLY);
   1111   if (fd < 0) {
   1112     DLOGE("Failed to open %s with error %s", hdr_stream_path, strerror(errno));
   1113     return kErrorFileDescriptor;
   1114   }
   1115 
   1116   const void *hdr_metadata = reinterpret_cast<const void*>(&hdr_ctrl);
   1117   ssize_t len = Sys::pwrite_(fd, hdr_metadata, sizeof(hdr_ctrl), 0);
   1118   if (len <= 0) {
   1119     DLOGE("Failed to write hdr_metadata");
   1120     error = kErrorUndefined;
   1121   }
   1122   Sys::close_(fd);
   1123 #endif
   1124 
   1125   return error;
   1126 }
   1127 
   1128 }  // namespace sdm
   1129 
   1130