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