1 /* 2 * Copyright (c) 2014 - 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 #define __STDC_FORMAT_MACROS 31 32 #include <stdio.h> 33 #include <ctype.h> 34 #include <math.h> 35 #include <fcntl.h> 36 #include <unistd.h> 37 #include <string.h> 38 #include <inttypes.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include <sys/ioctl.h> 42 #include <linux/fb.h> 43 #include <utils/constants.h> 44 #include <utils/debug.h> 45 #include <utils/sys.h> 46 #include <vector> 47 #include <algorithm> 48 #include <string> 49 50 #include "hw_device.h" 51 #include "hw_primary.h" 52 #include "hw_hdmi.h" 53 #include "hw_virtual.h" 54 #include "hw_info_interface.h" 55 56 #define __CLASS__ "HWDevice" 57 58 using std::string; 59 using std::to_string; 60 using std::fstream; 61 62 namespace sdm { 63 64 DisplayError HWInterface::Create(DisplayType type, HWInfoInterface *hw_info_intf, 65 BufferSyncHandler *buffer_sync_handler, 66 HWInterface **intf) { 67 DisplayError error = kErrorNone; 68 HWDevice *hw = nullptr; 69 70 switch (type) { 71 case kPrimary: 72 hw = new HWPrimary(buffer_sync_handler, hw_info_intf); 73 break; 74 case kHDMI: 75 hw = new HWHDMI(buffer_sync_handler, hw_info_intf); 76 break; 77 case kVirtual: 78 hw = new HWVirtual(buffer_sync_handler, hw_info_intf); 79 break; 80 default: 81 DLOGE("Undefined display type"); 82 return kErrorUndefined; 83 } 84 85 error = hw->Init(); 86 if (error != kErrorNone) { 87 delete hw; 88 DLOGE("Init on HW Intf type %d failed", type); 89 return error; 90 } 91 *intf = hw; 92 93 return error; 94 } 95 96 DisplayError HWInterface::Destroy(HWInterface *intf) { 97 HWDevice *hw = static_cast<HWDevice *>(intf); 98 hw->Deinit(); 99 delete hw; 100 101 return kErrorNone; 102 } 103 104 HWDevice::HWDevice(BufferSyncHandler *buffer_sync_handler) 105 : fb_node_index_(-1), fb_path_("/sys/devices/virtual/graphics/fb"), 106 buffer_sync_handler_(buffer_sync_handler), synchronous_commit_(false) { 107 } 108 109 DisplayError HWDevice::Init() { 110 // Read the fb node index 111 fb_node_index_ = GetFBNodeIndex(device_type_); 112 if (fb_node_index_ == -1) { 113 DLOGE("device type = %d should be present", device_type_); 114 return kErrorHardware; 115 } 116 117 const char *dev_name = NULL; 118 vector<string> dev_paths = {"/dev/graphics/fb", "/dev/fb"}; 119 for (size_t i = 0; i < dev_paths.size(); i++) { 120 dev_paths[i] += to_string(fb_node_index_); 121 if (Sys::access_(dev_paths[i].c_str(), F_OK) >= 0) { 122 dev_name = dev_paths[i].c_str(); 123 DLOGI("access(%s) successful", dev_name); 124 break; 125 } 126 127 DLOGI("access(%s), errno = %d, error = %s", dev_paths[i].c_str(), errno, strerror(errno)); 128 } 129 130 if (!dev_name) { 131 DLOGE("access() failed for all possible paths"); 132 return kErrorHardware; 133 } 134 135 // Populate Panel Info (Used for Partial Update) 136 PopulateHWPanelInfo(); 137 // Populate HW Capabilities 138 hw_resource_ = HWResourceInfo(); 139 hw_info_intf_->GetHWResourceInfo(&hw_resource_); 140 141 device_fd_ = Sys::open_(dev_name, O_RDWR); 142 if (device_fd_ < 0) { 143 DLOGE("open %s failed errno = %d, error = %s", dev_name, errno, strerror(errno)); 144 return kErrorResources; 145 } 146 147 return HWScale::Create(&hw_scale_, hw_resource_.has_qseed3); 148 } 149 150 DisplayError HWDevice::Deinit() { 151 HWScale::Destroy(hw_scale_); 152 153 if (device_fd_ >= 0) { 154 Sys::close_(device_fd_); 155 device_fd_ = -1; 156 } 157 158 return kErrorNone; 159 } 160 161 DisplayError HWDevice::GetActiveConfig(uint32_t *active_config) { 162 *active_config = 0; 163 return kErrorNone; 164 } 165 166 DisplayError HWDevice::GetNumDisplayAttributes(uint32_t *count) { 167 *count = 1; 168 return kErrorNone; 169 } 170 171 DisplayError HWDevice::GetDisplayAttributes(uint32_t index, 172 HWDisplayAttributes *display_attributes) { 173 return kErrorNone; 174 } 175 176 DisplayError HWDevice::GetHWPanelInfo(HWPanelInfo *panel_info) { 177 *panel_info = hw_panel_info_; 178 return kErrorNone; 179 } 180 181 DisplayError HWDevice::SetDisplayAttributes(uint32_t index) { 182 return kErrorNone; 183 } 184 185 DisplayError HWDevice::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) { 186 return kErrorNotSupported; 187 } 188 189 DisplayError HWDevice::GetConfigIndex(uint32_t mode, uint32_t *index) { 190 return kErrorNone; 191 } 192 193 DisplayError HWDevice::PowerOn() { 194 DTRACE_SCOPED(); 195 196 if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_UNBLANK) < 0) { 197 if (errno == ESHUTDOWN) { 198 DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence"); 199 return kErrorShutDown; 200 } 201 IOCTL_LOGE(FB_BLANK_UNBLANK, device_type_); 202 return kErrorHardware; 203 } 204 205 return kErrorNone; 206 } 207 208 DisplayError HWDevice::PowerOff() { 209 return kErrorNone; 210 } 211 212 DisplayError HWDevice::Doze() { 213 return kErrorNone; 214 } 215 216 DisplayError HWDevice::DozeSuspend() { 217 return kErrorNone; 218 } 219 220 DisplayError HWDevice::Standby() { 221 return kErrorNone; 222 } 223 224 DisplayError HWDevice::Validate(HWLayers *hw_layers) { 225 DTRACE_SCOPED(); 226 227 DisplayError error = kErrorNone; 228 229 HWLayersInfo &hw_layer_info = hw_layers->info; 230 LayerStack *stack = hw_layer_info.stack; 231 232 DLOGV_IF(kTagDriverConfig, "************************** %s Validate Input ***********************", 233 device_name_); 234 DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count); 235 236 mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1; 237 uint32_t &mdp_layer_count = mdp_commit.input_layer_cnt; 238 239 DLOGI_IF(kTagDriverConfig, "left_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.left_roi.x, 240 mdp_commit.left_roi.y, mdp_commit.left_roi.w, mdp_commit.left_roi.h); 241 DLOGI_IF(kTagDriverConfig, "right_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.right_roi.x, 242 mdp_commit.right_roi.y, mdp_commit.right_roi.w, mdp_commit.right_roi.h); 243 244 for (uint32_t i = 0; i < hw_layer_info.count; i++) { 245 uint32_t layer_index = hw_layer_info.index[i]; 246 Layer *layer = stack->layers.at(layer_index); 247 LayerBuffer *input_buffer = layer->input_buffer; 248 HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe; 249 HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe; 250 HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session; 251 bool is_rotator_used = (hw_rotator_session->hw_block_count != 0); 252 bool is_cursor_pipe_used = (hw_layer_info.use_hw_cursor & layer->flags.cursor); 253 254 for (uint32_t count = 0; count < 2; count++) { 255 HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe; 256 HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count]; 257 258 if (hw_rotate_info->valid) { 259 input_buffer = &hw_rotator_session->output_buffer; 260 } 261 262 if (pipe_info->valid) { 263 mdp_input_layer &mdp_layer = mdp_in_layers_[mdp_layer_count]; 264 mdp_layer_buffer &mdp_buffer = mdp_layer.buffer; 265 266 mdp_buffer.width = input_buffer->width; 267 mdp_buffer.height = input_buffer->height; 268 mdp_buffer.comp_ratio.denom = 1000; 269 mdp_buffer.comp_ratio.numer = UINT32(hw_layers->config[i].compression * 1000); 270 271 if (layer->flags.solid_fill) { 272 mdp_buffer.format = MDP_ARGB_8888; 273 } else { 274 error = SetFormat(input_buffer->format, &mdp_buffer.format); 275 if (error != kErrorNone) { 276 return error; 277 } 278 } 279 mdp_layer.alpha = layer->plane_alpha; 280 mdp_layer.z_order = UINT16(pipe_info->z_order); 281 mdp_layer.transp_mask = 0xffffffff; 282 SetBlending(layer->blending, &mdp_layer.blend_op); 283 mdp_layer.pipe_ndx = pipe_info->pipe_id; 284 mdp_layer.horz_deci = pipe_info->horizontal_decimation; 285 mdp_layer.vert_deci = pipe_info->vertical_decimation; 286 287 SetRect(pipe_info->src_roi, &mdp_layer.src_rect); 288 SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect); 289 SetMDPFlags(layer, is_rotator_used, is_cursor_pipe_used, &mdp_layer.flags); 290 SetCSC(layer->input_buffer->csc, &mdp_layer.color_space); 291 if (pipe_info->flags & kIGC) { 292 SetIGC(layer->input_buffer, mdp_layer_count); 293 } 294 if (pipe_info->flags & kMultiRect) { 295 mdp_layer.flags |= MDP_LAYER_MULTIRECT_ENABLE; 296 if (pipe_info->flags & kMultiRectParallelMode) { 297 mdp_layer.flags |= MDP_LAYER_MULTIRECT_PARALLEL_MODE; 298 } 299 } 300 mdp_layer.bg_color = layer->solid_fill_color; 301 302 // HWScaleData to MDP driver 303 hw_scale_->SetHWScaleData(pipe_info->scale_data, mdp_layer_count, &mdp_commit, 304 pipe_info->sub_block_type); 305 mdp_layer.scale = hw_scale_->GetScaleDataRef(mdp_layer_count, pipe_info->sub_block_type); 306 307 mdp_layer_count++; 308 309 DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************", 310 i, count ? "Right" : "Left"); 311 DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d", mdp_buffer.width, mdp_buffer.height, 312 mdp_buffer.format); 313 DLOGV_IF(kTagDriverConfig, "plane_alpha %d, zorder %d, blending %d, horz_deci %d, " 314 "vert_deci %d, pipe_id = 0x%x, mdp_flags 0x%x", mdp_layer.alpha, mdp_layer.z_order, 315 mdp_layer.blend_op, mdp_layer.horz_deci, mdp_layer.vert_deci, mdp_layer.pipe_ndx, 316 mdp_layer.flags); 317 DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_layer.src_rect.x, 318 mdp_layer.src_rect.y, mdp_layer.src_rect.w, mdp_layer.src_rect.h); 319 DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_layer.dst_rect.x, 320 mdp_layer.dst_rect.y, mdp_layer.dst_rect.w, mdp_layer.dst_rect.h); 321 hw_scale_->DumpScaleData(mdp_layer.scale); 322 DLOGV_IF(kTagDriverConfig, "*************************************************************"); 323 } 324 } 325 } 326 327 // TODO(user): This block should move to the derived class 328 if (device_type_ == kDeviceVirtual) { 329 LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer; 330 mdp_out_layer_.writeback_ndx = hw_resource_.writeback_index; 331 mdp_out_layer_.buffer.width = output_buffer->width; 332 mdp_out_layer_.buffer.height = output_buffer->height; 333 if (output_buffer->flags.secure) { 334 mdp_out_layer_.flags |= MDP_LAYER_SECURE_SESSION; 335 } 336 mdp_out_layer_.buffer.comp_ratio.denom = 1000; 337 mdp_out_layer_.buffer.comp_ratio.numer = UINT32(hw_layers->output_compression * 1000); 338 #ifdef OUT_LAYER_COLOR_SPACE 339 SetCSC(output_buffer->csc, &mdp_out_layer_.color_space); 340 #endif 341 SetFormat(output_buffer->format, &mdp_out_layer_.buffer.format); 342 343 DLOGI_IF(kTagDriverConfig, "********************* Output buffer Info ************************"); 344 DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d", 345 mdp_out_layer_.buffer.width, mdp_out_layer_.buffer.height, 346 mdp_out_layer_.buffer.format, mdp_out_layer_.writeback_ndx); 347 DLOGI_IF(kTagDriverConfig, "*****************************************************************"); 348 } 349 350 uint32_t index = 0; 351 for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) { 352 DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i); 353 354 if (it == hw_layer_info.dest_scale_info_map.end()) { 355 continue; 356 } 357 358 HWDestScaleInfo *dest_scale_info = it->second; 359 360 mdp_destination_scaler_data *dest_scalar_data = &mdp_dest_scalar_data_[index]; 361 hw_scale_->SetHWScaleData(dest_scale_info->scale_data, index, &mdp_commit, 362 kHWDestinationScalar); 363 364 if (dest_scale_info->scale_update) { 365 dest_scalar_data->flags |= MDP_DESTSCALER_SCALE_UPDATE; 366 } 367 368 dest_scalar_data->dest_scaler_ndx = i; 369 dest_scalar_data->lm_width = dest_scale_info->mixer_width; 370 dest_scalar_data->lm_height = dest_scale_info->mixer_height; 371 dest_scalar_data->scale = reinterpret_cast <uint64_t> 372 (hw_scale_->GetScaleDataRef(index, kHWDestinationScalar)); 373 374 index++; 375 376 DLOGV_IF(kTagDriverConfig, "************************ DestScalar[%d] **************************", 377 dest_scalar_data->dest_scaler_ndx); 378 DLOGV_IF(kTagDriverConfig, "Mixer WxH %dx%d", dest_scalar_data->lm_width, 379 dest_scalar_data->lm_height); 380 DLOGI_IF(kTagDriverConfig, "*****************************************************************"); 381 } 382 mdp_commit.dest_scaler_cnt = UINT32(hw_layer_info.dest_scale_info_map.size()); 383 384 mdp_commit.flags |= MDP_VALIDATE_LAYER; 385 if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) { 386 if (errno == ESHUTDOWN) { 387 DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence"); 388 return kErrorShutDown; 389 } 390 IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_); 391 DumpLayerCommit(mdp_disp_commit_); 392 return kErrorHardware; 393 } 394 395 return kErrorNone; 396 } 397 398 void HWDevice::DumpLayerCommit(const mdp_layer_commit &layer_commit) { 399 const mdp_layer_commit_v1 &mdp_commit = layer_commit.commit_v1; 400 const mdp_input_layer *mdp_layers = mdp_commit.input_layers; 401 const mdp_rect &l_roi = mdp_commit.left_roi; 402 const mdp_rect &r_roi = mdp_commit.right_roi; 403 404 DLOGI("mdp_commit: flags = %x, release fence = %x", mdp_commit.flags, mdp_commit.release_fence); 405 DLOGI("left_roi: x = %d, y = %d, w = %d, h = %d", l_roi.x, l_roi.y, l_roi.w, l_roi.h); 406 DLOGI("right_roi: x = %d, y = %d, w = %d, h = %d", r_roi.x, r_roi.y, r_roi.w, r_roi.h); 407 for (uint32_t i = 0; i < mdp_commit.input_layer_cnt; i++) { 408 const mdp_input_layer &layer = mdp_layers[i]; 409 const mdp_rect &src_rect = layer.src_rect; 410 const mdp_rect &dst_rect = layer.dst_rect; 411 DLOGI("layer = %d, pipe_ndx = %x, z = %d, flags = %x", 412 i, layer.pipe_ndx, layer.z_order, layer.flags); 413 DLOGI("src_rect: x = %d, y = %d, w = %d, h = %d", 414 src_rect.x, src_rect.y, src_rect.w, src_rect.h); 415 DLOGI("dst_rect: x = %d, y = %d, w = %d, h = %d", 416 dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h); 417 } 418 } 419 420 DisplayError HWDevice::Commit(HWLayers *hw_layers) { 421 DTRACE_SCOPED(); 422 423 HWLayersInfo &hw_layer_info = hw_layers->info; 424 LayerStack *stack = hw_layer_info.stack; 425 426 DLOGV_IF(kTagDriverConfig, "*************************** %s Commit Input ************************", 427 device_name_); 428 DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count); 429 430 mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1; 431 uint32_t mdp_layer_index = 0; 432 433 for (uint32_t i = 0; i < hw_layer_info.count; i++) { 434 uint32_t layer_index = hw_layer_info.index[i]; 435 LayerBuffer *input_buffer = stack->layers.at(layer_index)->input_buffer; 436 HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe; 437 HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe; 438 HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session; 439 440 for (uint32_t count = 0; count < 2; count++) { 441 HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe; 442 HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count]; 443 444 if (hw_rotate_info->valid) { 445 input_buffer = &hw_rotator_session->output_buffer; 446 } 447 448 if (pipe_info->valid) { 449 mdp_layer_buffer &mdp_buffer = mdp_in_layers_[mdp_layer_index].buffer; 450 mdp_input_layer &mdp_layer = mdp_in_layers_[mdp_layer_index]; 451 if (input_buffer->planes[0].fd >= 0) { 452 mdp_buffer.plane_count = 1; 453 mdp_buffer.planes[0].fd = input_buffer->planes[0].fd; 454 mdp_buffer.planes[0].offset = input_buffer->planes[0].offset; 455 SetStride(device_type_, input_buffer->format, input_buffer->planes[0].stride, 456 &mdp_buffer.planes[0].stride); 457 } else { 458 mdp_buffer.plane_count = 0; 459 } 460 461 mdp_buffer.fence = input_buffer->acquire_fence_fd; 462 mdp_layer_index++; 463 464 DLOGV_IF(kTagDriverConfig, "****************** Layer[%d] %s pipe Input *******************", 465 i, count ? "Right" : "Left"); 466 DLOGI_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d, horz_deci %d, vert_deci %d", 467 mdp_buffer.width, mdp_buffer.height, mdp_buffer.format, mdp_layer.horz_deci, 468 mdp_layer.vert_deci); 469 DLOGI_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_buf_stride %d, " \ 470 "in_plane_count %d, in_fence %d, layer count %d", mdp_buffer.planes[0].fd, 471 mdp_buffer.planes[0].offset, mdp_buffer.planes[0].stride, mdp_buffer.plane_count, 472 mdp_buffer.fence, mdp_commit.input_layer_cnt); 473 DLOGV_IF(kTagDriverConfig, "*************************************************************"); 474 } 475 } 476 } 477 478 // TODO(user): Move to derived class 479 if (device_type_ == kDeviceVirtual) { 480 LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer; 481 482 if (output_buffer->planes[0].fd >= 0) { 483 mdp_out_layer_.buffer.planes[0].fd = output_buffer->planes[0].fd; 484 mdp_out_layer_.buffer.planes[0].offset = output_buffer->planes[0].offset; 485 SetStride(device_type_, output_buffer->format, output_buffer->planes[0].stride, 486 &mdp_out_layer_.buffer.planes[0].stride); 487 mdp_out_layer_.buffer.plane_count = 1; 488 } else { 489 DLOGE("Invalid output buffer fd"); 490 return kErrorParameters; 491 } 492 493 mdp_out_layer_.buffer.fence = output_buffer->acquire_fence_fd; 494 495 DLOGI_IF(kTagDriverConfig, "********************** Output buffer Info ***********************"); 496 DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, acquire_fence %d", 497 mdp_out_layer_.buffer.planes[0].fd, mdp_out_layer_.buffer.planes[0].offset, 498 mdp_out_layer_.buffer.planes[0].stride, mdp_out_layer_.buffer.fence); 499 DLOGI_IF(kTagDriverConfig, "*****************************************************************"); 500 } 501 502 mdp_commit.release_fence = -1; 503 mdp_commit.flags &= UINT32(~MDP_VALIDATE_LAYER); 504 if (synchronous_commit_) { 505 mdp_commit.flags |= MDP_COMMIT_WAIT_FOR_FINISH; 506 } 507 if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) { 508 if (errno == ESHUTDOWN) { 509 DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence"); 510 return kErrorShutDown; 511 } 512 IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_); 513 DumpLayerCommit(mdp_disp_commit_); 514 synchronous_commit_ = false; 515 return kErrorHardware; 516 } 517 518 stack->retire_fence_fd = mdp_commit.retire_fence; 519 #ifdef VIDEO_MODE_DEFER_RETIRE_FENCE 520 if (hw_panel_info_.mode == kModeVideo) { 521 stack->retire_fence_fd = stored_retire_fence; 522 stored_retire_fence = mdp_commit.retire_fence; 523 } 524 #endif 525 // MDP returns only one release fence for the entire layer stack. Duplicate this fence into all 526 // layers being composed by MDP. 527 528 std::vector<uint32_t> fence_dup_flag; 529 fence_dup_flag.clear(); 530 531 for (uint32_t i = 0; i < hw_layer_info.count; i++) { 532 uint32_t layer_index = hw_layer_info.index[i]; 533 LayerBuffer *input_buffer = stack->layers.at(layer_index)->input_buffer; 534 HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session; 535 536 if (hw_rotator_session->hw_block_count) { 537 input_buffer = &hw_rotator_session->output_buffer; 538 input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence); 539 continue; 540 } 541 542 // Make sure the release fence is duplicated only once for each buffer. 543 if (std::find(fence_dup_flag.begin(), fence_dup_flag.end(), layer_index) == 544 fence_dup_flag.end()) { 545 input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence); 546 fence_dup_flag.push_back(layer_index); 547 } 548 } 549 fence_dup_flag.clear(); 550 551 hw_layer_info.sync_handle = Sys::dup_(mdp_commit.release_fence); 552 553 DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************", 554 device_name_); 555 DLOGI_IF(kTagDriverConfig, "retire_fence_fd %d", stack->retire_fence_fd); 556 DLOGI_IF(kTagDriverConfig, "*******************************************************************"); 557 558 if (mdp_commit.release_fence >= 0) { 559 Sys::close_(mdp_commit.release_fence); 560 } 561 562 if (synchronous_commit_) { 563 // A synchronous commit can be requested when changing the display mode so we need to update 564 // panel info. 565 PopulateHWPanelInfo(); 566 synchronous_commit_ = false; 567 } 568 569 return kErrorNone; 570 } 571 572 DisplayError HWDevice::Flush() { 573 ResetDisplayParams(); 574 mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1; 575 mdp_commit.input_layer_cnt = 0; 576 mdp_commit.output_layer = NULL; 577 578 mdp_commit.flags &= UINT32(~MDP_VALIDATE_LAYER); 579 if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) { 580 if (errno == ESHUTDOWN) { 581 DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence"); 582 return kErrorShutDown; 583 } 584 IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_); 585 DumpLayerCommit(mdp_disp_commit_); 586 return kErrorHardware; 587 } 588 return kErrorNone; 589 } 590 591 DisplayError HWDevice::SetFormat(const LayerBufferFormat &source, uint32_t *target) { 592 switch (source) { 593 case kFormatARGB8888: *target = MDP_ARGB_8888; break; 594 case kFormatRGBA8888: *target = MDP_RGBA_8888; break; 595 case kFormatBGRA8888: *target = MDP_BGRA_8888; break; 596 case kFormatRGBX8888: *target = MDP_RGBX_8888; break; 597 case kFormatBGRX8888: *target = MDP_BGRX_8888; break; 598 case kFormatRGBA5551: *target = MDP_RGBA_5551; break; 599 case kFormatRGBA4444: *target = MDP_RGBA_4444; break; 600 case kFormatRGB888: *target = MDP_RGB_888; break; 601 case kFormatBGR888: *target = MDP_BGR_888; break; 602 case kFormatRGB565: *target = MDP_RGB_565; break; 603 case kFormatBGR565: *target = MDP_BGR_565; break; 604 case kFormatYCbCr420Planar: *target = MDP_Y_CB_CR_H2V2; break; 605 case kFormatYCrCb420Planar: *target = MDP_Y_CR_CB_H2V2; break; 606 case kFormatYCrCb420PlanarStride16: *target = MDP_Y_CR_CB_GH2V2; break; 607 case kFormatYCbCr420SemiPlanar: *target = MDP_Y_CBCR_H2V2; break; 608 case kFormatYCrCb420SemiPlanar: *target = MDP_Y_CRCB_H2V2; break; 609 case kFormatYCbCr422H1V2SemiPlanar: *target = MDP_Y_CBCR_H1V2; break; 610 case kFormatYCrCb422H1V2SemiPlanar: *target = MDP_Y_CRCB_H1V2; break; 611 case kFormatYCbCr422H2V1SemiPlanar: *target = MDP_Y_CBCR_H2V1; break; 612 case kFormatYCrCb422H2V1SemiPlanar: *target = MDP_Y_CRCB_H2V1; break; 613 case kFormatYCbCr422H2V1Packed: *target = MDP_YCBYCR_H2V1; break; 614 case kFormatYCbCr420SemiPlanarVenus: *target = MDP_Y_CBCR_H2V2_VENUS; break; 615 case kFormatRGBA8888Ubwc: *target = MDP_RGBA_8888_UBWC; break; 616 case kFormatRGBX8888Ubwc: *target = MDP_RGBX_8888_UBWC; break; 617 case kFormatBGR565Ubwc: *target = MDP_RGB_565_UBWC; break; 618 case kFormatYCbCr420SPVenusUbwc: *target = MDP_Y_CBCR_H2V2_UBWC; break; 619 case kFormatRGBA1010102: *target = MDP_RGBA_1010102; break; 620 case kFormatARGB2101010: *target = MDP_ARGB_2101010; break; 621 case kFormatRGBX1010102: *target = MDP_RGBX_1010102; break; 622 case kFormatXRGB2101010: *target = MDP_XRGB_2101010; break; 623 case kFormatBGRA1010102: *target = MDP_BGRA_1010102; break; 624 case kFormatABGR2101010: *target = MDP_ABGR_2101010; break; 625 case kFormatBGRX1010102: *target = MDP_BGRX_1010102; break; 626 case kFormatXBGR2101010: *target = MDP_XBGR_2101010; break; 627 case kFormatRGBA1010102Ubwc: *target = MDP_RGBA_1010102_UBWC; break; 628 case kFormatRGBX1010102Ubwc: *target = MDP_RGBX_1010102_UBWC; break; 629 case kFormatYCbCr420P010: *target = MDP_Y_CBCR_H2V2_P010; break; 630 case kFormatYCbCr420TP10Ubwc: *target = MDP_Y_CBCR_H2V2_TP10_UBWC; break; 631 default: 632 DLOGE("Unsupported format type %d", source); 633 return kErrorParameters; 634 } 635 636 return kErrorNone; 637 } 638 639 DisplayError HWDevice::SetStride(HWDeviceType device_type, LayerBufferFormat format, 640 uint32_t width, uint32_t *target) { 641 // TODO(user): This SetStride function is a workaround to satisfy the driver expectation for 642 // rotator and virtual devices. Eventually this will be taken care in the driver. 643 if (device_type != kDeviceRotator && device_type != kDeviceVirtual) { 644 *target = width; 645 return kErrorNone; 646 } 647 648 switch (format) { 649 case kFormatARGB8888: 650 case kFormatRGBA8888: 651 case kFormatBGRA8888: 652 case kFormatRGBX8888: 653 case kFormatBGRX8888: 654 case kFormatRGBA8888Ubwc: 655 case kFormatRGBX8888Ubwc: 656 case kFormatRGBA1010102: 657 case kFormatARGB2101010: 658 case kFormatRGBX1010102: 659 case kFormatXRGB2101010: 660 case kFormatBGRA1010102: 661 case kFormatABGR2101010: 662 case kFormatBGRX1010102: 663 case kFormatXBGR2101010: 664 case kFormatRGBA1010102Ubwc: 665 case kFormatRGBX1010102Ubwc: 666 *target = width * 4; 667 break; 668 case kFormatRGB888: 669 case kFormatBGR888: 670 *target = width * 3; 671 break; 672 case kFormatRGB565: 673 case kFormatBGR565: 674 case kFormatBGR565Ubwc: 675 *target = width * 2; 676 break; 677 case kFormatYCbCr420SemiPlanarVenus: 678 case kFormatYCbCr420SPVenusUbwc: 679 case kFormatYCbCr420Planar: 680 case kFormatYCrCb420Planar: 681 case kFormatYCrCb420PlanarStride16: 682 case kFormatYCbCr420SemiPlanar: 683 case kFormatYCrCb420SemiPlanar: 684 case kFormatYCbCr420P010: 685 case kFormatYCbCr420TP10Ubwc: 686 *target = width; 687 break; 688 case kFormatYCbCr422H2V1Packed: 689 case kFormatYCrCb422H2V1SemiPlanar: 690 case kFormatYCrCb422H1V2SemiPlanar: 691 case kFormatYCbCr422H2V1SemiPlanar: 692 case kFormatYCbCr422H1V2SemiPlanar: 693 case kFormatRGBA5551: 694 case kFormatRGBA4444: 695 *target = width * 2; 696 break; 697 default: 698 DLOGE("Unsupported format type %d", format); 699 return kErrorParameters; 700 } 701 702 return kErrorNone; 703 } 704 705 void HWDevice::SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target) { 706 switch (source) { 707 case kBlendingPremultiplied: *target = BLEND_OP_PREMULTIPLIED; break; 708 case kBlendingOpaque: *target = BLEND_OP_OPAQUE; break; 709 case kBlendingCoverage: *target = BLEND_OP_COVERAGE; break; 710 default: *target = BLEND_OP_NOT_DEFINED; break; 711 } 712 } 713 714 void HWDevice::SetRect(const LayerRect &source, mdp_rect *target) { 715 target->x = UINT32(source.left); 716 target->y = UINT32(source.top); 717 target->w = UINT32(source.right) - target->x; 718 target->h = UINT32(source.bottom) - target->y; 719 } 720 721 void HWDevice::SetMDPFlags(const Layer *layer, const bool &is_rotator_used, 722 bool is_cursor_pipe_used, uint32_t *mdp_flags) { 723 const LayerBuffer *input_buffer = layer->input_buffer; 724 725 // Flips will be taken care by rotator, if layer uses rotator for downscale/rotation. So ignore 726 // flip flags for MDP. 727 if (!is_rotator_used) { 728 if (layer->transform.flip_vertical) { 729 *mdp_flags |= MDP_LAYER_FLIP_UD; 730 } 731 732 if (layer->transform.flip_horizontal) { 733 *mdp_flags |= MDP_LAYER_FLIP_LR; 734 } 735 736 if (input_buffer->flags.interlace) { 737 *mdp_flags |= MDP_LAYER_DEINTERLACE; 738 } 739 } 740 741 if (input_buffer->flags.secure) { 742 *mdp_flags |= MDP_LAYER_SECURE_SESSION; 743 } 744 745 if (input_buffer->flags.secure_display) { 746 *mdp_flags |= MDP_LAYER_SECURE_DISPLAY_SESSION; 747 } 748 749 if (layer->flags.solid_fill) { 750 *mdp_flags |= MDP_LAYER_SOLID_FILL; 751 } 752 753 if (hw_panel_info_.mode != kModeCommand && layer->flags.cursor && is_cursor_pipe_used) { 754 // command mode panels does not support async position update 755 *mdp_flags |= MDP_LAYER_ASYNC; 756 } 757 } 758 759 int HWDevice::GetFBNodeIndex(HWDeviceType device_type) { 760 for (int i = 0; i < kFBNodeMax; i++) { 761 HWPanelInfo panel_info; 762 GetHWPanelInfoByNode(i, &panel_info); 763 switch (device_type) { 764 case kDevicePrimary: 765 if (panel_info.is_primary_panel) { 766 return i; 767 } 768 break; 769 case kDeviceHDMI: 770 if (panel_info.is_pluggable == true) { 771 if (IsFBNodeConnected(i)) { 772 return i; 773 } 774 } 775 break; 776 case kDeviceVirtual: 777 if (panel_info.port == kPortWriteBack) { 778 return i; 779 } 780 break; 781 default: 782 break; 783 } 784 } 785 return -1; 786 } 787 788 void HWDevice::PopulateHWPanelInfo() { 789 hw_panel_info_ = HWPanelInfo(); 790 GetHWPanelInfoByNode(fb_node_index_, &hw_panel_info_); 791 DLOGI("Device type = %d, Display Port = %d, Display Mode = %d, Device Node = %d, Is Primary = %d", 792 device_type_, hw_panel_info_.port, hw_panel_info_.mode, fb_node_index_, 793 hw_panel_info_.is_primary_panel); 794 DLOGI("Partial Update = %d, Dynamic FPS = %d", 795 hw_panel_info_.partial_update, hw_panel_info_.dynamic_fps); 796 DLOGI("Align: left = %d, width = %d, top = %d, height = %d", 797 hw_panel_info_.left_align, hw_panel_info_.width_align, 798 hw_panel_info_.top_align, hw_panel_info_.height_align); 799 DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d", 800 hw_panel_info_.min_roi_width, hw_panel_info_.min_roi_height, 801 hw_panel_info_.needs_roi_merge); 802 DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps); 803 DLOGI("Ping Pong Split = %d", hw_panel_info_.ping_pong_split); 804 DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split, 805 hw_panel_info_.split_info.right_split); 806 } 807 808 void HWDevice::GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info) { 809 string file_name = fb_path_ + to_string(device_node) + "/msm_fb_panel_info"; 810 811 Sys::fstream fs(file_name, fstream::in); 812 if (!fs.is_open()) { 813 DLOGW("Failed to open msm_fb_panel_info node device node %d", device_node); 814 return; 815 } 816 817 string line; 818 while (Sys::getline_(fs, line)) { 819 uint32_t token_count = 0; 820 const uint32_t max_count = 10; 821 char *tokens[max_count] = { NULL }; 822 if (!ParseLine(line.c_str(), "=\n", tokens, max_count, &token_count)) { 823 if (!strncmp(tokens[0], "panel_name", strlen("panel_name"))) { 824 snprintf(panel_info->panel_name, sizeof(panel_info->panel_name), "%s", tokens[1]); 825 break; 826 } 827 } 828 } 829 } 830 831 void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) { 832 string file_name = fb_path_ + to_string(device_node) + "/msm_fb_panel_info"; 833 834 Sys::fstream fs(file_name, fstream::in); 835 if (!fs.is_open()) { 836 DLOGW("Failed to open msm_fb_panel_info node device node %d", device_node); 837 return; 838 } 839 840 string line; 841 while (Sys::getline_(fs, line)) { 842 uint32_t token_count = 0; 843 const uint32_t max_count = 10; 844 char *tokens[max_count] = { NULL }; 845 if (!ParseLine(line.c_str(), tokens, max_count, &token_count)) { 846 if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) { 847 panel_info->partial_update = atoi(tokens[1]); 848 } else if (!strncmp(tokens[0], "xstart", strlen("xstart"))) { 849 panel_info->left_align = atoi(tokens[1]); 850 } else if (!strncmp(tokens[0], "walign", strlen("walign"))) { 851 panel_info->width_align = atoi(tokens[1]); 852 } else if (!strncmp(tokens[0], "ystart", strlen("ystart"))) { 853 panel_info->top_align = atoi(tokens[1]); 854 } else if (!strncmp(tokens[0], "halign", strlen("halign"))) { 855 panel_info->height_align = atoi(tokens[1]); 856 } else if (!strncmp(tokens[0], "min_w", strlen("min_w"))) { 857 panel_info->min_roi_width = atoi(tokens[1]); 858 } else if (!strncmp(tokens[0], "min_h", strlen("min_h"))) { 859 panel_info->min_roi_height = atoi(tokens[1]); 860 } else if (!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) { 861 panel_info->needs_roi_merge = atoi(tokens[1]); 862 } else if (!strncmp(tokens[0], "dyn_fps_en", strlen("dyn_fps_en"))) { 863 panel_info->dynamic_fps = atoi(tokens[1]); 864 } else if (!strncmp(tokens[0], "dfps_porch_mode", strlen("dfps_porch_mode"))) { 865 panel_info->dfps_porch_mode = atoi(tokens[1]); 866 } else if (!strncmp(tokens[0], "is_pingpong_split", strlen("is_pingpong_split"))) { 867 panel_info->ping_pong_split = atoi(tokens[1]); 868 } else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) { 869 panel_info->min_fps = UINT32(atoi(tokens[1])); 870 } else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) { 871 panel_info->max_fps = UINT32(atoi(tokens[1])); 872 } else if (!strncmp(tokens[0], "primary_panel", strlen("primary_panel"))) { 873 panel_info->is_primary_panel = atoi(tokens[1]); 874 } else if (!strncmp(tokens[0], "is_pluggable", strlen("is_pluggable"))) { 875 panel_info->is_pluggable = atoi(tokens[1]); 876 } 877 } 878 } 879 880 GetHWDisplayPortAndMode(device_node, panel_info); 881 GetSplitInfo(device_node, panel_info); 882 GetHWPanelNameByNode(device_node, panel_info); 883 GetHWPanelMaxBrightnessFromNode(panel_info); 884 } 885 886 void HWDevice::GetHWDisplayPortAndMode(int device_node, HWPanelInfo *panel_info) { 887 DisplayPort *port = &panel_info->port; 888 HWDisplayMode *mode = &panel_info->mode; 889 890 *port = kPortDefault; 891 *mode = kModeDefault; 892 893 string file_name = fb_path_ + to_string(device_node) + "/msm_fb_type"; 894 895 Sys::fstream fs(file_name, fstream::in); 896 if (!fs.is_open()) { 897 DLOGW("File not found %s", file_name.c_str()); 898 return; 899 } 900 901 string line; 902 if (!Sys::getline_(fs, line)) { 903 return; 904 } 905 906 if ((strncmp(line.c_str(), "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) { 907 *port = kPortDSI; 908 *mode = kModeCommand; 909 } else if ((strncmp(line.c_str(), "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) { 910 *port = kPortDSI; 911 *mode = kModeVideo; 912 } else if ((strncmp(line.c_str(), "lvds panel", strlen("lvds panel")) == 0)) { 913 *port = kPortLVDS; 914 *mode = kModeVideo; 915 } else if ((strncmp(line.c_str(), "edp panel", strlen("edp panel")) == 0)) { 916 *port = kPortEDP; 917 *mode = kModeVideo; 918 } else if ((strncmp(line.c_str(), "dtv panel", strlen("dtv panel")) == 0)) { 919 *port = kPortDTV; 920 *mode = kModeVideo; 921 } else if ((strncmp(line.c_str(), "writeback panel", strlen("writeback panel")) == 0)) { 922 *port = kPortWriteBack; 923 *mode = kModeCommand; 924 } else if ((strncmp(line.c_str(), "dp panel", strlen("dp panel")) == 0)) { 925 *port = kPortDP; 926 *mode = kModeVideo; 927 } 928 929 return; 930 } 931 932 void HWDevice::GetSplitInfo(int device_node, HWPanelInfo *panel_info) { 933 // Split info - for MDSS Version 5 - No need to check version here 934 string file_name = fb_path_ + to_string(device_node) + "/msm_fb_split"; 935 936 Sys::fstream fs(file_name, fstream::in); 937 if (!fs.is_open()) { 938 DLOGW("File not found %s", file_name.c_str()); 939 return; 940 } 941 942 // Format "left right" space as delimiter 943 uint32_t token_count = 0; 944 const uint32_t max_count = 10; 945 char *tokens[max_count] = { NULL }; 946 string line; 947 if (Sys::getline_(fs, line)) { 948 if (!ParseLine(line.c_str(), tokens, max_count, &token_count)) { 949 panel_info->split_info.left_split = UINT32(atoi(tokens[0])); 950 panel_info->split_info.right_split = UINT32(atoi(tokens[1])); 951 } 952 } 953 } 954 955 void HWDevice::GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info) { 956 char brightness[kMaxStringLength] = { 0 }; 957 char kMaxBrightnessNode[64] = { 0 }; 958 959 snprintf(kMaxBrightnessNode, sizeof(kMaxBrightnessNode), "%s", 960 "/sys/class/leds/lcd-backlight/max_brightness"); 961 962 panel_info->panel_max_brightness = 0; 963 int fd = Sys::open_(kMaxBrightnessNode, O_RDONLY); 964 if (fd < 0) { 965 DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode, 966 strerror(errno)); 967 return; 968 } 969 970 if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) { 971 panel_info->panel_max_brightness = atoi(brightness); 972 DLOGI("Max brightness level = %d", panel_info->panel_max_brightness); 973 } else { 974 DLOGW("Failed to read max brightness level. error = %s", strerror(errno)); 975 } 976 Sys::close_(fd); 977 } 978 979 int HWDevice::ParseLine(const char *input, char *tokens[], const uint32_t max_token, 980 uint32_t *count) { 981 char *tmp_token = NULL; 982 char *temp_ptr; 983 uint32_t index = 0; 984 const char *delim = ", =\n"; 985 if (!input) { 986 return -1; 987 } 988 tmp_token = strtok_r(const_cast<char *>(input), delim, &temp_ptr); 989 while (tmp_token && index < max_token) { 990 tokens[index++] = tmp_token; 991 tmp_token = strtok_r(NULL, delim, &temp_ptr); 992 } 993 *count = index; 994 995 return 0; 996 } 997 998 int HWDevice::ParseLine(const char *input, const char *delim, char *tokens[], 999 const uint32_t max_token, uint32_t *count) { 1000 char *tmp_token = NULL; 1001 char *temp_ptr; 1002 uint32_t index = 0; 1003 if (!input) { 1004 return -1; 1005 } 1006 tmp_token = strtok_r(const_cast<char *>(input), delim, &temp_ptr); 1007 while (tmp_token && index < max_token) { 1008 tokens[index++] = tmp_token; 1009 tmp_token = strtok_r(NULL, delim, &temp_ptr); 1010 } 1011 *count = index; 1012 1013 return 0; 1014 } 1015 1016 bool HWDevice::EnableHotPlugDetection(int enable) { 1017 char hpdpath[kMaxStringLength]; 1018 char value = enable ? '1' : '0'; 1019 1020 // Enable HPD for all pluggable devices. 1021 for (int i = 0; i < kFBNodeMax; i++) { 1022 HWPanelInfo panel_info; 1023 GetHWPanelInfoByNode(i, &panel_info); 1024 if (panel_info.is_pluggable == true) { 1025 snprintf(hpdpath , sizeof(hpdpath), "%s%d/hpd", fb_path_, i); 1026 1027 ssize_t length = SysFsWrite(hpdpath, &value, sizeof(value)); 1028 if (length <= 0) { 1029 return false; 1030 } 1031 } 1032 } 1033 1034 return true; 1035 } 1036 1037 void HWDevice::ResetDisplayParams() { 1038 memset(&mdp_disp_commit_, 0, sizeof(mdp_disp_commit_)); 1039 memset(&mdp_in_layers_, 0, sizeof(mdp_in_layers_)); 1040 memset(&mdp_out_layer_, 0, sizeof(mdp_out_layer_)); 1041 mdp_out_layer_.buffer.fence = -1; 1042 hw_scale_->ResetScaleParams(); 1043 memset(&pp_params_, 0, sizeof(pp_params_)); 1044 memset(&igc_lut_data_, 0, sizeof(igc_lut_data_)); 1045 1046 for (size_t i = 0; i < mdp_dest_scalar_data_.size(); i++) { 1047 mdp_dest_scalar_data_[i] = {}; 1048 } 1049 1050 for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) { 1051 mdp_in_layers_[i].buffer.fence = -1; 1052 } 1053 1054 mdp_disp_commit_.version = MDP_COMMIT_VERSION_1_0; 1055 mdp_disp_commit_.commit_v1.input_layers = mdp_in_layers_; 1056 mdp_disp_commit_.commit_v1.output_layer = &mdp_out_layer_; 1057 mdp_disp_commit_.commit_v1.release_fence = -1; 1058 mdp_disp_commit_.commit_v1.retire_fence = -1; 1059 mdp_disp_commit_.commit_v1.dest_scaler = mdp_dest_scalar_data_.data(); 1060 } 1061 1062 void HWDevice::SetCSC(LayerCSC source, mdp_color_space *color_space) { 1063 switch (source) { 1064 case kCSCLimitedRange601: *color_space = MDP_CSC_ITU_R_601; break; 1065 case kCSCFullRange601: *color_space = MDP_CSC_ITU_R_601_FR; break; 1066 case kCSCLimitedRange709: *color_space = MDP_CSC_ITU_R_709; break; 1067 } 1068 } 1069 1070 void HWDevice::SetIGC(const LayerBuffer *layer_buffer, uint32_t index) { 1071 mdp_input_layer &mdp_layer = mdp_in_layers_[index]; 1072 mdp_overlay_pp_params &pp_params = pp_params_[index]; 1073 mdp_igc_lut_data_v1_7 &igc_lut_data = igc_lut_data_[index]; 1074 1075 switch (layer_buffer->igc) { 1076 case kIGCsRGB: 1077 igc_lut_data.table_fmt = mdp_igc_srgb; 1078 pp_params.igc_cfg.ops = MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE; 1079 break; 1080 1081 default: 1082 pp_params.igc_cfg.ops = MDP_PP_OPS_DISABLE; 1083 break; 1084 } 1085 1086 pp_params.config_ops = MDP_OVERLAY_PP_IGC_CFG; 1087 pp_params.igc_cfg.version = mdp_igc_v1_7; 1088 pp_params.igc_cfg.cfg_payload = &igc_lut_data; 1089 1090 mdp_layer.pp_info = &pp_params; 1091 mdp_layer.flags |= MDP_LAYER_PP; 1092 } 1093 1094 DisplayError HWDevice::SetCursorPosition(HWLayers *hw_layers, int x, int y) { 1095 DTRACE_SCOPED(); 1096 1097 HWLayersInfo &hw_layer_info = hw_layers->info; 1098 uint32_t count = hw_layer_info.count; 1099 uint32_t cursor_index = count - 1; 1100 HWPipeInfo *left_pipe = &hw_layers->config[cursor_index].left_pipe; 1101 1102 mdp_async_layer async_layer = {}; 1103 async_layer.flags = MDP_LAYER_ASYNC; 1104 async_layer.pipe_ndx = left_pipe->pipe_id; 1105 async_layer.src.x = UINT32(left_pipe->src_roi.left); 1106 async_layer.src.y = UINT32(left_pipe->src_roi.top); 1107 async_layer.dst.x = UINT32(x); 1108 async_layer.dst.y = UINT32(y); 1109 1110 mdp_position_update pos_update = {}; 1111 pos_update.input_layer_cnt = 1; 1112 pos_update.input_layers = &async_layer; 1113 if (Sys::ioctl_(device_fd_, INT(MSMFB_ASYNC_POSITION_UPDATE), &pos_update) < 0) { 1114 if (errno == ESHUTDOWN) { 1115 DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence"); 1116 return kErrorShutDown; 1117 } 1118 IOCTL_LOGE(MSMFB_ASYNC_POSITION_UPDATE, device_type_); 1119 return kErrorHardware; 1120 } 1121 1122 return kErrorNone; 1123 } 1124 1125 DisplayError HWDevice::GetPPFeaturesVersion(PPFeatureVersion *vers) { 1126 return kErrorNotSupported; 1127 } 1128 1129 DisplayError HWDevice::SetPPFeatures(PPFeaturesConfig *feature_list) { 1130 return kErrorNotSupported; 1131 } 1132 1133 DisplayError HWDevice::SetVSyncState(bool enable) { 1134 int vsync_on = enable ? 1 : 0; 1135 if (Sys::ioctl_(device_fd_, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) < 0) { 1136 if (errno == ESHUTDOWN) { 1137 DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence"); 1138 return kErrorShutDown; 1139 } 1140 IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, device_type_); 1141 return kErrorHardware; 1142 } 1143 return kErrorNone; 1144 } 1145 1146 void HWDevice::SetIdleTimeoutMs(uint32_t timeout_ms) { 1147 } 1148 1149 DisplayError HWDevice::SetDisplayMode(const HWDisplayMode hw_display_mode) { 1150 return kErrorNotSupported; 1151 } 1152 1153 DisplayError HWDevice::SetRefreshRate(uint32_t refresh_rate) { 1154 return kErrorNotSupported; 1155 } 1156 1157 DisplayError HWDevice::SetPanelBrightness(int level) { 1158 return kErrorNotSupported; 1159 } 1160 1161 DisplayError HWDevice::GetHWScanInfo(HWScanInfo *scan_info) { 1162 return kErrorNotSupported; 1163 } 1164 1165 DisplayError HWDevice::GetVideoFormat(uint32_t config_index, uint32_t *video_format) { 1166 return kErrorNotSupported; 1167 } 1168 1169 DisplayError HWDevice::GetMaxCEAFormat(uint32_t *max_cea_format) { 1170 return kErrorNotSupported; 1171 } 1172 1173 DisplayError HWDevice::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) { 1174 return kErrorNotSupported; 1175 } 1176 1177 DisplayError HWDevice::GetPanelBrightness(int *level) { 1178 return kErrorNotSupported; 1179 } 1180 1181 ssize_t HWDevice::SysFsWrite(const char* file_node, const char* value, ssize_t length) { 1182 int fd = Sys::open_(file_node, O_RDWR, 0); 1183 if (fd < 0) { 1184 DLOGW("Open failed = %s", file_node); 1185 return -1; 1186 } 1187 ssize_t len = Sys::pwrite_(fd, value, static_cast<size_t>(length), 0); 1188 if (len <= 0) { 1189 DLOGE("Write failed for path %s with value %s", file_node, value); 1190 } 1191 Sys::close_(fd); 1192 1193 return len; 1194 } 1195 1196 bool HWDevice::IsFBNodeConnected(int fb_node) { 1197 string file_name = fb_path_ + to_string(fb_node) + "/connected"; 1198 1199 Sys::fstream fs(file_name, fstream::in); 1200 if (!fs.is_open()) { 1201 DLOGW("File not found %s", file_name.c_str()); 1202 return false; 1203 } 1204 1205 string line; 1206 if (!Sys::getline_(fs, line)) { 1207 return false; 1208 } 1209 1210 return atoi(line.c_str()); 1211 } 1212 1213 DisplayError HWDevice::SetS3DMode(HWS3DMode s3d_mode) { 1214 return kErrorNotSupported; 1215 } 1216 1217 DisplayError HWDevice::SetScaleLutConfig(HWScaleLutInfo *lut_info) { 1218 mdp_scale_luts_info mdp_lut_info = {}; 1219 mdp_set_cfg cfg = {}; 1220 1221 if (!hw_resource_.has_qseed3) { 1222 DLOGV_IF(kTagDriverConfig, "No support for QSEED3 luts"); 1223 return kErrorNone; 1224 } 1225 1226 if (!lut_info->dir_lut_size && !lut_info->dir_lut && !lut_info->cir_lut_size && 1227 !lut_info->cir_lut && !lut_info->sep_lut_size && !lut_info->sep_lut) { 1228 // HWSupports QSEED3, but LutInfo is invalid as scalar is disabled by property or 1229 // its loading failed. Driver will use default settings/filter 1230 return kErrorNone; 1231 } 1232 1233 mdp_lut_info.dir_lut_size = lut_info->dir_lut_size; 1234 mdp_lut_info.dir_lut = lut_info->dir_lut; 1235 mdp_lut_info.cir_lut_size = lut_info->cir_lut_size; 1236 mdp_lut_info.cir_lut = lut_info->cir_lut; 1237 mdp_lut_info.sep_lut_size = lut_info->sep_lut_size; 1238 mdp_lut_info.sep_lut = lut_info->sep_lut; 1239 1240 cfg.flags = MDP_QSEED3_LUT_CFG; 1241 cfg.len = sizeof(mdp_scale_luts_info); 1242 cfg.payload = reinterpret_cast<uint64_t>(&mdp_lut_info); 1243 1244 if (Sys::ioctl_(device_fd_, MSMFB_MDP_SET_CFG, &cfg) < 0) { 1245 if (errno == ESHUTDOWN) { 1246 DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence"); 1247 return kErrorShutDown; 1248 } 1249 IOCTL_LOGE(MSMFB_MDP_SET_CFG, device_type_); 1250 return kErrorHardware; 1251 } 1252 1253 return kErrorNone; 1254 } 1255 1256 DisplayError HWDevice::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) { 1257 if (!hw_resource_.hw_dest_scalar_info.count) { 1258 return kErrorNotSupported; 1259 } 1260 1261 if (mixer_attributes.width > display_attributes_.x_pixels || 1262 mixer_attributes.height > display_attributes_.y_pixels) { 1263 DLOGW("Input resolution exceeds display resolution! input: res %dx%d display: res %dx%d", 1264 mixer_attributes.width, mixer_attributes.height, display_attributes_.x_pixels, 1265 display_attributes_.y_pixels); 1266 return kErrorNotSupported; 1267 } 1268 1269 uint32_t max_input_width = hw_resource_.hw_dest_scalar_info.max_input_width; 1270 if (display_attributes_.is_device_split) { 1271 max_input_width *= 2; 1272 } 1273 1274 if (mixer_attributes.width > max_input_width) { 1275 DLOGW("Input width exceeds width limit! input_width %d width_limit %d", mixer_attributes.width, 1276 max_input_width); 1277 return kErrorNotSupported; 1278 } 1279 1280 float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height); 1281 float display_aspect_ratio = 1282 FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels); 1283 1284 if (display_aspect_ratio != mixer_aspect_ratio) { 1285 DLOGW("Aspect ratio mismatch! input: res %dx%d display: res %dx%d", mixer_attributes.width, 1286 mixer_attributes.height, display_attributes_.x_pixels, display_attributes_.y_pixels); 1287 return kErrorNotSupported; 1288 } 1289 1290 float scale_x = FLOAT(display_attributes_.x_pixels) / FLOAT(mixer_attributes.width); 1291 float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height); 1292 float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up; 1293 if (scale_x > max_scale_up || scale_y > max_scale_up) { 1294 DLOGW("Up scaling ratio exceeds for destination scalar upscale limit scale_x %f scale_y %f " \ 1295 "max_scale_up %f", scale_x, scale_y, max_scale_up); 1296 return kErrorNotSupported; 1297 } 1298 1299 float mixer_split_ratio = FLOAT(mixer_attributes_.split_left) / FLOAT(mixer_attributes_.width); 1300 1301 mixer_attributes_ = mixer_attributes; 1302 mixer_attributes_.split_left = mixer_attributes_.width; 1303 if (display_attributes_.is_device_split) { 1304 mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio); 1305 } 1306 1307 return kErrorNone; 1308 } 1309 1310 DisplayError HWDevice::GetMixerAttributes(HWMixerAttributes *mixer_attributes) { 1311 if (!mixer_attributes) { 1312 return kErrorParameters; 1313 } 1314 1315 *mixer_attributes = mixer_attributes_; 1316 1317 return kErrorNone; 1318 } 1319 1320 } // namespace sdm 1321 1322