All of 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  0:52 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.