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