Files

172 lines
5.5 KiB
C++

/*
* Copyright (C) 2024 Amlogic Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include <errno.h>
#include <inttypes.h>
#include <vector>
#include "DrmProperty.h"
#include "DispAdptLog.h"
DrmProperty::DrmProperty(int drvFd, drmModePropertyPtr p, uint32_t objectId, uint64_t value)
: mDrvFd(drvFd),
mValue(value),
mComponentId(objectId) {
memcpy(&mPropRes, p, sizeof(mPropRes));
if (p->count_values > 0) {
size_t contentLen = p->count_values * sizeof(uint64_t);
mPropRes.values = (uint64_t*)malloc(contentLen);
memcpy(mPropRes.values, p->values, contentLen);
} else {
mPropRes.values = NULL;
}
if (p->count_enums > 0) {
size_t contentLen = p->count_enums * sizeof(struct drm_mode_property_enum);
mPropRes.enums = (struct drm_mode_property_enum *)malloc(contentLen);
memcpy(mPropRes.enums, p->enums, contentLen);
} else {
mPropRes.enums = NULL;
}
if (p->count_blobs > 0) {
size_t contentLen = p->count_blobs * sizeof(uint32_t);
mPropRes.blob_ids = (uint32_t*)malloc(contentLen);
memcpy(mPropRes.blob_ids, p->blob_ids, contentLen);
} else {
mPropRes.blob_ids = NULL;
}
mType = 0;
if (drm_property_type_is(p, DRM_MODE_PROP_RANGE)) {
mType = DRM_MODE_PROP_RANGE;
DISPLAY_ASSERT(p->count_values > 0, " NO RANGE SPECIFIED (%s)", mPropRes.name);
} else if (drm_property_type_is(p, DRM_MODE_PROP_SIGNED_RANGE)) {
mType = DRM_MODE_PROP_SIGNED_RANGE;
DISPLAY_ASSERT(p->count_values > 0, " NO RANGE SPECIFIED (%s)", mPropRes.name);
} else if (drm_property_type_is(p, DRM_MODE_PROP_ENUM)) {
mType = DRM_MODE_PROP_ENUM;
DISPLAY_ASSERT(p->count_enums > 0, " NO ENUM SPECIFIED (%s)", mPropRes.name);
} else if (drm_property_type_is(p, DRM_MODE_PROP_OBJECT)) {
mType = DRM_MODE_PROP_OBJECT;
} else if (drm_property_type_is(p, DRM_MODE_PROP_BLOB)) {
mType = DRM_MODE_PROP_BLOB;
} else if (drm_property_type_is(p, DRM_MODE_PROP_BITMASK)) {
mType = DRM_MODE_PROP_BITMASK;
}
DISPLAY_ASSERT(mType !=0, "UNKNOWN type for prop (%s)", mPropRes.name);
DISPLAY_LOGD("DrmProperty: %s (%d), value [%" PRId64 "]",
mPropRes.name, mPropRes.prop_id, mValue);
}
DrmProperty::~DrmProperty() {
if (mPropRes.values)
free(mPropRes.values);
if (mPropRes.enums)
free(mPropRes.enums);
if (mPropRes.blob_ids)
free(mPropRes.blob_ids);
}
int DrmProperty::setValue(uint64_t val) {
if (isImmutable())
return -EIO;
if (mType == DRM_MODE_PROP_RANGE) {
if (val < mPropRes.values[0] || val > mPropRes.values[1]) {
DISPLAY_LOGE("[%s] RANGE ERROR (%" PRId64 ") -> (%" PRId64 ",%" PRId64 ")",
mPropRes.name, val, mPropRes.values[0], mPropRes.values[1]);
return -EINVAL;
}
} else if (mType == DRM_MODE_PROP_SIGNED_RANGE) {
int64_t signedVal = (int64_t)val;
int64_t minVal = (int64_t) mPropRes.values[0];
int64_t maxVal = (int64_t) mPropRes.values[1];
if (signedVal < minVal || signedVal > maxVal) {
return -EINVAL;
}
}
if (mValue != val) {
mValue = val;
}
return 0;
}
uint64_t DrmProperty::getValue() {
switch (mType) {
case DRM_MODE_PROP_OBJECT:
case DRM_MODE_PROP_RANGE:
case DRM_MODE_PROP_SIGNED_RANGE:
case DRM_MODE_PROP_BLOB:
case DRM_MODE_PROP_ENUM:
case DRM_MODE_PROP_BITMASK:
return mValue;
default:
DISPLAY_LOGE("unknown property type");
return 0;
}
}
int DrmProperty::getBlobData(std::vector<uint8_t> & blob) {
if (mType != DRM_MODE_PROP_BLOB)
return -EINVAL;
return getBlobData(blob, mValue);
}
int DrmProperty::getBlobData(std::vector<uint8_t> & blob, uint32_t blobId) {
DISPLAY_ASSERT(mType == DRM_MODE_PROP_BLOB, "Only For blob.");
drmModePropertyBlobPtr blobProp =
drmModeGetPropertyBlob(mDrvFd, blobId);
if (!blobProp) {
return -EIO;
}
uint8_t * blobData = (uint8_t * )blobProp->data;
for (uint32_t i = 0; i < blobProp->length; i++) {
blob.push_back(blobData[i]);
}
drmModeFreePropertyBlob(blobProp);
return 0;
}
int DrmProperty::getEnumValueWithName(const char *name, uint64_t & val) {
DISPLAY_ASSERT(mType == DRM_MODE_PROP_ENUM, "Only For RANG ENUM.");
for (int i = 0; i < mPropRes.count_enums; i++) {
if (strcmp(mPropRes.enums[i].name, name) == 0) {
val = mPropRes.enums[i].value;
return 0;
}
}
return -EINVAL;
}
int DrmProperty::getRangeValue(uint64_t &min, uint64_t &max) {
DISPLAY_ASSERT(mType == DRM_MODE_PROP_RANGE || mType == DRM_MODE_PROP_SIGNED_RANGE, "Only For RANG PROP.");
min = mPropRes.values[0];
max = mPropRes.values[1];
return 0;
}
int DrmProperty::apply(drmModeAtomicReqPtr req) {
return drmModeAtomicAddProperty(req, mComponentId, mPropRes.prop_id, getValue());
}