1 /*
2 * Copyright (c) 2019-2021, 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 <drm_logger.h>
31
32 #include <string.h>
33 #include "drm_atomic_req.h"
34 #include "drm_connector.h"
35 #include "drm_crtc.h"
36 #include "drm_encoder.h"
37 #include "drm_manager.h"
38 #include "drm_plane.h"
39
40 using std::lock_guard;
41 using std::mutex;
42
43 extern "C" {
44
GetDRMManager(int fd,sde_drm::DRMManagerInterface ** intf)45 int GetDRMManager(int fd, sde_drm::DRMManagerInterface **intf) {
46 sde_drm::DRMManager *drm_mgr = sde_drm::DRMManager::GetInstance(fd);
47 if (!drm_mgr) {
48 return -ENODEV;
49 }
50
51 *intf = drm_mgr;
52 return 0;
53 }
54
DestroyDRMManager()55 int DestroyDRMManager() {
56 sde_drm::DRMManager::Destroy();
57 return 0;
58 }
59
60 } // extern "C"
61
62 namespace sde_drm {
63
64 #define __CLASS__ "DRMManager"
65
66 DRMManager *DRMManager::s_drm_instance = NULL;
67 mutex DRMManager::s_lock;
68
GetInstance(int fd)69 DRMManager *DRMManager::GetInstance(int fd) {
70 lock_guard<mutex> lock(s_lock);
71 if (!s_drm_instance) {
72 s_drm_instance = new DRMManager();
73
74 int ret = s_drm_instance ? s_drm_instance->Init(fd) : DRM_ERR_INVALID;
75 if (ret) {
76 delete s_drm_instance;
77 s_drm_instance = nullptr;
78 }
79 }
80
81 return s_drm_instance;
82 }
83
Destroy()84 void DRMManager::Destroy() {
85 lock_guard<mutex> lock(s_lock);
86 if (s_drm_instance) {
87 delete s_drm_instance;
88 s_drm_instance = nullptr;
89 }
90 }
91
Init(int drm_fd)92 int DRMManager::Init(int drm_fd) {
93 fd_ = drm_fd;
94
95 drmSetClientCap(fd_, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
96 drmSetClientCap(fd_, DRM_CLIENT_CAP_ATOMIC, 1);
97
98 drmModeRes *resource = drmModeGetResources(fd_);
99 if (resource == NULL) {
100 DRM_LOGE("drmModeGetResources failed");
101 return DRM_ERR_INVALID;
102 }
103
104 conn_mgr_ = new DRMConnectorManager(fd_);
105 if (!conn_mgr_) {
106 DRM_LOGE("Failed to get Connector Mgr");
107 return DRM_ERR_INVALID;
108 }
109 conn_mgr_->Init(resource);
110
111 encoder_mgr_ = new DRMEncoderManager(fd_);
112 if (!encoder_mgr_) {
113 DRM_LOGE("Failed to get Encoder Mgr");
114 return DRM_ERR_INVALID;
115 }
116 encoder_mgr_->Init(resource);
117
118 crtc_mgr_ = new DRMCrtcManager(fd_);
119 if (!crtc_mgr_) {
120 DRM_LOGE("Failed to get Crtc Mgr");
121 return DRM_ERR_INVALID;
122 }
123 crtc_mgr_->Init(resource);
124
125 plane_mgr_ = new DRMPlaneManager(fd_);
126 if (!plane_mgr_) {
127 DRM_LOGE("Failed to get Plane Mgr");
128 return DRM_ERR_INVALID;
129 }
130 plane_mgr_->Init();
131
132 dpps_mgr_intf_ = GetDppsManagerIntf();
133 if (dpps_mgr_intf_)
134 dpps_mgr_intf_->Init(fd_, resource);
135
136 panel_feature_mgr_intf_ = GetPanelFeatureManagerIntf();
137 if (!panel_feature_mgr_intf_) {
138 DRM_LOGE("Failed to get Panel feature Mgr");
139 return DRM_ERR_INVALID;
140 }
141 panel_feature_mgr_intf_->Init(fd_, resource);
142
143 drmModeFreeResources(resource);
144 return 0;
145 }
146
GetConnectorInfo(uint32_t conn_id,DRMConnectorInfo * info)147 int DRMManager::GetConnectorInfo(uint32_t conn_id, DRMConnectorInfo *info) {
148 *info = {};
149 return conn_mgr_->GetConnectorInfo(conn_id, info);
150 }
151
GetConnectorsInfo(DRMConnectorsInfo * infos)152 int DRMManager::GetConnectorsInfo(DRMConnectorsInfo *infos) {
153 *infos = {};
154 int ret = -ENODEV;
155 std::vector<uint32_t> conn_ids;
156 conn_mgr_->Update();
157 conn_mgr_->GetConnectorList(&conn_ids);
158 for (auto iter : conn_ids) {
159 DRMConnectorInfo info;
160 ret = GetConnectorInfo(iter, &info);
161 if (!ret) {
162 (*infos)[iter] = info;
163 } else {
164 break;
165 }
166 }
167
168 return ret;
169 }
170
GetEncoderInfo(uint32_t encoder_id,DRMEncoderInfo * info)171 int DRMManager::GetEncoderInfo(uint32_t encoder_id, DRMEncoderInfo *info) {
172 *info = {};
173 return encoder_mgr_->GetEncoderInfo(encoder_id, info);
174 }
175
GetEncodersInfo(DRMEncodersInfo * infos)176 int DRMManager::GetEncodersInfo(DRMEncodersInfo *infos) {
177 *infos = {};
178 int ret = -ENODEV;
179 std::vector<uint32_t> encoder_ids;
180 encoder_mgr_->GetEncoderList(&encoder_ids);
181 for (auto iter : encoder_ids) {
182 DRMEncoderInfo info;
183 ret = GetEncoderInfo(iter, &info);
184 if (!ret) {
185 (*infos)[iter] = info;
186 } else {
187 break;
188 }
189 }
190
191 return ret;
192 }
193
GetCrtcInfo(uint32_t crtc_id,DRMCrtcInfo * info)194 int DRMManager::GetCrtcInfo(uint32_t crtc_id, DRMCrtcInfo *info) {
195 *info = {};
196 return crtc_mgr_->GetCrtcInfo(crtc_id, info);
197 }
198
GetPlanesInfo(DRMPlanesInfo * info)199 void DRMManager::GetPlanesInfo(DRMPlanesInfo *info) {
200 plane_mgr_->GetPlanesInfo(info);
201 }
202
GetCrtcPPInfo(uint32_t crtc_id,DRMPPFeatureInfo * info)203 void DRMManager::GetCrtcPPInfo(uint32_t crtc_id, DRMPPFeatureInfo *info) {
204 crtc_mgr_->GetPPInfo(crtc_id, info);
205 }
206
GetPlaneMgr()207 DRMPlaneManager *DRMManager::GetPlaneMgr() {
208 return plane_mgr_;
209 }
210
GetConnectorMgr()211 DRMConnectorManager *DRMManager::GetConnectorMgr() {
212 return conn_mgr_;
213 }
214
GetEncoderMgr()215 DRMEncoderManager *DRMManager::GetEncoderMgr() {
216 return encoder_mgr_;
217 }
218
GetCrtcMgr()219 DRMCrtcManager *DRMManager::GetCrtcMgr() {
220 return crtc_mgr_;
221 }
222
GetDppsMgrIntf()223 DRMDppsManagerIntf *DRMManager::GetDppsMgrIntf() {
224 return dpps_mgr_intf_;
225 }
226
RegisterDisplay(DRMDisplayType disp_type,DRMDisplayToken * token)227 int DRMManager::RegisterDisplay(DRMDisplayType disp_type, DRMDisplayToken *token) {
228 int ret = conn_mgr_->Reserve(disp_type, token);
229 if (ret) {
230 if (ret == -ENODEV) {
231 DRM_LOGI("display type %d is not present", disp_type);
232 } else {
233 DRM_LOGE("Error reserving connector for display type %d. Error = %d (%s)", disp_type, ret,
234 strerror(abs(ret)));
235 }
236 return ret;
237 }
238
239 std::set<uint32_t> possible_encoders;
240 ret = conn_mgr_->GetPossibleEncoders(token->conn_id, &possible_encoders);
241 if (ret) {
242 DRM_LOGE("Error retreiving possible encoders for display type %d. Error = %d (%s)", disp_type,
243 ret, strerror(abs(ret)));
244 return ret;
245 }
246
247 ret = encoder_mgr_->Reserve(possible_encoders, token);
248 if (ret) {
249 DRM_LOGE("Error reserving encoder for display type %d. Error = %d (%s)", disp_type, ret,
250 strerror(abs(ret)));
251 conn_mgr_->Free(token);
252 return ret;
253 }
254
255 std::set<uint32_t> possible_crtc_indices;
256 ret = encoder_mgr_->GetPossibleCrtcIndices(token->encoder_id, &possible_crtc_indices);
257 if (ret) {
258 DRM_LOGE("Error retreiving possible crtcs for display type %d. Error = %d (%s)", disp_type,
259 ret, strerror(abs(ret)));
260 return ret;
261 }
262
263 ret = crtc_mgr_->Reserve(possible_crtc_indices, token);
264 if (ret) {
265 DRM_LOGE("Error reserving crtc for display type %d. Error = %d (%s)", disp_type, ret,
266 strerror(abs(ret)));
267 encoder_mgr_->Free(token);
268 conn_mgr_->Free(token);
269 return ret;
270 }
271
272 return 0;
273 }
274
RegisterDisplay(int32_t display_id,DRMDisplayToken * token)275 int DRMManager::RegisterDisplay(int32_t display_id, DRMDisplayToken *token) {
276 int ret = conn_mgr_->Reserve(display_id, token);
277 if (ret) {
278 DRM_LOGE("Error reserving connector %d. Error = %d (%s)", display_id, ret, strerror(abs(ret)));
279 return ret;
280 }
281
282 std::set<uint32_t> possible_encoders;
283 ret = conn_mgr_->GetPossibleEncoders(token->conn_id, &possible_encoders);
284 if (ret) {
285 DRM_LOGE("Error retreiving possible encoders for display id %d. Error = %d (%s)", display_id,
286 ret, strerror(abs(ret)));
287 return ret;
288 }
289
290 ret = encoder_mgr_->Reserve(possible_encoders, token);
291 if (ret) {
292 DRM_LOGE("Error reserving encoder for display %d. Error: %d (%s)", display_id, ret,
293 strerror(abs(ret)));
294 return ret;
295 }
296
297 std::set<uint32_t> possible_crtc_indices;
298 ret = encoder_mgr_->GetPossibleCrtcIndices(token->encoder_id, &possible_crtc_indices);
299 if (ret) {
300 DRM_LOGE("Error retreiving possible crtcs for display id %d. Error = %d (%s)", display_id,
301 ret, strerror(abs(ret)));
302 encoder_mgr_->Free(token);
303 conn_mgr_->Free(token);
304 return ret;
305 }
306
307 ret = crtc_mgr_->Reserve(possible_crtc_indices, token);
308 if (ret) {
309 DRM_LOGE("Error reserving crtc for display %d. Error: %d (%s)", display_id,
310 ret, strerror(abs(ret)));
311 encoder_mgr_->Free(token);
312 conn_mgr_->Free(token);
313 return ret;
314 }
315
316 return 0;
317 }
318
UnregisterDisplay(DRMDisplayToken * token)319 void DRMManager::UnregisterDisplay(DRMDisplayToken *token) {
320 conn_mgr_->Free(token);
321 encoder_mgr_->Free(token);
322 crtc_mgr_->Free(token);
323 }
324
~DRMManager()325 DRMManager::~DRMManager() {
326 if (conn_mgr_) {
327 conn_mgr_->DeInit();
328 delete conn_mgr_;
329 conn_mgr_ = NULL;
330 }
331 if (encoder_mgr_) {
332 encoder_mgr_->DeInit();
333 delete encoder_mgr_;
334 encoder_mgr_ = NULL;
335 }
336 if (crtc_mgr_) {
337 crtc_mgr_->DeInit();
338 delete crtc_mgr_;
339 crtc_mgr_ = NULL;
340 }
341 if (plane_mgr_) {
342 plane_mgr_->DeInit();
343 delete plane_mgr_;
344 plane_mgr_ = NULL;
345 }
346 if (panel_feature_mgr_intf_) {
347 panel_feature_mgr_intf_->DeInit();
348 }
349 }
350
CreateAtomicReq(const DRMDisplayToken & token,DRMAtomicReqInterface ** intf)351 int DRMManager::CreateAtomicReq(const DRMDisplayToken &token, DRMAtomicReqInterface **intf) {
352 DRMAtomicReq *req = new DRMAtomicReq(fd_, this);
353 int ret = req ? req->Init(token) : -ENOMEM;
354
355 if (ret < 0) {
356 DRM_LOGE("Initializing DRMAtomicReqInterface failed with error %d (%s)", ret,
357 strerror(abs(ret)));
358 delete req;
359 return ret;
360 }
361 *intf = req;
362
363 return 0;
364 }
365
DestroyAtomicReq(DRMAtomicReqInterface * intf)366 int DRMManager::DestroyAtomicReq(DRMAtomicReqInterface *intf) {
367 delete intf;
368 return 0;
369 }
370
SetScalerLUT(const DRMScalerLUTInfo & lut_info)371 int DRMManager::SetScalerLUT(const DRMScalerLUTInfo &lut_info) {
372 plane_mgr_->SetScalerLUT(lut_info);
373 crtc_mgr_->SetScalerLUT(lut_info);
374 return 0;
375 }
376
UnsetScalerLUT()377 int DRMManager::UnsetScalerLUT() {
378 plane_mgr_->UnsetScalerLUT();
379 crtc_mgr_->UnsetScalerLUT();
380 return 0;
381 }
382
GetDppsFeatureInfo(DRMDppsFeatureInfo * info)383 void DRMManager::GetDppsFeatureInfo(DRMDppsFeatureInfo *info) {
384 if (dpps_mgr_intf_)
385 dpps_mgr_intf_->GetDppsFeatureInfo(info);
386 }
387
GetPanelFeatureMgrIntf()388 DRMPanelFeatureMgrIntf *DRMManager::GetPanelFeatureMgrIntf() {
389 return panel_feature_mgr_intf_;
390 }
391
GetPanelFeature(DRMPanelFeatureInfo * info)392 void DRMManager::GetPanelFeature(DRMPanelFeatureInfo *info) {
393 if (panel_feature_mgr_intf_) {
394 panel_feature_mgr_intf_->GetPanelFeatureInfo(info);
395 } else {
396 DRM_LOGE("Failed, panel feature mgr not available");
397 }
398 }
399
SetPanelFeature(const DRMPanelFeatureInfo & info)400 void DRMManager::SetPanelFeature(const DRMPanelFeatureInfo &info) {
401 if (panel_feature_mgr_intf_) {
402 panel_feature_mgr_intf_->CachePanelFeature(info);
403 } else {
404 DRM_LOGE("Failed, panel feature mgr not available");
405 }
406 }
407
408 } // namespace sde_drm
409