Nouveau Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Dave Airlie <airlied@gmail.com>
To: dri-devel@lists.freedesktop.org
Cc: nouveau@lists.freedesktop.org
Subject: [PATCH 2/4] nouveau: add FRL and DSC parameters to HDMI sink caps interface
Date: Thu, 23 Apr 2026 10:42:14 +1000	[thread overview]
Message-ID: <20260423004552.3289884-3-airlied@gmail.com> (raw)
In-Reply-To: <20260423004552.3289884-1-airlied@gmail.com>

From: Dave Airlie <airlied@redhat.com>

Extend the outp-level hdmi_sink_caps method with max_frl_rate and
dsc_1p2 parameters so GSP firmware can be informed about the sink's
HDMI 2.1 FRL and DSC capabilities at detect time.

Add nouveau_hdmi_get_frl_rate() helper to convert drm_hdmi_info
lane count and per-lane rate into the FRL rate index (1-6) expected
by the RM SET_HDMI_SINK_CAPS command.

This was claude code assisted.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/nouveau/include/nvif/if0012.h |  4 +++-
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |  2 +-
 drivers/gpu/drm/nouveau/nouveau_connector.c   | 24 ++++++++++++++++++-
 drivers/gpu/drm/nouveau/nvif/outp.c           |  9 ++++---
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.h   |  2 +-
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  |  3 ++-
 .../nouveau/nvkm/subdev/gsp/rm/r535/disp.c    | 22 ++++++++++++++++-
 7 files changed, 57 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index 89cfac7ef3a54..dc0a5c372f511 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -172,7 +172,9 @@ union nvif_outp_hdmi_sink_caps_args {
 		__u8 scdc;
 		__u8 scdc_scrambling;
 		__u8 scdc_low_rates;
-		__u8 pad04[4];
+		__u8 max_frl_rate;
+		__u8 dsc_1p2;
+		__u8 pad06[2];
 	} v0;
 };
 
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index 240e1f80ed539..55c02a34f381e 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -67,7 +67,7 @@ enum nvif_outp_detect_status {
 enum nvif_outp_detect_status nvif_outp_detect(struct nvif_outp *);
 int nvif_outp_edid_get(struct nvif_outp *, u8 **pedid);
 int nvif_outp_hdmi_sink_caps(struct nvif_outp *, bool scdc, bool scdc_scrambling,
-			     bool scdc_low_rates);
+			     bool scdc_low_rates, int max_frl_rate, int dsc_1p2);
 
 int nvif_outp_load_detect(struct nvif_outp *, u32 loadval);
 int nvif_outp_acquire_dac(struct nvif_outp *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index eae37d938f3bc..870b467d35e17 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -560,6 +560,23 @@ nouveau_connector_set_edid(struct nouveau_connector *nv_connector,
 	}
 }
 
+static int
+nouveau_hdmi_get_frl_rate(u8 max_frl_rate_per_lane, u8 max_lanes)
+{
+	switch (max_lanes) {
+	case 3:
+		switch (max_frl_rate_per_lane) {
+		case 3: return 1;
+		case 6: return 2;
+		}
+		return 0;
+	case 4:
+		return max_frl_rate_per_lane / 2;
+	default:
+		return 0;
+	}
+}
+
 static enum drm_connector_status
 nouveau_connector_detect(struct drm_connector *connector, bool force)
 {
@@ -645,7 +662,12 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
 			nvif_outp_hdmi_sink_caps(&nv_encoder->outp,
 						hdmi->scdc.supported,
 						hdmi->scdc.scrambling.supported,
-						hdmi->scdc.scrambling.low_rates);
+						hdmi->scdc.scrambling.low_rates,
+						nouveau_hdmi_get_frl_rate(hdmi->max_frl_rate_per_lane,
+									 hdmi->max_lanes),
+						hdmi->dsc_cap.v_1p2 ?
+							nouveau_hdmi_get_frl_rate(hdmi->dsc_cap.max_frl_rate_per_lane,
+										  hdmi->dsc_cap.max_lanes) : 0);
 		}
 
 		if (nv_encoder->dcb->type == DCB_OUTPUT_DP)
diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c
index d66f437587ff3..60479c884b2dc 100644
--- a/drivers/gpu/drm/nouveau/nvif/outp.c
+++ b/drivers/gpu/drm/nouveau/nvif/outp.c
@@ -463,7 +463,7 @@ nvif_outp_edid_get(struct nvif_outp *outp, u8 **pedid)
 
 int
 nvif_outp_hdmi_sink_caps(struct nvif_outp *outp, bool scdc, bool scdc_scrambling,
-			 bool scdc_low_rates)
+			 bool scdc_low_rates, int max_frl_rate, int dsc_1p2)
 {
 	struct nvif_outp_hdmi_sink_caps_v0 args;
 	int ret;
@@ -472,11 +472,14 @@ nvif_outp_hdmi_sink_caps(struct nvif_outp *outp, bool scdc, bool scdc_scrambling
 	args.scdc = scdc;
 	args.scdc_scrambling = scdc_scrambling;
 	args.scdc_low_rates = scdc_low_rates;
+	args.max_frl_rate = max_frl_rate;
+	args.dsc_1p2 = dsc_1p2;
 
 	ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_HDMI_SINK_CAPS, &args, sizeof(args));
 	NVIF_ERRON(ret, &outp->object,
-		   "[HDMI_SINK_CAPS scdc:%d scrambling:%d low_rates:%d]",
-		   args.scdc, args.scdc_scrambling, args.scdc_low_rates);
+		   "[HDMI_SINK_CAPS scdc:%d scrambling:%d low_rates:%d max_frl_rate:%d dsc_1p2:%d]",
+		   args.scdc, args.scdc_scrambling, args.scdc_low_rates,
+		   args.max_frl_rate, args.dsc_1p2);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
index fd54c17ba4d6d..17698b9ea7186 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
@@ -96,7 +96,7 @@ struct nvkm_outp_func {
 	int (*detect)(struct nvkm_outp *);
 	int (*edid_get)(struct nvkm_outp *, u8 *data, u16 *size);
 	void (*hdmi_sink_caps)(struct nvkm_outp *, bool scdc, bool scrambling,
-			       bool low_rates);
+			       bool low_rates, int max_frl_rate, int dsc_1p2);
 
 	struct nvkm_ior *(*inherit)(struct nvkm_outp *);
 	int (*acquire)(struct nvkm_outp *, bool hda);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index 84381ba71ebaf..202fdc73f7cab 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -483,7 +483,8 @@ nvkm_uoutp_mthd_hdmi_sink_caps(struct nvkm_outp *outp, void *argv, u32 argc)
 		return -EINVAL;
 
 	outp->func->hdmi_sink_caps(outp, args->v0.scdc, args->v0.scdc_scrambling,
-				   args->v0.scdc_low_rates);
+				   args->v0.scdc_low_rates, args->v0.max_frl_rate,
+				   args->v0.dsc_1p2);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c
index fa20a0c633653..2fb7cc83852f9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c
@@ -1218,7 +1218,7 @@ r535_tmds_edid_get(struct nvkm_outp *outp, u8 *data, u16 *psize)
 
 static void
 r535_outp_hdmi_sink_caps(struct nvkm_outp *outp, bool scdc, bool scrambling,
-			 bool low_rates)
+			 bool low_rates, int max_frl_rate, int dsc_1p2)
 {
 	struct nvkm_disp *disp = outp->disp;
 	NV0073_CTRL_SPECIFIC_SET_HDMI_SINK_CAPS_PARAMS *ctrl;
@@ -1236,7 +1236,27 @@ r535_outp_hdmi_sink_caps(struct nvkm_outp *outp, bool scdc, bool scrambling,
 		ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, GT_340MHZ_CLOCK_SUPPORTED, TRUE);
 	if (low_rates)
 		ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, LTE_340MHZ_SCRAMBLING_SUPPORTED, TRUE);
+	switch (max_frl_rate) {
+	case 1: ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, MAX_FRL_RATE_SUPPORTED, 3LANES_3G); break;
+	case 2: ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, MAX_FRL_RATE_SUPPORTED, 3LANES_6G); break;
+	case 3: ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, MAX_FRL_RATE_SUPPORTED, 4LANES_6G); break;
+	case 4: ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, MAX_FRL_RATE_SUPPORTED, 4LANES_8G); break;
+	case 5: ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, MAX_FRL_RATE_SUPPORTED, 4LANES_10G); break;
+	case 6: ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, MAX_FRL_RATE_SUPPORTED, 4LANES_12G); break;
+	default: break;
+	}
 
+	if (dsc_1p2) {
+		ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, DSC_12_SUPPORTED, TRUE);
+		switch (dsc_1p2) {
+		case 1: ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, DSC_MAX_FRL_RATE_SUPPORTED, 3LANES_3G); break;
+		case 2: ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, DSC_MAX_FRL_RATE_SUPPORTED, 3LANES_6G); break;
+		case 3: ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, DSC_MAX_FRL_RATE_SUPPORTED, 4LANES_6G); break;
+		case 4: ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, DSC_MAX_FRL_RATE_SUPPORTED, 4LANES_8G); break;
+		case 5: ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, DSC_MAX_FRL_RATE_SUPPORTED, 4LANES_10G); break;
+		case 6: ctrl->caps |= NVDEF(NV0073_CTRL_CMD_SPECIFIC, SET_HDMI_SINK_CAPS, DSC_MAX_FRL_RATE_SUPPORTED, 4LANES_12G); break;
+		}
+	}
 	WARN_ON(nvkm_gsp_rm_ctrl_wr(&disp->rm.objcom, ctrl));
 }
 
-- 
2.53.0


  parent reply	other threads:[~2026-04-23  2:55 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-23  0:42 nouveau: add HDMI FRL support for GSP enabled GPUs Dave Airlie
2026-04-23  0:42 ` [PATCH 1/4] nouveau: move HDMI sink caps to outp level for GSP-RM Dave Airlie
2026-04-23  0:42 ` Dave Airlie [this message]
2026-04-23  0:42 ` [PATCH 3/4] nouveau: add HDMI FRL training API and retrain event handling Dave Airlie
2026-04-23  0:42 ` [PATCH 4/4] nouveau: wire up HDMI FRL in the display frontend Dave Airlie

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260423004552.3289884-3-airlied@gmail.com \
    --to=airlied@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=nouveau@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox