• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2021, The Linux Foundataion. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29 
30 #include <sstream>
31 #include <errno.h>
32 #include <string>
33 #include <drm_logger.h>
34 #include <cstring>
35 #include <regex>
36 #include <inttypes.h>
37 
38 #include "drm_panel_feature_mgr.h"
39 
40 #define __CLASS__ "DRMPanelFeatureMgr"
41 
42 namespace sde_drm {
43 
44 using std::map;
45 using std::vector;
46 using std::mutex;
47 using std::lock_guard;
48 
49 static DRMPanelFeatureMgr panel_feature_mgr;
50 
GetPanelFeatureManagerIntf()51 DRMPanelFeatureMgrIntf *GetPanelFeatureManagerIntf() {
52   return &panel_feature_mgr;
53 }
54 
Init(int fd,drmModeRes * res)55 void DRMPanelFeatureMgr::Init(int fd, drmModeRes* res) {
56   lock_guard<mutex> lock(lock_);
57 
58   if (!res || (fd < 0)) {
59     DRM_LOGE("Invalid arguments for init - fd %d and DRM resources pointer 0x%p", fd, (void *)res);
60     return;
61   }
62 
63   drm_res_ = res;
64   dev_fd_ = fd;
65 
66   for (int i = 0; i < res->count_crtcs; i++) {
67     drmModeCrtc *crtc = drmModeGetCrtc(dev_fd_, res->crtcs[i]);
68     if (crtc) {
69       int err = InitObjectProps(crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
70       if (err) {
71         DRM_LOGE("Failed to get crtc props %d", crtc->crtc_id);
72       }
73       drmModeFreeCrtc(crtc);
74     }
75   }
76 
77   for (int i = 0; i < res->count_connectors; i++) {
78     drmModeConnector *conn = drmModeGetConnector(dev_fd_, res->connectors[i]);
79     if (conn) {
80       int err = InitObjectProps(conn->connector_id, DRM_MODE_OBJECT_CONNECTOR);
81       if (err) {
82         DRM_LOGE("Failed to get conn %d properties", conn->connector_id);
83       }
84       drmModeFreeConnector(conn);
85     }
86   }
87 
88   drm_property_map_[kDRMPanelFeatureDsppRCInfo] = DRMProperty::DSPP_CAPABILITIES;
89   drm_property_map_[kDRMPanelFeatureRCInit] = DRMProperty::DSPP_RC_MASK_V1;
90   drm_prop_type_map_[kDRMPanelFeatureRCInit] = DRMPropType::kPropBlob;
91   drm_prop_type_map_[kDRMPanelFeatureDsppRCInfo] = DRMPropType::kPropRange;
92 
93 
94   feature_info_tbl_[kDRMPanelFeatureRCInit] = DRMPanelFeatureInfo {
95       kDRMPanelFeatureRCInit, DRM_MODE_OBJECT_CRTC, UINT32_MAX, 1, sizeof(msm_rc_mask_cfg), 0};
96 
97   feature_info_tbl_[kDRMPanelFeatureDsppRCInfo] = DRMPanelFeatureInfo {
98     kDRMPanelFeatureDsppRCInfo, DRM_MODE_OBJECT_CRTC, UINT32_MAX, 1, 64, 0};
99 }
100 
DeInit()101 void DRMPanelFeatureMgr::DeInit() {
102   int ret = 0;
103   for (int i = 0; i < kDRMPanelFeatureMax; i++) {
104     DRMPanelFeatureID prop_id = static_cast<DRMPanelFeatureID>(i);
105     if (drm_prop_blob_ids_map_[prop_id]) {
106       ret = drmModeDestroyPropertyBlob(dev_fd_, drm_prop_blob_ids_map_[prop_id]);
107       if (ret) {
108         DRM_LOGE("failed to destroy blob for feature %d, ret = %d", prop_id, ret);
109         return;
110       } else {
111         drm_prop_blob_ids_map_[prop_id] = 0;
112       }
113     }
114   }
115 }
116 
InitObjectProps(int obj_id,int obj_type)117 int DRMPanelFeatureMgr::InitObjectProps(int obj_id, int obj_type) {
118   if (dev_fd_ < 0 || obj_id < 0) {
119     DRM_LOGE("Invalid dev_fd_ %d or crtc_id %d", dev_fd_, obj_id);
120     return -EINVAL;
121   }
122 
123   drmModeObjectProperties *props =
124           drmModeObjectGetProperties(dev_fd_, obj_id, obj_type);
125   if (!props || !props->props || !props->prop_values) {
126     DRM_LOGE("Failed to get props for obj_id:%d obj_type:%d", obj_id, obj_type);
127     drmModeFreeObjectProperties(props);
128     return -EINVAL;
129   }
130 
131   for (uint32_t j = 0; j < props->count_props; j++) {
132     drmModePropertyRes *info = drmModeGetProperty(dev_fd_, props->props[j]);
133     if (!info) {
134       continue;
135     }
136 
137     std::string property_name(info->name);
138     DRMProperty prop_enum = prop_mgr_.GetPropertyEnum(property_name);
139     if (prop_enum == DRMProperty::INVALID) {
140       DRM_LOGD("DRMProperty %s missing from global property mapping", info->name);
141       drmModeFreeProperty(info);
142       continue;
143     }
144 
145     prop_mgr_.SetPropertyId(prop_enum, info->prop_id);
146     drmModeFreeProperty(info);
147   }
148 
149   drmModeFreeObjectProperties(props);
150   return 0;
151 }
152 
ParseDsppCapabilities(uint32_t blob_id,std::vector<int> * values,uint32_t * size,const std::string str)153 void DRMPanelFeatureMgr::ParseDsppCapabilities(uint32_t blob_id, std::vector<int> *values,
154                                             uint32_t *size, const std::string str) {
155   drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(dev_fd_, blob_id);
156   if (!blob) {
157     DRM_LOGW("Unable to find blob for id %d", blob_id);
158     return;
159   }
160 
161   if (!blob->data) {
162     DRM_LOGW("Invalid blob - no data for for blob-id %d", blob_id);
163     return;
164   }
165 
166   char *fmt_str = new char[blob->length + 1];
167   std::memcpy(fmt_str, blob->data, blob->length);
168   fmt_str[blob->length] = '\0';
169   std::stringstream stream(fmt_str);
170   std::string line = {};
171   // Search for panel feature property pattern. Which is defined as rc0=1, rc1=1
172   const std::regex exp(str + "(\\d+)=1");
173   std::smatch sm;
174   while (std::getline(stream, line)) {
175     std::regex_match(line, sm, exp);
176     // smatch shall include full line as a match followed by the hw block # as a match
177     if (sm.size() == 2) {
178       std::string tmpstr(sm[1]);
179       int temp = atoi(tmpstr.c_str());  // atoi safe to use due to regex success
180       values->push_back(temp);
181     }
182   }
183 
184   *size = sizeof(int) * values->size();
185   delete[] fmt_str;
186 }
187 
ParseCapabilities(uint32_t blob_id,char * value,uint32_t max_len,const std::string str)188 void DRMPanelFeatureMgr::ParseCapabilities(uint32_t blob_id, char* value, uint32_t max_len,
189                                            const std::string str) {
190   drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(dev_fd_, blob_id);
191   if (!blob) {
192     DRM_LOGW("Unable to find blob for id %d", blob_id);
193     return;
194   }
195 
196   if (!blob->data) {
197     DRM_LOGW("Invalid blob - no data for for blob-id %d", blob_id);
198     return;
199   }
200 
201   char *fmt_str = new char[blob->length + 1];
202   std::memcpy(fmt_str, blob->data, blob->length);
203   fmt_str[blob->length] = '\0';
204   std::stringstream stream(fmt_str);
205   std::string line = {};
206   std::string val = {};
207   const std::string goal = str + "=";
208   while (std::getline(stream, line)) {
209     if (line.find(goal) != std::string::npos) {
210       val = std::string(line, goal.length());
211     }
212   }
213 
214   if (max_len <= val.size()) {
215     DRM_LOGW("Insufficient size max_len: %d actual size: %zu", max_len, val.size());
216     return;
217   }
218   std::copy(val.begin(), val.end(), value);
219   value[val.size()] = '\0';
220   delete[] fmt_str;
221 }
222 
GetPanelFeatureInfo(DRMPanelFeatureInfo * info)223 void DRMPanelFeatureMgr::GetPanelFeatureInfo(DRMPanelFeatureInfo *info) {
224   lock_guard<mutex> lock(lock_);
225 
226   if (!info) {
227     DRM_LOGE("Invalid input, DRMPanelFeatureInfo is NULL");
228     return;
229   }
230 
231   if (info->prop_id > kDRMPanelFeatureMax) {
232     DRM_LOGE("Invalid feature id %d", info->prop_id);
233     return;
234   }
235 
236   DRMProperty prop_enum = drm_property_map_[info->prop_id];
237   if (!prop_mgr_.IsPropertyAvailable(prop_enum)) {
238     DRM_LOGE("Property id is not available for DRMProperty: %d feature-id: %d",
239              prop_enum, info->prop_id);
240     return;
241   }
242 
243   // memory is not allocated by client - populate default property info
244   if (!info->prop_ptr) {
245     *info = feature_info_tbl_[info->prop_id];
246     return;
247   }
248 
249   drmModeObjectProperties *props =
250           drmModeObjectGetProperties(dev_fd_, info->obj_id, info->obj_type);
251   if (!props || !props->props || !props->prop_values) {
252     drmModeFreeObjectProperties(props);
253     DRM_LOGE("Failed to Get properties for obj: %d type:%d", info->obj_id, info->obj_type);
254     return;
255   }
256 
257   for (uint32_t j = 0; j < props->count_props; j++) {
258     drmModePropertyRes *property = drmModeGetProperty(dev_fd_, props->props[j]);
259     if (!property) {
260       continue;
261     }
262 
263     std::string property_name(property->name);
264     if (prop_enum != prop_mgr_.GetPropertyEnum(property_name)) {
265       drmModeFreeProperty(property);
266       continue;
267     }
268     else if (info->prop_id == kDRMPanelFeatureDsppRCInfo) {
269       ParseDsppCapabilities(props->prop_values[j],
270               reinterpret_cast<std::vector<int> *> (info->prop_ptr), &(info->prop_size), "rc");
271     } else if (drm_prop_type_map_[info->prop_id] == DRMPropType::kPropBlob) {
272       drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(dev_fd_, props->prop_values[j]);
273       if (!blob || !blob->data || !blob->length) {
274         return;
275       }
276       uint8_t *src_begin = reinterpret_cast<uint8_t *> (blob->data);
277       uint8_t *src_end = src_begin + blob->length;
278       uint8_t *dst = reinterpret_cast<uint8_t *> (info->prop_ptr);
279       std::copy(src_begin, src_end, dst);
280     } else {
281       uint8_t *src_begin = reinterpret_cast<uint8_t *> (props->prop_values[j]);
282       uint8_t *src_end = src_begin + info->prop_size;
283       uint8_t *dst = reinterpret_cast<uint8_t *> (info->prop_ptr);
284       std::copy(src_begin, src_end, dst);
285     }
286 
287     drmModeFreeProperty(property);
288   }
289 
290   drmModeFreeObjectProperties(props);
291 }
292 
CachePanelFeature(const DRMPanelFeatureInfo & info)293 void DRMPanelFeatureMgr::CachePanelFeature(const DRMPanelFeatureInfo &info) {
294   lock_guard<mutex> lock(lock_);
295 
296   if (info.prop_id >= kDRMPanelFeatureMax || info.obj_id == UINT32_MAX) {
297     DRM_LOGE("invalid property info to set id %d value ptr %" PRIu64 , info.prop_id, info.prop_ptr);
298     return;
299   }
300 
301   dirty_features_[info.prop_id].first = true;
302   dirty_features_[info.prop_id].second = info;
303 }
304 
CommitPanelFeatures(drmModeAtomicReq * req,const DRMDisplayToken & tok)305 void DRMPanelFeatureMgr::CommitPanelFeatures(drmModeAtomicReq *req, const DRMDisplayToken &tok) {
306   int ret = 0;
307 
308   lock_guard<mutex> lock(lock_);
309   for (auto it = dirty_features_.begin(); it != dirty_features_.end(); it++) {
310     DRMPanelFeatureInfo &info = it->second;
311 
312     if (!it->first)
313         continue;
314 
315     if (info.prop_id >= kDRMPanelFeatureMax) {
316       DRM_LOGE("invalid property info to set id %d value ptr %" PRIu64 , info.prop_id, info.prop_ptr);
317       continue;
318     }
319 
320     // Commit only features meant for the given DisplayToken
321     if (tok.crtc_id != info.obj_id && tok.conn_id != info.obj_id) {
322       continue;
323     }
324 
325     uint32_t prop_id = prop_mgr_.GetPropertyId(drm_property_map_[info.prop_id]);
326     uint64_t value = 0;
327 
328     if (DRMPropType::kPropBlob == drm_prop_type_map_[info.prop_id]) {
329       uint32_t blob_id = 0;
330       if (!info.prop_ptr) {
331         // Reset the feature.
332         ret = drmModeAtomicAddProperty(req, info.obj_id, prop_id, 0);
333         if (ret < 0) {
334           DRM_LOGE("failed to add property ret:%d, obj_id:%d prop_id:%u value:%" PRIu64,
335                     ret, info.obj_id, prop_id, value);
336           return;
337         }
338         continue;
339       }
340 
341       ret = drmModeCreatePropertyBlob(dev_fd_, reinterpret_cast<void *> (info.prop_ptr),
342               info.prop_size, &blob_id);
343       if (ret || blob_id == 0) {
344         DRM_LOGE("failed to create blob ret %d, id = %d prop_ptr:%" PRIu64 " prop_sz:%d",
345                 ret, blob_id, info.prop_ptr, info.prop_size);
346         return;
347       }
348 
349       if (drm_prop_blob_ids_map_[info.prop_id]) {
350         ret = drmModeDestroyPropertyBlob(dev_fd_, drm_prop_blob_ids_map_[info.prop_id]);
351         if (ret) {
352           DRM_LOGE("failed to destroy blob for feature %d, ret = %d", info.prop_id, ret);
353           return;
354         }
355       }
356       drm_prop_blob_ids_map_[info.prop_id] = blob_id;
357 
358       value = blob_id;
359     } else if (info.prop_size == sizeof(uint64_t)) {
360       value = (reinterpret_cast<uint64_t *> (info.prop_ptr))[0];
361     } else {
362       DRM_LOGE("Unsupported property type id = %d size:%d", info.prop_id, info.prop_size);
363     }
364 
365     ret = drmModeAtomicAddProperty(req, info.obj_id, prop_id, value);
366     if (ret < 0) {
367       DRM_LOGE("failed to add property ret:%d, obj_id:%d prop_id:%x value:%" PRIu64,
368                 ret, info.obj_id, prop_id, value);
369     }
370     *it = {};
371   }
372 }
373 
374 }  // namespace sde_drm
375 
376