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