1 /* 2 * Copyright (c) 2017, The Linux Foundation. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 13 * * Neither the name of The Linux Foundation nor the names of its 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <dlfcn.h> 31 #include <drm/drm_fourcc.h> 32 #include <drm_lib_loader.h> 33 #include <drm_master.h> 34 #include <drm_res_mgr.h> 35 #include <fcntl.h> 36 #include <media/msm_sde_rotator.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <sys/stat.h> 41 #include <sys/types.h> 42 #include <utils/constants.h> 43 #include <utils/debug.h> 44 #include <utils/sys.h> 45 46 #include <algorithm> 47 #include <fstream> 48 #include <iostream> 49 #include <map> 50 #include <memory> 51 #include <string> 52 #include <utility> 53 #include <vector> 54 55 #include "hw_info_drm.h" 56 57 #ifndef DRM_FORMAT_MOD_QCOM_COMPRESSED 58 #define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1) 59 #endif 60 #ifndef DRM_FORMAT_MOD_QCOM_DX 61 #define DRM_FORMAT_MOD_QCOM_DX fourcc_mod_code(QCOM, 0x2) 62 #endif 63 #ifndef DRM_FORMAT_MOD_QCOM_TIGHT 64 #define DRM_FORMAT_MOD_QCOM_TIGHT fourcc_mod_code(QCOM, 0x4) 65 #endif 66 67 #define __CLASS__ "HWInfoDRM" 68 69 using drm_utils::DRMMaster; 70 using drm_utils::DRMResMgr; 71 using drm_utils::DRMLogger; 72 using drm_utils::DRMLibLoader; 73 using sde_drm::GetDRMManager; 74 using sde_drm::DRMPlanesInfo; 75 using sde_drm::DRMCrtcInfo; 76 using sde_drm::DRMPlaneType; 77 78 using std::vector; 79 using std::map; 80 using std::string; 81 using std::fstream; 82 using std::to_string; 83 84 namespace sdm { 85 86 class DRMLoggerImpl : public DRMLogger { 87 public: 88 #define PRINTLOG(tag, method, format, buf) \ 89 va_list list; \ 90 va_start(list, format); \ 91 vsnprintf(buf, sizeof(buf), format, list); \ 92 va_end(list); \ 93 Debug::Get()->method(tag, "%s", buf); 94 95 void Error(const char *format, ...) { PRINTLOG(kTagNone, Error, format, buf_); } 96 void Warning(const char *format, ...) { PRINTLOG(kTagDriverConfig, Warning, format, buf_); } 97 void Info(const char *format, ...) { PRINTLOG(kTagDriverConfig, Info, format, buf_); } 98 void Debug(const char *format, ...) { PRINTLOG(kTagDriverConfig, Debug, format, buf_); } 99 void Verbose(const char *format, ...) { PRINTLOG(kTagDriverConfig, Verbose, format, buf_); } 100 101 private: 102 char buf_[1024] = {}; 103 }; 104 105 HWResourceInfo *HWInfoDRM::hw_resource_ = nullptr; 106 107 HWInfoDRM::HWInfoDRM() { 108 DRMLogger::Set(new DRMLoggerImpl()); 109 drm_lib = DRMLibLoader::GetInstance(); 110 if (drm_lib == nullptr) { 111 DLOGE("Failed to load DRM Library"); 112 return; 113 } 114 default_mode_ = (drm_lib->IsLoaded() == false); 115 if (!default_mode_) { 116 DRMMaster *drm_master = {}; 117 int dev_fd = -1; 118 DRMMaster::GetInstance(&drm_master); 119 if (!drm_master) { 120 DLOGE("Failed to acquire DRMMaster instance"); 121 return; 122 } 123 drm_master->GetHandle(&dev_fd); 124 drm_lib->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_); 125 } 126 } 127 128 HWInfoDRM::~HWInfoDRM() { 129 if (hw_resource_ != nullptr) { 130 delete hw_resource_; 131 hw_resource_ = nullptr; 132 } 133 134 if (drm_mgr_intf_) { 135 if (drm_lib != nullptr) { 136 drm_lib->FuncDestroyDRMManager()(); 137 } 138 drm_mgr_intf_ = nullptr; 139 } 140 141 drm_lib->Destroy(); 142 drm_lib = nullptr; 143 DRMMaster::DestroyInstance(); 144 } 145 146 DisplayError HWInfoDRM::GetDynamicBWLimits(HWResourceInfo *hw_resource) { 147 HWDynBwLimitInfo* bw_info = &hw_resource->dyn_bw_info; 148 for (int index = 0; index < kBwModeMax; index++) { 149 bw_info->total_bw_limit[index] = UINT32(hw_resource->max_bandwidth_low); 150 bw_info->pipe_bw_limit[index] = hw_resource->max_pipe_bw; 151 } 152 153 return kErrorNone; 154 } 155 156 DisplayError HWInfoDRM::GetHWResourceInfo(HWResourceInfo *hw_resource) { 157 if (hw_resource_) { 158 *hw_resource = *hw_resource_; 159 return kErrorNone; 160 } 161 162 hw_resource->num_blending_stages = 1; 163 hw_resource->max_pipe_width = 2560; 164 hw_resource->max_cursor_size = 128; 165 hw_resource->max_scale_down = 1; 166 hw_resource->max_scale_up = 1; 167 hw_resource->has_decimation = false; 168 hw_resource->max_bandwidth_low = 9600000; 169 hw_resource->max_bandwidth_high = 9600000; 170 hw_resource->max_pipe_bw = 4500000; 171 hw_resource->max_sde_clk = 412500000; 172 hw_resource->clk_fudge_factor = FLOAT(105) / FLOAT(100); 173 hw_resource->macrotile_nv12_factor = 8; 174 hw_resource->macrotile_factor = 4; 175 hw_resource->linear_factor = 1; 176 hw_resource->scale_factor = 1; 177 hw_resource->extra_fudge_factor = 2; 178 hw_resource->amortizable_threshold = 0; 179 hw_resource->system_overhead_lines = 0; 180 hw_resource->hw_dest_scalar_info.count = 0; 181 hw_resource->hw_dest_scalar_info.max_scale_up = 0; 182 hw_resource->hw_dest_scalar_info.max_input_width = 0; 183 hw_resource->hw_dest_scalar_info.max_output_width = 0; 184 hw_resource->is_src_split = true; 185 hw_resource->perf_calc = false; 186 hw_resource->has_dyn_bw_support = false; 187 hw_resource->has_qseed3 = false; 188 hw_resource->has_concurrent_writeback = false; 189 190 // TODO(user): Deprecate 191 hw_resource->hw_version = kHWMdssVersion5; 192 hw_resource->hw_revision = 0; 193 hw_resource->max_mixer_width = 0; 194 hw_resource->writeback_index = 0; 195 hw_resource->has_bwc = false; 196 hw_resource->has_ubwc = true; 197 hw_resource->has_macrotile = true; 198 hw_resource->separate_rotator = true; 199 hw_resource->has_non_scalar_rgb = false; 200 201 GetSystemInfo(hw_resource); 202 GetHWPlanesInfo(hw_resource); 203 GetWBInfo(hw_resource); 204 205 // Disable destination scalar count to 0 if extension library is not present 206 DynLib extension_lib; 207 if (!extension_lib.Open("libsdmextension.so")) { 208 hw_resource->hw_dest_scalar_info.count = 0; 209 } 210 211 DLOGI("Max plane width = %d", hw_resource->max_pipe_width); 212 DLOGI("Max cursor width = %d", hw_resource->max_cursor_size); 213 DLOGI("Max plane upscale = %d", hw_resource->max_scale_up); 214 DLOGI("Max plane downscale = %d", hw_resource->max_scale_down); 215 DLOGI("Has Decimation = %d", hw_resource->has_decimation); 216 DLOGI("Max Blending Stages = %d", hw_resource->num_blending_stages); 217 DLOGI("Has Source Split = %d", hw_resource->is_src_split); 218 DLOGI("Has QSEED3 = %d", hw_resource->has_qseed3); 219 DLOGI("Has UBWC = %d", hw_resource->has_ubwc); 220 DLOGI("Has Concurrent Writeback = %d", hw_resource->has_concurrent_writeback); 221 DLOGI("Max Low Bw = %" PRIu64 "", hw_resource->max_bandwidth_low); 222 DLOGI("Max High Bw = % " PRIu64 "", hw_resource->max_bandwidth_high); 223 DLOGI("Max Pipe Bw = %" PRIu64 " KBps", hw_resource->max_pipe_bw); 224 DLOGI("MaxSDEClock = % " PRIu64 " Hz", hw_resource->max_sde_clk); 225 DLOGI("Clock Fudge Factor = %f", hw_resource->clk_fudge_factor); 226 DLOGI("Prefill factors:"); 227 DLOGI("\tTiled_NV12 = %d", hw_resource->macrotile_nv12_factor); 228 DLOGI("\tTiled = %d", hw_resource->macrotile_factor); 229 DLOGI("\tLinear = %d", hw_resource->linear_factor); 230 DLOGI("\tScale = %d", hw_resource->scale_factor); 231 DLOGI("\tFudge_factor = %d", hw_resource->extra_fudge_factor); 232 233 if (hw_resource->separate_rotator || hw_resource->num_dma_pipe) { 234 GetHWRotatorInfo(hw_resource); 235 } 236 237 if (hw_resource->has_dyn_bw_support) { 238 DisplayError ret = GetDynamicBWLimits(hw_resource); 239 if (ret != kErrorNone) { 240 DLOGE("Failed to read dynamic band width info"); 241 return ret; 242 } 243 244 DLOGI("Has Support for multiple bw limits shown below"); 245 for (int index = 0; index < kBwModeMax; index++) { 246 DLOGI("Mode-index=%d total_bw_limit=%d and pipe_bw_limit=%d", index, 247 hw_resource->dyn_bw_info.total_bw_limit[index], 248 hw_resource->dyn_bw_info.pipe_bw_limit[index]); 249 } 250 } 251 252 if (!hw_resource_) { 253 hw_resource_ = new HWResourceInfo(); 254 *hw_resource_ = *hw_resource; 255 } 256 257 return kErrorNone; 258 } 259 260 void HWInfoDRM::GetSystemInfo(HWResourceInfo *hw_resource) { 261 DRMCrtcInfo info; 262 drm_mgr_intf_->GetCrtcInfo(0 /* system_info */, &info); 263 hw_resource->is_src_split = info.has_src_split; 264 hw_resource->has_qseed3 = (info.qseed_version == sde_drm::QSEEDVersion::V3); 265 hw_resource->num_blending_stages = info.max_blend_stages; 266 hw_resource->smart_dma_rev = (info.smart_dma_rev == sde_drm::SmartDMARevision::V2) ? 267 SmartDMARevision::V2 : SmartDMARevision::V1; 268 } 269 270 void HWInfoDRM::GetHWPlanesInfo(HWResourceInfo *hw_resource) { 271 DRMPlanesInfo planes; 272 drm_mgr_intf_->GetPlanesInfo(&planes); 273 for (auto &pipe_obj : planes) { 274 HWPipeCaps pipe_caps; 275 string name = {}; 276 switch (pipe_obj.second.type) { 277 case DRMPlaneType::DMA: 278 name = "DMA"; 279 pipe_caps.type = kPipeTypeDMA; 280 if (!hw_resource->num_dma_pipe) { 281 PopulateSupportedFmts(kHWDMAPipe, pipe_obj.second, hw_resource); 282 } 283 hw_resource->num_dma_pipe++; 284 break; 285 case DRMPlaneType::VIG: 286 name = "VIG"; 287 pipe_caps.type = kPipeTypeVIG; 288 if (!hw_resource->num_vig_pipe) { 289 PopulatePipeCaps(pipe_obj.second, hw_resource); 290 PopulateSupportedFmts(kHWVIGPipe, pipe_obj.second, hw_resource); 291 } 292 hw_resource->num_vig_pipe++; 293 break; 294 case DRMPlaneType::CURSOR: 295 name = "CURSOR"; 296 pipe_caps.type = kPipeTypeCursor; 297 if (!hw_resource->num_cursor_pipe) { 298 PopulateSupportedFmts(kHWCursorPipe, pipe_obj.second, hw_resource); 299 hw_resource->max_cursor_size = pipe_obj.second.max_linewidth; 300 } 301 hw_resource->num_cursor_pipe++; 302 break; 303 default: 304 continue; // Not adding any other pipe type 305 } 306 pipe_caps.id = pipe_obj.first; 307 pipe_caps.master_pipe_id = pipe_obj.second.master_plane_id; 308 DLOGI("Adding %s Pipe : Id %d", name.c_str(), pipe_obj.first); 309 hw_resource->hw_pipes.push_back(std::move(pipe_caps)); 310 } 311 } 312 313 void HWInfoDRM::PopulatePipeCaps(const sde_drm::DRMPlaneTypeInfo &info, 314 HWResourceInfo *hw_resource) { 315 hw_resource->max_pipe_width = info.max_linewidth; 316 hw_resource->max_scale_down = info.max_downscale; 317 hw_resource->max_scale_up = info.max_upscale; 318 hw_resource->has_decimation = info.max_horizontal_deci > 1 && info.max_vertical_deci > 1; 319 } 320 321 void HWInfoDRM::PopulateSupportedFmts(HWSubBlockType sub_blk_type, 322 const sde_drm::DRMPlaneTypeInfo &info, 323 HWResourceInfo *hw_resource) { 324 vector<LayerBufferFormat> sdm_formats; 325 FormatsMap &fmts_map = hw_resource->supported_formats_map; 326 327 if (fmts_map.find(sub_blk_type) == fmts_map.end()) { 328 for (auto &fmts : info.formats_supported) { 329 GetSDMFormat(fmts.first, fmts.second, &sdm_formats); 330 } 331 332 fmts_map.insert(make_pair(sub_blk_type, sdm_formats)); 333 } 334 } 335 336 void HWInfoDRM::GetWBInfo(HWResourceInfo *hw_resource) { 337 HWSubBlockType sub_blk_type = kHWWBIntfOutput; 338 vector<LayerBufferFormat> supported_sdm_formats; 339 sde_drm::DRMDisplayToken token; 340 341 // Fake register 342 if (drm_mgr_intf_->RegisterDisplay(sde_drm::DRMDisplayType::VIRTUAL, &token)) { 343 return; 344 } 345 346 sde_drm::DRMConnectorInfo connector_info; 347 drm_mgr_intf_->GetConnectorInfo(token.conn_id, &connector_info); 348 for (auto &fmts : connector_info.formats_supported) { 349 GetSDMFormat(fmts.first, fmts.second, &supported_sdm_formats); 350 } 351 352 hw_resource->supported_formats_map.erase(sub_blk_type); 353 hw_resource->supported_formats_map.insert(make_pair(sub_blk_type, supported_sdm_formats)); 354 355 drm_mgr_intf_->UnregisterDisplay(token); 356 } 357 358 void HWInfoDRM::GetSDMFormat(uint32_t v4l2_format, LayerBufferFormat *sdm_format) { 359 switch (v4l2_format) { 360 case SDE_PIX_FMT_ARGB_8888: *sdm_format = kFormatARGB8888; break; 361 case SDE_PIX_FMT_RGBA_8888: *sdm_format = kFormatRGBA8888; break; 362 case SDE_PIX_FMT_BGRA_8888: *sdm_format = kFormatBGRA8888; break; 363 case SDE_PIX_FMT_RGBX_8888: *sdm_format = kFormatRGBX8888; break; 364 case SDE_PIX_FMT_BGRX_8888: *sdm_format = kFormatBGRX8888; break; 365 case SDE_PIX_FMT_RGBA_5551: *sdm_format = kFormatRGBA5551; break; 366 case SDE_PIX_FMT_RGBA_4444: *sdm_format = kFormatRGBA4444; break; 367 case SDE_PIX_FMT_RGB_888: *sdm_format = kFormatRGB888; break; 368 case SDE_PIX_FMT_BGR_888: *sdm_format = kFormatBGR888; break; 369 case SDE_PIX_FMT_RGB_565: *sdm_format = kFormatRGB565; break; 370 case SDE_PIX_FMT_BGR_565: *sdm_format = kFormatBGR565; break; 371 case SDE_PIX_FMT_Y_CB_CR_H2V2: *sdm_format = kFormatYCbCr420Planar; break; 372 case SDE_PIX_FMT_Y_CR_CB_H2V2: *sdm_format = kFormatYCrCb420Planar; break; 373 case SDE_PIX_FMT_Y_CR_CB_GH2V2: *sdm_format = kFormatYCrCb420PlanarStride16; break; 374 case SDE_PIX_FMT_Y_CBCR_H2V2: *sdm_format = kFormatYCbCr420SemiPlanar; break; 375 case SDE_PIX_FMT_Y_CRCB_H2V2: *sdm_format = kFormatYCrCb420SemiPlanar; break; 376 case SDE_PIX_FMT_Y_CBCR_H1V2: *sdm_format = kFormatYCbCr422H1V2SemiPlanar; break; 377 case SDE_PIX_FMT_Y_CRCB_H1V2: *sdm_format = kFormatYCrCb422H1V2SemiPlanar; break; 378 case SDE_PIX_FMT_Y_CBCR_H2V1: *sdm_format = kFormatYCbCr422H2V1SemiPlanar; break; 379 case SDE_PIX_FMT_Y_CRCB_H2V1: *sdm_format = kFormatYCrCb422H2V1SemiPlanar; break; 380 case SDE_PIX_FMT_YCBYCR_H2V1: *sdm_format = kFormatYCbCr422H2V1Packed; break; 381 case SDE_PIX_FMT_Y_CBCR_H2V2_VENUS: *sdm_format = kFormatYCbCr420SemiPlanarVenus; break; 382 case SDE_PIX_FMT_Y_CRCB_H2V2_VENUS: *sdm_format = kFormatYCrCb420SemiPlanarVenus; break; 383 case SDE_PIX_FMT_RGBA_8888_UBWC: *sdm_format = kFormatRGBA8888Ubwc; break; 384 case SDE_PIX_FMT_RGBX_8888_UBWC: *sdm_format = kFormatRGBX8888Ubwc; break; 385 case SDE_PIX_FMT_RGB_565_UBWC: *sdm_format = kFormatBGR565Ubwc; break; 386 case SDE_PIX_FMT_Y_CBCR_H2V2_UBWC: *sdm_format = kFormatYCbCr420SPVenusUbwc; break; 387 case SDE_PIX_FMT_RGBA_1010102: *sdm_format = kFormatRGBA1010102; break; 388 case SDE_PIX_FMT_ARGB_2101010: *sdm_format = kFormatARGB2101010; break; 389 case SDE_PIX_FMT_RGBX_1010102: *sdm_format = kFormatRGBX1010102; break; 390 case SDE_PIX_FMT_XRGB_2101010: *sdm_format = kFormatXRGB2101010; break; 391 case SDE_PIX_FMT_BGRA_1010102: *sdm_format = kFormatBGRA1010102; break; 392 case SDE_PIX_FMT_ABGR_2101010: *sdm_format = kFormatABGR2101010; break; 393 case SDE_PIX_FMT_BGRX_1010102: *sdm_format = kFormatBGRX1010102; break; 394 case SDE_PIX_FMT_XBGR_2101010: *sdm_format = kFormatXBGR2101010; break; 395 case SDE_PIX_FMT_RGBA_1010102_UBWC: *sdm_format = kFormatRGBA1010102Ubwc; break; 396 case SDE_PIX_FMT_RGBX_1010102_UBWC: *sdm_format = kFormatRGBX1010102Ubwc; break; 397 case SDE_PIX_FMT_Y_CBCR_H2V2_P010: *sdm_format = kFormatYCbCr420P010; break; 398 case SDE_PIX_FMT_Y_CBCR_H2V2_TP10_UBWC: *sdm_format = kFormatYCbCr420TP10Ubwc; break; 399 /* TODO(user) : enable when defined in uapi 400 case SDE_PIX_FMT_Y_CBCR_H2V2_P010_UBWC: *sdm_format = kFormatYCbCr420P010Ubwc; break; */ 401 default: *sdm_format = kFormatInvalid; 402 } 403 } 404 405 void HWInfoDRM::GetRotatorFormatsForType(int fd, uint32_t type, 406 vector<LayerBufferFormat> *supported_formats) { 407 struct v4l2_fmtdesc fmtdesc = {}; 408 fmtdesc.type = type; 409 while (!Sys::ioctl_(fd, static_cast<int>(VIDIOC_ENUM_FMT), &fmtdesc)) { 410 LayerBufferFormat sdm_format = kFormatInvalid; 411 GetSDMFormat(fmtdesc.pixelformat, &sdm_format); 412 if (sdm_format != kFormatInvalid) { 413 supported_formats->push_back(sdm_format); 414 } 415 fmtdesc.index++; 416 } 417 } 418 419 DisplayError HWInfoDRM::GetRotatorSupportedFormats(uint32_t v4l2_index, 420 HWResourceInfo *hw_resource) { 421 string path = "/dev/video" + to_string(v4l2_index); 422 int fd = Sys::open_(path.c_str(), O_RDONLY); 423 if (fd < 0) { 424 DLOGE("Failed to open %s with error %d", path.c_str(), errno); 425 return kErrorNotSupported; 426 } 427 428 vector<LayerBufferFormat> supported_formats = {}; 429 GetRotatorFormatsForType(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT, &supported_formats); 430 hw_resource->supported_formats_map.erase(kHWRotatorInput); 431 hw_resource->supported_formats_map.insert(make_pair(kHWRotatorInput, supported_formats)); 432 433 supported_formats = {}; 434 GetRotatorFormatsForType(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, &supported_formats); 435 hw_resource->supported_formats_map.erase(kHWRotatorOutput); 436 hw_resource->supported_formats_map.insert(make_pair(kHWRotatorOutput, supported_formats)); 437 438 Sys::close_(fd); 439 440 return kErrorNone; 441 } 442 443 DisplayError HWInfoDRM::GetHWRotatorInfo(HWResourceInfo *hw_resource) { 444 string v4l2_path = "/sys/class/video4linux/video"; 445 const uint32_t kMaxV4L2Nodes = 64; 446 447 for (uint32_t i = 0; i < kMaxV4L2Nodes; i++) { 448 string path = v4l2_path + to_string(i) + "/name"; 449 Sys::fstream fs(path, fstream::in); 450 if (!fs.is_open()) { 451 continue; 452 } 453 454 string line; 455 if (Sys::getline_(fs, line) && (!strncmp(line.c_str(), "sde_rotator", strlen("sde_rotator")))) { 456 hw_resource->hw_rot_info.device_path = string("/dev/video" + to_string(i)); 457 hw_resource->hw_rot_info.num_rotator++; 458 hw_resource->hw_rot_info.type = HWRotatorInfo::ROT_TYPE_V4L2; 459 hw_resource->hw_rot_info.has_downscale = true; 460 GetRotatorSupportedFormats(i, hw_resource); 461 462 string caps_path = v4l2_path + to_string(i) + "/device/caps"; 463 Sys::fstream caps_fs(caps_path, fstream::in); 464 465 if (caps_fs.is_open()) { 466 string caps; 467 while (Sys::getline_(caps_fs, caps)) { 468 const string downscale_compression = "downscale_compression="; 469 const string min_downscale = "min_downscale="; 470 if (caps.find(downscale_compression) != string::npos) { 471 hw_resource->hw_rot_info.downscale_compression = 472 std::stoi(string(caps, downscale_compression.length())); 473 } else if (caps.find(min_downscale) != string::npos) { 474 hw_resource->hw_rot_info.min_downscale = 475 std::stof(string(caps, min_downscale.length())); 476 } 477 } 478 } 479 480 // We support only 1 rotator 481 break; 482 } 483 } 484 485 DLOGI("V4L2 Rotator: Count = %d, Downscale = %d, Min_downscale = %f, Downscale_compression = %d", 486 hw_resource->hw_rot_info.num_rotator, hw_resource->hw_rot_info.has_downscale, 487 hw_resource->hw_rot_info.min_downscale, hw_resource->hw_rot_info.downscale_compression); 488 489 return kErrorNone; 490 } 491 492 void HWInfoDRM::GetSDMFormat(uint32_t drm_format, uint64_t drm_format_modifier, 493 vector<LayerBufferFormat> *sdm_formats) { 494 vector<LayerBufferFormat> &fmts(*sdm_formats); 495 switch (drm_format) { 496 case DRM_FORMAT_BGRA8888: 497 fmts.push_back(kFormatARGB8888); 498 break; 499 case DRM_FORMAT_ABGR8888: 500 fmts.push_back(drm_format_modifier ? kFormatRGBA8888Ubwc : kFormatRGBA8888); 501 break; 502 case DRM_FORMAT_ARGB8888: 503 fmts.push_back(kFormatBGRA8888); 504 break; 505 case DRM_FORMAT_BGRX8888: 506 fmts.push_back(kFormatXRGB8888); 507 break; 508 case DRM_FORMAT_XBGR8888: 509 fmts.push_back(drm_format_modifier ? kFormatRGBX8888Ubwc : kFormatRGBX8888); 510 break; 511 case DRM_FORMAT_XRGB8888: 512 fmts.push_back(kFormatBGRX8888); 513 break; 514 case DRM_FORMAT_ABGR1555: 515 fmts.push_back(kFormatRGBA5551); 516 break; 517 case DRM_FORMAT_ABGR4444: 518 fmts.push_back(kFormatRGBA4444); 519 break; 520 case DRM_FORMAT_BGR888: 521 fmts.push_back(kFormatRGB888); 522 break; 523 case DRM_FORMAT_RGB888: 524 fmts.push_back(kFormatBGR888); 525 break; 526 case DRM_FORMAT_BGR565: 527 fmts.push_back(drm_format_modifier ? kFormatBGR565Ubwc : kFormatRGB565); 528 break; 529 case DRM_FORMAT_RGB565: 530 fmts.push_back(kFormatBGR565); 531 break; 532 case DRM_FORMAT_ABGR2101010: 533 fmts.push_back(drm_format_modifier ? kFormatRGBA1010102Ubwc : kFormatRGBA1010102); 534 break; 535 case DRM_FORMAT_BGRA1010102: 536 fmts.push_back(kFormatARGB2101010); 537 break; 538 case DRM_FORMAT_XBGR2101010: 539 fmts.push_back(drm_format_modifier ? kFormatRGBX1010102Ubwc : kFormatRGBX1010102); 540 break; 541 case DRM_FORMAT_BGRX1010102: 542 fmts.push_back(kFormatXRGB2101010); 543 break; 544 case DRM_FORMAT_ARGB2101010: 545 fmts.push_back(kFormatBGRA1010102); 546 break; 547 case DRM_FORMAT_RGBA1010102: 548 fmts.push_back(kFormatABGR2101010); 549 break; 550 case DRM_FORMAT_XRGB2101010: 551 fmts.push_back(kFormatBGRX1010102); 552 break; 553 case DRM_FORMAT_RGBX1010102: 554 fmts.push_back(kFormatXBGR2101010); 555 break; 556 case DRM_FORMAT_YVU420: 557 fmts.push_back(kFormatYCrCb420PlanarStride16); 558 break; 559 case DRM_FORMAT_NV12: 560 if (drm_format_modifier == (DRM_FORMAT_MOD_QCOM_COMPRESSED | 561 DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_TIGHT)) { 562 fmts.push_back(kFormatYCbCr420TP10Ubwc); 563 } else if (drm_format_modifier == (DRM_FORMAT_MOD_QCOM_COMPRESSED | 564 DRM_FORMAT_MOD_QCOM_DX)) { 565 fmts.push_back(kFormatYCbCr420P010Ubwc); 566 } else if (drm_format_modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED) { 567 fmts.push_back(kFormatYCbCr420SPVenusUbwc); 568 } else if (drm_format_modifier == DRM_FORMAT_MOD_QCOM_DX) { 569 fmts.push_back(kFormatYCbCr420P010); 570 } else { 571 fmts.push_back(kFormatYCbCr420SemiPlanarVenus); 572 fmts.push_back(kFormatYCbCr420SemiPlanar); 573 } 574 break; 575 case DRM_FORMAT_NV21: 576 fmts.push_back(kFormatYCrCb420SemiPlanarVenus); 577 fmts.push_back(kFormatYCrCb420SemiPlanar); 578 break; 579 case DRM_FORMAT_NV16: 580 fmts.push_back(kFormatYCbCr422H2V1SemiPlanar); 581 break; 582 default: 583 break; 584 } 585 } 586 587 DisplayError HWInfoDRM::GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) { 588 hw_disp_info->type = kPrimary; 589 hw_disp_info->is_connected = true; 590 591 return kErrorNone; 592 } 593 594 } // namespace sdm 595