blob: 6a5f10c08319f7997a15debff1038cb4ed48ea12 [file] [log] [blame]
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +05301/*
2* Copyright (c) 2019, 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 <stdint.h>
31#include <stdlib.h>
32#include <drm.h>
33#include <drm/sde_drm.h>
34#include <drm/msm_drm.h>
35#include <drm_logger.h>
36#include <errno.h>
Ramkumar Radhakrishnan4518d302019-06-18 19:57:41 -070037#include <string.h>
38
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +053039#include <algorithm>
40#include <map>
41#include <memory>
42#include <sstream>
43#include <string>
44#include <utility>
45#include <vector>
46#include <mutex>
47
48#include "drm_utils.h"
49#include "drm_property.h"
50#include "drm_connector.h"
51
52namespace sde_drm {
53
54using std::string;
55using std::stringstream;
56using std::pair;
57using std::vector;
58using std::unique_ptr;
59using std::map;
60using std::mutex;
61using std::lock_guard;
Varun Arora6ba9eda2019-02-07 17:59:32 -080062using std::set;
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +053063
64static uint8_t ON = 0;
65static uint8_t DOZE = 1;
66static uint8_t DOZE_SUSPEND = 2;
67static uint8_t OFF = 5;
68
69// Connector FB Secure Modes
70static uint8_t NON_SECURE = 0;
71static uint8_t SECURE = 1;
72
73static uint8_t QSYNC_MODE_NONE = 0;
74static uint8_t QSYNC_MODE_CONTINUOUS = 1;
75
Xu Yang39503f12018-12-24 17:43:36 +080076static uint8_t FRAME_TRIGGER_DEFAULT = 0;
77static uint8_t FRAME_TRIGGER_SERIALIZE = 1;
78static uint8_t FRAME_TRIGGER_POSTED_START = 2;
79
Gousemoodhin Nadaf47b82be2019-05-09 15:30:11 +053080static uint8_t DRM_MODE_COLORIMETRY_DEFAULT = 0;
81static uint8_t DRM_MODE_COLORIMETRY_SMPTE_170M_YCC = 1;
82static uint8_t DRM_MODE_COLORIMETRY_BT709_YCC = 2;
83static uint8_t DRM_MODE_COLORIMETRY_XVYCC_601 = 3;
84static uint8_t DRM_MODE_COLORIMETRY_XVYCC_709 = 4;
85static uint8_t DRM_MODE_COLORIMETRY_SYCC_601 = 5;
86static uint8_t DRM_MODE_COLORIMETRY_OPYCC_601 = 6;
87static uint8_t DRM_MODE_COLORIMETRY_OPRGB = 7;
88static uint8_t DRM_MODE_COLORIMETRY_BT2020_CYCC = 8;
89static uint8_t DRM_MODE_COLORIMETRY_BT2020_RGB = 9;
90static uint8_t DRM_MODE_COLORIMETRY_BT2020_YCC = 10;
91static uint8_t DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65 = 11;
92static uint8_t DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER = 12;
93
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +053094static void PopulatePowerModes(drmModePropertyRes *prop) {
95 for (auto i = 0; i < prop->count_enums; i++) {
96 string enum_name(prop->enums[i].name);
97 if (enum_name == "ON") {
98 ON = prop->enums[i].value;
99 } else if (enum_name == "LP1") {
100 DOZE = prop->enums[i].value;
101 } else if (enum_name == "LP2") {
102 DOZE_SUSPEND = prop->enums[i].value;
103 } else if (enum_name == "OFF") {
104 OFF = prop->enums[i].value;
105 }
106 }
107}
108
109static void PopulateSecureModes(drmModePropertyRes *prop) {
110 for (auto i = 0; i < prop->count_enums; i++) {
111 string enum_name(prop->enums[i].name);
112 if (enum_name == "non_sec") {
113 NON_SECURE = prop->enums[i].value;
114 } else if (enum_name == "sec") {
115 SECURE = prop->enums[i].value;
116 }
117 }
118}
119
Gousemoodhin Nadaf47b82be2019-05-09 15:30:11 +0530120static void PopulateSupportedColorspaces(drmModePropertyRes *prop) {
121 for (auto i = 0; i < prop->count_enums; i++) {
122 string enum_name(prop->enums[i].name);
123 if (enum_name == "Default") {
124 DRM_MODE_COLORIMETRY_DEFAULT = prop->enums[i].value;
125 } else if (enum_name == "SMPTE_170M_YCC") {
126 DRM_MODE_COLORIMETRY_SMPTE_170M_YCC = prop->enums[i].value;
127 } else if (enum_name == "BT709_YCC") {
128 DRM_MODE_COLORIMETRY_BT709_YCC = prop->enums[i].value;
129 } else if (enum_name == "XVYCC_601") {
130 DRM_MODE_COLORIMETRY_XVYCC_601 = prop->enums[i].value;
131 } else if (enum_name == "XVYCC_709") {
132 DRM_MODE_COLORIMETRY_XVYCC_709 = prop->enums[i].value;
133 } else if (enum_name == "SYCC_601") {
134 DRM_MODE_COLORIMETRY_SYCC_601 = prop->enums[i].value;
135 } else if (enum_name == "opYCC_601") {
136 DRM_MODE_COLORIMETRY_OPYCC_601 = prop->enums[i].value;
137 } else if (enum_name == "opRGB") {
138 DRM_MODE_COLORIMETRY_OPRGB = prop->enums[i].value;
139 } else if (enum_name == "BT2020_CYCC") {
140 DRM_MODE_COLORIMETRY_BT2020_CYCC = prop->enums[i].value;
141 } else if (enum_name == "BT2020_RGB") {
142 DRM_MODE_COLORIMETRY_BT2020_RGB = prop->enums[i].value;
143 } else if (enum_name == "BT2020_YCC") {
144 DRM_MODE_COLORIMETRY_BT2020_YCC = prop->enums[i].value;
145 } else if (enum_name == "DCI_P3_RGB_D65") {
146 DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65 = prop->enums[i].value;
147 } else if (enum_name == "DCI_P3_RGB_Theater") {
148 DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER = prop->enums[i].value;
149 }
150 }
151}
152
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530153static DRMTopology GetTopologyEnum(const string &topology) {
154 if (topology == "sde_singlepipe") return DRMTopology::SINGLE_LM;
155 if (topology == "sde_singlepipe_dsc") return DRMTopology::SINGLE_LM_DSC;
156 if (topology == "sde_dualpipe") return DRMTopology::DUAL_LM;
157 if (topology == "sde_dualpipe_dsc") return DRMTopology::DUAL_LM_DSC;
158 if (topology == "sde_dualpipemerge") return DRMTopology::DUAL_LM_MERGE;
159 if (topology == "sde_dualpipemerge_dsc") return DRMTopology::DUAL_LM_MERGE_DSC;
160 if (topology == "sde_dualpipe_dscmerge") return DRMTopology::DUAL_LM_DSCMERGE;
161 if (topology == "sde_ppsplit") return DRMTopology::PPSPLIT;
162 return DRMTopology::UNKNOWN;
163}
164
165static void PopulateQsyncModes(drmModePropertyRes *prop) {
166 for (auto i = 0; i < prop->count_enums; i++) {
167 string enum_name(prop->enums[i].name);
168 if (enum_name == "none") {
169 QSYNC_MODE_NONE = prop->enums[i].value;
170 } else if (enum_name == "continuous") {
171 QSYNC_MODE_CONTINUOUS = prop->enums[i].value;
172 }
173 }
174}
175
Xu Yang39503f12018-12-24 17:43:36 +0800176static void PopulateFrameTriggerModes(drmModePropertyRes *prop) {
177 for (auto i = 0; i < prop->count_enums; i++) {
178 string enum_name(prop->enums[i].name);
179 if (enum_name == "default") {
180 FRAME_TRIGGER_DEFAULT = prop->enums[i].value;
181 } else if (enum_name == "serilize_frame_trigger") {
182 FRAME_TRIGGER_SERIALIZE = prop->enums[i].value;
183 } else if (enum_name == "posted_start") {
184 FRAME_TRIGGER_POSTED_START = prop->enums[i].value;
185 }
186 }
187}
188
Gousemoodhin Nadaf47b82be2019-05-09 15:30:11 +0530189static int32_t GetColorspace(DRMColorspace drm_colorspace) {
190 uint32_t colorspace = 0;
191 switch (drm_colorspace) {
192 case (DRMColorspace::DEFAULT):
193 colorspace = DRM_MODE_COLORIMETRY_DEFAULT;
194 break;
195 case (DRMColorspace::SMPTE_170M_YCC):
196 colorspace = DRM_MODE_COLORIMETRY_SMPTE_170M_YCC;
197 break;
198 case (DRMColorspace::BT709_YCC):
199 colorspace = DRM_MODE_COLORIMETRY_BT709_YCC;
200 break;
201 case (DRMColorspace::XVYCC_601):
202 colorspace = DRM_MODE_COLORIMETRY_XVYCC_601;
203 break;
204 case (DRMColorspace::XVYCC_709):
205 colorspace = DRM_MODE_COLORIMETRY_XVYCC_709;
206 break;
207 case (DRMColorspace::SYCC_601):
208 colorspace = DRM_MODE_COLORIMETRY_SYCC_601;
209 break;
210 case (DRMColorspace::OPYCC_601):
211 colorspace = DRM_MODE_COLORIMETRY_OPYCC_601;
212 break;
213 case (DRMColorspace::OPRGB):
214 colorspace = DRM_MODE_COLORIMETRY_OPRGB;
215 break;
216 case (DRMColorspace::BT2020_CYCC):
217 colorspace = DRM_MODE_COLORIMETRY_BT2020_CYCC;
218 break;
219 case (DRMColorspace::BT2020_RGB):
220 colorspace = DRM_MODE_COLORIMETRY_BT2020_RGB;
221 break;
222 case (DRMColorspace::BT2020_YCC):
223 colorspace = DRM_MODE_COLORIMETRY_BT2020_YCC;
224 break;
225 case (DRMColorspace::DCI_P3_RGB_D65):
226 colorspace = DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65;
227 break;
228 case (DRMColorspace::DCI_P3_RGB_THEATER):
229 colorspace = DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER;
230 break;
231 default:
232 colorspace = -1;
233 break;
234 }
235 return colorspace;
236}
237
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530238#define __CLASS__ "DRMConnectorManager"
239
240void DRMConnectorManager::Init(drmModeRes *resource) {
241 lock_guard<mutex> lock(lock_);
242 for (int i = 0; i < resource->count_connectors; i++) {
243 unique_ptr<DRMConnector> conn(new DRMConnector(fd_));
244 drmModeConnector *libdrm_conn = drmModeGetConnector(fd_, resource->connectors[i]);
245 if (libdrm_conn) {
246 conn->InitAndParse(libdrm_conn);
247 connector_pool_[resource->connectors[i]] = std::move(conn);
248 } else {
Mathew Joseph Karimpanala46c8d82018-12-06 19:10:56 +0530249 DRM_LOGE("Critical error: drmModeGetConnector() failed for connector %u.",
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530250 resource->connectors[i]);
251 }
252 }
253}
254
255void DRMConnectorManager::Update() {
256 lock_guard<mutex> lock(lock_);
257 drmModeRes *resource = drmModeGetResources(fd_);
258
259 if (NULL == resource) {
260 DRM_LOGE("drmModeGetResources() failed. Connector status not updated.");
261 return;
262 }
263
264 // Build a map of the updated list of connector ids.
265 std::map<uint32_t, uint32_t> drm_connectors;
266 for (int i = 0; i < resource->count_connectors; i++) {
267 drm_connectors[resource->connectors[i]] = resource->connectors[i];
268 }
269
270 // Delete connectors in connector pool.
271 for (auto conn = connector_pool_.cbegin(); conn != connector_pool_.cend();) {
272 auto drmconn = drm_connectors.find(conn->first);
273 if (drmconn == drm_connectors.end()) {
274 // A DRM Connector in our pool was deleted.
275 if (conn->second->GetStatus() == DRMStatus::FREE) {
Mathew Joseph Karimpanala46c8d82018-12-06 19:10:56 +0530276 DRM_LOGD("Removing connector id %u from pool.", conn->first);
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530277 conn = connector_pool_.erase(conn);
278 } else {
279 // Physically removed DRM Connectors (displays) first go to disconnected state. When its
280 // reserved resources are freed up, they are removed from the driver's connector list. Do
281 // not remove DRM Connectors that are DRMStatus::BUSY.
Mathew Joseph Karimpanala46c8d82018-12-06 19:10:56 +0530282 DRM_LOGW("In-use connector id %u removed by DRM.", conn->first);
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530283 conn++;
284 }
285 } else {
286 // Remove DRM Connector present in both lists to ensure that only new connector ids remain.
287 drm_connectors.erase(drmconn);
288 conn++;
289 }
290 }
291
292 // Add new connectors in connector pool.
293 for (auto &drmconn : drm_connectors) {
Mathew Joseph Karimpanala46c8d82018-12-06 19:10:56 +0530294 DRM_LOGD("Adding connector id %u to pool.", drmconn.first);
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530295 unique_ptr<DRMConnector> conn(new DRMConnector(fd_));
296 drmModeConnector *libdrm_conn = drmModeGetConnector(fd_, drmconn.first);
297 if (libdrm_conn) {
298 conn->InitAndParse(libdrm_conn);
Mathew Joseph Karimpanala46c8d82018-12-06 19:10:56 +0530299 conn->SetSkipConnectorReload(true);
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530300 connector_pool_[drmconn.first] = std::move(conn);
301 } else {
Mathew Joseph Karimpanala46c8d82018-12-06 19:10:56 +0530302 DRM_LOGE("Critical error: drmModeGetConnector() failed for connector %u.", drmconn.first);
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530303 }
304 }
305
306 drmModeFreeResources(resource);
307}
308
309void DRMConnectorManager::DumpByID(uint32_t id) {
310 lock_guard<mutex> lock(lock_);
311 connector_pool_[id]->Dump();
312}
313
314void DRMConnectorManager::DumpAll() {
315 lock_guard<mutex> lock(lock_);
316 for (auto &conn : connector_pool_) {
317 conn.second->Dump();
318 }
319}
320
321void DRMConnectorManager::Perform(DRMOps code, uint32_t obj_id, drmModeAtomicReq *req,
322 va_list args) {
323 lock_guard<mutex> lock(lock_);
324 auto it = connector_pool_.find(obj_id);
325 if (it == connector_pool_.end()) {
326 DRM_LOGE("Invalid connector id %d", obj_id);
327 return;
328 }
329
330 it->second->Perform(code, req, args);
331}
332
333int DRMConnectorManager::GetConnectorInfo(uint32_t conn_id, DRMConnectorInfo *info) {
334 lock_guard<mutex> lock(lock_);
335 int ret = -ENODEV;
336 auto iter = connector_pool_.find(conn_id);
337
338 if (iter != connector_pool_.end()) {
339 ret = connector_pool_[conn_id]->GetInfo(info);
340 }
341
342 return ret;
343}
344
345void DRMConnectorManager::GetConnectorList(std::vector<uint32_t> *conn_ids) {
346 lock_guard<mutex> lock(lock_);
347 if (!conn_ids) {
348 DRM_LOGE("No output parameter provided.");
349 return;
350 }
351 conn_ids->clear();
352 for (auto &conn : connector_pool_) {
353 conn_ids->push_back(conn.first);
354 }
355}
356
357static bool IsTVConnector(uint32_t type) {
358 return (type == DRM_MODE_CONNECTOR_TV || type == DRM_MODE_CONNECTOR_HDMIA ||
359 type == DRM_MODE_CONNECTOR_HDMIB || type == DRM_MODE_CONNECTOR_DisplayPort ||
360 type == DRM_MODE_CONNECTOR_VGA);
361}
362
363int DRMConnectorManager::Reserve(DRMDisplayType disp_type, DRMDisplayToken *token) {
364 lock_guard<mutex> lock(lock_);
365 int ret = -ENODEV;
366 token->conn_id = 0;
367
368 for (auto &conn : connector_pool_) {
369 if (conn.second->GetStatus() == DRMStatus::FREE) {
370 uint32_t conn_type;
371 conn.second->GetType(&conn_type);
372 if ((disp_type == DRMDisplayType::PERIPHERAL && conn_type == DRM_MODE_CONNECTOR_DSI) ||
373 (disp_type == DRMDisplayType::VIRTUAL && conn_type == DRM_MODE_CONNECTOR_VIRTUAL) ||
374 (disp_type == DRMDisplayType::TV && IsTVConnector(conn_type))) {
375 if (conn.second->IsConnected()) {
376 // Free-up previously reserved connector, if any.
377 if (token->conn_id) {
378 connector_pool_[token->conn_id]->Unlock();
379 }
380 conn.second->Lock();
381 token->conn_id = conn.first;
382 ret = 0;
383 break;
384 } else {
385 // Hold on to the first reserved connector.
386 if (token->conn_id) {
387 continue;
388 }
389 // Prefer a connector that is connected. Continue search.
390 conn.second->Lock();
391 token->conn_id = conn.first;
392 ret = 0;
393 }
394 }
395 }
396 }
397
398 return ret;
399}
400
401int DRMConnectorManager::Reserve(uint32_t conn_id, DRMDisplayToken *token) {
402 lock_guard<mutex> lock(lock_);
403 int ret = -ENODEV;
404
405 auto iter = connector_pool_.find(conn_id);
406 if ((iter != connector_pool_.end()) && (iter->second->GetStatus() == DRMStatus::FREE)) {
407 iter->second->Lock();
408 token->conn_id = iter->first;
409 ret = 0;
410 }
411
412 return ret;
413}
414
Varun Arora6ba9eda2019-02-07 17:59:32 -0800415int DRMConnectorManager::GetPossibleEncoders(uint32_t connector_id,
416 set<uint32_t> *possible_encoders) {
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530417 lock_guard<mutex> lock(lock_);
Varun Arora6ba9eda2019-02-07 17:59:32 -0800418 return connector_pool_[connector_id]->GetPossibleEncoders(possible_encoders);
419}
420
Varun Aroradf0dbda2019-03-04 16:29:35 -0800421
Varun Arora6ba9eda2019-02-07 17:59:32 -0800422void DRMConnectorManager::Free(DRMDisplayToken *token) {
423 lock_guard<mutex> lock(lock_);
424 connector_pool_.at(token->conn_id)->Unlock();
425 token->conn_id = 0;
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530426}
427
428// ==============================================================================================//
429
430#undef __CLASS__
431#define __CLASS__ "DRMConnector"
432
433DRMConnector::~DRMConnector() {
434 if (drm_connector_) {
435 drmModeFreeConnector(drm_connector_);
436 }
437}
438
439void DRMConnector::ParseProperties() {
440 drmModeObjectProperties *props =
441 drmModeObjectGetProperties(fd_, drm_connector_->connector_id, DRM_MODE_OBJECT_CONNECTOR);
442 if (!props || !props->props || !props->prop_values) {
443 drmModeFreeObjectProperties(props);
444 return;
445 }
446
447 for (uint32_t j = 0; j < props->count_props; j++) {
448 drmModePropertyRes *info = drmModeGetProperty(fd_, props->props[j]);
449 if (!info) {
450 continue;
451 }
452
453 string property_name(info->name);
454 DRMProperty prop_enum = prop_mgr_.GetPropertyEnum(property_name);
455
456 if (prop_enum == DRMProperty::INVALID) {
457 DRM_LOGD("DRMProperty %s missing from global property mapping", info->name);
458 drmModeFreeProperty(info);
459 continue;
460 }
461
462 if (prop_enum == DRMProperty::LP) {
463 PopulatePowerModes(info);
464 } else if (prop_enum == DRMProperty::FB_TRANSLATION_MODE) {
465 PopulateSecureModes(info);
466 } else if (prop_enum == DRMProperty::QSYNC_MODE) {
467 PopulateQsyncModes(info);
Xu Yang39503f12018-12-24 17:43:36 +0800468 } else if (prop_enum == DRMProperty::FRAME_TRIGGER) {
469 PopulateFrameTriggerModes(info);
Gousemoodhin Nadaf47b82be2019-05-09 15:30:11 +0530470 } else if (prop_enum == DRMProperty::COLORSPACE) {
471 PopulateSupportedColorspaces(info);
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530472 }
473
474 prop_mgr_.SetPropertyId(prop_enum, info->prop_id);
475 drmModeFreeProperty(info);
476 }
477
478 drmModeFreeObjectProperties(props);
479}
480
481void DRMConnector::ParseCapabilities(uint64_t blob_id, DRMConnectorInfo *info) {
482 drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(fd_, blob_id);
483 if (!blob) {
484 return;
485 }
486
487 const char *fmt_str = reinterpret_cast<const char *>(blob->data);
488 stringstream stream(fmt_str);
489 string line = {};
490 const string display_type = "display type=";
491 const string panel_name = "panel name=";
492 const string panel_mode = "panel mode=";
493 const string dfps_support = "dfps support=";
494 const string pixel_formats = "pixel_formats=";
495 const string max_linewidth = "maxlinewidth=";
496 const string panel_orientation = "panel orientation=";
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530497 const string qsync_support = "qsync support=";
498 const string wb_ubwc = "wb_ubwc";
Alex Sarraf24fd2b92018-10-30 18:27:21 +0530499 const string dyn_bitclk_support = "dyn bitclk support=";
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530500
501 while (std::getline(stream, line)) {
502 if (line.find(pixel_formats) != string::npos) {
503 vector<pair<uint32_t, uint64_t>> formats_supported;
504 ParseFormats(line.erase(0, pixel_formats.length()), &formats_supported);
505 info->formats_supported = move(formats_supported);
506 } else if (line.find(max_linewidth) != string::npos) {
507 info->max_linewidth = std::stoi(string(line, max_linewidth.length()));
508 } else if (line.find(display_type) != string::npos) {
509 info->is_primary = (string(line, display_type.length()) == "primary");
510 } else if (line.find(panel_name) != string::npos) {
511 info->panel_name = string(line, panel_name.length());
512 } else if (line.find(panel_mode) != string::npos) {
513 info->panel_mode = (string(line, panel_mode.length()) == "video") ? DRMPanelMode::VIDEO
514 : DRMPanelMode::COMMAND;
515 } else if (line.find(dfps_support) != string::npos) {
516 info->dynamic_fps = (string(line, dfps_support.length()) == "true");
517 } else if (line.find(panel_orientation) != string::npos) {
518 if (string(line, panel_orientation.length()) == "horz flip") {
519 info->panel_orientation = DRMRotation::FLIP_H;
520 } else if (string(line, panel_orientation.length()) == "vert flip") {
521 info->panel_orientation = DRMRotation::FLIP_V;
522 } else if (string(line, panel_orientation.length()) == "horz & vert flip") {
523 info->panel_orientation = DRMRotation::ROT_180;
524 }
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530525 } else if (line.find(qsync_support) != string::npos) {
526 info->qsync_support = (string(line, qsync_support.length()) == "true");
527 } else if (line.find(wb_ubwc) != string::npos) {
528 info->is_wb_ubwc_supported = true;
Alex Sarraf24fd2b92018-10-30 18:27:21 +0530529 } else if (line.find(dyn_bitclk_support) != string::npos) {
530 info->dyn_bitclk_support = (string(line, dyn_bitclk_support.length()) == "true");
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530531 }
532 }
533
534 drmModeFreePropertyBlob(blob);
535}
536
537void DRMConnector::ParseCapabilities(uint64_t blob_id, drm_panel_hdr_properties *hdr_info) {
538 drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(fd_, blob_id);
539 if (!blob) {
540 return;
541 }
542
543 struct drm_panel_hdr_properties *hdr_data = (struct drm_panel_hdr_properties*)(blob->data);
544
545 if (hdr_data) {
546 hdr_info->hdr_enabled = hdr_data->hdr_enabled;
547 hdr_info->peak_brightness = hdr_data->peak_brightness;
548 hdr_info->blackness_level = hdr_data->blackness_level;
549 for (int i = 0; i < DISPLAY_PRIMARIES_MAX; i++) {
550 hdr_info->display_primaries[i] = hdr_data->display_primaries[i];
551 }
552 }
553 drmModeFreePropertyBlob(blob);
554}
555
556void DRMConnector::ParseModeProperties(uint64_t blob_id, DRMConnectorInfo *info) {
557 drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(fd_, blob_id);
558 if (!blob) {
559 return;
560 }
561
562 const char *fmt_str = reinterpret_cast<const char *>(blob->data);
563 stringstream stream(fmt_str);
564 string line = {};
565 const string mode_name = "mode_name=";
566 const string topology = "topology=";
567 const string pu_num_roi = "partial_update_num_roi=";
568 const string pu_xstart = "partial_update_xstart=";
569 const string pu_ystart = "partial_update_ystart=";
570 const string pu_walign = "partial_update_walign=";
571 const string pu_halign = "partial_update_halign=";
572 const string pu_wmin = "partial_update_wmin=";
573 const string pu_hmin = "partial_update_hmin=";
574 const string pu_roimerge = "partial_update_roimerge=";
Alex Sarraf24fd2b92018-10-30 18:27:21 +0530575 const string bit_clk_rate = "bit_clk_rate=";
Alex Sarraf8729aa72019-01-04 18:08:56 -0800576 const string mdp_transfer_time_us = "mdp_transfer_time_us=";
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530577
578 // Map of parsed mode_name to mode_properties
579 map<string, DRMModeInfo> mode_props_map {};
580 auto it = mode_props_map.end();
581 while (std::getline(stream, line)) {
582 if (line.find(mode_name) != string::npos) {
583 string name(line, mode_name.length());
584 it = mode_props_map.insert(make_pair(name, DRMModeInfo())).first;
585 } else if (line.find(topology) != string::npos) {
586 it->second.topology = GetTopologyEnum(string(line, topology.length()));
587 } else if (line.find(pu_num_roi) != string::npos) {
588 it->second.num_roi = std::stoi(string(line, pu_num_roi.length()));
589 } else if (line.find(pu_xstart) != string::npos) {
590 it->second.xstart = std::stoi(string(line, pu_xstart.length()));
591 } else if (line.find(pu_ystart) != string::npos) {
592 it->second.ystart = std::stoi(string(line, pu_ystart.length()));
593 } else if (line.find(pu_walign) != string::npos) {
594 it->second.walign = std::stoi(string(line, pu_walign.length()));
595 } else if (line.find(pu_halign) != string::npos) {
596 it->second.halign = std::stoi(string(line, pu_halign.length()));
597 } else if (line.find(pu_wmin) != string::npos) {
598 it->second.wmin = std::stoi(string(line, pu_wmin.length()));
599 } else if (line.find(pu_hmin) != string::npos) {
600 it->second.hmin = std::stoi(string(line, pu_hmin.length()));
601 } else if (line.find(pu_roimerge) != string::npos) {
602 it->second.roi_merge = std::stoi(string(line, pu_roimerge.length()));
Alex Sarraf24fd2b92018-10-30 18:27:21 +0530603 } else if (line.find(bit_clk_rate) != string::npos) {
604 it->second.bit_clk_rate = std::stoi(string(line, bit_clk_rate.length()));
Alex Sarraf8729aa72019-01-04 18:08:56 -0800605 } else if (line.find(mdp_transfer_time_us) != string::npos) {
606 it->second.transfer_time_us = std::stoi(string(line, mdp_transfer_time_us.length()));
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530607 }
608 }
609
610 for (uint32_t i = 0; i < info->modes.size(); i++) {
611 DRMModeInfo &mode_item = info->modes.at(i);
612 auto it = mode_props_map.find(string(mode_item.mode.name));
613 if (it != mode_props_map.end()) {
614 mode_item.topology = it->second.topology;
615 mode_item.num_roi = it->second.num_roi;
616 mode_item.roi_merge = it->second.roi_merge;
617 mode_item.xstart = it->second.xstart;
618 mode_item.ystart = it->second.ystart;
619 mode_item.wmin = it->second.wmin;
620 mode_item.hmin = it->second.hmin;
621 mode_item.walign = it->second.walign;
622 mode_item.halign = it->second.halign;
Alex Sarraf24fd2b92018-10-30 18:27:21 +0530623 mode_item.bit_clk_rate = it->second.bit_clk_rate;
Alex Sarraf8729aa72019-01-04 18:08:56 -0800624 mode_item.transfer_time_us = it->second.transfer_time_us;
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530625 }
626 }
627
628 drmModeFreePropertyBlob(blob);
629}
630
631void DRMConnector::ParseCapabilities(uint64_t blob_id, drm_msm_ext_hdr_properties *hdr_info) {
632 drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(fd_, blob_id);
633 if (!blob) {
634 return;
635 }
636
637 struct drm_msm_ext_hdr_properties *hdr_cdata = (struct drm_msm_ext_hdr_properties*)(blob->data);
638
Gousemoodhin Nadaf47b82be2019-05-09 15:30:11 +0530639 if (hdr_cdata) {
640 hdr_info->hdr_supported = hdr_cdata->hdr_supported;
641 hdr_info->hdr_plus_supported = hdr_cdata->hdr_plus_supported;
642 hdr_info->hdr_eotf = hdr_cdata->hdr_eotf;
643 hdr_info->hdr_metadata_type_one = hdr_cdata->hdr_metadata_type_one;
644 hdr_info->hdr_max_luminance = hdr_cdata->hdr_max_luminance;
645 hdr_info->hdr_avg_luminance = hdr_cdata->hdr_avg_luminance;
646 hdr_info->hdr_min_luminance = hdr_cdata->hdr_min_luminance;
647 DRM_LOGI("hdr_supported = %d, hdr_plus_supported = %d, hdr_eotf = %d, "
648 "hdr_metadata_type_one = %d, hdr_max_luminance = %d, hdr_avg_luminance = %d, "
649 "hdr_min_luminance = %d\n", hdr_info->hdr_supported,
650 hdr_info->hdr_plus_supported,
651 hdr_info->hdr_eotf, hdr_info->hdr_metadata_type_one, hdr_info->hdr_max_luminance,
652 hdr_info->hdr_avg_luminance, hdr_info->hdr_min_luminance);
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530653 }
654 drmModeFreePropertyBlob(blob);
655}
656
Varun Arora6ba9eda2019-02-07 17:59:32 -0800657void DRMConnector::ParseCapabilities(uint64_t blob_id, std::vector<uint8_t> *edid) {
658 drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(fd_, blob_id);
659 if (!blob) {
660 return;
661 }
662
663 uint8_t *edid_blob = (uint8_t*)(blob->data);
664 uint32_t length = blob->length;
665 (*edid).assign(edid_blob, edid_blob + length);
666
667 drmModeFreePropertyBlob(blob);
668}
669
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530670int DRMConnector::GetInfo(DRMConnectorInfo *info) {
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530671 uint32_t conn_id = drm_connector_->connector_id;
Mathew Joseph Karimpanala46c8d82018-12-06 19:10:56 +0530672 if (!skip_connector_reload_ && (IsTVConnector(drm_connector_->connector_type)
673 || (DRM_MODE_CONNECTOR_VIRTUAL == drm_connector_->connector_type))) {
674 // Reload since for some connectors like Virtual and DP, modes may change.
675 drmModeConnectorPtr drm_connector = drmModeGetConnector(fd_, conn_id);
676 if (!drm_connector) {
677 // Connector resource not found. This could happen if a connector is removed before a commit
678 // was done on it. Mark the connector as disconnected for graceful teardown. Update 'info'
679 // with basic information from previously initialized drm_connector_ for graceful teardown.
680 info->is_connected = false;
681 info->modes.clear();
682 info->type = drm_connector_->connector_type;
Varun Arora75c05f02019-05-14 14:53:37 -0700683 info->type_id = drm_connector_->connector_type_id;
Mathew Joseph Karimpanala46c8d82018-12-06 19:10:56 +0530684 DLOGW("Connector %u not found. Possibly removed.", conn_id);
685 return 0;
686 }
687 drmModeFreeConnector(drm_connector_);
688 drm_connector_ = drm_connector;
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530689 }
690
Mathew Joseph Karimpanala46c8d82018-12-06 19:10:56 +0530691 SetSkipConnectorReload(false); // Reset skip_connector_reload_ setting.
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530692 info->modes.clear();
693 if (!drm_connector_->count_modes) {
694 DRM_LOGW("Zero modes on connector %u.", conn_id);
695 }
696 for (auto i = 0; i < drm_connector_->count_modes; i++) {
697 DRMModeInfo modes_item {};
698 modes_item.mode = drm_connector_->modes[i];
699 info->modes.push_back(modes_item);
700 }
701 info->mmWidth = drm_connector_->mmWidth;
702 info->mmHeight = drm_connector_->mmHeight;
703 info->type = drm_connector_->connector_type;
Varun Arora75c05f02019-05-14 14:53:37 -0700704 info->type_id = drm_connector_->connector_type_id;
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530705 info->is_connected = IsConnected();
706
707 drmModeObjectProperties *props =
708 drmModeObjectGetProperties(fd_, drm_connector_->connector_id, DRM_MODE_OBJECT_CONNECTOR);
709 if (!props || !props->props || !props->prop_values) {
710 drmModeFreeObjectProperties(props);
711 return -ENODEV;
712 }
713
714 uint32_t index = UINT32_MAX;
715
716 if (prop_mgr_.IsPropertyAvailable(DRMProperty::HDR_PROPERTIES)) {
717 index = std::distance(props->props,
718 std::find(props->props, props->props + props->count_props,
719 prop_mgr_.GetPropertyId(DRMProperty::HDR_PROPERTIES)));
720 if (index < props->count_props)
721 ParseCapabilities(props->prop_values[index], &info->panel_hdr_prop);
722 }
723
724 if (prop_mgr_.IsPropertyAvailable(DRMProperty::CAPABILITIES)) {
725 index = std::distance(props->props,
726 std::find(props->props, props->props + props->count_props,
727 prop_mgr_.GetPropertyId(DRMProperty::CAPABILITIES)));
728 if (index < props->count_props)
729 ParseCapabilities(props->prop_values[index], info);
730 }
731
732 if (prop_mgr_.IsPropertyAvailable(DRMProperty::MODE_PROPERTIES)) {
733 index = std::distance(props->props,
734 std::find(props->props, props->props + props->count_props,
735 prop_mgr_.GetPropertyId(DRMProperty::MODE_PROPERTIES)));
736 if (index < props->count_props)
737 ParseModeProperties(props->prop_values[index], info);
738 }
739
740 if (prop_mgr_.IsPropertyAvailable(DRMProperty::EXT_HDR_PROPERTIES)) {
741 index = std::distance(props->props,
742 std::find(props->props, props->props + props->count_props,
743 prop_mgr_.GetPropertyId(DRMProperty::EXT_HDR_PROPERTIES)));
744 if (index < props->count_props)
745 ParseCapabilities(props->prop_values[index], &info->ext_hdr_prop);
746 }
747
748 if (prop_mgr_.IsPropertyAvailable(DRMProperty::TOPOLOGY_CONTROL)) {
749 index = std::distance(props->props,
750 std::find(props->props, props->props + props->count_props,
751 prop_mgr_.GetPropertyId(DRMProperty::TOPOLOGY_CONTROL)));
752 info->topology_control = props->prop_values[index];
753 }
Varun Arora6ba9eda2019-02-07 17:59:32 -0800754 if (prop_mgr_.IsPropertyAvailable(DRMProperty::EDID)) {
755 index = std::distance(props->props,
756 std::find(props->props, props->props + props->count_props,
757 prop_mgr_.GetPropertyId(DRMProperty::EDID)));
758 ParseCapabilities(props->prop_values[index], &info->edid);
759 }
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530760
Gousemoodhin Nadaf47b82be2019-05-09 15:30:11 +0530761 if (prop_mgr_.IsPropertyAvailable(DRMProperty::SUPPORTED_COLORSPACES)) {
762 index = std::distance(props->props,
763 std::find(props->props, props->props + props->count_props,
764 prop_mgr_.GetPropertyId(DRMProperty::SUPPORTED_COLORSPACES)));
765 info->supported_colorspaces = props->prop_values[index];
766 }
767
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530768 drmModeFreeObjectProperties(props);
769
770 return 0;
771}
772
773void DRMConnector::InitAndParse(drmModeConnector *conn) {
774 drm_connector_ = conn;
775 ParseProperties();
776 pp_mgr_ = std::unique_ptr<DRMPPManager>(new DRMPPManager(fd_));
777 pp_mgr_->Init(prop_mgr_, DRM_MODE_OBJECT_CONNECTOR);
778}
779
780void DRMConnector::Perform(DRMOps code, drmModeAtomicReq *req, va_list args) {
781 uint32_t obj_id = drm_connector_->connector_id;
782
783 switch (code) {
784 case DRMOps::CONNECTOR_SET_CRTC: {
785 uint32_t crtc = va_arg(args, uint32_t);
786 drmModeAtomicAddProperty(req, obj_id, prop_mgr_.GetPropertyId(DRMProperty::CRTC_ID), crtc);
787 DRM_LOGD("Connector %d: Setting CRTC %d", obj_id, crtc);
788 } break;
789
790 case DRMOps::CONNECTOR_GET_RETIRE_FENCE: {
791 int64_t *fence = va_arg(args, int64_t *);
792 *fence = -1;
793 uint32_t prop_id = prop_mgr_.GetPropertyId(DRMProperty::RETIRE_FENCE);
794 drmModeAtomicAddProperty(req, obj_id, prop_id, reinterpret_cast<uint64_t>(fence));
795 } break;
796
797 case DRMOps::CONNECTOR_SET_OUTPUT_RECT: {
798 DRMRect rect = va_arg(args, DRMRect);
799 drmModeAtomicAddProperty(req, obj_id,
800 prop_mgr_.GetPropertyId(DRMProperty::DST_X), rect.left);
801 drmModeAtomicAddProperty(req, obj_id,
802 prop_mgr_.GetPropertyId(DRMProperty::DST_Y), rect.top);
803 drmModeAtomicAddProperty(req, obj_id, prop_mgr_.GetPropertyId(DRMProperty::DST_W),
804 rect.right - rect.left);
805 drmModeAtomicAddProperty(req, obj_id, prop_mgr_.GetPropertyId(DRMProperty::DST_H),
806 rect.bottom - rect.top);
807 DRM_LOGD("Connector %d: Setting dst [x,y,w,h][%d,%d,%d,%d]", obj_id, rect.left,
808 rect.top, (rect.right - rect.left), (rect.bottom - rect.top));
809 } break;
810
811 case DRMOps::CONNECTOR_SET_OUTPUT_FB_ID: {
812 uint32_t fb_id = va_arg(args, uint32_t);
813 drmModeAtomicAddProperty(req, obj_id, prop_mgr_.GetPropertyId(DRMProperty::FB_ID), fb_id);
814 DRM_LOGD("Connector %d: Setting fb_id %d", obj_id, fb_id);
815 } break;
816
817 case DRMOps::CONNECTOR_SET_POWER_MODE: {
818 int drm_power_mode = va_arg(args, int);
819 uint32_t power_mode = ON;
820 switch (drm_power_mode) {
821 case (int)DRMPowerMode::ON:
822 power_mode = ON;
823 break;
824 case (int)DRMPowerMode::DOZE:
825 power_mode = DOZE;
826 break;
827 case (int)DRMPowerMode::DOZE_SUSPEND:
828 power_mode = DOZE_SUSPEND;
829 break;
830 case (int)DRMPowerMode::OFF:
831 power_mode = OFF;
832 break;
833 default:
834 DRM_LOGE("Invalid power mode %d to set on connector %d", drm_power_mode, obj_id);
835 break;
836 }
837 drmModeAtomicAddProperty(req, obj_id, prop_mgr_.GetPropertyId(DRMProperty::LP), power_mode);
838 DRM_LOGD("Connector %d: Setting power_mode %d", obj_id, power_mode);
839 } break;
840
841 case DRMOps::CONNECTOR_SET_ROI: {
842 uint32_t num_roi = va_arg(args, uint32_t);
843 DRMRect *conn_rois = va_arg(args, DRMRect*);
844 SetROI(req, obj_id, num_roi, conn_rois);
845 } break;
846
847 case DRMOps::CONNECTOR_SET_AUTOREFRESH: {
848 uint32_t enable = va_arg(args, uint32_t);
849 drmModeAtomicAddProperty(req, obj_id, prop_mgr_.GetPropertyId(DRMProperty::AUTOREFRESH),
850 enable);
851 DRM_LOGD("Connector %d: Setting autorefresh %d", obj_id, enable);
852 } break;
853
854 case DRMOps::CONNECTOR_SET_FB_SECURE_MODE: {
855 int secure_mode = va_arg(args, int);
856 uint32_t fb_secure_mode = (secure_mode == (int)DRMSecureMode::SECURE) ? SECURE : NON_SECURE;
857 drmModeAtomicAddProperty(req, obj_id,
858 prop_mgr_.GetPropertyId(DRMProperty::FB_TRANSLATION_MODE),
859 fb_secure_mode);
860 DRM_LOGD("Connector %d: Setting FB secure mode %d", obj_id, fb_secure_mode);
861 } break;
862
863 case DRMOps::CONNECTOR_SET_POST_PROC: {
864 DRMPPFeatureInfo *data = va_arg(args, DRMPPFeatureInfo*);
865 if (data)
866 pp_mgr_->SetPPFeature(req, obj_id, *data);
867 } break;
868
869 case DRMOps::CONNECTOR_SET_HDR_METADATA: {
870 drm_msm_ext_hdr_metadata *hdr_metadata = va_arg(args, drm_msm_ext_hdr_metadata *);
871 drmModeAtomicAddProperty(req, obj_id, prop_mgr_.GetPropertyId(DRMProperty::HDR_METADATA),
872 reinterpret_cast<uint64_t>(hdr_metadata));
873 } break;
874
875 case DRMOps::CONNECTOR_SET_QSYNC_MODE: {
876 if (!prop_mgr_.IsPropertyAvailable(DRMProperty::QSYNC_MODE)) {
877 return;
878 }
879 int drm_qsync_mode = va_arg(args, int);
880 uint32_t qsync_mode =
881 (drm_qsync_mode == (int)DRMQsyncMode::NONE) ? QSYNC_MODE_NONE : QSYNC_MODE_CONTINUOUS;
882 drmModeAtomicAddProperty(req, obj_id, prop_mgr_.GetPropertyId(DRMProperty::QSYNC_MODE),
883 qsync_mode);
884 DRM_LOGD("Connector %d: Setting Qsync mode %d", obj_id, qsync_mode);
885 } break;
886
887 case DRMOps::CONNECTOR_SET_TOPOLOGY_CONTROL: {
888 uint32_t topology_control = va_arg(args, uint32_t);
889 drmModeAtomicAddProperty(req, obj_id, prop_mgr_.GetPropertyId(DRMProperty::TOPOLOGY_CONTROL),
890 topology_control);
891 } break;
892
Xu Yang39503f12018-12-24 17:43:36 +0800893 case DRMOps::CONNECTOR_SET_FRAME_TRIGGER: {
894 if (!prop_mgr_.IsPropertyAvailable(DRMProperty::FRAME_TRIGGER)) {
895 return;
896 }
897 int drm_frame_trigger_mode = va_arg(args, int);
898 DRMFrameTriggerMode mode = static_cast<DRMFrameTriggerMode>(drm_frame_trigger_mode);
899 int32_t frame_trigger_mode = -1;
900 switch (mode) {
901 case (DRMFrameTriggerMode::FRAME_DONE_WAIT_DEFAULT):
902 frame_trigger_mode = FRAME_TRIGGER_DEFAULT;
903 break;
904 case (DRMFrameTriggerMode::FRAME_DONE_WAIT_SERIALIZE):
905 frame_trigger_mode = FRAME_TRIGGER_SERIALIZE;
906 break;
907 case (DRMFrameTriggerMode::FRAME_DONE_WAIT_POSTED_START):
908 frame_trigger_mode = FRAME_TRIGGER_POSTED_START;
909 break;
910 default:
911 DRM_LOGE("Invalid frame trigger mode %d to set on connector %d",
912 drm_frame_trigger_mode, obj_id);
913 break;
914 }
915 if (frame_trigger_mode >= 0) {
916 uint32_t prop_id = prop_mgr_.GetPropertyId(DRMProperty::FRAME_TRIGGER);
917 int ret = drmModeAtomicAddProperty(req, obj_id, prop_id, frame_trigger_mode);
Xu Yangc07ec4d2019-05-08 14:54:24 +0800918 if (ret < 0) {
Xu Yang39503f12018-12-24 17:43:36 +0800919 DRM_LOGE("AtomicAddProperty failed obj_id 0x%x, prop_id %d mode %d ret %d",
920 obj_id, prop_id, frame_trigger_mode, ret);
921 } else {
922 DRM_LOGD("Connector %d: Setting frame trigger mode %d", obj_id, frame_trigger_mode);
923 }
924 }
925 } break;
926
Gousemoodhin Nadaf47b82be2019-05-09 15:30:11 +0530927 case DRMOps::CONNECTOR_SET_COLORSPACE: {
928 if (!prop_mgr_.IsPropertyAvailable(DRMProperty::COLORSPACE)) {
929 return;
930 }
931 DRMColorspace drm_colorspace = static_cast<DRMColorspace>(va_arg(args, uint32_t));
932 int32_t colorspace = 0;
933 colorspace = GetColorspace(drm_colorspace);
934 if (colorspace >= 0) {
935 uint32_t prop_id = prop_mgr_.GetPropertyId(DRMProperty::COLORSPACE);
936 int ret = drmModeAtomicAddProperty(req, obj_id, prop_id, colorspace);
937 if (ret < 0) {
938 DRM_LOGE("AtomicAddProperty failed obj_id 0x%x, prop_id %d mode %d ret %d",
939 obj_id, prop_id, colorspace, ret);
940 } else {
941 DRM_LOGD("Connector %d: Setting colorspace %d", obj_id, colorspace);
942 }
943 } else {
944 DRM_LOGE("Invalid colorspace %d", colorspace);
945 }
946 } break;
947
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530948 default:
949 DRM_LOGE("Invalid opcode %d to set on connector %d", code, obj_id);
950 break;
951 }
952}
953
954void DRMConnector::SetROI(drmModeAtomicReq *req, uint32_t obj_id, uint32_t num_roi,
955 DRMRect *conn_rois) {
956#ifdef SDE_MAX_ROI_V1
Ramkumar Radhakrishnanf7f52162019-06-06 19:40:04 -0700957 if (num_roi > SDE_MAX_ROI_V1 || !prop_mgr_.IsPropertyAvailable(DRMProperty::ROI_V1)) {
958 return;
959 }
960 if (!num_roi || !conn_rois) {
961 drmModeAtomicAddProperty(req, obj_id, prop_mgr_.GetPropertyId(DRMProperty::ROI_V1), 0);
962 DRM_LOGD("Connector ROI is set to NULL to indicate full frame update");
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530963 return;
964 }
965
966 static struct sde_drm_roi_v1 roi_v1 {};
Ramkumar Radhakrishnan4518d302019-06-18 19:57:41 -0700967 memset(&roi_v1, 0, sizeof(roi_v1));
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530968 roi_v1.num_rects = num_roi;
969
970 for (uint32_t i = 0; i < num_roi; i++) {
971 roi_v1.roi[i].x1 = conn_rois[i].left;
972 roi_v1.roi[i].x2 = conn_rois[i].right;
973 roi_v1.roi[i].y1 = conn_rois[i].top;
974 roi_v1.roi[i].y2 = conn_rois[i].bottom;
975 DRM_LOGD("Conn %d, ROI[l,t,b,r][%d %d %d %d]", obj_id,
976 roi_v1.roi[i].x1,roi_v1.roi[i].y1,roi_v1.roi[i].x2,roi_v1.roi[i].y2);
977 }
978 drmModeAtomicAddProperty(req, obj_id, prop_mgr_.GetPropertyId(DRMProperty::ROI_V1),
979 reinterpret_cast<uint64_t>(&roi_v1));
980#endif
981}
982
Varun Arora6ba9eda2019-02-07 17:59:32 -0800983int DRMConnector::GetPossibleEncoders(set<uint32_t> *possible_encoders) {
984 if (!possible_encoders) {
985 return -EINVAL;
986 }
987
988 uint32_t count_enc = drm_connector_->count_encoders;
989 if (count_enc == 0) {
990 DRM_LOGW("No possible encoders for connector %u", drm_connector_->connector_id);
991 }
992
993 (*possible_encoders).clear();
994 for (uint32_t i = 0; i < count_enc; i++) {
995 (*possible_encoders).insert(drm_connector_->encoders[i]);
996 }
997
998 return 0;
999}
1000
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +05301001void DRMConnector::Dump() {
1002 DRM_LOGE("id: %d\tenc_id: %d\tconn: %d\ttype: %d\tPhy: %dx%d\n", drm_connector_->connector_id,
1003 drm_connector_->encoder_id, drm_connector_->connection, drm_connector_->connector_type,
1004 drm_connector_->mmWidth, drm_connector_->mmHeight);
1005 DRM_LOGE("Modes: \n");
1006 for (uint32_t i = 0; i < (uint32_t)drm_connector_->count_modes; i++) {
1007 DRM_LOGE(
1008 "Name: %s\tvref: %d\thdisp: %d\t hsync_s: %d\thsync_e:%d\thtotal: %d\t"
1009 "vdisp: %d\tvsync_s: %d\tvsync_e: %d\tvtotal: %d\n",
1010 drm_connector_->modes[i].name, drm_connector_->modes[i].vrefresh,
1011 drm_connector_->modes[i].hdisplay, drm_connector_->modes[i].hsync_start,
1012 drm_connector_->modes[i].hsync_end, drm_connector_->modes[i].htotal,
1013 drm_connector_->modes[i].vdisplay, drm_connector_->modes[i].vsync_start,
1014 drm_connector_->modes[i].vsync_end, drm_connector_->modes[i].vtotal);
1015 }
1016}
1017
1018} // namespace sde_drm