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 <pthread.h> 34 #include <fcntl.h> 35 #include <sys/prctl.h> 36 #include <sys/ioctl.h> 37 #include <sys/time.h> 38 #include <sys/resource.h> 39 #include <utils/debug.h> 40 #include <utils/sys.h> 41 #include <core/display_interface.h> 42 #include <linux/msm_mdp_ext.h> 43 #include <utils/rect.h> 44 45 #include <string> 46 47 #include "hw_primary.h" 48 #include "hw_color_manager.h" 49 50 #define __CLASS__ "HWPrimary" 51 52 #ifndef MDP_COMMIT_CWB_EN 53 #define MDP_COMMIT_CWB_EN 0x800 54 #endif 55 56 #ifndef MDP_COMMIT_CWB_DSPP 57 #define MDP_COMMIT_CWB_DSPP 0x1000 58 #endif 59 60 #ifndef MDP_COMMIT_AVR_EN 61 #define MDP_COMMIT_AVR_EN 0x08 62 #endif 63 64 #ifndef MDP_COMMIT_AVR_ONE_SHOT_MODE 65 #define MDP_COMMIT_AVR_ONE_SHOT_MODE 0x10 66 #endif 67 68 #ifndef MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI 69 #define MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI 0x20 70 #endif 71 72 namespace sdm { 73 74 using std::string; 75 using std::to_string; 76 using std::fstream; 77 78 HWPrimary::HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf) 79 : HWDevice(buffer_sync_handler) { 80 HWDevice::device_type_ = kDevicePrimary; 81 HWDevice::device_name_ = "Primary Display Device"; 82 HWDevice::hw_info_intf_ = hw_info_intf; 83 } 84 85 DisplayError HWPrimary::Init() { 86 DisplayError error = kErrorNone; 87 88 error = HWDevice::Init(); 89 if (error != kErrorNone) { 90 return error; 91 } 92 93 mdp_dest_scalar_data_.resize(hw_resource_.hw_dest_scalar_info.count); 94 95 error = PopulateDisplayAttributes(); 96 if (error != kErrorNone) { 97 return error; 98 } 99 100 UpdateMixerAttributes(); 101 102 // Need to enable HPD, but toggle at start when HDMI is external 103 // This helps for framework reboot or adb shell stop/start 104 EnableHotPlugDetection(0); 105 EnableHotPlugDetection(1); 106 InitializeConfigs(); 107 108 avr_prop_disabled_ = Debug::IsAVRDisabled(); 109 110 return error; 111 } 112 113 bool HWPrimary::GetCurrentModeFromSysfs(size_t *curr_x_pixels, size_t *curr_y_pixels) { 114 bool ret = false; 115 string mode_path = fb_path_ + string("0/mode"); 116 117 Sys::fstream fs(mode_path, fstream::in); 118 if (!fs.is_open()) { 119 return false; 120 } 121 122 string line; 123 if (Sys::getline_(fs, line)) { 124 // String is of form "U:1600x2560p-0". Documentation/fb/modedb.txt in 125 // kernel has more info on the format. 126 size_t xpos = line.find(':'); 127 size_t ypos = line.find('x'); 128 129 if (xpos == string::npos || ypos == string::npos) { 130 DLOGI("Resolution switch not supported"); 131 } else { 132 *curr_x_pixels = static_cast<size_t>(atoi(line.c_str() + xpos + 1)); 133 *curr_y_pixels = static_cast<size_t>(atoi(line.c_str() + ypos + 1)); 134 DLOGI("Current Config: %u x %u", *curr_x_pixels, *curr_y_pixels); 135 ret = true; 136 } 137 } 138 139 return ret; 140 } 141 142 void HWPrimary::InitializeConfigs() { 143 size_t curr_x_pixels = 0; 144 size_t curr_y_pixels = 0; 145 146 if (!GetCurrentModeFromSysfs(&curr_x_pixels, &curr_y_pixels)) { 147 return; 148 } 149 150 string modes_path = string(fb_path_) + string("0/modes"); 151 152 Sys::fstream fs(modes_path, fstream::in); 153 if (!fs.is_open()) { 154 DLOGI("Unable to process modes"); 155 return; 156 } 157 158 string line; 159 while (Sys::getline_(fs, line)) { 160 DisplayConfigVariableInfo config; 161 // std::getline (unlike ::getline) removes \n while driver expects it in mode, so add back 162 line += '\n'; 163 size_t xpos = line.find(':'); 164 size_t ypos = line.find('x'); 165 166 if (xpos == string::npos || ypos == string::npos) { 167 continue; 168 } 169 170 config.x_pixels = UINT32(atoi(line.c_str() + xpos + 1)); 171 config.y_pixels = UINT32(atoi(line.c_str() + ypos + 1)); 172 DLOGI("Found mode %d x %d", config.x_pixels, config.y_pixels); 173 display_configs_.push_back(config); 174 display_config_strings_.push_back(string(line.c_str())); 175 176 if (curr_x_pixels == config.x_pixels && curr_y_pixels == config.y_pixels) { 177 active_config_index_ = UINT32(display_configs_.size() - 1); 178 DLOGI("Active config index %u", active_config_index_); 179 } 180 } 181 } 182 183 DisplayError HWPrimary::GetNumDisplayAttributes(uint32_t *count) { 184 *count = IsResolutionSwitchEnabled() ? UINT32(display_configs_.size()) : 1; 185 return kErrorNone; 186 } 187 188 DisplayError HWPrimary::GetActiveConfig(uint32_t *active_config_index) { 189 *active_config_index = active_config_index_; 190 return kErrorNone; 191 } 192 193 DisplayError HWPrimary::GetDisplayAttributes(uint32_t index, 194 HWDisplayAttributes *display_attributes) { 195 if (!display_attributes) { 196 return kErrorParameters; 197 } 198 199 if (IsResolutionSwitchEnabled() && index >= display_configs_.size()) { 200 return kErrorParameters; 201 } 202 203 *display_attributes = display_attributes_; 204 if (IsResolutionSwitchEnabled()) { 205 // Overwrite only the parent portion of object 206 display_attributes->x_pixels = display_configs_.at(index).x_pixels; 207 display_attributes->y_pixels = display_configs_.at(index).y_pixels; 208 } 209 210 return kErrorNone; 211 } 212 213 DisplayError HWPrimary::PopulateDisplayAttributes() { 214 DTRACE_SCOPED(); 215 216 // Variable screen info 217 fb_var_screeninfo var_screeninfo = {}; 218 219 if (Sys::ioctl_(device_fd_, FBIOGET_VSCREENINFO, &var_screeninfo) < 0) { 220 IOCTL_LOGE(FBIOGET_VSCREENINFO, device_type_); 221 return kErrorHardware; 222 } 223 224 // Frame rate 225 msmfb_metadata meta_data = {}; 226 meta_data.op = metadata_op_frame_rate; 227 if (Sys::ioctl_(device_fd_, MSMFB_METADATA_GET, &meta_data) < 0) { 228 IOCTL_LOGE(MSMFB_METADATA_GET, device_type_); 229 return kErrorHardware; 230 } 231 232 // If driver doesn't return width/height information, default to 320 dpi 233 if (INT(var_screeninfo.width) <= 0 || INT(var_screeninfo.height) <= 0) { 234 var_screeninfo.width = UINT32(((FLOAT(var_screeninfo.xres) * 25.4f)/320.0f) + 0.5f); 235 var_screeninfo.height = UINT32(((FLOAT(var_screeninfo.yres) * 25.4f)/320.0f) + 0.5f); 236 DLOGW("Driver doesn't report panel physical width and height - defaulting to 320dpi"); 237 } 238 239 display_attributes_.x_pixels = var_screeninfo.xres; 240 display_attributes_.y_pixels = var_screeninfo.yres; 241 display_attributes_.v_front_porch = var_screeninfo.lower_margin; 242 display_attributes_.v_back_porch = var_screeninfo.upper_margin; 243 display_attributes_.v_pulse_width = var_screeninfo.vsync_len; 244 uint32_t h_blanking = var_screeninfo.right_margin + var_screeninfo.left_margin + 245 var_screeninfo.hsync_len; 246 display_attributes_.h_total = var_screeninfo.xres + h_blanking; 247 display_attributes_.x_dpi = 248 (FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width); 249 display_attributes_.y_dpi = 250 (FLOAT(var_screeninfo.yres) * 25.4f) / FLOAT(var_screeninfo.height); 251 display_attributes_.fps = meta_data.data.panel_frame_rate; 252 display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps); 253 display_attributes_.is_device_split = (hw_panel_info_.split_info.right_split || 254 (var_screeninfo.xres > hw_resource_.max_mixer_width)); 255 display_attributes_.h_total += (display_attributes_.is_device_split || 256 hw_panel_info_.ping_pong_split)? h_blanking : 0; 257 258 return kErrorNone; 259 } 260 261 DisplayError HWPrimary::SetDisplayAttributes(uint32_t index) { 262 DisplayError ret = kErrorNone; 263 264 if (!IsResolutionSwitchEnabled()) { 265 return kErrorNotSupported; 266 } 267 268 if (index >= display_configs_.size()) { 269 return kErrorParameters; 270 } 271 272 string mode_path = string(fb_path_) + string("0/mode"); 273 int fd = Sys::open_(mode_path.c_str(), O_WRONLY); 274 275 if (fd < 0) { 276 DLOGE("Opening mode failed"); 277 return kErrorNotSupported; 278 } 279 280 ssize_t written = Sys::pwrite_(fd, display_config_strings_.at(index).c_str(), 281 display_config_strings_.at(index).length(), 0); 282 if (written > 0) { 283 DLOGI("Successfully set config %u", index); 284 PopulateHWPanelInfo(); 285 PopulateDisplayAttributes(); 286 UpdateMixerAttributes(); 287 active_config_index_ = index; 288 } else { 289 DLOGE("Writing config index %u failed with error: %s", index, strerror(errno)); 290 ret = kErrorParameters; 291 } 292 293 Sys::close_(fd); 294 295 return ret; 296 } 297 298 DisplayError HWPrimary::SetRefreshRate(uint32_t refresh_rate) { 299 char node_path[kMaxStringLength] = {0}; 300 301 if (hw_resource_.has_avr && !avr_prop_disabled_) { 302 return kErrorNotSupported; 303 } 304 305 snprintf(node_path, sizeof(node_path), "%s%d/dynamic_fps", fb_path_, fb_node_index_); 306 307 int fd = Sys::open_(node_path, O_WRONLY); 308 if (fd < 0) { 309 DLOGE("Failed to open %s with error %s", node_path, strerror(errno)); 310 return kErrorFileDescriptor; 311 } 312 313 char refresh_rate_string[kMaxStringLength]; 314 snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", refresh_rate); 315 DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", refresh_rate); 316 ssize_t len = Sys::pwrite_(fd, refresh_rate_string, strlen(refresh_rate_string), 0); 317 if (len < 0) { 318 DLOGE("Failed to write %d with error %s", refresh_rate, strerror(errno)); 319 Sys::close_(fd); 320 return kErrorUndefined; 321 } 322 Sys::close_(fd); 323 324 DisplayError error = PopulateDisplayAttributes(); 325 if (error != kErrorNone) { 326 return error; 327 } 328 329 return kErrorNone; 330 } 331 332 DisplayError HWPrimary::GetConfigIndex(uint32_t mode, uint32_t *index) { 333 return HWDevice::GetConfigIndex(mode, index); 334 } 335 336 DisplayError HWPrimary::PowerOff() { 337 if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) { 338 IOCTL_LOGE(FB_BLANK_POWERDOWN, device_type_); 339 return kErrorHardware; 340 } 341 342 auto_refresh_ = false; 343 344 return kErrorNone; 345 } 346 347 DisplayError HWPrimary::Doze() { 348 if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_NORMAL) < 0) { 349 IOCTL_LOGE(FB_BLANK_NORMAL, device_type_); 350 return kErrorHardware; 351 } 352 353 return kErrorNone; 354 } 355 356 DisplayError HWPrimary::DozeSuspend() { 357 if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_VSYNC_SUSPEND) < 0) { 358 IOCTL_LOGE(FB_BLANK_VSYNC_SUSPEND, device_type_); 359 return kErrorHardware; 360 } 361 362 return kErrorNone; 363 } 364 365 DisplayError HWPrimary::Validate(HWLayers *hw_layers) { 366 HWLayersInfo &hw_layer_info = hw_layers->info; 367 LayerStack *stack = hw_layer_info.stack; 368 369 HWDevice::ResetDisplayParams(); 370 371 mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1; 372 373 LayerRect left_roi = hw_layer_info.left_frame_roi.at(0); 374 LayerRect right_roi = hw_layer_info.right_frame_roi.at(0); 375 376 mdp_commit.left_roi.x = UINT32(left_roi.left); 377 mdp_commit.left_roi.y = UINT32(left_roi.top); 378 mdp_commit.left_roi.w = UINT32(left_roi.right - left_roi.left); 379 mdp_commit.left_roi.h = UINT32(left_roi.bottom - left_roi.top); 380 381 // Update second roi information in right_roi 382 if (hw_layer_info.left_frame_roi.size() == 2) { 383 mdp_commit.flags |= MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI; 384 right_roi = hw_layer_info.left_frame_roi.at(1); 385 } 386 387 // SDM treats ROI as one full coordinate system. 388 // In case source split is disabled, However, Driver assumes Mixer to operate in 389 // different co-ordinate system. 390 if (IsValid(right_roi)) { 391 mdp_commit.right_roi.x = UINT32(right_roi.left); 392 if (!hw_resource_.is_src_split) { 393 mdp_commit.right_roi.x = UINT32(right_roi.left) - mixer_attributes_.split_left; 394 } 395 mdp_commit.right_roi.y = UINT32(right_roi.top); 396 mdp_commit.right_roi.w = UINT32(right_roi.right - right_roi.left); 397 mdp_commit.right_roi.h = UINT32(right_roi.bottom - right_roi.top); 398 } 399 400 if (stack->output_buffer && hw_resource_.has_concurrent_writeback) { 401 LayerBuffer *output_buffer = stack->output_buffer; 402 mdp_out_layer_.writeback_ndx = hw_resource_.writeback_index; 403 mdp_out_layer_.buffer.width = output_buffer->unaligned_width; 404 mdp_out_layer_.buffer.height = output_buffer->unaligned_height; 405 mdp_out_layer_.buffer.comp_ratio.denom = 1000; 406 mdp_out_layer_.buffer.comp_ratio.numer = UINT32(hw_layers->output_compression * 1000); 407 mdp_out_layer_.buffer.fence = -1; 408 #ifdef OUT_LAYER_COLOR_SPACE 409 SetCSC(output_buffer->color_metadata, &mdp_out_layer_.color_space); 410 #endif 411 SetFormat(output_buffer->format, &mdp_out_layer_.buffer.format); 412 mdp_commit.flags |= MDP_COMMIT_CWB_EN; 413 mdp_commit.flags |= (stack->flags.post_processed_output) ? MDP_COMMIT_CWB_DSPP : 0; 414 DLOGI_IF(kTagDriverConfig, "****************** Conc WB Output buffer Info ******************"); 415 DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d DSPP output %d", 416 mdp_out_layer_.buffer.width, mdp_out_layer_.buffer.height, 417 mdp_out_layer_.buffer.format, mdp_out_layer_.writeback_ndx, 418 stack->flags.post_processed_output); 419 DLOGI_IF(kTagDriverConfig, "****************************************************************"); 420 } 421 422 if (hw_resource_.has_avr) { 423 SetAVRFlags(hw_layers->hw_avr_info, &mdp_commit.flags); 424 } 425 426 return HWDevice::Validate(hw_layers); 427 } 428 429 DisplayError HWPrimary::Commit(HWLayers *hw_layers) { 430 LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer; 431 432 if (hw_resource_.has_concurrent_writeback && output_buffer) { 433 if (output_buffer->planes[0].fd >= 0) { 434 mdp_out_layer_.buffer.planes[0].fd = output_buffer->planes[0].fd; 435 mdp_out_layer_.buffer.planes[0].offset = output_buffer->planes[0].offset; 436 SetStride(device_type_, output_buffer->format, output_buffer->planes[0].stride, 437 &mdp_out_layer_.buffer.planes[0].stride); 438 mdp_out_layer_.buffer.plane_count = 1; 439 mdp_out_layer_.buffer.fence = -1; 440 441 DLOGI_IF(kTagDriverConfig, "****************** Conc WB Output buffer Info ****************"); 442 DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d", 443 mdp_out_layer_.buffer.planes[0].fd, mdp_out_layer_.buffer.planes[0].offset, 444 mdp_out_layer_.buffer.planes[0].stride); 445 DLOGI_IF(kTagDriverConfig, "**************************************************************"); 446 } else { 447 DLOGE("Invalid output buffer fd"); 448 return kErrorParameters; 449 } 450 } 451 452 DisplayError ret = HWDevice::Commit(hw_layers); 453 454 if (ret == kErrorNone && hw_resource_.has_concurrent_writeback && output_buffer) { 455 output_buffer->release_fence_fd = mdp_out_layer_.buffer.fence; 456 } 457 458 return ret; 459 } 460 461 void HWPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) { 462 char node_path[kMaxStringLength] = {0}; 463 464 DLOGI_IF(kTagDriverConfig, "Setting idle timeout to = %d ms", timeout_ms); 465 466 snprintf(node_path, sizeof(node_path), "%s%d/idle_time", fb_path_, fb_node_index_); 467 468 // Open a sysfs node to send the timeout value to driver. 469 int fd = Sys::open_(node_path, O_WRONLY); 470 if (fd < 0) { 471 DLOGE("Unable to open %s, node %s", node_path, strerror(errno)); 472 return; 473 } 474 475 char timeout_string[64]; 476 snprintf(timeout_string, sizeof(timeout_string), "%d", timeout_ms); 477 478 // Notify driver about the timeout value 479 ssize_t length = Sys::pwrite_(fd, timeout_string, strlen(timeout_string), 0); 480 if (length <= 0) { 481 DLOGE("Unable to write into %s, node %s", node_path, strerror(errno)); 482 } 483 484 Sys::close_(fd); 485 } 486 487 DisplayError HWPrimary::SetVSyncState(bool enable) { 488 DTRACE_SCOPED(); 489 return HWDevice::SetVSyncState(enable); 490 } 491 492 DisplayError HWPrimary::SetDisplayMode(const HWDisplayMode hw_display_mode) { 493 uint32_t mode = kModeDefault; 494 495 switch (hw_display_mode) { 496 case kModeVideo: 497 mode = kModeLPMVideo; 498 break; 499 case kModeCommand: 500 mode = kModeLPMCommand; 501 break; 502 default: 503 DLOGW("Failed to translate SDE display mode %d to a MSMFB_LPM_ENABLE mode", 504 hw_display_mode); 505 return kErrorParameters; 506 } 507 508 if (Sys::ioctl_(device_fd_, INT(MSMFB_LPM_ENABLE), &mode) < 0) { 509 IOCTL_LOGE(MSMFB_LPM_ENABLE, device_type_); 510 return kErrorHardware; 511 } 512 513 DLOGI("Triggering display mode change to %d on next commit.", hw_display_mode); 514 synchronous_commit_ = true; 515 516 return kErrorNone; 517 } 518 519 DisplayError HWPrimary::SetPanelBrightness(int level) { 520 char buffer[kMaxSysfsCommandLength] = {0}; 521 522 DLOGV_IF(kTagDriverConfig, "Set brightness level to %d", level); 523 int fd = Sys::open_(kBrightnessNode, O_RDWR); 524 if (fd < 0) { 525 DLOGV_IF(kTagDriverConfig, "Failed to open node = %s, error = %s ", kBrightnessNode, 526 strerror(errno)); 527 return kErrorFileDescriptor; 528 } 529 530 int32_t bytes = snprintf(buffer, kMaxSysfsCommandLength, "%d\n", level); 531 if (bytes < 0) { 532 DLOGV_IF(kTagDriverConfig, "Failed to copy new brightness level = %d", level); 533 Sys::close_(fd); 534 return kErrorUndefined; 535 } 536 537 ssize_t ret = Sys::pwrite_(fd, buffer, static_cast<size_t>(bytes), 0); 538 if (ret <= 0) { 539 DLOGV_IF(kTagDriverConfig, "Failed to write to node = %s, error = %s ", kBrightnessNode, 540 strerror(errno)); 541 Sys::close_(fd); 542 return kErrorUndefined; 543 } 544 Sys::close_(fd); 545 546 return kErrorNone; 547 } 548 549 DisplayError HWPrimary::GetPanelBrightness(int *level) { 550 char brightness[kMaxStringLength] = {0}; 551 552 if (!level) { 553 DLOGV_IF(kTagDriverConfig, "Invalid input, null pointer."); 554 return kErrorParameters; 555 } 556 557 int fd = Sys::open_(kBrightnessNode, O_RDWR); 558 if (fd < 0) { 559 DLOGV_IF(kTagDriverConfig, "Failed to open brightness node = %s, error = %s", kBrightnessNode, 560 strerror(errno)); 561 return kErrorFileDescriptor; 562 } 563 564 if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) { 565 *level = atoi(brightness); 566 DLOGV_IF(kTagDriverConfig, "Brightness level = %d", *level); 567 } 568 Sys::close_(fd); 569 570 return kErrorNone; 571 } 572 573 DisplayError HWPrimary::CachePanelBrightness(int level) { 574 bl_level_update_commit = level; 575 bl_update_commit = true; 576 return kErrorNone; 577 } 578 579 DisplayError HWPrimary::SetAutoRefresh(bool enable) { 580 const int kWriteLength = 2; 581 char buffer[kWriteLength] = {'\0'}; 582 ssize_t bytes = snprintf(buffer, kWriteLength, "%d", enable); 583 584 if (enable == auto_refresh_) { 585 return kErrorNone; 586 } 587 588 if (HWDevice::SysFsWrite(kAutoRefreshNode, buffer, bytes) <= 0) { // Returns bytes written 589 return kErrorUndefined; 590 } 591 592 auto_refresh_ = enable; 593 594 return kErrorNone; 595 } 596 597 DisplayError HWPrimary::GetPPFeaturesVersion(PPFeatureVersion *vers) { 598 mdp_pp_feature_version version = {}; 599 600 #ifdef PA_DITHER 601 uint32_t feature_id_mapping[kMaxNumPPFeatures] = { PCC, IGC, GC, GC, PA, 602 DITHER, GAMUT, PA_DITHER }; 603 #else 604 uint32_t feature_id_mapping[kMaxNumPPFeatures] = { PCC, IGC, GC, GC, PA, DITHER, GAMUT }; 605 #endif 606 607 for (int i(0); i < kMaxNumPPFeatures; i++) { 608 version.pp_feature = feature_id_mapping[i]; 609 610 if (Sys::ioctl_(device_fd_, INT(MSMFB_MDP_PP_GET_FEATURE_VERSION), &version) < 0) { 611 IOCTL_LOGE(MSMFB_MDP_PP_GET_FEATURE_VERSION, device_type_); 612 return kErrorHardware; 613 } 614 vers->version[i] = version.version_info; 615 } 616 617 return kErrorNone; 618 } 619 620 // It was entered with PPFeaturesConfig::locker_ being hold. 621 DisplayError HWPrimary::SetPPFeatures(PPFeaturesConfig *feature_list) { 622 msmfb_mdp_pp kernel_params = {}; 623 int ret = 0; 624 PPFeatureInfo *feature = NULL; 625 626 while (true) { 627 ret = feature_list->RetrieveNextFeature(&feature); 628 if (ret) 629 break; 630 631 if (feature) { 632 DLOGV_IF(kTagDriverConfig, "feature_id = %d", feature->feature_id_); 633 634 if ((feature->feature_id_ < kMaxNumPPFeatures)) { 635 HWColorManager::SetFeature[feature->feature_id_](*feature, &kernel_params); 636 if (Sys::ioctl_(device_fd_, INT(MSMFB_MDP_PP), &kernel_params) < 0) { 637 IOCTL_LOGE(MSMFB_MDP_PP, device_type_); 638 639 feature_list->Reset(); 640 return kErrorHardware; 641 } 642 } 643 } 644 } // while(true) 645 646 // Once all features were consumed, then destroy all feature instance from feature_list, 647 // Then mark it as non-dirty of PPFeaturesConfig cache. 648 feature_list->Reset(); 649 650 return kErrorNone; 651 } 652 653 DisplayError HWPrimary::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) { 654 if (IsResolutionSwitchEnabled()) { 655 return kErrorNotSupported; 656 } 657 658 return HWDevice::SetMixerAttributes(mixer_attributes); 659 } 660 661 void HWPrimary::UpdateMixerAttributes() { 662 mixer_attributes_.width = display_attributes_.x_pixels; 663 mixer_attributes_.height = display_attributes_.y_pixels; 664 mixer_attributes_.split_left = display_attributes_.is_device_split ? 665 hw_panel_info_.split_info.left_split : mixer_attributes_.width; 666 } 667 668 void HWPrimary::SetAVRFlags(const HWAVRInfo &hw_avr_info, uint32_t *avr_flags) { 669 if (hw_avr_info.enable) { 670 *avr_flags |= MDP_COMMIT_AVR_EN; 671 } 672 673 if (hw_avr_info.mode == kOneShotMode) { 674 *avr_flags |= MDP_COMMIT_AVR_ONE_SHOT_MODE; 675 } 676 } 677 678 } // namespace sdm 679 680