• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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