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 <cstring>
31 #include <errno.h>
32 #include <drm_logger.h>
33
34 #include "libdrm_macros.h"
35 #include "drm/drm_fourcc.h"
36 #include "drm_dpps_mgr_imp.h"
37
38 #define __CLASS__ "DRMDppsManagerImp"
39 namespace sde_drm {
40
41 static DRMDppsManagerImp dpps_mgr;
42 static DRMDppsManagerDummyImp dpps_dummy_mgr;
43
GetDppsManagerIntf()44 DRMDppsManagerIntf* GetDppsManagerIntf()
45 {
46 #if (defined(__ANDROID__))
47 return &dpps_mgr;
48 #else
49 return &dpps_dummy_mgr;
50 #endif
51 }
52
~DRMDppsManagerImp()53 DRMDppsManagerImp::~DRMDppsManagerImp() {
54 /* clean up the ION buffers for LTM */
55 DeInitLtmBuffers();
56
57 conn_id_ = -1;
58 crtc_id_ = -1;
59 drm_fd_ = -1;
60 }
61
GetDrmResources(drmModeRes * res)62 int DRMDppsManagerImp::GetDrmResources(drmModeRes* res) {
63 int enc_id = -1;
64 drmModeConnector *conn = NULL;
65 drmModeEncoder *enc = NULL;
66 drmModeCrtc *crtc = NULL;
67
68 if (drm_fd_ < 0 ) {
69 DRM_LOGE("Invalid drm_fd_ %d", drm_fd_);
70 return -EINVAL;
71 }
72
73 for (auto i = 0; i < res->count_connectors; i++) {
74 conn = drmModeGetConnector(drm_fd_, res->connectors[i]);
75 if (conn && conn->connector_type == DRM_MODE_CONNECTOR_DSI &&
76 conn->count_modes && conn->connection == DRM_MODE_CONNECTED) {
77 DRM_LOGI("Found connector %d", conn->connector_id);
78 conn_id_ = conn->connector_id;
79 break;
80 }
81 drmModeFreeConnector(conn);
82 conn = NULL;
83 }
84 if (conn_id_ < 0 || !conn) {
85 DRM_LOGE("Cannot find valid connector");
86 conn_id_ = -1;
87 return -EINVAL;
88 }
89
90 for (auto i = 0; i < conn->count_encoders; i++) {
91 enc = drmModeGetEncoder(drm_fd_, conn->encoders[i]);
92 if (enc && enc->encoder_type == DRM_MODE_ENCODER_DSI) {
93 DRM_LOGI("Found encoder %d", enc->encoder_id);
94 enc_id = enc->encoder_id;
95 break;
96 }
97 drmModeFreeEncoder(enc);
98 enc = NULL;
99 }
100 if (enc_id < 0 || !enc) {
101 DRM_LOGE("Cannot find valid encoder");
102 drmModeFreeConnector(conn);
103 conn = NULL;
104 res = NULL;
105 conn_id_ = -1;
106 return -EINVAL;
107 }
108
109 for (auto i = 0; i < res->count_crtcs; i++) {
110 if (enc->possible_crtcs & (1 << i)) {
111 crtc = drmModeGetCrtc(drm_fd_, res->crtcs[i]);
112 if (crtc) {
113 DRM_LOGI("Found crtc %d", crtc->crtc_id);
114 crtc_id_ = crtc->crtc_id;
115 break;
116 }
117 drmModeFreeCrtc(crtc);
118 crtc = NULL;
119 }
120 }
121 if (crtc_id_ < 0 || !crtc) {
122 DRM_LOGE("Cannot find valid crtc");
123 drmModeFreeEncoder(enc);
124 drmModeFreeConnector(conn);
125 enc = NULL;
126 conn = NULL;
127 conn_id_ = -1;
128 crtc_id_ = -1;
129 return -EINVAL;
130 }
131 return 0;
132 }
133
InitCrtcProps()134 int DRMDppsManagerImp::InitCrtcProps() {
135 if (drm_fd_ < 0 || crtc_id_ < 0) {
136 DRM_LOGE("Invalid drm_fd_ %d or crtc_id_ %d", drm_fd_, crtc_id_);
137 return -EINVAL;
138 }
139
140 drmModeObjectProperties *props =
141 drmModeObjectGetProperties(drm_fd_, crtc_id_, DRM_MODE_OBJECT_CRTC);
142 if (!props || !props->props || !props->prop_values) {
143 drmModeFreeObjectProperties(props);
144 return -EINVAL;
145 }
146
147 for (uint32_t j = 0; j < props->count_props; j++) {
148 drmModePropertyRes *info = drmModeGetProperty(drm_fd_, props->props[j]);
149 if (!info) {
150 continue;
151 }
152
153 std::string property_name(info->name);
154 DRMProperty prop_enum = prop_mgr_.GetPropertyEnum(property_name);
155 if (prop_enum == DRMProperty::INVALID) {
156 DRM_LOGD("DRMProperty %s missing from global property mapping", info->name);
157 drmModeFreeProperty(info);
158 continue;
159 }
160
161 prop_mgr_.SetPropertyId(prop_enum, info->prop_id);
162 drmModeFreeProperty(info);
163 }
164
165 drmModeFreeObjectProperties(props);
166 return 0;
167 }
168
InitConnProps()169 int DRMDppsManagerImp::InitConnProps()
170 {
171 if (drm_fd_ < 0 || conn_id_ < 0) {
172 DRM_LOGE("Invalid drm_fd_ %d or conn_id_ %d", drm_fd_, conn_id_);
173 return -EINVAL;
174 }
175
176 drmModeObjectProperties *props =
177 drmModeObjectGetProperties(drm_fd_, conn_id_, DRM_MODE_OBJECT_CONNECTOR);
178 if (!props || !props->props || !props->prop_values) {
179 drmModeFreeObjectProperties(props);
180 return -EINVAL;
181 }
182
183 for (uint32_t j = 0; j < props->count_props; j++) {
184 drmModePropertyRes *info = drmModeGetProperty(drm_fd_, props->props[j]);
185 if (!info) {
186 continue;
187 }
188
189 std::string property_name(info->name);
190 DRMProperty prop_enum = prop_mgr_.GetPropertyEnum(property_name);
191 if (prop_enum == DRMProperty::INVALID) {
192 DRM_LOGD("DRMProperty %s missing from global property mapping", info->name);
193 drmModeFreeProperty(info);
194 continue;
195 }
196
197 prop_mgr_.SetPropertyId(prop_enum, info->prop_id);
198 drmModeFreeProperty(info);
199 }
200
201 drmModeFreeObjectProperties(props);
202 return 0;
203 }
204
Init(int fd,drmModeRes * res)205 void DRMDppsManagerImp::Init(int fd, drmModeRes* res) {
206 std::lock_guard<std::mutex> guard(api_lock_);
207 int ret = 0;
208
209 if (fd < 0 || !res) {
210 DRM_LOGE("Invalid drm fd %d or res %p", fd, res);
211 return;
212 }
213
214 drm_fd_ = fd;
215 ret = GetDrmResources(res);
216 if (ret) {
217 DRM_LOGE("Failed to get DRM resources %d", ret);
218 return;
219 } else {
220 ret = InitCrtcProps();
221 if (ret) {
222 DRM_LOGE("Failed to initialize crtc properties %d", ret);
223 return;
224 }
225 ret = InitConnProps();
226 if (ret) {
227 DRM_LOGE("Failed to initialize conn properties %d", ret);
228 return;
229 }
230 }
231
232 memset(&dpps_feature_, 0, sizeof(dpps_feature_));
233 dpps_feature_[kFeatureAd4Mode] = DRMDppsPropInfo {
234 (prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_MODE) == 0 ? 0U : 4U) /* version */,
235 DRMProperty::SDE_DSPP_AD4_MODE, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_MODE),
236 false /* is_event */};
237 dpps_feature_[kFeatureAd4Init] = DRMDppsPropInfo {4 /* version */,
238 DRMProperty::SDE_DSPP_AD4_INIT, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_INIT),
239 false /* is_event */};
240 dpps_feature_[kFeatureAd4Cfg] = DRMDppsPropInfo { 4 /* version */,
241 DRMProperty::SDE_DSPP_AD4_CFG, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_CFG),
242 false /* is_event */};
243 dpps_feature_[kFeatureAd4Input] = DRMDppsPropInfo {4 /* version */,
244 DRMProperty::SDE_DSPP_AD4_INPUT, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_INPUT),
245 false /* is_event */};
246 dpps_feature_[kFeatureAd4Backlight] = DRMDppsPropInfo {4 /* version */,
247 DRMProperty::SDE_DSPP_AD4_BACKLIGHT, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_BACKLIGHT),
248 false /* is_event */};
249 dpps_feature_[kFeatureAd4Assertiveness] = DRMDppsPropInfo {4 /* version */,
250 DRMProperty::SDE_DSPP_AD4_ASSERTIVENESS, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_ASSERTIVENESS),
251 false /* is_event */};
252 dpps_feature_[kFeatureAd4Roi] = DRMDppsPropInfo {4 /* version */,
253 DRMProperty::SDE_DSPP_AD4_ROI, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_ROI),
254 false /* is_event */};
255 dpps_feature_[kFeatureAd4ManualStrength] = DRMDppsPropInfo {4 /* version */,
256 DRMProperty::SDE_DSPP_AD4_STRENGTH, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_STRENGTH),
257 false /* is_event */};
258 dpps_feature_[kFeatureAbaHistCtrl] = DRMDppsPropInfo {1 /* version */,
259 DRMProperty::SDE_DSPP_ABA_HIST_CTRL, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_ABA_HIST_CTRL),
260 false /* is_event */};
261 dpps_feature_[kFeatureAbaHistIRQ] = DRMDppsPropInfo {1 /* version */,
262 DRMProperty::SDE_DSPP_ABA_HIST_IRQ, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_ABA_HIST_IRQ),
263 false /* is_event */};
264 dpps_feature_[kFeatureAbaLut] = DRMDppsPropInfo {1 /* version */,
265 DRMProperty::SDE_DSPP_ABA_LUT, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_ABA_LUT),
266 false /* is_event */};
267 dpps_feature_[kFeatureSvBlScale] = DRMDppsPropInfo {1 /* version */,
268 DRMProperty::SDE_DSPP_SV_BL_SCALE, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_SV_BL_SCALE),
269 false /* is_event */};
270 dpps_feature_[kFeatureBacklightScale] = DRMDppsPropInfo {1 /* version */,
271 DRMProperty::SDE_DSPP_BL_SCALE, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_BL_SCALE),
272 false /* is_event */};
273
274 if (prop_mgr_.IsPropertyAvailable(DRMProperty::SDE_LTM_VERSION)) {
275 dpps_feature_[kFeatureLtm] = DRMDppsPropInfo {1 /* version */,
276 DRMProperty::SDE_LTM_VERSION, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_VERSION),
277 false /* is_event */};
278 dpps_feature_[kFeatureLtmInit] = DRMDppsPropInfo {1 /* version */,
279 DRMProperty::SDE_LTM_INIT, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_INIT),
280 false /* is_event */};
281 dpps_feature_[kFeatureLtmCfg] = DRMDppsPropInfo {1 /* version */,
282 DRMProperty::SDE_LTM_CFG, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_CFG),
283 false /* is_event */};
284 dpps_feature_[kFeatureLtmNoiseThresh] = DRMDppsPropInfo {1 /* version */,
285 DRMProperty::SDE_LTM_NOISE_THRESH, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_NOISE_THRESH),
286 false /* is_event */};
287 dpps_feature_[kFeatureLtmBufferCtrl] = DRMDppsPropInfo {1 /* version */,
288 DRMProperty::SDE_LTM_BUFFER_CTRL, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_BUFFER_CTRL),
289 false /* is_event */};
290 dpps_feature_[kFeatureLtmQueueBuffer] = DRMDppsPropInfo {1 /* version */,
291 DRMProperty::SDE_LTM_QUEUE_BUFFER, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_QUEUE_BUFFER),
292 false /* is_event */};
293 dpps_feature_[kFeatureLtmQueueBuffer2] = DRMDppsPropInfo {1 /* version */,
294 DRMProperty::SDE_LTM_QUEUE_BUFFER2, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_QUEUE_BUFFER2),
295 false /* is_event */};
296 dpps_feature_[kFeatureLtmQueueBuffer3] = DRMDppsPropInfo {1 /* version */,
297 DRMProperty::SDE_LTM_QUEUE_BUFFER3, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_QUEUE_BUFFER3),
298 false /* is_event */};
299 dpps_feature_[kFeatureLtmHistCtrl] = DRMDppsPropInfo {1 /* version */,
300 DRMProperty::SDE_LTM_HIST_CTRL, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_HIST_CTRL),
301 false /* is_event */};
302 dpps_feature_[kFeatureLtmVlut] = DRMDppsPropInfo {1 /* version */,
303 DRMProperty::SDE_LTM_VLUT, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_VLUT),
304 false /* is_event */};
305 } else {
306 DRM_LOGI("LTM properties are not available");
307 }
308
309 dpps_feature_[kFeaturePowerEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
310 dpps_feature_[kFeatureAbaHistEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
311 dpps_feature_[kFeatureBackLightEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
312 dpps_feature_[kFeatureAdAttBlEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
313 dpps_feature_[kFeatureLtmHistEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
314 dpps_feature_[kFeatureLtmWbPbEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
315 dpps_feature_[kFeatureLtmOffEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
316 }
317
CacheDppsFeature(uint32_t obj_id,va_list args)318 void DRMDppsManagerImp::CacheDppsFeature(uint32_t obj_id, va_list args) {
319 std::lock_guard<std::mutex> guard(api_lock_);
320 uint32_t feature_id = va_arg(args, uint32_t);
321 uint64_t value = va_arg(args, uint64_t);
322 struct DRMDppsPropInfo* info;
323
324 if (feature_id >= kDppsFeaturesMax) {
325 DRM_LOGE("Invalid feature id %d for obj_id 0x%x", feature_id, obj_id);
326 return;
327 }
328
329 info = &dpps_feature_[feature_id];
330 info->obj_id = obj_id;
331 info->value = value;
332 if (info->is_event) {
333 dpps_dirty_event_.push_back(*info);
334 } else {
335 for (auto &it : dpps_dirty_prop_) {
336 if ((it.obj_id == info->obj_id) && (it.prop_id == info->prop_id)) {
337 it.value = info->value;
338 return;
339 }
340 }
341 dpps_dirty_prop_.push_back(*info);
342 }
343 }
344
CommitDppsFeatures(drmModeAtomicReq * req,const DRMDisplayToken & tok)345 void DRMDppsManagerImp::CommitDppsFeatures(drmModeAtomicReq *req, const DRMDisplayToken &tok) {
346 std::lock_guard<std::mutex> guard(api_lock_);
347 int ret = 0;
348
349 if (!req)
350 return;
351
352 // Set Dpps properties
353 if (!dpps_dirty_prop_.empty()) {
354 for (auto it = dpps_dirty_prop_.begin(); it != dpps_dirty_prop_.end();) {
355 if (it->obj_id == tok.crtc_id || it->obj_id == tok.conn_id) {
356 ret = drmModeAtomicAddProperty(req, it->obj_id, it->prop_id, it->value);
357 if (ret < 0)
358 DRM_LOGE("AtomicAddProperty failed obj_id 0x%x, prop_id %d ret %d ", it->obj_id,
359 it->prop_id, ret);
360 else
361 it = dpps_dirty_prop_.erase(it);
362 } else {
363 it++;
364 }
365 }
366 }
367
368 // Set Dpps events
369 if (!dpps_dirty_event_.empty()) {
370 for (auto it = dpps_dirty_event_.begin(); it != dpps_dirty_event_.end();) {
371 if (!it->value)
372 continue;
373
374 struct DRMDppsEventInfo info = *(struct DRMDppsEventInfo*)it->value;
375 struct drm_msm_event_req event_req = {};
376 int ret;
377 if (it->obj_id == tok.crtc_id || it->obj_id == tok.conn_id) {
378 event_req.object_id = it->obj_id;
379 event_req.object_type = info.object_type;
380 event_req.event = info.event_type;
381 if (info.enable)
382 ret = drmIoctl(info.drm_fd, DRM_IOCTL_MSM_REGISTER_EVENT, &event_req);
383 else
384 ret = drmIoctl(info.drm_fd, DRM_IOCTL_MSM_DEREGISTER_EVENT, &event_req);
385 if (ret) {
386 ret = -errno;
387 if (ret == -EALREADY) {
388 DRM_LOGI("Duplicated request to set event 0x%x, object_id %u, object_type 0x%x, enable %d",
389 event_req.event, event_req.object_id, info.object_type, info.enable);
390 } else {
391 DRM_LOGE("Failed to set event 0x%x, object_id %u, object_type 0x%x, enable %d, ret %d",
392 event_req.event, event_req.object_id, info.object_type, info.enable, ret);
393 }
394 }
395 if (ret != -ENODEV)
396 it = dpps_dirty_event_.erase(it);
397 else
398 it++;
399 } else {
400 it++;
401 }
402 }
403 }
404 }
405
GetDppsFeatureInfo(DRMDppsFeatureInfo * info)406 void DRMDppsManagerImp::GetDppsFeatureInfo(DRMDppsFeatureInfo *info)
407 {
408 std::lock_guard<std::mutex> guard(api_lock_);
409 int ret = 0;
410 struct DRMDppsPropInfo* prop_info;
411
412 if (!info) {
413 DRM_LOGE("Invalid info NULL");
414 return;
415 }
416
417 DRMDPPSFeatureID id = info->id;
418 if (id >= kDppsFeaturesMax) {
419 DRM_LOGE("Invalid feature id %d", id);
420 return;
421 }
422 info->version = dpps_feature_[id].version;
423
424 if ((id == kFeatureLtmBufferCtrl) && (dpps_feature_[kFeatureLtm].prop_id != 0)) {
425 /* setup ION buffers for LTM */
426 ret = InitLtmBuffers(info);
427 if (ret) {
428 DRM_LOGE("Failed to init LTM buffers %d", ret);
429 return;
430 } else {
431 prop_info = &dpps_feature_[kFeatureLtmBufferCtrl];
432 prop_info->obj_id = info->obj_id;
433 for (const auto& it : ltm_buffers_ctrl_map_) {
434 if (it.first == info->obj_id)
435 prop_info->value = (uint64_t)&(it.second);
436 }
437 dpps_dirty_prop_.push_back(*prop_info);
438 }
439 }
440 }
441
InitLtmBuffers(struct DRMDppsFeatureInfo * info)442 int DRMDppsManagerImp::InitLtmBuffers(struct DRMDppsFeatureInfo *info) {
443 int ret = 0;
444 uint32_t buffer_size, i = 0, bpp = 0;
445 void* uva;
446 struct DRMDppsLtmBuffers *buffers;
447 DRMDppsLtmBuffers ltm_buffers = {};
448 drm_msm_ltm_buffers_ctrl ltm_buffers_ctrl = {};
449 struct drm_prime_handle prime_req;
450 struct drm_mode_fb_cmd2 fb_obj;
451 struct drm_gem_close gem_close;
452
453 if (drm_fd_ < 0) {
454 DRM_LOGE("Invalid drm_fd_ %d", drm_fd_);
455 return -EINVAL;
456 }
457
458 for (const auto& it : ltm_buffers_map_) {
459 if (it.first == info->obj_id) {
460 DRM_LOGE("LTM buffer already initialized, obj id %d", info->obj_id);
461 return -EALREADY;
462 }
463 }
464
465 if (!info->payload || info->payload_size != sizeof(struct DRMDppsLtmBuffers)) {
466 DRM_LOGE("Invalid payload %p size %d expected %zu", info->payload, info->payload_size,
467 sizeof(struct DRMDppsLtmBuffers));
468 return -EINVAL;
469 }
470
471 buffers = (struct DRMDppsLtmBuffers *)info->payload;
472 if (buffers->num_of_buffers <= 0 || buffers->num_of_buffers > LTM_BUFFER_SIZE) {
473 DRM_LOGE("Invalid number of buffers %d", buffers->num_of_buffers);
474 return -EINVAL;
475 }
476
477 std::memset(<m_buffers, 0, sizeof(ltm_buffers));
478 std::memset(<m_buffers_ctrl, 0, sizeof(ltm_buffers_ctrl));
479
480 ltm_buffers.num_of_buffers = buffers->num_of_buffers;
481
482 buffer_size = sizeof(struct drm_msm_ltm_stats_data) + LTM_GUARD_BYTES;
483 std::memset(&fb_obj, 0, sizeof(drm_mode_fb_cmd2));
484 fb_obj.pixel_format = DRM_FORMAT_YVYU;
485 /* YVYU gives us a bpp of 16 (2 bytes) so we must take that into account */
486 fb_obj.height = 2;
487 /* add extra one to compensate integer rounding */
488 fb_obj.width = buffer_size / (2 * fb_obj.height) + 1;
489 /* bpp for YVYU is 16 */
490 bpp = 16;
491 fb_obj.flags = DRM_MODE_FB_MODIFIERS;
492 fb_obj.pitches[0] = fb_obj.width * bpp / 8;
493
494 for (i = 0; i < buffers->num_of_buffers && !ret; i++) {
495 std::memset(&prime_req, 0, sizeof(drm_prime_handle));
496 prime_req.fd = buffers->ion_buffer_fd[i];
497 ret = drmIoctl(drm_fd_, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_req);
498 if (ret) {
499 ret = -errno;
500 DRM_LOGE("failed get prime handle: %d", ret);
501 break;
502 }
503 ltm_buffers.ion_buffer_fd[i] = buffers->ion_buffer_fd[i];
504
505 fb_obj.handles[0] = prime_req.handle;
506 ret = drmIoctl(drm_fd_, DRM_IOCTL_MODE_ADDFB2, &fb_obj);
507 if (ret) {
508 ret = -errno;
509 DRM_LOGE("return value from addFB2: %d", ret);
510 break;
511 }
512 ltm_buffers.drm_fb_id[i] = buffers->drm_fb_id[i] = fb_obj.fb_id;
513 ltm_buffers_ctrl.fds[i] = ltm_buffers.drm_fb_id[i];
514
515 /**
516 * ADDFB2 will take reference to GEM handles,
517 * so drop reference taken by PrimeFDtoHandle now
518 */
519 std::memset(&gem_close, 0, sizeof(gem_close));
520 gem_close.handle = prime_req.handle;
521 ret = drmIoctl(drm_fd_, DRM_IOCTL_GEM_CLOSE, &gem_close);
522 if(ret) {
523 ret = -errno;
524 DRM_LOGE("return value from GEM_CLOSE: %d\n", ret);
525 break;
526 }
527
528 uva = drm_mmap(0, buffers->buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED,
529 buffers->ion_buffer_fd[i], 0);
530 if (uva == MAP_FAILED) {
531 ret = -errno;
532 DRM_LOGE("failed to get uva: %d", ret);
533 break;
534 }
535 ltm_buffers.uva[i] = buffers->uva[i] = uva;
536 }
537
538 if (!ret) {
539 buffers->status = 0;
540 ltm_buffers.buffer_size = buffers->buffer_size;
541 ltm_buffers_ctrl.num_of_buffers = ltm_buffers.num_of_buffers;
542 DRM_LOGV("InitLtmBuffers return successful");
543 } else {
544 DeInitLtmBuffers();
545 buffers->status = ret;
546 return ret;
547 }
548
549 ltm_buffers_map_.push_back(std::make_pair(info->obj_id, std::move(ltm_buffers)));
550 ltm_buffers_ctrl_map_.push_back(std::make_pair(info->obj_id, std::move(ltm_buffers_ctrl)));
551 return ret;
552 }
553
DeInitLtmBuffers()554 int DRMDppsManagerImp::DeInitLtmBuffers() {
555 int ret = 0;
556 uint32_t i = 0;
557
558 if (drm_fd_ < 0) {
559 return -EINVAL;
560 }
561
562 for (auto& it : ltm_buffers_map_) {
563 DRMDppsLtmBuffers& ltm_buffers = it.second;
564 for (i = 0; i < ltm_buffers.num_of_buffers; i++) {
565 if (ltm_buffers.uva[i]) {
566 drm_munmap(ltm_buffers.uva[i], ltm_buffers.buffer_size);
567 ltm_buffers.uva[i] = NULL;
568 }
569
570 if (ltm_buffers.drm_fb_id[i] >= 0) {
571 #ifdef DRM_IOCTL_MSM_RMFB2
572 ret = drmIoctl(drm_fd_, DRM_IOCTL_MSM_RMFB2, <m_buffers.drm_fb_id[i]);
573 if (ret) {
574 ret = errno;
575 DRM_LOGE("RMFB2 failed for fb_id %d with error %d", ltm_buffers.drm_fb_id[i], ret);
576 }
577 #endif
578 ltm_buffers.drm_fb_id[i] = -1;
579 }
580 ltm_buffers.ion_buffer_fd[i] = -1;
581 }
582
583 ltm_buffers.num_of_buffers = 0;
584 ltm_buffers.buffer_size = 0;
585 }
586
587 for (auto& it : ltm_buffers_ctrl_map_) {
588 drm_msm_ltm_buffers_ctrl& ltm_buffers_ctrl = it.second;
589 std::memset(<m_buffers_ctrl, 0, sizeof(ltm_buffers_ctrl));
590 }
591
592 ltm_buffers_map_.clear();
593 ltm_buffers_ctrl_map_.clear();
594 return 0;
595 }
596
597 } // namespace sde_drm
598