summaryrefslogtreecommitdiff
authorsky 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)
commit98bd43a171d65c8736e403085f178480f2d87006 (patch)
tree3f1a1bda2196615bd0c93d2e173a121c2a304ce7
parentf7caa15bfb315dbcfae282c99c3022408b6a4ebe (diff)
downloadhwcomposer-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>
Diffstat
-rw-r--r--common/display/HwDisplayCrtc.cpp16
-rw-r--r--common/hwc/DualDisplayPipe.cpp144
-rw-r--r--common/hwc/HwcDisplayPipe.cpp13
-rw-r--r--common/hwc/HwcVsync.cpp41
-rw-r--r--hwc2/Hwc2Display.cpp39
-rw-r--r--hwc2/Hwc2Display.h2
-rw-r--r--hwc2/MesonHwc2.cpp9
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.");
}