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