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 3/4] nouveau: add HDMI FRL training API and retrain event handling
Date: Thu, 23 Apr 2026 10:42:15 +1000	[thread overview]
Message-ID: <20260423004552.3289884-4-airlied@gmail.com> (raw)
In-Reply-To: <20260423004552.3289884-1-airlied@gmail.com>

From: Dave Airlie <airlied@redhat.com>

Add the nvif/nvkm plumbing for HDMI 2.1 Fixed Rate Link training and
FRL retrain event notification from GSP-RM firmware.

Wire format: NVIF_OUTP_V0_HDMI_FRL (0x51) method with head and frl_rate
parameters, dispatched through the acquired IOR table in uoutp.c.

Backend: r535 GSP-RM implementation using SET_HDMI_FRL_CONFIG (0x73029a)
RM control with NVVAL-encoded FRL rate. Training attempts real link
training first, falling back to fake LT on failure.

Events: Register for NV2080_NOTIFIERS_HDMI_FRL_RETRAINING_REQUEST (18)
from GSP, propagated as NVKM_DPYID_FRL_RETRAIN / NVIF_CONN_EVENT_V0_FRL
through the existing connector event infrastructure.

FRL is automatically cleared when HDMI output is disabled.

This was claude code assisted.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/nouveau/include/nvif/if0011.h |  1 +
 drivers/gpu/drm/nouveau/include/nvif/if0012.h | 10 +++
 drivers/gpu/drm/nouveau/include/nvif/outp.h   |  1 +
 .../drm/nouveau/include/nvkm/engine/disp.h    |  8 ++-
 drivers/gpu/drm/nouveau/nvif/outp.c           | 16 +++++
 .../gpu/drm/nouveau/nvkm/engine/disp/ior.h    |  1 +
 .../gpu/drm/nouveau/nvkm/engine/disp/uconn.c  |  3 +
 .../gpu/drm/nouveau/nvkm/engine/disp/uoutp.c  | 20 ++++++
 .../nouveau/nvkm/subdev/gsp/rm/r535/disp.c    | 65 ++++++++++++++++++-
 .../nvkm/subdev/gsp/rm/r535/nvrm/disp.h       | 26 ++++++++
 10 files changed, 147 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0011.h b/drivers/gpu/drm/nouveau/include/nvif/if0011.h
index 3ed0ddd75bd8f..3dfbcd1238fc0 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0011.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0011.h
@@ -26,6 +26,7 @@ union nvif_conn_event_args {
 #define NVIF_CONN_EVENT_V0_PLUG   0x01
 #define NVIF_CONN_EVENT_V0_UNPLUG 0x02
 #define NVIF_CONN_EVENT_V0_IRQ    0x04
+#define NVIF_CONN_EVENT_V0_FRL    0x08
 		__u8 types;
 		__u8 pad02[6];
 	} v0;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index dc0a5c372f511..84145d22c2593 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -57,6 +57,7 @@ union nvif_outp_args {
 #define NVIF_OUTP_V0_LVDS          0x40
 
 #define NVIF_OUTP_V0_HDMI          0x50
+#define NVIF_OUTP_V0_HDMI_FRL      0x51
 
 #define NVIF_OUTP_V0_INFOFRAME     0x60
 #define NVIF_OUTP_V0_HDA_ELD       0x61
@@ -192,6 +193,15 @@ union nvif_outp_hdmi_args {
 	} v0;
 };
 
+union nvif_outp_hdmi_frl_args {
+	struct nvif_outp_hdmi_frl_v0 {
+		__u8 version;
+		__u8 head;
+		__u8 frl_rate;
+		__u8 pad03[5];
+	} v0;
+};
+
 union nvif_outp_infoframe_args {
 	struct nvif_outp_infoframe_v0 {
 		__u8 version;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index 55c02a34f381e..22681b14add4f 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -93,6 +93,7 @@ int nvif_outp_lvds(struct nvif_outp *, bool dual, bool bpc8);
 
 int nvif_outp_hdmi(struct nvif_outp *, int head, bool enable, u8 max_ac_packet, u8 rekey, u32 khz,
 		   bool scdc, bool scdc_scrambling, bool scdc_low_rates);
+int nvif_outp_hdmi_frl(struct nvif_outp *, int head, int frl_rate);
 
 int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_v0 *, u32 size);
 int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
index 7903d7470d194..4736f07a266b9 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
@@ -18,12 +18,14 @@ struct nvkm_disp {
 		struct nvkm_gsp_object objcom;
 		struct nvkm_gsp_object object;
 
-#define NVKM_DPYID_PLUG   BIT(0)
-#define NVKM_DPYID_UNPLUG BIT(1)
-#define NVKM_DPYID_IRQ    BIT(2)
+#define NVKM_DPYID_PLUG       BIT(0)
+#define NVKM_DPYID_UNPLUG     BIT(1)
+#define NVKM_DPYID_IRQ        BIT(2)
+#define NVKM_DPYID_FRL_RETRAIN BIT(3)
 		struct nvkm_event event;
 		struct nvkm_gsp_event hpd;
 		struct nvkm_gsp_event irq;
+		struct nvkm_gsp_event frl_retrain;
 
 		u32 assigned_sors;
 	} rm;
diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c
index 60479c884b2dc..828c312536d41 100644
--- a/drivers/gpu/drm/nouveau/nvif/outp.c
+++ b/drivers/gpu/drm/nouveau/nvif/outp.c
@@ -222,6 +222,22 @@ nvif_outp_infoframe(struct nvif_outp *outp, u8 type, struct nvif_outp_infoframe_
 	return ret;
 }
 
+int
+nvif_outp_hdmi_frl(struct nvif_outp *outp, int head, int frl_rate)
+{
+	struct nvif_outp_hdmi_frl_v0 args;
+	int ret;
+
+	args.version = 0;
+	args.head = head;
+	args.frl_rate = frl_rate;
+
+	ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_HDMI_FRL, &args, sizeof(args));
+	NVIF_ERRON(ret, &outp->object, "[HDMI_FRL head:%d frl_rate:%d]",
+		   args.head, args.frl_rate);
+	return ret;
+}
+
 int
 nvif_outp_hdmi(struct nvif_outp *outp, int head, bool enable, u8 max_ac_packet, u8 rekey,
 	       u32 khz, bool scdc, bool scdc_scrambling, bool scdc_low_rates)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
index 3ba04bead2f9c..fba24625b6882 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
@@ -75,6 +75,7 @@ struct nvkm_ior_func {
 		void (*infoframe_avi)(struct nvkm_ior *, int head, void *data, u32 size);
 		void (*infoframe_vsi)(struct nvkm_ior *, int head, void *data, u32 size);
 		void (*audio)(struct nvkm_ior *, int head, bool enable);
+		void (*frl_train)(struct nvkm_ior *, int head, int frl_rate);
 	} *hdmi;
 
 	const struct nvkm_ior_func_dp {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
index 23d1e5c27bb1e..e1e2760833ad5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
@@ -43,6 +43,8 @@ nvkm_uconn_uevent_gsp(struct nvkm_object *object, u64 token, u32 bits)
 		args.v0.types |= NVIF_CONN_EVENT_V0_UNPLUG;
 	if (bits & NVKM_DPYID_IRQ)
 		args.v0.types |= NVIF_CONN_EVENT_V0_IRQ;
+	if (bits & NVKM_DPYID_FRL_RETRAIN)
+		args.v0.types |= NVIF_CONN_EVENT_V0_FRL;
 
 	return object->client->event(token, &args, sizeof(args.v0));
 }
@@ -122,6 +124,7 @@ nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_
 		if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG  ) bits |= NVKM_DPYID_PLUG;
 		if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_DPYID_UNPLUG;
 		if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ   ) bits |= NVKM_DPYID_IRQ;
+		if (args->v0.types & NVIF_CONN_EVENT_V0_FRL   ) bits |= NVKM_DPYID_FRL_RETRAIN;
 
 		return nvkm_uevent_add(uevent, &disp->rm.event, outp->index, bits,
 				       nvkm_uconn_uevent_gsp);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index 202fdc73f7cab..2245fbd2d1e94 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -239,6 +239,23 @@ nvkm_uoutp_mthd_infoframe(struct nvkm_outp *outp, void *argv, u32 argc)
 	return -EINVAL;
 }
 
+static int
+nvkm_uoutp_mthd_hdmi_frl(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+	union nvif_outp_hdmi_frl_args *args = argv;
+	struct nvkm_ior *ior = outp->ior;
+
+	if (argc != sizeof(args->v0) || args->v0.version != 0)
+		return -ENOSYS;
+	if (!ior->func->hdmi || !ior->func->hdmi->frl_train)
+		return -EINVAL;
+	if (!nvkm_head_find(outp->disp, args->v0.head))
+		return -EINVAL;
+
+	ior->func->hdmi->frl_train(ior, args->v0.head, args->v0.frl_rate);
+	return 0;
+}
+
 static int
 nvkm_uoutp_mthd_hdmi(struct nvkm_outp *outp, void *argv, u32 argc)
 {
@@ -257,6 +274,8 @@ nvkm_uoutp_mthd_hdmi(struct nvkm_outp *outp, void *argv, u32 argc)
 		return -EINVAL;
 
 	if (!args->v0.enable) {
+		if (ior->func->hdmi->frl_train)
+			ior->func->hdmi->frl_train(ior, args->v0.head, 0);
 		ior->func->hdmi->infoframe_avi(ior, args->v0.head, NULL, 0);
 		ior->func->hdmi->infoframe_vsi(ior, args->v0.head, NULL, 0);
 		ior->func->hdmi->ctrl(ior, args->v0.head, false, 0, 0);
@@ -518,6 +537,7 @@ nvkm_uoutp_mthd_acquired(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc)
 	case NVIF_OUTP_V0_RELEASE      : return nvkm_uoutp_mthd_release      (outp, argv, argc);
 	case NVIF_OUTP_V0_LVDS         : return nvkm_uoutp_mthd_lvds         (outp, argv, argc);
 	case NVIF_OUTP_V0_HDMI         : return nvkm_uoutp_mthd_hdmi         (outp, argv, argc);
+	case NVIF_OUTP_V0_HDMI_FRL     : return nvkm_uoutp_mthd_hdmi_frl     (outp, argv, argc);
 	case NVIF_OUTP_V0_INFOFRAME    : return nvkm_uoutp_mthd_infoframe    (outp, argv, argc);
 	case NVIF_OUTP_V0_HDA_ELD      : return nvkm_uoutp_mthd_hda_eld      (outp, argv, argc);
 	case NVIF_OUTP_V0_DP_TRAIN     : return nvkm_uoutp_mthd_dp_train     (outp, argv, argc);
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 2fb7cc83852f9..a4a9462d59027 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
@@ -552,6 +552,46 @@ r535_sor_hdmi_ctrl(struct nvkm_ior *sor, int head, bool enable, u8 max_ac_packet
 	WARN_ON(nvkm_gsp_rm_ctrl_wr(&disp->rm.objcom, ctrl));
 }
 
+static int
+r535_sor_frl_train_one(struct nvkm_ior *sor, int frl_rate, bool fake_lt)
+{
+	struct nvkm_disp *disp = sor->disp;
+	NV0073_CTRL_SPECIFIC_SET_HDMI_FRL_LINK_CONFIG_PARAMS *ctrl;
+	int ret;
+
+	ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom,
+				    NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_FRL_CONFIG,
+				    sizeof(*ctrl));
+	if (IS_ERR(ctrl))
+		return PTR_ERR(ctrl);
+
+	ctrl->displayId = BIT(sor->asy.outp->index);
+	ctrl->data = NVVAL(NV0073_CTRL, HDMI_FRL_DATA, SET_FRL_RATE, frl_rate);
+	ctrl->bFakeLt = fake_lt;
+	ctrl->bDoNotSkipLt = true;
+
+	ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl));
+	if (ret) {
+		nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
+		return ret;
+	}
+
+	ret = ctrl->bLtSkipped ? -EIO : 0;
+
+	nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
+	return ret;
+}
+
+static void
+r535_sor_frl_train(struct nvkm_ior *sor, int head, int frl_rate)
+{
+	if (!frl_rate)
+		return;
+
+	if (r535_sor_frl_train_one(sor, frl_rate, false))
+		r535_sor_frl_train_one(sor, frl_rate, true);
+}
+
 static const struct nvkm_ior_func_hdmi
 r535_sor_hdmi = {
 	.ctrl = r535_sor_hdmi_ctrl,
@@ -559,6 +599,7 @@ r535_sor_hdmi = {
 	.infoframe_avi = gv100_sor_hdmi_infoframe_avi,
 	.infoframe_vsi = gv100_sor_hdmi_infoframe_vsi,
 	.audio = r535_sor_hdmi_audio,
+	.frl_train = r535_sor_frl_train,
 };
 
 static const struct nvkm_ior_func
@@ -1383,6 +1424,21 @@ r535_outp_new(struct nvkm_disp *disp, u32 id)
 	return 0;
 }
 
+static void
+r535_disp_frl_retrain(struct nvkm_gsp_event *event, void *repv, u32 repc)
+{
+	struct nvkm_disp *disp = container_of(event, typeof(*disp), rm.frl_retrain);
+	Nv2080HdmiFrlRetrainingRequestNotification *frl = repv;
+
+	if (WARN_ON(repc < sizeof(*frl)))
+		return;
+
+	nvkm_debug(&disp->engine.subdev, "event: frl retrain displayId %08x\n", frl->displayId);
+
+	if (frl->displayId)
+		nvkm_event_ntfy(&disp->rm.event, fls(frl->displayId) - 1, NVKM_DPYID_FRL_RETRAIN);
+}
+
 static void
 r535_disp_irq(struct nvkm_gsp_event *event, void *repv, u32 repc)
 {
@@ -1465,6 +1521,7 @@ r535_disp_fini(struct nvkm_disp *disp, bool suspend)
 	nvkm_gsp_rm_free(&disp->rm.object);
 
 	if (!suspend) {
+		nvkm_gsp_event_dtor(&disp->rm.frl_retrain);
 		nvkm_gsp_event_dtor(&disp->rm.irq);
 		nvkm_gsp_event_dtor(&disp->rm.hpd);
 		nvkm_event_fini(&disp->rm.event);
@@ -1706,7 +1763,7 @@ r535_disp_oneinit(struct nvkm_disp *disp)
 			return ret;
 	}
 
-	ret = nvkm_event_init(&r535_disp_event, &gsp->subdev, 3, 32, &disp->rm.event);
+	ret = nvkm_event_init(&r535_disp_event, &gsp->subdev, 4, 32, &disp->rm.event);
 	if (WARN_ON(ret))
 		return ret;
 
@@ -1720,6 +1777,12 @@ r535_disp_oneinit(struct nvkm_disp *disp)
 	if (ret)
 		return ret;
 
+	ret = nvkm_gsp_device_event_ctor(&disp->rm.device, 0x007e0002,
+					 NV2080_NOTIFIERS_HDMI_FRL_RETRAINING_REQUEST,
+					 r535_disp_frl_retrain, &disp->rm.frl_retrain);
+	if (ret)
+		return ret;
+
 	/* RAMHT. */
 	ret = nvkm_ramht_new(device, disp->func->ramht_size ? disp->func->ramht_size :
 			     0x1000, 0, disp->inst, &disp->ramht);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/nvrm/disp.h b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/nvrm/disp.h
index 7b7539639540a..f6c7f0b96a48b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/nvrm/disp.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/nvrm/disp.h
@@ -184,6 +184,12 @@ typedef struct Nv2080DpIrqNotificationRec {
     NvU32 displayId;
 } Nv2080DpIrqNotification;
 
+#define NV2080_NOTIFIERS_HDMI_FRL_RETRAINING_REQUEST               (18)
+
+typedef struct {
+    NvU32 displayId;
+} Nv2080HdmiFrlRetrainingRequestNotification;
+
 #define NV0073_CTRL_CMD_SYSTEM_GET_CONNECT_STATE (0x730122U) /* finn: Evaluated from "(FINN_NV04_DISPLAY_COMMON_SYSTEM_INTERFACE_ID << 8) | NV0073_CTRL_SYSTEM_GET_CONNECT_STATE_PARAMS_MESSAGE_ID" */
 typedef struct NV0073_CTRL_SYSTEM_GET_CONNECT_STATE_PARAMS {
     NvU32 subDeviceInstance;
@@ -393,6 +399,26 @@ typedef struct NV0073_CTRL_SPECIFIC_SET_HDMI_SINK_CAPS_PARAMS {
 #define NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_SINK_CAPS_DSC_MAX_FRL_RATE_SUPPORTED_4LANES_10G (0x00000005U)
 #define NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_SINK_CAPS_DSC_MAX_FRL_RATE_SUPPORTED_4LANES_12G (0x00000006U)
 
+#define NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_FRL_CONFIG (0x73029aU)
+#define NV0073_CTRL_SPECIFIC_SET_HDMI_FRL_LINK_CONFIG_PARAMS_MESSAGE_ID (0x9AU)
+typedef struct NV0073_CTRL_SPECIFIC_SET_HDMI_FRL_LINK_CONFIG_PARAMS {
+    NvU32  subDeviceInstance;
+    NvU32  displayId;
+    NvU32  data;
+    NvBool bFakeLt;
+    NvBool bDoNotSkipLt;
+    NvBool bLtSkipped;
+    NvBool bLinkAssessmentOnly;
+} NV0073_CTRL_SPECIFIC_SET_HDMI_FRL_LINK_CONFIG_PARAMS;
+#define NV0073_CTRL_HDMI_FRL_DATA_SET_FRL_RATE                                           2:0
+#define NV0073_CTRL_HDMI_FRL_DATA_SET_FRL_RATE_NONE       (0x00000000U)
+#define NV0073_CTRL_HDMI_FRL_DATA_SET_FRL_RATE_3LANES_3G  (0x00000001U)
+#define NV0073_CTRL_HDMI_FRL_DATA_SET_FRL_RATE_3LANES_6G  (0x00000002U)
+#define NV0073_CTRL_HDMI_FRL_DATA_SET_FRL_RATE_4LANES_6G  (0x00000003U)
+#define NV0073_CTRL_HDMI_FRL_DATA_SET_FRL_RATE_4LANES_8G  (0x00000004U)
+#define NV0073_CTRL_HDMI_FRL_DATA_SET_FRL_RATE_4LANES_10G (0x00000005U)
+#define NV0073_CTRL_HDMI_FRL_DATA_SET_FRL_RATE_4LANES_12G (0x00000006U)
+
 #define NV0073_CTRL_SET_OD_MAX_PACKET_SIZE     36U
 
 #define NV0073_CTRL_CMD_SPECIFIC_SET_OD_PACKET (0x730288U) /* finn: Evaluated from "(FINN_NV04_DISPLAY_COMMON_SPECIFIC_INTERFACE_ID << 8) | NV0073_CTRL_SPECIFIC_SET_OD_PACKET_PARAMS_MESSAGE_ID" */
-- 
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 ` [PATCH 2/4] nouveau: add FRL and DSC parameters to HDMI sink caps interface Dave Airlie
2026-04-23  0:42 ` Dave Airlie [this message]
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-4-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