From 802d855785d9cecca8c674a0aa61bba44293cbbb Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Fri, 14 Jan 2022 10:18:52 +0100 Subject: [PATCH] backends/drm: support link-status Userspace is expected to do a modeset and set link-status to good again, if link-status gets bad. This is needed to prevent some black screen situations. BUG: 448177 --- src/backends/drm/drm_object_connector.cpp | 12 ++++++++++++ src/backends/drm/drm_object_connector.h | 6 ++++++ src/backends/drm/drm_pipeline.cpp | 4 ++++ 3 files changed, 22 insertions(+) diff --git a/src/backends/drm/drm_object_connector.cpp b/src/backends/drm/drm_object_connector.cpp index eb8888ddc3..93bcbb0bfc 100644 --- a/src/backends/drm/drm_object_connector.cpp +++ b/src/backends/drm/drm_object_connector.cpp @@ -101,6 +101,10 @@ DrmConnector::DrmConnector(DrmGpu *gpu, uint32_t connectorId) QByteArrayLiteral("Limited 16:235") }), PropertyDefinition(QByteArrayLiteral("max bpc"), Requirement::Optional), + PropertyDefinition(QByteArrayLiteral("link-status"), Requirement::Optional, { + QByteArrayLiteral("Good"), + QByteArrayLiteral("Bad") + }), }, DRM_MODE_OBJECT_CONNECTOR) , m_pipeline(new DrmPipeline(this)) , m_conn(drmModeGetConnector(gpu->fd(), connectorId)) @@ -421,6 +425,14 @@ void DrmConnector::disable() setPending(PropertyIndex::CrtcId, 0); } +DrmConnector::LinkStatus DrmConnector::linkStatus() const +{ + if (const auto &property = getProp(PropertyIndex::LinkStatus)) { + return property->enumForValue(property->current()); + } + return LinkStatus::Good; +} + QDebug& operator<<(QDebug& s, const KWin::DrmConnector *obj) { QDebugStateSaver saver(s); diff --git a/src/backends/drm/drm_object_connector.h b/src/backends/drm/drm_object_connector.h index 3fd48edb33..46660a4f0c 100644 --- a/src/backends/drm/drm_object_connector.h +++ b/src/backends/drm/drm_object_connector.h @@ -66,6 +66,7 @@ public: Underscan_hborder = 8, Broadcast_RGB = 9, MaxBpc = 10, + LinkStatus = 11, Count }; @@ -74,6 +75,10 @@ public: On = 1, Auto = 2, }; + enum class LinkStatus : uint32_t { + Good = 0, + Bad = 1 + }; bool init() override; bool needsModeset() const override; @@ -105,6 +110,7 @@ public: bool vrrCapable() const; bool hasRgbRange() const; AbstractWaylandOutput::RgbRange rgbRange() const; + LinkStatus linkStatus() const; private: QScopedPointer m_pipeline; diff --git a/src/backends/drm/drm_pipeline.cpp b/src/backends/drm/drm_pipeline.cpp index fafb2910cd..460dd52996 100644 --- a/src/backends/drm/drm_pipeline.cpp +++ b/src/backends/drm/drm_pipeline.cpp @@ -230,6 +230,9 @@ void DrmPipeline::prepareAtomicModeset() if (const auto &prop = m_connector->getProp(DrmConnector::PropertyIndex::Broadcast_RGB)) { prop->setEnum(pending.rgbRange); } + if (const auto &prop = m_connector->getProp(DrmConnector::PropertyIndex::LinkStatus)) { + prop->setEnum(DrmConnector::LinkStatus::Good); + } pending.crtc->setPending(DrmCrtc::PropertyIndex::Active, activePending()); pending.crtc->setPending(DrmCrtc::PropertyIndex::ModeId, activePending() ? mode->blobId() : 0); @@ -501,6 +504,7 @@ bool DrmPipeline::needsModeset() const || pending.modeIndex != m_current.modeIndex || pending.rgbRange != m_current.rgbRange || pending.bufferTransformation != m_current.bufferTransformation + || m_connector->linkStatus() == DrmConnector::LinkStatus::Bad || m_modesetPresentPending; }