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