From 614b7d7d7b10d8e3f146bed311215f818be5accd Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 10 Jun 2020 17:15:58 -0500 Subject: Initial 5.7.2 rebase Signed-off-by: Justin M. Forbes --- ...Share-DP-SST-mode_valid-handling-with-MST.patch | 209 +++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 0001-kms-nv50-Share-DP-SST-mode_valid-handling-with-MST.patch (limited to '0001-kms-nv50-Share-DP-SST-mode_valid-handling-with-MST.patch') diff --git a/0001-kms-nv50-Share-DP-SST-mode_valid-handling-with-MST.patch b/0001-kms-nv50-Share-DP-SST-mode_valid-handling-with-MST.patch new file mode 100644 index 000000000..c14aed7ea --- /dev/null +++ b/0001-kms-nv50-Share-DP-SST-mode_valid-handling-with-MST.patch @@ -0,0 +1,209 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lyude Paul +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 +Signed-off-by: Ben Skeggs +--- + 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 + -- cgit