author | sky zhou <sky.zhou@amlogic.com> | 2020-03-06 08:05:01 (GMT) |
---|---|---|
committer | sky zhou <sky.zhou@amlogic.com> | 2020-05-21 11:01:37 (GMT) |
commit | 98bd43a171d65c8736e403085f178480f2d87006 (patch) | |
tree | 3f1a1bda2196615bd0c93d2e173a121c2a304ce7 | |
parent | f7caa15bfb315dbcfae282c99c3022408b6a4ebe (diff) | |
download | hwcomposer-98bd43a171d65c8736e403085f178480f2d87006.zip hwcomposer-98bd43a171d65c8736e403085f178480f2d87006.tar.gz hwcomposer-98bd43a171d65c8736e403085f178480f2d87006.tar.bz2 |
display: dual display pipe fix. [1/2]
PD#SWPL-21854
Problem:
screen show error when hdmi hot pull and plug
Solution:
adjust display mode when hdmi hot pull and plug
Verify:
verify on 905d3
Change-Id: Iad0e7939c72838771ea63e4da3a1ecdbecb2761c
Signed-off-by: sky zhou <sky.zhou@amlogic.com>
Signed-off-by: Tianhua Sun <tianhua.sun@amlogic.com>
-rw-r--r-- | common/display/HwDisplayCrtc.cpp | 16 | ||||
-rw-r--r-- | common/hwc/DualDisplayPipe.cpp | 144 | ||||
-rw-r--r-- | common/hwc/HwcDisplayPipe.cpp | 13 | ||||
-rw-r--r-- | common/hwc/HwcVsync.cpp | 41 | ||||
-rw-r--r-- | hwc2/Hwc2Display.cpp | 39 | ||||
-rw-r--r-- | hwc2/Hwc2Display.h | 2 | ||||
-rw-r--r-- | hwc2/MesonHwc2.cpp | 9 |
7 files changed, 168 insertions, 96 deletions
diff --git a/common/display/HwDisplayCrtc.cpp b/common/display/HwDisplayCrtc.cpp index 9b4108c..fe4fd50 100644 --- a/common/display/HwDisplayCrtc.cpp +++ b/common/display/HwDisplayCrtc.cpp @@ -65,7 +65,14 @@ int32_t HwDisplayCrtc::bind( } int32_t HwDisplayCrtc::unbind() { + /*TODO: temp disable here. + * systemcontrol and hwc set display mode + * at the same time, there is a timing issue now. + * Just disable it here, later will remove systemcontrol + * set displaymode when hotplug. + */ if (mBinded) { + #if 0 static drm_mode_info_t nullMode = { DRM_DISPLAY_MODE_NULL, 0, 0, @@ -74,6 +81,7 @@ int32_t HwDisplayCrtc::unbind() { }; std::string dispmode(nullMode.name); writeCurDisplayMode(dispmode); + #endif if (mConnector.get()) mConnector->setCrtc(NULL); mConnector.reset(); @@ -164,7 +172,15 @@ int32_t HwDisplayCrtc::update() { mId, displayMode.c_str(), mModes.size(), mCurModeInfo.name); } } else { + /*clear mode info.*/ + memset(&mCurModeInfo, 0, sizeof(mCurModeInfo)); + /* TODO: temp disable mode setting in HWC. */ + #if 0 + strcpy(mCurModeInfo.name, DRM_DISPLAY_MODE_NULL); + setMode(mCurModeInfo); + #else//amlogic fix MESON_LOGD("crtc(%d) update with no connector", mId); + #endif } return 0; diff --git a/common/hwc/DualDisplayPipe.cpp b/common/hwc/DualDisplayPipe.cpp index 8d1df02..88fcb0f 100644 --- a/common/hwc/DualDisplayPipe.cpp +++ b/common/hwc/DualDisplayPipe.cpp @@ -22,7 +22,7 @@ DualDisplayPipe::DualDisplayPipe() /*Todo:init status need to get from??*/ mPrimaryConnectorType = DRM_MODE_CONNECTOR_INVALID; mExtendConnectorType = DRM_MODE_CONNECTOR_INVALID; - mHdmi_connected = true; + mHdmi_connected = false; } DualDisplayPipe::~DualDisplayPipe() { @@ -30,6 +30,12 @@ DualDisplayPipe::~DualDisplayPipe() { int32_t DualDisplayPipe::init( std::map<uint32_t, std::shared_ptr<HwcDisplay>> & hwcDisps) { + /*update hdmi connect status*/ + std::shared_ptr<HwDisplayConnector> hwConnector; + getConnector(DRM_MODE_CONNECTOR_HDMI, hwConnector); + hwConnector->update(); + mHdmi_connected = hwConnector->isConnected(); + HwcDisplayPipe::init(hwcDisps); MESON_ASSERT(HwcConfig::getDisplayNum() == 2, @@ -48,7 +54,7 @@ int32_t DualDisplayPipe::init( if (init == true) return 0; /*reinit dual display pipeline display mode*/ - static drm_mode_info_t displayMode = { + drm_mode_info_t displayMode = { DRM_DISPLAY_MODE_NULL, 0, 0, 0, 0, @@ -99,10 +105,6 @@ int32_t DualDisplayPipe::init( int32_t DualDisplayPipe::getPipeCfg(uint32_t hwcid, PipeCfg & cfg) { /*get hdmi hpd state firstly for init default config*/ - std::shared_ptr<HwDisplayConnector> hwConnector; - getConnector(DRM_MODE_CONNECTOR_HDMI, hwConnector); - hwConnector->update(); - mHdmi_connected = hwConnector->isConnected(); drm_connector_type_t connector = getConnetorCfg(hwcid); if (hwcid == 0) { if (HwcConfig::dynamicSwitchViuEnabled() == true && @@ -154,89 +156,87 @@ void DualDisplayPipe::handleEvent(drm_display_event event, int val) { MESON_LOGD("Hotplug handle value %d.",val); bool connected = (val == 0) ? false : true; mHdmi_connected = connected; - static drm_mode_info_t displayMode = { + drm_mode_info_t displayMode = { DRM_DISPLAY_MODE_NULL, 0, 0, 0, 0, 60.0 }; - if (mPrimaryConnectorType != DRM_MODE_CONNECTOR_INVALID && - mExtendConnectorType != DRM_MODE_CONNECTOR_INVALID) { - for (auto statIt : mPipeStats) { - PipeCfg cfg; - getPipeCfg(statIt.second->hwcId, cfg); - if ((statIt.second->cfg.modeConnectorType != cfg.modeConnectorType) || - (statIt.second->cfg.hwcCrtcId != cfg.hwcCrtcId)) { - /* If display pip stat resource change, then - * reset vout displaymode, for we need do pipeline switch*/ - statIt.second->hwcCrtc->unbind(); - } - } - /*update display pipe.*/ - for (auto statIt : mPipeStats) { - updatePipe(statIt.second); + + MESON_LOGD("SET display mode null."); + /*reset vout displaymode, for we need do pipeline switch*/ + for (auto statIt : mPipeStats) { + //TODO: need disable vsycn before setmode to null. + std::string curMode; + statIt.second->modeCrtc->readCurDisplayMode(curMode); + if (strcmp(curMode.c_str(), "panel") == 0) { + statIt.second->modeCrtc->setMode(displayMode); + MESON_LOGE("set panel to NULL displaymode "); } - /*update display mode*/ + } + + if (connected == false) { for (auto statIt : mPipeStats) { if (statIt.second->modeConnector->getType() == DRM_MODE_CONNECTOR_HDMI) { - std::string displayattr(DRM_DISPLAY_ATTR_DEFAULT); - std::string prefdisplayMode; - if (connected == false) { - strcpy(displayMode.name, DRM_DISPLAY_MODE_NULL); - prefdisplayMode = DRM_DISPLAY_MODE_NULL; + statIt.second->modeConnector->update(); + statIt.second->hwcDisplay->onHotplug(false); + } + } + } + + MESON_LOGD("Update pipeline"); + /*update display pipe.*/ + for (auto statIt : mPipeStats) { + updatePipe(statIt.second); + } + + /*update display mode*/ + /*handle hdmi firstly, for vout2 bug which cost too much time may caused + */ + for (auto statIt : mPipeStats) { + MESON_LOGD("Update display mode for HDMI"); + if (statIt.second->modeConnector->getType() == DRM_MODE_CONNECTOR_HDMI) { + std::string displayattr(DRM_DISPLAY_ATTR_DEFAULT); + std::string prefdisplayMode; + if (connected == false) { + strcpy(displayMode.name, DRM_DISPLAY_MODE_NULL); + prefdisplayMode = DRM_DISPLAY_MODE_NULL; + } else { + /*get hdmi prefect display mode*/ + if (sc_get_pref_display_mode(prefdisplayMode) == false) { + strcpy(displayMode.name, DRM_DISPLAY_MODE_DEFAULT); + prefdisplayMode = DRM_DISPLAY_MODE_DEFAULT; + MESON_LOGD("sc_get_pref_display_mode fail! use default mode"); } else { - /*get hdmi prefect display mode*/ - if (sc_get_pref_display_mode(prefdisplayMode) == false) { - strcpy(displayMode.name, DRM_DISPLAY_MODE_DEFAULT); - prefdisplayMode = DRM_DISPLAY_MODE_DEFAULT; - MESON_LOGI("sc_get_pref_display_mode fail! use default mode"); - } else { - strcpy(displayMode.name, prefdisplayMode.c_str()); - } + strcpy(displayMode.name, prefdisplayMode.c_str()); } - sc_set_display_mode(prefdisplayMode); - } else if (statIt.second->modeConnector->getType() == DRM_MODE_CONNECTOR_PANEL) { - std::string lcd_mute("8"); - sc_write_sysfs(LCD_MUTE, lcd_mute); - MESON_LOGD("DualDisplayPipe::handleEvent lcd mute"); - strcpy(displayMode.name, DRM_DISPLAY_MODE_PANEL); - statIt.second->modeCrtc->setMode(displayMode); - /*mode change config move here for dual display panle*/ - statIt.second->modeCrtc->loadProperities(); - statIt.second->modeCrtc->update(); - statIt.second->modeMgr->update(); - statIt.second->hwcDisplay->onModeChanged(val); - /*update display dynamic info.*/ - drm_mode_info_t mode; - if (HwcConfig::softwareVsyncEnabled()) { - if (0 == statIt.second->modeMgr->getDisplayMode(mode)) { - statIt.second->hwcVsync->setPeriod(1e9 / mode.refreshRate); - } - } - if (mode.refreshRate) - usleep(1000000 / mode.refreshRate); - else - usleep(20000); - std::string lcd_unmute("0"); - sc_write_sysfs(LCD_MUTE, lcd_unmute); - MESON_LOGD("HwcDisplayPipe::handleEvent lcd unmute"); - } else { - strcpy(displayMode.name, DRM_DISPLAY_MODE_NULL); - statIt.second->modeCrtc->setMode(displayMode); } - MESON_LOGI("DualDisplayPipe::handleEvent set mode (%s)",displayMode.name); - statIt.second->modeMgr->setDisplayResources(statIt.second->modeCrtc, statIt.second->modeConnector); - statIt.second->modeMgr->update(); + + MESON_LOGD("HDMI SET display mode %s.", prefdisplayMode.c_str()); + sc_set_display_mode(prefdisplayMode); + + if (connected) { + statIt.second->modeConnector->update(); + statIt.second->hwcDisplay->onHotplug(true); + } } } + for (auto statIt : mPipeStats) { - if (statIt.second->modeConnector->getType() == DRM_MODE_CONNECTOR_HDMI) { - statIt.second->modeConnector->update(); - statIt.second->hwcDisplay->onHotplug(connected); + MESON_LOGD("Update display mode for PANEL"); + if (statIt.second->modeConnector->getType() == DRM_MODE_CONNECTOR_PANEL) { + std::string lcd_mute("8"); + sc_write_sysfs(LCD_MUTE, lcd_mute); + strcpy(displayMode.name, DRM_DISPLAY_MODE_PANEL); + statIt.second->modeCrtc->setMode(displayMode); + usleep(20000); + std::string lcd_unmute("0"); + sc_write_sysfs(LCD_MUTE, lcd_unmute); + MESON_LOGD("HwcDisplayPipe::handleEvent lcd unmute"); } } + } else { - MESON_LOGI("Receive DualDisplayPipe unhandled event %d", event); HwcDisplayPipe::handleEvent(event, val); } } diff --git a/common/hwc/HwcDisplayPipe.cpp b/common/hwc/HwcDisplayPipe.cpp index 67732cd..ed1cf7f 100644 --- a/common/hwc/HwcDisplayPipe.cpp +++ b/common/hwc/HwcDisplayPipe.cpp @@ -207,8 +207,13 @@ int32_t HwcDisplayPipe::updatePipe(std::shared_ptr<PipeStat> & stat) { resChanged = true; } + MESON_LOGD("HwcDisplayPipe::updatePipe (%d) [%s], crtc (%d) connector (%d)", + stat->hwcId, resChanged ? "CHANGED" : "NOT-CHANGED", + cfg.hwcCrtcId, cfg.hwcConnectorType); + if (resChanged) { - MESON_LOGD("HwcDisplayPipe::updatePipe %d changed", stat->hwcId); + /*reset vout displaymode, it will be null.*/ + stat->hwcCrtc->unbind(); stat->hwcCrtc->bind(stat->hwcConnector, stat->hwcPlanes); stat->hwcCrtc->loadProperities(); stat->hwcCrtc->update(); @@ -216,6 +221,7 @@ int32_t HwcDisplayPipe::updatePipe(std::shared_ptr<PipeStat> & stat) { if (cfg.modeCrtcId != cfg.hwcCrtcId) { std::vector<std::shared_ptr<HwDisplayPlane>> planes; getPlanes (cfg.modeCrtcId, planes); + stat->modeCrtc->unbind(); stat->modeCrtc->bind(stat->modeConnector, planes); stat->modeCrtc->loadProperities(); stat->modeCrtc->update(); @@ -230,6 +236,11 @@ int32_t HwcDisplayPipe::updatePipe(std::shared_ptr<PipeStat> & stat) { stat->hwcVsync->setHwMode(stat->modeCrtc); } + drm_mode_info_t mode; + if (0 == stat->modeMgr->getDisplayMode(mode)) { + stat->hwcVsync->setPeriod(1e9 / mode.refreshRate); + } + stat->hwcDisplay->setVsync(stat->hwcVsync); stat->hwcDisplay->setModeMgr(stat->modeMgr); stat->hwcDisplay->setDisplayResource( diff --git a/common/hwc/HwcVsync.cpp b/common/hwc/HwcVsync.cpp index f18f3be..bc7545b 100644 --- a/common/hwc/HwcVsync.cpp +++ b/common/hwc/HwcVsync.cpp @@ -17,6 +17,9 @@ HwcVsync::HwcVsync() { mSoftVsync = true; mEnabled = false; mPreTimeStamp = 0; + mPeriod = 0; + mExit = false; + mObserver = NULL; int ret; ret = pthread_create(&hw_vsync_thread, NULL, vsyncThread, this); @@ -43,6 +46,8 @@ int32_t HwcVsync::setSoftwareMode() { std::unique_lock<std::mutex> stateLock(mStatLock); mSoftVsync = true; mCrtc.reset(); + stateLock.unlock(); + mStateCondition.notify_all(); return 0; } @@ -50,6 +55,8 @@ int32_t HwcVsync::setHwMode(std::shared_ptr<HwDisplayCrtc> & crtc) { std::unique_lock<std::mutex> stateLock(mStatLock); mCrtc = crtc; mSoftVsync = false; + stateLock.unlock(); + mStateCondition.notify_all(); return 0; } @@ -69,19 +76,21 @@ int32_t HwcVsync::setEnabled(bool enabled) { void * HwcVsync::vsyncThread(void * data) { HwcVsync* pThis = (HwcVsync*)data; - MESON_LOGV("HwDisplayVsync: vsyncThread start."); + MESON_LOGV("HwDisplayVsync: vsyncThread start - (%p).", pThis); + int print_cnt = 10; while (true) { - std::unique_lock<std::mutex> stateLock(pThis->mStatLock); - while (!pThis->mEnabled) { - pThis->mStateCondition.wait(stateLock); - if (pThis->mExit) { - pthread_exit(0); - MESON_LOGD("exit vsync loop"); - return NULL; + { + std::unique_lock<std::mutex> stateLock(pThis->mStatLock); + while (!pThis->mEnabled) { + pThis->mStateCondition.wait(stateLock); + if (pThis->mExit) { + MESON_LOGD("exit vsync loop"); + pthread_exit(0); + return NULL; + } } } - stateLock.unlock(); nsecs_t timestamp; int32_t ret; @@ -90,17 +99,23 @@ void * HwcVsync::vsyncThread(void * data) { } else { ret = pThis->mCrtc->waitVBlank(timestamp); } - bool debug = false; + bool debug = true; if (debug) { nsecs_t period = timestamp - pThis->mPreTimeStamp; UNUSED(period); - if (pThis->mPreTimeStamp != 0) - MESON_LOGD("wait for vsync success, peroid: %lld", period); + print_cnt --; + if (pThis->mPreTimeStamp != 0 && print_cnt <= 0) { + MESON_LOGD("wait for vsync success, (%p) peroid: %lld", pThis, period); + print_cnt = 10; + } pThis->mPreTimeStamp = timestamp; } if ( ret == 0 && pThis->mObserver) { pThis->mObserver->onVsync(timestamp); + } else { + MESON_LOGE("HwcVsync vsync callback fail (%p)-(%d)-(%p)", + pThis, ret, pThis->mObserver); } } return NULL; @@ -111,7 +126,7 @@ int32_t HwcVsync::waitSoftwareVsync(nsecs_t& vsync_timestamp) { static nsecs_t old_vsync_period = 0; nsecs_t now = systemTime(CLOCK_MONOTONIC); - mPeriod = (mPeriod == 0) ? SF_VSYNC_DFT_PERIOD : mPeriod; + mPeriod = (mPeriod == 0) ? 1e9/SF_VSYNC_DFT_PERIOD : mPeriod; //cal the last vsync time with old period if (mPeriod != old_vsync_period) { diff --git a/hwc2/Hwc2Display.cpp b/hwc2/Hwc2Display.cpp index 9e1be89..1738e14 100644 --- a/hwc2/Hwc2Display.cpp +++ b/hwc2/Hwc2Display.cpp @@ -29,6 +29,7 @@ Hwc2Display::Hwc2Display(std::shared_ptr<Hwc2DisplayObserver> observer) { mPowerMode = std::make_shared<HwcPowerMode>(); mSignalHpd = false; mValidateDisplay = false; + mVsyncState = false; memset(&mHdrCaps, 0, sizeof(mHdrCaps)); memset(mColorMatrix, 0, sizeof(float) * 16); memset(&mCalibrateCoordinates, 0, sizeof(int) * 4); @@ -140,10 +141,17 @@ int32_t Hwc2Display::setPostProcessor( int32_t Hwc2Display::setVsync(std::shared_ptr<HwcVsync> vsync) { std::lock_guard<std::mutex> lock(mMutex); - if (vsync) - vsync->setObserver(this); + if (mVsync != vsync) { + if (mVsync.get()) { + mVsync->setEnabled(false); + mVsync->setObserver(NULL); + } else { + mVsync = vsync; + mVsync->setObserver(this); + mVsync->setEnabled(mVsyncState); + } + } - mVsync = vsync; return 0; } @@ -200,6 +208,7 @@ hwc2_error_t Hwc2Display::getFrameMetadataKeys( #endif hwc2_error_t Hwc2Display::setVsyncEnable(hwc2_vsync_t enabled) { + std::lock_guard<std::mutex> lock(mMutex); bool state; switch (enabled) { case HWC2_VSYNC_ENABLE: @@ -212,7 +221,10 @@ hwc2_error_t Hwc2Display::setVsyncEnable(hwc2_vsync_t enabled) { MESON_LOGE("[%s]: set vsync state invalid %d.", __func__, enabled); return HWC2_ERROR_BAD_PARAMETER; } - mVsync->setEnabled(state); + + mVsyncState = state; + if (mVsync.get()) + mVsync->setEnabled(mVsyncState); return HWC2_ERROR_NONE; } @@ -232,15 +244,26 @@ void Hwc2Display::onHotplug(bool connected) { return; } mPowerMode->setConnectorStatus(false); - if (mObserver != NULL && mModeMgr->getPolicyType() != FIXED_SIZE_POLICY - && mModeMgr->getPolicyType() != ACTIVE_MODE_POLICY) { + if (mObserver != NULL ) { bSendPlugOut = true; } } /*call hotplug out of lock, SF may call some hwc function to cause deadlock.*/ - if (bSendPlugOut) + if (bSendPlugOut) { + std::shared_ptr<IComposer> clientComposer = mComposers.find(MESON_CLIENT_COMPOSER)->second; + clientComposer->prepare(); + if (mLayers.size() >= 1) + mLayers.clear(); + + uint32_t outNumTypes; + uint32_t outNumRequests; + int32_t outPresentFence; + validateDisplay(&outNumTypes,&outNumRequests); + presentDisplay(&outPresentFence); + mObserver->onHotplug(false); + } } void Hwc2Display::onUpdate(bool bHdcp) { @@ -259,6 +282,8 @@ void Hwc2Display::onUpdate(bool bHdcp) { void Hwc2Display::onVsync(int64_t timestamp) { if (mObserver != NULL) { mObserver->onVsync(timestamp); + } else { + MESON_LOGE("Hwc2Display (%p) observer is NULL", this); } } diff --git a/hwc2/Hwc2Display.h b/hwc2/Hwc2Display.h index f08b020..5711060 100644 --- a/hwc2/Hwc2Display.h +++ b/hwc2/Hwc2Display.h @@ -193,6 +193,8 @@ protected: std::vector<drm_hdr_meatadata_t> mHdrKeys; #endif std::mutex mMutex; + + bool mVsyncState; }; #endif/*HWC2_DISPLAY_H*/ diff --git a/hwc2/MesonHwc2.cpp b/hwc2/MesonHwc2.cpp index 8e7a0e4..afc4aea 100644 --- a/hwc2/MesonHwc2.cpp +++ b/hwc2/MesonHwc2.cpp @@ -765,10 +765,13 @@ void MesonHwc2::onHotplug(hwc2_display_t display, bool connected) { return; } + hwc2_connection_t connection = + connected ? HWC2_CONNECTION_CONNECTED : HWC2_CONNECTION_DISCONNECTED; + if (mHotplugFn) { - MESON_LOGD("On hotplug, Fn: %p, Data: %p, display: %d(%d), connected: %d", - mHotplugFn, mHotplugData, (int)display, HWC_DISPLAY_PRIMARY, connected); - mHotplugFn(mHotplugData, display, connected); + MESON_LOGD("On hotplug, Fn: %p, Data: %p, display: %d(%d), connection: %d", + mHotplugFn, mHotplugData, (int)display, HWC_DISPLAY_PRIMARY, connection); + mHotplugFn(mHotplugData, display, connection); } else { MESON_LOGE("No hotplug callback registered."); } |