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