blob: b3179c70d978f5d527c90e3d0ec52f9363bc7170 [file] [log] [blame]
Sean Paul6a55e9f2015-04-30 15:31:06 -04001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "hwc-drm-connector"
18
Roman Stratiienko13cc3662020-08-29 21:35:39 +030019#include "DrmConnector.h"
Sean Paul6a55e9f2015-04-30 15:31:06 -040020
Roman Stratiienko13cc3662020-08-29 21:35:39 +030021#include <xf86drmMode.h>
Sean Paul6a55e9f2015-04-30 15:31:06 -040022
Roman Kovalivskyidf882992019-11-04 17:43:40 +020023#include <array>
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020024#include <cerrno>
25#include <cstdint>
Roman Kovalivskyidf882992019-11-04 17:43:40 +020026#include <sstream>
27
Roman Stratiienko13cc3662020-08-29 21:35:39 +030028#include "DrmDevice.h"
Roman Stratiienkod518a052021-02-25 19:15:14 +020029#include "utils/log.h"
Sean Paul6a55e9f2015-04-30 15:31:06 -040030
31namespace android {
32
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020033constexpr size_t kTypesCount = 17;
Roman Kovalivskyie606a622019-11-25 19:13:05 +020034
Alexandru Gheorghe0f5abd72018-05-01 14:37:10 +010035DrmConnector::DrmConnector(DrmDevice *drm, drmModeConnectorPtr c,
Sean Paul6a55e9f2015-04-30 15:31:06 -040036 DrmEncoder *current_encoder,
37 std::vector<DrmEncoder *> &possible_encoders)
38 : drm_(drm),
39 id_(c->connector_id),
40 encoder_(current_encoder),
41 display_(-1),
42 type_(c->connector_type),
Roman Kovalivskyidf882992019-11-04 17:43:40 +020043 type_id_(c->connector_type_id),
Sean Paul6a55e9f2015-04-30 15:31:06 -040044 state_(c->connection),
45 mm_width_(c->mmWidth),
46 mm_height_(c->mmHeight),
47 possible_encoders_(possible_encoders) {
48}
49
Sean Paul6a55e9f2015-04-30 15:31:06 -040050int DrmConnector::Init() {
51 int ret = drm_->GetConnectorProperty(*this, "DPMS", &dpms_property_);
52 if (ret) {
53 ALOGE("Could not get DPMS property\n");
54 return ret;
55 }
Sean Paul877be972015-06-03 14:08:27 -040056 ret = drm_->GetConnectorProperty(*this, "CRTC_ID", &crtc_id_property_);
57 if (ret) {
58 ALOGE("Could not get CRTC_ID property\n");
59 return ret;
60 }
Roman Stratiienko6a10c4c2021-02-15 11:25:23 +020061 UpdateEdidProperty();
Alexandru Gheorghe364f9572018-03-21 11:40:01 +000062 if (writeback()) {
63 ret = drm_->GetConnectorProperty(*this, "WRITEBACK_PIXEL_FORMATS",
64 &writeback_pixel_formats_);
65 if (ret) {
66 ALOGE("Could not get WRITEBACK_PIXEL_FORMATS connector_id = %d\n", id_);
67 return ret;
68 }
69 ret = drm_->GetConnectorProperty(*this, "WRITEBACK_FB_ID",
70 &writeback_fb_id_);
71 if (ret) {
72 ALOGE("Could not get WRITEBACK_FB_ID connector_id = %d\n", id_);
73 return ret;
74 }
75 ret = drm_->GetConnectorProperty(*this, "WRITEBACK_OUT_FENCE_PTR",
76 &writeback_out_fence_);
77 if (ret) {
78 ALOGE("Could not get WRITEBACK_OUT_FENCE_PTR connector_id = %d\n", id_);
79 return ret;
80 }
81 }
Sean Paul6a55e9f2015-04-30 15:31:06 -040082 return 0;
83}
84
Andrii Chepurnyiadc5d822020-07-10 16:07:03 +030085int DrmConnector::UpdateEdidProperty() {
86 int ret = drm_->GetConnectorProperty(*this, "EDID", &edid_property_);
87 if (ret) {
88 ALOGW("Could not get EDID property\n");
89 }
90 return ret;
91}
92
Roman Stratiienko3e8ce572021-09-29 12:46:28 +030093auto DrmConnector::GetEdidBlob() -> DrmModePropertyBlobUnique {
Roman Stratiienkob3b5c1e2021-02-15 13:44:19 +020094 uint64_t blob_id = 0;
Andrii Chepurnyiadc5d822020-07-10 16:07:03 +030095 int ret = UpdateEdidProperty();
Roman Stratiienko3e8ce572021-09-29 12:46:28 +030096 if (ret != 0) {
97 return DrmModePropertyBlobUnique();
Andrii Chepurnyiadc5d822020-07-10 16:07:03 +030098 }
99
100 std::tie(ret, blob_id) = edid_property().value();
Roman Stratiienko3e8ce572021-09-29 12:46:28 +0300101 if (ret != 0) {
102 return DrmModePropertyBlobUnique();
Andrii Chepurnyiadc5d822020-07-10 16:07:03 +0300103 }
104
Roman Stratiienko3e8ce572021-09-29 12:46:28 +0300105 return MakeDrmModePropertyBlobUnique(drm_->fd(), blob_id);
Andrii Chepurnyiadc5d822020-07-10 16:07:03 +0300106}
107
Sean Paul6a55e9f2015-04-30 15:31:06 -0400108uint32_t DrmConnector::id() const {
109 return id_;
110}
111
112int DrmConnector::display() const {
113 return display_;
114}
115
116void DrmConnector::set_display(int display) {
117 display_ = display;
118}
119
Robert Foss610d9892017-11-01 12:50:04 -0500120bool DrmConnector::internal() const {
Sean Paul6a55e9f2015-04-30 15:31:06 -0400121 return type_ == DRM_MODE_CONNECTOR_LVDS || type_ == DRM_MODE_CONNECTOR_eDP ||
Mykhailo Sopiha87769e62019-07-11 14:31:09 +0300122 type_ == DRM_MODE_CONNECTOR_DSI ||
123 type_ == DRM_MODE_CONNECTOR_VIRTUAL || type_ == DRM_MODE_CONNECTOR_DPI;
Sean Paul6a55e9f2015-04-30 15:31:06 -0400124}
125
Robert Foss610d9892017-11-01 12:50:04 -0500126bool DrmConnector::external() const {
Sean Paulf72cccd2018-08-27 13:59:08 -0400127 return type_ == DRM_MODE_CONNECTOR_HDMIA ||
128 type_ == DRM_MODE_CONNECTOR_DisplayPort ||
Mauro Rossi556bedf2018-01-06 00:59:59 +0100129 type_ == DRM_MODE_CONNECTOR_DVID || type_ == DRM_MODE_CONNECTOR_DVII ||
130 type_ == DRM_MODE_CONNECTOR_VGA;
Robert Foss610d9892017-11-01 12:50:04 -0500131}
132
Alexandru Gheorghe364f9572018-03-21 11:40:01 +0000133bool DrmConnector::writeback() const {
134#ifdef DRM_MODE_CONNECTOR_WRITEBACK
135 return type_ == DRM_MODE_CONNECTOR_WRITEBACK;
136#else
137 return false;
138#endif
139}
140
Robert Foss610d9892017-11-01 12:50:04 -0500141bool DrmConnector::valid_type() const {
Alexandru Gheorghe364f9572018-03-21 11:40:01 +0000142 return internal() || external() || writeback();
Robert Foss610d9892017-11-01 12:50:04 -0500143}
144
Roman Kovalivskyidf882992019-11-04 17:43:40 +0200145std::string DrmConnector::name() const {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200146 constexpr std::array<const char *, kTypesCount> kNames =
Roman Kovalivskyie606a622019-11-25 19:13:05 +0200147 {"None", "VGA", "DVI-I", "DVI-D", "DVI-A", "Composite",
148 "SVIDEO", "LVDS", "Component", "DIN", "DP", "HDMI-A",
149 "HDMI-B", "TV", "eDP", "Virtual", "DSI"};
Roman Kovalivskyidf882992019-11-04 17:43:40 +0200150
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200151 if (type_ < kTypesCount) {
Roman Kovalivskyid6a6e6e2019-11-25 19:17:53 +0200152 std::ostringstream name_buf;
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200153 name_buf << kNames[type_] << "-" << type_id_;
Roman Kovalivskyid6a6e6e2019-11-25 19:17:53 +0200154 return name_buf.str();
Roman Kovalivskyid6a6e6e2019-11-25 19:17:53 +0200155 }
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200156
157 ALOGE("Unknown type in connector %d, could not make his name", id_);
158 return "None";
Roman Kovalivskyidf882992019-11-04 17:43:40 +0200159}
160
Sean Paul6a55e9f2015-04-30 15:31:06 -0400161int DrmConnector::UpdateModes() {
162 int fd = drm_->fd();
163
164 drmModeConnectorPtr c = drmModeGetConnector(fd, id_);
165 if (!c) {
166 ALOGE("Failed to get connector %d", id_);
167 return -ENODEV;
168 }
169
Sean Paul09216492015-10-26 15:36:37 -0400170 state_ = c->connection;
171
Andrii Chepurnyi1b1e35e2019-02-19 21:38:13 +0200172 bool preferred_mode_found = false;
Sean Paul6a55e9f2015-04-30 15:31:06 -0400173 std::vector<DrmMode> new_modes;
174 for (int i = 0; i < c->count_modes; ++i) {
175 bool exists = false;
Zach Reiznerff30b522015-10-28 19:08:45 -0700176 for (const DrmMode &mode : modes_) {
177 if (mode == c->modes[i]) {
178 new_modes.push_back(mode);
Sean Paul6a55e9f2015-04-30 15:31:06 -0400179 exists = true;
180 break;
181 }
182 }
Andrii Chepurnyi1b1e35e2019-02-19 21:38:13 +0200183 if (!exists) {
184 DrmMode m(&c->modes[i]);
185 m.set_id(drm_->next_mode_id());
186 new_modes.push_back(m);
187 }
John Stultza3429c72019-03-26 21:11:31 -0700188 // Use only the first DRM_MODE_TYPE_PREFERRED mode found
189 if (!preferred_mode_found &&
190 (new_modes.back().type() & DRM_MODE_TYPE_PREFERRED)) {
Andrii Chepurnyi1b1e35e2019-02-19 21:38:13 +0200191 preferred_mode_id_ = new_modes.back().id();
192 preferred_mode_found = true;
193 }
Sean Paul6a55e9f2015-04-30 15:31:06 -0400194 }
195 modes_.swap(new_modes);
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200196 if (!preferred_mode_found && !modes_.empty()) {
Andrii Chepurnyi1b1e35e2019-02-19 21:38:13 +0200197 preferred_mode_id_ = modes_[0].id();
198 }
Sean Paul6a55e9f2015-04-30 15:31:06 -0400199 return 0;
200}
201
202const DrmMode &DrmConnector::active_mode() const {
203 return active_mode_;
204}
205
Sean Paul877be972015-06-03 14:08:27 -0400206void DrmConnector::set_active_mode(const DrmMode &mode) {
207 active_mode_ = mode;
Sean Paul6a55e9f2015-04-30 15:31:06 -0400208}
209
210const DrmProperty &DrmConnector::dpms_property() const {
211 return dpms_property_;
212}
213
Sean Paul877be972015-06-03 14:08:27 -0400214const DrmProperty &DrmConnector::crtc_id_property() const {
215 return crtc_id_property_;
216}
217
Lowry Li (Arm Technology China)b3d81782019-12-18 14:28:22 +0800218const DrmProperty &DrmConnector::edid_property() const {
219 return edid_property_;
220}
221
Alexandru Gheorghe364f9572018-03-21 11:40:01 +0000222const DrmProperty &DrmConnector::writeback_pixel_formats() const {
223 return writeback_pixel_formats_;
224}
225
226const DrmProperty &DrmConnector::writeback_fb_id() const {
227 return writeback_fb_id_;
228}
229
230const DrmProperty &DrmConnector::writeback_out_fence() const {
231 return writeback_out_fence_;
232}
233
Sean Paul6a55e9f2015-04-30 15:31:06 -0400234DrmEncoder *DrmConnector::encoder() const {
235 return encoder_;
236}
237
238void DrmConnector::set_encoder(DrmEncoder *encoder) {
239 encoder_ = encoder;
240}
241
Sean Paul09216492015-10-26 15:36:37 -0400242drmModeConnection DrmConnector::state() const {
243 return state_;
244}
245
Sean Paul6a55e9f2015-04-30 15:31:06 -0400246uint32_t DrmConnector::mm_width() const {
247 return mm_width_;
248}
249
250uint32_t DrmConnector::mm_height() const {
251 return mm_height_;
252}
Sean Paulf72cccd2018-08-27 13:59:08 -0400253} // namespace android