c1d5388741
* Thu May 28 2020 CKI@GitLab <cki-project@redhat.com> [5.7.0-0.rc7.20200528gitb0c3ba31be3e.1] - b0c3ba31be3e rebase - Updated changelog for the release based on 444fc5cde643 ("CKI@GitLab") Resolves: rhbz# Signed-off-by: Justin M. Forbes <jforbes@fedoraproject.org>
210 lines
7.1 KiB
Diff
210 lines
7.1 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Lyude Paul <lyude@redhat.com>
|
|
Date: Mon, 11 May 2020 18:41:27 -0400
|
|
Subject: [PATCH] kms/nv50-: Share DP SST mode_valid() handling with MST
|
|
|
|
Currently, the nv50_mstc_mode_valid() function is happy to take any and
|
|
all modes, even the ones we can't actually support sometimes like
|
|
interlaced modes.
|
|
|
|
Luckily, the only difference between the mode validation that needs to
|
|
be performed for MST vs. SST is that eventually we'll need to check the
|
|
minimum PBN against the MSTB's full PBN capabilities (remember-we don't
|
|
care about the current bw state here). Otherwise, all of the other code
|
|
can be shared.
|
|
|
|
So, we move all of the common mode validation in
|
|
nouveau_connector_mode_valid() into a separate helper,
|
|
nv50_dp_mode_valid(), and use that from both nv50_mstc_mode_valid() and
|
|
nouveau_connector_mode_valid(). Note that we allow for returning the
|
|
calculated clock that nv50_dp_mode_valid() came up with, since we'll
|
|
eventually want to use that for PBN calculation in
|
|
nv50_mstc_mode_valid().
|
|
|
|
Signed-off-by: Lyude Paul <lyude@redhat.com>
|
|
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
|
|
---
|
|
drivers/gpu/drm/nouveau/dispnv50/disp.c | 9 +++-
|
|
drivers/gpu/drm/nouveau/nouveau_connector.c | 46 ++++++++++++---------
|
|
drivers/gpu/drm/nouveau/nouveau_connector.h | 5 +++
|
|
drivers/gpu/drm/nouveau/nouveau_dp.c | 31 ++++++++++++++
|
|
drivers/gpu/drm/nouveau/nouveau_encoder.h | 4 ++
|
|
5 files changed, 75 insertions(+), 20 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
|
|
index e92e7bf49780..d5d69532f3c5 100644
|
|
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
|
|
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
|
|
@@ -1056,7 +1056,14 @@ static enum drm_mode_status
|
|
nv50_mstc_mode_valid(struct drm_connector *connector,
|
|
struct drm_display_mode *mode)
|
|
{
|
|
- return MODE_OK;
|
|
+ struct nv50_mstc *mstc = nv50_mstc(connector);
|
|
+ struct nouveau_encoder *outp = mstc->mstm->outp;
|
|
+
|
|
+ /* TODO: calculate the PBN from the dotclock and validate against the
|
|
+ * MSTB's max possible PBN
|
|
+ */
|
|
+
|
|
+ return nv50_dp_mode_valid(connector, outp, mode, NULL);
|
|
}
|
|
|
|
static int
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
|
|
index 6dae00da5d7e..1b383ae0248f 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
|
|
@@ -38,6 +38,7 @@
|
|
#include "nouveau_reg.h"
|
|
#include "nouveau_drv.h"
|
|
#include "dispnv04/hw.h"
|
|
+#include "dispnv50/disp.h"
|
|
#include "nouveau_acpi.h"
|
|
|
|
#include "nouveau_display.h"
|
|
@@ -1033,6 +1034,29 @@ get_tmds_link_bandwidth(struct drm_connector *connector)
|
|
return 112000 * duallink_scale;
|
|
}
|
|
|
|
+enum drm_mode_status
|
|
+nouveau_conn_mode_clock_valid(const struct drm_display_mode *mode,
|
|
+ const unsigned min_clock,
|
|
+ const unsigned max_clock,
|
|
+ unsigned int *clock_out)
|
|
+{
|
|
+ unsigned int clock = mode->clock;
|
|
+
|
|
+ if ((mode->flags & DRM_MODE_FLAG_3D_MASK) ==
|
|
+ DRM_MODE_FLAG_3D_FRAME_PACKING)
|
|
+ clock *= 2;
|
|
+
|
|
+ if (clock < min_clock)
|
|
+ return MODE_CLOCK_LOW;
|
|
+ if (clock > max_clock)
|
|
+ return MODE_CLOCK_HIGH;
|
|
+
|
|
+ if (clock_out)
|
|
+ *clock_out = clock;
|
|
+
|
|
+ return MODE_OK;
|
|
+}
|
|
+
|
|
static enum drm_mode_status
|
|
nouveau_connector_mode_valid(struct drm_connector *connector,
|
|
struct drm_display_mode *mode)
|
|
@@ -1041,7 +1065,6 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
|
|
struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
|
|
struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
|
|
unsigned min_clock = 25000, max_clock = min_clock;
|
|
- unsigned clock = mode->clock;
|
|
|
|
switch (nv_encoder->dcb->type) {
|
|
case DCB_OUTPUT_LVDS:
|
|
@@ -1064,29 +1087,14 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
|
|
case DCB_OUTPUT_TV:
|
|
return get_slave_funcs(encoder)->mode_valid(encoder, mode);
|
|
case DCB_OUTPUT_DP:
|
|
- if (mode->flags & DRM_MODE_FLAG_INTERLACE &&
|
|
- !nv_encoder->caps.dp_interlace)
|
|
- return MODE_NO_INTERLACE;
|
|
-
|
|
- max_clock = nv_encoder->dp.link_nr;
|
|
- max_clock *= nv_encoder->dp.link_bw;
|
|
- clock = clock * (connector->display_info.bpc * 3) / 10;
|
|
- break;
|
|
+ return nv50_dp_mode_valid(connector, nv_encoder, mode, NULL);
|
|
default:
|
|
BUG();
|
|
return MODE_BAD;
|
|
}
|
|
|
|
- if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
|
|
- clock *= 2;
|
|
-
|
|
- if (clock < min_clock)
|
|
- return MODE_CLOCK_LOW;
|
|
-
|
|
- if (clock > max_clock)
|
|
- return MODE_CLOCK_HIGH;
|
|
-
|
|
- return MODE_OK;
|
|
+ return nouveau_conn_mode_clock_valid(mode, min_clock, max_clock,
|
|
+ NULL);
|
|
}
|
|
|
|
static struct drm_encoder *
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
|
|
index de84fb4708c7..9e062c7adec8 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
|
|
@@ -195,6 +195,11 @@ int nouveau_conn_atomic_get_property(struct drm_connector *,
|
|
const struct drm_connector_state *,
|
|
struct drm_property *, u64 *);
|
|
struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *);
|
|
+enum drm_mode_status
|
|
+nouveau_conn_mode_clock_valid(const struct drm_display_mode *,
|
|
+ const unsigned min_clock,
|
|
+ const unsigned max_clock,
|
|
+ unsigned *clock);
|
|
|
|
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
|
|
extern int nouveau_backlight_init(struct drm_connector *);
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
|
|
index 2674f1587457..8a0f7994e1ae 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
|
|
@@ -98,3 +98,34 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
|
|
return NOUVEAU_DP_SST;
|
|
return ret;
|
|
}
|
|
+
|
|
+/* TODO:
|
|
+ * - Use the minimum possible BPC here, once we add support for the max bpc
|
|
+ * property.
|
|
+ * - Validate the mode against downstream port caps (see
|
|
+ * drm_dp_downstream_max_clock())
|
|
+ * - Validate against the DP caps advertised by the GPU (we don't check these
|
|
+ * yet)
|
|
+ */
|
|
+enum drm_mode_status
|
|
+nv50_dp_mode_valid(struct drm_connector *connector,
|
|
+ struct nouveau_encoder *outp,
|
|
+ const struct drm_display_mode *mode,
|
|
+ unsigned *out_clock)
|
|
+{
|
|
+ const unsigned min_clock = 25000;
|
|
+ unsigned max_clock, clock;
|
|
+ enum drm_mode_status ret;
|
|
+
|
|
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace)
|
|
+ return MODE_NO_INTERLACE;
|
|
+
|
|
+ max_clock = outp->dp.link_nr * outp->dp.link_bw;
|
|
+ clock = mode->clock * (connector->display_info.bpc * 3) / 10;
|
|
+
|
|
+ ret = nouveau_conn_mode_clock_valid(mode, min_clock, max_clock,
|
|
+ &clock);
|
|
+ if (out_clock)
|
|
+ *out_clock = clock;
|
|
+ return ret;
|
|
+}
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
|
|
index 3217f587eceb..de51733b0476 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
|
|
@@ -104,6 +104,10 @@ enum nouveau_dp_status {
|
|
};
|
|
|
|
int nouveau_dp_detect(struct nouveau_encoder *);
|
|
+enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *,
|
|
+ struct nouveau_encoder *,
|
|
+ const struct drm_display_mode *,
|
|
+ unsigned *clock);
|
|
|
|
struct nouveau_connector *
|
|
nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
|
|
--
|
|
2.26.2
|
|
|