1 /*
2 * Copyright (c) 2019-2020, 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 drmModeFreeResources(resource);
136
137 return 0;
138 }
139
GetConnectorInfo(uint32_t conn_id,DRMConnectorInfo * info)140 int DRMManager::GetConnectorInfo(uint32_t conn_id, DRMConnectorInfo *info) {
141 *info = {};
142 return conn_mgr_->GetConnectorInfo(conn_id, info);
143 }
144
GetConnectorsInfo(DRMConnectorsInfo * infos)145 int DRMManager::GetConnectorsInfo(DRMConnectorsInfo *infos) {
146 *infos = {};
147 int ret = -ENODEV;
148 std::vector<uint32_t> conn_ids;
149 conn_mgr_->Update();
150 conn_mgr_->GetConnectorList(&conn_ids);
151 for (auto iter : conn_ids) {
152 DRMConnectorInfo info;
153 ret = GetConnectorInfo(iter, &info);
154 if (!ret) {
155 (*infos)[iter] = info;
156 } else {
157 break;
158 }
159 }
160
161 return ret;
162 }
163
GetEncoderInfo(uint32_t encoder_id,DRMEncoderInfo * info)164 int DRMManager::GetEncoderInfo(uint32_t encoder_id, DRMEncoderInfo *info) {
165 *info = {};
166 return encoder_mgr_->GetEncoderInfo(encoder_id, info);
167 }
168
GetEncodersInfo(DRMEncodersInfo * infos)169 int DRMManager::GetEncodersInfo(DRMEncodersInfo *infos) {
170 *infos = {};
171 int ret = -ENODEV;
172 std::vector<uint32_t> encoder_ids;
173 encoder_mgr_->GetEncoderList(&encoder_ids);
174 for (auto iter : encoder_ids) {
175 DRMEncoderInfo info;
176 ret = GetEncoderInfo(iter, &info);
177 if (!ret) {
178 (*infos)[iter] = info;
179 } else {
180 break;
181 }
182 }
183
184 return ret;
185 }
186
GetCrtcInfo(uint32_t crtc_id,DRMCrtcInfo * info)187 int DRMManager::GetCrtcInfo(uint32_t crtc_id, DRMCrtcInfo *info) {
188 *info = {};
189 return crtc_mgr_->GetCrtcInfo(crtc_id, info);
190 }
191
GetPlanesInfo(DRMPlanesInfo * info)192 void DRMManager::GetPlanesInfo(DRMPlanesInfo *info) {
193 plane_mgr_->GetPlanesInfo(info);
194 }
195
GetCrtcPPInfo(uint32_t crtc_id,DRMPPFeatureInfo * info)196 void DRMManager::GetCrtcPPInfo(uint32_t crtc_id, DRMPPFeatureInfo *info) {
197 crtc_mgr_->GetPPInfo(crtc_id, info);
198 }
199
GetPlaneMgr()200 DRMPlaneManager *DRMManager::GetPlaneMgr() {
201 return plane_mgr_;
202 }
203
GetConnectorMgr()204 DRMConnectorManager *DRMManager::GetConnectorMgr() {
205 return conn_mgr_;
206 }
207
GetEncoderMgr()208 DRMEncoderManager *DRMManager::GetEncoderMgr() {
209 return encoder_mgr_;
210 }
211
GetCrtcMgr()212 DRMCrtcManager *DRMManager::GetCrtcMgr() {
213 return crtc_mgr_;
214 }
215
GetDppsMgrIntf()216 DRMDppsManagerIntf *DRMManager::GetDppsMgrIntf() {
217 return dpps_mgr_intf_;
218 }
219
RegisterDisplay(DRMDisplayType disp_type,DRMDisplayToken * token)220 int DRMManager::RegisterDisplay(DRMDisplayType disp_type, DRMDisplayToken *token) {
221 int ret = conn_mgr_->Reserve(disp_type, token);
222 if (ret) {
223 if (ret == -ENODEV) {
224 DRM_LOGI("display type %d is not present", disp_type);
225 } else {
226 DRM_LOGE("Error reserving connector for display type %d. Error = %d (%s)", disp_type, ret,
227 strerror(abs(ret)));
228 }
229 return ret;
230 }
231
232 std::set<uint32_t> possible_encoders;
233 ret = conn_mgr_->GetPossibleEncoders(token->conn_id, &possible_encoders);
234 if (ret) {
235 DRM_LOGE("Error retreiving possible encoders for display type %d. Error = %d (%s)", disp_type,
236 ret, strerror(abs(ret)));
237 return ret;
238 }
239
240 ret = encoder_mgr_->Reserve(possible_encoders, token);
241 if (ret) {
242 DRM_LOGE("Error reserving encoder for display type %d. Error = %d (%s)", disp_type, ret,
243 strerror(abs(ret)));
244 conn_mgr_->Free(token);
245 return ret;
246 }
247
248 std::set<uint32_t> possible_crtc_indices;
249 ret = encoder_mgr_->GetPossibleCrtcIndices(token->encoder_id, &possible_crtc_indices);
250 if (ret) {
251 DRM_LOGE("Error retreiving possible crtcs for display type %d. Error = %d (%s)", disp_type,
252 ret, strerror(abs(ret)));
253 return ret;
254 }
255
256 ret = crtc_mgr_->Reserve(possible_crtc_indices, token);
257 if (ret) {
258 DRM_LOGE("Error reserving crtc for display type %d. Error = %d (%s)", disp_type, ret,
259 strerror(abs(ret)));
260 encoder_mgr_->Free(token);
261 conn_mgr_->Free(token);
262 return ret;
263 }
264
265 return 0;
266 }
267
RegisterDisplay(int32_t display_id,DRMDisplayToken * token)268 int DRMManager::RegisterDisplay(int32_t display_id, DRMDisplayToken *token) {
269 int ret = conn_mgr_->Reserve(display_id, token);
270 if (ret) {
271 DRM_LOGE("Error reserving connector %d. Error = %d (%s)", display_id, ret, strerror(abs(ret)));
272 return ret;
273 }
274
275 std::set<uint32_t> possible_encoders;
276 ret = conn_mgr_->GetPossibleEncoders(token->conn_id, &possible_encoders);
277 if (ret) {
278 DRM_LOGE("Error retreiving possible encoders for display id %d. Error = %d (%s)", display_id,
279 ret, strerror(abs(ret)));
280 return ret;
281 }
282
283 ret = encoder_mgr_->Reserve(possible_encoders, token);
284 if (ret) {
285 DRM_LOGE("Error reserving encoder for display %d. Error: %d (%s)", display_id, ret,
286 strerror(abs(ret)));
287 return ret;
288 }
289
290 std::set<uint32_t> possible_crtc_indices;
291 ret = encoder_mgr_->GetPossibleCrtcIndices(token->encoder_id, &possible_crtc_indices);
292 if (ret) {
293 DRM_LOGE("Error retreiving possible crtcs for display id %d. Error = %d (%s)", display_id,
294 ret, strerror(abs(ret)));
295 encoder_mgr_->Free(token);
296 conn_mgr_->Free(token);
297 return ret;
298 }
299
300 ret = crtc_mgr_->Reserve(possible_crtc_indices, token);
301 if (ret) {
302 DRM_LOGE("Error reserving crtc for display %d. Error: %d (%s)", display_id,
303 ret, strerror(abs(ret)));
304 encoder_mgr_->Free(token);
305 conn_mgr_->Free(token);
306 return ret;
307 }
308
309 return 0;
310 }
311
UnregisterDisplay(DRMDisplayToken * token)312 void DRMManager::UnregisterDisplay(DRMDisplayToken *token) {
313 conn_mgr_->Free(token);
314 encoder_mgr_->Free(token);
315 crtc_mgr_->Free(token);
316 }
317
~DRMManager()318 DRMManager::~DRMManager() {
319 if (conn_mgr_) {
320 conn_mgr_->DeInit();
321 delete conn_mgr_;
322 conn_mgr_ = NULL;
323 }
324 if (encoder_mgr_) {
325 encoder_mgr_->DeInit();
326 delete encoder_mgr_;
327 encoder_mgr_ = NULL;
328 }
329 if (crtc_mgr_) {
330 crtc_mgr_->DeInit();
331 delete crtc_mgr_;
332 crtc_mgr_ = NULL;
333 }
334 if (plane_mgr_) {
335 plane_mgr_->DeInit();
336 delete plane_mgr_;
337 plane_mgr_ = NULL;
338 }
339 }
340
CreateAtomicReq(const DRMDisplayToken & token,DRMAtomicReqInterface ** intf)341 int DRMManager::CreateAtomicReq(const DRMDisplayToken &token, DRMAtomicReqInterface **intf) {
342 DRMAtomicReq *req = new DRMAtomicReq(fd_, this);
343 int ret = req ? req->Init(token) : -ENOMEM;
344
345 if (ret < 0) {
346 DRM_LOGE("Initializing DRMAtomicReqInterface failed with error %d (%s)", ret,
347 strerror(abs(ret)));
348 delete req;
349 return ret;
350 }
351 *intf = req;
352
353 return 0;
354 }
355
DestroyAtomicReq(DRMAtomicReqInterface * intf)356 int DRMManager::DestroyAtomicReq(DRMAtomicReqInterface *intf) {
357 delete intf;
358 return 0;
359 }
360
SetScalerLUT(const DRMScalerLUTInfo & lut_info)361 int DRMManager::SetScalerLUT(const DRMScalerLUTInfo &lut_info) {
362 plane_mgr_->SetScalerLUT(lut_info);
363 crtc_mgr_->SetScalerLUT(lut_info);
364 return 0;
365 }
366
UnsetScalerLUT()367 int DRMManager::UnsetScalerLUT() {
368 plane_mgr_->UnsetScalerLUT();
369 crtc_mgr_->UnsetScalerLUT();
370 return 0;
371 }
372
GetDppsFeatureInfo(DRMDppsFeatureInfo * info)373 void DRMManager::GetDppsFeatureInfo(DRMDppsFeatureInfo *info) {
374 if (dpps_mgr_intf_)
375 dpps_mgr_intf_->GetDppsFeatureInfo(info);
376 }
377
378 } // namespace sde_drm
379