blob: 04685275ead6e10b2793e5e285b0702dff76db8b [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
93int DrmConnector::GetEdidBlob(drmModePropertyBlobPtr &blob) {
Roman Stratiienkob3b5c1e2021-02-15 13:44:19 +020094 uint64_t blob_id = 0;
Andrii Chepurnyiadc5d822020-07-10 16:07:03 +030095 int ret = UpdateEdidProperty();
96 if (ret) {
97 return ret;
98 }
99
100 std::tie(ret, blob_id) = edid_property().value();
101 if (ret) {
102 return ret;
103 }
104
105 blob = drmModeGetPropertyBlob(drm_->fd(), blob_id);
Marijn Suijten25ddbc42020-09-19 12:12:03 +0200106 return !blob;
Andrii Chepurnyiadc5d822020-07-10 16:07:03 +0300107}
108
Sean Paul6a55e9f2015-04-30 15:31:06 -0400109uint32_t DrmConnector::id() const {
110 return id_;
111}
112
113int DrmConnector::display() const {
114 return display_;
115}
116
117void DrmConnector::set_display(int display) {
118 display_ = display;
119}
120
Robert Foss610d9892017-11-01 12:50:04 -0500121bool DrmConnector::internal() const {
Sean Paul6a55e9f2015-04-30 15:31:06 -0400122 return type_ == DRM_MODE_CONNECTOR_LVDS || type_ == DRM_MODE_CONNECTOR_eDP ||
Mykhailo Sopiha87769e62019-07-11 14:31:09 +0300123 type_ == DRM_MODE_CONNECTOR_DSI ||
124 type_ == DRM_MODE_CONNECTOR_VIRTUAL || type_ == DRM_MODE_CONNECTOR_DPI;
Sean Paul6a55e9f2015-04-30 15:31:06 -0400125}
126
Robert Foss610d9892017-11-01 12:50:04 -0500127bool DrmConnector::external() const {
Sean Paulf72cccd2018-08-27 13:59:08 -0400128 return type_ == DRM_MODE_CONNECTOR_HDMIA ||
129 type_ == DRM_MODE_CONNECTOR_DisplayPort ||
Mauro Rossi556bedf2018-01-06 00:59:59 +0100130 type_ == DRM_MODE_CONNECTOR_DVID || type_ == DRM_MODE_CONNECTOR_DVII ||
131 type_ == DRM_MODE_CONNECTOR_VGA;
Robert Foss610d9892017-11-01 12:50:04 -0500132}
133
Alexandru Gheorghe364f9572018-03-21 11:40:01 +0000134bool DrmConnector::writeback() const {
135#ifdef DRM_MODE_CONNECTOR_WRITEBACK
136 return type_ == DRM_MODE_CONNECTOR_WRITEBACK;
137#else
138 return false;
139#endif
140}
141
Robert Foss610d9892017-11-01 12:50:04 -0500142bool DrmConnector::valid_type() const {
Alexandru Gheorghe364f9572018-03-21 11:40:01 +0000143 return internal() || external() || writeback();
Robert Foss610d9892017-11-01 12:50:04 -0500144}
145
Roman Kovalivskyidf882992019-11-04 17:43:40 +0200146std::string DrmConnector::name() const {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200147 constexpr std::array<const char *, kTypesCount> kNames =
Roman Kovalivskyie606a622019-11-25 19:13:05 +0200148 {"None", "VGA", "DVI-I", "DVI-D", "DVI-A", "Composite",
149 "SVIDEO", "LVDS", "Component", "DIN", "DP", "HDMI-A",
150 "HDMI-B", "TV", "eDP", "Virtual", "DSI"};
Roman Kovalivskyidf882992019-11-04 17:43:40 +0200151
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200152 if (type_ < kTypesCount) {
Roman Kovalivskyid6a6e6e2019-11-25 19:17:53 +0200153 std::ostringstream name_buf;
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200154 name_buf << kNames[type_] << "-" << type_id_;
Roman Kovalivskyid6a6e6e2019-11-25 19:17:53 +0200155 return name_buf.str();
Roman Kovalivskyid6a6e6e2019-11-25 19:17:53 +0200156 }
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200157
158 ALOGE("Unknown type in connector %d, could not make his name", id_);
159 return "None";
Roman Kovalivskyidf882992019-11-04 17:43:40 +0200160}
161
Sean Paul6a55e9f2015-04-30 15:31:06 -0400162int DrmConnector::UpdateModes() {
163 int fd = drm_->fd();
164
165 drmModeConnectorPtr c = drmModeGetConnector(fd, id_);
166 if (!c) {
167 ALOGE("Failed to get connector %d", id_);
168 return -ENODEV;
169 }
170
Sean Paul09216492015-10-26 15:36:37 -0400171 state_ = c->connection;
172
Andrii Chepurnyi1b1e35e2019-02-19 21:38:13 +0200173 bool preferred_mode_found = false;
Sean Paul6a55e9f2015-04-30 15:31:06 -0400174 std::vector<DrmMode> new_modes;
175 for (int i = 0; i < c->count_modes; ++i) {
176 bool exists = false;
Zach Reiznerff30b522015-10-28 19:08:45 -0700177 for (const DrmMode &mode : modes_) {
178 if (mode == c->modes[i]) {
179 new_modes.push_back(mode);
Sean Paul6a55e9f2015-04-30 15:31:06 -0400180 exists = true;
181 break;
182 }
183 }
Andrii Chepurnyi1b1e35e2019-02-19 21:38:13 +0200184 if (!exists) {
185 DrmMode m(&c->modes[i]);
186 m.set_id(drm_->next_mode_id());
187 new_modes.push_back(m);
188 }
John Stultza3429c72019-03-26 21:11:31 -0700189 // Use only the first DRM_MODE_TYPE_PREFERRED mode found
190 if (!preferred_mode_found &&
191 (new_modes.back().type() & DRM_MODE_TYPE_PREFERRED)) {
Andrii Chepurnyi1b1e35e2019-02-19 21:38:13 +0200192 preferred_mode_id_ = new_modes.back().id();
193 preferred_mode_found = true;
194 }
Sean Paul6a55e9f2015-04-30 15:31:06 -0400195 }
196 modes_.swap(new_modes);
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200197 if (!preferred_mode_found && !modes_.empty()) {
Andrii Chepurnyi1b1e35e2019-02-19 21:38:13 +0200198 preferred_mode_id_ = modes_[0].id();
199 }
Sean Paul6a55e9f2015-04-30 15:31:06 -0400200 return 0;
201}
202
203const DrmMode &DrmConnector::active_mode() const {
204 return active_mode_;
205}
206
Sean Paul877be972015-06-03 14:08:27 -0400207void DrmConnector::set_active_mode(const DrmMode &mode) {
208 active_mode_ = mode;
Sean Paul6a55e9f2015-04-30 15:31:06 -0400209}
210
211const DrmProperty &DrmConnector::dpms_property() const {
212 return dpms_property_;
213}
214
Sean Paul877be972015-06-03 14:08:27 -0400215const DrmProperty &DrmConnector::crtc_id_property() const {
216 return crtc_id_property_;
217}
218
Lowry Li (Arm Technology China)b3d81782019-12-18 14:28:22 +0800219const DrmProperty &DrmConnector::edid_property() const {
220 return edid_property_;
221}
222
Alexandru Gheorghe364f9572018-03-21 11:40:01 +0000223const DrmProperty &DrmConnector::writeback_pixel_formats() const {
224 return writeback_pixel_formats_;
225}
226
227const DrmProperty &DrmConnector::writeback_fb_id() const {
228 return writeback_fb_id_;
229}
230
231const DrmProperty &DrmConnector::writeback_out_fence() const {
232 return writeback_out_fence_;
233}
234
Sean Paul6a55e9f2015-04-30 15:31:06 -0400235DrmEncoder *DrmConnector::encoder() const {
236 return encoder_;
237}
238
239void DrmConnector::set_encoder(DrmEncoder *encoder) {
240 encoder_ = encoder;
241}
242
Sean Paul09216492015-10-26 15:36:37 -0400243drmModeConnection DrmConnector::state() const {
244 return state_;
245}
246
Sean Paul6a55e9f2015-04-30 15:31:06 -0400247uint32_t DrmConnector::mm_width() const {
248 return mm_width_;
249}
250
251uint32_t DrmConnector::mm_height() const {
252 return mm_height_;
253}
Sean Paulf72cccd2018-08-27 13:59:08 -0400254} // namespace android