1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "drm_device.h" 17 #include <string> 18 #include <cerrno> 19 #include <fcntl.h> 20 #include <memory> 21 #include <drm_fourcc.h> 22 #include "display_common.h" 23 #include "drm_display.h" 24 25 namespace OHOS { 26 namespace HDI { 27 namespace DISPLAY { 28 FdPtr DrmDevice::mDrmFd = nullptr; 29 std::shared_ptr<DrmDevice> DrmDevice::mInstance; 30 Create()31 std::shared_ptr<HdiDeviceInterface> DrmDevice::Create() 32 { 33 DISPLAY_DEBUGLOG(); 34 if (mDrmFd == nullptr) { 35 const std::string name("rockchip"); 36 int drmFd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC); // drmOpen(name.c_str(), nullptr); 37 if (drmFd < 0) { 38 DISPLAY_LOGE("drm file:%{public}s open failed %{public}s", name.c_str(), strerror(errno)); 39 return nullptr; 40 } 41 DISPLAY_DEBUGLOG("the drm fd is %{public}d", drmFd); 42 mDrmFd = std::make_shared<HdiSharedFd>(drmFd); 43 } 44 if (mInstance == nullptr) { 45 mInstance = std::make_shared<DrmDevice>(); 46 } 47 return mInstance; 48 } 49 GetDrmFd()50 int DrmDevice::GetDrmFd() 51 { 52 if (mDrmFd == nullptr) { 53 DISPLAY_LOGE("the drmfd is null not open"); 54 return -1; 55 } 56 return mDrmFd->GetFd(); 57 } 58 59 using PixelFormatConvertTbl = struct PixFmtConvertTbl { 60 uint32_t drmFormat; 61 PixelFormat pixFormat; 62 }; 63 ConvertToDrmFormat(PixelFormat fmtIn)64 uint32_t DrmDevice::ConvertToDrmFormat(PixelFormat fmtIn) 65 { 66 static const PixelFormatConvertTbl convertTable[] = { 67 {DRM_FORMAT_XBGR8888, PIXEL_FMT_RGBX_8888}, {DRM_FORMAT_ABGR8888, PIXEL_FMT_RGBA_8888}, 68 {DRM_FORMAT_RGB888, PIXEL_FMT_RGB_888}, {DRM_FORMAT_RGB565, PIXEL_FMT_BGR_565}, 69 {DRM_FORMAT_BGRX4444, PIXEL_FMT_BGRX_4444}, {DRM_FORMAT_BGRA4444, PIXEL_FMT_BGRA_4444}, 70 {DRM_FORMAT_RGBA4444, PIXEL_FMT_RGBA_4444}, {DRM_FORMAT_RGBX4444, PIXEL_FMT_RGBX_4444}, 71 {DRM_FORMAT_BGRX5551, PIXEL_FMT_BGRX_5551}, {DRM_FORMAT_BGRA5551, PIXEL_FMT_BGRA_5551}, 72 {DRM_FORMAT_BGRX8888, PIXEL_FMT_BGRX_8888}, {DRM_FORMAT_ARGB8888, PIXEL_FMT_BGRA_8888}, 73 {DRM_FORMAT_NV12, PIXEL_FMT_YCBCR_420_SP}, {DRM_FORMAT_NV21, PIXEL_FMT_YCRCB_420_SP}, 74 {DRM_FORMAT_YUV420, PIXEL_FMT_YCBCR_420_P}, {DRM_FORMAT_YVU420, PIXEL_FMT_YCRCB_420_P}, 75 {DRM_FORMAT_NV16, PIXEL_FMT_YCBCR_422_SP}, {DRM_FORMAT_NV61, PIXEL_FMT_YCRCB_422_SP}, 76 {DRM_FORMAT_YUV422, PIXEL_FMT_YCBCR_422_P}, {DRM_FORMAT_YVU422, PIXEL_FMT_YCRCB_422_P}, 77 }; 78 uint32_t fmtOut = 0; 79 for (uint32_t i = 0; i < sizeof(convertTable) / sizeof(convertTable[0]); i++) { 80 if (convertTable[i].pixFormat == fmtIn) { 81 fmtOut = convertTable[i].drmFormat; 82 } 83 } 84 DISPLAY_DEBUGLOG("fmtIn %{public}d, outFmt %{public}d", fmtIn, fmtOut); 85 return fmtOut; 86 } 87 DrmDevice()88 DrmDevice::DrmDevice() 89 { 90 } 91 GetCrtcProperty(const DrmCrtc & crtc,const std::string & name,DrmProperty & prop)92 int32_t DrmDevice::GetCrtcProperty(const DrmCrtc &crtc, const std::string &name, DrmProperty &prop) 93 { 94 return GetProperty(crtc.GetId(), DRM_MODE_OBJECT_CRTC, name, prop); 95 } 96 GetConnectorProperty(const DrmConnector & connector,const std::string & name,DrmProperty & prop)97 int32_t DrmDevice::GetConnectorProperty(const DrmConnector &connector, const std::string &name, 98 DrmProperty &prop) 99 { 100 return GetProperty(connector.GetId(), DRM_MODE_OBJECT_CONNECTOR, name, prop); 101 } 102 GetPlaneProperty(const DrmPlane & plane,const std::string & name,DrmProperty & prop)103 int32_t DrmDevice::GetPlaneProperty(const DrmPlane &plane, const std::string &name, DrmProperty &prop) 104 { 105 return GetProperty(plane.GetId(), DRM_MODE_OBJECT_PLANE, name, prop); 106 } 107 GetProperty(uint32_t objId,uint32_t objType,const std::string & name,DrmProperty & prop)108 int32_t DrmDevice::GetProperty(uint32_t objId, uint32_t objType, const std::string &name, DrmProperty &prop) 109 { 110 drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(GetDrmFd(), objId, objType); 111 DISPLAY_CHK_RETURN((!props), DISPLAY_FAILURE, DISPLAY_LOGE("can not get properties")); 112 bool found = false; 113 for (uint32_t i = 0; i < props->count_props; i++) { 114 drmModePropertyPtr p = drmModeGetProperty(GetDrmFd(), props->props[i]); 115 if (strcmp(p->name, name.c_str()) == 0) { 116 found = true; 117 prop.propId = p->prop_id; 118 prop.value = props->prop_values[i]; 119 prop.name = p->name; 120 prop.flags = p->flags; 121 122 for (int i = 0; i < p->count_values; ++i) { 123 prop.values.push_back(p->values[i]); 124 } 125 for (int i = 0; i < p->count_enums; ++i) { 126 prop.enums.push_back(DrmPropertyEnum(&p->enums[i])); 127 } 128 129 for (int i = 0; i < p->count_blobs; ++i) { 130 prop.blob_ids.push_back(p->blob_ids[i]); 131 } 132 if (prop.flags & DRM_MODE_PROP_RANGE) { 133 prop.type = static_cast<uint32_t>(DrmPropertyType::DRM_PROPERTY_TYPE_INT); 134 } else if (prop.flags & DRM_MODE_PROP_ENUM) { 135 prop.type = static_cast<uint32_t>(DrmPropertyType::DRM_PROPERTY_TYPE_ENUM); 136 } else if (prop.flags & DRM_MODE_PROP_OBJECT) { 137 prop.type = static_cast<uint32_t>(DrmPropertyType::DRM_PROPERTY_TYPE_OBJECT); 138 } else if (prop.flags & DRM_MODE_PROP_BLOB) { 139 prop.type = static_cast<uint32_t>(DrmPropertyType::DRM_PROPERTY_TYPE_BLOB); 140 } else if (prop.flags & DRM_MODE_PROP_BITMASK) { 141 prop.type = static_cast<uint32_t>(DrmPropertyType::DRM_PROPERTY_TYPE_BITMASK); 142 } 143 } 144 drmModeFreeProperty(p); 145 } 146 drmModeFreeObjectProperties(props); 147 return found ? DISPLAY_SUCCESS : DISPLAY_NOT_SUPPORT; 148 } 149 Init()150 int32_t DrmDevice::Init() 151 { 152 int ret = drmSetClientCap(GetDrmFd(), DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); 153 DISPLAY_CHK_RETURN( 154 (ret), DISPLAY_FAILURE, 155 DISPLAY_LOGE("DRM_CLIENT_CAP_UNIVERSAL_PLANES set failed %{public}s", strerror(errno))); 156 ret = drmSetClientCap(GetDrmFd(), DRM_CLIENT_CAP_ATOMIC, 1); 157 DISPLAY_CHK_RETURN((ret), DISPLAY_FAILURE, 158 DISPLAY_LOGE("DRM_CLIENT_CAP_ATOMIC set failed %{public}s", strerror(errno))); 159 160 ret = drmSetMaster(GetDrmFd()); 161 DISPLAY_CHK_RETURN((ret), DISPLAY_FAILURE, 162 DISPLAY_LOGE("can not set to master errno : %{public}d", errno)); 163 DISPLAY_LOGE("chenyf master"); 164 ret = drmIsMaster(GetDrmFd()); 165 DISPLAY_CHK_RETURN((!ret), DISPLAY_FAILURE, DISPLAY_LOGE("is not master : %{public}d", errno)); 166 167 return DISPLAY_SUCCESS; 168 } 169 DeInit()170 void DrmDevice::DeInit() 171 { 172 mDisplays.clear(); 173 mCrtcs.clear(); 174 } 175 FindAllCrtc(const drmModeResPtr & res)176 void DrmDevice::FindAllCrtc(const drmModeResPtr &res) 177 { 178 DISPLAY_CHK_RETURN_NOT_VALUE((res == nullptr), DISPLAY_LOGE("the res is null")); 179 mCrtcs.clear(); 180 for (int i = 0; i < res->count_crtcs; i++) { 181 drmModeCrtcPtr crtc = drmModeGetCrtc(GetDrmFd(), res->crtcs[i]); 182 if (!crtc) { 183 DISPLAY_LOGE("can not get crtc %{public}d", i); 184 continue; 185 } 186 uint32_t crtc_id = crtc->crtc_id; 187 std::shared_ptr<DrmCrtc> drmCrtc = std::make_shared<DrmCrtc>(crtc, i); 188 int ret = drmCrtc->Init(*this); 189 drmModeFreeCrtc(crtc); 190 if (ret != DISPLAY_SUCCESS) { 191 DISPLAY_LOGE("crtc %{public}d init failed", i); 192 continue; 193 } 194 mCrtcs.emplace(crtc_id, std::move(drmCrtc)); 195 } 196 } 197 FindAllEncoder(const drmModeResPtr & res)198 void DrmDevice::FindAllEncoder(const drmModeResPtr &res) 199 { 200 DISPLAY_CHK_RETURN_NOT_VALUE((res == nullptr), DISPLAY_LOGE("the res is null")); 201 mEncoders.clear(); 202 for (int i = 0; i < res->count_encoders; i++) { 203 drmModeEncoderPtr encoder = drmModeGetEncoder(GetDrmFd(), res->encoders[i]); 204 if (!encoder) { 205 DISPLAY_LOGE("can not get encoder %{public}d", i); 206 continue; 207 } 208 std::shared_ptr<DrmEncoder> drmEncoder = std::make_shared<DrmEncoder>(*encoder); 209 mEncoders.emplace(encoder->encoder_id, std::move(drmEncoder)); 210 drmModeFreeEncoder(encoder); 211 } 212 DISPLAY_DEBUGLOG("find encoder count %{public}zd", mEncoders.size()); 213 } 214 FindAllConnector(const drmModeResPtr & res)215 void DrmDevice::FindAllConnector(const drmModeResPtr &res) 216 { 217 DISPLAY_CHK_RETURN_NOT_VALUE((res == nullptr), DISPLAY_LOGE("the res is null")); 218 mConnectors.clear(); 219 int ret; 220 for (int i = 0; i < res->count_connectors; i++) { 221 drmModeConnectorPtr connector = drmModeGetConnector(GetDrmFd(), res->connectors[i]); 222 if (!connector) { 223 DISPLAY_LOGE("can not get connector mode %{public}d", i); 224 continue; 225 } 226 std::shared_ptr<DrmConnector> drmConnector = std::make_shared<DrmConnector>(*connector, mDrmFd); 227 ret = drmConnector->Init(*this); 228 drmModeFreeConnector(connector); 229 if (ret != DISPLAY_SUCCESS) { 230 continue; 231 } 232 int connectorId = drmConnector->GetId(); 233 mConnectors.emplace(connectorId, std::move(drmConnector)); 234 } 235 DISPLAY_DEBUGLOG("find connector count %{public}zd", mConnectors.size()); 236 } 237 FindAllPlane()238 void DrmDevice::FindAllPlane() 239 { 240 mPlanes.clear(); 241 int ret; 242 drmModePlaneResPtr planeRes = drmModeGetPlaneResources(GetDrmFd()); 243 DISPLAY_CHK_RETURN_NOT_VALUE((planeRes == nullptr), DISPLAY_LOGE("can not get plane resource")); 244 DISPLAY_DEBUGLOG("count_planes %{public}d", planeRes->count_planes); 245 for (uint32_t i = 0; i < planeRes->count_planes; i++) { 246 drmModePlanePtr p = drmModeGetPlane(GetDrmFd(), planeRes->planes[i]); 247 if (!p) { 248 DISPLAY_LOGE("can not get plane %{public}d", i); 249 continue; 250 } 251 std::shared_ptr<DrmPlane> drmPlane = std::make_shared<DrmPlane>(*p); 252 DISPLAY_DEBUGLOG(); 253 ret = drmPlane->Init(*this); 254 DISPLAY_DEBUGLOG(); 255 drmModeFreePlane(p); 256 if (ret != DISPLAY_SUCCESS) { 257 DISPLAY_LOGE("drm plane %{public}d init failed", i); 258 continue; 259 } 260 mPlanes.emplace_back(std::move(drmPlane)); 261 } 262 DISPLAY_DEBUGLOG("find plane count %{public}zd", mPlanes.size()); 263 } 264 GetDrmEncoderFromId(uint32_t id)265 std::shared_ptr<DrmEncoder> DrmDevice::GetDrmEncoderFromId(uint32_t id) 266 { 267 return nullptr; 268 } 269 GetDrmConnectorFromId(uint32_t id)270 std::shared_ptr<DrmConnector> DrmDevice::GetDrmConnectorFromId(uint32_t id) 271 { 272 return nullptr; 273 } 274 GetDrmCrtcFromId(uint32_t id)275 std::shared_ptr<DrmCrtc> DrmDevice::GetDrmCrtcFromId(uint32_t id) 276 { 277 return nullptr; 278 } 279 GetDrmPlane(uint32_t pipe,uint32_t type)280 std::vector<std::shared_ptr<DrmPlane>> DrmDevice::GetDrmPlane(uint32_t pipe, uint32_t type) 281 { 282 std::vector<std::shared_ptr<DrmPlane>> planes; 283 for (const auto &plane : mPlanes) { 284 if (plane->IsIdle() && ((1 << pipe) & plane->GetPossibleCrtcs()) && (type == plane->GetType())) { 285 planes.push_back(plane); 286 } 287 } 288 DISPLAY_DEBUGLOG("the planes count %{public}zd", planes.size()); 289 return planes; 290 } 291 HandleHotplug(uint32_t dispId,bool plugIn)292 bool DrmDevice::HandleHotplug(uint32_t dispId, bool plugIn) 293 { 294 uint32_t find = 0; 295 uint32_t connectorId; 296 297 for (auto &dispConnectorIdMap : dispConnectorIdMaps_) { 298 if (dispConnectorIdMap.first == dispId) { 299 connectorId = dispConnectorIdMap.second; 300 find = 1; 301 break; 302 } 303 } 304 if (find) { 305 for (auto &connectorPair : mConnectors) { 306 auto connector = connectorPair.second; 307 if (connectorId == connector->GetId()) { 308 if (connector->HandleHotplug(mEncoders, mCrtcs, plugIn) == true) { 309 connector->Init(*this); 310 return true; 311 } 312 } 313 } 314 } 315 return false; 316 } 317 DiscoveryDisplay()318 std::unordered_map<uint32_t, std::shared_ptr<HdiDisplay>> DrmDevice::DiscoveryDisplay() 319 { 320 uint32_t dispId; 321 uint32_t connectorId; 322 323 dispConnectorIdMaps_.clear(); 324 mDisplays.clear(); 325 drmModeResPtr res = drmModeGetResources(GetDrmFd()); 326 DISPLAY_CHK_RETURN((res == nullptr), mDisplays, DISPLAY_LOGE("can not get drm resource")); 327 // discovery all drm resource 328 FindAllCrtc(res); 329 FindAllEncoder(res); 330 FindAllConnector(res); 331 FindAllPlane(); 332 DISPLAY_DEBUGLOG(); 333 // travel all connector 334 for (auto &connectorPair : mConnectors) { 335 auto connector = connectorPair.second; 336 uint32_t crtcId = 0; 337 int32_t ret = connector->PickIdleCrtcId(mEncoders, mCrtcs, crtcId); 338 if (ret != DISPLAY_SUCCESS) { 339 continue; 340 } 341 DISPLAY_DEBUGLOG(); 342 343 auto crtcIter = mCrtcs.find(crtcId); 344 if (crtcIter == mCrtcs.end()) { 345 DISPLAY_LOGE("can not find crtc for the id %{public}d", connector->GetId()); 346 continue; 347 } 348 DISPLAY_DEBUGLOG(); 349 auto crtc = crtcIter->second; 350 DISPLAY_DEBUGLOG("crtc %{public}p", crtc.get()); 351 // create the display 352 std::shared_ptr<HdiDisplay> display = std::make_shared<DrmDisplay>(connector, crtc, mInstance); 353 DISPLAY_DEBUGLOG(); 354 display->Init(); 355 dispId = display->GetId(); 356 connectorId = connector->GetId(); 357 mDisplays.emplace(dispId, std::move(display)); 358 dispConnectorIdMaps_.emplace(dispId, connectorId); 359 } 360 DISPLAY_DEBUGLOG("find display size %{public}zd", mDisplays.size()); 361 return mDisplays; 362 } 363 } // namespace OHOS 364 } // namespace HDI 365 } // namespace DISPLAY 366