From 66c941bd5d7b02b0419d2792c6664037d3531538 Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Wed, 6 Jul 2016 17:34:05 -0700 Subject: sdm: drm: Add Atomic commit support Add support for atomic commit, MDP comp for the peripheral display. Change-Id: I579d3379ba97cbc73485a4434bf29126226e2f85 CRs-fixed: 1114808 --- .clang-format | 13 + libdrmutils/Android.mk | 7 +- libdrmutils/drm_interface.h | 370 ++++++++++++++++++++++++++ libdrmutils/drm_lib_loader.cpp | 77 ++++++ libdrmutils/drm_lib_loader.h | 63 +++++ libdrmutils/drm_logger.h | 30 +-- libdrmutils/drm_master.cpp | 10 +- libdrmutils/drm_res_mgr.cpp | 16 +- sdm/.clang-format | 13 - sdm/libs/core/Android.mk | 3 + sdm/libs/core/drm/hw_device_drm.cpp | 517 ++++++++++++++++++++++++------------ sdm/libs/core/drm/hw_device_drm.h | 47 ++-- sdm/libs/core/drm/hw_info_drm.cpp | 412 ++++++++++++++++++++-------- sdm/libs/core/drm/hw_info_drm.h | 28 +- sdm/libs/core/fb/hw_primary.cpp | 6 +- sdm/libs/core/strategy.cpp | 6 +- 16 files changed, 1267 insertions(+), 351 deletions(-) create mode 100644 .clang-format create mode 100644 libdrmutils/drm_interface.h create mode 100644 libdrmutils/drm_lib_loader.cpp create mode 100644 libdrmutils/drm_lib_loader.h delete mode 100644 sdm/.clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..9082c400 --- /dev/null +++ b/.clang-format @@ -0,0 +1,13 @@ +--- +Language: Cpp +BasedOnStyle: Google +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortBlocksOnASingleLine: false +ColumnLimit: 100 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +DerivePointerAlignment: false +PointerAlignment: Right +#ReflowComments: false diff --git a/libdrmutils/Android.mk b/libdrmutils/Android.mk index 2f7ae4a9..8d9205d9 100644 --- a/libdrmutils/Android.mk +++ b/libdrmutils/Android.mk @@ -5,11 +5,12 @@ LOCAL_MODULE := libdrmutils LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \ external/libdrm -LOCAL_SHARED_LIBRARIES := libdrm +LOCAL_SHARED_LIBRARIES := libdrm libdl LOCAL_CFLAGS := -DLOG_TAG=\"DRMUTILS\" -Wall -std=c++11 -Werror LOCAL_CLANG := true LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr -LOCAL_SRC_FILES := drm_master.cpp drm_res_mgr.cpp +LOCAL_SRC_FILES := drm_master.cpp drm_res_mgr.cpp drm_lib_loader.cpp LOCAL_COPY_HEADERS_TO := qcom/display -LOCAL_COPY_HEADERS := drm_master.h drm_res_mgr.h +LOCAL_COPY_HEADERS := drm_master.h drm_res_mgr.h drm_lib_loader.h drm_logger.h drm_interface.h + include $(BUILD_SHARED_LIBRARY) diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h new file mode 100644 index 00000000..6c06e206 --- /dev/null +++ b/libdrmutils/drm_interface.h @@ -0,0 +1,370 @@ +/* +* Copyright (c) 2017, 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 __DRM_INTERFACE_H__ +#define __DRM_INTERFACE_H__ + +#include +#include +#include +#include + +#include "xf86drm.h" +#include "xf86drmMode.h" + +namespace sde_drm { +/* + * Drm Atomic Operation Codes + */ +enum struct DRMOps { + /* + * Op: Sets plane source crop + * Arg: uint32_t - Plane ID + * DRMRect - Source Rectangle + */ + PLANE_SET_SRC_RECT, + /* + * Op: Sets plane destination rect + * Arg: uint32_t - Plane ID + * DRMRect - Dst Rectangle + */ + PLANE_SET_DST_RECT, + /* + * Op: Sets plane zorder + * Arg: uint32_t - Plane ID + * uint32_t - zorder + */ + PLANE_SET_ZORDER, + /* + * Op: Sets plane rotation flags + * Arg: uint32_t - Plane ID + * uint32_t - bit mask of rotation flags (See drm_mode.h for enums) + */ + PLANE_SET_ROTATION, + /* + * Op: Sets plane alpha + * Arg: uint32_t - Plane ID + * uint32_t - alpha value + */ + PLANE_SET_ALPHA, + /* + * Op: Sets the blend type + * Arg: uint32_t - Plane ID + * uint32_t - blend type (see DRMBlendType) + */ + PLANE_SET_BLEND_TYPE, + /* + * Op: Sets horizontal decimation + * Arg: uint32_t - Plane ID + * uint32_t - decimation factor + */ + PLANE_SET_H_DECIMATION, + /* + * Op: Sets vertical decimation + * Arg: uint32_t - Plane ID + * uint32_t - decimation factor + */ + PLANE_SET_V_DECIMATION, + /* + * Op: Sets frame buffer ID for plane. Set together with CRTC. + * Arg: uint32_t - Plane ID + * uint32_t - Framebuffer ID + */ + PLANE_SET_FB_ID, + /* + * Op: Sets the crtc for this plane. Set together with FB_ID. + * Arg: uint32_t - Plane ID + * uint32_t - CRTC ID + */ + PLANE_SET_CRTC, + /* + * Op: Sets acquire fence for this plane's buffer. Set together with FB_ID, CRTC. + * Arg: uint32_t - Plane ID + * uint32_t - Input fence + */ + PLANE_SET_INPUT_FENCE, + /* + * Op: Activate or deactivate a CRTC + * Arg: uint32_t - CRTC ID + * uint32_t - 1 to enable, 0 to disable + */ + CRTC_SET_ACTIVE, + /* + * Op: Sets display mode + * Arg: uint32_t - CRTC ID + * drmModeModeInfo* - Pointer to display mode + */ + CRTC_SET_MODE, + /* + * Op: Sets an offset indicating when a release fence should be signalled. + * Arg: uint32_t - offset + * 0: non-speculative, default + * 1: speculative + */ + CRTC_SET_OUTPUT_FENCE_OFFSET, + /* + * Op: Returns release fence for this frame. Should be called after Commit() on + * DRMAtomicReqInterface. + * Arg: uint32_t - CRTC ID + * int * - Pointer to an integer that will hold the returned fence + */ + CRTC_GET_RELEASE_FENCE, + /* + * Op: Returns retire fence for this commit. Should be called after Commit() on + * DRMAtomicReqInterface. + * Arg: uint32_t - Connector ID + * int * - Pointer to an integer that will hold the returned fence + */ + CONNECTOR_GET_RETIRE_FENCE, + /* + * Op: Sets writeback connector destination rect + * Arg: uint32_t - Connector ID + * DRMRect - Dst Rectangle + */ + CONNECTOR_SET_OUTPUT_RECT, + /* + * Op: Sets frame buffer ID for writeback connector. + * Arg: uint32_t - Connector ID + * uint32_t - Framebuffer ID + */ + CONNECTOR_SET_OUTPUT_FB_ID, +}; + +enum struct DRMBlendType { + UNDEFINED = 0, + OPAQUE = 1, + PREMULTIPLIED = 2, + COVERAGE = 3, +}; + +/* Display type to identify a suitable connector */ +enum struct DRMDisplayType { + PERIPHERAL, + TV, + VIRTUAL, +}; + +struct DRMRect { + uint32_t left; // Left-most pixel coordinate. + uint32_t top; // Top-most pixel coordinate. + uint32_t right; // Right-most pixel coordinate. + uint32_t bottom; // Bottom-most pixel coordinate. +}; + +//------------------------------------------------------------------------ +// DRM Info Query Types +//------------------------------------------------------------------------ + +enum struct QSEEDVersion { + V1, + V2, + V3, +}; + +/* Per CRTC Resource Info*/ +struct DRMCrtcInfo { + bool has_src_split; + uint32_t max_blend_stages; + QSEEDVersion qseed_version; +}; + +enum struct DRMPlaneType { + // Has CSC and scaling capability + VIG = 0, + // Has scaling capability but no CSC + RGB, + // No scaling support + DMA, + // Supports a small dimension and doesn't use a CRTC stage + CURSOR, + MAX, +}; + +struct DRMPlaneTypeInfo { + // FourCC format enum and modifier + std::vector> formats_supported; + uint32_t max_linewidth; + uint32_t max_upscale; + uint32_t max_downscale; + uint32_t max_horizontal_deci; + uint32_t max_vertical_deci; +}; + +/* All DRM Planes Info*/ +struct DRMPlanesInfo { + // Plane id and plane type sorted by highest to lowest priority + std::vector> planes; + // Plane type and type info + std::map types; +}; + +enum struct DRMTopology { + UNKNOWN, // To be compat with driver defs in sde_kms.h + SINGLE_LM, + DUAL_LM, + PPSPLIT, + DUAL_LM_MERGE, +}; + +enum struct DRMPanelMode { + VIDEO, + COMMAND, +}; + +/* Per Connector Info*/ +struct DRMConnectorInfo { + uint32_t mmWidth; + uint32_t mmHeight; + uint32_t type; + uint32_t num_modes; + drmModeModeInfo *modes; + DRMTopology topology; + std::string panel_name; + DRMPanelMode panel_mode; + bool is_primary; + // Valid only if DRMPanelMode is VIDEO + bool dynamic_fps; + // FourCC format enum and modifier + std::vector> formats_supported; + // Valid only if type is DRM_MODE_CONNECTOR_VIRTUAL + uint32_t max_linewidth; +}; + +/* Identifier token for a display */ +struct DRMDisplayToken { + uint32_t conn_id; + uint32_t crtc_id; +}; + +/* DRM Atomic Request Property Set. + * + * Helper class to create and populate atomic properties of DRM components + * when rendered in DRM atomic mode */ +class DRMAtomicReqInterface { + public: + virtual ~DRMAtomicReqInterface() {} + /* Perform request operation. + * + * [input]: opcode: operation code from DRMOps list. + * var_arg: arguments for DRMOps's can differ in number and + * data type. Refer above DRMOps to details. + * [return]: Error code if the API fails, 0 on success. + */ + virtual int Perform(DRMOps opcode, ...) = 0; + + /* + * Commit the params set via Perform(). Also resets the properties after commit. Needs to be + * called every frame. + * [input]: synchronous: Determines if the call should block until a h/w flip + * [return]: Error code if the API fails, 0 on success. + */ + virtual int Commit(bool synchronous) = 0; + /* + * Validate the params set via Perform(). + * [return]: Error code if the API fails, 0 on success. + */ + virtual int Validate() = 0; +}; + +class DRMManagerInterface; + +/* Populates a singleton instance of DRMManager */ +typedef int (*GetDRMManager)(int fd, DRMManagerInterface **intf); + +/* Destroy DRMManager instance */ +typedef int (*DestroyDRMManager)(DRMManagerInterface *intf); + +/* + * 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 + * with SDM. + */ + +class DRMManagerInterface { + public: + virtual ~DRMManagerInterface() {} + + /* + * Since SDM completely manages the planes. GetPlanesInfo will provide all + * the plane information. + * [output]: DRMPlanesInfo: Resource Info for planes. + */ + virtual void GetPlanesInfo(DRMPlanesInfo *info) = 0; + + /* + * Will provide all the information of a selected crtc. + * [input]: Use crtc id 0 to obtain system wide info + * [output]: DRMCrtcInfo: Resource Info for the given CRTC id. + */ + virtual void GetCrtcInfo(uint32_t crtc_id, DRMCrtcInfo *info) = 0; + + /* + * Will provide all the information of a selected connector. + * [output]: DRMConnectorInfo: Resource Info for the given connector id + */ + virtual void GetConnectorInfo(uint32_t conn_id, DRMConnectorInfo *info) = 0; + + /* + * Register a logical display to receive a token. + * Each display pipeline in DRM is identified by its CRTC and Connector(s). + * On display connect(bootup or hotplug), clients should invoke this interface to + * establish the pipeline for the display and should get a DisplayToken + * populated with crtc and connnector(s) id's. Here onwards, Client should + * use this token to represent the display for any Perform operations if + * needed. + * + * [input]: disp_type - Peripheral / TV / Virtual + * [output]: DRMDisplayToken - CRTC and Connector id's for the display + * [return]: 0 on success, a negative error value otherwise + */ + virtual int RegisterDisplay(DRMDisplayType disp_type, DRMDisplayToken *tok) = 0; + + /* Client should invoke this interface on display disconnect. + * [input]: DRMDisplayToken - identifier for the display. + */ + virtual void UnregisterDisplay(const DRMDisplayToken &token) = 0; + + /* + * Creates and returns an instance of DRMAtomicReqInterface corresponding to a display token + * returned as part of RegisterDisplay API. Needs to be called per display. + * [input]: DRMDisplayToken that identifies a display pipeline + * [output]: Pointer to an instance of DRMAtomicReqInterface. + * [return]: Error code if the API fails, 0 on success. + */ + virtual int CreateAtomicReq(const DRMDisplayToken &token, DRMAtomicReqInterface **intf) = 0; + + /* + * Destroys the instance of DRMAtomicReqInterface + * [input]: Pointer to a DRMAtomicReqInterface + * [return]: Error code if the API fails, 0 on success. + */ + virtual int DestroyAtomicReq(DRMAtomicReqInterface *intf) = 0; +}; +} // namespace sde_drm +#endif // __DRM_INTERFACE_H__ diff --git a/libdrmutils/drm_lib_loader.cpp b/libdrmutils/drm_lib_loader.cpp new file mode 100644 index 00000000..845c1500 --- /dev/null +++ b/libdrmutils/drm_lib_loader.cpp @@ -0,0 +1,77 @@ +/* +* Copyright (c) 2017, 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 + +#include "drm_lib_loader.h" + +#define __CLASS__ "DRMLibLoader" + +using std::mutex; +using std::lock_guard; + +namespace drm_utils { + +DRMLibLoader *DRMLibLoader::s_instance = nullptr; +mutex DRMLibLoader::s_lock; + +DRMLibLoader *DRMLibLoader::GetInstance() { + lock_guard obj(s_lock); + + if (!s_instance) { + s_instance = new DRMLibLoader(); + } + + return s_instance; +} + +DRMLibLoader::DRMLibLoader() { + if (Open("libsdedrm.so")) { + if (Sym("GetDRMManager", reinterpret_cast(&func_get_drm_manager_)) && + Sym("DestroyDRMManager", reinterpret_cast(&func_destroy_drm_manager_))) { + is_loaded_ = true; + } + } +} + +bool DRMLibLoader::Open(const char *lib_name) { + lib_ = ::dlopen(lib_name, RTLD_NOW); + + return (lib_ != nullptr); +} + +bool DRMLibLoader::Sym(const char *func_name, void **func_ptr) { + if (lib_) { + *func_ptr = ::dlsym(lib_, func_name); + } + + return (*func_ptr != nullptr); +} + +} // namespace drm_utils diff --git a/libdrmutils/drm_lib_loader.h b/libdrmutils/drm_lib_loader.h new file mode 100644 index 00000000..dbc31a51 --- /dev/null +++ b/libdrmutils/drm_lib_loader.h @@ -0,0 +1,63 @@ +/* +* Copyright (c) 2017, 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 __DRM_LIB_LOADER_H__ +#define __DRM_LIB_LOADER_H__ + +#include +#include + +namespace drm_utils { + +class DRMLibLoader { + public: + ~DRMLibLoader() {} + bool IsLoaded() { return is_loaded_; } + sde_drm::GetDRMManager FuncGetDRMManager() { return func_get_drm_manager_; } + sde_drm::DestroyDRMManager FuncDestroyDRMManager() { return func_destroy_drm_manager_; } + + static DRMLibLoader *GetInstance(); + + private: + DRMLibLoader(); + bool Open(const char *lib_name); + bool Sym(const char *func_name, void **func_ptr); + + void *lib_ = {}; + sde_drm::GetDRMManager func_get_drm_manager_ = {}; + sde_drm::DestroyDRMManager func_destroy_drm_manager_ = {}; + bool is_loaded_ = false; + + static DRMLibLoader *s_instance; // Singleton instance + static std::mutex s_lock; +}; + +} // namespace drm_utils + +#endif // __DRM_LIB_LOADER_H__ diff --git a/libdrmutils/drm_logger.h b/libdrmutils/drm_logger.h index b332ea04..d0b07738 100644 --- a/libdrmutils/drm_logger.h +++ b/libdrmutils/drm_logger.h @@ -38,6 +38,7 @@ class DRMLogger { public: virtual ~DRMLogger() {} virtual void Error(const char *format, ...) = 0; + virtual void Warning(const char *format, ...) = 0; virtual void Info(const char *format, ...) = 0; virtual void Debug(const char *format, ...) = 0; @@ -48,28 +49,21 @@ class DRMLogger { static DRMLogger *s_instance; }; -template -void DRM_LOGE(const char *format, T&&... args) { - if (DRMLogger::Get()) { - DRMLogger::Get()->Error(format, std::forward(args)...); +#define DRM_LOG(method, format, ...) \ + if (drm_utils::DRMLogger::Get()) { \ + drm_utils::DRMLogger::Get()->method(format, ##__VA_ARGS__); \ } -} -template -void DRM_LOGI(const char *format, T&&... args) { - if (DRMLogger::Get()) { - DRMLogger::Get()->Info(format, std::forward(args)...); - } -} +#define DRM_LOG_CONTEXT(method, format, ...) \ + DRM_LOG(method, __CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__); -template -void DRM_LOGD_IF(bool pred, const char *format, T&&... args) { - if (pred && DRMLogger::Get()) { - DRMLogger::Get()->Debug(format, std::forward(args)...); - } -} +#define DRM_LOGE(format, ...) DRM_LOG_CONTEXT(Error, format, ##__VA_ARGS__) +#define DRM_LOGW(format, ...) DRM_LOG_CONTEXT(Warning, format, ##__VA_ARGS__) +#define DRM_LOGI(format, ...) DRM_LOG_CONTEXT(Info, format, ##__VA_ARGS__) +#define DRM_LOGD_IF(pred, format, ...) \ + if (pred) \ + DRM_LOG_CONTEXT(Debug, format, ##__VA_ARGS__) } // namespace drm_utils #endif // __DRM_LOGGER_H__ - diff --git a/libdrmutils/drm_master.cpp b/libdrmutils/drm_master.cpp index f6a2e41f..46ea24ef 100644 --- a/libdrmutils/drm_master.cpp +++ b/libdrmutils/drm_master.cpp @@ -27,13 +27,13 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include #include #include #include -#include #include #include @@ -74,7 +74,7 @@ int DRMMaster::GetInstance(DRMMaster **master) { int DRMMaster::Init() { dev_fd_ = drmOpen("msm_drm", nullptr); if (dev_fd_ < 0) { - DRM_LOGE("%s::%s: drmOpen failed with error %d", __CLASS__, __FUNCTION__, dev_fd_); + DRM_LOGE("drmOpen failed with error %d", dev_fd_); return -ENODEV; } @@ -89,7 +89,7 @@ DRMMaster::~DRMMaster() { int DRMMaster::CreateFbId(const DRMBuffer &drm_buffer, uint32_t *gem_handle, uint32_t *fb_id) { int ret = drmPrimeFDToHandle(dev_fd_, drm_buffer.fd, gem_handle); if (ret) { - DRM_LOGE("%s::%s: drmPrimeFDToHandle failed with error %d", __CLASS__, __FUNCTION__, ret); + DRM_LOGE("drmPrimeFDToHandle failed with error %d", ret); return ret; } @@ -106,7 +106,7 @@ int DRMMaster::CreateFbId(const DRMBuffer &drm_buffer, uint32_t *gem_handle, uin ret = drmModeAddFB3(dev_fd_, drm_buffer.width, drm_buffer.height, drm_buffer.drm_format, gem_handles, pitches, offsets, modifier, fb_id, DRM_MODE_FB_MODIFIERS); if (ret) { - DRM_LOGE("%s::%s: drmModeAddFB3 failed with error %d", __CLASS__, __FUNCTION__, ret); + DRM_LOGE("drmModeAddFB3 failed with error %d", ret); struct drm_gem_close gem_close = {}; gem_close.handle = *gem_handle; int ret1 = drmIoctl(dev_fd_, DRM_IOCTL_GEM_CLOSE, &gem_close); @@ -121,7 +121,7 @@ int DRMMaster::CreateFbId(const DRMBuffer &drm_buffer, uint32_t *gem_handle, uin int DRMMaster::RemoveFbId(uint32_t gem_handle, uint32_t fb_id) { int ret = drmModeRmFB(dev_fd_, fb_id); if (ret) { - DRM_LOGE("%s::%s: drmModeRmFB failed with error %d", __CLASS__, __FUNCTION__, ret); + DRM_LOGE("drmModeRmFB failed with error %d", ret); } struct drm_gem_close gem_close = {}; diff --git a/libdrmutils/drm_res_mgr.cpp b/libdrmutils/drm_res_mgr.cpp index 61d25c44..1d29495d 100644 --- a/libdrmutils/drm_res_mgr.cpp +++ b/libdrmutils/drm_res_mgr.cpp @@ -49,7 +49,7 @@ static bool GetConnector(int dev_fd, drmModeRes *res, drmModeConnector **connect if (conn && conn->connector_type == DRM_MODE_CONNECTOR_DSI && conn->count_modes && conn->connection == DRM_MODE_CONNECTED) { *connector = conn; - DRM_LOGI("drm_utils::%s found connector %d", __FUNCTION__, conn->connector_id); + DRM_LOGI("Found connector %d", conn->connector_id); return true; } } @@ -62,7 +62,7 @@ static bool GetEncoder(int dev_fd, drmModeConnector *conn, drmModeEncoder **enco drmModeEncoder *enc = drmModeGetEncoder(dev_fd, conn->encoders[i]); if (enc && enc->encoder_type == DRM_MODE_ENCODER_DSI) { *encoder = enc; - DRM_LOGI("drm_utils::%s found encoder %d", __FUNCTION__, enc->encoder_id); + DRM_LOGI("Found encoder %d", enc->encoder_id); return true; } } @@ -75,7 +75,7 @@ static bool GetCrtc(int dev_fd, drmModeRes *res, drmModeEncoder *enc, drmModeCrt drmModeCrtc *c = drmModeGetCrtc(dev_fd, res->crtcs[i]); if (c) { *crtc = c; - DRM_LOGI("drm_utils::%s found crtc %d", __FUNCTION__, c->crtc_id); + DRM_LOGI("Found crtc %d", c->crtc_id); return true; } } @@ -84,6 +84,8 @@ static bool GetCrtc(int dev_fd, drmModeRes *res, drmModeEncoder *enc, drmModeCrt return false; } +#define __CLASS__ "DRMResMgr" + int DRMResMgr::GetInstance(DRMResMgr **res_mgr) { lock_guard obj(s_lock); @@ -112,26 +114,26 @@ int DRMResMgr::Init() { master->GetHandle(&dev_fd); drmModeRes *res = drmModeGetResources(dev_fd); if (res == nullptr) { - DRM_LOGE("%s::%s: drmModeGetResources failed", __CLASS__, __FUNCTION__); + DRM_LOGE("drmModeGetResources failed"); return -ENODEV; } drmModeConnector *conn = nullptr; if (!GetConnector(dev_fd, res, &conn)) { - DRM_LOGE("%s::%s: Failed to find a connector", __CLASS__, __FUNCTION__); + DRM_LOGE("Failed to find a connector"); return -ENODEV; } drmModeEncoder *enc = nullptr; if (!GetEncoder(dev_fd, conn, &enc)) { - DRM_LOGE("%s::%s: Failed to find an encoder", __CLASS__, __FUNCTION__); + DRM_LOGE("Failed to find an encoder"); drmModeFreeConnector(conn); return -ENODEV; } drmModeCrtc *crtc = nullptr; if (!GetCrtc(dev_fd, res, enc, &crtc)) { - DRM_LOGE("%s::%s: Failed to find a crtc", __CLASS__, __FUNCTION__); + DRM_LOGE("Failed to find a crtc"); drmModeFreeEncoder(enc); drmModeFreeConnector(conn); drmModeFreeResources(res); diff --git a/sdm/.clang-format b/sdm/.clang-format deleted file mode 100644 index 9082c400..00000000 --- a/sdm/.clang-format +++ /dev/null @@ -1,13 +0,0 @@ ---- -Language: Cpp -BasedOnStyle: Google -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -AllowShortFunctionsOnASingleLine: Inline -AllowShortBlocksOnASingleLine: false -ColumnLimit: 100 -ConstructorInitializerAllOnOneLineOrOnePerLine: true -ConstructorInitializerIndentWidth: 4 -DerivePointerAlignment: false -PointerAlignment: Right -#ReflowComments: false diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk index 10d06aba..cdf89256 100644 --- a/sdm/libs/core/Android.mk +++ b/sdm/libs/core/Android.mk @@ -7,6 +7,9 @@ LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes) $(common_header_export_path) LOCAL_CFLAGS := -Wno-unused-parameter -DLOG_TAG=\"SDM\" \ $(common_flags) +ifeq ($(use_hwc2),false) + LOCAL_CFLAGS += -DUSE_SPECULATIVE_FENCES +endif LOCAL_HW_INTF_PATH_1 := fb LOCAL_SHARED_LIBRARIES := libdl libsdmutils diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp index 3b7c3157..a72aae7b 100644 --- a/sdm/libs/core/drm/hw_device_drm.cpp +++ b/sdm/libs/core/drm/hw_device_drm.cpp @@ -29,22 +29,23 @@ #define __STDC_FORMAT_MACROS -#include #include -#include +#include +#include +#include #include -#include -#include #include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include -#include -#include #include #include @@ -61,57 +62,103 @@ using std::to_string; using std::fstream; using drm_utils::DRMMaster; using drm_utils::DRMResMgr; -using drm_utils::DRMLogger; +using drm_utils::DRMLibLoader; +using sde_drm::GetDRMManager; +using sde_drm::DestroyDRMManager; +using sde_drm::DRMDisplayType; +using sde_drm::DRMDisplayToken; +using sde_drm::DRMConnectorInfo; +using sde_drm::DRMRect; +using sde_drm::DRMBlendType; +using sde_drm::DRMOps; +using sde_drm::DRMTopology; namespace sdm { -class DRMLoggerDAL : public DRMLogger { - public: -#define PRIV_LOG(suffix) { \ - char buf[1024]; \ - va_list list; \ - va_start(list, str); \ - vsnprintf(buf, sizeof(buf), str, list); \ - va_end(list); \ - DLOG##suffix("%s", buf); \ -} - void Error(const char *str, ...) { - PRIV_LOG(E); - } - void Info(const char *str, ...) { - PRIV_LOG(I); - } - void Debug(const char *str, ...) { - PRIV_LOG(D); - } -}; - HWDeviceDRM::HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf) - : hw_info_intf_(hw_info_intf), buffer_sync_handler_(buffer_sync_handler) { - DRMLogger::Set(new DRMLoggerDAL()); + : hw_info_intf_(hw_info_intf), buffer_sync_handler_(buffer_sync_handler) { + device_type_ = kDevicePrimary; + device_name_ = "Peripheral Display"; + hw_info_intf_ = hw_info_intf; } DisplayError HWDeviceDRM::Init() { - // Populate Panel Info (Used for Partial Update) + default_mode_ = (DRMLibLoader::GetInstance()->IsLoaded() == false); + + if (!default_mode_) { + DRMMaster *drm_master = {}; + int dev_fd = -1; + DRMMaster::GetInstance(&drm_master); + drm_master->GetHandle(&dev_fd); + DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_); + if (drm_mgr_intf_->RegisterDisplay(DRMDisplayType::PERIPHERAL, &token_)) { + DLOGE("RegisterDisplay failed"); + return kErrorResources; + } + + drm_mgr_intf_->CreateAtomicReq(token_, &drm_atomic_intf_); + drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_); + InitializeConfigs(); + drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, ¤t_mode_); +#ifdef USE_SPECULATIVE_FENCES + drm_atomic_intf_->Perform(DRMOps::CRTC_SET_OUTPUT_FENCE_OFFSET, token_.crtc_id, 1); +#endif + // TODO(user): Enable this and remove the one in SetupAtomic() onces underruns are fixed + // drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1); + // Commit to setup pipeline with mode, which then tells us the topology etc + if (drm_atomic_intf_->Commit(true /* synchronous */)) { + DLOGE("Setting up CRTC %d, Connector %d for %s failed", token_.crtc_id, token_.conn_id, + device_name_); + return kErrorResources; + } + + // Reload connector info for updated info after 1st commit + drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_); + DLOGI("Setup CRTC %d, Connector %d for %s", token_.crtc_id, token_.conn_id, device_name_); + } + + PopulateDisplayAttributes(); PopulateHWPanelInfo(); - // Populate HW Capabilities - hw_resource_ = HWResourceInfo(); + UpdateMixerAttributes(); hw_info_intf_->GetHWResourceInfo(&hw_resource_); - DRMResMgr *res_mgr = nullptr; - int ret = DRMResMgr::GetInstance(&res_mgr); - if (ret < 0) { - DLOGE("Failed to acquire DRMResMgr instance"); - return kErrorResources; - } + return kErrorNone; +} - // TODO(user): check if default mode enabled - drmModeModeInfo mode; - res_mgr->GetMode(&mode); +DisplayError HWDeviceDRM::Deinit() { + drm_mgr_intf_->DestroyAtomicReq(drm_atomic_intf_); + drm_atomic_intf_ = {}; + drm_mgr_intf_->UnregisterDisplay(token_); + return kErrorNone; +} +void HWDeviceDRM::InitializeConfigs() { + // TODO(user): Update modes + current_mode_ = connector_info_.modes[0]; +} + +DisplayError HWDeviceDRM::PopulateDisplayAttributes() { + drmModeModeInfo mode = {}; uint32_t mm_width = 0; uint32_t mm_height = 0; - res_mgr->GetDisplayDimInMM(&mm_width, &mm_height); + DRMTopology topology = DRMTopology::SINGLE_LM; + + if (default_mode_) { + DRMResMgr *res_mgr = nullptr; + int ret = DRMResMgr::GetInstance(&res_mgr); + if (ret < 0) { + DLOGE("Failed to acquire DRMResMgr instance"); + return kErrorResources; + } + + res_mgr->GetMode(&mode); + res_mgr->GetDisplayDimInMM(&mm_width, &mm_height); + } else { + mode = current_mode_; + mm_width = connector_info_.mmWidth; + mm_height = connector_info_.mmHeight; + topology = connector_info_.topology; + } display_attributes_.x_pixels = mode.hdisplay; display_attributes_.y_pixels = mode.vdisplay; @@ -135,19 +182,126 @@ DisplayError HWDeviceDRM::Init() { display_attributes_.h_total = mode.htotal; uint32_t h_blanking = mode.htotal - mode.hdisplay; - display_attributes_.is_device_split = true; + display_attributes_.is_device_split = + (topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_MERGE); display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0; - display_attributes_.x_dpi = - (FLOAT(mode.hdisplay) * 25.4f) / FLOAT(mm_width); - display_attributes_.y_dpi = - (FLOAT(mode.vdisplay) * 25.4f) / FLOAT(mm_height); + display_attributes_.x_dpi = (FLOAT(mode.hdisplay) * 25.4f) / FLOAT(mm_width); + display_attributes_.y_dpi = (FLOAT(mode.vdisplay) * 25.4f) / FLOAT(mm_height); return kErrorNone; } -DisplayError HWDeviceDRM::Deinit() { - return kErrorNone; +void HWDeviceDRM::PopulateHWPanelInfo() { + hw_panel_info_ = {}; + + snprintf(hw_panel_info_.panel_name, sizeof(hw_panel_info_.panel_name), "%s", + connector_info_.panel_name.c_str()); + hw_panel_info_.split_info.left_split = display_attributes_.x_pixels; + if (display_attributes_.is_device_split) { + hw_panel_info_.split_info.left_split = hw_panel_info_.split_info.right_split = + display_attributes_.x_pixels / 2; + } + + hw_panel_info_.partial_update = 0; + hw_panel_info_.left_align = 0; + hw_panel_info_.width_align = 0; + hw_panel_info_.top_align = 0; + hw_panel_info_.height_align = 0; + hw_panel_info_.min_roi_width = 0; + hw_panel_info_.min_roi_height = 0; + hw_panel_info_.needs_roi_merge = 0; + hw_panel_info_.dynamic_fps = connector_info_.dynamic_fps; + hw_panel_info_.min_fps = 60; + hw_panel_info_.max_fps = 60; + hw_panel_info_.is_primary_panel = connector_info_.is_primary; + hw_panel_info_.is_pluggable = 0; + + if (!default_mode_) { + hw_panel_info_.needs_roi_merge = (connector_info_.topology == DRMTopology::DUAL_LM_MERGE); + } + + GetHWDisplayPortAndMode(); + GetHWPanelMaxBrightness(); + + DLOGI("%s, Panel Interface = %s, Panel Mode = %s, Is Primary = %d", device_name_, + interface_str_.c_str(), hw_panel_info_.mode == kModeVideo ? "Video" : "Command", + hw_panel_info_.is_primary_panel); + DLOGI("Partial Update = %d, Dynamic FPS = %d", hw_panel_info_.partial_update, + hw_panel_info_.dynamic_fps); + DLOGI("Align: left = %d, width = %d, top = %d, height = %d", hw_panel_info_.left_align, + hw_panel_info_.width_align, hw_panel_info_.top_align, hw_panel_info_.height_align); + DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d", hw_panel_info_.min_roi_width, + hw_panel_info_.min_roi_height, hw_panel_info_.needs_roi_merge); + DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps); + DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split, + hw_panel_info_.split_info.right_split); +} + +void HWDeviceDRM::GetHWDisplayPortAndMode() { + hw_panel_info_.port = kPortDefault; + hw_panel_info_.mode = + (connector_info_.panel_mode == sde_drm::DRMPanelMode::VIDEO) ? kModeVideo : kModeCommand; + + if (default_mode_) { + return; + } + + switch (connector_info_.type) { + case DRM_MODE_CONNECTOR_DSI: + hw_panel_info_.port = kPortDSI; + interface_str_ = "DSI"; + break; + case DRM_MODE_CONNECTOR_LVDS: + hw_panel_info_.port = kPortLVDS; + interface_str_ = "LVDS"; + break; + case DRM_MODE_CONNECTOR_eDP: + hw_panel_info_.port = kPortEDP; + interface_str_ = "EDP"; + break; + case DRM_MODE_CONNECTOR_TV: + case DRM_MODE_CONNECTOR_HDMIA: + case DRM_MODE_CONNECTOR_HDMIB: + hw_panel_info_.port = kPortDTV; + interface_str_ = "HDMI"; + break; + case DRM_MODE_CONNECTOR_VIRTUAL: + hw_panel_info_.port = kPortWriteBack; + interface_str_ = "Virtual"; + break; + case DRM_MODE_CONNECTOR_DisplayPort: + // TODO(user): Add when available + interface_str_ = "DisplayPort"; + break; + } + + return; +} + +void HWDeviceDRM::GetHWPanelMaxBrightness() { + char brightness[kMaxStringLength] = {0}; + char kMaxBrightnessNode[64] = {0}; + + snprintf(kMaxBrightnessNode, sizeof(kMaxBrightnessNode), "%s", + "/sys/class/leds/lcd-backlight/max_brightness"); + + hw_panel_info_.panel_max_brightness = 255; + int fd = Sys::open_(kMaxBrightnessNode, O_RDONLY); + if (fd < 0) { + DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode, + strerror(errno)); + return; + } + + if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) { + hw_panel_info_.panel_max_brightness = atoi(brightness); + DLOGI("Max brightness level = %d", hw_panel_info_.panel_max_brightness); + } else { + DLOGW("Failed to read max brightness level. error = %s", strerror(errno)); + } + + Sys::close_(fd); } DisplayError HWDeviceDRM::GetActiveConfig(uint32_t *active_config) { @@ -204,13 +358,99 @@ DisplayError HWDeviceDRM::Standby() { return kErrorNone; } +void HWDeviceDRM::SetupAtomic(HWLayers *hw_layers, bool validate) { + if (default_mode_) { + return; + } + + HWLayersInfo &hw_layer_info = hw_layers->info; + uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size()); + + for (uint32_t i = 0; i < hw_layer_count; i++) { + Layer &layer = hw_layer_info.hw_layers.at(i); + LayerBuffer &input_buffer = layer.input_buffer; + HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe; + HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe; + + // TODO(user): Add support for solid fill + if (layer.flags.solid_fill) { + continue; + } + + for (uint32_t count = 0; count < 2; count++) { + HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe; + if (pipe_info->valid) { + uint32_t pipe_id = pipe_info->pipe_id; + if (input_buffer.fb_id == 0) { + // We set these to 0 to clear any previous cycle's state from another buffer. + // Unfortunately this layer will be skipped from validation because it's dimensions are + // tied to fb_id which is not available yet. + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_FB_ID, pipe_id, 0); + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_CRTC, pipe_id, 0); + continue; + } + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ALPHA, pipe_id, layer.plane_alpha); + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ZORDER, pipe_id, pipe_info->z_order); + DRMBlendType blending = {}; + SetBlending(layer.blending, &blending); + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_BLEND_TYPE, pipe_id, blending); + DRMRect src = {}; + SetRect(pipe_info->src_roi, &src); + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SRC_RECT, pipe_id, src); + DRMRect dst = {}; + SetRect(pipe_info->dst_roi, &dst); + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DST_RECT, pipe_id, dst); + uint32_t rot_bit_mask = 0; + if (layer.transform.flip_horizontal) { + rot_bit_mask |= 1 << DRM_REFLECT_X; + } + if (layer.transform.flip_vertical) { + rot_bit_mask |= 1 << DRM_REFLECT_Y; + } + + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_H_DECIMATION, pipe_id, + pipe_info->horizontal_decimation); + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_V_DECIMATION, pipe_id, + pipe_info->vertical_decimation); + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION, pipe_id, rot_bit_mask); + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_FB_ID, pipe_id, input_buffer.fb_id); + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_CRTC, pipe_id, token_.crtc_id); + if (!validate && input_buffer.acquire_fence_fd >= 0) { + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_INPUT_FENCE, pipe_id, + input_buffer.acquire_fence_fd); + } + } + } + + // TODO(user): Remove this and enable the one in Init() onces underruns are fixed + drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1); + } +} + DisplayError HWDeviceDRM::Validate(HWLayers *hw_layers) { DTRACE_SCOPED(); + SetupAtomic(hw_layers, true /* validate */); + + int ret = drm_atomic_intf_->Validate(); + if (ret) { + DLOGE("%s failed with error %d", __FUNCTION__, ret); + return kErrorHardware; + } + return kErrorNone; } DisplayError HWDeviceDRM::Commit(HWLayers *hw_layers) { DTRACE_SCOPED(); + if (default_mode_) { + return DefaultCommit(hw_layers); + } + + return AtomicCommit(hw_layers); +} + +DisplayError HWDeviceDRM::DefaultCommit(HWLayers *hw_layers) { + DTRACE_SCOPED(); HWLayersInfo &hw_layer_info = hw_layers->info; LayerStack *stack = hw_layer_info.stack; @@ -258,126 +498,67 @@ DisplayError HWDeviceDRM::Commit(HWLayers *hw_layers) { return kErrorNone; } -DisplayError HWDeviceDRM::Flush() { - return kErrorNone; -} - -void HWDeviceDRM::PopulateHWPanelInfo() { - hw_panel_info_ = HWPanelInfo(); - GetHWPanelInfoByNode(0 /* Primary */, &hw_panel_info_); - DLOGI("Device type = %d, Display Port = %d, Display Mode = %d, Device Node = %d, Is Primary = %d", - device_type_, hw_panel_info_.port, hw_panel_info_.mode, 0 /* primary */, - hw_panel_info_.is_primary_panel); - DLOGI("Partial Update = %d, Dynamic FPS = %d", - hw_panel_info_.partial_update, hw_panel_info_.dynamic_fps); - DLOGI("Align: left = %d, width = %d, top = %d, height = %d", - hw_panel_info_.left_align, hw_panel_info_.width_align, - hw_panel_info_.top_align, hw_panel_info_.height_align); - DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d", - hw_panel_info_.min_roi_width, hw_panel_info_.min_roi_height, - hw_panel_info_.needs_roi_merge); - DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps); - DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split, - hw_panel_info_.split_info.right_split); -} +DisplayError HWDeviceDRM::AtomicCommit(HWLayers *hw_layers) { + DTRACE_SCOPED(); + SetupAtomic(hw_layers, false /* validate */); -void HWDeviceDRM::GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info) { - snprintf(panel_info->panel_name, sizeof(panel_info->panel_name), "%s", - "Dual SHARP video mode dsi panel"); -} - -void HWDeviceDRM::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) { - panel_info->partial_update = 0; - panel_info->left_align = 0; - panel_info->width_align = 0; - panel_info->top_align = 0; - panel_info->height_align = 0; - panel_info->min_roi_width = 0; - panel_info->min_roi_height = 0; - panel_info->needs_roi_merge = 0; - panel_info->dynamic_fps = 0; - panel_info->min_fps = 60; - panel_info->max_fps = 60; - panel_info->is_primary_panel = 1; - panel_info->is_pluggable = 0; - - GetHWDisplayPortAndMode(device_node, panel_info); - GetSplitInfo(device_node, panel_info); - GetHWPanelNameByNode(device_node, panel_info); - GetHWPanelMaxBrightnessFromNode(panel_info); -} - -void HWDeviceDRM::GetHWDisplayPortAndMode(int device_node, HWPanelInfo *panel_info) { - DisplayPort *port = &panel_info->port; - HWDisplayMode *mode = &panel_info->mode; - - *port = kPortDefault; - *mode = kModeDefault; - - string line = "mipi dsi video panel"; - - if ((strncmp(line.c_str(), "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) { - *port = kPortDSI; - *mode = kModeCommand; - } else if ((strncmp(line.c_str(), "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) { - *port = kPortDSI; - *mode = kModeVideo; - } else if ((strncmp(line.c_str(), "lvds panel", strlen("lvds panel")) == 0)) { - *port = kPortLVDS; - *mode = kModeVideo; - } else if ((strncmp(line.c_str(), "edp panel", strlen("edp panel")) == 0)) { - *port = kPortEDP; - *mode = kModeVideo; - } else if ((strncmp(line.c_str(), "dtv panel", strlen("dtv panel")) == 0)) { - *port = kPortDTV; - *mode = kModeVideo; - } else if ((strncmp(line.c_str(), "writeback panel", strlen("writeback panel")) == 0)) { - *port = kPortWriteBack; - *mode = kModeCommand; + int ret = drm_atomic_intf_->Commit(false /* synchronous */); + if (ret) { + DLOGE("%s failed with error %d", __FUNCTION__, ret); + return kErrorHardware; } - return; -} + int release_fence = -1; + int retire_fence = -1; -void HWDeviceDRM::GetSplitInfo(int device_node, HWPanelInfo *panel_info) { - if (display_attributes_.is_device_split) { - panel_info->split_info.left_split = panel_info->split_info.right_split = - display_attributes_.x_pixels / 2; + drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence); + drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE, token_.conn_id, &retire_fence); + + HWLayersInfo &hw_layer_info = hw_layers->info; + LayerStack *stack = hw_layer_info.stack; + stack->retire_fence_fd = retire_fence; + + for (Layer &layer : hw_layer_info.hw_layers) { + layer.input_buffer.release_fence_fd = Sys::dup_(release_fence); } -} -void HWDeviceDRM::GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info) { - char brightness[kMaxStringLength] = { 0 }; - char kMaxBrightnessNode[64] = { 0 }; + hw_layer_info.sync_handle = release_fence; - snprintf(kMaxBrightnessNode, sizeof(kMaxBrightnessNode), "%s", - "/sys/class/leds/lcd-backlight/max_brightness"); + return kErrorNone; +} - panel_info->panel_max_brightness = 0; - int fd = Sys::open_(kMaxBrightnessNode, O_RDONLY); - if (fd < 0) { - DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode, - strerror(errno)); - return; - } +DisplayError HWDeviceDRM::Flush() { + return kErrorNone; +} - if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) { - panel_info->panel_max_brightness = atoi(brightness); - DLOGI("Max brightness level = %d", panel_info->panel_max_brightness); - } else { - DLOGW("Failed to read max brightness level. error = %s", strerror(errno)); +void HWDeviceDRM::SetBlending(const LayerBlending &source, DRMBlendType *target) { + switch (source) { + case kBlendingPremultiplied: + *target = DRMBlendType::PREMULTIPLIED; + break; + case kBlendingOpaque: + *target = DRMBlendType::OPAQUE; + break; + case kBlendingCoverage: + *target = DRMBlendType::COVERAGE; + break; + default: + *target = DRMBlendType::UNDEFINED; } - Sys::close_(fd); +} - panel_info->panel_max_brightness = 255; +void HWDeviceDRM::SetRect(const LayerRect &source, DRMRect *target) { + target->left = UINT32(source.left); + target->top = UINT32(source.top); + target->right = UINT32(source.right); + target->bottom = UINT32(source.bottom); } bool HWDeviceDRM::EnableHotPlugDetection(int enable) { return true; } -void HWDeviceDRM::ResetDisplayParams() { -} +void HWDeviceDRM::ResetDisplayParams() {} DisplayError HWDeviceDRM::SetCursorPosition(HWLayers *hw_layers, int x, int y) { DTRACE_SCOPED(); @@ -396,8 +577,7 @@ DisplayError HWDeviceDRM::SetVSyncState(bool enable) { return kErrorNone; } -void HWDeviceDRM::SetIdleTimeoutMs(uint32_t timeout_ms) { -} +void HWDeviceDRM::SetIdleTimeoutMs(uint32_t timeout_ms) {} DisplayError HWDeviceDRM::SetDisplayMode(const HWDisplayMode hw_display_mode) { return kErrorNotSupported; @@ -465,7 +645,7 @@ DisplayError HWDeviceDRM::SetMixerAttributes(const HWMixerAttributes &mixer_attr float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height); float display_aspect_ratio = - FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels); + FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels); if (display_aspect_ratio != mixer_aspect_ratio) { DLOGW("Aspect ratio mismatch! input: res %dx%d display: res %dx%d", mixer_attributes.width, @@ -477,8 +657,10 @@ DisplayError HWDeviceDRM::SetMixerAttributes(const HWMixerAttributes &mixer_attr float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height); float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up; if (scale_x > max_scale_up || scale_y > max_scale_up) { - DLOGW("Up scaling ratio exceeds for destination scalar upscale limit scale_x %f scale_y %f " \ - "max_scale_up %f", scale_x, scale_y, max_scale_up); + DLOGW( + "Up scaling ratio exceeds for destination scalar upscale limit scale_x %f scale_y %f " + "max_scale_up %f", + scale_x, scale_y, max_scale_up); return kErrorNotSupported; } @@ -500,11 +682,20 @@ DisplayError HWDeviceDRM::GetMixerAttributes(HWMixerAttributes *mixer_attributes mixer_attributes_.width = display_attributes_.x_pixels; mixer_attributes_.height = display_attributes_.y_pixels; - mixer_attributes_.split_left = display_attributes_.is_device_split ? - hw_panel_info_.split_info.left_split : mixer_attributes_.width; + mixer_attributes_.split_left = display_attributes_.is_device_split + ? hw_panel_info_.split_info.left_split + : mixer_attributes_.width; *mixer_attributes = mixer_attributes_; return kErrorNone; } +void HWDeviceDRM::UpdateMixerAttributes() { + mixer_attributes_.width = display_attributes_.x_pixels; + mixer_attributes_.height = display_attributes_.y_pixels; + mixer_attributes_.split_left = display_attributes_.is_device_split + ? hw_panel_info_.split_info.left_split + : mixer_attributes_.width; +} + } // namespace sdm diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h index d4b984d1..db135a03 100644 --- a/sdm/libs/core/drm/hw_device_drm.h +++ b/sdm/libs/core/drm/hw_device_drm.h @@ -30,15 +30,17 @@ #ifndef __HW_DEVICE_DRM_H__ #define __HW_DEVICE_DRM_H__ +#include #include #include #include +#include #include #include "hw_interface.h" -#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, \ - type, errno, strerror(errno)) +#define IOCTL_LOGE(ioctl, type) \ + DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, type, errno, strerror(errno)) namespace sdm { class HWInfoInterface; @@ -96,29 +98,38 @@ class HWDeviceDRM : public HWInterface { static const int kNumPhysicalDisplays = 2; DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target); - DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format, - uint32_t width, uint32_t *target); + DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format, uint32_t width, + uint32_t *target); + DisplayError PopulateDisplayAttributes(); void PopulateHWPanelInfo(); - void GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info); - void GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info); - void GetHWDisplayPortAndMode(int device_node, HWPanelInfo *panel_info); - void GetSplitInfo(int device_node, HWPanelInfo *panel_info); - void GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info); - int ParseLine(const char *input, char *tokens[], const uint32_t max_token, uint32_t *count); - int ParseLine(const char *input, const char *delim, char *tokens[], - const uint32_t max_token, uint32_t *count); + void GetHWDisplayPortAndMode(); + void GetHWPanelMaxBrightness(); void ResetDisplayParams(); bool EnableHotPlugDetection(int enable); + void UpdateMixerAttributes(); + void InitializeConfigs(); + void SetBlending(const LayerBlending &source, sde_drm::DRMBlendType *target); + void SetRect(const LayerRect &source, sde_drm::DRMRect *target); + DisplayError DefaultCommit(HWLayers *hw_layers); + DisplayError AtomicCommit(HWLayers *hw_layers); + void SetupAtomic(HWLayers *hw_layers, bool validate); - HWResourceInfo hw_resource_; - HWPanelInfo hw_panel_info_; - HWInfoInterface *hw_info_intf_; - BufferSyncHandler *buffer_sync_handler_; - HWDeviceType device_type_; - const char *device_name_; + HWResourceInfo hw_resource_ = {}; + HWPanelInfo hw_panel_info_ = {}; + HWInfoInterface *hw_info_intf_ = {}; + BufferSyncHandler *buffer_sync_handler_ = {}; + HWDeviceType device_type_ = {}; + const char *device_name_ = {}; bool synchronous_commit_ = false; HWDisplayAttributes display_attributes_ = {}; HWMixerAttributes mixer_attributes_ = {}; + sde_drm::DRMManagerInterface *drm_mgr_intf_ = {}; + sde_drm::DRMAtomicReqInterface *drm_atomic_intf_ = {}; + sde_drm::DRMDisplayToken token_ = {}; + drmModeModeInfo current_mode_ = {}; + bool default_mode_ = false; + sde_drm::DRMConnectorInfo connector_info_ = {}; + std::string interface_str_ = "DSI"; }; } // namespace sdm diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp index 78b598ed..3fb87d36 100644 --- a/sdm/libs/core/drm/hw_info_drm.cpp +++ b/sdm/libs/core/drm/hw_info_drm.cpp @@ -27,21 +27,24 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include +#include +#include +#include +#include #include #include -#include +#include #include #include #include #include #include -#include -#include #include -#include #include +#include #include #include #include @@ -52,6 +55,15 @@ #define __CLASS__ "HWInfoDRM" +using drm_utils::DRMMaster; +using drm_utils::DRMResMgr; +using drm_utils::DRMLogger; +using drm_utils::DRMLibLoader; +using sde_drm::GetDRMManager; +using sde_drm::DRMPlanesInfo; +using sde_drm::DRMCrtcInfo; +using sde_drm::DRMPlaneType; + using std::vector; using std::map; using std::string; @@ -60,22 +72,40 @@ using std::to_string; namespace sdm { -int HWInfoDRM::ParseString(const char *input, char *tokens[], const uint32_t max_token, - const char *delim, uint32_t *count) { - char *tmp_token = NULL; - char *temp_ptr; - uint32_t index = 0; - if (!input) { - return -1; - } - tmp_token = strtok_r(const_cast(input), delim, &temp_ptr); - while (tmp_token && index < max_token) { - tokens[index++] = tmp_token; - tmp_token = strtok_r(NULL, delim, &temp_ptr); - } - *count = index; +class DRMLoggerImpl : public DRMLogger { + public: +#define PRINTLOG(method, format, buf) \ + va_list list; \ + va_start(list, format); \ + vsnprintf(buf, sizeof(buf), format, list); \ + va_end(list); \ + Debug::Get()->method(kTagNone, "%s", buf); + + void Error(const char *format, ...) { PRINTLOG(Error, format, buf_); } + void Warning(const char *format, ...) { PRINTLOG(Warning, format, buf_); } + void Info(const char *format, ...) { PRINTLOG(Info, format, buf_); } + void Debug(const char *format, ...) { PRINTLOG(Debug, format, buf_); } + + private: + char buf_[1024] = {}; +}; - return 0; +HWResourceInfo *HWInfoDRM::hw_resource_ = nullptr; + +HWInfoDRM::HWInfoDRM() { + DRMLogger::Set(new DRMLoggerImpl()); + default_mode_ = (DRMLibLoader::GetInstance()->IsLoaded() == false); + if (!default_mode_) { + DRMMaster *drm_master = {}; + int dev_fd = -1; + DRMMaster::GetInstance(&drm_master); + if (!drm_master) { + DLOGE("Failed to acquire DRMMaster instance"); + return; + } + drm_master->GetHandle(&dev_fd); + DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_); + } } DisplayError HWInfoDRM::GetDynamicBWLimits(HWResourceInfo *hw_resource) { @@ -89,17 +119,19 @@ DisplayError HWInfoDRM::GetDynamicBWLimits(HWResourceInfo *hw_resource) { } DisplayError HWInfoDRM::GetHWResourceInfo(HWResourceInfo *hw_resource) { - InitSupportedFormatMap(hw_resource); - hw_resource->hw_version = kHWMdssVersion5; - hw_resource->hw_revision = 268894210; // HW Rev, v1/v2 - hw_resource->num_blending_stages = 7; - hw_resource->max_scale_down = 4; - hw_resource->max_scale_up = 20; - hw_resource->max_bandwidth_low = 9600000; - hw_resource->max_bandwidth_high = 9600000; - hw_resource->max_mixer_width = 2560; + if (hw_resource_) { + *hw_resource = *hw_resource_; + return kErrorNone; + } + + hw_resource->num_blending_stages = 1; hw_resource->max_pipe_width = 2560; hw_resource->max_cursor_size = 128; + hw_resource->max_scale_down = 1; + hw_resource->max_scale_up = 1; + hw_resource->has_decimation = false; + hw_resource->max_bandwidth_low = 9600000; + hw_resource->max_bandwidth_high = 9600000; hw_resource->max_pipe_bw = 4500000; hw_resource->max_sde_clk = 412500000; hw_resource->clk_fudge_factor = FLOAT(105) / FLOAT(100); @@ -110,35 +142,30 @@ DisplayError HWInfoDRM::GetHWResourceInfo(HWResourceInfo *hw_resource) { hw_resource->extra_fudge_factor = 2; hw_resource->amortizable_threshold = 0; hw_resource->system_overhead_lines = 0; - hw_resource->writeback_index = 2; hw_resource->hw_dest_scalar_info.count = 0; hw_resource->hw_dest_scalar_info.max_scale_up = 0; hw_resource->hw_dest_scalar_info.max_input_width = 0; hw_resource->hw_dest_scalar_info.max_output_width = 0; - hw_resource->has_bwc = false; - hw_resource->has_ubwc = true; - hw_resource->has_decimation = true; - hw_resource->has_macrotile = true; hw_resource->is_src_split = true; - hw_resource->has_non_scalar_rgb = false; hw_resource->perf_calc = false; hw_resource->has_dyn_bw_support = false; - hw_resource->separate_rotator = true; hw_resource->has_qseed3 = false; hw_resource->has_concurrent_writeback = false; - hw_resource->num_vig_pipe = 0; - hw_resource->num_dma_pipe = 0; - hw_resource->num_cursor_pipe = 0; - uint32_t pipe_count = 2; - for (uint32_t i = 0; i < pipe_count; i++) { - HWPipeCaps pipe_caps; - pipe_caps.type = kPipeTypeUnused; - pipe_caps.type = kPipeTypeRGB; - hw_resource->num_rgb_pipe++; - pipe_caps.id = UINT32(0x8 << i); - pipe_caps.max_rects = 1; - hw_resource->hw_pipes.push_back(pipe_caps); - } + + // TODO(user): Deprecate + hw_resource->hw_version = kHWMdssVersion5; + hw_resource->hw_revision = 0; + hw_resource->max_mixer_width = 0; + hw_resource->writeback_index = 0; + hw_resource->has_bwc = false; + hw_resource->has_ubwc = true; + hw_resource->has_macrotile = true; + hw_resource->separate_rotator = true; + hw_resource->has_non_scalar_rgb = false; + + GetSystemInfo(hw_resource); + GetHWPlanesInfo(hw_resource); + GetWBInfo(hw_resource); // Disable destination scalar count to 0 if extension library is not present DynLib extension_lib; @@ -146,33 +173,32 @@ DisplayError HWInfoDRM::GetHWResourceInfo(HWResourceInfo *hw_resource) { hw_resource->hw_dest_scalar_info.count = 0; } - DLOGI("SDE Version = %d, SDE Revision = %x, RGB = %d, VIG = %d, DMA = %d, Cursor = %d", - hw_resource->hw_version, hw_resource->hw_revision, hw_resource->num_rgb_pipe, - hw_resource->num_vig_pipe, hw_resource->num_dma_pipe, hw_resource->num_cursor_pipe); - DLOGI("Upscale Ratio = %d, Downscale Ratio = %d, Blending Stages = %d", hw_resource->max_scale_up, - hw_resource->max_scale_down, hw_resource->num_blending_stages); - DLOGI("SourceSplit = %d QSEED3 = %d", hw_resource->is_src_split, hw_resource->has_qseed3); - DLOGI("BWC = %d, UBWC = %d, Decimation = %d, Tile Format = %d Concurrent Writeback = %d", - hw_resource->has_bwc, hw_resource->has_ubwc, hw_resource->has_decimation, - hw_resource->has_macrotile, hw_resource->has_concurrent_writeback); - DLOGI("MaxLowBw = %" PRIu64 " , MaxHighBw = % " PRIu64 "", hw_resource->max_bandwidth_low, - hw_resource->max_bandwidth_high); - DLOGI("MaxPipeBw = %" PRIu64 " KBps, MaxSDEClock = % " PRIu64 " Hz, ClockFudgeFactor = %f", - hw_resource->max_pipe_bw, hw_resource->max_sde_clk, hw_resource->clk_fudge_factor); - DLOGI("Prefill factors: Tiled_NV12 = %d, Tiled = %d, Linear = %d, Scale = %d, Fudge_factor = %d", - hw_resource->macrotile_nv12_factor, hw_resource->macrotile_factor, - hw_resource->linear_factor, hw_resource->scale_factor, hw_resource->extra_fudge_factor); + DLOGI("Max plane width = %d", hw_resource->max_pipe_width); + DLOGI("Max cursor width = %d", hw_resource->max_cursor_size); + DLOGI("Max plane upscale = %d", hw_resource->max_scale_up); + DLOGI("Max plane downscale = %d", hw_resource->max_scale_down); + DLOGI("Has Decimation = %d", hw_resource->has_decimation); + DLOGI("Max Blending Stages = %d", hw_resource->num_blending_stages); + DLOGI("Has Source Split = %d", hw_resource->is_src_split); + DLOGI("Has QSEED3 = %d", hw_resource->has_qseed3); + DLOGI("Has UBWC = %d", hw_resource->has_ubwc); + DLOGI("Has Concurrent Writeback = %d", hw_resource->has_concurrent_writeback); + DLOGI("Max Low Bw = %" PRIu64 "", hw_resource->max_bandwidth_low); + DLOGI("Max High Bw = % " PRIu64 "", hw_resource->max_bandwidth_high); + DLOGI("Max Pipe Bw = %" PRIu64 " KBps", hw_resource->max_pipe_bw); + DLOGI("MaxSDEClock = % " PRIu64 " Hz", hw_resource->max_sde_clk); + DLOGI("Clock Fudge Factor = %f", hw_resource->clk_fudge_factor); + DLOGI("Prefill factors:"); + DLOGI("\tTiled_NV12 = %d", hw_resource->macrotile_nv12_factor); + DLOGI("\tTiled = %d", hw_resource->macrotile_factor); + DLOGI("\tLinear = %d", hw_resource->linear_factor); + DLOGI("\tScale = %d", hw_resource->scale_factor); + DLOGI("\tFudge_factor = %d", hw_resource->extra_fudge_factor); if (hw_resource->separate_rotator || hw_resource->num_dma_pipe) { GetHWRotatorInfo(hw_resource); } - // If the driver doesn't spell out the wb index, assume it to be the number of rotators, - // based on legacy implementation. - if (hw_resource->writeback_index == kHWBlockMax) { - hw_resource->writeback_index = hw_resource->hw_rot_info.num_rotator; - } - if (hw_resource->has_dyn_bw_support) { DisplayError ret = GetDynamicBWLimits(hw_resource); if (ret != kErrorNone) { @@ -182,15 +208,130 @@ DisplayError HWInfoDRM::GetHWResourceInfo(HWResourceInfo *hw_resource) { DLOGI("Has Support for multiple bw limits shown below"); for (int index = 0; index < kBwModeMax; index++) { - DLOGI("Mode-index=%d total_bw_limit=%d and pipe_bw_limit=%d", - index, hw_resource->dyn_bw_info.total_bw_limit[index], + DLOGI("Mode-index=%d total_bw_limit=%d and pipe_bw_limit=%d", index, + hw_resource->dyn_bw_info.total_bw_limit[index], hw_resource->dyn_bw_info.pipe_bw_limit[index]); } } + if (!hw_resource_) { + hw_resource_ = new HWResourceInfo(); + *hw_resource_ = *hw_resource; + } + return kErrorNone; } +void HWInfoDRM::GetSystemInfo(HWResourceInfo *hw_resource) { + DRMCrtcInfo info; + drm_mgr_intf_->GetCrtcInfo(0 /* system_info */, &info); + hw_resource->is_src_split = info.has_src_split; + hw_resource->has_qseed3 = (info.qseed_version == sde_drm::QSEEDVersion::V3); + hw_resource->num_blending_stages = info.max_blend_stages; +} + +void HWInfoDRM::GetHWPlanesInfo(HWResourceInfo *hw_resource) { + DRMPlanesInfo info; + drm_mgr_intf_->GetPlanesInfo(&info); + for (auto &pipe_obj : info.planes) { + HWPipeCaps pipe_caps; + string name = {}; + switch (pipe_obj.second) { + case DRMPlaneType::RGB: + pipe_caps.type = kPipeTypeRGB; + hw_resource->num_rgb_pipe++; + name = "RGB"; + break; + case DRMPlaneType::VIG: + pipe_caps.type = kPipeTypeVIG; + hw_resource->num_vig_pipe++; + name = "VIG"; + break; + case DRMPlaneType::DMA: + pipe_caps.type = kPipeTypeDMA; + hw_resource->num_dma_pipe++; + name = "DMA"; + break; + case DRMPlaneType::CURSOR: + pipe_caps.type = kPipeTypeCursor; + hw_resource->num_cursor_pipe++; + name = "CURSOR"; + break; + default: + break; + } + pipe_caps.id = pipe_obj.first; + pipe_caps.max_rects = 1; + DLOGI("%s Pipe : Id %d", name.c_str(), pipe_obj.first); + hw_resource->hw_pipes.push_back(std::move(pipe_caps)); + } + + for (auto &pipe_type : info.types) { + vector supported_sdm_formats = {}; + for (auto &fmts : pipe_type.second.formats_supported) { + GetSDMFormat(fmts.first, fmts.second, &supported_sdm_formats); + } + + HWSubBlockType sub_blk_type = kHWSubBlockMax; + switch (pipe_type.first) { + case DRMPlaneType::RGB: + sub_blk_type = kHWRGBPipe; + // These properties are per plane but modeled in SDM as system-wide. + hw_resource->max_pipe_width = pipe_type.second.max_linewidth; + hw_resource->max_scale_down = pipe_type.second.max_downscale; + hw_resource->max_scale_up = pipe_type.second.max_upscale; + hw_resource->has_decimation = + pipe_type.second.max_horizontal_deci > 1 && pipe_type.second.max_vertical_deci > 1; + break; + case DRMPlaneType::VIG: + sub_blk_type = kHWVIGPipe; + // These properties are per plane but modeled in SDM as system-wide. + hw_resource->max_pipe_width = pipe_type.second.max_linewidth; + hw_resource->max_scale_down = pipe_type.second.max_downscale; + hw_resource->max_scale_up = pipe_type.second.max_upscale; + hw_resource->has_decimation = + pipe_type.second.max_horizontal_deci > 1 && pipe_type.second.max_vertical_deci > 1; + break; + case DRMPlaneType::DMA: + sub_blk_type = kHWDMAPipe; + break; + case DRMPlaneType::CURSOR: + sub_blk_type = kHWCursorPipe; + hw_resource->max_cursor_size = pipe_type.second.max_linewidth; + break; + default: + break; + } + + if (sub_blk_type != kHWSubBlockMax) { + hw_resource->supported_formats_map.erase(sub_blk_type); + hw_resource->supported_formats_map.insert(make_pair(sub_blk_type, supported_sdm_formats)); + } + } +} + +void HWInfoDRM::GetWBInfo(HWResourceInfo *hw_resource) { + HWSubBlockType sub_blk_type = kHWWBIntfOutput; + vector supported_sdm_formats = {}; + sde_drm::DRMDisplayToken token; + + // Fake register + if (drm_mgr_intf_->RegisterDisplay(sde_drm::DRMDisplayType::VIRTUAL, &token)) { + return; + } + + sde_drm::DRMConnectorInfo connector_info; + drm_mgr_intf_->GetConnectorInfo(token.conn_id, &connector_info); + for (auto &fmts : connector_info.formats_supported) { + GetSDMFormat(fmts.first, fmts.second, &supported_sdm_formats); + } + + hw_resource->supported_formats_map.erase(sub_blk_type); + hw_resource->supported_formats_map.insert(make_pair(sub_blk_type, supported_sdm_formats)); + + drm_mgr_intf_->UnregisterDisplay(token); +} + DisplayError HWInfoDRM::GetHWRotatorInfo(HWResourceInfo *hw_resource) { const uint32_t kMaxV4L2Nodes = 64; bool found = false; @@ -203,14 +344,13 @@ DisplayError HWInfoDRM::GetHWRotatorInfo(HWResourceInfo *hw_resource) { } string line; - if (Sys::getline_(fs, line) && - (!strncmp(line.c_str(), "sde_rotator", strlen("sde_rotator")))) { - hw_resource->hw_rot_info.device_path = string("/dev/video" + to_string(i)); - hw_resource->hw_rot_info.num_rotator++; - hw_resource->hw_rot_info.type = HWRotatorInfo::ROT_TYPE_V4L2; - hw_resource->hw_rot_info.has_downscale = true; - // We support only 1 rotator - found = true; + if (Sys::getline_(fs, line) && (!strncmp(line.c_str(), "sde_rotator", strlen("sde_rotator")))) { + hw_resource->hw_rot_info.device_path = string("/dev/video" + to_string(i)); + hw_resource->hw_rot_info.num_rotator++; + hw_resource->hw_rot_info.type = HWRotatorInfo::ROT_TYPE_V4L2; + hw_resource->hw_rot_info.has_downscale = true; + // We support only 1 rotator + found = true; } } @@ -220,33 +360,97 @@ DisplayError HWInfoDRM::GetHWRotatorInfo(HWResourceInfo *hw_resource) { return kErrorNone; } -LayerBufferFormat HWInfoDRM::GetSDMFormat(uint32_t drm_format, uint32_t drm_format_modifier) { +void HWInfoDRM::GetSDMFormat(uint32_t drm_format, uint64_t drm_format_modifier, + vector *sdm_formats) { + vector &fmts(*sdm_formats); switch (drm_format) { - case DRM_FORMAT_RGBA8888: return kFormatRGBA8888; - default: return kFormatInvalid; + case DRM_FORMAT_ARGB8888: + fmts.push_back(kFormatARGB8888); + break; + case DRM_FORMAT_RGBA8888: + fmts.push_back(drm_format_modifier ? kFormatRGBA8888Ubwc : kFormatRGBA8888); + break; + case DRM_FORMAT_BGRA8888: + fmts.push_back(kFormatBGRA8888); + break; + case DRM_FORMAT_XRGB8888: + fmts.push_back(kFormatXRGB8888); + break; + case DRM_FORMAT_RGBX8888: + fmts.push_back(drm_format_modifier ? kFormatRGBX8888Ubwc : kFormatRGBX8888); + break; + case DRM_FORMAT_BGRX8888: + fmts.push_back(kFormatBGRX8888); + break; + case DRM_FORMAT_RGBA5551: + fmts.push_back(kFormatRGBA5551); + break; + case DRM_FORMAT_RGBA4444: + fmts.push_back(kFormatRGBA4444); + break; + case DRM_FORMAT_RGB888: + fmts.push_back(kFormatRGB888); + break; + case DRM_FORMAT_BGR888: + fmts.push_back(kFormatBGR888); + break; + case DRM_FORMAT_RGB565: + fmts.push_back(drm_format_modifier ? kFormatBGR565Ubwc : kFormatBGR565); + break; + case DRM_FORMAT_BGR565: + fmts.push_back(kFormatBGR565); + break; + case DRM_FORMAT_RGBA1010102: + fmts.push_back(drm_format_modifier ? kFormatRGBA1010102Ubwc : kFormatRGBA1010102); + break; + case DRM_FORMAT_ARGB2101010: + fmts.push_back(kFormatARGB2101010); + break; + case DRM_FORMAT_RGBX1010102: + fmts.push_back(drm_format_modifier ? kFormatRGBX1010102Ubwc : kFormatRGBX1010102); + break; + case DRM_FORMAT_XRGB2101010: + fmts.push_back(kFormatXRGB2101010); + break; + case DRM_FORMAT_BGRA1010102: + fmts.push_back(kFormatBGRA1010102); + break; + case DRM_FORMAT_ABGR2101010: + fmts.push_back(kFormatABGR2101010); + break; + case DRM_FORMAT_BGRX1010102: + fmts.push_back(kFormatBGRX1010102); + break; + case DRM_FORMAT_XBGR2101010: + fmts.push_back(kFormatXBGR2101010); + break; + /* case DRM_FORMAT_P010: + fmts.push_back(drm_format_modifier == (DRM_FORMAT_MOD_QCOM_COMPRESSED | + DRM_FORMAT_MOD_QCOM_TIGHT) ? + kFormatYCbCr420TP10Ubwc : kFormatYCbCr420P010; */ + case DRM_FORMAT_YVU420: + fmts.push_back(kFormatYCrCb420PlanarStride16); + break; + case DRM_FORMAT_NV12: + if (drm_format_modifier) { + fmts.push_back(kFormatYCbCr420SPVenusUbwc); + } else { + fmts.push_back(kFormatYCbCr420SemiPlanarVenus); + fmts.push_back(kFormatYCbCr420SemiPlanar); + } + break; + case DRM_FORMAT_NV21: + fmts.push_back(kFormatYCrCb420SemiPlanarVenus); + fmts.push_back(kFormatYCrCb420SemiPlanar); + break; + case DRM_FORMAT_NV16: + fmts.push_back(kFormatYCbCr422H2V1SemiPlanar); + break; + default: + break; } } -void HWInfoDRM::InitSupportedFormatMap(HWResourceInfo *hw_resource) { - hw_resource->supported_formats_map.clear(); - - for (int sub_blk_type = INT(kHWVIGPipe); sub_blk_type < INT(kHWSubBlockMax); sub_blk_type++) { - PopulateSupportedFormatMap((HWSubBlockType)sub_blk_type, hw_resource); - } -} - -void HWInfoDRM::PopulateSupportedFormatMap(HWSubBlockType sub_blk_type, - HWResourceInfo *hw_resource) { - vector supported_sdm_formats; - LayerBufferFormat sdm_format = kFormatRGBA8888; // GetSDMFormat(INT(mdp_format)); - if (sdm_format != kFormatInvalid) { - supported_sdm_formats.push_back(sdm_format); - } - - hw_resource->supported_formats_map.erase(sub_blk_type); - hw_resource->supported_formats_map.insert(make_pair(sub_blk_type, supported_sdm_formats)); -} - DisplayError HWInfoDRM::GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) { hw_disp_info->type = kPrimary; hw_disp_info->is_connected = true; diff --git a/sdm/libs/core/drm/hw_info_drm.h b/sdm/libs/core/drm/hw_info_drm.h index 51560935..143cbdf3 100644 --- a/sdm/libs/core/drm/hw_info_drm.h +++ b/sdm/libs/core/drm/hw_info_drm.h @@ -30,10 +30,12 @@ #ifndef __HW_INFO_DRM_H__ #define __HW_INFO_DRM_H__ -#include #include +#include +#include #include #include +#include #include "hw_info_interface.h" @@ -41,26 +43,26 @@ namespace sdm { class HWInfoDRM: public HWInfoInterface { public: + HWInfoDRM(); virtual DisplayError GetHWResourceInfo(HWResourceInfo *hw_resource); virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info); private: - virtual DisplayError GetHWRotatorInfo(HWResourceInfo *hw_resource); + DisplayError GetHWRotatorInfo(HWResourceInfo *hw_resource); + void GetSystemInfo(HWResourceInfo *hw_resource); + void GetHWPlanesInfo(HWResourceInfo *hw_resource); + void GetWBInfo(HWResourceInfo *hw_resource); + DisplayError GetDynamicBWLimits(HWResourceInfo *hw_resource); + void GetSDMFormat(uint32_t drm_format, uint64_t drm_format_modifier, + std::vector *sdm_formats); + + sde_drm::DRMManagerInterface *drm_mgr_intf_ = {}; + bool default_mode_ = false; // TODO(user): Read Mdss version from the driver static const int kHWMdssVersion5 = 500; // MDSS_V5 static const int kMaxStringLength = 1024; - // MDP Capabilities are replicated across all frame buffer devices. - // However, we rely on reading the capabalities from fbO since this - // is guaranteed to be available. - static const int kHWCapabilitiesNode = 0; - - static int ParseString(const char *input, char *tokens[], const uint32_t max_token, - const char *delim, uint32_t *count); - DisplayError GetDynamicBWLimits(HWResourceInfo *hw_resource); - LayerBufferFormat GetSDMFormat(uint32_t drm_format, uint32_t drm_format_modifier); - void InitSupportedFormatMap(HWResourceInfo *hw_resource); - void PopulateSupportedFormatMap(HWSubBlockType sub_blk_type, HWResourceInfo *hw_resource); + static HWResourceInfo *hw_resource_; }; } // namespace sdm diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp index a381d7f9..3fdc8b24 100644 --- a/sdm/libs/core/fb/hw_primary.cpp +++ b/sdm/libs/core/fb/hw_primary.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved. +* Copyright (c) 2015 - 2017, 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 @@ -250,8 +250,8 @@ DisplayError HWPrimary::PopulateDisplayAttributes() { (FLOAT(var_screeninfo.yres) * 25.4f) / FLOAT(var_screeninfo.height); display_attributes_.fps = meta_data.data.panel_frame_rate; display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps); - display_attributes_.is_device_split = (hw_panel_info_.split_info.left_split || - (var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false; + display_attributes_.is_device_split = (hw_panel_info_.split_info.right_split || + (var_screeninfo.xres > hw_resource_.max_mixer_width)); display_attributes_.h_total += (display_attributes_.is_device_split || hw_panel_info_.ping_pong_split)? h_blanking : 0; diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp index 97a6cc36..aa89e64d 100644 --- a/sdm/libs/core/strategy.cpp +++ b/sdm/libs/core/strategy.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. +* Copyright (c) 2014 - 2017, 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: @@ -177,9 +177,7 @@ void Strategy::GenerateROI() { float layer_mixer_width = mixer_attributes_.width; float layer_mixer_height = mixer_attributes_.height; - if (!hw_resource_info_.is_src_split && - ((layer_mixer_width > hw_resource_info_.max_mixer_width) || - ((hw_panel_info_.is_primary_panel) && hw_panel_info_.split_info.right_split))) { + if (!hw_resource_info_.is_src_split && display_attributes_.is_device_split) { split_display = true; } -- cgit v1.2.3