115 lines
4.5 KiB
Diff
115 lines
4.5 KiB
Diff
From 64d17f25dcad518461ccf0c260544e1e379c5b35 Mon Sep 17 00:00:00 2001
|
|
From: Hans de Goede <hdegoede@redhat.com>
|
|
Date: Thu, 24 Oct 2019 10:52:53 +0200
|
|
Subject: [PATCH v2 2/2] drm/nouveau: Fix drm-core using atomic code-paths on
|
|
pre-nv50 hardware
|
|
|
|
We do not support atomic modesetting on pre-nv50 hardware, but until now
|
|
our connector code was setting drm_connector->state on pre-nv50 hardware.
|
|
|
|
This causes the core to enter atomic modesetting paths in at least:
|
|
|
|
1. drm_connector_get_encoder(), returning connector->state->best_encoder
|
|
which is always 0, causing us to always report 0 as encoder_id in
|
|
the drmModeConnector struct returned by drmModeGetConnector().
|
|
|
|
2. drm_encoder_get_crtc(), returning NULL because uses_atomic get set,
|
|
causing us to always report 0 as crtc_id in the drmModeEncoder struct
|
|
returned by drmModeGetEncoder()
|
|
|
|
Which in turn confuses userspace, at least plymouth thinks that the pipe
|
|
has changed because of this and tries to reconfigure it unnecessarily.
|
|
|
|
More in general we should not set drm_connector->state in the non-atomic
|
|
code as this violates the drm-core's expectations.
|
|
|
|
This commit fixes this by using a nouveau_conn_atom struct embedded in the
|
|
nouveau_connector struct for property handling in the non-atomic case.
|
|
|
|
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1706557
|
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
|
|
---
|
|
drivers/gpu/drm/nouveau/nouveau_connector.c | 28 +++++++++++++++------
|
|
drivers/gpu/drm/nouveau/nouveau_connector.h | 6 +++++
|
|
2 files changed, 27 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
|
|
index 5b413588b823..9a9a7f5003d3 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
|
|
@@ -245,14 +245,22 @@ nouveau_conn_atomic_duplicate_state(struct drm_connector *connector)
|
|
void
|
|
nouveau_conn_reset(struct drm_connector *connector)
|
|
{
|
|
+ struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
|
struct nouveau_conn_atom *asyc;
|
|
|
|
- if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
|
|
- return;
|
|
+ if (drm_drv_uses_atomic_modeset(connector->dev)) {
|
|
+ if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
|
|
+ return;
|
|
+
|
|
+ if (connector->state)
|
|
+ nouveau_conn_atomic_destroy_state(connector,
|
|
+ connector->state);
|
|
+
|
|
+ __drm_atomic_helper_connector_reset(connector, &asyc->state);
|
|
+ } else {
|
|
+ asyc = &nv_connector->properties_state;
|
|
+ }
|
|
|
|
- if (connector->state)
|
|
- nouveau_conn_atomic_destroy_state(connector, connector->state);
|
|
- __drm_atomic_helper_connector_reset(connector, &asyc->state);
|
|
asyc->dither.mode = DITHERING_MODE_AUTO;
|
|
asyc->dither.depth = DITHERING_DEPTH_AUTO;
|
|
asyc->scaler.mode = DRM_MODE_SCALE_NONE;
|
|
@@ -276,8 +284,14 @@ void
|
|
nouveau_conn_attach_properties(struct drm_connector *connector)
|
|
{
|
|
struct drm_device *dev = connector->dev;
|
|
- struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state);
|
|
struct nouveau_display *disp = nouveau_display(dev);
|
|
+ struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
|
+ struct nouveau_conn_atom *armc;
|
|
+
|
|
+ if (drm_drv_uses_atomic_modeset(connector->dev))
|
|
+ armc = nouveau_conn_atom(connector->state);
|
|
+ else
|
|
+ armc = &nv_connector->properties_state;
|
|
|
|
/* Init DVI-I specific properties. */
|
|
if (connector->connector_type == DRM_MODE_CONNECTOR_DVII)
|
|
@@ -748,9 +762,9 @@ static int
|
|
nouveau_connector_set_property(struct drm_connector *connector,
|
|
struct drm_property *property, uint64_t value)
|
|
{
|
|
- struct nouveau_conn_atom *asyc = nouveau_conn_atom(connector->state);
|
|
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
|
struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
|
|
+ struct nouveau_conn_atom *asyc = &nv_connector->properties_state;
|
|
struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
|
|
int ret;
|
|
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
|
|
index de9588420884..de84fb4708c7 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
|
|
@@ -118,6 +118,12 @@ struct nouveau_connector {
|
|
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
|
|
struct nouveau_backlight *backlight;
|
|
#endif
|
|
+ /*
|
|
+ * Our connector property code expects a nouveau_conn_atom struct
|
|
+ * even on pre-nv50 where we do not support atomic. This embedded
|
|
+ * version gets used in the non atomic modeset case.
|
|
+ */
|
|
+ struct nouveau_conn_atom properties_state;
|
|
};
|
|
|
|
static inline struct nouveau_connector *nouveau_connector(
|
|
--
|
|
2.23.0
|
|
|