diff options
-rw-r--r-- | BoardConfigCFlags.mk | 3 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDisplay.cpp | 29 | ||||
-rw-r--r-- | libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp | 93 | ||||
-rw-r--r-- | libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h | 12 | ||||
-rw-r--r-- | libhwc2.1/libdisplayinterface/ExynosDisplayInterface.h | 2 | ||||
-rw-r--r-- | libhwc2.1/libdrmresource/drm/drmconnector.cpp | 10 | ||||
-rw-r--r-- | libhwc2.1/libdrmresource/include/drmconnector.h | 2 | ||||
-rw-r--r-- | libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp | 175 | ||||
-rw-r--r-- | libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h | 11 |
9 files changed, 226 insertions, 111 deletions
diff --git a/BoardConfigCFlags.mk b/BoardConfigCFlags.mk index 1a0dfa0..93a8d68 100644 --- a/BoardConfigCFlags.mk +++ b/BoardConfigCFlags.mk @@ -50,6 +50,3 @@ ifeq ($(BOARD_USES_HDRUI_GLES_CONVERSION), true) LOCAL_CFLAGS += -DUSES_HDR_GLES_CONVERSION endif -ifeq ($(BOARD_USES_DOZEMODE), true) - LOCAL_CFLAGS += -DUSES_DOZEMODE -endif diff --git a/libhwc2.1/libdevice/ExynosDisplay.cpp b/libhwc2.1/libdevice/ExynosDisplay.cpp index fd75f0f..ef9be6e 100644 --- a/libhwc2.1/libdevice/ExynosDisplay.cpp +++ b/libhwc2.1/libdevice/ExynosDisplay.cpp @@ -2395,11 +2395,12 @@ int32_t ExynosDisplay::getDisplayType( int32_t ExynosDisplay::getDozeSupport( int32_t* outSupport) { -#ifdef USES_DOZEMODE - *outSupport = 1; -#else - *outSupport = 0; -#endif + if (mDisplayInterface->isDozeModeAvailable()) { + *outSupport = 1; + } else { + *outSupport = 0; + } + return 0; } @@ -2907,9 +2908,9 @@ int32_t ExynosDisplay::getDisplayCapabilities(uint32_t* outNumCapabilities, if (mBrightnessFd != NULL) capabilityNum++; -#ifdef USES_DOZEMODE - capabilityNum++; -#endif + if (mDisplayInterface->isDozeModeAvailable()) { + capabilityNum++; + } if (outCapabilities == NULL) { *outNumCapabilities = capabilityNum; @@ -2924,9 +2925,9 @@ int32_t ExynosDisplay::getDisplayCapabilities(uint32_t* outNumCapabilities, if (mBrightnessFd != NULL) outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_BRIGHTNESS; -#ifdef USES_DOZEMODE - outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_DOZE; -#endif + if (mDisplayInterface->isDozeModeAvailable()) { + outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_DOZE; + } return HWC2_ERROR_NONE; } @@ -2993,10 +2994,10 @@ int32_t ExynosDisplay::setPowerMode( int32_t /*hwc2_power_mode_t*/ mode) { Mutex::Autolock lock(mDisplayMutex); -#ifndef USES_DOZEMODE - if ((mode == HWC2_POWER_MODE_DOZE) || (mode == HWC2_POWER_MODE_DOZE_SUSPEND)) + if (!mDisplayInterface->isDozeModeAvailable() && + (mode == HWC2_POWER_MODE_DOZE || mode == HWC2_POWER_MODE_DOZE_SUSPEND)) { return HWC2_ERROR_UNSUPPORTED; -#endif + } if (mode == HWC_POWER_MODE_OFF) { mDevice->mPrimaryBlank = true; diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp index 21b6d9b..7dba60a 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp +++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp @@ -65,7 +65,7 @@ void ExynosDisplayDrmInterface::init(ExynosDisplay *exynosDisplay) mDrmDevice = NULL; mDrmCrtc = NULL; mDrmConnector = NULL; - mActiveConfig = -1; + mActiveConfig = UINT_MAX; } void ExynosDisplayDrmInterface::parseEnums(const DrmProperty& property, @@ -201,6 +201,8 @@ void ExynosDisplayDrmInterface::initDrmDevice(DrmDevice *drmDevice) return; } + getLowPowerDrmModeModeInfo(); + mOldFbIds.assign(getMaxWindowNum(), 0); mVsyncCallbak.init(mExynosDisplay->mDevice, mExynosDisplay); @@ -246,6 +248,35 @@ void ExynosDisplayDrmInterface::ExynosVsyncCallback::Callback( } } +int32_t ExynosDisplayDrmInterface::getLowPowerDrmModeModeInfo() { + int ret; + uint64_t blobId; + + std::tie(ret, blobId) = mDrmConnector->lp_mode().value(); + if (ret) { + ALOGE("Fail to get blob id for lp mode"); + return HWC2_ERROR_UNSUPPORTED; + } + drmModePropertyBlobPtr blob = drmModeGetPropertyBlob(mDrmDevice->fd(), blobId); + if (!blob) { + ALOGE("Fail to get blob for lp mode(%" PRId64 ")", blobId); + return HWC2_ERROR_UNSUPPORTED; + } + drmModeModeInfo dozeModeInfo = *static_cast<drmModeModeInfoPtr>(blob->data); + mDozeDrmMode = DrmMode(&dozeModeInfo); + drmModeFreePropertyBlob(blob); + + return NO_ERROR; +} + +int32_t ExynosDisplayDrmInterface::setLowPowerMode() { + if (!isDozeModeAvailable()) { + return HWC2_ERROR_UNSUPPORTED; + } + + return setActiveDrmMode(mDozeDrmMode); +} + int32_t ExynosDisplayDrmInterface::setPowerMode(int32_t mode) { int ret = 0; @@ -386,45 +417,24 @@ int32_t ExynosDisplayDrmInterface::setColorMode(int32_t mode) return 0; } -int32_t ExynosDisplayDrmInterface::setActiveConfig(hwc2_config_t config) -{ - ALOGI("%s:: %s config(%d)", __func__, mExynosDisplay->mDisplayName.string(), config); - - if (mActiveConfig == config) { - ALOGI("%s:: Same display config is set", __func__); - return NO_ERROR; - } - - auto mode = std::find_if(mDrmConnector->modes().begin(), - mDrmConnector->modes().end(), - [config](DrmMode const &m) { - return m.id() == config; - }); - if (mode == mDrmConnector->modes().end()) { - HWC_LOGE(mExynosDisplay, "Could not find active mode for %d", config); - return HWC2_ERROR_BAD_CONFIG; - } - +int32_t ExynosDisplayDrmInterface::setActiveDrmMode(DrmMode const &mode) { uint32_t mm_width = mDrmConnector->mm_width(); uint32_t mm_height = mDrmConnector->mm_height(); - mActiveConfig = mode->id(); - mExynosDisplay->mXres = mode->h_display(); - mExynosDisplay->mYres = mode->v_display(); + mExynosDisplay->mXres = mode.h_display(); + mExynosDisplay->mYres = mode.v_display(); // in nanoseconds - mExynosDisplay->mVsyncPeriod = 1000 * 1000 * 1000 / mode->v_refresh(); + mExynosDisplay->mVsyncPeriod = 1000 * 1000 * 1000 / mode.v_refresh(); // Dots per 1000 inches - mExynosDisplay->mXdpi = mm_width ? (mode->h_display() * kUmPerInch) / mm_width : -1; + mExynosDisplay->mXdpi = mm_width ? (mode.h_display() * kUmPerInch) / mm_width : -1; // Dots per 1000 inches - mExynosDisplay->mYdpi = mm_height ? (mode->v_display() * kUmPerInch) / mm_height : -1; + mExynosDisplay->mYdpi = mm_height ? (mode.v_display() * kUmPerInch) / mm_height : -1; - mModeState.mode = *mode; - if (mModeState.blob_id) - mDrmDevice->DestroyPropertyBlob(mModeState.blob_id); + mModeState.mode = mode; struct drm_mode_modeinfo drm_mode; memset(&drm_mode, 0, sizeof(drm_mode)); - mode->ToDrmModeModeInfo(&drm_mode); + mode.ToDrmModeModeInfo(&drm_mode); uint32_t id = 0; int ret = mDrmDevice->CreatePropertyBlob(&drm_mode, sizeof(drm_mode), @@ -433,12 +443,33 @@ int32_t ExynosDisplayDrmInterface::setActiveConfig(hwc2_config_t config) HWC_LOGE(mExynosDisplay, "Failed to create mode property blob %d", ret); return ret; } + + if (mModeState.blob_id) { + mDrmDevice->DestroyPropertyBlob(mModeState.blob_id); + } + mModeState.blob_id = id; mModeState.needs_modeset = true; - if (applyDisplayMode() < 0) + if (applyDisplayMode() < 0) { HWC_LOGE(mExynosDisplay, "%s: Fail to apply display mode", __func__); + } + return HWC2_ERROR_NONE; +} + +int32_t ExynosDisplayDrmInterface::setActiveConfig(hwc2_config_t config) { + auto mode = std::find_if(mDrmConnector->modes().begin(), mDrmConnector->modes().end(), + [config](DrmMode const &m) { return m.id() == config; }); + if (mode == mDrmConnector->modes().end()) { + HWC_LOGE(mExynosDisplay, "Could not find active mode for %d", config); + return HWC2_ERROR_BAD_CONFIG; + } + + mActiveConfig = mode->id(); + if (!setActiveDrmMode(*mode)) + ALOGI("%s:: %s config(%d)", __func__, mExynosDisplay->mDisplayName.string(), config); + return 0; } diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h index 162b046..0f94964 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h +++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h @@ -103,6 +103,10 @@ class ExynosDisplayDrmInterface : public ExynosDisplayInterface { ~ExynosDisplayDrmInterface(); virtual void init(ExynosDisplay *exynosDisplay); virtual int32_t setPowerMode(int32_t mode); + virtual int32_t setLowPowerMode() override; + virtual bool isDozeModeAvailable() const { + return mDozeDrmMode.h_display() > 0 && mDozeDrmMode.v_display() > 0; + }; virtual int32_t setVsyncEnabled(uint32_t enabled); virtual int32_t getDisplayAttribute( hwc2_config_t config, @@ -168,6 +172,11 @@ class ExynosDisplayDrmInterface : public ExynosDisplayInterface { void parseRangeEnums(const DrmProperty& property); int32_t setupWritebackCommit(DrmModeAtomicReq &drmReq); + + private: + int32_t getLowPowerDrmModeModeInfo(); + int32_t setActiveDrmMode(DrmMode const &mode); + protected: struct ModeState { bool needs_modeset = false; @@ -233,6 +242,9 @@ class ExynosDisplayDrmInterface : public ExynosDisplayInterface { DrmPropertyMap mRangeEnums; DrmReadbackInfo mReadbackInfo; + + private: + DrmMode mDozeDrmMode; }; #endif diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayInterface.h b/libhwc2.1/libdisplayinterface/ExynosDisplayInterface.h index 420ea9f..ee63065 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDisplayInterface.h +++ b/libhwc2.1/libdisplayinterface/ExynosDisplayInterface.h @@ -33,6 +33,8 @@ class ExynosDisplayInterface { virtual ~ExynosDisplayInterface(); virtual void init(ExynosDisplay* __unused exynosDisplay) {}; virtual int32_t setPowerMode(int32_t __unused mode) {return NO_ERROR;}; + virtual int32_t setLowPowerMode() { return HWC2_ERROR_UNSUPPORTED; }; + virtual bool isDozeModeAvailable() const { return false; }; virtual int32_t setVsyncEnabled(uint32_t __unused enabled) {return NO_ERROR;}; virtual int32_t getDisplayAttribute( hwc2_config_t __unused config, diff --git a/libhwc2.1/libdrmresource/drm/drmconnector.cpp b/libhwc2.1/libdrmresource/drm/drmconnector.cpp index 6f5acde..ebc6b93 100644 --- a/libhwc2.1/libdrmresource/drm/drmconnector.cpp +++ b/libhwc2.1/libdrmresource/drm/drmconnector.cpp @@ -107,6 +107,11 @@ int DrmConnector::Init() { ALOGE("Could not get hdr_formats property\n"); } + ret = drm_->GetConnectorProperty(*this, "lp_mode", &lp_mode_); + if (ret) { + ALOGE("Could not get lp_mode property\n"); + } + properties_.push_back(&dpms_property_); properties_.push_back(&crtc_id_property_); properties_.push_back(&edid_property_); @@ -119,6 +124,7 @@ int DrmConnector::Init() { properties_.push_back(&max_avg_luminance_); properties_.push_back(&min_luminance_); properties_.push_back(&hdr_formats_); + properties_.push_back(&lp_mode_); return 0; } @@ -265,6 +271,10 @@ const DrmProperty &DrmConnector::hdr_formats() const { return hdr_formats_; } +const DrmProperty &DrmConnector::lp_mode() const { + return lp_mode_; +} + DrmEncoder *DrmConnector::encoder() const { return encoder_; } diff --git a/libhwc2.1/libdrmresource/include/drmconnector.h b/libhwc2.1/libdrmresource/include/drmconnector.h index b8a1080..c240577 100644 --- a/libhwc2.1/libdrmresource/include/drmconnector.h +++ b/libhwc2.1/libdrmresource/include/drmconnector.h @@ -70,6 +70,7 @@ class DrmConnector { const DrmProperty &max_avg_luminance() const; const DrmProperty &min_luminance() const; const DrmProperty &hdr_formats() const; + const DrmProperty &lp_mode() const; const std::vector<DrmProperty *> &properties() const { return properties_; @@ -117,6 +118,7 @@ class DrmConnector { DrmProperty max_avg_luminance_; DrmProperty min_luminance_; DrmProperty hdr_formats_; + DrmProperty lp_mode_; std::vector<DrmProperty *> properties_; std::vector<DrmEncoder *> possible_encoders_; diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp index 72b3377..f050c63 100644 --- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp +++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp @@ -118,85 +118,136 @@ int ExynosPrimaryDisplay::getDDIScalerMode(int width, int height) { return 1; // WQHD } +int32_t ExynosPrimaryDisplay::getActiveConfig(hwc2_config_t *outConfig) { + if (outConfig && mPendActiveConfig != UINT_MAX) { + *outConfig = mPendActiveConfig; + return HWC2_ERROR_NONE; + } + return ExynosDisplay::getActiveConfig(outConfig); +} + +int32_t ExynosPrimaryDisplay::setActiveConfig(hwc2_config_t config) { + hwc2_config_t cur_config; + + getActiveConfig(&cur_config); + if (cur_config == config) { + ALOGI("%s:: Same display config is set", __func__); + return HWC2_ERROR_NONE; + } + if (mPowerModeState != HWC2_POWER_MODE_ON) { + mPendActiveConfig = config; + return HWC2_ERROR_NONE; + } + return ExynosDisplay::setActiveConfig(config); +} + +int32_t ExynosPrimaryDisplay::applyPendingConfig() { + hwc2_config_t config; + + if (mPendActiveConfig != UINT_MAX) { + config = mPendActiveConfig; + mPendActiveConfig = UINT_MAX; + } else { + getActiveConfig(&config); + } + return ExynosDisplay::setActiveConfig(config); +} + +int32_t ExynosPrimaryDisplay::setPowerOn() { + ATRACE_CALL(); + + int ret = applyPendingConfig(); + + if (mPowerModeState == HWC2_POWER_MODE_OFF) { + // check the dynamic recomposition thread by following display + mDevice->checkDynamicRecompositionThread(); + if (ret) { + mDisplayInterface->setPowerMode(HWC2_POWER_MODE_ON); + } + setGeometryChanged(GEOMETRY_DISPLAY_POWER_ON); + } + + mPowerModeState = HWC2_POWER_MODE_ON; + + return HWC2_ERROR_NONE; +} + +int32_t ExynosPrimaryDisplay::setPowerOff() { + ATRACE_CALL(); + + clearDisplay(); + + // check the dynamic recomposition thread by following display + mDevice->checkDynamicRecompositionThread(); + + mDisplayInterface->setPowerMode(HWC2_POWER_MODE_OFF); + mPowerModeState = HWC2_POWER_MODE_OFF; + + /* It should be called from validate() when the screen is on */ + mSkipFrame = true; + setGeometryChanged(GEOMETRY_DISPLAY_POWER_OFF); + if ((mRenderingState >= RENDERING_STATE_VALIDATED) && + (mRenderingState < RENDERING_STATE_PRESENTED)) + closeFencesForSkipFrame(RENDERING_STATE_VALIDATED); + mRenderingState = RENDERING_STATE_NONE; + + return HWC2_ERROR_NONE; +} + +int32_t ExynosPrimaryDisplay::setPowerDoze() { + ATRACE_CALL(); + + if (!mDisplayInterface->isDozeModeAvailable()) { + return HWC2_ERROR_UNSUPPORTED; + } + + if (mDisplayInterface->setLowPowerMode()) { + ALOGI("Not support LP mode."); + return HWC2_ERROR_UNSUPPORTED; + } + + mPowerModeState = HWC2_POWER_MODE_DOZE; + + return HWC2_ERROR_NONE; +} + int32_t ExynosPrimaryDisplay::setPowerMode(int32_t mode) { Mutex::Autolock lock(mDisplayMutex); if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::PAUSE)) { - mPauseDisplay = true; - /** - * TODO(b/165712292): This is a temp fix. - * - * There is no power state check in common path. - * Repeated RESUME or HWC2_POWER_MODE_ON mode set triggers device reset. - * Add state check in PAUSE/RESUME path to fix repeated mode set issue - * triggered by factory or desense tool. - * Should add generic state check in common path later. - */ - if (mPowerModeState == HWC2_POWER_MODE_OFF) { - ALOGD("Skip PAUSE mode set due to no power mode change"); - return HWC2_ERROR_NONE; - } mode = HWC2_POWER_MODE_OFF; + mPauseDisplay = true; } else if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME)) { - mPauseDisplay = false; - if (mPowerModeState == HWC2_POWER_MODE_ON) { - ALOGD("Skip RESUME mode set due to no power mode change"); - return HWC2_ERROR_NONE; - } mode = HWC2_POWER_MODE_ON; + mPauseDisplay = false; } -#ifndef USES_DOZEMODE - if ((mode == HWC2_POWER_MODE_DOZE) || (mode == HWC2_POWER_MODE_DOZE_SUSPEND)) - return HWC2_ERROR_UNSUPPORTED; -#endif - - /* TODO state check routine should be added */ - int fb_blank = -1; - - if (mode == HWC_POWER_MODE_DOZE || - mode == HWC_POWER_MODE_DOZE_SUSPEND) { - if (mPowerModeState != HWC_POWER_MODE_DOZE && - mPowerModeState != HWC_POWER_MODE_OFF && - mPowerModeState != HWC_POWER_MODE_DOZE_SUSPEND) { - fb_blank = FB_BLANK_POWERDOWN; - clearDisplay(); - } else { - ALOGE("DOZE or Power off called twice, mPowerModeState : %d", mPowerModeState); - } - } else if (mode == HWC_POWER_MODE_OFF) { - fb_blank = FB_BLANK_POWERDOWN; - clearDisplay(); - ALOGV("HWC2: Clear display (power off)"); - } else { - fb_blank = FB_BLANK_UNBLANK; + if (mode == static_cast<int32_t>(mPowerModeState)) { + ALOGI("Skip power mode transition due to the same power state."); + return HWC2_ERROR_NONE; } + int fb_blank = (mode != HWC2_POWER_MODE_OFF) ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; ALOGD("%s:: FBIOBLANK mode(%d), blank(%d)", __func__, mode, fb_blank); if (fb_blank == FB_BLANK_POWERDOWN) mDREnable = false; - else if (fb_blank == FB_BLANK_UNBLANK) + else mDREnable = mDRDefault; - // check the dynamic recomposition thread by following display - mDevice->checkDynamicRecompositionThread(); - - mDisplayInterface->setPowerMode(mode); - mPowerModeState = (hwc2_power_mode_t)mode; - - ALOGD("%s:: S3CFB_POWER_MODE mode(%d), blank(%d)", __func__, mode, fb_blank); - - if (mode == HWC_POWER_MODE_OFF) { - /* It should be called from validate() when the screen is on */ - mSkipFrame = true; - setGeometryChanged(GEOMETRY_DISPLAY_POWER_OFF); - if ((mRenderingState >= RENDERING_STATE_VALIDATED) && - (mRenderingState < RENDERING_STATE_PRESENTED)) - closeFencesForSkipFrame(RENDERING_STATE_VALIDATED); - mRenderingState = RENDERING_STATE_NONE; - } else { - setGeometryChanged(GEOMETRY_DISPLAY_POWER_ON); + switch (mode) { + case HWC2_POWER_MODE_DOZE_SUSPEND: + return HWC2_ERROR_UNSUPPORTED; + case HWC2_POWER_MODE_DOZE: + return setPowerDoze(); + case HWC2_POWER_MODE_OFF: + setPowerOff(); + break; + case HWC2_POWER_MODE_ON: + setPowerOn(); + break; + default: + return HWC2_ERROR_BAD_PARAMETER; } return HWC2_ERROR_NONE; diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h index 005f791..b2f375b 100644 --- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h +++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h @@ -27,6 +27,8 @@ class ExynosPrimaryDisplay : public ExynosDisplay { ~ExynosPrimaryDisplay(); virtual void setDDIScalerEnable(int width, int height); virtual int getDDIScalerMode(int width, int height); + virtual int32_t setActiveConfig(hwc2_config_t config) override; + virtual int32_t getActiveConfig(hwc2_config_t* outConfig) override; virtual void initDisplayInterface(uint32_t interfaceType); protected: @@ -38,11 +40,18 @@ class ExynosPrimaryDisplay : public ExynosDisplay { * Returns HWC2_ERROR_NONE or the following error: * HWC2_ERROR_UNSUPPORTED when DOZE mode not support */ - virtual int32_t setPowerMode(int32_t mode); + virtual int32_t setPowerMode(int32_t mode) override; virtual bool getHDRException(ExynosLayer* __unused layer); public: // Prepare multi resolution ResolutionInfo mResolutionInfo; + + private: + int32_t applyPendingConfig(); + int32_t setPowerOn(); + int32_t setPowerOff(); + int32_t setPowerDoze(); + hwc2_config_t mPendActiveConfig = UINT_MAX; }; #endif |