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