Merge remote-tracking branch 'quic/display.lnx.7.0.1' into 8.0
Change-Id: I9312a2c7733584a86ad97d1f6bb81b03b193e190
diff --git a/Android.bp b/Android.bp
index f4e137d..2a55fb3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -140,4 +140,5 @@
"sdm/libs/core",
"qmaa",
"libmemutils",
+ "oem_services",
]
diff --git a/composer/Android.bp b/composer/Android.bp
index 924ac69..03b488b 100644
--- a/composer/Android.bp
+++ b/composer/Android.bp
@@ -60,6 +60,8 @@
"libgralloctypes",
"libdisplayconfig.qti",
"libdrm",
+ "libthermalclient",
+ "vendor.qti.hardware.display.demura@1.0",
],
srcs: composer_srcs,
diff --git a/composer/display_null.h b/composer/display_null.h
index 7cdd016..37fc4b4 100644
--- a/composer/display_null.h
+++ b/composer/display_null.h
@@ -66,6 +66,7 @@
virtual bool IsSupportSsppTonemap() { return false; }
virtual bool CanSkipValidate() { return true; }
virtual bool GameEnhanceSupported() { return false; }
+ virtual bool HasDemura() { return false; }
MAKE_NO_OP(Commit(LayerStack *))
MAKE_NO_OP(GetDisplayState(DisplayState *))
diff --git a/composer/hwc_display.cpp b/composer/hwc_display.cpp
index 5fb53e2..c9e7643 100644
--- a/composer/hwc_display.cpp
+++ b/composer/hwc_display.cpp
@@ -2516,6 +2516,10 @@
return false;
}
+ if (display_intf_->HasDemura()) {
+ return false;
+ }
+
bool skip_prepare = true;
for (auto hwc_layer : layer_set_) {
if (!hwc_layer->GetSDMLayer()->flags.skip ||
diff --git a/composer/ipc_impl.cpp b/composer/ipc_impl.cpp
index e4a6a7b..0d1e992 100644
--- a/composer/ipc_impl.cpp
+++ b/composer/ipc_impl.cpp
@@ -43,6 +43,11 @@
QRTRClientInterface *IPCImpl::qrtr_client_intf_ = nullptr;
int IPCImpl::Init() {
+ if (init_done_) {
+ DLOGW("IPC intf already initialized");
+ return 0;
+ }
+
// Try to load extension library & get handle to its interface.
if (qrtr_client_lib_.Open(QRTR_CLIENT_LIB_NAME)) {
if (!qrtr_client_lib_.Sym(CREATE_QRTR_CLIENT_INTERFACE_NAME,
@@ -68,11 +73,13 @@
} else {
DLOGW("Unable to load = %s, error = %s", QRTR_CLIENT_LIB_NAME, qrtr_client_lib_.Error());
}
+ init_done_ = true;
return 0;
}
int IPCImpl::Deinit() {
if (destroy_qrtr_client_intf_) {
+ init_done_ = false;
return destroy_qrtr_client_intf_(qrtr_client_intf_);
}
return 0;
@@ -138,11 +145,56 @@
}
int IPCImpl::ProcessOps(IPCOps op, const GenericPayload &in, GenericPayload *out) {
- (void)op;
- (void)in;
- (void)out;
- DLOGE("ProcessOps on op %d is not supported", op);
- return -ENOTSUP;
+ if (!out) {
+ return -EINVAL;
+ }
+
+ int ret = 0;
+
+ switch (op) {
+ case kIpcOpsFilePath: {
+ uint32_t sz = 0;
+ uint64_t* panel_id = nullptr;
+ std::string *demura_file = nullptr;
+ std::string file_path = "";
+ sp<IDemuraFileFinder> mClient = IDemuraFileFinder::getService();
+ if (mClient != NULL) {
+ if ((ret = in.GetPayload(panel_id, &sz))) {
+ DLOGE("Failed to get input payload error = %d", ret);
+ return ret;
+ }
+ DLOGI("panel_id %" PRIu64, *panel_id);
+ if ((ret = out->GetPayload(demura_file, &sz))) {
+ DLOGE("Failed to get output payload error = %d", ret);
+ return ret;
+ }
+ mClient->getCorrectionFile((*panel_id),
+ [&](const auto& tmpReturn, const auto& tmpHandle){
+ ret = tmpReturn;
+ if (ret != 0) {
+ file_path = "";
+ return;
+ }
+ file_path=(std::string)tmpHandle;
+ });
+ if (ret != 0) {
+ DLOGE("getCorrectionFile failed %d", ret);
+ return ret;
+ }
+ *demura_file = file_path;
+ DLOGI("File Path %s", file_path.c_str());
+ } else {
+ DLOGE("Could not get IDemuraFileFinder");
+ return -ENODEV;
+ }
+ break;
+ }
+ default:
+ DLOGE("Unsupported IPCOps");
+ return -EINVAL;
+ }
+
+ return ret;
}
int IPCImpl::OnResponse(Response *rsp) {
@@ -168,5 +220,4 @@
DLOGI("LE server is exited");
}
-
} // namespace sdm
diff --git a/composer/ipc_impl.h b/composer/ipc_impl.h
index e93d0a7..3011d57 100644
--- a/composer/ipc_impl.h
+++ b/composer/ipc_impl.h
@@ -35,8 +35,13 @@
#include "vm_interface.h"
#include "utils/sys.h"
+#include <vendor/qti/hardware/display/demura/1.0/IDemuraFileFinder.h>
+
namespace sdm {
+using ::android::sp;
+using ::vendor::qti::hardware::display::demura::V1_0::IDemuraFileFinder;
+
class IPCImpl: public IPCIntf, QRTRCallbackInterface {
public:
virtual ~IPCImpl() {};
@@ -54,6 +59,7 @@
static CreateQrtrClientIntf create_qrtr_client_intf_;
static DestroyQrtrClientIntf destroy_qrtr_client_intf_;
static QRTRClientInterface *qrtr_client_intf_;
+ bool init_done_ = false;
};
} // namespace sdm
diff --git a/config/display-product.mk b/config/display-product.mk
index df074af..fae91cd 100644
--- a/config/display-product.mk
+++ b/config/display-product.mk
@@ -33,6 +33,11 @@
modetest \
libmemutils
+#oem_services library
+PRODUCT_PACKAGES += \
+ libfilefinder \
+ vendor.qti.hardware.display.demura@1.0-service
+
ifneq ($(TARGET_HAS_LOW_RAM),true)
#QDCM calibration xml file for 2k panel
PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_nt35597_cmd_mode_dsi_truly_panel_with_DSC.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_nt35597_cmd_mode_dsi_truly_panel_with_DSC.xml
@@ -173,7 +178,11 @@
SOONG_CONFIG_qtidisplay_default := true
ifeq ($(TARGET_IS_HEADLESS), true)
+ # TODO: QMAA prebuilts
PRODUCT_SOONG_NAMESPACES += hardware/qcom/display/qmaa
+ PRODUCT_SOONG_NAMESPACES += hardware/qcom/display/gralloc
+ PRODUCT_SOONG_NAMESPACES += hardware/qcom/display/init
+ PRODUCT_SOONG_NAMESPACES += hardware/qcom/display/libdebug
SOONG_CONFIG_qtidisplay_headless := true
SOONG_CONFIG_qtidisplay_default := false
else
@@ -184,15 +193,16 @@
#Properties that should not be set in QMAA are enabled here.
PRODUCT_PROPERTY_OVERRIDES += \
vendor.display.enable_early_wakeup=1
- PRODUCT_SOONG_NAMESPACES += hardware/qcom/display
+ ifeq ($(BUILD_DISPLAY_TECHPACK_SOURCE), true)
+ PRODUCT_SOONG_NAMESPACES += hardware/qcom/display
+ PRODUCT_SOONG_NAMESPACES += hardware/qcom/display/gralloc
+ PRODUCT_SOONG_NAMESPACES += hardware/qcom/display/init
+ PRODUCT_SOONG_NAMESPACES += hardware/qcom/display/libdebug
+ else
+ PRODUCT_SOONG_NAMESPACES += vendor/qcom/opensource/techpack/artifacts/display
+ endif
endif
-#Modules that will be added in QMAA/Non-QMAA paths
-PRODUCT_SOONG_NAMESPACES += hardware/qcom/display/gralloc
-PRODUCT_SOONG_NAMESPACES += hardware/qcom/display/init
-PRODUCT_SOONG_NAMESPACES += hardware/qcom/display/libdebug
-
-
QMAA_ENABLED_HAL_MODULES += display
# Properties using default value:
diff --git a/include/display_properties.h b/include/display_properties.h
index d6d6501..375222d 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -125,6 +125,12 @@
#define ENABLE_SPR DISPLAY_PROP("enable_spr")
#define ENABLE_MEMORY_MAPPING DISPLAY_PROP("enable_memory_mapping")
+// Panel Feature Demura Properties
+#define ENABLE_DEMURA DISPLAY_PROP("enable_demura")
+#define DISABLE_DEMURA_PRIMARY DISPLAY_PROP("disable_demura_primary")
+#define DISABLE_DEMURA_SECONDARY DISPLAY_PROP("disable_demura_secondary")
+#define DISABLE_DEMURA_PANEL_REPLACEMENT DISPLAY_PROP("disable_demura_panel_replacement")
+
// PERF hint properties
#define ENABLE_PERF_HINT_LARGE_COMP_CYCLE DISPLAY_PROP("enable_perf_hint_large_comp_cycle")
#define DISABLE_DYNAMIC_FPS DISPLAY_PROP("disable_dynamic_fps")
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 238e878..c22c5e2 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -406,6 +406,11 @@
*/
COMMIT_PANEL_FEATURES,
/*
+ * Op: Null Commit panel features.
+ * Arg: drmModeAtomicReq - Atomic request
+ */
+ NULL_COMMIT_PANEL_FEATURES,
+ /*
* Op: Sets qsync mode on connector
* Arg: uint32_t - Connector ID
* uint32_t - qsync mode
@@ -455,6 +460,7 @@
OPAQUE = 1,
PREMULTIPLIED = 2,
COVERAGE = 3,
+ SKIP_BLENDING = 4,
};
enum struct DRMSrcConfig {
@@ -521,6 +527,10 @@
kInlineRotationV2,
};
+/* Type for panel feature resource reservation info */
+typedef std::tuple<std::string, int32_t, int8_t> FetchResource;
+typedef std::vector<FetchResource> FetchResourceList;
+
/* Per CRTC Resource Info*/
struct DRMCrtcInfo {
bool has_src_split;
@@ -565,6 +575,8 @@
uint32_t ubwc_version = 1;
bool has_spr = false;
uint64_t rc_total_mem_size = 0;
+ uint32_t demura_count = 0;
+ uint32_t dspp_count = 0;
};
enum struct DRMPlaneType {
@@ -612,6 +624,8 @@
uint32_t dgm_csc_version = 0; // csc used with DMA
std::map<DRMTonemapLutType, uint32_t> tonemap_lut_version_map = {};
bool block_sec_ui = false;
+ int32_t pipe_idx = -1;
+ int32_t demura_block_capability = -1;
};
// All DRM Planes as map<Plane_id , plane_type_info> listed from highest to lowest priority
@@ -685,6 +699,7 @@
bool dyn_bitclk_support;
std::vector<uint8_t> edid;
uint32_t supported_colorspaces;
+ uint64_t panel_id = 0;
};
// All DRM Connectors as map<Connector_id , connector_info>
@@ -734,6 +749,7 @@
kPropEnum,
kPropRange,
kPropBlob,
+ kPropBitmask,
kPropTypeMax,
};
@@ -810,6 +826,7 @@
};
enum DRMPanelFeatureID {
+ kDRMPanelFeaturePanelId,
kDRMPanelFeatureDsppIndex,
kDRMPanelFeatureDsppSPRInfo,
kDRMPanelFeatureDsppDemuraInfo,
@@ -818,6 +835,7 @@
kDRMPanelFeatureSPRPackType,
kDRMPanelFeatureDemuraInit,
kDRMPanelFeatureRCInit,
+ kDRMPanelFeatureDemuraResources,
kDRMPanelFeatureMax,
};
@@ -988,6 +1006,7 @@
/* Destroy DRMManager instance */
typedef int (*DestroyDRMManager)();
+
/*
* DRM Manager Interface - Any class which plans to implement helper function for vendor
* specific DRM driver implementation must implement the below interface routines to work
@@ -1129,6 +1148,33 @@
*/
virtual void SetPanelFeature(const DRMPanelFeatureInfo &info) = 0;
+ /*
+ * Mark particular panel feature property to be applied in the next null commit
+ * [input]: Display token to identify which display the property belongs to
+ * [input]: Feature ID
+ */
+ virtual void MarkPanelFeatureForNullCommit(const DRMDisplayToken &token,
+ const DRMPanelFeatureID &id) = 0;
+
+ /*
+ * Get the initial planes (cont. splash) info
+ * [input]: None
+ * [output]: Map from plane id to connector id
+ */
+ virtual void MapPlaneToConnector(std::map<uint32_t, uint32_t> *plane_to_connector) = 0;
+
+ /*
+ * Get the required Demura resources count for each Demura capable display type
+ * [output]: Key: display identifier Value: required demura resource count
+ */
+ virtual void GetRequiredDemuraFetchResourceCount(std::map<uint32_t, uint8_t>*
+ required_demura_fetch_cnt) = 0;
+
+ /*
+ * Get the planes used for Demura in initial boot (cont. splash)
+ * [output]: List of plane ids that were used for Demura
+ */
+ virtual void GetInitialDemuraInfo(std::vector<uint32_t> *initial_demura_planes) = 0;
};
} // namespace sde_drm
diff --git a/oem_services/Android.bp b/oem_services/Android.bp
new file mode 100644
index 0000000..69684bc
--- /dev/null
+++ b/oem_services/Android.bp
@@ -0,0 +1,82 @@
+//
+// file finder library
+//
+cc_library_shared {
+
+ name: "libfilefinder",
+ sanitize: {
+ integer_overflow: true,
+ },
+ cflags: [
+ "-Wno-undefined-bool-conversion",
+ "-Wno-format",
+ "-Wall",
+ "-fcolor-diagnostics",
+ "-Wno-unused-parameter",
+ "-DLOG_TAG=\"SDM\"",
+ ],
+ clang: true,
+ header_libs: ["display_headers"],
+
+ shared_libs: [
+ "liblog",
+ "libcutils",
+ "libdl",
+ "libutils",
+ "libdisplaydebug",
+ "vendor.qti.hardware.display.demura@1.0",
+ ],
+
+ srcs: ["file_finder_oem_extension.cpp"],
+ owner: "qti",
+ vendor: true,
+}
+
+//
+// demura hidl
+//
+
+cc_binary {
+
+ name: "vendor.qti.hardware.display.demura@1.0-service",
+ sanitize: {
+ integer_overflow: true,
+ },
+ cflags: [
+ "-Wno-undefined-bool-conversion",
+ "-Wno-format",
+ "-Wall",
+ "-fcolor-diagnostics",
+ "-Wno-unused-parameter",
+ "-DLOG_TAG=\"SDM\"",
+ ],
+ clang: true,
+
+ header_libs: ["display_headers"],
+
+ relative_install_path: "hw",
+
+ shared_libs: [
+ "liblog",
+ "libcutils",
+ "libdl",
+ "libutils",
+ "libbinder",
+ "libhidlbase",
+ "libfilefinder",
+ "libdisplaydebug",
+ "libsdmutils",
+ "vendor.qti.hardware.display.demura@1.0",
+ ],
+
+ srcs: [
+ "demura_file_finder.cpp",
+ "service.cpp",
+ ],
+
+ owner: "qti",
+ vendor: true,
+
+ init_rc: ["vendor.qti.hardware.display.demura@1.0-service.rc"],
+ vintf_fragments: ["vendor.qti.hardware.display.demura-service.xml"],
+}
diff --git a/oem_services/demura_file_finder.cpp b/oem_services/demura_file_finder.cpp
new file mode 100644
index 0000000..344cb0b
--- /dev/null
+++ b/oem_services/demura_file_finder.cpp
@@ -0,0 +1,154 @@
+/*
+ *Copyright (c) 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 <string>
+#include "demura_file_finder.h"
+
+namespace vendor {
+namespace qti {
+namespace hardware {
+namespace display {
+namespace demura {
+namespace V1_0 {
+namespace implementation {
+
+using sdm::FileFinderInterface;
+using sdm::GenericPayload;
+using sdm::kFileFinderFileData;
+
+IDemuraFileFinder *DemuraFileFinder::file_finder_ = NULL;
+FileFinderInterface *DemuraFileFinder::file_intf_ = NULL;
+DestroyFileFinderIntf DemuraFileFinder::destroy_ff_intf_ = NULL;
+
+IDemuraFileFinder *DemuraFileFinder::GetInstance() {
+ if (!file_finder_) {
+ sdm::DynLib demura_file_intf_lib;
+ if (!demura_file_intf_lib.Open(OEM_FILE_FINDER_LIB_NAME)) {
+ ALOGE("Failed to load lib %s", OEM_FILE_FINDER_LIB_NAME);
+ return nullptr;
+ }
+
+ GetFileFinderIntf get_ff_intf = NULL;
+
+ if (!demura_file_intf_lib.Sym(GET_FILE_FINDER_INTF_NAME,
+ reinterpret_cast<void **>(&(get_ff_intf)))) {
+ ALOGE("Unable to load symbols, err %s", demura_file_intf_lib.Error());
+ return nullptr;
+ }
+ if (!demura_file_intf_lib.Sym(DESTROY_FILE_FINDER_INTF_NAME,
+ reinterpret_cast<void **>(&(destroy_ff_intf_)))) {
+ ALOGE("Unable to load symbols, err %s", demura_file_intf_lib.Error());
+ return nullptr;
+ }
+
+ file_intf_ = get_ff_intf();
+ if (!file_intf_) {
+ ALOGE("Failed to get FileFinder Interface!");
+ return nullptr;
+ }
+
+ int error = file_intf_->Init();
+ if (error) {
+ ALOGE("Failed to initalize FileFinderInterface error = %d", error);
+ return nullptr;
+ }
+ file_finder_ = new DemuraFileFinder();
+ }
+
+ return file_finder_;
+}
+
+DemuraFileFinder::~DemuraFileFinder() {
+ if (file_intf_) {
+ file_intf_->Deinit();
+ if (destroy_ff_intf_) {
+ destroy_ff_intf_();
+ }
+ }
+}
+
+Return<void> DemuraFileFinder::getCorrectionFile(uint64_t panel_id, getCorrectionFile_cb _hidl_cb) {
+ int ret = 0;
+ std::string client_file = "";
+
+ if (!file_intf_) {
+ ALOGE("file_intf_ was not initialized, or not found. Command not supported");
+ ret = -EINVAL;
+ _hidl_cb(ret, client_file);
+ return Void();
+ }
+
+ if (panel_id == UINT64_MAX) {
+ ret = -EINVAL;
+ _hidl_cb(ret, client_file);
+ return Void();
+ }
+
+ uint64_t *input = nullptr;
+ GenericPayload in;
+ GenericPayload out;
+ std::string *path = nullptr;
+
+ int error = 0;
+ if ((error = in.CreatePayload(input))) {
+ ret = -ENOMEM;
+ ALOGE("Failed to create input payload error = %d", error);
+ _hidl_cb(ret, client_file);
+ return Void();
+ }
+
+ if ((error = out.CreatePayload(path))) {
+ ret = -ENOMEM;
+ ALOGE("Failed to create output payload error = %d", error);
+ _hidl_cb(ret, client_file);
+ return Void();
+ }
+
+ *input = panel_id;
+ if ((error = file_intf_->ProcessOps(kFileFinderFileData, in, &out))) {
+ ret = error;
+ ALOGE("Failed to process ops error = %d", error);
+ _hidl_cb(ret, client_file);
+ return Void();
+ }
+
+ ALOGI("Demura correction file %s", path->c_str());
+ client_file = *path;
+ _hidl_cb(ret, client_file);
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace demura
+} // namespace display
+} // namespace hardware
+} // namespace qti
+} // namespace vendor
diff --git a/oem_services/demura_file_finder.h b/oem_services/demura_file_finder.h
new file mode 100644
index 0000000..3aac305
--- /dev/null
+++ b/oem_services/demura_file_finder.h
@@ -0,0 +1,80 @@
+/*
+*Copyright (c) 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.
+*/
+
+#ifndef __DEMURA_FILE_FINDER_H__
+#define __DEMURA_FILE_FINDER_H__
+
+#include <vendor/qti/hardware/display/demura/1.0/IDemuraFileFinder.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <log/log.h>
+#include <utils/sys.h>
+#include <file_finder_interface.h>
+
+namespace vendor {
+namespace qti {
+namespace hardware {
+namespace display {
+namespace demura {
+namespace V1_0 {
+namespace implementation {
+using sdm::FileFinderInterface;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::vendor::qti::hardware::display::demura::V1_0::IDemuraFileFinder;
+
+#define OEM_FILE_FINDER_LIB_NAME "libfilefinder.so"
+#define GET_FILE_FINDER_INTF_NAME "GetFileFinderIntf"
+#define DESTROY_FILE_FINDER_INTF_NAME "DestroyFileFinderIntf"
+typedef FileFinderInterface *(*GetFileFinderIntf)();
+typedef void *(*DestroyFileFinderIntf)();
+
+class DemuraFileFinder : public IDemuraFileFinder {
+ public:
+ virtual ~DemuraFileFinder();
+ static IDemuraFileFinder *GetInstance();
+ static FileFinderInterface *file_intf_;
+ static IDemuraFileFinder *file_finder_;
+ static DestroyFileFinderIntf destroy_ff_intf_;
+
+ // IDemuraFileFinder
+ Return<void> getCorrectionFile(uint64_t panel_id, getCorrectionFile_cb _hidl_cb) override;
+
+ private:
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace demura
+} // namespace display
+} // namespace hardware
+} // namespace qti
+} // namespace vendor
+
+#endif // __DEMURA_FILE_FINDER_H__
diff --git a/oem_services/file_finder_interface.h b/oem_services/file_finder_interface.h
new file mode 100644
index 0000000..4303362
--- /dev/null
+++ b/oem_services/file_finder_interface.h
@@ -0,0 +1,53 @@
+/*
+*Copyright (c) 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.
+*/
+
+#ifndef __FILE_FINDER_INTERFACE_H__
+#define __FILE_FINDER_INTERFACE_H__
+
+#include <private/generic_intf.h>
+#include <private/generic_payload.h>
+
+namespace sdm {
+
+enum FileFinderParams {
+ kFileFinderParamMax
+};
+
+enum FileFinderOps {
+ kFileFinderFileData,
+ kFileFinderOpMax
+};
+
+using FileFinderInterface = sdm::GenericIntf<FileFinderParams, FileFinderOps, GenericPayload>;
+extern "C" FileFinderInterface* GetFileFinderIntf();
+extern "C" void DestroyFileFinderIntf();
+
+} // namespace sdm
+
+#endif // __FILE_FINDER_INTERFACE_H__
diff --git a/oem_services/file_finder_oem_extension.cpp b/oem_services/file_finder_oem_extension.cpp
new file mode 100644
index 0000000..034b55a
--- /dev/null
+++ b/oem_services/file_finder_oem_extension.cpp
@@ -0,0 +1,210 @@
+/*
+*Copyright (c) 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 <sstream>
+#include <iomanip>
+#include <string>
+#include "file_finder_oem_extension.h"
+
+#define __CLASS__ "FileFinderOemExtn"
+
+#define DESTINATION_PATH "/data/vendor/display/demura/"
+#define LOCAL_SOURCE_PATH "/vendor/etc/"
+#define FILE_CHUNK_SIZE 8192
+
+namespace sdm {
+
+FileFinderOemExtn *FileFinderOemExtn::file_finder_ = NULL;
+uint32_t FileFinderOemExtn::ref_count_ = 0;
+std::mutex FileFinderOemExtn::lock_ = {};
+
+FileFinderInterface *GetFileFinderIntf() {
+ std::lock_guard<std::mutex> g(FileFinderOemExtn::lock_);
+ if (FileFinderOemExtn::file_finder_ == NULL) {
+ FileFinderOemExtn::file_finder_ = new FileFinderOemExtn();
+ }
+ FileFinderOemExtn::ref_count_++;
+ return FileFinderOemExtn::file_finder_;
+}
+
+void DestroyFileFinderIntf() {
+ std::lock_guard<std::mutex> g(FileFinderOemExtn::lock_);
+ FileFinderOemExtn::ref_count_--;
+ if (FileFinderOemExtn::ref_count_ == 0) {
+ delete FileFinderOemExtn::file_finder_;
+ FileFinderOemExtn::file_finder_ = NULL;
+ }
+}
+
+FileFinderOemExtn::FileFinderOemExtn() {
+ std::function<int(FileFinderOemExtn *, const GenericPayload &, GenericPayload *)> ffd =
+ &FileFinderOemExtn::FindFileData;
+ ops_fcns_.emplace(kFileFinderFileData, ffd);
+}
+
+int FileFinderOemExtn::Init() {
+ return 0;
+}
+
+int FileFinderOemExtn::Deinit() {
+ return 0;
+}
+
+int FileFinderOemExtn::SetParameter(FileFinderParams param, const GenericPayload &in) {
+ (void)param;
+ (void)in;
+ DLOGE("SetParameter on param %d not supported", param);
+ return -ENOTSUP;
+}
+
+int FileFinderOemExtn::GetParameter(FileFinderParams param, GenericPayload *out) {
+ (void)param;
+ (void)out;
+ DLOGE("GetParameter on param %d not supported", param);
+ return -ENOTSUP;
+}
+
+int FileFinderOemExtn::ProcessOps(FileFinderOps op, const GenericPayload &in, GenericPayload *out) {
+ if (out == NULL) {
+ return -EINVAL;
+ }
+
+ if (op < kFileFinderOpMax) {
+ auto fcn = ops_fcns_.at(op);
+ return fcn(this, in, out);
+ } else {
+ DLOGE("Invalid op %d", op);
+ return -EINVAL;
+ }
+}
+
+int FileFinderOemExtn::FindFileData(const GenericPayload &in, GenericPayload *out) {
+ int status = 0;
+ uint32_t sz = 0;
+ uint64_t *panel_id = nullptr;
+ std::string panel_id_hex_str = "";
+ FILE *file_in = nullptr;
+ FILE *file_out = nullptr;
+ std::string *file_path = nullptr;
+ std::string file_path_out = "";
+
+ status = in.GetPayload(panel_id, &sz);
+ if ((status != 0) || sz != 1) {
+ return -EINVAL;
+ }
+ std::stringstream temp;
+ uint64_t id = *panel_id;
+ temp << std::setfill('0') << std::setw(16) << std::hex << id << std::dec;
+ panel_id_hex_str = temp.str();
+
+ status = out->GetPayload(file_path, &sz);
+ if ((status != 0) || sz != 1) {
+ return -EINVAL;
+ }
+
+ file_in = getSrcFile(panel_id_hex_str);
+ if (!file_in) {
+ DLOGE("Did not get a correction file");
+ *file_path = "";
+ return -EINVAL;
+ }
+
+ errno = 0;
+ status = mkdir(DESTINATION_PATH, 755);
+ if ((status != 0) && errno != EEXIST) {
+ DLOGE("Failed to create %s directory errno = %d, desc = %s", DESTINATION_PATH, errno,
+ strerror(errno));
+ fclose(file_in);
+ return -EPERM;
+ }
+
+ // Even if directory exists already, need to explicitly change the permission.
+ if (chmod(DESTINATION_PATH, 0755) != 0) {
+ DLOGE("Failed to change permissions on %s directory", DESTINATION_PATH);
+ fclose(file_in);
+ return -EACCES;
+ }
+
+ std::string ds = DESTINATION_PATH;
+ file_path_out = ds + "demura_config_" + panel_id_hex_str;
+ file_out = fopen(file_path_out.c_str(), "wb+");
+ if (file_out == NULL) {
+ DLOGI("cannot create file for writing in /data\n");
+ fclose(file_in);
+ return -ENOENT;
+ }
+
+ // Read and write contents from file
+ size_t bytes = 0;
+ uint8_t buffer[FILE_CHUNK_SIZE] = {};
+ while ((bytes = fread(buffer, 1, sizeof(buffer), file_in)) > 0) {
+ fwrite(buffer, 1, bytes, file_out);
+ }
+
+ fclose(file_in);
+ fclose(file_out);
+
+ *file_path = file_path_out;
+ return 0;
+}
+
+FILE *FileFinderOemExtn::getSrcFile(const std::string &panel_id_hex_str) {
+ FILE *file = NULL;
+ std::string sp = LOCAL_SOURCE_PATH;
+ std::string src_path = sp + "demura_config_" + panel_id_hex_str;
+ errno = 0;
+ file = fopen(src_path.c_str(), "rb");
+ if (file == NULL) {
+ DLOGW("Failed to open file locally at %s. Error = %s", src_path.c_str(), strerror(errno));
+ src_path = getFileOTA(panel_id_hex_str);
+ errno = 0;
+ file = fopen(src_path.c_str(), "rb");
+ if (file == NULL) {
+ DLOGE("Failed to open file after OTA at %s. Error = %s", src_path.c_str(), strerror(errno));
+ }
+ }
+
+ return file;
+}
+
+std::string FileFinderOemExtn::getFileOTA(const std::string &panel_id_hex_str) {
+ /*
+ * Communication to a server shall begin here.
+ * API shall securely contact the server and download the data to a file on the device
+ * and the location must accessible for both read and write by this process.
+ * This API shall return the path to the file to the caller.
+ *
+ * The stub impl of this API simply returns the local path the caller would have already checked
+ * before requesting server download of the file.
+ */
+ std::string sp = LOCAL_SOURCE_PATH;
+ return sp + "demura_config_" + panel_id_hex_str;
+}
+
+} // namespace sdm
diff --git a/oem_services/file_finder_oem_extension.h b/oem_services/file_finder_oem_extension.h
new file mode 100644
index 0000000..563151e
--- /dev/null
+++ b/oem_services/file_finder_oem_extension.h
@@ -0,0 +1,70 @@
+/*
+*Copyright (c) 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.
+*/
+
+#ifndef __FILE_FINDER_OEM_EXTENSION_H__
+#define __FILE_FINDER_OEM_EXTENSION_H__
+
+#include <vendor/qti/hardware/display/demura/1.0/IDemuraFileFinder.h>
+#include <log/log.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+#include <mutex>
+#include <map>
+#include <string>
+#include "file_finder_interface.h"
+#include "debug_handler.h"
+
+using ::vendor::qti::hardware::display::demura::V1_0::IDemuraFileFinder;
+
+namespace sdm {
+
+class FileFinderOemExtn : public FileFinderInterface {
+ public:
+ virtual ~FileFinderOemExtn() {}
+ FileFinderOemExtn();
+ int Init();
+ int Deinit();
+ int SetParameter(FileFinderParams param, const GenericPayload &in);
+ int GetParameter(FileFinderParams param, GenericPayload *out);
+ int ProcessOps(FileFinderOps op, const GenericPayload &in, GenericPayload *out);
+ static FileFinderOemExtn *file_finder_;
+ static uint32_t ref_count_;
+ static std::mutex lock_;
+
+ private:
+ int FindFileData(const GenericPayload &in, GenericPayload *out);
+ FILE *getSrcFile(const std::string &panel_id_hex_str);
+ std::string getFileOTA(const std::string &panel_id_hex_str);
+ std::map<FileFinderOps,
+ std::function<int(FileFinderOemExtn *, const GenericPayload &, GenericPayload *)>>
+ ops_fcns_;
+};
+} // namespace sdm
+
+#endif // __FILE_FINDER_OEM_EXTENSION_H__
diff --git a/oem_services/service.cpp b/oem_services/service.cpp
new file mode 100644
index 0000000..a97d349
--- /dev/null
+++ b/oem_services/service.cpp
@@ -0,0 +1,63 @@
+/*
+*Copyright (c) 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 <vendor/qti/hardware/display/demura/1.0/IDemuraFileFinder.h>
+#include <hidl/Status.h>
+#include <hidl/MQDescriptor.h>
+#include <binder/ProcessState.h>
+#include <hidl/LegacySupport.h>
+#include <log/log.h>
+#include "demura_file_finder.h"
+
+
+using vendor::qti::hardware::display::demura::V1_0::IDemuraFileFinder;
+using vendor::qti::hardware::display::demura::V1_0::implementation::DemuraFileFinder;
+
+using android::sp;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+
+using android::status_t;
+using android::OK;
+
+int main() {
+ android::ProcessState::initWithDriver("/dev/vndbinder");
+ android::sp<IDemuraFileFinder> demura_file_finder = DemuraFileFinder::GetInstance();
+ if (!demura_file_finder) {
+ ALOGE("Could not create the IDemuraFileFinder, not registering process!!");
+ return -1;
+ }
+ configureRpcThreadpool(1, true /*callerWillJoin*/);
+ if (demura_file_finder->registerAsService() != OK) {
+ ALOGE("Cannot register DemuraFileFinder service");
+ return -EINVAL;
+ }
+ joinRpcThreadpool();
+ return 0;
+}
diff --git a/oem_services/vendor.qti.hardware.display.demura-service.xml b/oem_services/vendor.qti.hardware.display.demura-service.xml
new file mode 100644
index 0000000..e8d1cdc
--- /dev/null
+++ b/oem_services/vendor.qti.hardware.display.demura-service.xml
@@ -0,0 +1,39 @@
+<!--
+*Copyright (c) 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.
+-->
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>vendor.qti.hardware.display.demura</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IDemuraFileFinder</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/oem_services/vendor.qti.hardware.display.demura@1.0-service.rc b/oem_services/vendor.qti.hardware.display.demura@1.0-service.rc
new file mode 100644
index 0000000..5316b6c
--- /dev/null
+++ b/oem_services/vendor.qti.hardware.display.demura@1.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.qti.hardware.display.demura /vendor/bin/hw/vendor.qti.hardware.display.demura@1.0-service
+ class hal
+ user system
+ group graphics
diff --git a/sde-drm/drm_atomic_req.cpp b/sde-drm/drm_atomic_req.cpp
index 87f863e..17f1a5a 100644
--- a/sde-drm/drm_atomic_req.cpp
+++ b/sde-drm/drm_atomic_req.cpp
@@ -141,6 +141,9 @@
case DRMOps::COMMIT_PANEL_FEATURES: {
drm_mgr_->GetPanelFeatureMgrIntf()->CommitPanelFeatures(drm_atomic_req_, token_);
} break;
+ case DRMOps::NULL_COMMIT_PANEL_FEATURES: {
+ drm_mgr_->GetPanelFeatureMgrIntf()->NullCommitPanelFeatures(drm_atomic_req_, token_);
+ } break;
default:
DRM_LOGE("Invalid opcode %d", opcode);
}
diff --git a/sde-drm/drm_connector.cpp b/sde-drm/drm_connector.cpp
index 0223f18..0837cba 100644
--- a/sde-drm/drm_connector.cpp
+++ b/sde-drm/drm_connector.cpp
@@ -54,6 +54,7 @@
using std::string;
using std::stringstream;
using std::pair;
+using std::make_pair;
using std::vector;
using std::unique_ptr;
using std::map;
@@ -432,6 +433,77 @@
token->conn_id = 0;
}
+// DSI only
+int DRMConnectorManager::GetPreferredModeLMCounts(std::map<uint32_t, uint8_t> *lm_counts) {
+ lock_guard<mutex> lock(lock_);
+ int ret = 0;
+ for (auto &conn : connector_pool_) {
+ uint32_t conn_type;
+ const uint32_t &id = conn.first;
+ conn.second->GetType(&conn_type);
+ if (conn_type == DRM_MODE_CONNECTOR_DSI) {
+ DRMConnectorInfo info = {};
+ connector_pool_[id]->GetInfo(&info);
+ uint8_t lm_cnt = 0;
+ uint32_t mode_index = 0;
+ for (uint32_t index = 0; index < info.modes.size(); index++) {
+ if (info.modes[index].mode.type & DRM_MODE_TYPE_PREFERRED) {
+ mode_index = index;
+ break;
+ }
+ }
+
+ switch (info.modes[mode_index].topology) {
+ case DRMTopology::SINGLE_LM:
+ case DRMTopology::SINGLE_LM_DSC:
+ case DRMTopology::PPSPLIT:
+ lm_cnt = 1;
+ break;
+ case DRMTopology::DUAL_LM:
+ case DRMTopology::DUAL_LM_DSC:
+ case DRMTopology::DUAL_LM_MERGE:
+ case DRMTopology::DUAL_LM_MERGE_DSC:
+ case DRMTopology::DUAL_LM_DSCMERGE:
+ lm_cnt = 2;
+ break;
+ case DRMTopology::QUAD_LM_MERGE:
+ case DRMTopology::QUAD_LM_DSCMERGE:
+ case DRMTopology::QUAD_LM_MERGE_DSC:
+ case DRMTopology::QUAD_LM_DSC4HSMERGE:
+ lm_cnt = 4;
+ break;
+ default:
+ lm_cnt = UINT8_MAX;
+ DLOGE("Invalid lm_cnt for connector %u", id);
+ break;
+ }
+
+ if (lm_cnt != UINT8_MAX) {
+ (*lm_counts)[id] = lm_cnt;
+ }
+ }
+ }
+
+ return ret;
+}
+
+void DRMConnectorManager::MapEncoderToConnector(std::map<uint32_t, uint32_t> *encoder_to_connector) {
+ lock_guard<mutex> lock(lock_);
+
+ if (!encoder_to_connector) {
+ DLOGE("map is NULL! Not expected.");
+ return;
+ }
+
+ encoder_to_connector->clear();
+
+ for (auto &conn : connector_pool_) {
+ uint32_t encoder_id = 0;
+ conn.second->GetEncoder(&encoder_id);
+ if (encoder_id)
+ encoder_to_connector->insert(make_pair(encoder_id, conn.first));
+ }
+}
// ==============================================================================================//
#undef __CLASS__
@@ -618,7 +690,7 @@
// Move to the next mode_item
mode_item = &info->modes.at(index++);
} else if (line.find(topology) != string::npos) {
- mode_item->topology = GetTopologyEnum(string(line, topology.length()));;
+ mode_item->topology = GetTopologyEnum(string(line, topology.length()));
} else if (line.find(pu_num_roi) != string::npos) {
mode_item->num_roi = std::stoi(string(line, pu_num_roi.length()));
} else if (line.find(pu_xstart) != string::npos) {
@@ -689,6 +761,27 @@
drmModeFreePropertyBlob(blob);
}
+void DRMConnector::ParseCapabilities(uint64_t blob_id, uint64_t *panel_id) {
+ drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(fd_, blob_id);
+ if (!blob) {
+ return;
+ }
+
+ if (blob->length != sizeof(uint64_t)) {
+ DRM_LOGE("Expecting %zu bytes but got %u", sizeof(uint64_t), blob->length);
+ return;
+ }
+
+ // Read as-is / big endian. Driver has supplied the value in this manner.
+ uint8_t *data = (uint8_t*)(blob->data);
+ for (size_t i = 0; i < blob->length; i++) {
+ *panel_id = (*panel_id << 8) | *data;
+ data++;
+ }
+
+ drmModeFreePropertyBlob(blob);
+}
+
int DRMConnector::GetInfo(DRMConnectorInfo *info) {
uint32_t conn_id = drm_connector_->connector_id;
if (!skip_connector_reload_ && (IsTVConnector(drm_connector_->connector_type)
@@ -792,6 +885,13 @@
info->supported_colorspaces = props->prop_values[index];
}
+ if (prop_mgr_.IsPropertyAvailable(DRMProperty::DEMURA_PANEL_ID)) {
+ index = std::distance(props->props,
+ std::find(props->props, props->props + props->count_props,
+ prop_mgr_.GetPropertyId(DRMProperty::DEMURA_PANEL_ID)));
+ ParseCapabilities(props->prop_values[index], &info->panel_id);
+ }
+
drmModeFreeObjectProperties(props);
return 0;
diff --git a/sde-drm/drm_connector.h b/sde-drm/drm_connector.h
index 24f6e99..bd43cf2 100644
--- a/sde-drm/drm_connector.h
+++ b/sde-drm/drm_connector.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+* 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
@@ -57,6 +57,7 @@
DRMStatus GetStatus() { return status_; }
int GetInfo(DRMConnectorInfo *info);
void GetType(uint32_t *conn_type) { *conn_type = drm_connector_->connector_type; }
+ void GetEncoder(uint32_t *encoder_id) { *encoder_id = drm_connector_->encoder_id; }
void Perform(DRMOps code, drmModeAtomicReq *req, va_list args);
int IsConnected() { return (DRM_MODE_CONNECTED == drm_connector_->connection); }
int GetPossibleEncoders(std::set<uint32_t> *possible_encoders);
@@ -70,6 +71,7 @@
void ParseModeProperties(uint64_t blob_id, DRMConnectorInfo *info);
void ParseCapabilities(uint64_t blob_id, drm_msm_ext_hdr_properties *hdr_info);
void ParseCapabilities(uint64_t blob_id, std::vector<uint8_t> *edid);
+ void ParseCapabilities(uint64_t blob_id, uint64_t *panel_id);
void SetROI(drmModeAtomicReq *req, uint32_t obj_id, uint32_t num_roi,
DRMRect *conn_rois);
@@ -99,6 +101,8 @@
int GetConnectorInfo(uint32_t conn_id, DRMConnectorInfo *info);
void GetConnectorList(std::vector<uint32_t> *conn_ids);
int GetPossibleEncoders(uint32_t connector_id, std::set<uint32_t> *possible_encoders);
+ int GetPreferredModeLMCounts(std::map<uint32_t, uint8_t> *lm_counts);
+ void MapEncoderToConnector(std::map<uint32_t, uint32_t> *encoder_to_connector);
~DRMConnectorManager() {}
private:
diff --git a/sde-drm/drm_crtc.cpp b/sde-drm/drm_crtc.cpp
index b17e009..c468b47 100644
--- a/sde-drm/drm_crtc.cpp
+++ b/sde-drm/drm_crtc.cpp
@@ -298,6 +298,13 @@
crtc_pool_.at(crtc_id)->PostCommit(success);
}
+void DRMCrtcManager::GetCrtcList(std::vector<uint32_t> *crtc_ids) {
+ lock_guard<mutex> lock(lock_);
+ for (auto &crtc : crtc_pool_) {
+ crtc_ids->emplace_back(crtc.first);
+ }
+}
+
// ==============================================================================================//
#undef __CLASS__
@@ -424,6 +431,8 @@
string ubwc_version = "UBWC version=";
string spr = "spr=";
string rc_total_mem_size = "rc_mem_size=";
+ string demura_count = "demura_count=";
+ string dspp_count = "dspp_count=";
while (std::getline(stream, line)) {
if (line.find(max_blendstages) != string::npos) {
@@ -544,6 +553,10 @@
crtc_info_.has_spr = std::stoi(string(line, spr.length())) == -1 ? false: true;
} else if (line.find(rc_total_mem_size) != string::npos) {
crtc_info_.rc_total_mem_size = std::stoi(string(line, rc_total_mem_size.length()));
+ } else if (line.find(demura_count) != string::npos) {
+ crtc_info_.demura_count = std::stoi(string(line, demura_count.length()));
+ } else if (line.find(dspp_count) != string::npos) {
+ crtc_info_.dspp_count = std::stoi(string(line, dspp_count.length()));
}
}
drmModeFreePropertyBlob(blob);
diff --git a/sde-drm/drm_crtc.h b/sde-drm/drm_crtc.h
index a17b222..7ba3dc5 100644
--- a/sde-drm/drm_crtc.h
+++ b/sde-drm/drm_crtc.h
@@ -119,6 +119,7 @@
void GetPPInfo(uint32_t crtc_id, DRMPPFeatureInfo *info);
void PostValidate(uint32_t crtc_id, bool success);
void PostCommit(uint32_t crtc_id, bool success);
+ void GetCrtcList(std::vector<uint32_t> *crtc_ids);
private:
int fd_ = -1;
diff --git a/sde-drm/drm_encoder.cpp b/sde-drm/drm_encoder.cpp
index ed2d8bf..cb38984 100644
--- a/sde-drm/drm_encoder.cpp
+++ b/sde-drm/drm_encoder.cpp
@@ -205,6 +205,22 @@
return encoder_pool_[encoder_id]->GetPossibleCrtcIndices(possible_crtc_indices);
}
+void DRMEncoderManager::MapCrtcToEncoder(std::map<uint32_t, uint32_t> *crtc_to_encoder) {
+ if (!crtc_to_encoder) {
+ DLOGE("Map is NULL! Not expected.");
+ return;
+ }
+
+ crtc_to_encoder->clear();
+
+ for (auto &encoder : encoder_pool_) {
+ uint32_t crtc_id = 0;
+ encoder.second->GetCrtc(&crtc_id);
+ if (crtc_id)
+ crtc_to_encoder->insert(make_pair(crtc_id, encoder.first));
+ }
+}
+
// ==============================================================================================//
#undef __CLASS__
diff --git a/sde-drm/drm_encoder.h b/sde-drm/drm_encoder.h
index c4ea586..a9f7217 100644
--- a/sde-drm/drm_encoder.h
+++ b/sde-drm/drm_encoder.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+* 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
@@ -51,12 +51,13 @@
DRMStatus GetStatus() { return status_; }
void GetInfo(DRMEncoderInfo *info);
void GetType(uint32_t *encoder_type) {
- drm_encoder_ ? *encoder_type = drm_encoder_->encoder_type
- : *encoder_type = fake_type_;
+ *encoder_type = drm_encoder_ ? drm_encoder_->encoder_type : fake_type_;
}
void GetId(uint32_t *encoder_id) {
- drm_encoder_ ? *encoder_id = drm_encoder_->encoder_id
- : *encoder_id = fake_id_;
+ *encoder_id = drm_encoder_ ? drm_encoder_->encoder_id : fake_id_;
+ }
+ void GetCrtc(uint32_t *crtc_id) {
+ *crtc_id = drm_encoder_ ? drm_encoder_->crtc_id : 0;
}
int GetPossibleCrtcIndices(std::set<uint32_t> *possible_crtc_indices);
void Dump();
@@ -89,6 +90,7 @@
int GetEncoderInfo(uint32_t encoder_id, DRMEncoderInfo *info);
int GetEncoderList(std::vector<uint32_t> *encoder_ids);
int GetPossibleCrtcIndices(uint32_t encoder_id, std::set<uint32_t> *possible_crtc_indices);
+ void MapCrtcToEncoder(std::map<uint32_t, uint32_t> *crtc_to_encoder);
private:
int fd_ = -1;
diff --git a/sde-drm/drm_manager.cpp b/sde-drm/drm_manager.cpp
index 6a45710..04a4b15 100644
--- a/sde-drm/drm_manager.cpp
+++ b/sde-drm/drm_manager.cpp
@@ -39,6 +39,8 @@
using std::lock_guard;
using std::mutex;
+using std::pair;
+using std::make_pair;
extern "C" {
@@ -386,7 +388,7 @@
dpps_mgr_intf_->GetDppsFeatureInfo(info);
}
-DRMPanelFeatureMgrIntf *DRMManager::GetPanelFeatureMgrIntf() {
+DRMPanelFeatureMgrIntf* DRMManager::GetPanelFeatureMgrIntf() {
return panel_feature_mgr_intf_;
}
@@ -406,4 +408,95 @@
}
}
+void DRMManager::MarkPanelFeatureForNullCommit(const DRMDisplayToken &token,
+ const DRMPanelFeatureID &id) {
+ if (panel_feature_mgr_intf_) {
+ panel_feature_mgr_intf_->MarkForNullCommit(token, id);
+ } else {
+ DRM_LOGE("Failed, panel feature mgr not available");
+ }
+}
+
+void DRMManager::MapPlaneToConnector(std::map<uint32_t, uint32_t> *plane_to_connector) {
+ if (!plane_to_connector) {
+ DRM_LOGE("Map is NULL! Not expected.");
+ return;
+ }
+
+ plane_to_connector->clear();
+
+ std::map<uint32_t, uint32_t> plane_to_crtc;
+ std::map<uint32_t, uint32_t> crtc_to_encoder;
+ std::map<uint32_t, uint32_t> encoder_to_connector;
+
+ // Cont. Splash planes are detected by CRTC existence on the PLANE
+ // These are the planes that ultimately need to know their CONNECTOR
+ plane_mgr_->MapPlaneToCrtc(&plane_to_crtc);
+ if (!plane_to_crtc.size()) {
+ DRM_LOGI("No cont. splash planes found");
+ return;
+ }
+
+ // CRTC is connected to ENCODER. Find the ENCODERs who have CRTCs and establish
+ // reverse lookup CRTC --> ENCODER
+ encoder_mgr_->MapCrtcToEncoder(&crtc_to_encoder);
+ if (!crtc_to_encoder.size()) {
+ DRM_LOGW("Planes are associated with CRTCs but no CRTC to ENCODERs found");
+ return;
+ }
+
+ // ENCODER is connected to CONNECTOR. Find the CONNECTORs who have ENCODERs and establish
+ // reverse lookup ENCODER --> CONNECTOR
+ conn_mgr_->MapEncoderToConnector(&encoder_to_connector);
+ if (!encoder_to_connector.size()) {
+ DRM_LOGW("CRTCs are associated with ENCODERs but no ENCODERs to CONNECTORs found");
+ return;
+ }
+
+ // Link the Cont. Splash PLANEs with their CONNECTOR
+ for (auto &plane_entry : plane_to_crtc) {
+ uint32_t plane_id = plane_entry.first;
+ auto &crtc_id = plane_entry.second;
+ auto enc_entry = crtc_to_encoder.find(crtc_id);
+ if (enc_entry == crtc_to_encoder.end()) {
+ DRM_LOGW("Plane %u mapped to crtc %u didn't have an encoder. Not expected.", plane_id,
+ crtc_id);
+ continue;
+ }
+ auto &encoder_id = enc_entry->second;
+ auto conn_entry = encoder_to_connector.find(encoder_id);
+ if (conn_entry == encoder_to_connector.end()) {
+ DRM_LOGW("Plane %u, crtc %u, encoder %u, didn't have a connector. Not expected.",
+ plane_id, crtc_id, encoder_id);
+ continue;
+ }
+ uint32_t connector_id = conn_entry->second;
+
+ plane_to_connector->insert(make_pair(plane_id, connector_id));
+ }
+}
+
+void DRMManager::GetRequiredDemuraFetchResourceCount(
+ std::map<uint32_t, uint8_t> *required_demura_fetch_cnt) {
+ conn_mgr_->GetPreferredModeLMCounts(required_demura_fetch_cnt);
+}
+
+void DRMManager::GetInitialDemuraInfo(std::vector<uint32_t> *initial_demura_planes) {
+ if (panel_feature_mgr_intf_) {
+ initial_demura_planes->clear();
+ std::vector<uint32_t> crtc_ids;
+ crtc_mgr_->GetCrtcList(&crtc_ids);
+ FetchResourceList frl;
+ for (auto &id : crtc_ids) {
+ DRMPanelFeatureInfo info;
+ info.prop_id = kDRMPanelFeatureDemuraResources;
+ info.obj_type = DRM_MODE_OBJECT_CRTC;
+ info.obj_id = id;
+ info.prop_ptr = reinterpret_cast<uint64_t>(&frl);
+ panel_feature_mgr_intf_->GetPanelFeatureInfo(&info);
+ }
+ // Safe to assume pipe to crtc to Demura associations are functionally correct
+ plane_mgr_->GetPlaneIdsFromDescriptions(frl, initial_demura_planes);
+ }
+}
} // namespace sde_drm
diff --git a/sde-drm/drm_manager.h b/sde-drm/drm_manager.h
index 6f47594..850c594 100644
--- a/sde-drm/drm_manager.h
+++ b/sde-drm/drm_manager.h
@@ -66,6 +66,12 @@
virtual void GetDppsFeatureInfo(DRMDppsFeatureInfo *info);
virtual void GetPanelFeature(DRMPanelFeatureInfo *info);
virtual void SetPanelFeature(const DRMPanelFeatureInfo &info);
+ virtual void MapPlaneToConnector(std::map<uint32_t, uint32_t> *plane_to_connector);
+ virtual void GetRequiredDemuraFetchResourceCount(std::map<uint32_t, uint8_t>
+ *required_demura_fetch_cnt);
+ virtual void GetInitialDemuraInfo(std::vector<uint32_t> *initial_demura_planes);
+ virtual void MarkPanelFeatureForNullCommit(const DRMDisplayToken &token,
+ const DRMPanelFeatureID &id);
DRMPlaneManager *GetPlaneMgr();
DRMConnectorManager *GetConnectorMgr();
diff --git a/sde-drm/drm_panel_feature_mgr.cpp b/sde-drm/drm_panel_feature_mgr.cpp
index 4aba91b..fac11a2 100644
--- a/sde-drm/drm_panel_feature_mgr.cpp
+++ b/sde-drm/drm_panel_feature_mgr.cpp
@@ -28,6 +28,8 @@
*/
#include <sstream>
+#include <string>
+#include <tuple>
#include <errno.h>
#include <string>
#include <drm_logger.h>
@@ -48,6 +50,12 @@
static DRMPanelFeatureMgr panel_feature_mgr;
+// Demura Planes' Default Bit Indices
+static uint8_t DEMURA_DMA1RECT0 = 0x1;
+static uint8_t DEMURA_DMA1RECT1 = 0x2;
+static uint8_t DEMURA_DMA3RECT0 = 0x3;
+static uint8_t DEMURA_DMA3RECT1 = 0x4;
+
DRMPanelFeatureMgrIntf *GetPanelFeatureManagerIntf() {
return &panel_feature_mgr;
}
@@ -85,6 +93,9 @@
}
}
+ drm_property_map_[kDRMPanelFeatureDemuraResources] = DRMProperty::DEMURA_BOOT_PLANE_V1;
+ drm_property_map_[kDRMPanelFeatureDemuraInit] = DRMProperty::DEMURA_INIT_CFG_V1;
+ drm_property_map_[kDRMPanelFeaturePanelId] = DRMProperty::DEMURA_PANEL_ID;
drm_property_map_[kDRMPanelFeatureSPRInit] = DRMProperty::SPR_INIT_CFG_V1;
drm_property_map_[kDRMPanelFeatureSPRPackType] = DRMProperty::CAPABILITIES;
drm_property_map_[kDRMPanelFeatureDsppIndex] = DRMProperty::DSPP_CAPABILITIES;
@@ -93,6 +104,9 @@
drm_property_map_[kDRMPanelFeatureDsppRCInfo] = DRMProperty::DSPP_CAPABILITIES;
drm_property_map_[kDRMPanelFeatureRCInit] = DRMProperty::DSPP_RC_MASK_V1;
+ drm_prop_type_map_[kDRMPanelFeatureDemuraResources] = DRMPropType::kPropBitmask;
+ drm_prop_type_map_[kDRMPanelFeatureDemuraInit] = DRMPropType::kPropBlob;
+ drm_prop_type_map_[kDRMPanelFeaturePanelId] = DRMPropType::kPropBlob;
drm_prop_type_map_[kDRMPanelFeatureSPRInit] = DRMPropType::kPropBlob;
drm_prop_type_map_[kDRMPanelFeatureRCInit] = DRMPropType::kPropBlob;
drm_prop_type_map_[kDRMPanelFeatureSPRPackType] = DRMPropType::kPropBlob;
@@ -101,6 +115,12 @@
drm_prop_type_map_[kDRMPanelFeatureDsppDemuraInfo] = DRMPropType::kPropRange;
drm_prop_type_map_[kDRMPanelFeatureDsppRCInfo] = DRMPropType::kPropRange;
+ feature_info_tbl_[kDRMPanelFeatureDemuraResources] = DRMPanelFeatureInfo {
+ kDRMPanelFeatureDemuraResources, DRM_MODE_OBJECT_CRTC, UINT32_MAX, 1, 0, 0};
+ feature_info_tbl_[kDRMPanelFeatureDemuraInit] = DRMPanelFeatureInfo {kDRMPanelFeatureDemuraInit,
+ DRM_MODE_OBJECT_CRTC, UINT32_MAX, 1, sizeof(drm_msm_dem_cfg), 0};
+ feature_info_tbl_[kDRMPanelFeaturePanelId] = DRMPanelFeatureInfo {kDRMPanelFeaturePanelId,
+ DRM_MODE_OBJECT_CONNECTOR, UINT32_MAX, 1, sizeof(uint64_t), 0};
feature_info_tbl_[kDRMPanelFeatureSPRInit] = DRMPanelFeatureInfo {kDRMPanelFeatureSPRInit,
DRM_MODE_OBJECT_CRTC, UINT32_MAX, 1, sizeof(drm_msm_spr_init_cfg), 0};
feature_info_tbl_[kDRMPanelFeatureRCInit] = DRMPanelFeatureInfo {
@@ -169,8 +189,64 @@
return 0;
}
+void DRMPanelFeatureMgr::ParsePanelId(uint32_t blob_id, DRMPanelFeatureInfo *info) {
+ drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(dev_fd_, blob_id);
+ if (!blob) {
+ return;
+ }
+
+ if (blob->length != sizeof(uint64_t)) {
+ DRM_LOGE("Expecting %zu bytes but got %u", sizeof(uint64_t), blob->length);
+ return;
+ }
+
+ uint64_t* panel_id = reinterpret_cast<uint64_t *>(info->prop_ptr);
+ // Read as-is / big endian. Driver has supplied the value in this manner.
+ uint8_t *data = (uint8_t*)(blob->data);
+ for (size_t i = 0; i < blob->length; i++) {
+ *panel_id = (*panel_id << 8) | *data;
+ data++;
+ }
+ info->prop_size = sizeof(uint64_t);
+
+ drmModeFreePropertyBlob(blob);
+}
+
+void DRMPanelFeatureMgr::ParseDemuraResources(drmModePropertyRes *prop, uint64_t value,
+ DRMPanelFeatureInfo *info) {
+ // Values come as bit indices, not fully-realized values, for DRM_MODE_PROP_BITMASK
+ for (auto i = 0; i < prop->count_enums; i++) {
+ std::string enum_name(prop->enums[i].name);
+ if (enum_name == "demura_dma1_rect0") {
+ DEMURA_DMA1RECT0 = (1 << prop->enums[i].value);
+ } else if (enum_name == "demura_dma1_rect1") {
+ DEMURA_DMA1RECT1 = (1 << prop->enums[i].value);
+ } else if (enum_name == "demura_dma3_rect0") {
+ DEMURA_DMA3RECT0 = (1 << prop->enums[i].value);
+ } else if (enum_name == "demura_dma3_rect1") {
+ DEMURA_DMA3RECT1 = (1 << prop->enums[i].value);
+ }
+ }
+
+ FetchResourceList *frl = reinterpret_cast<FetchResourceList*>(info->prop_ptr);
+ if (value & DEMURA_DMA1RECT0) {
+ frl->push_back(std::make_tuple("DMA", 1, 0));
+ }
+ if (value & DEMURA_DMA1RECT1) {
+ frl->push_back(std::make_tuple("DMA", 1, 1));
+ }
+ if (value & DEMURA_DMA3RECT0) {
+ frl->push_back(std::make_tuple("DMA", 3, 0));
+ }
+ if (value & DEMURA_DMA3RECT1) {
+ frl->push_back(std::make_tuple("DMA", 3, 1));
+ }
+
+ info->prop_size += frl->size();
+}
+
void DRMPanelFeatureMgr::ParseDsppCapabilities(uint32_t blob_id, std::vector<int> *values,
- uint32_t *size, const std::string str) {
+ uint32_t *size, const std::string str) {
drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(dev_fd_, blob_id);
if (!blob) {
DRM_LOGW("Unable to find blob for id %d", blob_id);
@@ -289,17 +365,21 @@
ParseCapabilities(props->prop_values[j],
reinterpret_cast<char *> (info->prop_ptr), info->prop_size, "spr_pack_type");
} else if (info->prop_id == kDRMPanelFeatureDsppIndex) {
- ParseCapabilities(props->prop_values[j],
- reinterpret_cast<char *> (info->prop_ptr), info->prop_size, "dspp_index");
+ ParseDsppCapabilities(props->prop_values[j],
+ reinterpret_cast<std::vector<int> *>(info->prop_ptr), &(info->prop_size), "dspp");
+ } else if (info->prop_id == kDRMPanelFeatureDemuraResources) {
+ ParseDemuraResources(property, props->prop_values[j], info);
+ } else if (info->prop_id == kDRMPanelFeaturePanelId) {
+ ParsePanelId(props->prop_values[j], info);
} else if (info->prop_id == kDRMPanelFeatureDsppSPRInfo) {
- ParseCapabilities(props->prop_values[j],
- reinterpret_cast<char *> (info->prop_ptr), info->prop_size, "spr");
+ ParseDsppCapabilities(props->prop_values[j],
+ reinterpret_cast<std::vector<int> *>(info->prop_ptr), &(info->prop_size), "spr");
} else if (info->prop_id == kDRMPanelFeatureDsppDemuraInfo) {
- ParseCapabilities(props->prop_values[j],
- reinterpret_cast<char *> (info->prop_ptr), info->prop_size, "demura");
+ ParseDsppCapabilities(props->prop_values[j],
+ reinterpret_cast<std::vector<int> *>(info->prop_ptr), &(info->prop_size), "demura");
} else if (info->prop_id == kDRMPanelFeatureDsppRCInfo) {
ParseDsppCapabilities(props->prop_values[j],
- reinterpret_cast<std::vector<int> *> (info->prop_ptr), &(info->prop_size), "rc");
+ reinterpret_cast<std::vector<int> *>(info->prop_ptr), &(info->prop_size), "rc");
} else if (drm_prop_type_map_[info->prop_id] == DRMPropType::kPropBlob) {
drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(dev_fd_, props->prop_values[j]);
if (!blob || !blob->data || !blob->length) {
@@ -334,74 +414,123 @@
dirty_features_[info.prop_id].second = info;
}
-void DRMPanelFeatureMgr::CommitPanelFeatures(drmModeAtomicReq *req, const DRMDisplayToken &tok) {
- int ret = 0;
-
+void DRMPanelFeatureMgr::CommitPanelFeatures(drmModeAtomicReq *req, const DRMDisplayToken &token) {
lock_guard<mutex> lock(lock_);
for (auto it = dirty_features_.begin(); it != dirty_features_.end(); it++) {
DRMPanelFeatureInfo &info = it->second;
if (!it->first)
- continue;
-
- if (info.prop_id >= kDRMPanelFeatureMax) {
- DRM_LOGE("invalid property info to set id %d value ptr %" PRIu64 , info.prop_id, info.prop_ptr);
continue;
- }
- // Commit only features meant for the given DisplayToken
- if (tok.crtc_id != info.obj_id && tok.conn_id != info.obj_id) {
- continue;
- }
-
- uint32_t prop_id = prop_mgr_.GetPropertyId(drm_property_map_[info.prop_id]);
- uint64_t value = 0;
-
- if (DRMPropType::kPropBlob == drm_prop_type_map_[info.prop_id]) {
- uint32_t blob_id = 0;
- if (!info.prop_ptr) {
- // Reset the feature.
- ret = drmModeAtomicAddProperty(req, info.obj_id, prop_id, 0);
- if (ret < 0) {
- DRM_LOGE("failed to add property ret:%d, obj_id:%d prop_id:%u value:%" PRIu64,
- ret, info.obj_id, prop_id, value);
- return;
- }
- continue;
- }
-
- ret = drmModeCreatePropertyBlob(dev_fd_, reinterpret_cast<void *> (info.prop_ptr),
- info.prop_size, &blob_id);
- if (ret || blob_id == 0) {
- DRM_LOGE("failed to create blob ret %d, id = %d prop_ptr:%" PRIu64 " prop_sz:%d",
- ret, blob_id, info.prop_ptr, info.prop_size);
- return;
- }
-
- if (drm_prop_blob_ids_map_[info.prop_id]) {
- ret = drmModeDestroyPropertyBlob(dev_fd_, drm_prop_blob_ids_map_[info.prop_id]);
- if (ret) {
- DRM_LOGE("failed to destroy blob for feature %d, ret = %d", info.prop_id, ret);
- return;
- }
- }
- drm_prop_blob_ids_map_[info.prop_id] = blob_id;
-
- value = blob_id;
- } else if (info.prop_size == sizeof(uint64_t)) {
- value = (reinterpret_cast<uint64_t *> (info.prop_ptr))[0];
- } else {
- DRM_LOGE("Unsupported property type id = %d size:%d", info.prop_id, info.prop_size);
- }
-
- ret = drmModeAtomicAddProperty(req, info.obj_id, prop_id, value);
- if (ret < 0) {
- DRM_LOGE("failed to add property ret:%d, obj_id:%d prop_id:%x value:%" PRIu64,
- ret, info.obj_id, prop_id, value);
- }
+ ApplyDirtyFeature(req, token, info);
*it = {};
}
}
-} // namespace sde_drm
+void DRMPanelFeatureMgr::NullCommitPanelFeatures(drmModeAtomicReq *req,
+ const DRMDisplayToken &token) {
+ lock_guard<mutex> lock(lock_);
+ for (auto it = dirty_features_.begin(); it != dirty_features_.end(); it++) {
+ DRMPanelFeatureInfo &info = it->second;
+ auto entry_iter = apply_in_null_commit_.find(info.obj_id);
+ if (entry_iter == apply_in_null_commit_.end())
+ continue;
+ if (entry_iter->second != info.prop_id)
+ continue;
+
+ if (!it->first) {
+ DLOGW("Prop %u is already committed via draw cycle", info.prop_id);
+ apply_in_null_commit_.erase(info.obj_id);
+ continue;
+ }
+
+ ApplyDirtyFeature(req, token, info);
+ apply_in_null_commit_.erase(info.obj_id);
+ *it = {};
+ }
+}
+
+void DRMPanelFeatureMgr::MarkForNullCommit(const DRMDisplayToken &token, const DRMPanelFeatureID &id) {
+ DRMPanelFeatureInfo &info = feature_info_tbl_[id];
+ uint32_t obj_id = 0;
+ switch (info.obj_type) {
+ case DRM_MODE_OBJECT_CRTC:
+ obj_id = token.crtc_id;
+ break;
+ case DRM_MODE_OBJECT_CONNECTOR:
+ obj_id = token.conn_id;
+ break;
+ default:
+ return;
+ }
+ apply_in_null_commit_[obj_id] = id;
+ DLOGI("Marked %u for null commit", id);
+}
+
+void DRMPanelFeatureMgr::ApplyDirtyFeature(drmModeAtomicReq *req, const DRMDisplayToken &token,
+ DRMPanelFeatureInfo &info) {
+ int ret = 0;
+ if (info.prop_id >= kDRMPanelFeatureMax) {
+ DRM_LOGE("invalid property info to set id %d value ptr %" PRIu64, info.prop_id, info.prop_ptr);
+ return;
+ }
+
+ // Commit only features meant for the given DisplayToken
+ if (token.crtc_id != info.obj_id && token.conn_id != info.obj_id) {
+ return;
+ }
+
+ uint32_t prop_id = prop_mgr_.GetPropertyId(drm_property_map_[info.prop_id]);
+ if (!prop_id) {
+ DRM_LOGE("prop_id is 0 for panel feature-id %u", info.prop_id);
+ return;
+ }
+ uint64_t value = 0;
+
+ if (DRMPropType::kPropBlob == drm_prop_type_map_[info.prop_id]) {
+ uint32_t blob_id = 0;
+ if (!info.prop_ptr) {
+ // Reset the feature.
+ ret = drmModeAtomicAddProperty(req, info.obj_id, prop_id, 0);
+ if (ret < 0) {
+ DRM_LOGE("failed to add property ret:%d, obj_id:%d prop_id:%u value:%" PRIu64,
+ ret, info.obj_id, prop_id, value);
+ }
+ DLOGI("Commited panel feature [disabled]: %u-%u", info.prop_id, prop_id);
+ return;
+ }
+
+ ret = drmModeCreatePropertyBlob(dev_fd_, reinterpret_cast<void *> (info.prop_ptr),
+ info.prop_size, &blob_id);
+ if (ret || blob_id == 0) {
+ DRM_LOGE("failed to create blob ret %d, id = %d prop_ptr:%" PRIu64 " prop_sz:%d",
+ ret, blob_id, info.prop_ptr, info.prop_size);
+ return;
+ }
+
+ if (drm_prop_blob_ids_map_[info.prop_id]) {
+ ret = drmModeDestroyPropertyBlob(dev_fd_, drm_prop_blob_ids_map_[info.prop_id]);
+ if (ret) {
+ DRM_LOGE("failed to destroy blob for feature %d, ret = %d", info.prop_id, ret);
+ return;
+ }
+ }
+ drm_prop_blob_ids_map_[info.prop_id] = blob_id;
+
+ value = blob_id;
+ } else if (info.prop_size == sizeof(uint64_t)) {
+ value = (reinterpret_cast<uint64_t *> (info.prop_ptr))[0];
+ } else {
+ DRM_LOGE("Unsupported property type id = %d size:%d", info.prop_id, info.prop_size);
+ }
+
+ ret = drmModeAtomicAddProperty(req, info.obj_id, prop_id, value);
+ if (ret < 0) {
+ DRM_LOGE("failed to add property ret:%d, obj_id:%d prop_id:%x value:%" PRIu64,
+ ret, info.obj_id, prop_id, value);
+ }
+ DLOGI("Commited panel feature [enabled]: %u-%u", info.prop_id, prop_id);
+}
+
+} // namespace sde_drm
diff --git a/sde-drm/drm_panel_feature_mgr.h b/sde-drm/drm_panel_feature_mgr.h
index afc314b..14bfdcc 100644
--- a/sde-drm/drm_panel_feature_mgr.h
+++ b/sde-drm/drm_panel_feature_mgr.h
@@ -46,13 +46,19 @@
void Deinit();
void GetPanelFeatureInfo(DRMPanelFeatureInfo *info);
void CachePanelFeature(const DRMPanelFeatureInfo &info);
- void CommitPanelFeatures(drmModeAtomicReq *req, const DRMDisplayToken &tok);
+ void CommitPanelFeatures(drmModeAtomicReq *req, const DRMDisplayToken &token);
+ void NullCommitPanelFeatures(drmModeAtomicReq *req, const DRMDisplayToken &token);
+ void MarkForNullCommit(const DRMDisplayToken &token, const DRMPanelFeatureID &id);
private:
int InitObjectProps(int obj_id, int obj_type);
void ParseCapabilities(uint32_t blob_id, char* value, uint32_t max_len, const std::string str);
void ParseDsppCapabilities(uint32_t blob_id, std::vector<int> *values, uint32_t *size,
const std::string str);
+ void ParsePanelId(uint32_t blob_id, DRMPanelFeatureInfo *info);
+ void ParseDemuraResources(drmModePropertyRes *prop, uint64_t value, DRMPanelFeatureInfo *info);
+ void ApplyDirtyFeature(drmModeAtomicReq *req, const DRMDisplayToken &token,
+ DRMPanelFeatureInfo &info);
std::mutex lock_;
int dev_fd_ = -1;
@@ -64,6 +70,7 @@
std::map<DRMPanelFeatureID, DRMPropType> drm_prop_type_map_ {};
std::map<DRMPanelFeatureID, uint32_t> drm_prop_blob_ids_map_ {};
std::array<DRMPanelFeatureInfo, kDRMPanelFeatureMax> feature_info_tbl_ {};
+ std::map<uint32_t /* obj_id */, DRMPanelFeatureID> apply_in_null_commit_ {};
};
} // namespace sde_drm
diff --git a/sde-drm/drm_panel_feature_mgr_intf.h b/sde-drm/drm_panel_feature_mgr_intf.h
index bb5106f..8731602 100644
--- a/sde-drm/drm_panel_feature_mgr_intf.h
+++ b/sde-drm/drm_panel_feature_mgr_intf.h
@@ -41,8 +41,9 @@
virtual void Deinit() = 0;
virtual void GetPanelFeatureInfo(DRMPanelFeatureInfo *info) = 0;
virtual void CachePanelFeature(const DRMPanelFeatureInfo &info) = 0;
- virtual void CommitPanelFeatures(drmModeAtomicReq *req,
- const DRMDisplayToken &tok) = 0;
+ virtual void CommitPanelFeatures(drmModeAtomicReq *req, const DRMDisplayToken &token) = 0;
+ virtual void NullCommitPanelFeatures(drmModeAtomicReq *req, const DRMDisplayToken &token) = 0;
+ virtual void MarkForNullCommit(const DRMDisplayToken &token, const DRMPanelFeatureID &id) = 0;
};
extern "C" DRMPanelFeatureMgrIntf *GetPanelFeatureManagerIntf();
diff --git a/sde-drm/drm_plane.cpp b/sde-drm/drm_plane.cpp
index b46a1df..43a21af 100644
--- a/sde-drm/drm_plane.cpp
+++ b/sde-drm/drm_plane.cpp
@@ -56,6 +56,7 @@
using std::string;
using std::map;
using std::pair;
+using std::make_pair;
using std::vector;
using std::unique_ptr;
using std::tuple;
@@ -139,6 +140,13 @@
static uint8_t MULTIRECT_PARALLEL = 1;
static uint8_t MULTIRECT_SERIAL = 2;
+// Blend Type
+static uint8_t UNDEFINED = 0;
+static uint8_t OPAQUE = 1;
+static uint8_t PREMULTIPLIED = 2;
+static uint8_t COVERAGE = 3;
+static uint8_t SKIP_BLENDING = 4;
+
static void SetRect(DRMRect &source, drm_clip_rect *target) {
target->x1 = uint16_t(source.left);
target->y1 = uint16_t(source.top);
@@ -226,6 +234,27 @@
}
}
+static void PopulateBlendType(drmModePropertyRes *prop) {
+ static bool blend_type_populated = false;
+ if (!blend_type_populated) {
+ for (auto i = 0; i < prop->count_enums; i++) {
+ string enum_name(prop->enums[i].name);
+ if (enum_name == "not_defined") {
+ UNDEFINED = prop->enums[i].value;
+ } else if (enum_name == "opaque") {
+ OPAQUE = prop->enums[i].value;
+ } else if (enum_name == "premultiplied") {
+ PREMULTIPLIED = prop->enums[i].value;
+ } else if (enum_name == "coverage") {
+ COVERAGE = prop->enums[i].value;
+ } else if (enum_name == "skip_blending") {
+ SKIP_BLENDING = prop->enums[i].value;
+ }
+ }
+ blend_type_populated = true;
+ }
+}
+
static const char *GetColorLutString(DRMTonemapLutType lut_type) {
switch (lut_type) {
case DRMTonemapLutType::DMA_1D_IGC:
@@ -416,6 +445,52 @@
}
}
+void DRMPlaneManager::MapPlaneToCrtc(std::map<uint32_t, uint32_t> *plane_to_crtc) {
+ lock_guard<mutex> lock(lock_);
+
+ if (!plane_to_crtc) {
+ DLOGE("Map is NULL! Not expected.");
+ return;
+ }
+
+ plane_to_crtc->clear();
+
+ for (auto &plane : plane_pool_) {
+ uint32_t crtc_id = 0;
+ plane.second->GetCrtc(&crtc_id);
+ if (crtc_id)
+ plane_to_crtc->insert(make_pair(plane.first, crtc_id));
+ }
+}
+
+void DRMPlaneManager::GetPlaneIdsFromDescriptions(FetchResourceList &descriptions,
+ std::vector<uint32_t> *plane_ids) {
+ lock_guard<mutex> lock(lock_);
+ for (auto &desc : descriptions) {
+ const string &type_str = std::get<0>(desc);
+ DRMPlaneType type = DRMPlaneType::MAX;
+ if (type_str == "DMA") {
+ type = DRMPlaneType::DMA;
+ } else {
+ continue;
+ }
+ const int32_t &idx = std::get<1>(desc);
+ const int8_t &rect = std::get<2>(desc);
+ for (auto &p : plane_pool_) {
+ DRMPlaneType plane_type;
+ p.second->GetType(&plane_type);
+ uint8_t plane_idx;
+ p.second->GetIndex(&plane_idx);
+ uint8_t plane_rect;
+ p.second->GetRect(&plane_rect);
+ if (plane_idx == idx && plane_rect == rect && plane_type == type) {
+ plane_ids->emplace_back(p.first);
+ break;
+ }
+ }
+ }
+}
+
// ==============================================================================================//
#undef __CLASS__
@@ -483,6 +558,8 @@
string true_inline_dwnscale_rt_numerator = "true_inline_dwnscale_rt_numerator=";
string true_inline_dwnscale_rt_denominator = "true_inline_dwnscale_rt_denominator=";
string true_inline_max_height = "true_inline_max_height=";
+ string pipe_idx = "pipe_idx=";
+ string demura_block = "demura_block=";
while (std::getline(stream, line)) {
if (line.find(inline_rot_pixel_formats) != string::npos) {
@@ -526,7 +603,12 @@
true_inline_dwnscale_rt_denominator.length()));
} else if (line.find(true_inline_max_height) != string::npos) {
info->max_rotation_linewidth = std::stoi(line.erase(0, true_inline_max_height.length()));
+ } else if (line.find(pipe_idx) != string::npos) {
+ info->pipe_idx = std::stoi(line.erase(0, pipe_idx.length()));
+ } else if (line.find(demura_block) != string::npos) {
+ info->demura_block_capability = std::stoi(line.erase(0, demura_block.length()));
}
+
}
// TODO(user): Get max_scaler_linewidth and non_scaler_linewidth from driver
@@ -575,6 +657,8 @@
} else if (prop_enum == DRMProperty::MULTIRECT_MODE) {
PopulateMultiRectModes(info);
plane_type_info_.multirect_prop_present = true;
+ } else if (prop_enum == DRMProperty::BLEND_OP) {
+ PopulateBlendType(info);
}
prop_mgr_.SetPropertyId(prop_enum, info->prop_id);
@@ -866,10 +950,32 @@
} break;
case DRMOps::PLANE_SET_BLEND_TYPE: {
- uint32_t blending = va_arg(args, uint32_t);
+ DRMBlendType blending = va_arg(args, DRMBlendType);
+ uint32_t blend_type = UNDEFINED;
+ switch (blending) {
+ case DRMBlendType::OPAQUE:
+ blend_type = OPAQUE;
+ break;
+ case DRMBlendType::PREMULTIPLIED:
+ blend_type = PREMULTIPLIED;
+ break;
+ case DRMBlendType::COVERAGE:
+ blend_type = COVERAGE;
+ break;
+ case DRMBlendType::SKIP_BLENDING:
+ blend_type = SKIP_BLENDING;
+ break;
+ case DRMBlendType::UNDEFINED:
+ blend_type = UNDEFINED;
+ break;
+ default:
+ DRM_LOGE("Invalid blend type %d to set on plane %d", blending, obj_id);
+ break;
+ }
+
prop_id = prop_mgr_.GetPropertyId(DRMProperty::BLEND_OP);
- AddProperty(req, obj_id, prop_id, blending, true /* cache */, tmp_prop_val_map_);
- DRM_LOGV("Plane %d: Setting blending %d", obj_id, blending);
+ AddProperty(req, obj_id, prop_id, blend_type, true /* cache */, tmp_prop_val_map_);
+ DRM_LOGV("Plane %d: Setting blending %d", obj_id, blend_type);
} break;
case DRMOps::PLANE_SET_H_DECIMATION: {
diff --git a/sde-drm/drm_plane.h b/sde-drm/drm_plane.h
index c827489..18d1e41 100644
--- a/sde-drm/drm_plane.h
+++ b/sde-drm/drm_plane.h
@@ -64,6 +64,7 @@
void GetPriority(uint32_t *priority) { *priority = priority_; }
void GetAssignedCrtc(uint32_t *crtc_id) { *crtc_id = assigned_crtc_id_; }
void GetRequestedCrtc(uint32_t *crtc_id) { *crtc_id = requested_crtc_id_; }
+ void GetCrtc(uint32_t *crtc_id) { *crtc_id = drm_plane_->crtc_id; }
void SetAssignedCrtc(uint32_t crtc_id) { assigned_crtc_id_ = crtc_id; }
void SetRequestedCrtc(uint32_t crtc_id) { requested_crtc_id_ = crtc_id; }
bool SetScalerConfig(drmModeAtomicReq *req, uint64_t handle);
@@ -85,6 +86,8 @@
void ResetColorLUTState(DRMTonemapLutType lut_type, bool is_commit, drmModeAtomicReq *req);
void ResetColorLUT(DRMPPFeatureID id, drmModeAtomicReq *req);
void ResetCache(drmModeAtomicReq *req);
+ void GetIndex(uint8_t *index) { *index = plane_type_info_.pipe_idx; }
+ void GetRect(uint8_t *rect) { *rect = plane_type_info_.master_plane_id ? 1 : 0; }
private:
typedef std::map<DRMProperty, std::tuple<uint64_t, drmModePropertyRes *>> PropertyMap;
@@ -135,6 +138,9 @@
void PostValidate(uint32_t crtc_id, bool success);
void PostCommit(uint32_t crtc_id, bool success);
void ResetCache(drmModeAtomicReq *req, uint32_t crtc_id);
+ void MapPlaneToCrtc(std::map<uint32_t, uint32_t> *plane_to_crtc);
+ void GetPlaneIdsFromDescriptions(FetchResourceList &descriptions,
+ std::vector<uint32_t> *plane_ids);
private:
void Perform(DRMOps code, drmModeAtomicReq *req, uint32_t obj_id, ...);
diff --git a/sde-drm/drm_property.cpp b/sde-drm/drm_property.cpp
index 8edb0d0..a0af621 100644
--- a/sde-drm/drm_property.cpp
+++ b/sde-drm/drm_property.cpp
@@ -169,6 +169,9 @@
if (name == "SDE_SPR_INIT_CFG_V1") { return DRMProperty::SPR_INIT_CFG_V1; }
if (name == "SDE_DSPP_RC_MASK_V1") { return DRMProperty::DSPP_RC_MASK_V1; }
if (name == "panel_mode") { return DRMProperty::PANEL_MODE; }
+ if (name == "SDE_DEMURA_INIT_CFG_V1") { return DRMProperty::DEMURA_INIT_CFG_V1; }
+ if (name == "DEMURA_PANEL_ID") { return DRMProperty::DEMURA_PANEL_ID; }
+ if (name == "SDE_DEMURA_BOOT_PLANE_V1") { return DRMProperty::DEMURA_BOOT_PLANE_V1; }
return DRMProperty::INVALID;
}
diff --git a/sde-drm/drm_property.h b/sde-drm/drm_property.h
index 67398eb..2e3fd32 100644
--- a/sde-drm/drm_property.h
+++ b/sde-drm/drm_property.h
@@ -174,6 +174,9 @@
SPR_INIT_CFG_V1,
DSPP_RC_MASK_V1,
PANEL_MODE,
+ DEMURA_INIT_CFG_V1,
+ DEMURA_PANEL_ID,
+ DEMURA_BOOT_PLANE_V1,
// Insert above
MAX
diff --git a/sdm/include/core/core_interface.h b/sdm/include/core/core_interface.h
index 2ec7b32..bd03592 100644
--- a/sdm/include/core/core_interface.h
+++ b/sdm/include/core/core_interface.h
@@ -37,6 +37,7 @@
#ifndef __CORE_INTERFACE_H__
#define __CORE_INTERFACE_H__
+#include <core/ipc_interface.h>
#include <stdint.h>
#include <map>
#include <vector>
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index afee291..4798183 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -1008,6 +1008,12 @@
*/
virtual DisplayError NotifyDisplayCalibrationMode(bool in_calibration) = 0;
+ /*! @brief Method to check if display has Demura requirement
+
+ @return \link bool \endlink
+ */
+ virtual bool HasDemura() = 0;
+
protected:
virtual ~DisplayInterface() { }
};
@@ -1015,4 +1021,3 @@
} // namespace sdm
#endif // __DISPLAY_INTERFACE_H__
-
diff --git a/sdm/include/core/ipc_interface.h b/sdm/include/core/ipc_interface.h
index d1b979f..4374fd6 100644
--- a/sdm/include/core/ipc_interface.h
+++ b/sdm/include/core/ipc_interface.h
@@ -37,6 +37,7 @@
};
enum IPCOps {
+ kIpcOpsFilePath,
kIPCOpMax
};
diff --git a/sdm/include/core/layer_buffer.h b/sdm/include/core/layer_buffer.h
index 6fb12d5..d688c48 100644
--- a/sdm/include/core/layer_buffer.h
+++ b/sdm/include/core/layer_buffer.h
@@ -217,6 +217,9 @@
uint32_t game : 1; //!< This flag shall be set by the client to indicate that the
//!< the content is game.
+
+ uint32_t demura : 1; //!< This flag shall be set to indicate that the
+ //!< content is demura correction data
};
uint32_t flags = 0; //!< For initialization purpose only.
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index 29e924b..c55eac1 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.h
@@ -40,6 +40,8 @@
#include <unordered_map>
#include <memory>
#include <bitset>
+#include <string>
+#include <tuple>
#include "layer_buffer.h"
#include "sdm_types.h"
@@ -62,6 +64,9 @@
kBlendingCoverage, //!< Pixel color is expressed using straight alpha in color tuples. If
//!< plane alpha is less than 0xff, apply modulation as well.
//!< pixel.rgb = src.rgb x src.a + dest.rgb x (1 - src.a)
+
+ kBlendingSkip, //!< Used only to denote layer should not be staged for blending, but
+ //!< still requires fetch resources for a different HW block
};
/*! @brief This enum represents display layer composition types.
@@ -84,6 +89,8 @@
kCompositionStitch, //!< This layer will be drawn onto the target buffer by GPU. No blend
//!< required.
+ kCompositionDemura, //!< This layer will be applied by Demura HW. No blend required.
+
kCompositionSDE, //!< This layer will be composed by SDE. It must not be composed by
//!< GPU or Blit.
@@ -195,6 +202,9 @@
uint32_t sde_preferred : 1; //! This flag shall be set by client to indicate that this layer
//! will be composed by display device, layer with this flag
//! will have highest priority. To be used by OEMs only.
+
+ uint32_t is_demura : 1; //!< This flag shall be set to indicate that this layer
+ //!< is a demura correction layer
};
uint32_t flags = 0; //!< For initialization purpose only.
@@ -290,6 +300,10 @@
uint32_t layer_id_support : 1; //! This flag shall be set by Client to indicate that it has
//! set the unique Layer Id on each SDM Layer, which will
//! persist across draw cycles until the layer gets removed.
+
+ uint32_t stitch_present : 1; //!< This flag shall be set to true to indicate stack has stitch
+
+ uint32_t demura_present : 1; //!< This flag shall be set to true to indicate stack has demura
};
uint32_t flags = 0; //!< For initialization purpose only.
@@ -487,4 +501,3 @@
} // namespace sdm
#endif // __LAYER_STACK_H__
-
diff --git a/sdm/include/private/demura_intf.h b/sdm/include/private/demura_intf.h
new file mode 100644
index 0000000..ace7484
--- /dev/null
+++ b/sdm/include/private/demura_intf.h
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 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.
+*/
+
+#ifndef __DEMURA_INTF_H__
+#define __DEMURA_INTF_H__
+
+#include <core/buffer_allocator.h>
+#include <core/buffer_sync_handler.h>
+#include <core/ipc_interface.h>
+
+#include <private/generic_intf.h>
+#include <private/generic_payload.h>
+
+#include <string>
+#include <vector>
+#include <bitset>
+
+#define RESOURCE_BITSET 8
+
+namespace sdm {
+
+struct DemuraInputConfig {
+ bool secure_session = false;
+ std::string brightness_path;
+ std::bitset<RESOURCE_BITSET> resources;
+};
+
+// Demura specific param as strings
+const std::string kDemuraFeatureParamActive = "Active";
+const std::string kDemuraFeatureParamCorrectionBuffer = "CorrectionBuffer";
+
+using DemuraIntf = GenericIntf<const std::string&, const std::string&, GenericPayload>;
+} // namespace sdm
+
+#endif // __DEMURA_INTF_H__
diff --git a/sdm/include/private/demura_parser_manager_intf.h b/sdm/include/private/demura_parser_manager_intf.h
new file mode 100644
index 0000000..f6c0bdd
--- /dev/null
+++ b/sdm/include/private/demura_parser_manager_intf.h
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 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.
+*/
+
+#ifndef __DEMURA_PARSER_MANAGER_INTF_H___
+#define __DEMURA_PARSER_MANAGER_INTF_H___
+
+#include <private/generic_payload.h>
+#include <private/generic_intf.h>
+
+namespace sdm {
+
+enum DemuraParserManagerParams {
+ kDemuraParserManagerParamPanelIds,
+ kDemuraParserManagerParamMax,
+};
+
+enum DemuraParserManagerOps {
+ kDemuraParserManagerOpsParser,
+ kDemuraParserManagerOpsMax,
+};
+
+using DemuraParserManagerIntf =
+ GenericIntf<DemuraParserManagerParams, DemuraParserManagerOps, GenericPayload>;
+
+} // namespace sdm
+
+#endif // __DEMURA_PARSER_MANAGER_INTF_H__
diff --git a/sdm/include/private/generic_payload.h b/sdm/include/private/generic_payload.h
index 716f13b..59f14e6 100644
--- a/sdm/include/private/generic_payload.h
+++ b/sdm/include/private/generic_payload.h
@@ -43,7 +43,7 @@
struct GenericPayload {
public:
GenericPayload():
- type_size(0), payload(nullptr), array_size(0) {}
+ type_size(0), payload(nullptr), array_size(0), release(nullptr) {}
GenericPayload(const GenericPayload &in) {
type_size = 0;
@@ -66,7 +66,7 @@
type_size = sizeof(A);
array_size = in.array_size;
- if (payload != nullptr) {
+ if (payload != nullptr && release != nullptr) {
release();
}
A* p2 = nullptr;
@@ -136,6 +136,10 @@
return -EINVAL;
}
+ if (!sz) {
+ return -EINVAL;
+ }
+
p = reinterpret_cast<A *>(payload);
*sz = 0;
if (p == nullptr && copy_constructed) {
@@ -153,7 +157,7 @@
}
void DeletePayload() {
- if (payload != nullptr) {
+ if (payload != nullptr && release != nullptr) {
release();
}
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 2f2cb5c..c793d0d 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -38,6 +38,7 @@
#include <string>
#include <vector>
#include <utility>
+#include <tuple>
namespace sdm {
using std::string;
@@ -235,6 +236,12 @@
uint64_t pipe_bw_limit[kBwModeMax] = { 0 };
};
+enum SplashType {
+ kSplashNone,
+ kSplashLayer,
+ kSplashDemura,
+};
+
struct HWPipeCaps {
PipeType type = kPipeTypeUnused;
uint32_t id = 0;
@@ -244,6 +251,10 @@
uint32_t dgm_csc_version = 0;
std::map<HWToneMapLut, uint32_t> tm_lut_version_map = {};
bool block_sec_ui = false;
+ int32_t cont_splash_disp_id = -1;
+ SplashType splash_type = kSplashNone;
+ int32_t pipe_idx = -1;
+ int32_t demura_block_capability = -1;
};
struct HWRotatorInfo {
@@ -361,6 +372,10 @@
bool has_micro_idle = false;
uint32_t ubwc_version = 1;
uint32_t rc_total_mem_size = 0;
+ std::map<uint32_t, uint32_t> plane_to_connector = {};
+ std::vector<uint32_t> initial_demura_planes = {};
+ uint32_t demura_count = 0;
+ uint32_t dspp_count = 0;
};
struct HWSplitInfo {
@@ -701,6 +716,9 @@
std::vector<LayerRect> excl_rects = {}; // list of exclusion rects
};
+typedef std::tuple<std::string, int32_t, int8_t> FetchResource;
+typedef std::vector<FetchResource> FetchResourceList;
+
struct HWQosData {
bool valid = false;
uint64_t core_ab_bps = 0;
@@ -722,8 +740,9 @@
struct HWLayersInfo {
uint32_t app_layer_count = 0; // Total number of app layers. Must not be 0.
- uint32_t gpu_target_index = 0; // GPU target layer index. 0 if not present.
- uint32_t stitch_target_index = 0; // Blit target layer index. 0 if not present.
+ int32_t gpu_target_index = -1; // GPU target layer index. -1 if not present.
+ int32_t stitch_target_index = -1; // Blit target layer index. -1 if not present.
+ int32_t demura_target_index = -1; // Demura target layer index. -1 if not present.
std::vector<ColorPrimaries> wide_color_primaries = {}; // list of wide color primaries
std::vector<Layer> hw_layers = {}; // Layers which need to be programmed on the HW
@@ -762,6 +781,8 @@
LayerBuffer *output_buffer = NULL; //!< Pointer to the buffer where composed buffer would be
//!< rendered for virtual displays.
//!< NOTE: This field applies to a virtual display only.
+ bool stitch_present = false; // Indicates there is stitch layer or not
+ bool demura_present = false; // Indicates there is demura layer or not
};
struct DispLayerStack {
@@ -847,4 +868,3 @@
} // namespace sdm
#endif // __HW_INFO_TYPES_H__
-
diff --git a/sdm/include/private/panel_feature_factory_intf.h b/sdm/include/private/panel_feature_factory_intf.h
index afcc24a..9edeee8 100644
--- a/sdm/include/private/panel_feature_factory_intf.h
+++ b/sdm/include/private/panel_feature_factory_intf.h
@@ -36,6 +36,8 @@
#include "spr_intf.h"
#include "panel_feature_property_intf.h"
#include "rc_intf.h"
+#include "demura_intf.h"
+#include "demura_parser_manager_intf.h"
namespace sdm {
@@ -48,15 +50,19 @@
class PanelFeatureFactoryIntf {
public:
virtual ~PanelFeatureFactoryIntf() {}
-
virtual std::shared_ptr<SPRIntf>
CreateSPRIntf(const SPRInputConfig &input_cfg, PanelFeaturePropertyIntf *prop_intf) = 0;
virtual std::unique_ptr<RCIntf> CreateRCIntf(const RCInputConfig &input_cfg,
PanelFeaturePropertyIntf *prop_intf) = 0;
+ virtual std::shared_ptr<DemuraParserManagerIntf>
+ CreateDemuraParserManager(std::shared_ptr<IPCIntf> ipc_intf) = 0;
+ virtual std::unique_ptr<DemuraIntf>
+ CreateDemuraIntf(const DemuraInputConfig &input_cfg,
+ PanelFeaturePropertyIntf *prop_intf,
+ BufferAllocator *buffer_allocator,
+ std::shared_ptr<SPRIntf> spr) = 0;
};
-extern "C" PanelFeatureFactoryIntf *GetPanelFeatureFactoryIntf();
-
} // namespace sdm
#endif // __PANEL_FEATURE_FACTORY_INTF_H__
diff --git a/sdm/include/private/panel_feature_property_intf.h b/sdm/include/private/panel_feature_property_intf.h
index 6cb2aed..3d7a870 100644
--- a/sdm/include/private/panel_feature_property_intf.h
+++ b/sdm/include/private/panel_feature_property_intf.h
@@ -31,6 +31,7 @@
#define __PANEL_FEATURE_PROPERTY_INTF_H__
#include <utils/constants.h>
+#include <inttypes.h>
namespace sdm {
@@ -44,7 +45,8 @@
kPanelFeatureSPRPackType,
kPanelFeatureDemuraInitCfg,
kPanelFeatureRCInitCfg,
- kPanelFeaturePropertyIDMax,
+ kPanelFeatureDemuraPanelId,
+ kPanelFeaturePropertyIDMax
};
struct PanelFeaturePropertyInfo {
diff --git a/sdm/include/private/rc_intf.h b/sdm/include/private/rc_intf.h
index 1ddff2d..8da61b9 100644
--- a/sdm/include/private/rc_intf.h
+++ b/sdm/include/private/rc_intf.h
@@ -31,10 +31,11 @@
#define __RC_INTF_H__
#include <core/display_interface.h>
-#include <string>
-#include "generic_intf.h"
-#include "generic_payload.h"
+#include <private/generic_intf.h>
+#include <private/generic_payload.h>
+
+#include <string>
#define SDE_HW_PU_USECASE 0x1000
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index df53ff6..8d3f6f0 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -26,6 +26,7 @@
#define __RESOURCE_INTERFACE_H__
#include <core/display_interface.h>
+#include <map>
#include "hw_info_types.h"
namespace sdm {
@@ -62,12 +63,10 @@
virtual DisplayError PostCommit(Handle display_ctx, DispLayerStack *disp_layer_stack) = 0;
virtual void Purge(Handle display_ctx) = 0;
virtual DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) = 0;
- virtual DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst,
- bool rotate90, BufferLayout layout,
- bool use_rotator_downscale) = 0;
+ virtual DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90,
+ BufferLayout layout, bool use_rotator_downscale) = 0;
virtual DisplayError ValidateAndSetCursorPosition(Handle display_ctx,
- DispLayerStack *disp_layer_stack,
- int x, int y,
+ DispLayerStack *disp_layer_stack, int x, int y,
DisplayConfigVariableInfo *fb_config) = 0;
virtual DisplayError SetMaxBandwidthMode(HWBwModes mode) = 0;
virtual DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
@@ -77,10 +76,15 @@
const shared_ptr<Fence> &sync_handle) = 0;
virtual DisplayError Perform(int cmd, ...) = 0;
virtual bool IsRotatorSupportedFormat(LayerBufferFormat format) = 0;
- virtual ~ResourceInterface() { }
+ virtual DisplayError FreeDemuraFetchResources(Handle display_ctx) = 0;
+ virtual DisplayError GetDemuraFetchResourceCount(
+ std::map<uint32_t, uint8_t> *fetch_resource_cnt) = 0;
+ virtual DisplayError ReserveDemuraFetchResources(const int32_t &display_id,
+ const int8_t &preferred_rect) = 0;
+ virtual DisplayError GetDemuraFetchResources(Handle display_ctx, FetchResourceList *frl) = 0;
+ virtual ~ResourceInterface() {}
};
} // namespace sdm
#endif // __RESOURCE_INTERFACE_H__
-
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index a695604..380823b 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -28,6 +28,7 @@
#include <set>
#include <string>
#include <vector>
+#include <map>
#include "comp_manager.h"
#include "strategy.h"
@@ -156,6 +157,8 @@
max_sde_ext_layers_ = UINT32(Debug::GetExtMaxlayers());
}
+ display_demura_status_[display_id] = false;
+
DLOGV_IF(kTagCompManager, "Registered displays [%s], display %d-%d",
StringDisplayList(registered_displays_).c_str(), display_comp_ctx->display_id,
display_comp_ctx->display_type);
@@ -274,7 +277,12 @@
constraints->safe_mode = true;
}
- uint32_t app_layer_count = UINT32(disp_layer_stack->stack->layers.size()) - 1;
+ uint32_t size_ff = 1; // gpu target layer always present
+ if (disp_layer_stack->info.stitch_present)
+ size_ff++;
+ if (disp_layer_stack->info.demura_present)
+ size_ff++;
+ uint32_t app_layer_count = UINT32(disp_layer_stack->stack->layers.size()) - size_ff;
if (display_comp_ctx->idle_fallback || display_comp_ctx->thermal_fallback_) {
// Handle the idle timeout by falling back
constraints->safe_mode = true;
@@ -706,4 +714,30 @@
return display_comp_ctx->strategy->SwapBuffers();
}
+DisplayError CompManager::FreeDemuraFetchResources(Handle display_ctx) {
+ SCOPE_LOCK(locker_);
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+ return resource_intf_->FreeDemuraFetchResources(display_comp_ctx->display_resource_ctx);
+}
+
+DisplayError CompManager::GetDemuraFetchResourceCount(
+ std::map<uint32_t, uint8_t> *fetch_resource_cnt) {
+ SCOPE_LOCK(locker_);
+ return resource_intf_->GetDemuraFetchResourceCount(fetch_resource_cnt);
+}
+
+DisplayError CompManager::ReserveDemuraFetchResources(const uint32_t &display_id,
+ const int8_t &preferred_rect) {
+ SCOPE_LOCK(locker_);
+ return resource_intf_->ReserveDemuraFetchResources(display_id, preferred_rect);
+}
+
+DisplayError CompManager::GetDemuraFetchResources(Handle display_ctx, FetchResourceList *frl) {
+ SCOPE_LOCK(locker_);
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+ return resource_intf_->GetDemuraFetchResources(display_comp_ctx->display_resource_ctx, frl);
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index e28849b..db20667 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -32,6 +32,7 @@
#include <set>
#include <vector>
#include <string>
+#include <map>
#include "strategy.h"
#include "resource_default.h"
@@ -93,6 +94,19 @@
bool CheckResourceState(Handle display_ctx);
bool IsRotatorSupportedFormat(LayerBufferFormat format);
DisplayError SwapBuffers(Handle display_ctx);
+ DisplayError FreeDemuraFetchResources(Handle display_ctx);
+ DisplayError GetDemuraFetchResourceCount(std::map<uint32_t, uint8_t> *fetch_resource_cnt);
+ DisplayError ReserveDemuraFetchResources(const uint32_t &display_id,
+ const int8_t &preferred_rect);
+ DisplayError GetDemuraFetchResources(Handle display_ctx, FetchResourceList *frl);
+ void SetDemuraStatus(bool status) { demura_enabled_ = status; }
+ bool GetDemuraStatus() { return demura_enabled_; }
+ void SetDemuraStatusForDisplay(const int32_t &display_id, bool status) {
+ display_demura_status_[display_id] = status;
+ }
+ bool GetDemuraStatusForDisplay(const int32_t &display_id) {
+ return display_demura_status_[display_id];
+ }
private:
static const int kMaxThermalLevel = 3;
@@ -135,6 +149,8 @@
uint32_t max_sde_ext_layers_ = 0;
uint32_t max_sde_builtin_layers_ = 2;
DppsControlInterface *dpps_ctrl_intf_ = NULL;
+ bool demura_enabled_ = false;
+ std::map<int32_t /* display_id */, bool> display_demura_status_;
};
} // namespace sdm
diff --git a/sdm/libs/core/core_impl.cpp b/sdm/libs/core/core_impl.cpp
index 4e0c730..e6fb611 100644
--- a/sdm/libs/core/core_impl.cpp
+++ b/sdm/libs/core/core_impl.cpp
@@ -28,6 +28,8 @@
#include <utils/debug.h>
#include <utils/locker.h>
#include <utils/utils.h>
+#include <map>
+#include <vector>
#include "color_manager.h"
#include "core_impl.h"
@@ -102,6 +104,11 @@
DLOGW("Failed getting displays status. Error = %d", error);
}
+ // Must only call after GetDisplaysStatus
+ if (ReserveDemuraResources() != kErrorNone) {
+ comp_mgr_.SetDemuraStatus(false);
+ }
+
signal(SIGPIPE, SIG_IGN);
return kErrorNone;
@@ -262,5 +269,132 @@
return comp_mgr_.IsRotatorSupportedFormat(format);
}
-} // namespace sdm
+DisplayError CoreImpl::ReserveDemuraResources() {
+ DisplayError err = kErrorNone;
+ int enable = 0;
+ Debug::Get()->GetProperty(ENABLE_DEMURA, &enable);
+ if (!enable) {
+ comp_mgr_.SetDemuraStatus(false);
+ DLOGI("Demura is disabled");
+ return kErrorNone;
+ } else {
+ DLOGI("Demura is enabled");
+ comp_mgr_.SetDemuraStatus(true);
+ }
+ std::map<uint32_t, uint8_t> required_demura_fetch_cnt; // display_id, count
+ if ((err = hw_info_intf_->GetRequiredDemuraFetchResourceCount(&required_demura_fetch_cnt)) !=
+ kErrorNone) {
+ DLOGE("Unable to get required demura pipes count");
+ return err;
+ }
+
+ if (!required_demura_fetch_cnt.size()) {
+ DLOGW("Demura is enabled but no panels support it. Disabling..");
+ comp_mgr_.SetDemuraStatus(false);
+ return kErrorNone;
+ }
+
+ int primary_off = 0;
+ int secondary_off = 0;
+ Debug::Get()->GetProperty(DISABLE_DEMURA_PRIMARY, &primary_off);
+ Debug::Get()->GetProperty(DISABLE_DEMURA_SECONDARY, &secondary_off);
+
+ int available_blocks = hw_resource_.demura_count;
+ for (auto r = required_demura_fetch_cnt.begin(); r != required_demura_fetch_cnt.end();) {
+ HWDisplayInfo &info = hw_displays_info_[r->first];
+ DLOGI("[%d] is_primary = %d, p_off = %d, s_off = %d", r->first, info.is_primary, primary_off,
+ secondary_off);
+ if (info.is_primary && primary_off) {
+ r = required_demura_fetch_cnt.erase(r);
+ continue;
+ } else if (!info.is_primary && secondary_off) {
+ r = required_demura_fetch_cnt.erase(r);
+ continue;
+ }
+
+ available_blocks -= r->second;
+ if (available_blocks < 0) {
+ DLOGE("Not enough Demura blocks (%u)", hw_resource_.demura_count);
+ return kErrorResources;
+ }
+ ++r;
+ }
+
+ std::map<uint32_t, uint8_t> fetch_resource_cnt; // display id, count
+ comp_mgr_.GetDemuraFetchResourceCount(&fetch_resource_cnt);
+ for (auto &req : required_demura_fetch_cnt) {
+ uint8_t cnt = 0;
+ auto it = fetch_resource_cnt.find(req.first);
+ if (it != fetch_resource_cnt.end()) {
+ cnt = it->second;
+ }
+ uint8_t req_cnt = req.second;
+ if (req_cnt != cnt && cnt != 0) {
+ DLOGE("Cont Splash only allocated %u pipes for Demura, but %u is needed", cnt, req_cnt);
+ return kErrorDriverData;
+ }
+ if (req_cnt != 0 && cnt == 0) {
+ DLOGI("[%u] Needs Demura resources %u", req.first, req_cnt);
+ // Reserving demura resources requires knowledge of which rect to reserve when the req_cnt
+ // is 1. As the HW pipeline for any display is not known yet, we shall assume primary display
+ // takes 0 and non-primary takes 1. When req_cnt > 1, pass in -1
+ int8_t preferred_rect = -1;
+ if (req_cnt == 1) {
+ HWDisplayInfo &info = hw_displays_info_[req.first];
+ preferred_rect = info.is_primary ? 0 : 1;
+ DLOGI("[%u] is single LM. Requesting Demura rect %d", req.first, preferred_rect);
+ }
+ if ((err = comp_mgr_.ReserveDemuraFetchResources(req.first, preferred_rect)) !=
+ kErrorNone) {
+ DLOGE("Failed to reserve resources error = %d", err);
+ return err;
+ }
+ }
+ }
+
+ GetPanelFeatureFactory get_factory_f_ptr = nullptr;
+ if (!extension_lib_.Sym(GET_PANEL_FEATURE_FACTORY,
+ reinterpret_cast<void **>(&get_factory_f_ptr))) {
+ DLOGE("Unable to load symbols, error = %s", extension_lib_.Error());
+ return kErrorUndefined;
+ }
+
+ panel_feature_factory_intf_ = get_factory_f_ptr();
+ std::shared_ptr<DemuraParserManagerIntf> pm_intf =
+ panel_feature_factory_intf_->CreateDemuraParserManager(ipc_intf_);
+ if (!pm_intf) {
+ DLOGE("Failed to get Parser Manager intf");
+ return kErrorResources;
+ }
+ if (pm_intf->Init() != 0) {
+ DLOGE("Failed to init Parser Manager intf");
+ return kErrorResources;
+ }
+
+ std::vector<uint64_t> *panel_ids;
+ GenericPayload in;
+ int ret = in.CreatePayload<std::vector<uint64_t>>(panel_ids);
+ if (ret) {
+ DLOGE("Failed to create payload for panel ids, error = %d", ret);
+ return kErrorResources;
+ }
+
+ if ((err = hw_info_intf_->GetDemuraPanelIds(panel_ids)) != kErrorNone) {
+ DLOGE("Unable to get demura panel ids");
+ return err;
+ }
+
+ for (auto &id : *panel_ids) {
+ DLOGI("Detected panel_id = %" PRIu64 " (0x%" PRIx64 ")", id, id);
+ }
+
+ if ((ret = pm_intf->SetParameter(kDemuraParserManagerParamPanelIds, in))) {
+ DLOGE("Failed to set the panel ids to the parser manager");
+ return kErrorResources;
+ }
+
+ return err;
+}
+
+} // namespace sdm
diff --git a/sdm/libs/core/core_impl.h b/sdm/libs/core/core_impl.h
index 51eb6bc..794ae58 100644
--- a/sdm/libs/core/core_impl.h
+++ b/sdm/libs/core/core_impl.h
@@ -28,16 +28,24 @@
#include <core/core_interface.h>
#include <private/extension_interface.h>
#include <private/color_interface.h>
+#include <private/panel_feature_factory_intf.h>
#include <utils/locker.h>
#include <utils/sys.h>
+#include <memory>
+#include <vector>
+#include <utility>
+
#include "hw_interface.h"
#include "comp_manager.h"
#define SET_REVISION(major, minor) ((major << 8) | minor)
+#define GET_PANEL_FEATURE_FACTORY "GetPanelFeatureFactoryIntf"
namespace sdm {
+typedef PanelFeatureFactoryIntf* (*GetPanelFeatureFactory)();
+
class CoreImpl : public CoreInterface {
public:
// This class implements display core interface revision 1.0.
@@ -65,6 +73,8 @@
virtual bool IsRotatorSupportedFormat(LayerBufferFormat format);
protected:
+ DisplayError ReserveDemuraResources();
+
Locker locker_;
BufferAllocator *buffer_allocator_ = NULL;
HWResourceInfo hw_resource_;
@@ -74,6 +84,7 @@
ExtensionInterface *extension_intf_ = NULL;
CreateExtensionInterface create_extension_intf_ = NULL;
DestroyExtensionInterface destroy_extension_intf_ = NULL;
+ PanelFeatureFactoryIntf *panel_feature_factory_intf_ = NULL;
SocketHandler *socket_handler_ = NULL;
HWDisplaysInfo hw_displays_info_ = {};
std::shared_ptr<IPCIntf> ipc_intf_ = nullptr;
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index aa66ec3..fa72473 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -172,6 +172,8 @@
hw_recovery_threshold_ = (UINT32(hw_recovery_threshold));
}
+ SetupPanelFeatureFactory();
+
return kErrorNone;
CleanupOnError:
@@ -196,13 +198,58 @@
HWInterface::Destroy(hw_intf_);
if (rc_panel_feature_init_) {
rc_core_->Deinit();
- rc_panel_feature_init_ = false;
+ rc_panel_feature_init_ = false;
}
return kErrorNone;
}
+DisplayError DisplayBase::SetupPanelFeatureFactory() {
+ if (pf_factory_ && prop_intf_) {
+ return kErrorNone;
+ }
+
+ DynLib feature_impl_lib;
+ GetPanelFeatureFactory get_factory_f_ptr = nullptr;
+ if (feature_impl_lib.Open(EXTENSION_LIBRARY_NAME)) {
+ if (!feature_impl_lib.Sym(GET_PANEL_FEATURE_FACTORY,
+ reinterpret_cast<void **>(&get_factory_f_ptr))) {
+ DLOGE("Unable to load symbols, error = %s", feature_impl_lib.Error());
+ return kErrorUndefined;
+ }
+ } else {
+ DLOGW("Unable to load = %s, error = %s", EXTENSION_LIBRARY_NAME, feature_impl_lib.Error());
+ DLOGW("SDM Extension is not supported");
+ return kErrorNone;
+ }
+
+ pf_factory_ = get_factory_f_ptr();
+ if (!pf_factory_) {
+ DLOGE("Failed to create PanelFeatureFactory");
+ return kErrorResources;
+ }
+
+ prop_intf_ = hw_intf_->GetPanelFeaturePropertyIntf();
+ if (!prop_intf_) {
+ DLOGW("Failed to create PanelFeaturePropertyIntf");
+ pf_factory_ = nullptr;
+ return kErrorResources;
+ }
+
+ DLOGI("Setup pf factory and prop intf for Panel Features");
+ return kErrorNone;
+}
+
// Query the dspp capabilities and enable the RC feature.
DisplayError DisplayBase::SetupRC() {
+ // Get status of RC enablement property. Default RC is disabled.
+ int rc_prop_value = 0;
+ Debug::GetProperty(ENABLE_ROUNDED_CORNER, &rc_prop_value);
+ rc_enable_prop_ = rc_prop_value ? true : false;
+ DLOGI("RC feature %s.", rc_enable_prop_ ? "enabled" : "disabled");
+ if (!rc_enable_prop_) {
+ return kErrorNone;
+ }
+
RCInputConfig input_cfg = {};
input_cfg.display_id = display_id_;
input_cfg.display_type = display_type_;
@@ -228,6 +275,7 @@
return kErrorResources;
}
+ rc_panel_feature_init_ = true;
return kErrorNone;
}
@@ -235,6 +283,8 @@
std::vector<Layer *> &layers = layer_stack->layers;
HWLayersInfo &hw_layers_info = disp_layer_stack_.info;
hw_layers_info.app_layer_count = 0;
+ hw_layers_info.gpu_target_index = -1;
+ hw_layers_info.stitch_target_index = -1;
disp_layer_stack_.stack = layer_stack;
hw_layers_info.flags = layer_stack->flags;
@@ -261,7 +311,6 @@
}
}
- hw_layers_info.stitch_target_index = hw_layers_info.gpu_target_index + 1;
DLOGD_IF(kTagDisplay, "LayerStack layer_count: %zu, app_layer_count: %d, "
"gpu_target_index: %d, stitch_index: %d game_present: %d, display: %d-%d",
layers.size(), hw_layers_info.app_layer_count,
@@ -273,7 +322,7 @@
return kErrorNoAppLayers;
}
- if (hw_layers_info.gpu_target_index) {
+ if (hw_layers_info.gpu_target_index > 0) {
return ValidateGPUTargetParams();
}
@@ -1119,6 +1168,7 @@
case kCompositionStitch: return "STITCH";
case kCompositionGPUTarget: return "GPU_TARGET";
case kCompositionStitchTarget: return "STITCH_TARGET";
+ case kCompositionDemura: return "DEMURA";
default: return "UNKNOWN";
}
}
@@ -1850,7 +1900,8 @@
// TODO(user): Other FBT layer attributes like surface damage, dataspace, secure camera and
// secure display flags are also updated during SetClientTarget() called between validate and
// commit. Need to revist this and update it accordingly for FBT layer.
- if (disp_layer_stack_.info.gpu_target_index == sdm_layer_index) {
+ if (disp_layer_stack_.info.gpu_target_index > 0 &&
+ (static_cast<uint32_t>(disp_layer_stack_.info.gpu_target_index) == sdm_layer_index)) {
hw_layer.input_buffer.flags.secure = sdm_layer->input_buffer.flags.secure;
hw_layer.input_buffer.format = sdm_layer->input_buffer.format;
hw_layer.input_buffer.width = sdm_layer->input_buffer.width;
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index dd52659..b0dc999 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -44,11 +44,15 @@
#include "color_manager.h"
#include "hw_events_interface.h"
+#define GET_PANEL_FEATURE_FACTORY "GetPanelFeatureFactoryIntf"
+
namespace sdm {
using std::recursive_mutex;
using std::lock_guard;
+typedef PanelFeatureFactoryIntf* (*GetPanelFeatureFactory)();
+
class DisplayBase : public DisplayInterface {
public:
DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
@@ -178,6 +182,7 @@
virtual DisplayError NotifyDisplayCalibrationMode(bool in_calibration) {
return kErrorNotSupported;
}
+ virtual bool HasDemura() { return false; }
protected:
struct DisplayMutex {
@@ -216,7 +221,7 @@
const char *kBt2020Pq = "bt2020_pq";
const char *kBt2020Hlg = "bt2020_hlg";
const char *kDisplayBt2020 = "display_bt2020";
- DisplayError BuildLayerStackStats(LayerStack *layer_stack);
+ virtual DisplayError BuildLayerStackStats(LayerStack *layer_stack);
virtual DisplayError ValidateGPUTargetParams();
void CommitLayerParams(LayerStack *layer_stack);
void PostCommitLayerParams(LayerStack *layer_stack);
@@ -250,6 +255,7 @@
DisplayError ResetPendingPowerState(const shared_ptr<Fence> &retire_fence);
DisplayError GetPendingDisplayState(DisplayState *disp_state);
void SetPendingPowerState(DisplayState state);
+ DisplayError SetupPanelFeatureFactory();
DisplayMutex disp_mutex_;
int32_t display_id_ = -1;
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index 368caaa..d8065de 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -27,6 +27,7 @@
#include <utils/rect.h>
#include <utils/utils.h>
#include <utils/formats.h>
+#include <core/buffer_allocator.h>
#include <iomanip>
#include <algorithm>
#include <functional>
@@ -131,19 +132,30 @@
Debug::Get()->GetProperty(DEFER_FPS_FRAME_COUNT, &value);
deferred_config_.frame_count = (value > 0) ? UINT32(value) : 0;
- spr_prop_value_ = 0;
- // Enable SPR as default is disabled.
- Debug::GetProperty(ENABLE_SPR, &spr_prop_value_);
+ if (pf_factory_ && prop_intf_) {
+ if (DisplayBase::SetupRC() != kErrorNone) {
+ // Non-fatal but not expected, log error
+ DLOGE("RC Failed to initialize. Error = %d", error);
+ }
- error = CreatePanelfeatures();
- if (error != kErrorNone) {
- DLOGE("Failed to setup panel feature factory, error: %d", error);
+ if ((error = SetupSPR()) != kErrorNone) {
+ DLOGE("SPR Failed to initialize. Error = %d", error);
+ DisplayBase::Deinit();
+ HWInterface::Destroy(hw_intf_);
+ return error;
+ }
+
+ if (SetupDemura() != kErrorNone) {
+ // Non-fatal but not expected, log error
+ DLOGE("Demura failed to initialize, Error = %d", error);
+ comp_manager_->FreeDemuraFetchResources(display_comp_ctx_);
+ comp_manager_->SetDemuraStatusForDisplay(display_id_, false);
+ if (demura_) {
+ SetDemuraIntfStatus(false);
+ }
+ }
} else {
- // Get status of RC enablement property. Default RC is disabled.
- int rc_prop_value = 0;
- Debug::GetProperty(ENABLE_ROUNDED_CORNER, &rc_prop_value);
- rc_enable_prop_ = rc_prop_value ? true : false;
- DLOGI("RC feature %s.", rc_enable_prop_ ? "enabled" : "disabled");
+ DLOGW("Skipping Panel Feature Setups!");
}
value = 0;
DebugHandler::Get()->GetProperty(DISABLE_DYNAMIC_FPS, &value);
@@ -168,45 +180,18 @@
ClientLock lock(disp_mutex_);
dpps_info_.Deinit();
- }
- return DisplayBase::Deinit();
-}
-// Create instance for RC, SPR and demura feature.
-DisplayError DisplayBuiltIn::CreatePanelfeatures() {
- if (pf_factory_ && prop_intf_) {
- return kErrorNone;
- }
+ if (demura_) {
+ SetDemuraIntfStatus(false);
- if (!GetPanelFeatureFactoryIntfFunc_) {
- DynLib feature_impl_lib;
- if (feature_impl_lib.Open(EXTENSION_LIBRARY_NAME)) {
- if (!feature_impl_lib.Sym("GetPanelFeatureFactoryIntf",
- reinterpret_cast<void **>(&GetPanelFeatureFactoryIntfFunc_))) {
- DLOGE("Unable to load symbols, error = %s", feature_impl_lib.Error());
- return kErrorUndefined;
+ if (demura_->Deinit() != 0) {
+ DLOGE("Unable to DeInit Demura on Display %d", display_id_);
}
- } else {
- DLOGW("Unable to load = %s, error = %s", EXTENSION_LIBRARY_NAME, feature_impl_lib.Error());
- DLOGW("Panel features are not supported");
- return kErrorNotSupported;
+
+ comp_manager_->FreeDemuraFetchResources(display_comp_ctx_);
}
}
-
- pf_factory_ = GetPanelFeatureFactoryIntfFunc_();
- if (!pf_factory_) {
- DLOGE("Failed to create PanelFeatureFactoryIntf");
- return kErrorResources;
- }
-
- prop_intf_ = hw_intf_->GetPanelFeaturePropertyIntf();
- if (!prop_intf_) {
- DLOGE("Failed to create PanelFeaturePropertyIntf");
- pf_factory_ = nullptr;
- return kErrorResources;
- }
-
- return kErrorNone;
+ return DisplayBase::Deinit();
}
DisplayError DisplayBuiltIn::Prepare(LayerStack *layer_stack) {
@@ -218,6 +203,7 @@
uint32_t display_height = display_attributes_.y_pixels;
DTRACE_SCOPED();
+
if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) {
error = ReconfigureMixer(new_mixer_width, new_mixer_height);
if (error != kErrorNone) {
@@ -348,32 +334,131 @@
}
DisplayError DisplayBuiltIn::SetupSPR() {
- SPRInputConfig spr_cfg;
- spr_cfg.panel_name = std::string(hw_panel_info_.panel_name);
- spr_ = pf_factory_->CreateSPRIntf(spr_cfg, prop_intf_);
- if (!spr_ || spr_->Init() != 0) {
- DLOGE("Failed to initialize SPR");
- return kErrorResources;
+ int spr_prop_value = 0;
+ // Enable SPR as default is disabled.
+ Debug::GetProperty(ENABLE_SPR, &spr_prop_value);
+
+ if (spr_prop_value) {
+ SPRInputConfig spr_cfg;
+ spr_cfg.panel_name = std::string(hw_panel_info_.panel_name);
+ spr_ = pf_factory_->CreateSPRIntf(spr_cfg, prop_intf_);
+
+ if (spr_ == nullptr) {
+ DLOGE("Failed to create SPR interface");
+ return kErrorResources;
+ }
+
+ if (spr_->Init() != 0) {
+ DLOGE("Failed to initialize SPR");
+ return kErrorResources;
+ }
}
return kErrorNone;
}
DisplayError DisplayBuiltIn::SetupDemura() {
- return kErrorNone;
+ if (!comp_manager_->GetDemuraStatus()) {
+ comp_manager_->FreeDemuraFetchResources(display_comp_ctx_);
+ comp_manager_->SetDemuraStatusForDisplay(display_id_, false);
+ return kErrorNone;
+ }
+
+ int value = 0;
+ if (IsPrimaryDisplay()) {
+ Debug::Get()->GetProperty(DISABLE_DEMURA_PRIMARY, &value);
+ } else {
+ Debug::Get()->GetProperty(DISABLE_DEMURA_SECONDARY, &value);
+ }
+
+ if (value > 0) {
+ comp_manager_->FreeDemuraFetchResources(display_comp_ctx_);
+ comp_manager_->SetDemuraStatusForDisplay(display_id_, false);
+ return kErrorNone;
+ } else if (value == 0) {
+ DemuraInputConfig input_cfg;
+ input_cfg.secure_session = false; // TODO(user): Integrate with secure solution
+ std::string brightness_base;
+ hw_intf_->GetPanelBrightnessBasePath(&brightness_base);
+ input_cfg.brightness_path = brightness_base+"brightness";
+
+ FetchResourceList frl;
+ comp_manager_->GetDemuraFetchResources(display_comp_ctx_, &frl);
+ for (auto &fr : frl) {
+ int i = std::get<1>(fr); // fetch resource index
+ input_cfg.resources.set(i);
+ }
+
+ demura_ = pf_factory_->CreateDemuraIntf(input_cfg, prop_intf_, buffer_allocator_, spr_);
+
+ if (!demura_) {
+ DLOGE("Unable to create Demura on Display %d", display_id_);
+ return kErrorMemory;
+ }
+
+ if (demura_->Init() != 0) {
+ DLOGE("Unable to initialize Demura on Display %d", display_id_);
+ return kErrorUndefined;
+ }
+
+ if (SetupDemuraLayer() != kErrorNone) {
+ DLOGE("Unable to setup Demura layer on Display %d", display_id_);
+ return kErrorUndefined;
+ }
+
+ if (SetDemuraIntfStatus(true)) {
+ return kErrorUndefined;
+ }
+
+ comp_manager_->SetDemuraStatusForDisplay(display_id_, true);
+ demura_intended_ = true;
+ DLOGI("Enabled Demura Core!");
+ return kErrorNone;
+ }
+
+ return kErrorUndefined;
}
-DisplayError DisplayBuiltIn::SetupPanelfeatures() {
- if (!pf_factory_ || !prop_intf_) {
- DLOGE("Failed to create PanelFeatures");
+DisplayError DisplayBuiltIn::SetupDemuraLayer() {
+ int ret = 0;
+ GenericPayload pl;
+ BufferInfo* buffer = nullptr;
+ if ((ret = pl.CreatePayload<BufferInfo>(buffer))) {
+ DLOGE("Failed to create payload for BufferInfo, error = %d", ret);
+ return kErrorResources;
+ }
+ if ((ret = demura_->GetParameter(kDemuraFeatureParamCorrectionBuffer, &pl))) {
+ DLOGE("Failed to get BufferInfo, error = %d", ret);
return kErrorResources;
}
- DisplayError ret = kErrorNone;
- if ((ret = SetupSPR()) != kErrorNone) return ret;
- if ((ret = SetupDemura()) != kErrorNone) return ret;
-
- return ret;
+ demura_layer_.input_buffer.size = buffer->alloc_buffer_info.size;
+ demura_layer_.input_buffer.buffer_id = buffer->alloc_buffer_info.id;
+ demura_layer_.input_buffer.format = buffer->alloc_buffer_info.format;
+ demura_layer_.input_buffer.width = buffer->alloc_buffer_info.aligned_width;
+ demura_layer_.input_buffer.unaligned_width = buffer->alloc_buffer_info.aligned_width;
+ demura_layer_.input_buffer.height = buffer->alloc_buffer_info.aligned_height;
+ demura_layer_.input_buffer.unaligned_height = buffer->alloc_buffer_info.aligned_height;
+ demura_layer_.input_buffer.planes[0].fd = buffer->alloc_buffer_info.fd;
+ demura_layer_.input_buffer.planes[0].stride = buffer->alloc_buffer_info.stride;
+ demura_layer_.input_buffer.planes[0].offset = 0;
+ demura_layer_.input_buffer.flags.demura = 1;
+ demura_layer_.composition = kCompositionDemura;
+ demura_layer_.blending = kBlendingSkip;
+ demura_layer_.flags.is_demura = 1;
+ // ROI must match input dimensions
+ demura_layer_.src_rect.top = 0;
+ demura_layer_.src_rect.left = 0;
+ demura_layer_.src_rect.right = buffer->buffer_config.width;
+ demura_layer_.src_rect.bottom = buffer->buffer_config.height;
+ LogI(kTagNone, "Demura src: ", demura_layer_.src_rect);
+ demura_layer_.dst_rect.top = 0;
+ demura_layer_.dst_rect.left = 0;
+ demura_layer_.dst_rect.right = buffer->buffer_config.width;
+ demura_layer_.dst_rect.bottom = buffer->buffer_config.height;
+ LogI(kTagNone, "Demura dst: ", demura_layer_.dst_rect);
+ demura_layer_.buffer_map = std::make_shared<LayerBufferMap>();
+ return kErrorNone;
}
DisplayError DisplayBuiltIn::Commit(LayerStack *layer_stack) {
@@ -535,6 +620,13 @@
SetDeferredFpsConfig();
}
+ // Must go in NullCommit
+ if (demura_intended_ &&
+ comp_manager_->GetDemuraStatusForDisplay(display_id_) && (state == kStateOff)) {
+ comp_manager_->SetDemuraStatusForDisplay(display_id_, false);
+ SetDemuraIntfStatus(false);
+ }
+
error = DisplayBase::SetDisplayState(state, teardown, release_fence);
if (error != kErrorNone) {
return error;
@@ -553,12 +645,11 @@
event_handler_->Refresh();
}
- if (spr_prop_value_ && !panel_feature_init_ && state != kStateOff && state != kStateStandby) {
- error = SetupPanelfeatures();
- panel_feature_init_ = true;
- if (error != kErrorNone) {
- DLOGE("SetupPanelfeatures failed with error :%d, ignoring!", error);
- }
+ // Must only happen after NullCommit and get applied in next frame
+ if (demura_intended_ &&
+ !comp_manager_->GetDemuraStatusForDisplay(display_id_) && (state == kStateOn)) {
+ comp_manager_->SetDemuraStatusForDisplay(display_id_, true);
+ SetDemuraIntfStatus(true);
}
return kErrorNone;
@@ -1547,9 +1638,16 @@
}
// Check Panel and Layer Stack attributes.
+ int8_t stack_fudge_factor = 1; // GPU Target Layer always present in input
+ if (layer_stack->flags.stitch_present)
+ stack_fudge_factor++;
+ if (layer_stack->flags.demura_present)
+ stack_fudge_factor++;
+
if (!hw_panel_info_.partial_update || (hw_panel_info_.left_roi_count != 1) ||
layer_stack->flags.geometry_changed || layer_stack->flags.config_changed ||
- (layer_stack->layers.size() != (disp_layer_stack_.info.app_layer_count + 1))) {
+ (layer_stack->layers.size() !=
+ (disp_layer_stack_.info.app_layer_count + stack_fudge_factor))) {
return false;
}
@@ -1619,7 +1717,13 @@
}
// Set the composition type for SDM layers.
- for (uint32_t i = 0; i < (layer_stack->layers.size() - 1); i++) {
+ size_t size_ff = 1; // GPU Target Layer always present in input
+ if (layer_stack->flags.stitch_present)
+ size_ff++;
+ if (layer_stack->flags.demura_present)
+ size_ff++;
+
+ for (uint32_t i = 0; i < (layer_stack->layers.size() - size_ff); i++) {
layer_stack->layers.at(i)->composition = kCompositionSDE;
}
}
@@ -1627,6 +1731,91 @@
return same_roi;
}
+DisplayError DisplayBuiltIn::BuildLayerStackStats(LayerStack *layer_stack) {
+ std::vector<Layer *> &layers = layer_stack->layers;
+ HWLayersInfo &hw_layers_info = disp_layer_stack_.info;
+ hw_layers_info.app_layer_count = 0;
+ hw_layers_info.gpu_target_index = -1;
+ hw_layers_info.stitch_target_index = -1;
+ hw_layers_info.demura_target_index = -1;
+
+ disp_layer_stack_.stack = layer_stack;
+ hw_layers_info.flags = layer_stack->flags;
+ hw_layers_info.blend_cs = layer_stack->blend_cs;
+
+ int index = 0;
+ for (auto &layer : layers) {
+ if (layer->buffer_map == nullptr) {
+ layer->buffer_map = std::make_shared<LayerBufferMap>();
+ }
+ if (layer->composition == kCompositionGPUTarget) {
+ hw_layers_info.gpu_target_index = index;
+ } else if (layer->composition == kCompositionStitchTarget) {
+ hw_layers_info.stitch_target_index = index;
+ disp_layer_stack_.stack->flags.stitch_present = true;
+ hw_layers_info.stitch_present = true;
+ } else if (layer->composition == kCompositionDemura) {
+ hw_layers_info.demura_target_index = index;
+ disp_layer_stack_.stack->flags.demura_present = true;
+ hw_layers_info.demura_present = true;
+ DLOGD_IF(kTagDisplay, "Display %d shall request Demura in this frame", display_id_);
+ } else {
+ hw_layers_info.app_layer_count++;
+ }
+ if (IsWideColor(layer->input_buffer.color_metadata.colorPrimaries)) {
+ hw_layers_info.wide_color_primaries.push_back(
+ layer->input_buffer.color_metadata.colorPrimaries);
+ }
+ if (layer->flags.is_game) {
+ hw_layers_info.game_present = true;
+ }
+ index++;
+ }
+ if (comp_manager_->GetDemuraStatus() &&
+ comp_manager_->GetDemuraStatusForDisplay(display_id_) &&
+ demura_layer_.input_buffer.planes[0].fd > 0 &&
+ hw_layers_info.demura_target_index == -1) {
+ layers.push_back(&demura_layer_);
+ hw_layers_info.demura_target_index = index;
+ hw_layers_info.demura_present = true;
+ disp_layer_stack_.stack->flags.demura_present = true;
+ DLOGD_IF(kTagDisplay, "Display %d shall request Demura in this frame", display_id_);
+ } else if ((!comp_manager_->GetDemuraStatus() ||
+ !comp_manager_->GetDemuraStatusForDisplay(display_id_)) &&
+ hw_layers_info.demura_target_index != -1 ) {
+ layers.erase(layers.begin() + hw_layers_info.demura_target_index);
+ hw_layers_info.demura_present = false;
+ disp_layer_stack_.stack->flags.demura_present = false;
+ if (hw_layers_info.gpu_target_index > hw_layers_info.demura_target_index) {
+ hw_layers_info.gpu_target_index--;
+ }
+ if (hw_layers_info.stitch_target_index > hw_layers_info.demura_target_index) {
+ hw_layers_info.stitch_target_index--;
+ }
+ hw_layers_info.demura_target_index = -1;
+ DLOGD_IF(kTagDisplay, "Display %d shall remove Demura in this frame", display_id_);
+ }
+
+ DLOGI_IF(kTagDisplay, "LayerStack layer_count: %zu, app_layer_count: %d, "
+ "gpu_target_index: %d, stitch_index: %d, demura_index: %d, "
+ "game_present: %d, display: %d-%d",
+ layers.size(), hw_layers_info.app_layer_count,
+ hw_layers_info.gpu_target_index, hw_layers_info.stitch_target_index,
+ hw_layers_info.demura_target_index, hw_layers_info.game_present,
+ display_id_, display_type_);
+
+ if (!hw_layers_info.app_layer_count) {
+ DLOGW("Layer count is zero");
+ return kErrorNoAppLayers;
+ }
+
+ if (hw_layers_info.gpu_target_index > 0) {
+ return ValidateGPUTargetParams();
+ }
+
+ return kErrorNone;
+}
+
DisplayError DisplayBuiltIn::SetActiveConfig(uint32_t index) {
deferred_config_.MarkDirty();
return DisplayBase::SetActiveConfig(index);
@@ -1819,4 +2008,28 @@
}
}
+int DisplayBuiltIn::SetDemuraIntfStatus(bool enable) {
+ if (!demura_) {
+ DLOGE("demura_ is nullptr");
+ return -EINVAL;
+ }
+
+ int ret = 0;
+ GenericPayload pl;
+ bool* enable_ptr = nullptr;
+ if ((ret = pl.CreatePayload<bool>(enable_ptr))) {
+ DLOGE("Failed to create payload for enable, error = %d", ret);
+ return ret;
+ } else {
+ *enable_ptr = enable;
+ if ((ret = demura_->SetParameter(kDemuraFeatureParamActive, pl))) {
+ DLOGE("Failed to set Active, error = %d", ret);
+ return ret;
+ }
+ }
+
+ DLOGI("Demura is now %s", enable ? "Enabled" : "Disabled");
+ return ret;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index 86887fc..a9e3b5c 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -82,8 +82,6 @@
}
};
-typedef PanelFeatureFactoryIntf* (*GetPanelFeatureFactoryIntfType)();
-
class DppsInfo {
public:
void Init(DppsPropIntf *intf, const std::string &panel_name);
@@ -142,6 +140,7 @@
DisplayError GetStcColorModes(snapdragoncolor::ColorModeList *mode_list) override;
DisplayError SetStcColorMode(const snapdragoncolor::ColorMode &color_mode) override;
DisplayError NotifyDisplayCalibrationMode(bool in_calibration) override;
+ bool HasDemura() override { return demura_intended_; }
std::string Dump() override;
DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info) override;
@@ -174,9 +173,10 @@
void SetDeferredFpsConfig();
void GetFpsConfig(HWDisplayAttributes *display_attributes, HWPanelInfo *panel_info);
PrimariesTransfer GetBlendSpaceFromStcColorMode(const snapdragoncolor::ColorMode &color_mode);
- DisplayError SetupPanelfeatures();
DisplayError SetupSPR();
DisplayError SetupDemura();
+ DisplayError SetupDemuraLayer();
+ DisplayError BuildLayerStackStats(LayerStack *layer_stack) override;
void UpdateDisplayModeParams();
void HandleQsyncPostCommit(LayerStack *layer_stack);
void UpdateQsyncMode();
@@ -184,6 +184,7 @@
void SendBacklight();
void SendDisplayConfigs();
bool CanLowerFps(bool idle_screen);
+ int SetDemuraIntfStatus(bool enable);
const uint32_t kPuTimeOutMs = 1000;
std::vector<HWEvent> event_list_;
@@ -213,13 +214,10 @@
sde_drm::DppsFeaturePayload histogramIRQ;
void initColorSamplingState();
DeferFpsConfig deferred_config_ = {};
-
snapdragoncolor::ColorMode current_color_mode_ = {};
snapdragoncolor::ColorModeList stc_color_modes_ = {};
- std::shared_ptr<SPRIntf> spr_;
- GetPanelFeatureFactoryIntfType GetPanelFeatureFactoryIntfFunc_ = nullptr;
- int spr_prop_value_ = 0;
+ std::shared_ptr<SPRIntf> spr_ = nullptr;
bool needs_validate_on_pu_enable_ = false;
bool enable_qsync_idle_ = false;
bool pending_vsync_enable_ = false;
@@ -228,6 +226,9 @@
bool enhance_idle_time_ = false;
int idle_time_ms_ = 0;
struct timespec idle_timer_start_;
+ std::unique_ptr<DemuraIntf> demura_ = nullptr;
+ Layer demura_layer_ = {};
+ bool demura_intended_ = false;
};
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index ec1829d..9a2b551 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -1286,7 +1286,7 @@
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ZORDER, pipe_id, pipe_info->z_order);
- DRMBlendType blending = {};
+ DRMBlendType blending = DRMBlendType::UNDEFINED;
SetBlending(layer.blending, &blending);
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_BLEND_TYPE, pipe_id, blending);
@@ -1372,7 +1372,9 @@
}
drm_atomic_intf_->Perform(DRMOps::DPPS_COMMIT_FEATURE, 0 /* argument is not used */);
- drm_atomic_intf_->Perform(DRMOps::COMMIT_PANEL_FEATURES, 0 /* argument is not used */);
+ if (!validate) {
+ drm_atomic_intf_->Perform(DRMOps::COMMIT_PANEL_FEATURES, 0 /* argument is not used */);
+ }
if (reset_output_fence_offset_ && !validate) {
// Change back the fence_offset
@@ -1733,6 +1735,9 @@
case kBlendingCoverage:
*target = DRMBlendType::COVERAGE;
break;
+ case kBlendingSkip:
+ *target = DRMBlendType::SKIP_BLENDING;
+ break;
default:
*target = DRMBlendType::UNDEFINED;
}
@@ -2406,6 +2411,7 @@
DisplayError HWDeviceDRM::NullCommit(bool synchronous, bool retain_planes) {
DTRACE_SCOPED();
AddDimLayerIfNeeded();
+ drm_atomic_intf_->Perform(DRMOps::NULL_COMMIT_PANEL_FEATURES, 0 /* argument is not used */);
int ret = drm_atomic_intf_->Commit(synchronous , retain_planes);
if (ret) {
DLOGE("failed with error %d", ret);
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index ea7c77e..a858ed1 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -30,6 +30,7 @@
#ifndef __HW_DEVICE_DRM_H__
#define __HW_DEVICE_DRM_H__
+#include <utils/formats.h>
#include <drm_interface.h>
#include <errno.h>
#include <pthread.h>
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index e995342..53e060f 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -74,6 +74,7 @@
using sde_drm::DRMCrtcInfo;
using sde_drm::DRMPlaneType;
using sde_drm::DRMTonemapLutType;
+using sde_drm::DRMPanelFeatureInfo;
using std::vector;
using std::map;
@@ -250,6 +251,8 @@
DLOGI("Max Pipe Bw = %" PRIu64 " KBps", hw_resource->dyn_bw_info.pipe_bw_limit[kBwVFEOn]);
DLOGI("Max Pipe Bw High= %" PRIu64 " KBps", hw_resource->dyn_bw_info.pipe_bw_limit[kBwVFEOff]);
DLOGI("MaxSDEClock = %d Hz", hw_resource->max_sde_clk);
+ DLOGI("Demura Count = %" PRIu32, hw_resource->demura_count);
+ DLOGI("DSPP Count = %" PRIu32, hw_resource->dspp_count);
DLOGI("Clock Fudge Factor = %f", hw_resource->clk_fudge_factor);
DLOGI("Prefill factors:");
DLOGI("\tTiled_NV12 = %d", hw_resource->macrotile_nv12_factor);
@@ -299,6 +302,8 @@
hw_resource->extra_fudge_factor = info.extra_prefill_lines;
hw_resource->amortizable_threshold = info.amortized_threshold;
hw_resource->has_micro_idle = info.has_micro_idle;
+ hw_resource->demura_count = info.demura_count;
+ hw_resource->dspp_count = info.dspp_count;
for (int index = 0; index < kBwModeMax; index++) {
if (index == kBwVFEOn) {
@@ -366,6 +371,8 @@
int disable_src_tonemap = 0;
Debug::Get()->GetProperty(DISABLE_SRC_TONEMAP_PROP, &disable_src_tonemap);
+ MapPlaneToConnector(hw_resource);
+ GetInitialDemuraInfo(hw_resource);
for (auto &pipe_obj : planes) {
if (max_vig_pipes && max_dma_pipes) {
uint32_t master_plane_id = pipe_obj.second.master_plane_id;
@@ -430,6 +437,14 @@
continue; // Not adding any other pipe type
}
pipe_caps.id = pipe_obj.first;
+ auto it = hw_resource->plane_to_connector.find(pipe_caps.id);
+ if (it != hw_resource->plane_to_connector.end()) {
+ pipe_caps.cont_splash_disp_id = it->second;
+ auto it2 = std::find(hw_resource->initial_demura_planes.begin(),
+ hw_resource->initial_demura_planes.end(), pipe_caps.id);
+ pipe_caps.splash_type = (it2 != hw_resource->initial_demura_planes.end()) ? kSplashDemura
+ : kSplashLayer;
+ }
pipe_caps.master_pipe_id = pipe_obj.second.master_plane_id;
pipe_caps.block_sec_ui = pipe_obj.second.block_sec_ui;
DLOGI("Adding %s Pipe : Id %d, master_pipe_id : Id %d block_sec_ui: %d",
@@ -437,6 +452,8 @@
pipe_obj.second.block_sec_ui);
pipe_caps.inverse_pma = pipe_obj.second.inverse_pma;
pipe_caps.dgm_csc_version = pipe_obj.second.dgm_csc_version;
+ pipe_caps.pipe_idx = pipe_obj.second.pipe_idx;
+ pipe_caps.demura_block_capability = pipe_obj.second.demura_block_capability;
// disable src tonemap feature if its disabled using property.
if (!disable_src_tonemap) {
for (auto &it : pipe_obj.second.tonemap_lut_version_map) {
@@ -473,8 +490,16 @@
hw_resource->has_excl_rect = planes[0].second.has_excl_rect;
}
+void HWInfoDRM::MapPlaneToConnector(HWResourceInfo *hw_resource) {
+ drm_mgr_intf_->MapPlaneToConnector(&hw_resource->plane_to_connector);
+}
+
+void HWInfoDRM::GetInitialDemuraInfo(HWResourceInfo *hw_resource) {
+ drm_mgr_intf_->GetInitialDemuraInfo(&hw_resource->initial_demura_planes);
+}
+
void HWInfoDRM::PopulatePipeCaps(const sde_drm::DRMPlaneTypeInfo &info,
- HWResourceInfo *hw_resource) {
+ HWResourceInfo *hw_resource) {
hw_resource->max_pipe_width = info.max_linewidth;
hw_resource->max_scaler_pipe_width = info.max_scaler_linewidth;
hw_resource->max_rotation_pipe_width = info.max_rotation_linewidth;
@@ -488,14 +513,14 @@
hw_resource->pipe_qseed3_version = GetQseedStepVersion(info.qseed3_version);
hw_resource->inline_rot_info.inrot_version = GetInRotVersion(info.inrot_version);
if (info.true_inline_dwnscale_rt_denom > 0 && info.true_inline_dwnscale_rt_num > 0 &&
- info.true_inline_dwnscale_rt_num >= info.true_inline_dwnscale_rt_denom) {
+ info.true_inline_dwnscale_rt_num >= info.true_inline_dwnscale_rt_denom) {
hw_resource->inline_rot_info.max_downscale_rt =
- info.true_inline_dwnscale_rt_num / info.true_inline_dwnscale_rt_denom;
+ info.true_inline_dwnscale_rt_num / info.true_inline_dwnscale_rt_denom;
}
}
void HWInfoDRM::PopulatePipeBWCaps(const sde_drm::DRMPlaneTypeInfo &info,
- HWResourceInfo *hw_resource) {
+ HWResourceInfo *hw_resource) {
for (int index = 0; index < kBwModeMax; index++) {
if (index == kBwVFEOn) {
hw_resource->dyn_bw_info.pipe_bw_limit[index] = info.max_pipe_bandwidth / kKiloUnit;
@@ -506,7 +531,7 @@
}
void HWInfoDRM::PopulateSupportedFmts(HWSubBlockType sub_blk_type,
- const sde_drm::DRMPlaneTypeInfo &info,
+ const sde_drm::DRMPlaneTypeInfo &info,
HWResourceInfo *hw_resource) {
vector<LayerBufferFormat> sdm_formats;
FormatsMap &fmts_map = hw_resource->supported_formats_map;
@@ -521,7 +546,7 @@
}
void HWInfoDRM::PopulateSupportedInlineFmts(const sde_drm::DRMPlaneTypeInfo &info,
- HWResourceInfo *hw_resource) {
+ HWResourceInfo *hw_resource) {
vector<LayerBufferFormat> *inrot_fmts = &hw_resource->inline_rot_info.inrot_fmts_supported;
for (auto &fmts : info.inrot_fmts_supported) {
@@ -940,4 +965,45 @@
return kErrorNone;
}
+DisplayError HWInfoDRM::GetRequiredDemuraFetchResourceCount(
+ std::map<uint32_t, uint8_t> *required_demura_fetch_cnt) {
+ if (!required_demura_fetch_cnt)
+ return kErrorParameters;
+
+ if (drm_mgr_intf_) {
+ required_demura_fetch_cnt->clear();
+ drm_mgr_intf_->GetRequiredDemuraFetchResourceCount(required_demura_fetch_cnt);
+
+ // Filter out displays that don't have panel_id
+ for (auto it = required_demura_fetch_cnt->begin(); it != required_demura_fetch_cnt->end();) {
+ sde_drm::DRMConnectorInfo info;
+ drm_mgr_intf_->GetConnectorInfo(it->first, &info);
+ if (!info.panel_id) {
+ it = required_demura_fetch_cnt->erase(it);
+ } else {
+ ++it;
+ }
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWInfoDRM::GetDemuraPanelIds(std::vector<uint64_t> *panel_ids) {
+ if (!panel_ids) {
+ return kErrorResources;
+ }
+
+ sde_drm::DRMConnectorsInfo conn_infos;
+ drm_mgr_intf_->GetConnectorsInfo(&conn_infos);
+ for (auto &conn : conn_infos) {
+ sde_drm::DRMConnectorInfo &info = conn.second;
+ if (info.panel_id) {
+ panel_ids->push_back(info.panel_id);
+ }
+ }
+
+ return kErrorNone;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_info_drm.h b/sdm/libs/core/drm/hw_info_drm.h
index 020920b..1cfbfdb 100644
--- a/sdm/libs/core/drm/hw_info_drm.h
+++ b/sdm/libs/core/drm/hw_info_drm.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-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
@@ -36,12 +36,13 @@
#include <private/hw_info_types.h>
#include <bitset>
#include <vector>
+#include <map>
#include "hw_info_interface.h"
namespace sdm {
-class HWInfoDRM: public HWInfoInterface {
+class HWInfoDRM : public HWInfoInterface {
public:
virtual DisplayError Init();
virtual ~HWInfoDRM();
@@ -49,6 +50,9 @@
virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info);
virtual DisplayError GetDisplaysStatus(HWDisplaysInfo *hw_displays_info);
virtual DisplayError GetMaxDisplaysSupported(DisplayType type, int32_t *max_displays);
+ virtual DisplayError GetRequiredDemuraFetchResourceCount(
+ std::map<uint32_t, uint8_t> *required_demura_fetch_cnt);
+ virtual DisplayError GetDemuraPanelIds(std::vector<uint64_t> *panel_ids);
private:
void Deinit();
@@ -63,12 +67,14 @@
void GetRotatorFormatsForType(int fd, uint32_t type,
std::vector<LayerBufferFormat> *supported_formats);
DisplayError GetRotatorSupportedFormats(uint32_t v4l2_index, HWResourceInfo *hw_resource);
- void PopulateSupportedFmts(HWSubBlockType sub_blk_type, const sde_drm::DRMPlaneTypeInfo &info,
+ void PopulateSupportedFmts(HWSubBlockType sub_blk_type, const sde_drm::DRMPlaneTypeInfo &info,
HWResourceInfo *hw_resource);
void PopulateSupportedInlineFmts(const sde_drm::DRMPlaneTypeInfo &info,
HWResourceInfo *hw_resource);
void PopulatePipeCaps(const sde_drm::DRMPlaneTypeInfo &info, HWResourceInfo *hw_resource);
void PopulatePipeBWCaps(const sde_drm::DRMPlaneTypeInfo &info, HWResourceInfo *hw_resource);
+ void MapPlaneToConnector(HWResourceInfo *hw_resource);
+ void GetInitialDemuraInfo(HWResourceInfo *hw_resource);
sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
bool default_mode_ = false;
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index 0b0fb2d..080e225 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -641,6 +641,10 @@
DisplayError HWPeripheralDRM::PowerOff(bool teardown) {
DTRACE_SCOPED();
+ if (!first_cycle_) {
+ drm_mgr_intf_->MarkPanelFeatureForNullCommit(token_,
+ panel_feature_property_map_[kPanelFeatureDemuraInitCfg]);
+ }
SetVMReqState();
DisplayError err = kErrorNone;
if (secure_display_active_) {
@@ -916,6 +920,7 @@
panel_feature_property_map_[kPanelFeatureDsppDemuraInfo] =
sde_drm::kDRMPanelFeatureDsppDemuraInfo;
panel_feature_property_map_[kPanelFeatureRCInitCfg] = sde_drm::kDRMPanelFeatureRCInit;
+ panel_feature_property_map_[kPanelFeatureDemuraPanelId] = sde_drm::kDRMPanelFeaturePanelId;
}
int HWPeripheralDRM::GetPanelFeature(PanelFeaturePropertyInfo *feature_info) {
@@ -939,6 +944,7 @@
switch (feature_info->prop_id) {
case kPanelFeatureSPRInitCfg:
+ case kPanelFeatureDemuraInitCfg:
case kPanelFeatureDsppIndex:
case kPanelFeatureDsppSPRInfo:
case kPanelFeatureDsppDemuraInfo:
@@ -948,6 +954,7 @@
drm_feature.obj_id = token_.crtc_id;
break;
case kPanelFeatureSPRPackType:
+ case kPanelFeatureDemuraPanelId:
drm_feature.obj_type = DRM_MODE_OBJECT_CONNECTOR;
drm_feature.obj_id = token_.conn_id;
break;
@@ -975,6 +982,7 @@
switch (feature_info.prop_id) {
case kPanelFeatureSPRInitCfg:
case kPanelFeatureRCInitCfg:
+ case kPanelFeatureDemuraInitCfg:
drm_feature.obj_type = DRM_MODE_OBJECT_CRTC;
drm_feature.obj_id = token_.crtc_id;
break;
diff --git a/sdm/libs/core/hw_info_interface.h b/sdm/libs/core/hw_info_interface.h
index 5eb2107..2ccf27d 100644
--- a/sdm/libs/core/hw_info_interface.h
+++ b/sdm/libs/core/hw_info_interface.h
@@ -25,9 +25,12 @@
#ifndef __HW_INFO_INTERFACE_H__
#define __HW_INFO_INTERFACE_H__
-#include <inttypes.h>
#include <core/core_interface.h>
#include <private/hw_info_types.h>
+#include <inttypes.h>
+#include <vector>
+#include <utility>
+#include <map>
namespace sdm {
@@ -40,7 +43,9 @@
virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) = 0;
virtual DisplayError GetDisplaysStatus(HWDisplaysInfo *hw_displays_info) = 0;
virtual DisplayError GetMaxDisplaysSupported(DisplayType type, int32_t *max_displays) = 0;
-
+ virtual DisplayError GetRequiredDemuraFetchResourceCount(
+ std::map<uint32_t, uint8_t> *required_demura_fetch_cnt) = 0;
+ virtual DisplayError GetDemuraPanelIds(std::vector<uint64_t> *panel_ids) = 0;
protected:
virtual ~HWInfoInterface() { }
};
diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h
index 5726a84..ea392e0 100644
--- a/sdm/libs/core/resource_default.h
+++ b/sdm/libs/core/resource_default.h
@@ -29,6 +29,7 @@
#include <private/resource_interface.h>
#include <utils/locker.h>
#include <vector>
+#include <map>
#include "hw_interface.h"
@@ -70,6 +71,18 @@
virtual DisplayError Perform(int cmd, ...) { return kErrorNone; }
DisplayError SetDisplayState(int32_t display_id, DisplayState state) { return kErrorNone; }
virtual bool IsRotatorSupportedFormat(LayerBufferFormat format) { return false; }
+ virtual DisplayError FreeDemuraFetchResources(Handle display_ctx) { return kErrorNone; }
+ virtual DisplayError GetDemuraFetchResourceCount(
+ std::map<uint32_t, uint8_t> *fetch_resource_cnt) {
+ return kErrorNone;
+ }
+ virtual DisplayError ReserveDemuraFetchResources(const int32_t &display_id,
+ const int8_t &preferred_rect) {
+ return kErrorNone;
+ }
+ virtual DisplayError GetDemuraFetchResources(Handle display_ctx, FetchResourceList *frl) {
+ return kErrorNone;
+ }
private:
enum PipeOwner {