172 lines
5.5 KiB
C++
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());
|
|
}
|