598 lines
20 KiB
C++
598 lines
20 KiB
C++
/*
|
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the following
|
|
* disclaimer in the documentation and/or other materials provided
|
|
* with the distribution.
|
|
* * Neither the name of The Linux Foundation nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
|
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
|
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <cstring>
|
|
#include <errno.h>
|
|
#include <drm_logger.h>
|
|
|
|
#include "libdrm_macros.h"
|
|
#include "drm/drm_fourcc.h"
|
|
#include "drm_dpps_mgr_imp.h"
|
|
|
|
#define __CLASS__ "DRMDppsManagerImp"
|
|
namespace sde_drm {
|
|
|
|
static DRMDppsManagerImp dpps_mgr;
|
|
static DRMDppsManagerDummyImp dpps_dummy_mgr;
|
|
|
|
DRMDppsManagerIntf* GetDppsManagerIntf()
|
|
{
|
|
#if (defined(__ANDROID__))
|
|
return &dpps_mgr;
|
|
#else
|
|
return &dpps_dummy_mgr;
|
|
#endif
|
|
}
|
|
|
|
DRMDppsManagerImp::~DRMDppsManagerImp() {
|
|
/* clean up the ION buffers for LTM */
|
|
DeInitLtmBuffers();
|
|
|
|
conn_id_ = -1;
|
|
crtc_id_ = -1;
|
|
drm_fd_ = -1;
|
|
}
|
|
|
|
int DRMDppsManagerImp::GetDrmResources(drmModeRes* res) {
|
|
int enc_id = -1;
|
|
drmModeConnector *conn = NULL;
|
|
drmModeEncoder *enc = NULL;
|
|
drmModeCrtc *crtc = NULL;
|
|
|
|
if (drm_fd_ < 0 ) {
|
|
DRM_LOGE("Invalid drm_fd_ %d", drm_fd_);
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (auto i = 0; i < res->count_connectors; i++) {
|
|
conn = drmModeGetConnector(drm_fd_, res->connectors[i]);
|
|
if (conn && conn->connector_type == DRM_MODE_CONNECTOR_DSI &&
|
|
conn->count_modes && conn->connection == DRM_MODE_CONNECTED) {
|
|
DRM_LOGI("Found connector %d", conn->connector_id);
|
|
conn_id_ = conn->connector_id;
|
|
break;
|
|
}
|
|
drmModeFreeConnector(conn);
|
|
conn = NULL;
|
|
}
|
|
if (conn_id_ < 0 || !conn) {
|
|
DRM_LOGE("Cannot find valid connector");
|
|
conn_id_ = -1;
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (auto i = 0; i < conn->count_encoders; i++) {
|
|
enc = drmModeGetEncoder(drm_fd_, conn->encoders[i]);
|
|
if (enc && enc->encoder_type == DRM_MODE_ENCODER_DSI) {
|
|
DRM_LOGI("Found encoder %d", enc->encoder_id);
|
|
enc_id = enc->encoder_id;
|
|
break;
|
|
}
|
|
drmModeFreeEncoder(enc);
|
|
enc = NULL;
|
|
}
|
|
if (enc_id < 0 || !enc) {
|
|
DRM_LOGE("Cannot find valid encoder");
|
|
drmModeFreeConnector(conn);
|
|
conn = NULL;
|
|
res = NULL;
|
|
conn_id_ = -1;
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (auto i = 0; i < res->count_crtcs; i++) {
|
|
if (enc->possible_crtcs & (1 << i)) {
|
|
crtc = drmModeGetCrtc(drm_fd_, res->crtcs[i]);
|
|
if (crtc) {
|
|
DRM_LOGI("Found crtc %d", crtc->crtc_id);
|
|
crtc_id_ = crtc->crtc_id;
|
|
break;
|
|
}
|
|
drmModeFreeCrtc(crtc);
|
|
crtc = NULL;
|
|
}
|
|
}
|
|
if (crtc_id_ < 0 || !crtc) {
|
|
DRM_LOGE("Cannot find valid crtc");
|
|
drmModeFreeEncoder(enc);
|
|
drmModeFreeConnector(conn);
|
|
enc = NULL;
|
|
conn = NULL;
|
|
conn_id_ = -1;
|
|
crtc_id_ = -1;
|
|
return -EINVAL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int DRMDppsManagerImp::InitCrtcProps() {
|
|
if (drm_fd_ < 0 || crtc_id_ < 0) {
|
|
DRM_LOGE("Invalid drm_fd_ %d or crtc_id_ %d", drm_fd_, crtc_id_);
|
|
return -EINVAL;
|
|
}
|
|
|
|
drmModeObjectProperties *props =
|
|
drmModeObjectGetProperties(drm_fd_, crtc_id_, DRM_MODE_OBJECT_CRTC);
|
|
if (!props || !props->props || !props->prop_values) {
|
|
drmModeFreeObjectProperties(props);
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (uint32_t j = 0; j < props->count_props; j++) {
|
|
drmModePropertyRes *info = drmModeGetProperty(drm_fd_, props->props[j]);
|
|
if (!info) {
|
|
continue;
|
|
}
|
|
|
|
std::string property_name(info->name);
|
|
DRMProperty prop_enum = prop_mgr_.GetPropertyEnum(property_name);
|
|
if (prop_enum == DRMProperty::INVALID) {
|
|
DRM_LOGD("DRMProperty %s missing from global property mapping", info->name);
|
|
drmModeFreeProperty(info);
|
|
continue;
|
|
}
|
|
|
|
prop_mgr_.SetPropertyId(prop_enum, info->prop_id);
|
|
drmModeFreeProperty(info);
|
|
}
|
|
|
|
drmModeFreeObjectProperties(props);
|
|
return 0;
|
|
}
|
|
|
|
int DRMDppsManagerImp::InitConnProps()
|
|
{
|
|
if (drm_fd_ < 0 || conn_id_ < 0) {
|
|
DRM_LOGE("Invalid drm_fd_ %d or conn_id_ %d", drm_fd_, conn_id_);
|
|
return -EINVAL;
|
|
}
|
|
|
|
drmModeObjectProperties *props =
|
|
drmModeObjectGetProperties(drm_fd_, conn_id_, DRM_MODE_OBJECT_CONNECTOR);
|
|
if (!props || !props->props || !props->prop_values) {
|
|
drmModeFreeObjectProperties(props);
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (uint32_t j = 0; j < props->count_props; j++) {
|
|
drmModePropertyRes *info = drmModeGetProperty(drm_fd_, props->props[j]);
|
|
if (!info) {
|
|
continue;
|
|
}
|
|
|
|
std::string property_name(info->name);
|
|
DRMProperty prop_enum = prop_mgr_.GetPropertyEnum(property_name);
|
|
if (prop_enum == DRMProperty::INVALID) {
|
|
DRM_LOGD("DRMProperty %s missing from global property mapping", info->name);
|
|
drmModeFreeProperty(info);
|
|
continue;
|
|
}
|
|
|
|
prop_mgr_.SetPropertyId(prop_enum, info->prop_id);
|
|
drmModeFreeProperty(info);
|
|
}
|
|
|
|
drmModeFreeObjectProperties(props);
|
|
return 0;
|
|
}
|
|
|
|
void DRMDppsManagerImp::Init(int fd, drmModeRes* res) {
|
|
std::lock_guard<std::mutex> guard(api_lock_);
|
|
int ret = 0;
|
|
|
|
if (fd < 0 || !res) {
|
|
DRM_LOGE("Invalid drm fd %d or res %p", fd, res);
|
|
return;
|
|
}
|
|
|
|
drm_fd_ = fd;
|
|
ret = GetDrmResources(res);
|
|
if (ret) {
|
|
DRM_LOGE("Failed to get DRM resources %d", ret);
|
|
return;
|
|
} else {
|
|
ret = InitCrtcProps();
|
|
if (ret) {
|
|
DRM_LOGE("Failed to initialize crtc properties %d", ret);
|
|
return;
|
|
}
|
|
ret = InitConnProps();
|
|
if (ret) {
|
|
DRM_LOGE("Failed to initialize conn properties %d", ret);
|
|
return;
|
|
}
|
|
}
|
|
|
|
memset(&dpps_feature_, 0, sizeof(dpps_feature_));
|
|
dpps_feature_[kFeatureAd4Mode] = DRMDppsPropInfo {
|
|
(prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_MODE) == 0 ? 0U : 4U) /* version */,
|
|
DRMProperty::SDE_DSPP_AD4_MODE, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_MODE),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureAd4Init] = DRMDppsPropInfo {4 /* version */,
|
|
DRMProperty::SDE_DSPP_AD4_INIT, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_INIT),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureAd4Cfg] = DRMDppsPropInfo { 4 /* version */,
|
|
DRMProperty::SDE_DSPP_AD4_CFG, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_CFG),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureAd4Input] = DRMDppsPropInfo {4 /* version */,
|
|
DRMProperty::SDE_DSPP_AD4_INPUT, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_INPUT),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureAd4Backlight] = DRMDppsPropInfo {4 /* version */,
|
|
DRMProperty::SDE_DSPP_AD4_BACKLIGHT, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_BACKLIGHT),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureAd4Assertiveness] = DRMDppsPropInfo {4 /* version */,
|
|
DRMProperty::SDE_DSPP_AD4_ASSERTIVENESS, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_ASSERTIVENESS),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureAd4Roi] = DRMDppsPropInfo {4 /* version */,
|
|
DRMProperty::SDE_DSPP_AD4_ROI, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_ROI),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureAd4ManualStrength] = DRMDppsPropInfo {4 /* version */,
|
|
DRMProperty::SDE_DSPP_AD4_STRENGTH, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_AD4_STRENGTH),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureAbaHistCtrl] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_DSPP_ABA_HIST_CTRL, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_ABA_HIST_CTRL),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureAbaHistIRQ] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_DSPP_ABA_HIST_IRQ, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_ABA_HIST_IRQ),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureAbaLut] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_DSPP_ABA_LUT, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_ABA_LUT),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureSvBlScale] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_DSPP_SV_BL_SCALE, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_SV_BL_SCALE),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureBacklightScale] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_DSPP_BL_SCALE, prop_mgr_.GetPropertyId(DRMProperty::SDE_DSPP_BL_SCALE),
|
|
false /* is_event */};
|
|
|
|
if (prop_mgr_.IsPropertyAvailable(DRMProperty::SDE_LTM_VERSION)) {
|
|
dpps_feature_[kFeatureLtm] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_LTM_VERSION, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_VERSION),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureLtmInit] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_LTM_INIT, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_INIT),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureLtmCfg] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_LTM_CFG, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_CFG),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureLtmNoiseThresh] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_LTM_NOISE_THRESH, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_NOISE_THRESH),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureLtmBufferCtrl] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_LTM_BUFFER_CTRL, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_BUFFER_CTRL),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureLtmQueueBuffer] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_LTM_QUEUE_BUFFER, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_QUEUE_BUFFER),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureLtmQueueBuffer2] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_LTM_QUEUE_BUFFER2, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_QUEUE_BUFFER2),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureLtmQueueBuffer3] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_LTM_QUEUE_BUFFER3, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_QUEUE_BUFFER3),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureLtmHistCtrl] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_LTM_HIST_CTRL, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_HIST_CTRL),
|
|
false /* is_event */};
|
|
dpps_feature_[kFeatureLtmVlut] = DRMDppsPropInfo {1 /* version */,
|
|
DRMProperty::SDE_LTM_VLUT, prop_mgr_.GetPropertyId(DRMProperty::SDE_LTM_VLUT),
|
|
false /* is_event */};
|
|
} else {
|
|
DRM_LOGI("LTM properties are not available");
|
|
}
|
|
|
|
dpps_feature_[kFeaturePowerEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
|
|
dpps_feature_[kFeatureAbaHistEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
|
|
dpps_feature_[kFeatureBackLightEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
|
|
dpps_feature_[kFeatureAdAttBlEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
|
|
dpps_feature_[kFeatureLtmHistEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
|
|
dpps_feature_[kFeatureLtmWbPbEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
|
|
dpps_feature_[kFeatureLtmOffEvent] = DRMDppsPropInfo{1, DRMProperty::INVALID, 0, true /* is_event */};
|
|
}
|
|
|
|
void DRMDppsManagerImp::CacheDppsFeature(uint32_t obj_id, va_list args) {
|
|
std::lock_guard<std::mutex> guard(api_lock_);
|
|
uint32_t feature_id = va_arg(args, uint32_t);
|
|
uint64_t value = va_arg(args, uint64_t);
|
|
struct DRMDppsPropInfo* info;
|
|
|
|
if (feature_id >= kDppsFeaturesMax) {
|
|
DRM_LOGE("Invalid feature id %d for obj_id 0x%x", feature_id, obj_id);
|
|
return;
|
|
}
|
|
|
|
info = &dpps_feature_[feature_id];
|
|
info->obj_id = obj_id;
|
|
info->value = value;
|
|
if (info->is_event) {
|
|
dpps_dirty_event_.push_back(*info);
|
|
} else {
|
|
for (auto &it : dpps_dirty_prop_) {
|
|
if ((it.obj_id == info->obj_id) && (it.prop_id == info->prop_id)) {
|
|
it.value = info->value;
|
|
return;
|
|
}
|
|
}
|
|
dpps_dirty_prop_.push_back(*info);
|
|
}
|
|
}
|
|
|
|
void DRMDppsManagerImp::CommitDppsFeatures(drmModeAtomicReq *req, const DRMDisplayToken &tok) {
|
|
std::lock_guard<std::mutex> guard(api_lock_);
|
|
int ret = 0;
|
|
|
|
if (!req)
|
|
return;
|
|
|
|
// Set Dpps properties
|
|
if (!dpps_dirty_prop_.empty()) {
|
|
for (auto it = dpps_dirty_prop_.begin(); it != dpps_dirty_prop_.end();) {
|
|
if (it->obj_id == tok.crtc_id || it->obj_id == tok.conn_id) {
|
|
ret = drmModeAtomicAddProperty(req, it->obj_id, it->prop_id, it->value);
|
|
if (ret < 0)
|
|
DRM_LOGE("AtomicAddProperty failed obj_id 0x%x, prop_id %d ret %d ", it->obj_id,
|
|
it->prop_id, ret);
|
|
else
|
|
it = dpps_dirty_prop_.erase(it);
|
|
} else {
|
|
it++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set Dpps events
|
|
if (!dpps_dirty_event_.empty()) {
|
|
for (auto it = dpps_dirty_event_.begin(); it != dpps_dirty_event_.end();) {
|
|
if (!it->value)
|
|
continue;
|
|
|
|
struct DRMDppsEventInfo info = *(struct DRMDppsEventInfo*)it->value;
|
|
struct drm_msm_event_req event_req = {};
|
|
int ret;
|
|
if (it->obj_id == tok.crtc_id || it->obj_id == tok.conn_id) {
|
|
event_req.object_id = it->obj_id;
|
|
event_req.object_type = info.object_type;
|
|
event_req.event = info.event_type;
|
|
if (info.enable)
|
|
ret = drmIoctl(info.drm_fd, DRM_IOCTL_MSM_REGISTER_EVENT, &event_req);
|
|
else
|
|
ret = drmIoctl(info.drm_fd, DRM_IOCTL_MSM_DEREGISTER_EVENT, &event_req);
|
|
if (ret) {
|
|
ret = -errno;
|
|
if (ret == -EALREADY) {
|
|
DRM_LOGI("Duplicated request to set event 0x%x, object_id %u, object_type 0x%x, enable %d",
|
|
event_req.event, event_req.object_id, info.object_type, info.enable);
|
|
} else {
|
|
DRM_LOGE("Failed to set event 0x%x, object_id %u, object_type 0x%x, enable %d, ret %d",
|
|
event_req.event, event_req.object_id, info.object_type, info.enable, ret);
|
|
}
|
|
}
|
|
if (ret != -ENODEV)
|
|
it = dpps_dirty_event_.erase(it);
|
|
else
|
|
it++;
|
|
} else {
|
|
it++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DRMDppsManagerImp::GetDppsFeatureInfo(DRMDppsFeatureInfo *info)
|
|
{
|
|
std::lock_guard<std::mutex> guard(api_lock_);
|
|
int ret = 0;
|
|
struct DRMDppsPropInfo* prop_info;
|
|
|
|
if (!info) {
|
|
DRM_LOGE("Invalid info NULL");
|
|
return;
|
|
}
|
|
|
|
DRMDPPSFeatureID id = info->id;
|
|
if (id >= kDppsFeaturesMax) {
|
|
DRM_LOGE("Invalid feature id %d", id);
|
|
return;
|
|
}
|
|
info->version = dpps_feature_[id].version;
|
|
|
|
if ((id == kFeatureLtmBufferCtrl) && (dpps_feature_[kFeatureLtm].prop_id != 0)) {
|
|
/* setup ION buffers for LTM */
|
|
ret = InitLtmBuffers(info);
|
|
if (ret) {
|
|
DRM_LOGE("Failed to init LTM buffers %d", ret);
|
|
return;
|
|
} else {
|
|
prop_info = &dpps_feature_[kFeatureLtmBufferCtrl];
|
|
prop_info->obj_id = info->obj_id;
|
|
for (const auto& it : ltm_buffers_ctrl_map_) {
|
|
if (it.first == info->obj_id)
|
|
prop_info->value = (uint64_t)&(it.second);
|
|
}
|
|
dpps_dirty_prop_.push_back(*prop_info);
|
|
}
|
|
}
|
|
}
|
|
|
|
int DRMDppsManagerImp::InitLtmBuffers(struct DRMDppsFeatureInfo *info) {
|
|
int ret = 0;
|
|
uint32_t buffer_size, i = 0, bpp = 0;
|
|
void* uva;
|
|
struct DRMDppsLtmBuffers *buffers;
|
|
DRMDppsLtmBuffers ltm_buffers = {};
|
|
drm_msm_ltm_buffers_ctrl ltm_buffers_ctrl = {};
|
|
struct drm_prime_handle prime_req;
|
|
struct drm_mode_fb_cmd2 fb_obj;
|
|
struct drm_gem_close gem_close;
|
|
|
|
if (drm_fd_ < 0) {
|
|
DRM_LOGE("Invalid drm_fd_ %d", drm_fd_);
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (const auto& it : ltm_buffers_map_) {
|
|
if (it.first == info->obj_id) {
|
|
DRM_LOGE("LTM buffer already initialized, obj id %d", info->obj_id);
|
|
return -EALREADY;
|
|
}
|
|
}
|
|
|
|
if (!info->payload || info->payload_size != sizeof(struct DRMDppsLtmBuffers)) {
|
|
DRM_LOGE("Invalid payload %p size %d expected %zu", info->payload, info->payload_size,
|
|
sizeof(struct DRMDppsLtmBuffers));
|
|
return -EINVAL;
|
|
}
|
|
|
|
buffers = (struct DRMDppsLtmBuffers *)info->payload;
|
|
if (buffers->num_of_buffers <= 0 || buffers->num_of_buffers > LTM_BUFFER_SIZE) {
|
|
DRM_LOGE("Invalid number of buffers %d", buffers->num_of_buffers);
|
|
return -EINVAL;
|
|
}
|
|
|
|
std::memset(<m_buffers, 0, sizeof(ltm_buffers));
|
|
std::memset(<m_buffers_ctrl, 0, sizeof(ltm_buffers_ctrl));
|
|
|
|
ltm_buffers.num_of_buffers = buffers->num_of_buffers;
|
|
|
|
buffer_size = sizeof(struct drm_msm_ltm_stats_data) + LTM_GUARD_BYTES;
|
|
std::memset(&fb_obj, 0, sizeof(drm_mode_fb_cmd2));
|
|
fb_obj.pixel_format = DRM_FORMAT_YVYU;
|
|
/* YVYU gives us a bpp of 16 (2 bytes) so we must take that into account */
|
|
fb_obj.height = 2;
|
|
/* add extra one to compensate integer rounding */
|
|
fb_obj.width = buffer_size / (2 * fb_obj.height) + 1;
|
|
/* bpp for YVYU is 16 */
|
|
bpp = 16;
|
|
fb_obj.flags = DRM_MODE_FB_MODIFIERS;
|
|
fb_obj.pitches[0] = fb_obj.width * bpp / 8;
|
|
|
|
for (i = 0; i < buffers->num_of_buffers && !ret; i++) {
|
|
std::memset(&prime_req, 0, sizeof(drm_prime_handle));
|
|
prime_req.fd = buffers->ion_buffer_fd[i];
|
|
ret = drmIoctl(drm_fd_, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_req);
|
|
if (ret) {
|
|
ret = -errno;
|
|
DRM_LOGE("failed get prime handle: %d", ret);
|
|
break;
|
|
}
|
|
ltm_buffers.ion_buffer_fd[i] = buffers->ion_buffer_fd[i];
|
|
|
|
fb_obj.handles[0] = prime_req.handle;
|
|
ret = drmIoctl(drm_fd_, DRM_IOCTL_MODE_ADDFB2, &fb_obj);
|
|
if (ret) {
|
|
ret = -errno;
|
|
DRM_LOGE("return value from addFB2: %d", ret);
|
|
break;
|
|
}
|
|
ltm_buffers.drm_fb_id[i] = buffers->drm_fb_id[i] = fb_obj.fb_id;
|
|
ltm_buffers_ctrl.fds[i] = ltm_buffers.drm_fb_id[i];
|
|
|
|
/**
|
|
* ADDFB2 will take reference to GEM handles,
|
|
* so drop reference taken by PrimeFDtoHandle now
|
|
*/
|
|
std::memset(&gem_close, 0, sizeof(gem_close));
|
|
gem_close.handle = prime_req.handle;
|
|
ret = drmIoctl(drm_fd_, DRM_IOCTL_GEM_CLOSE, &gem_close);
|
|
if(ret) {
|
|
ret = -errno;
|
|
DRM_LOGE("return value from GEM_CLOSE: %d\n", ret);
|
|
break;
|
|
}
|
|
|
|
uva = drm_mmap(0, buffers->buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
|
buffers->ion_buffer_fd[i], 0);
|
|
if (uva == MAP_FAILED) {
|
|
ret = -errno;
|
|
DRM_LOGE("failed to get uva: %d", ret);
|
|
break;
|
|
}
|
|
ltm_buffers.uva[i] = buffers->uva[i] = uva;
|
|
}
|
|
|
|
if (!ret) {
|
|
buffers->status = 0;
|
|
ltm_buffers.buffer_size = buffers->buffer_size;
|
|
ltm_buffers_ctrl.num_of_buffers = ltm_buffers.num_of_buffers;
|
|
DRM_LOGV("InitLtmBuffers return successful");
|
|
} else {
|
|
DeInitLtmBuffers();
|
|
buffers->status = ret;
|
|
return ret;
|
|
}
|
|
|
|
ltm_buffers_map_.push_back(std::make_pair(info->obj_id, std::move(ltm_buffers)));
|
|
ltm_buffers_ctrl_map_.push_back(std::make_pair(info->obj_id, std::move(ltm_buffers_ctrl)));
|
|
return ret;
|
|
}
|
|
|
|
int DRMDppsManagerImp::DeInitLtmBuffers() {
|
|
int ret = 0;
|
|
uint32_t i = 0;
|
|
|
|
if (drm_fd_ < 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (auto& it : ltm_buffers_map_) {
|
|
DRMDppsLtmBuffers& ltm_buffers = it.second;
|
|
for (i = 0; i < ltm_buffers.num_of_buffers; i++) {
|
|
if (ltm_buffers.uva[i]) {
|
|
drm_munmap(ltm_buffers.uva[i], ltm_buffers.buffer_size);
|
|
ltm_buffers.uva[i] = NULL;
|
|
}
|
|
|
|
if (ltm_buffers.drm_fb_id[i] >= 0) {
|
|
#ifdef DRM_IOCTL_MSM_RMFB2
|
|
ret = drmIoctl(drm_fd_, DRM_IOCTL_MSM_RMFB2, <m_buffers.drm_fb_id[i]);
|
|
if (ret) {
|
|
ret = errno;
|
|
DRM_LOGE("RMFB2 failed for fb_id %d with error %d", ltm_buffers.drm_fb_id[i], ret);
|
|
}
|
|
#endif
|
|
ltm_buffers.drm_fb_id[i] = -1;
|
|
}
|
|
ltm_buffers.ion_buffer_fd[i] = -1;
|
|
}
|
|
|
|
ltm_buffers.num_of_buffers = 0;
|
|
ltm_buffers.buffer_size = 0;
|
|
}
|
|
|
|
for (auto& it : ltm_buffers_ctrl_map_) {
|
|
drm_msm_ltm_buffers_ctrl& ltm_buffers_ctrl = it.second;
|
|
std::memset(<m_buffers_ctrl, 0, sizeof(ltm_buffers_ctrl));
|
|
}
|
|
|
|
ltm_buffers_map_.clear();
|
|
ltm_buffers_ctrl_map_.clear();
|
|
return 0;
|
|
}
|
|
|
|
} // namespace sde_drm
|