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