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