1 /*
2 * Copyright (c) 2017, 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 <errno.h>
31 
32 #include "drm_master.h"
33 #include "drm_res_mgr.h"
34 
35 #define DEBUG 0
36 #define __CLASS__ "DRMResMgr"
37 
38 using std::mutex;
39 using std::lock_guard;
40 
41 namespace drm_utils {
42 
43 DRMResMgr *DRMResMgr::s_instance = nullptr;
44 mutex DRMResMgr::s_lock;
45 
GetConnector(int dev_fd,drmModeRes * res,drmModeConnector ** connector)46 static bool GetConnector(int dev_fd, drmModeRes *res, drmModeConnector **connector) {
47   for (auto i = 0; i < res->count_connectors; i++) {
48     drmModeConnector *conn = drmModeGetConnector(dev_fd, res->connectors[i]);
49     if (conn && conn->connector_type == DRM_MODE_CONNECTOR_DSI && conn->count_modes &&
50         conn->connection == DRM_MODE_CONNECTED) {
51       *connector = conn;
52       DRM_LOGI("Found connector %d", conn->connector_id);
53       return true;
54     }
55   }
56 
57   return false;
58 }
59 
GetEncoder(int dev_fd,drmModeConnector * conn,drmModeEncoder ** encoder)60 static bool GetEncoder(int dev_fd, drmModeConnector *conn, drmModeEncoder **encoder) {
61   for (auto i = 0; i < conn->count_encoders; i++) {
62     drmModeEncoder *enc = drmModeGetEncoder(dev_fd, conn->encoders[i]);
63     if (enc && enc->encoder_type == DRM_MODE_ENCODER_DSI) {
64       *encoder = enc;
65       DRM_LOGI("Found encoder %d", enc->encoder_id);
66       return true;
67     }
68   }
69   return false;
70 }
71 
GetCrtc(int dev_fd,drmModeRes * res,drmModeEncoder * enc,drmModeCrtc ** crtc)72 static bool GetCrtc(int dev_fd, drmModeRes *res, drmModeEncoder *enc, drmModeCrtc **crtc) {
73   for (auto i = 0; i < res->count_crtcs; i++) {
74     if (enc->possible_crtcs & (1 << i)) {
75       drmModeCrtc *c = drmModeGetCrtc(dev_fd, res->crtcs[i]);
76       if (c) {
77         *crtc = c;
78         DRM_LOGI("Found crtc %d", c->crtc_id);
79         return true;
80       }
81     }
82   }
83 
84   return false;
85 }
86 
87 #define __CLASS__ "DRMResMgr"
88 
GetInstance(DRMResMgr ** res_mgr)89 int DRMResMgr::GetInstance(DRMResMgr **res_mgr) {
90   lock_guard<mutex> obj(s_lock);
91 
92   if (!s_instance) {
93     s_instance = new DRMResMgr();
94     if (s_instance->Init() < 0) {
95       delete s_instance;
96       s_instance = nullptr;
97       return -ENODEV;
98     }
99   }
100 
101   *res_mgr = s_instance;
102   return 0;
103 }
104 
Init()105 int DRMResMgr::Init() {
106   DRMMaster *master = nullptr;
107   int dev_fd = -1;
108 
109   int ret = DRMMaster::GetInstance(&master);
110   if (ret < 0) {
111     return ret;
112   }
113 
114   master->GetHandle(&dev_fd);
115   drmModeRes *res = drmModeGetResources(dev_fd);
116   if (res == nullptr) {
117     DRM_LOGE("drmModeGetResources failed");
118     return -ENODEV;
119   }
120 
121   drmModeConnector *conn = nullptr;
122   if (!GetConnector(dev_fd, res, &conn)) {
123     DRM_LOGE("Failed to find a connector");
124     return -ENODEV;
125   }
126 
127   drmModeEncoder *enc = nullptr;
128   if (!GetEncoder(dev_fd, conn, &enc)) {
129     DRM_LOGE("Failed to find an encoder");
130     drmModeFreeConnector(conn);
131     return -ENODEV;
132   }
133 
134   drmModeCrtc *crtc = nullptr;
135   if (!GetCrtc(dev_fd, res, enc, &crtc)) {
136     DRM_LOGE("Failed to find a crtc");
137     drmModeFreeEncoder(enc);
138     drmModeFreeConnector(conn);
139     drmModeFreeResources(res);
140     return -ENODEV;
141   }
142 
143   res_ = res;
144   conn_ = conn;
145   enc_ = enc;
146   crtc_ = crtc;
147 
148   return 0;
149 }
150 
151 }  // namespace drm_utils
152