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